Python的class容许定义许多特殊方法,可让咱们很是方便地生成特定的类。在类中应用或者重写python的特殊方法,获得的类,就是定制类。python
你们都知道print的用法。见下面例子shell
>>> lst = [2,3,4] >>> print lst [2, 3, 4] >>> class Animal(object): pass >>> a = Animal() >>> print a <__main__.Animal object at 0x01E6E990>
为何print都能识别出lst和p的数据类型呢?app
当咱们执行以下代码的时候,就知道为何了?函数
>>> print lst.__str__ <method-wrapper '__str__' of list object at 0x01E641E8> >>> print a.__str__ <method-wrapper '__str__' of Animal object at 0x01E6E990>
__str__特殊方法,能识别出每个数据类型。若是但愿类的实例print a 打印出 ‘object of Animal class’.怎么办?从新定义__str__方法。spa
>>> class Animal(object): def __str__(self): return 'object of Animal class' >>> a = Animal() >>> print a object of Animal class
可是有时候发现直接敲code
>>> a <__main__.Animal object at 0x01E6E990>
__str__不会被调用。由于当直接敲a这行代码的时候,直接调用的并非__str__.而是__repr__.对象
>>> class Animal(object): def __str__(self): return 'object of Animal class' __repr__ = __str__ //偷懒一下 >>> a = Animal() >>> a object of Animal class
python的特殊方法不少,这里就不作一一介绍。下面主要介绍 __slots__,__call__,@property用法。blog
python是一个动态语言,任何实例能够再运行期间都能动态添加实例的属性。可是有时候,想限制实例的添加属性,就使用__slot__方法。见下面例子:继承
>>> class Person(object): __slots__ = ('name','age')//限制只有name和age的属性 def __init__(self,name,age): self.name = name self.age = age >>> p = Person('zhangsan',25) >>> p.age 25 >>> p.name 'zhangsan' >>> p.gender ='man'//直接动态赋属性gender,会出现错误 Traceback (most recent call last): File "<pyshell#42>", line 1, in <module> p.gender ='man' AttributeError: 'Person' object has no attribute 'gender'
__slot__目的是限制当前类所能拥有的属性。因此在继承的环境下,子类不受影响。get
>>> class Student(Person): pass >>> s = Student('zhangsan',26) >>> s.age 26 >>> s.name 'zhangsan' >>> s.gender = 'man'//能够动态添加属性 >>> s.gender 'man'
因此子类Student若是想本身限制添加属性的话,也要经过__slots__来控制。
一个类的实例能够变成一个可调用的对象,只须要实现一个特殊的方法__call__就能够了。
接下来咱们把Student类变成一个可调用的对象:
>>> class Student(Person): def __init__(self,name,score): self.name = name self.score = score >>> class Student(Person): def __init__(self,name,score): self.name = name self.score = score def __call__(self,age): print 'my name is %s'% self.name print 'my age is %d'% age >>> s = Student('lixi',89) >>> s(25) my name is lixi my age is 25
有时候你会发现s(25)乍一眼感受不出来是一个函数仍是对象的实例。python语言函数和对象的实例不是区分的很明显。
上述的class Student中,当修改s实例的score值时,
>>> s.score = 89 >>> s.score = 9999
可是这样没法检查s实例的分数有效性。目前只能这样作:
>>> class Student(object): def __init__(self,name,score): self.name = name self.__score = score def set_score(self,score): if score <0 or score >100: raise ValueError('invalid score') self.__score = score def get_score(self): return self.__score >>> s = Student('wangwu',89) >>> s.set_score(89) >>> s.set_score(9999) //非法值,ValueError Traceback (most recent call last): File "<pyshell#75>", line 1, in <module> s.set_score(9999) File "<pyshell#71>", line 7, in set_score raise ValueError('invalid score') ValueError: invalid score
有时候以为写s.set_score和s.get_score没有直接写s.score那么直接。有没有其余办法?既能直接的s.score又能检查score的有效性?python提供@property高阶函数这样功能需求的装饰器。
>>> class Student(object): def __init__(self,name,score): self.name = name self.__score = score @property def score(self): return self.__score @score.setter def score(self,score): if score <0 or score >100: raise ValueError('invalid score') self.__score = score >>> s = Student('liunx',98) >>> s.score = 89 >>> s.score = 9999 Traceback (most recent call last): File "<pyshell#82>", line 1, in <module> s.score = 9999 File "<pyshell#79>", line 12, in score raise ValueError('invalid score') ValueError: invalid score
小结:
特殊方法:
1.任何数据实例都有特殊方法
2.特殊方法定义在class中
3.不须要直接调用
4.python的某些方法或者函数会直接调用数据实例的特殊方法
实现特殊方法:
1.从新编写用到的特殊方法
2.若是从新一些特殊方法,有些关联的特殊方法也要一并实现。例如:__setattr__,__getattr__,__delattr__