python中f的作用_Python中的“ @”(@)符号有什么作用?

在Python中添加了装饰器,以使函数和方法包装(接收函数并返回增强函数的函数)更易于阅读和理解。最初的用例是能够在定义的顶部将方法定义为类方法或静态方法。没有装饰器语法,将需要一个相当稀疏且重复的定义:

classWithoutDecorators:defsome_static_method():print("this is static method")some_static_method=staticmethod(some_static_method)defsome_class_method(cls):print("this is class method")some_class_method=classmethod(some_class_method)

如果将装饰器语法用于相同目的,则代码将更短且更易于理解:

classWithDecorators:@staticmethoddefsome_static_method():print("this is static method")@classmethoddefsome_class_method(cls):print("this is class method")

通用语法和可能的实现

装饰器通常是一个命名对象(不允许使用lambda表达式),该对象在被调用时将接受单个参数(它将成为装饰后的函数)并返回另一个可调用对象。此处使用“可调用”代替带有预想的“功能”。尽管装饰器通常在方法和功能的范围内进行讨论,但它们不限于此。实际上,任何可调用的对象(实现_call__方法的任何对象都被视为可调用对象)可以用作修饰符,并且它们返回的对象通常不是简单的函数,而是更多复杂类的实例,这些实例实现了自己的__call_方法。

装饰器语法只是一个语法糖。考虑以下装饰器用法:

@some_decoratordefdecorated_function():pass

总是可以用显式的装饰器调用和函数重新分配来代替:

defdecorated_function():passdecorated_function=some_decorator(decorated_function)

但是,如果在单个函数上使用多个装饰器,则后者的可读性较低,并且也很难理解。可以以多种不同方式使用装饰器,如下所示:

作为功​​能

编写自定义装饰器的方法有很多,但是最简单的方法是编写一个函数,该函数返回包装原始函数调用的子函数。

通用模式如下:

defmydecorator(function):defwrapped(*args,**kwargs):# do some stuff before the original# function gets calledresult=function(*args,**kwargs)# do some stuff after function call and# return the resultreturnresult# return wrapper as a decorated functionreturnwrapped

上课

尽管装饰器几乎总是可以使用函数来实现,但在某些情况下,使用用户定义的类是更好的选择。当装饰器需要复杂的参数化或取决于特定状态时,通常会发生这种情况。

非参数化装饰器作为类的通用模式如下:

classDecoratorAsClass:def__init__(self,function):self.function=functiondef__call__(self,*args,**kwargs):# do some stuff before the original# function gets calledresult=self.function(*args,**kwargs)# do some stuff after function call and# return the resultreturnresult

参数化装饰器

在实际代码中,经常需要使用可以参数化的装饰器。当将该函数用作装饰器时,解决方案很简单-必须使用第二层包装。这是装饰器的一个简单示例,该装饰器每次被调用都会重复执行装饰函数指定次数:

defrepeat(number=3):"""Cause decorated function to be repeated a number of times.

Last value of original function call is returned as a result

:param number: number of repetitions, 3 if not specified

"""defactual_decorator(function):defwrapper(*args,**kwargs):result=Nonefor_inrange(number):result=function(*args,**kwargs)returnresultreturnwrapperreturnactual_decorator

通过这种方式定义的装饰器可以接受参数:

>>>@repeat(2)...deffoo():...print("foo")...>>>foo()foo

foo

请注意,即使参数化装饰器的参数具有默认值,也必须在其名称后加上括号。使用带有默认参数的前面装饰器的正确方法如下:

>>>@repeat()...defbar():...print("bar")...>>>bar()bar

bar

bar

最后,让我们看看带有Properties的装饰器。

物产

这些属性提供了一个内置的描述符类型,该描述符类型知道如何将属性链接到一组方法。一个属性带有四个可选参数:fget,fset,fdel和doc。可以提供最后一个来定义链接到属性的文档字符串,就好像它是方法一样。这是一个Rectangle类的示例,可以通过直接访问存储两个角点的属性或使用width和height属性来控制它:

classRectangle:def__init__(self,x1,y1,x2,y2):self.x1,self.y1=x1,y1

self.x2,self.y2=x2,y2def_width_get(self):returnself.x2-self.x1def_width_set(self,value):self.x2=self.x1+valuedef_height_get(self):returnself.y2-self.y1def_height_set(self,value):self.y2=self.y1+value

width=property(_width_get,_width_set,doc="rectangle width measured from left")height=property(_height_get,_height_set,doc="rectangle height measured from top")def__repr__(self):return"{}({}, {}, {}, {})".format(self.__class__.__name__,self.x1,self.y1,self.x2,self.y2)

创建属性的最佳语法是使用属性作为装饰器。这将减少类内部方法签名的数量,并使代码更具可读性和可维护性。使用装饰器,以上类变为:

classRectangle:def__init__(self,x1,y1,x2,y2):self.x1,self.y1=x1,y1

self.x2,self.y2=x2,y2@propertydefwidth(self):"""rectangle height measured from top"""returnself.x2-self.x1@width.setterdefwidth(self,value):self.x2=self.x1+value@propertydefheight(self):"""rectangle height measured from top"""returnself.y2-self.y1@height.setterdefheight(self,value):self.y2=self.y1+value

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值