以下是一个样本装饰器:
def smart_divide(func):
def inner(a,b):
print("I am going to divide",a,"and",b)
if b == 0:
print("Whoops! cannot divide")
return
return func(a,b)
return inner
@smart_divide
def divide(a,b):
return a/b
如果func
是一个对象,那么如何从中访问变量a
和b
?
是不是想要这样做?
def func(potato):
print(y, x)
我有没有得到一个基本概念?这里发生的事情是Python中某些模式的一部分,还是a
和b
知道的特殊情况,因为它是一个生成器?
更新
的新示例def my_shiny_new_decorator(a_function_to_decorate):
def the_wrapper_around_the_original_function():
print("Before the function runs")
a_function_to_decorate()
print("After the function runs")
return the_wrapper_around_the_original_function
def a_stand_alone_function():
print("I am a stand alone function, don't you dare modify me")
发电机手动方式
a_stand_alone_function = my_shiny_new_decorator(a_stand_alone_function)
a_stand_alone_function()
发电机正确的方式
@my_shiny_new_decorator
def another_stand_alone_function():
print("Leave me alone")
根据我从“手动”方式获得新答案的地方,“正确方式”是相同的。
我认为这个例子可能会让我陷入困境,因为我试图将其扩展到涉及参数时。
我现在意识到我想象的没有意义
我认为我发布的原始代码与此相同
divide = smart_divide(divide(a,b))
如果执行将看起来像这样
def smart_divide(divide(a,b)):
def inner(a,b):
print("I am going to divide",a,"and",b)
if b == 0:
print("Whoops! cannot divide")
return
return func(a,b)
return inner
但这会导致div(a,b)在顶行执行
新示例中的'a_stand_alone_function'末尾没有()。这意味着它被视为一个对象。
所以我对它看起来像这个def smart_divide(divide(a,b)):
的想法没有意义,因为该函数不再被视为一个对象
这让我对smart_devide
如何获取作为参数传递的信息感到困惑。
答案 0 :(得分:2)
不,你的装饰师会返回inner
作为divide
的新实现。因此,当程序执行inner
时,首先调用函数divide(1, 2)
。致divide
的来电始终尊重inner
的签名(并在代码中划分)。
像
这样的功能def divide(a, b): # signature
return a / b # implementation or body
由两部分组成。签名描述了参数以及函数的实现。
你的装饰者只会修改你的功能的实现,如下所示:
def divide(a, b): # signature remains unmodified
print("I am going to divide",a,"and",b) # implementation of inner
if b == 0:
print("Whoops! cannot divide")
return
return a / b # call to the original implementation of divide
divide
的名称和签名保持不变。因此,inner
的签名很重要,而不是装饰者的签名。
答案 1 :(得分:2)
smart_divide
没有获取a
和b
。它返回一个函数对象(inner
函数), 函数获取a
并将b
传递给 it 。
如果您尝试这样做,您可以看到实际发生的事情:
def smart_divide(func):
print("I am running in smart_divide; func=", func)
def inner(a,b):
print("I am going to divide",a,"and",b)
if b == 0:
print("Whoops! cannot divide")
return
return func(a,b)
print("I am returning from smart_divide")
return inner
print("I am running at top level before declaring divide")
@smart_divide
def divide(a,b):
return a/b
print("The name 'divide' now refers to", divide)
print("I am now going to call the divide function")
divide(1, 2)
输出:
I am running at top level before declaring divide I am running in smart_divide; func= <function divide at 0x108ff2bf8> I am returning from smart_divide the name 'divide' now refers to <function smart_divide.<locals>.inner at 0x10565db70> I am now going to call the divide function I am going to divide 1 and 2