用python做些事:类
stevezhou 2015.11.15
基本语法
经典类:没有明显写出父类,有可能不继承自任何对象
新式类:有显式写出父类,至少继承自object
经典类与新式类区别
1) __slots__,
2) 继承顺序,super
3) __new__,
4) __getattribute__
# python3里所有的类都是新式类
属性
类属性
实例属性
私有属性
_x :可以通过属性名正常访问,需要自己人为约束调用行为
__x :不可能直接访问,但通过'_类名__x'的方式仍可以访问
__x__:系统自带的类私有属性,可以通过属性名正常访问
装饰器描述符
@property #把方法变成属性去访问
@属性.setter #‘属性’要与定义的方法名相同
@属性.deleter
在set值是对属性进行检查
__getattr__ #当调用的属性找不到时,会自动调用__getattr__函数
__setattr__
__delattr__
__slots__:
并没有限制对属性的访问,因为只要你把__dict__加入到__slots__中,你仍然可能设置或删除__slots__规定以外的属性。要真正达到限制访问,可能在每对属性进行操作(设置或删除)时,对属性是否在__slots__中进行检查;
描述符
数据描述符:实现了__get__、__set__的类,可以作为另一个类的属性
非数据描述符:仅实现了__get__
方法
类方法,@classmethod ——绑定类
实例方法 ——绑定实例对象
静态方法,@staticmethod ——无绑定,与函数无区别,只不过是通过类或实例进行调用
特殊方法(魔法方法),__init__ ——在某些场景下进行自动调用,可以是类方法或实例方法
#与函数的区别
形式上的区别
1、调用是通过类和实例进行的,不能直接调用
2、有自己的特殊参数,self,cls
3、有自己的声明语法,@classmethod,@staticmethod,__XX__()
#实质的区别在于绑定
示例:
#coding:utf-8
class Date(object):
def __init__(self,day=0,month=0,year=0):
self.day=day
self.month=month
self.year=year
def __str__(self):
return "{0}-{1}_{2}".format(self.year,self.month,self.day)
@classmethod
def from_string(cls,date_as_string):
year,month,day=map(int,date_as_string.split('-'))
date1=cls(day,month,year)
return date1
@staticmethod
def is_date_valid(date_as_string):
year,month,day=map(int,date_as_string.split('-'))
return day <=31 and month <=12 and year <=3999
@staticmethod
def millenium(month,day):
return Date(month,day,2000)
class DateTime(Date):
def __str__(self):
return "{0}-{1}-{2} - 00:00:00PM".format(self.year,self.month,self.day)
if __name__=="__main__":
s='2015-11-18'
if Date.is_date_valid(s):
date1=Date.from_string('2015-11-18')
print date1
date2=DateTime.from_string('2015-11-18')
print date2
m1=Date.millenium(11,18)
print m1
m2=DateTime.millenium(11,18)
print m2
特殊方法
属性访问:__getattr__,__setattr__,__getattribute__
实例生成/类生成:__init__,__new__
数字计算:__add__,__sub__,__mul__,__div__,__pow__,__round__
调用方法:__str__,__repr__,__len__,__bool__
比较大小:__cmp__,__lt__,__le__,__eq__,__ne__,__gt__,__ge__
# l:less , t:than , e:equal , g:great , n:negative
集合访问:__setslice__,__getslice__,__getitem__,__setitem__,__contains__
迭代器:__iter__,__next__
继承
实例.__class__ :查看是哪个类的实例,如a是类A的实例,则 a.__class__就显示A
实例.__class__.__base__:查看父类
多重继承
经典类(Classic):继承顺序深度优先,可用inspect库的getmro()方法查看继承优先顺序
新式类(New):继承顺序广度优先 ,可用特殊方法__mro__ 查看继续优先顺序(只能用类名,不能用实例名),如 A.__mro__
经典类示例:
class A:
a=1
b=1
class B(A):
b=2
class C(A):
a=3
b=3
c=3
class D(B,C):
pass
if __name__=='__main__':
d=D()
#查看d的属性值
新式类示例:
class A(object):
a=1
b=1
class B(A):
b=2
class C(A):
a=3
b=3
c=3
class D(B,C):
pass
if __name__=='__main__':
d=D()
#查看d的属性值
.如何解决一个父类方法被重复调用?
解决方法:用super方法,super方法仅在新式类里面有
如上例中,在调用父类方法时用:super(D,self).test()
组合
通过已有的类生成新类。
以已有类的实例作为参数,初始化新类的成员。
多态
多态是不同类的相同方法,相同参数,不同功能。调用时便于将一组对象放在集合里,无需判断对象的具体类型,统一调用。
重载:相同方法的不同参数类型。对应python的args,kwargs.
为什么会有多态?
面向对象的设计原则:里氏代换原则,即 父类出现的地方,子类一定可以出现,反之则不一定;
元类
用来创建类的类,即类是元类的实例。
需要理解python中:一切皆为对象。
__class__:用来查看是哪个类的实例。
type是python中内建的元类。
自定义元类:__metaclass__,你可以在__metaclass__中放置些什么代码呢?答案就是:可以创建一个类的东西。那么什么可以用来创建一个类呢?type,或者任何使用到type或者子类化type的东东都可以。<摘自:http://blog.jobbole.com/21351/>