2016-10-25 3 views
0

мы вообще знакомы с этим «Гоча» в Python из-за его обзорного:Future Proof Scoping В Callback Closures [Python]

functions = [] 
for i in range(3): 
    functions.append(lambda : i) 

out = [f() for f in functions] 

# naive expectation = [0, 1, 2] 
# actual result = [2, 2, 2] 

И мы вообще знакомы с тем, как соответствовать нашим ожиданиям:

functions.append(lambda i=i: i) 

Однако, пытаясь создать закрытие обратного вызова «будущего доказательства», я столкнулся с проблемой, когда возможность расширяющейся сигнатуры обратного вызова нарушила аргументы по умолчанию, используемые для определения области закрытия.


Рассмотрим этот случай:

def old_style_callback(data, *args, **kwargs): 
    # ... 

# define a bunch of closures 
closures = [] 
for cb in list_of_callbacks: 
    def old_style_closure(data, callback=cb, *args, **kwargs): 
     cb(data, *args, **kwargs) 
     # ... 
    closures.append(old_style_closure) 

Но что, если вам нужно добавить новый аргумент, который приспосабливает некоторые новые функции?

def new_style_callback(data, metadata, *args, **kwargs): 
    # ... 

Теперь ваш old_style_closure была нарушена, так как metadata получит передается аргумент по умолчанию, который вы использовали, чтобы расширить сферу Замыкание и доступ обратного вызова!


Похоже, если вы хотите «будущее доказательство» обратного вызова закрытия, вы вынуждены придерживаться с оригинальной подписью и просто передать все через эти аргументы. Это не так страшно, но это создает проблему, если вы не сделали свою оригинальную общую подпись.

Любые мысли или новые подходы к этой проблеме приветствуются.

ответ

0

После написания этого вопроса я пришел к осознанию того, что вы можете решить эту проблему, создав с ней новую функцию. own область действия для создания закрытия. Как только вы это сделаете, вы просто вызываете его в контуре:

def create_callback_closure(callback): 
    def old_style_closure(data, *args, **kwargs): 
     callback(data, *args, **kwargs) 
     # ... 

closures = [] 
for cb in list_of_callbacks: 
    closures.append(create_callback_closure(callback))