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

 2)使用修饰服,修饰方法,不须求实例化

示例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__()
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)

日常,访问类和实例属性的时候,将回来所蕴藏的连锁值,约等于直接和类(实例的)的__dict__对立。若果要正式这个访问和设值情势的话,

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)
示例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。意味着装饰器不用检查参数是或不是是基于地方的参数依旧根本字参数,末了以同样的格式保存在重回字典中。

Python内置装饰器

class Foo(object):
    def __init__(self,name):
        self._name=name
    @property
    def name(self):
        return self._name
    @name.setter
    def name(self,value):
        self._name=value
    @name.deleter
    def name(self):
        del self._name

 

剧情包涵:

最简便的函数,再次回到四个数的和

class Foo(object):
    def __init__(self,name):
        self.name=name
    def spam(self,x):
        print '%s.%s'%(self.name,x)

 @property 修饰,正是将艺术,变成2个特性来利用。

5、__slots__

当定义二个类时,能够动态的给该类绑定1天性质和措施,比如:

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

注意的是,上边是给3个实例绑定的相应的方式,也正是说当在变更1个实例时,上述扩展的性质和措施就不起成效了。可以给class绑定方法:

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

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

语法糖

python2.6新扩大了3个property装饰器,写起来更为的幽雅。

 

参考

上述博文具有很强的参阅意义,转述如下:
在类的多继承中,方法分析顺序MTiguanQ具有很首要的含义,比如对以下菱形继承,D的实例调用show方法,是调用A的还是C的show。

365bet体育在线网投 1

image.png

python解析顺序的规范化也是五个不息进步的进度,主要有以下多个阶段:

  • 2.二事先的经典类。经典类中多一而再方法分析选择深度优先从左到右搜索,即D-B-A-C-A,也便是说经典类中只采纳A的show方法。
  • 经典类对单层继承未有怎么难题,可是对上述来说,大家理解更乐于使用C的show方法,因为她是对A的具体化,可是经典类比并不可能促成,于是在2.2中引进新式类(继承自object),它依然采纳从左至右的深度优先遍历,不过只要遍历中冒出重复的类,只保留最后1个。并且在定义类时就总结出该类的
    MRO 并将其看成类的习性。因而最新类能够直接通过 mro 属性获取类的
    MRO。
    举个例证:

365bet体育在线网投 2

image.png

循途守辙深度遍历,其顺序为 [D, B, A, object, C, A,
object],重复类只保留最终三个,因而成为 [D, B, C, A, object]

如此那般看起来好像么有反常态,可是会有私人住房的标题,比如破坏了单调性原则,由此在贰.三中引进了
__ C3 算法__。

上面包车型的士例证正是装饰器的定义,包装函数的函数.事实上下边包车型大巴事例还足以更简明

class Foo(object):
    def __init__(self,name):
        self._name=name
    def getname(self):
        return self._name
    def setname(self,value):
        self._name=value
    def delname(self):
        del self._name
    name=property(getname,setname,delname)

 

  • 元类
  • python 对象和类的绑定以及类措施,静态方法
  • python 子类调用父类方法统计
  • python 方法分析顺序M汉兰达Q
  • python定制类和魔法方法
  • 有关用法__slots__
  • @property使用
  • 修饰器
class Human(object):
 """docstring for Human"""
 def __init__(self):
  super(Human, self).__init__()
 @staticmethod
 def say(message):
  if not message:
   message = 'hello'
  print 'I say %s' % message
 def speak(self, message):
  self.say(message)
Human.say(None)
human = Human()
human.speak('hi')

@classmethod定义静态方法和类措施时,实际上就钦定了采取差别的特色函数,以差别的格局处理对这一个措施的拜访。

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

参考学习

通晓以下几点:
一、类暗中同意的方法都以绑定对象的,而self参数也是指向该目的,未有实例化对象时,类中方法调用会出错,也涉嫌到python自动传送self参数。
二、若想不实例化而平昔通过 类名.方法
来调用,须要钦命该措施绑定到类,如下,一要使用@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())效果等同。待了然,工厂方法是何许?
三、若只想当成三个日常函数,定义不分包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
來源:简书

def calc_add(a, b):
 return a + b
calc_add(1, 2)
>>> f=Foo('hello')
>>> f.name
'hello'
>>> f.name='world'
>>> f.name
'world'
>>> del f.name
>>> f.name
AttributeError: 'Foo' object has no attribute '_name'

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

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

输出:

那样就能够对质量实行读取、设置和删除了:

一)是把函数嵌入到类中的壹种艺术,函数就属于类,同时注解函数不须求拜访那些类

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

无参数的函数装饰器

特色的选取遵从统1访问规格。假如未有特色,将会以简练属性的款式拜访属性,而其他质量将以艺术的款型拜访。费劲去询问曾几何时添加额外的()会带来不要求的歪曲。

Linux and
python学习沟通一,二群已满.

__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在提醒符下依旧上述音讯,因为间接显示变量调用的不是365bet体育在线网投,str(),而是repr(),两者的不一致是str()重临用户看到的字符串,而repr()重返程序开发者看到的字符串,相当于说,repr()是为调节和测试服务的。能够接近上述办法开始展览重写,作为驾驭即可。

staticmethod:把类中的方法定义为静态方法,使用staticmethod装饰的秘籍能够使用类或许类的实例对象来调用,不需求传入self

一种艺术是数额描述符,另1种正是python内置的数据描述符协议函数Property()。property是一种非常的值,访问它时会总计它的值。

发表评论

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