2013-02-22 2 views
6

прямо сейчас я использую затворы для создания функций, как в этом упрощенном примере:Генерация функций без закрытия в питоне

def constant_function(constant): 
    def dummyfunction(t): 
     return constant 
    return dummyfunction 

Этих сформировавшиеся функции затем передаются в Init-метод пользовательского класса, который хранит их как атрибуты экземпляра. Недостаток заключается в том, что это делает экземпляры классов неуправляемыми. Поэтому мне интересно, есть ли способ создать генераторы функций, избегая закрытий.

+0

Выбранные классы могут быть вариантом, хотя они имеют свой собственный набор предостережений и сложностей. –

ответ

8

Вы можете использовать вызываемую класс:

class ConstantFunction(object): 
    def __init__(self, constant): 
     self.constant = constant 
    def __call__(self, t): 
     return self.constant 

def constant_function(constant): 
    return ConstantFunction(constant) 

Замыкание состояние вашей функции затем передается в экземпляр атрибута вместо этого.

+0

В Python 3.3, травля лямбда дает мне '_pickle.PicklingError: не удается pickle : поиск атрибутов builtins.function failed'. (Регулярные функции травления с именем работают, но ссылаются только на имя и модуль этой функции.) – delnan

+0

@ delnan: hrmz, анонимные lambdas должны быть загружаемыми как функции. На данный момент удалена опция. –

+1

@ delnan: Оказывается, я неправильно понял [этот вопрос] (http://stackoverflow.com/questions/11878300/serializing-and-deserializing-lambdas), и, таким образом, думал, что lambdas будет работать. :-) –

0

Не то, чтобы я рекомендовал это для общего использования ... но есть альтернативный подход к компиляции и код exec. Он генерирует функцию без закрытия.

>>> def doit(constant): 
... constant = "def constant(t):\n return %s" % constant 
... return compile(constant, '<string>', 'exec') 
... 
>>> exec doit(1) 
>>> constant(4) 
1 
>>> constant 

Обратите внимание, что для этого в функции включения или класса (т.е. не в глобальном пространстве имен), вы должны также проходить в соответствующем пространстве имен exec. См: https://docs.python.org/2/reference/simple_stmts.html#the-exec-statement

Там также двойной lambda подход, который не является действительно замыкание, ну, вроде ...

>>> f = lambda x: lambda y:x 
>>> g = f(1) 
>>> g(4) 
1 
>>> import dill 
>>> _g = dill.dumps(g) 
>>> g_ = dill.loads(_g) 
>>> g_(5) 
1 

Вы, казалось, беспокоился о способности к маринованные закрытия подобных объектов, так что вы могут видеть, что даже двойные лямбды являются разборчивыми, если вы используете dill. То же самое для экземпляров класса.

Смежные вопросы