在编译时调用的 Python 装饰器函数
Posted
技术标签:
【中文标题】在编译时调用的 Python 装饰器函数【英文标题】:Python decorator function called at compile time 【发布时间】:2013-08-06 09:54:27 【问题描述】:我希望熟悉 Python 的编译/运行时过程的人能够对我关于 Python 如何编译装饰器函数的问题有所了解。
在我的示例代码中,我在定义 logtofile 闭包之前在“writeit”装饰器中包含了一个测试打印语句。如果您运行我提供的整个代码,那么在使用 writeit 之前,会为 Customer 类中定义的每个 @writeit 装饰器调用 writeit 中的“测试”打印语句。
为什么在编译时调用 logtofile?有人可以解释这种行为吗?
def writeit(func):
print('testing')
def logtofile(customer, *arg, **kwargs):
print('logtofile')
result = func(customer, *arg, **kwargs)
with open('dictlog.txt','w') as myfile:
myfile.write(func.__name__)
return result
return logtofile
class Customer(object):
def __init__(self,firstname,lastname,address,city,state,zipcode):
self._custinfo = dict(firstname=firstname,lastname=lastname,address=address,city=city,state=state,zipcode=zipcode)
@writeit
def setFirstName(self,firstname):
print('setFirstName')
self._custinfo['firstname']=firstname
@writeit
def setLastName(self,lastname):
print('setLastName')
self._custinfo['lastname']=lastname
@writeit
def setAddress(self,address):
print('setAddress')
self._custinfo['address']=address
def main():
cust1 = Customer('Joe','Shmoe','123 Washington','Washington DC','DC','12345')
cust1.setFirstName('Joseph')
cust1.setLastName('Shmoestein')
if(__name__ == '__main__'): main()
【问题讨论】:
不是在编译时,而是在运行时。但是在类定义中运行def
语句需要运行装饰它们的装饰器。
【参考方案1】:
您的代码在模块被导入时运行。 Python 执行所有***语句,包括当时的类定义。
类定义体作为函数执行,本地命名空间成为类属性。这意味着类主体在导入时执行,前提是该类是在模块的顶层定义的。
Python在执行时遇到修饰函数,会先定义类,然后执行修饰函数,传入函数对象,将修饰函数的返回值绑定到函数名。由于类体是在导入期间执行的,这意味着您的装饰器在那个时候执行。
【讨论】:
感谢您的澄清,Martijn。您能推荐一些我可以用来更详细地了解这一点的参考资料吗? 你必须通读Python reference; execution model 中记录了在导入时初始化模块,class
compound statement 参考中指定了如何定义类。如何应用装饰器是 function definitions 参考的一部分。【参考方案2】:
没有编译时间。 def
语句和相关的装饰器调用是可执行语句。
因此,当 Python 加载一个模块时,它会按顺序执行语句。执行类语句时,早期阶段之一是执行类主体中的所有语句。作为其中的一部分,def
s 运行以创建函数,这些函数对象将传递给装饰器进行处理。
您的“测试”打印语句将在调用装饰器时运行,而不是在调用它返回的函数时运行。如果您想要这种行为,请将装饰器移动到内部函数中。
【讨论】:
以上是关于在编译时调用的 Python 装饰器函数的主要内容,如果未能解决你的问题,请参考以下文章