这是一个样本装饰器:
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
知道的特殊情况,因为它是一个发电机?
更新
来自another stack exchange answer的新例子
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
如何获取作为参数传递的信息感到困惑。
smart_divide
没有得到a
和b
进入它。它返回一个函数对象(inner
函数),该函数将a
和b
传递给它。
如果您尝试这样做,您可以看到实际发生的情况:
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
不,你的装饰者将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
的签名很重要,而不是装饰者的签名。