Структурирование программы. Классы и функции в 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 неверна. Возможно, было бы неплохо рассмотреть основы. Эта ссылка поможет.

Основы Python - Классы

Другие вопросы по тегам