网络编程

当前位置:永利402游戏网站-永利402com官方网站 > 网络编程 > Python基础(七) python自带的三个装饰器

Python基础(七) python自带的三个装饰器

来源:http://www.xtcsyb.com 作者:永利402游戏网站-永利402com官方网站 时间:2019-11-10 04:07

聊到装饰器,就只好说python自带的八个装饰器:

内容满含:

1、@property   将某函数,做为属性使用

  • 元类
  • python 对象和类的绑定甚至类措施,静态方法
  • python 子类调用父类方法总计
  • python 方法解析顺序MENCOREQ
  • python定制类和法力方法
  • 至于用法__slots__
  • @property使用
  • 修饰器

 @property 修饰,就是将艺术,产生三个属性来行使。

0、元类

元类正是类的类,所反映的终端观念正是整个皆对象。

图片 1

image.png

关于深档次,待使用到在总计。

class A():


    @property
    def pfunc(self):
        return self.value

    @pfunc.setter
    def pfunc(self,value):
        self.value = value

    @property
    def pfunc1(self):
        print('this is property')

if __name__=="__main__":

    A.pfunc = 9
    print A.pfunc
    A.pfunc1

1、python 对象和类的绑定以致类措施,静态方法

平铺直叙大家要选用二个类中的方法时,都急需实例化该类,再张开调用,那类中 self 和 cls 有哪些意思,能还是必须要伊始化二个实例而直白调用类方法,对象方法和类措施,静态方法又有怎么样关系。是本篇文章思量的题目。

类的调用有以下二种艺术:

>>>class Test:
...    def func(self, message):
...        print message
...
>>>object1=Test()
>>>x=object1.func
>>>x('abc')
abc
>>>t=Test.func
>>>t(object1,'abc')
abc

只是对于 t=Test.func 来讲,变量名 t 是关系到了类 Test 的func 方法的地点上,t是非绑定的,所以在调用t(object1, ‘abc’) 时,必需显式的将实例名与 self 关联,不然将会报出”TypeError: unbound method func() must be called with Test instance as first argument (got str instance instead)” 的大错特错。

 

参照他事他说加以考查学习

清楚以下几点:
1、类私下认可的章程都以绑定对象的,而self参数也是指向该目的,未有实例化对象时,类中方法调用会出错,也涉及到python自动传送self参数。
2、若想不实例化而间接通过 类名.方法 来调用,必要钦定该方式绑定到类,如下,豆蔻梢头要使用@classmethod 装饰器,二方法中第叁个参数为cls,实际不是self。

>>> class Foo(object):          
...     @classmethod                #定义类方法要点1
...     def foo(cls):               #定义类方法要点2
...             print 'call foo'
... 
>>> Foo.foo()
call foo
>>> Foo().foo()
call foo

类也是指标,由此和下部的静态方法依然有不平等。类中从来定义的特性如下,在类措施中也是能够直接行使的。

class pizza(object):
    radius = 42
    @classmethod
    def get_radius(cls):
        return cls.radius
print pizza.get_radius()

类措施对于开创工厂函数最有用,如下

class pizza(object):
    def __init__(self,ingre):
        self.ingre = ingre

    @classmethod
    def from_other(cls,fridge):
        return cls(fridge.juice()+fridge.cheese())  
    def get_ingre(self):
        return self.ingre

cls代表此类,cls()也是用来创立对象,和pizza(fridge.juice()+fridge.cheese())效果同样。待驾驭,工厂方法是怎么?
3、若只想当成二个平时函数,定义不包涵self和cls,则足以应用静态方法,如下:

>>> class Foo(object):
...     @staticmethod
...     def foo():
...             print 'call foo'
... 
>>> Foo.foo()
call foo
>>> Foo().foo()
call foo

作者:_Zhao_
链接:http://www.jianshu.com/p/4b871019ef96
來源:简书

2、@classmethod  修饰类的点子

2、python 子类调用父类方法计算

参照来源

talk is weak,从程序最初:

class Person(object):
    def __init__(self):
        self.name = "Tom"
    def getName(self):
        return self.name

class Student(Person):
    def __init__(self):
        self.age = 12
    def getAge(self):
        return self.age

if __name__ == "__main__":
    stu = Student()
    print stu.getName()

作者:nummy
链接:http://www.jianshu.com/p/dfa189850651

图片 2

image.png

上面只是说Bellamy个常用的子类调用父类场景,即调用父类的早先化函数。
从来运维以上代码会出错,因为就算Student类世襲了Person类,不过并从未调用父类的init()方法,因为子类中对init函数举办了重写,若未有重写会生机勃勃直接轨父类的init函数自动运维。有以下二种办法:

参考
1、super方法

class Base:
    def __init__(self):
        print('Base.__init__')

class A(Base):
    def __init__(self):
        # super().__init__()
        super(A,self).__init__()
        print('A.__init__')

class B(Base):
    def __init__(self):
        # super().__init__()
        super(B,self).__init__()
        print('B.__init__')

class C(A,B):
    def __init__(self):
        # super().__init__()  # Only one call to super() here  python3
        super(C,self).__init__()
        print('C.__init__')

运行结果

>>> c = C()
Base.__init__
B.__init__
A.__init__
C.__init__
>>>

2、调用未绑定的父类构造方法

class Person(object):
    def __init__(self):
        self.name = "Tom"
    def getName(self):
        return self.name

class Student(Person):
    def __init__(self):
        Person.__init__(self)
        self.age = 12
    def getAge(self):
        return self.age

if __name__ == "__main__":
    stu = Student()
    print stu.getName()

作者:nummy
链接:http://www.jianshu.com/p/dfa189850651

非绑定方法不平时利用,上述现象却选用的可比多(即子类覆盖父类的格局卡塔 尔(阿拉伯语:قطر‎。运营时不曾父类person的实例,须要体现地开展传递,但有Student的实例,可以用来开展替代。
这种措施叫做调用父类的未绑定的构造方法。在调用八个实例的艺术时,该方法的self参数会被电动绑定到实例上(称为绑定方法卡塔尔。但万风流倜傥直接调用类的格局(例如Person.__init卡塔 尔(阿拉伯语:قطر‎,那么就平昔不实例会被绑定。那样就能够自由的提供应和须求要的self参数,这种措施称为未绑定unbound方法。
经过将日前的实例作为self参数提要求未绑定方法,Student类就能选拔其父类构造方法的具有实现,进而name变量棉被服装置。

带修饰类方法:cls做为方法的第贰个参数,隐式的将类做为对象,传递给艺术,调用时不用实例化。

3、python 方法深入分析顺序

日常性函数方法:self做为第叁个参数,隐式的将类实例传递给艺术,调用方法时,类必得实例化。

参考

上述博文具备很强的参谋意义,转述如下:
在类的多世袭中,方法深入分析顺序M逍客Q具备很关键的意思,比如对以下菱形世襲,D的实例调用show方法,是调用A的照旧C的show。

图片 3

image.png

python深入深入分析顺序的标准化也是一个不息提升的进度,首要有以下多个阶段:

  • 2.2事先的精髓类。杰出类中多再三再四方法分析接收深度优先从左到右找寻,即D-B-A-C-A,约等于说卓绝类中只选用A的show方法。
  • 杰出类对单层世襲未有啥难点,但是对上述来讲,我们分明更愿意使用C的show方法,因为他是对A的具体化,可是卓越类比并不能够完成,于是在2.第22中学引进新式类(世袭自object卡塔尔国,它依旧采纳从左至右的深浅优先遍历,但是假如遍历中冒出重复的类,只保留尾数。何况在定义类时就总结出该类的 MRO 并将其看做类的属性。由此最新类能够直接通过 mro 属性获取类的 MRO。
    例如:

图片 4

image.png

依据深度遍历,其顺序为 [D, B, A, object, C, A, object],重复类只保留最终一个,由此产生 [D, B, C, A, object]

那样看起来好像么反常,可是会有秘密的难题,举个例子破坏了单调性原则,因而在2.3中引进了 __ C3 算法__。

class A():
    def func(self,x,y):
        return x * y

    @classmethod
    def cfunc(cls,x,y):
        return x * y

if __name__=="__main__":
    print A().func(5,5)
    print A.cfunc(4,5)
C3 MRQ

我们把类 C 的线性化(MRO卡塔 尔(阿拉伯语:قطر‎记为 L[C] = [C1, C2,…,CN]。其中 C1 称为 L[C] 的头,其他成分 [C2,…,CN] 称为尾。假设叁个类 C 袭承自基类 B1、B2、……、BN,那么大家可以依照以下两步总括出 L[C]:
1、L[object] = [object]
2、L[C(B1…BN)] = [C] + merge(L[B1]…L[BN], [B1]…[BN])
此处的关键在于 merge,其输入是生机勃勃组列表,遵照如下方式出口二个列表:
反省第二个列表的头成分(如 L[B1] 的头),记作 H。
若 H 未出现在其他列表的尾巴,则将其出口,并将其从持有列表中除去,然后回来步骤1;不然,抽出下八个列表的头顶记作 H,继续该手续。
再一次上述手续,直至列表为空只怕无法再寻觅能够出口的因素。假设是前风度翩翩种情形,则算法截止;如若是后大器晚成种状态,表明不可能营造世襲关系,Python 会抛出极其。

举例:

图片 5

image.png

据悉C3,计算进程为:

图片 6

image.png

 

4、python定制类和法力方法

3、@staticmethod  修饰类的方法

参谋学习

形如__xxx__的变量或然函数名要在意,这一个在Python中是有破例用处。司空见惯的就是__inint__()函数了,在目的创制后用来开头化,相近的还恐怕有__new()__ 和__del__函数。用的不是过多,不做细节浓重。

1)是把函数嵌入到类中的生龙活虎种方法,函数就归于类,同期注明函数没有供给拜会那些类

__str__ 和 __rerp__
class yuan(object):
    def __init__(self):
        self.name = 'yuanqijie'
        self.age = 22
        self.ambition = 'yes'
    def __str__(self):
        return 'object name: %s'  % self.name

qijie = yuan()
print qijie

输出为:
object name: yuanqijie

若未有重写 __str__ 则输出为 <main.Student object at 0x109afb310>
但只顾到,若向来出口变量并不是用print在晋升符下依旧上述音讯,因为一向显示变量调用的不是str(),而是repr(),两个的分别是str()重返客户观察的字符串,而repr()再次来到程序开发者见到的字符串,约等于说,repr()是为调节和测量检验服务的。能够接近上述形式开展重写,作为精通就可以。

 2)使用修饰服,修饰方法,无需实例化

5、__slots__

当定义多个类时,能够动态的给该类绑定二个属性和方法,比方:

>>> class Student(object):
...     pass

>>> s = Student()
>>> s.name = 'Michael' # 动态给实例绑定一个属性
>>> print s.name
Michael

>>> def set_age(self, age): # 定义一个函数作为实例方法
...     self.age = age
...
>>> from types import MethodType
>>> s.set_age = MethodType(set_age, s, Student) # 给实例绑定一个方法
>>> s.set_age(25) # 调用实例方法
>>> s.age # 测试结果
25

留意的是,下面是给二个实例绑定的附和的措施,也正是说当在千变万化八个实例时,上述扩张的质量和办法就不起作用了。能够给class绑定方法:

>>> def set_score(self, score):
...     self.score = score
...
>>> Student.set_score = MethodType(set_score, None, Student)

只需将MethodType第贰个参数改为None就能够。

 

__slots__ 用来界定属性
>>> class people(object):
...     __slots__ = ('age','name') # 用tuple定义允许绑定的属性名称
... 
>>> p = people()
>>> p.age = 20
>>> p.na = yuan
>>> p.na = 'yuan'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'people' object has no attribute 'na'
>>> p.name = 'yuan'
>>> 
class A():
    def func(self,x,y):
        return x * y


    @staticmethod
    def sfunc(x,y):
        return x * y


if __name__=="__main__":

    print A.sfunc(6,5)

6、@property使用

参考
http://python.jobbole.com/80955/
由地点后生可畏节能够理解,绑定属性时,能够随便退换属性值,比如

s = Student()
s.score = 9999

重重时候都亟待对属性值举办剖断,譬如正负,大小范围等,平日的话就供给写三个函数进行逻辑检查,比如:

class Student(object):

    def get_score(self):
        return self._score

    def set_score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

如此那般就能够保证能对传播的值举行逻辑约束,可是每一遍设置要求调用相应函数,举个例子s.set_score( 99 ),又彰显不是很简短,能否像 s.score = 99同等简单又能实行逻辑检查吧。正是@property。
@property装饰器能够将多个method变为属性,能够像属性同样轻松调用,如student.get_score ,若未有装饰器,则赶回的是函数地址。关于setter用法见下。

class Student(object):

    @property
    def score(self):
        return self._score

    @score.setter
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

@score.setter装饰器表示能够对该属性赋值,若未有则是八个只读的属性。

 

7、修饰器

参照学习

 

示例1:
class myDecorator(object):
    def __init__(self, fn):
        print "inside myDecorator.__init__()"
        self.fn = fn

    def __call__(self):
        self.fn()
        print "inside myDecorator.__call__()"


@myDecorator
def aFunction():
    print "inside aFunction()"

print "Finished decorating aFunction()"
aFunction()

运维上述输出为:

inside myDecorator.__init__()
Finished decorating aFunction()
inside aFunction()
inside myDecorator.__call__()

Linux and python学习交流1,2群已满.

示例2:
def check_is_admin(f):
    def wrapper(*args, **kwargs):
        if kwargs.get('username') != 'admin':
            raise Exception("error occur")
        return f(*args, **kwargs)
    return wrapper

class store(object):
    @check_is_admin
    def get_food(self,username,food):
        print food

s = store()
s.get_food(username='admin',food='noodles')
print s.get_food.__name__

上述程序定义了check_is_admin的装饰器,装饰器的机要功能是调用某些函数在此以前实行意气风发类通用的操作,举个例子日志职分,上述是实行了权力检查。
函数棉被服装饰器修饰时,本质上函数变为
get_food = check_is_admin(get_food(self,username,food))
check_is_admin直接重回wrapper函数地址,因而get_food也是指向wrapper函数,故print s.get_food.__name__结果是 wrapper.
就此调用s.get_food(username='admin',food='noodles')也就是
wrapper(username='admin',food='noodles')。该函数最终一定会就要有return f(*args, **kwargs) ,那确定保障原本函数被实行并赶回结果。
因为装饰器使原函数指向了另二个函数(如上边的wrapper卡塔尔国,而原函数只是该函数的风流倜傥局地,该方式真正对原函数实行了增添。但还要引进了此外的难题,原函数的本性和名字未有了,如上面s.get_food.__name__并不是get_food。functools提供了名字为wraps的装饰器,会复制那几个属性给装饰器函数,用法如下:

import functools
def check_is_admin(f):
    @functools.wraps(f)
    def wrapper(*args, **kwargs):
        if kwargs.get('username') != 'admin':
            raise Exception("error occur")
        #return f(*args, **kwargs)
    return wrapper

只需额外增添两行代码。
值得生龙活虎提的是,**kwargs钦赐了字典情势传入数据,由此只帮助s.get_food(username='admin',food='noodles')而不帮忙s.get_food('admin','noodles')。为了代码的通用性,构思对其开展完美,使用inspect模块,最后为:

import functools
import inspect
def check_is_admin(f):
    @functools.wraps(f)
    def wrapper(*args, **kwargs):
        func_args = inspect.getcallargs(f,*args,**kwargs)
        if func_args.get('username') != 'admin':
            raise Exception("error occur")
        print 'test'
        return f(*args, **kwargs)
    return wrapper

func_args会以字典情势记录对应的key和value。意味着装饰器不用检查参数是还是不是是基于地方的参数依旧首要字参数,最后以同等的格式保存在回来字典中。

Linux and python学习交流3群新开,应接参与,一齐学习.qq 3群:563227894

不前进,不倒退,截至之处是未曾的.

同步前进,与君共勉,

 

本文由永利402游戏网站-永利402com官方网站发布于网络编程,转载请注明出处:Python基础(七) python自带的三个装饰器

关键词: