9

我希望熟悉 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()
4

2 回答 2

9

您的代码在导入模块时运行。Python 执行所有顶级语句,包括当时的类定义。

类定义主体作为函数执行,本地命名空间成为类属性。这意味着类体在导入时执行,前提是类是在模块的顶层定义的。

Python在执行时遇到装饰函数,会先定义类,然后执行装饰器函数,传入函数对象,将装饰器的返回值绑定到函数名上。由于类主体是在导入期间执行的,这意味着您的装饰器在那时执行。

于 2013-08-05T16:00:30.460 回答
2

没有编译时间。一个def语句,以及相关的装饰器调用是可执行语句。

因此,当 Python 加载模块时,它会按顺序执行语句。执行类语句时,早期阶段之一是执行类主体中的所有语句。作为该defs 的一部分运行以创建函数,并且这些函数对象将传递给装饰器进行处理。

您的“测试”打印语句将在调用装饰器时运行,而不是在调用它返回的函数时运行。如果您想要这种行为,请将装饰器移动到内部函数中。

于 2013-08-05T15:59:34.770 回答