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

说起装饰器,就不得不说python自带的多个装饰器:

剧情涵盖:

本文实例讲述了Python装饰器(decorator)定义与用法。分享给大家供大家参考,具体如下:

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

  • 元类
  • python 对象和类的绑定以及类格局,静态方法
  • python 子类调用父类方法总计
  • python 方法分析顺序M奇骏Q
  • python定制类和魔法方法
  • 至于用法__slots__
  • @property使用
  • 修饰器

怎么样是装饰器(decorator)

 @property 修饰,正是将艺术,产生5脾性子来行使。

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

一、python 对象和类的绑定以及类方式,静态方法

普通大家要动用二个类中的方法时,都急需实例化该类,再拓展调用,那类中
self 和 cls
有哪些意义,能还是无法不开头化3个实例而一贯调用类方法,对象方法和类格局,静态方法又有如何关联。是本篇小说考虑的难题。

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

>>>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(object一, ‘abc’)
时,必须显式的将实例名与 self 关联,不然将会报出”TypeError: unbound
method func() must be called with Test instance as first argument (got
str instance instead)” 的错误。

装饰器

 

参考学习

知情以下几点:
①、类私下认可的方法都以绑定对象的,而self参数也是指向该目的,未有实例化对象时,类中方法调用会出错,也关系到python自动传送self参数。
2、若想不实例化而直白通过 类名.方法
来调用,须要钦点该措施绑定到类,如下,1要使用@classmethod
装饰器,2方法中率先个参数为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())效果同样。待掌握,工厂方法是怎么样?
叁、若只想当成几个常见函数,定义不分包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
來源:简书

最简便易行的函数,重回三个数的和

二、@classmethod
 修饰类的办法

贰、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

地点只是说圣元(Nutrilon)个常用的子类调用父类场景,即调用父类的开端化函数。
平素运转以上代码会出错,因为纵然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__
>>>

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

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变量被设置。

def calc_add(a, b):
 return a + b
calc_add(1, 2)

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

三、python 方法分析顺序

只是今后又有新的急需,总括求和操作耗费时间,很简短,求和前取得一下时光,求和后再拿走二遍,求差即可

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

参考

上述博文具备很强的参照意义,转述如下:
在类的多承接中,方法分析顺序MCRUISERQ具有很要紧的意义,比如对以下菱形承袭,D的实例调用show方法,是调用A的依然C的show。

图片 3

image.png

python解析顺序的规范化也是1个不停升高的经过,重要有以下八个等级:

  • 二.二事先的经文类。杰出类中多一而再方法分析选择深度优先从左到右找寻,即D-B-A-C-A,也便是说卓绝类中只选择A的show方法。
  • 优良类对单层承接未有怎么难题,可是对上述来讲,大家强烈更乐于使用C的show方法,因为他是对A的具体化,但是卓越类比并不能够得以落成,于是在二.第22中学引进新式类(承继自object),它依旧选择从左至右的深度优先遍历,不过假设遍历中冒出重复的类,只保留最终1个。并且在定义类时就总结出该类的
    MRO 并将其看成类的属性。因而最新类能够直接通过 mro 属性获取类的
    MRO。
    举个例证:

图片 4

image.png

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

那样看起来好像么有毛病,然则会有机密的难点,比如破坏了单调性原则,因而在二.3中引进了
__ C3 算法__。

import datetime
def calc_add(a, b):
 start_time = datetime.datetime.now()
 result = a + b
 end_tiem = datetime.datetime.now()
 print "result:", result, "used:", (end_tiem - start_time).microseconds, "μs"
 return result
calc_add(1, 2)
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 继承自基类
B一、B贰、……、BN,那么大家得以依照以下两步计算出 L[C]:
1、L[object] = [object]
2、L[C(B1…BN)] = [C] + merge(L[B1]…L[BN], [B1]…[BN])
这里的关键在于 merge,其输入是1组列表,依据如下格局出口2个列表:
检查第1个列表的头成分(如 L[B1] 的头),记作 H。
若 H
未现身在其它列表的尾巴,则将其出口,并将其从有着列表中删去,然后重回步骤壹;否则,收取下一个列表的尾部记作
H,继续该手续。
再也上述手续,直至列表为空大概不能够再搜索能够输出的要素。若是是前一种意况,则算法停止;假若是后1种状态,表达不能营造承袭关系,Python
会抛出非凡。

举例:

图片 5

image.png

依照C3,总括进程为:

图片 6

image.png

现在呢,函数calc_diff(a, b),总括a-b,也想总计减法操作的时间差,很好办,把那段代码复制过去.不过1旦大家未来想编的是一个数学函数库,各类函数都想计算其施行耗费时间,总无法二个1个复制代码,想个更加好的办法.

 

4、python定制类和法力方法

作者们知晓,在Python中等高校函授数也是被视为对象的,能够看成参数传递,那么一旦把计算耗时的单身为二个单身的函数calc_spend_time(),然后把须要总计耗费时间的函数例如calc_add的引用传递给它,在calc_spend_time中调用calc_add,那样全数的须求总计耗费时间的函数都毫无修改本人的代码了.

三、@staticmethod
 修饰类的法子

参考学习

形如__xxx__的变量或然函数名要专注,那个在Python中是有独特用途。常见的便是__inint__()函数了,在对象成立后用来起头化,类似的还有__new()__
和__del__函数。用的不是众多,不做细节深刻。

def calc_spend_time(func, *args, **kargs):
 start_time = datetime.datetime.now()
 result = func(*args, **kargs)
 end_tiem = datetime.datetime.now()
 print "result:", result, "used:", (end_tiem - start_time).microseconds, "μs"
def calc_add(a, b):
 return a + b
calc_spend_time(calc_add, 1, 1)
# calc_spend_time(calc_add, a=1, b=2)

1)是把函数嵌入到类中的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()是为调节和测试服务的。能够接近上述方式开展重写,作为明白就可以。

看起来也没有错,负责总括的函数不用改换,只需调用的时候作为参数字传送给总结时间差的函数.但便是那,调用的时候方式变了,不再是clac(1, 二),而是calc_spend_time(clac_add, 1,
2),万一calc_add大规模被调用,那么还得壹处一处找,然后修改回复,仍旧很麻烦.假诺想不修改代码,就得使clac()calc_spend_time(clac)成效同样,那么能够在calc_spend_time()里把传播的clac包装一下,然后回来包装后的新的函数,再把重返的卷入好的函数赋给clac,那么calc()的功能就和上例calc_spend_time(calc())效益同样.

 二)使用修饰服,修饰方法,不须要实例化

5、__slots__

当定义2个类时,能够动态的给该类绑定二特性质和章程,比如:

>>> 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

小心的是,上边是给一个实例绑定的呼应的点子,也正是说当在转换1个实例时,上述增添的性质和章程就不起效率了。能够给class绑定方法:

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

只需将MethodType首个参数改为None就行。

import datetime
def calc_spend_time(func):
 def new_func(a, b):
  start_time = datetime.datetime.now()
  result = func(a, b)
  end_tiem = datetime.datetime.now()
  print "result:", result, "used:", (end_tiem - start_time).microseconds, "μs"
 return new_func
def calc_add(a, b):
 return a + b
calc_add = calc_spend_time(calc_add)
calc_add(1, 2)

发表评论

电子邮件地址不会被公开。 必填项已用*标注