Вы уже используете общий метод для обработки порядка вызова функций: передайте токен от функции к другой:
token1 = func1(token0)
token2 = func2(token1)
token3 = func2(token2)
...
Обычно токены также являются полезными результатами. В вашем примере: вы не позвоните transform_data
, если у вас нет data
, чтобы дать ему: data
- это token0
. Таким образом, transform_data
будет называться после query_data
.
Но я думаю, что реальная проблема, с которой вы сталкиваетесь, другая: вы боитесь, что пользователь неправильно введет следующую функцию и что функция может принять ее и вернуть неправильный результат:
[ 1135] Я просто обеспокоен тем, что в запутанном процессе было бы трудно проследить, есть ли у вас действительный ввод ... Разреженная матрица является недопустимым вводом для одного типа модели, но действительна для другого (комментарии) [1122 ]blockquote>
В статически типизированных языках этого не произойдет (как правило), потому что программа не будет компилироваться, если вы дадите кролика, когда ожидается кот. В python, с вводом утки, это не так просто. Давайте посмотрим, как можно применить это:
- хорошая документация
- проверить входные данные
- сгруппировать функции
- заблокировать некоторые параметры [1131 ]
Хорошая документация
Это, безусловно, лучшее решение. Каждый здесь взрослый. Не волнуйся слишком сильно.
Вы можете использовать Python способности печатать для информации о человеке.
Проверьте входные данные
Это вариант Защитного программирования . Если необходимо, оберните функции, которые вам не принадлежат:
def wrap_transform_data(data, arg1, arg2): if not valid(data): # find a way to check this raise Exception("data is not valid") return transform_data(data, arg1, arg2)
Используйте исключения и избегайте блока
1141 Этого иногда будет недостаточно. Представьте, что у вас квадратная матрица: как проверить, была ли она транспонирована перед следующим вызовом функции?try... except
, так как быстрый сбой здесь лучше.
Сгруппировать функции
Достаточно просто поместить модуль в другой функция, которая применяет функции по порядку, но, кажется, создает ненужно сложную функцию со многими аргументами, которая нарушает одну ответственность.
blockquote>Вы получаете что-то вроде этого:
def full_process(sql, arg1, arg2, frac_test, frac_validate, loss, learning_rate): data=query_data(sql) transformed_data=transform_data(data, arg1, arg2) train, test, validate = train_test_validate(transformed_data, frac_test, frac_validate) model = fit_model(train,test, loss, learning_rate) predictions, f1 = model.predict(validate) return ...
Как вы сказали, метод
full_process
имеет много смешанных параметров. Обычный способ справиться с этим в Python - это использовать значения по умолчанию:def full_process(sql, arg1=1, arg2=2, frac_test=0.7, frac_validate=0.5, loss=0.2, learning_rate=0.1): data=query_data(sql) transformed_data=transform_data(data, arg1, arg2) train, test, validate = train_test_validate(transformed_data, frac_test, frac_validate) model = fit_model(train,test, loss, learning_rate) predictions, f1 = model.predict(validate) return ...
Он становится читаемым, если у вас нет разных параметров каждый раз:
full_process(sql, frac_validate=0.9)
Это решит транспонированный приведенный выше пример матрицы, если функция
transpose
является одной из функций.Остерегайтесь: просто сгруппируйте детали без ответвлений . Не пишите что-то вроде этого:
def full_process(sql, , case1, case2, case3, arg1=1, arg2=2, frac_test=0.7, frac_validate=0.5, loss=0.2, learning_rate=0.1): data=query_data(sql) if case1: transformed_data=transform_data(data, arg1, arg2) train, test, validate = train_test_validate(transformed_data, frac_test, frac_validate) if case2: ... else: ... else: transformed_data=transform_data2(data, arg1, arg2) train, test, validate = train_test_validate(transformed_data, frac_test, frac_validate) if case2: ... else: ... return ...
Очень трудно читать, поддерживать, и это может привести к комбинаторному взрыву!
Заблокировать некоторые параметры
I добавьте это для отчета, но я не думаю, что это хорошая практика, за исключением некоторых конкретных случаев. Это похоже на то, что вы пробовали с классами, но с функциями.
Я сосредоточусь на двух строках:
data=get_matrix() transformed_data=transform_data(data, arg1, arg2)
Если вы хотите, чтобы пользователь вызывал
transform_data
с возвращаемым значениемquery_data
, вы можете вернуть функцию:def wrapped_query_data(sql): def ret(arg1, arg2) # you might use functools.partial transform_data(data, arg1, arg2) return ret
Код теперь:
data_transformer = wrapped_query_data(sql) train_test_validate = data_transformer(arg1, arg2) # no way the user can twist data here
Очевидно, что если вы попытаетесь обобщить это, вам понадобится обертка за шагом и вы ограничите возможности ветвления.
Заключение
Есть ли лучший способ убедиться, что код выполняется в определенном порядке и что этот порядок очевиден из структуры кода?
blockquote>Помните, что Python помогает каждому программисту быть ответственным. Используйте методы, которые обеспечивают порядок вызовов функций, только если это необходимо.
Вы отсутствовали, c освобождает подвижных
существует 3 способа выйти из этого
Первая вещь: не используйте TortoiseHg для этого. Используйте Подвижный установщик вместо этого.
(TortoiseHg пытается быть максимально независимым от Вашей установки Python, и по причинам, неясным этому новичку Python, вещи не Работают. Что-то о py2exe.)
Иначе просто выполните шаги в HgWebDirStepByStep. Я действительно должен был установить pywintypes, но YMMV. Наконец, разархивировать утилита, упомянутая на той странице, может сделать странные вещи с полномочиями файла: Я должен был добавить полномочия чтения к каталогу Templates и его файлам/подкаталогам.
Как в стороне, если Вы задаетесь вопросом, как установить стиль, добавьте это к hgweb.config:
[web]
style = foo
Я знаю, что на этот вопрос уже дан ответ, но я столкнулся с немного другой проблемой и нашел способ ее обойти -
Я уверен, что мне не хватает чего-то очевидного в конфигурации Python ( 2.5.4), но у меня проблемы с .pyd по сравнению с .dll. (У меня были те же проблемы с библиотеками Subversion Python.) Я вижу osutil.pyd в Mercurial \ library.zip, но он не может его загрузить. Поэтому я разархивировал library.zip, а затем скопировал * .pyd в * .dll, например:
REM Ugly DOS... Recursively renames all .pyd files to .dll
for /f "tokens=*" %%a in ('dir /s /b *.pyd') do copy "%%a" "%%~da%%~pa%%~na.dll"
Убедитесь, что каталог разархивированной библиотеки находится в PYTHONPATH, но после этого я успешно могу выполнить: from mercurial import osutil. Также не забудьте скопировать или переместить каталог Templates в каталог только что распакованной библиотеки.
Для остального выполните шаги, описанные в Разделе 5 HgWebDirStepByStep . Я не испытал "Попутных дел"