1. 什么是装饰器?
装饰器(Decorator)是一种特殊的函数,用来给函数添上新功能的函数。
主要用于抽离出大量函数中与函数本身无关的雷同代码并继续重用。
装饰器又可分为带参数和不带参数影响原有输出。
2.@标记:
装饰器以@标记来修饰函数和类的方法,使装饰目标对象更为简单易读。
在python中,@可以将python定义的函数“当作”属性访问,从而提供更加友好的访问方式。
class A:
@staticmethod
def m(self):
pass
相当于
class A:
def m(self):
pass
m=staticmethod(m)
其实就是调用一个函数参数为下行的变量,并且替换它。
3.装饰器的限制:
a.装饰函数要在被装饰函数前被定义
b.装饰器函数包括两层:第一层接收一个函数function,第二层构造一个函数来接收function的参数,然后在内部完成需要添加的功能并正确调用函数,然后在第一层返回第二层构造的这个函数。(之后可以加一个例子)
4语法糖
语法糖意指那些没有给计算机语言添加新功能,只是对人类来说更加“甜蜜”的语法,能够增加程序的可读性,减少代码出错的机会。
5. @classmethod 和@staticmethod
python 中有三种方法,静态方法(staticmethod)、类方法(classmethod)以及实例方法。
def fun(x):
print "executing foo(%s)" %(x)
class A(object):
#实例方法
def foo(self,x):
print "executing foo(%s,%s)" %(self,x)
@classmethod #类方法
def class_foo(cls,x):
print "executing class_foo(%s,%s)" %(self,x)
@staticmethod #静态方法
def static_foo(x):
print "executing static_foo(%s,%s)" %(self,x)
a=A()
1.首先,self 与cls是对类或者实例的绑定。
2.对于一般函数foo(x),可使用foo(x)调用,与任何东西(类与实例)无关。
3.实例方法,在类中每次定义方法的时候都需要绑定这个实例,就是foo(self,x)。为什么要这么做呢?因为实例方法离不开实例,需要把实例自己传给函数,调用的时候为a.foo(x).(其实为foo(a,x).)
4.类方法,同实例方法,只不过传递的是类而不是实例。调用的时候为A.class_foo(x)。
5.静态方法,和普通函数一样,不需要对谁进行绑定,唯一的区别是调用的时候需要使用a.static_foo(x)或者A.static_foo(x).
下面为三种方法调用的差别:
\ 实例方法 类方法 静态方法
a=A() a.foo(x) a.class_foo(x) a.static_foo(x)
A 不可用 A.class_foo(x) A.static_foo(x)
6.@property
常用@property来表明这个实例属性不是直接暴露的,而是可以通过getter和setter方法来实现的。
@property把一个getter方法变成属性,本身又创建了另一个装饰器@scoresetter负责把一个setter方法变成属性。由此,我们拥有一个可控的属性操作。
针对限制score的范围问题:假如写一个set_score方法来设置成绩,一个get_score方法来获取成绩,并在set_score方法中检查参数可实现,但是这种方法(见代码段1)略显复杂,没有直接用属性这么直接简单。所以使用@property来实现。(见代码段2)
代码1:
class Student(object):
# 变量私有,保证外部代码不能随意修改对象内部状态,通过访问限制的保护,代码更加健壮。
def __init__(slef,name,score):
self.__name=name
self.__score=score
# 外部代码要获取score
def get_score(self):
return self.__score
# 外部代码想修改score
def set_score(self,value):
if not isinstance(value,int):
raise ValueError('score must be an interger!')
if value<0 or value>100:
raise ValueError('score must between 0~100!')
self._score=value
代码2:
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
s = Student()
s.score = 60 #OK,实际转化为s.set_score(60)
print s.score #ok 输出60
s.score = 9999 #报错
也可以用来定义只读属性,即只定义getter方法,不定义setter方法。
(birth是可读写,age是只读,因为age是可以根据birth和当前时间计算出来的。)
class Student(object):
@property
def birth(self):
return self._birth
@birth.setter
def birth(self, value):
self._birth = value
@property
def age(self):
return 2014 - self._birth
代码部分来源于python廖雪峰教程。