Структурирование программы. Классы и функции в Python
Я пишу программу, которая использует генетические методы для разработки уравнений. Я хочу иметь возможность отправить функцию 'mainfunc' в функцию 'submit' в Parallel Python. Функция mainfunc вызывает два или три метода, определенных в классе Utility. Они создают другие классы и вызывают различные методы. Я думаю, что я хочу все это в одном NAMESPACE. Итак, я создал несколько (может быть, все) классов внутри функции 'mainfunc'. Я называю служебный метод 'generate()'. Если бы мы следовали его цепочке выполнения, это включало бы все классы и методы в коде.
Теперь уравнения хранятся в дереве. Каждый раз, когда дерево генерируется, мутирует или скрещивается, узлам необходимо дать новый ключ, чтобы к ним можно было получить доступ из словарного атрибута дерева. Класс KeySeq генерирует эти ключи.
В Parallel Python я собираюсь отправить несколько экземпляров mainfunc в функцию submit в PP. Каждый должен иметь доступ к KeySeq. Было бы хорошо, если бы все они обращались к одному и тому же экземпляру KeySeq, чтобы ни один из узлов в возвращенных деревьях не имел одинаковый ключ, но я мог бы обойти это в случае необходимости.
Итак: мой вопрос о вставке ВСЕХ в mainfunc. Спасибо (Edit) Если я не включаю все в mainfunc, я должен попытаться рассказать PP о зависимых функциях и т. Д., Передавая различные аргументы в разных местах. Я пытаюсь избежать этого.
(позднее редактирование), если ks.next() вызывается внутри функции "generate ()", он возвращает ошибку "NameError: глобальное имя" ks "не определено"
class KeySeq:
"Iterator to produce sequential \
integers for keys in dict"
def __init__(self, data = 0):
self.data = data
def __iter__(self):
return self
def next(self):
self.data = self.data + 1
return self.data
class One:
'some code'
class Two:
'some code'
class Three:
'some code'
class Utilities:
def generate(x):
'___________'
def obfiscate(y):
'___________'
def ruminate(z):
'__________'
def mainfunc(z):
ks = KeySeq()
one = One()
two = Two()
three = Three()
utilities = Utilities()
list_of_interest = utilities.generate(5)
return list_of_interest
result = mainfunc(params)
3 ответа
Если вы хотите, чтобы все экземпляры mainfunc
использовать то же самое KeySeq
объект, вы можете использовать трюк значения параметра по умолчанию:
def mainfunc(ks=KeySeq()):
key = ks.next()
Пока вы на самом деле не передаете значение ks
все звонки на mainfunc
будет использовать экземпляр KeySeq
который был создан, когда была определена функция.
Вот почему, если вы не знаете: функция - это объект. У него есть атрибуты. Один из его атрибутов называется func_defaults
; это кортеж, содержащий значения по умолчанию всех аргументов в его подписи, которые имеют значения по умолчанию. Когда вы вызываете функцию и не предоставляете значение для аргумента, который имеет значение по умолчанию, функция извлекает значение из func_defaults
, Поэтому, когда вы звоните mainfunc
без предоставления значения для ks
, он получает KeySeq()
экземпляр из func_defaults
кортеж. Который, для этого случая mainfunc
всегда один и тот же KeySeq
пример.
Теперь вы говорите, что вы собираетесь отправить "несколько экземпляров mainfunc
к submit
функция ПП."Вы действительно имеете в виду несколько экземпляров? Если это так, механизм, который я описываю, не будет работать.
Но сложно создать несколько экземпляров функции (а код, который вы опубликовали, нет). Например, эта функция возвращает новый экземпляр g
каждый раз, когда это называется:
>>> def f():
def g(x=[]):
return x
return g
>>> g1 = f()
>>> g2 = f()
>>> g1().append('a')
>>> g2().append('b')
>>> g1()
['a']
>>> g2()
['b']
Если я позвоню g()
без аргументов возвращает значение по умолчанию (изначально пустой список) из func_defaults
кортеж. поскольку g1
а также g2
разные случаи g
их значение по умолчанию для x
Аргумент также является другим примером, который демонстрирует выше.
Если вы хотите сделать это более явным, чем использовать хитрый побочный эффект значений по умолчанию, вот еще один способ сделать это:
def mainfunc (): если нет hasattr(mainfunc, "ks"): setattr(mainfunc, "ks", KeySeq()) key = mainfunc.ks.next()
Наконец, очень важный момент, который пропускает код, который вы опубликовали: если вы собираетесь выполнять параллельную обработку совместно используемых данных, код, который касается этих данных, должен реализовывать блокировку. Посмотрите на callback.py
пример в документации параллельного Python и посмотреть, как блокировка используется в Sum
класс и почему.
Хорошо структурировать вашу программу таким образом. Многие утилиты командной строки следуют той же схеме:
#imports, utilities, other functions
def main(arg):
#...
if __name__ == '__main__':
import sys
main(sys.argv[1])
Таким образом, вы можете позвонить main
импортировать его из другого модуля или запустить из командной строки.
Я думаю, что ваша концепция классов в Python неверна. Возможно, было бы неплохо рассмотреть основы. Эта ссылка поможет.