LINUX.ORG.RU

Боль динамической типизации

 , , , ,


0

2

Всем привет.

Поделитесь продвинутыми методами поиска списка членов какой-либо произвольной переменной в языках типа python.

Кроме самых очевидных:

1. Документация - часто неполная или отсутствует

2. IDE - ОЧЕНЬ часто сама не может определить тип переменной для динамических языков.

3. Пристальный взгляд в код - поиск мест использования

Для себя использую следующие ламерские методы:

1. Параллельно пишу код в IDLE и делаю dir(something) - знаю, жесть.

2. Поставить breakpoint в дебаге и палить окошко watch - тоже жесть.

Есть ли какая-нибудь удобная тула для навигации по docstrings?

По сравнению с java, где список методов получается легко и быстро (даже доки не нужны), эта проблема с питоном сильно тормозит разработку.

В качестве подтверждения попробуйте взять mechanize и определить, что есть в Browser.form. Лапшенавигирование по коду гарантировано.


Ответ на: комментарий от AlexM

Я тоже так делаю, только вместо явы питон. Может поэтому мне кажется что это светлые силы?:-) За исключением вызова питона из плюсов через питонье АПИ...

AIv ★★★★★
()
Ответ на: комментарий от AIv

Ну, «прикладному программисту» надо в таком случае смотреть на то, какие интерфейсы были определены в исходном C++, и каковы правила трансформации. Глядеть в тот бойлерплейт, что породил SWIG - это не слишком продуктивно: в следующей версии (SWIG или набора .i) бойлерплейт может оказаться совсем другим.

А что, вызывать питоньи колбэки - это страшно? Вроде в случае Java-генератора director'а справляются на ура, наружу ничего не торчит, всё под капотом. Да и обёрточный, генерённый, код получается не сильно страшный.

AlexM ★★★★★
()
Ответ на: комментарий от cccian

Да, прошу прощения, погорячился в прошлый раз, и не слишком ясно сформулировал свою мысль.

Моё соображение таково: использовать потроха чужого модуля, не имея ясной документации, что в этом модуле является публичным интерфейсом, а что - особенностями реализации такого интерфейса, чревато неприятными граблями в последующем. Поэтому или Вы хорошо представляете, как и почему устроен модуль, или пользуетесь только теми возможностями, которые автор объявил публичными и документировал.

AlexM ★★★★★
()
Ответ на: комментарий от AlexM

Ну, «прикладному программисту» надо в таком случае смотреть на то, какие интерфейсы были определены в исходном C++, и каковы правила трансформации.

Пока все хорошо так и получается. Но иногда этого оказывается недостаточно... Я вот писал когда то http://a-iv.ru/pyart/cpp2py.pdf

А что, вызывать питоньи колбэки - это страшно?

У меня как то так получается:

		int  __getitem__(int i) const { 
			if( i<0 ) i+= D;
			if( 0<=i && i<D ) return p[i]; 
			else throw PyErr_Format( PyExc_IndexError, "index [%i] out of range", i );
		}
		void __setitem__(int i, int x){ 
			if( i<0 ) i+= D;
			if( 0<=i && i<D ) p[i]=x; 
			else throw PyErr_Format( PyExc_IndexError, "index [%i] out of range", i );
		}

		PyObject* __getslice__( long a, long b ) const {
			if( a<0 ) a+= D; if( b<0 ) b+= D;
			if( a>D ) a = D; if( b>D ) b = D;
			PyObject *t = PyTuple_New(b-a);
			for(int i=a;i<b;i++) PyTuple_SET_ITEM( t, i-a, PyInt_FromLong(p[i]) ); 
			return _DCR(t);
		}
		void __setslice__( long a, long b, PyObject* t ){
			if( a<0 ) a+= D; if( b<0 ) b+= D;
			if( a>D ) a = D; if( b>D ) b = D;
			bool tt = PyTuple_Check(t) || PyList_Check(t);
			if( tt && PyObject_Size(t) != b-a ) throw PyErr_Format( PyExc_ValueError, "incorrect sequens length=%i for construct indx%i", PyObject_Size(t), D );
			for( int i = a; i < b; i++ ){ 
				PyObject* v = tt ? PySequence_Fast_GET_ITEM( t, i-a ) : PyObject_CallMethod( t, (char*)"__getitem__", (char*)"i", i-a );
				if( !v ) throw PyErr_Format( PyExc_IndexError, "index [%i] out of range", i );
				if( PyInt_Check(v) ) p[i] = PyInt_AsLong( v ); 
				else{
//					PyObject* m = PyObject_CallMethod( v, (char*)"__int__", (char*)"", NULL );
					PyObject* m =  PyNumber_Int( v ); 
					if( !m ) throw PyErr_Format( PyExc_TypeError, "value with index [%i] can't convert to int", i  );
					p[i] = PyInt_AsLong( m ); Py_DECREF(m); 
				}
				if(!tt){ Py_DECREF(v); }
			}
//			for(int i=a;i<b;i++) p[i] = PyInt_AsLong( PySequence_ITEM( t, i-a ) );
		}

Не то что страшно... геморно.

AIv ★★★★★
()
Ответ на: комментарий от AIv

Страшновато... Особенно, если это руками писанный бойлерплэйт в конечном, «пользовательском» коде.

Я, как уже писал, обошёлся director'ом, и C++-ная часть - это чистый task-specific C++ interface и метод, который этот интерфейс получает и внутри себя вызывает. Оба ничего ничего не знают ни за Java, ни за SWIG (ну, не совсем, везде, где только можно аргументы и результаты протаскиваются по const-ссылке, во избежание лишних расходов).

Ну и писанная руками Java-часть тоже получает готовый базовый Java-класс на основании C++-интерфейса. Он, конечно, не abstract по очевидным причинам, и, поэтому, IDE не ругается, если колбэчные методы не переопределены в наследниках, но это, в общем, наверное, единственное «видимое» отличие для прикладного программиста.

С промежуточным уровнем, на уровне .i, конечно, пришлось повозиться, соорудив простенькие ro-обвязки для контейнеров с Java-style итераторами и маппингом исключений, но тоже, в общем, не очень страшно.

AlexM ★★★★★
()
Ответ на: комментарий от anonymous

При достаточно развитой системе типов сигнатуры становятся отличной, а главное, автоматически верифицируемой документацией. Это, правда, не про жаву совсем.

как раз таки про джаву.

cccian
() автор топика
Ответ на: комментарий от dimon555

ты пишешь код, который обрабатывает объекты с неизвестным интерфейсом?

очередной раз повторю:

- в начале ВСЕ интерфейсы вам неизвестны

- интерфейс становится известным ВАМ, когда вы посмотрите на документацию, либо на его тип.

- мысль в том, как получить интерфейс, не имея нормальных доков.

И ты в рантайме определяешь интерфейс через тип, чтобы организовать нужное взаимодействие? это кривая архитектура, это нужно переделать. Диспетчеризация на основе типа в питоне, это странно.

жесть

cccian
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.