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

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)

三、python 方法分析顺序

 

0、元类

元类便是类的类,所反映的极端思想就是全方位皆对象。

图片 1

image.png

关于深层次,待使用到在计算。

谈到装饰器,就只能说python自带的五个装饰器:

示例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)
,那确认保障原来函数被实践并回到结果。
因为装饰器使原函数指向了另2个函数(如上边的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。意味着装饰器不用检查参数是不是是基于地方的参数照旧根本字参数,最后以同等的格式保存在回来字典中。

 @property 修饰,正是将艺术,变成贰脾性格来利用。

C3 MRQ

咱俩把类 C 的线性化(MRO)记为 L[C] = [C1, C2,…,CN]。其中 C1 称为
L[C] 的头,别的成分 [C2,…,CN] 称为尾。若是1个类 C 继承自基类
B一、B2、……、BN,那么大家能够依照以下两步总计出 L[C]:
1、L[object] = [object]
2、L[C(B1…BN)] = [C] + merge(L[B1]…L[BN], [B1]…[BN])
那边的关键在于 merge,其输入是1组列表,根据如下情势出口三个列表:
检查第叁个列表的头成分(如 L[B1] 的头),记作 H。
若 H
未出今后任何列表的尾巴,则将其出口,并将其从拥有列表中剔除,然后再次回到步骤一;不然,取出下贰个列表的底部记作
H,继续该步骤。
再一次上述手续,直至列表为空大概不可能再找出能够输出的成分。假诺是前1种意况,则算法截至;假若是后壹种情况,表达无法构建继承关系,Python
会抛出十一分。

举例:

图片 2

image.png

基于C3,总结进程为:

图片 3

image.png

 

__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()是为调节和测试服务的。能够接近上述形式进行重写,作为了然即可。

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

内容涵盖:

三、@staticmethod
 修饰类的情势

参照学习

形如__xxx__的变量或许函数名要留意,这一个在Python中是有例外用途。常见的正是__inint__()函数了,在指标创立后用来早先化,类似的还有__new()__
和__del__函数。用的不是不可胜言,不做细节深刻。

1)是把函数嵌入到类中的一种办法,函数就属于类,同时申明函数不必要拜访那些类

7、修饰器

参考学习

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

6、@property使用

参考
http://python.jobbole.com/80955/
由地方1节能够领悟,绑定属性时,能够四意修改属性值,比如

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装饰器能够将2个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装饰器表示能够对该属性赋值,若未有则是三个只读的属性。

 

参考

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

图片 4

image.png

python解析顺序的规范化也是3个不停升高的历程,首要有以下七个等级:

  • 2.二在此之前的经典类。经典类中多一而再方法分析选取深度优先从左到右搜索,即D-B-A-C-A,也即是说经典类中只选取A的show方法。
  • 经文类对单层继承未有啥样难点,不过对上述来说,大家明显更乐于使用C的show方法,因为他是对A的具体化,不过经典类比并无法促成,于是在贰.第22中学引进新式类(继承自object),它依旧选用从左至右的吃水优先遍历,可是1旦遍历中出现重复的类,只保留最终3个。并且在定义类时就计算出该类的
    MRO 并将其看作类的习性。由此最新类能够从来通过 mro 属性获取类的
    MRO。
    举个例子:

图片 5

image.png

依照深度遍历,其顺序为 [D, B, A, object, C, A,
object],重复类只保留最终2个,因而变成 [D, B, C, A, object]

那样看起来好像么有失常态,可是会有私人住房的难题,比如破坏了单调性原则,因而在二.叁中引进了
__ C3 算法__。

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

类也是目的,由此和下部的静态方法照旧有不1样。类中平素定义的属性如下,在类情势中也是能够直接采纳的。

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())效果等同。待掌握,工厂方法是什么?
叁、若只想当成1个日常函数,定义不包括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
來源:简书

相关文章