面向对象
类与对象
类是对象的定义,是对象各个特性的说明。
对象是根据类中的定义实际创建出来的实例。
创建类语法:
class <class_name>(base_class[,other base_class, …]): #object 可以是最基本的base_class
def<method_name>(self[,other_args])# 类中的方法第一个参数必须是self。Python在执行时要标识这个方法是属于哪个对象的。这个self参数在调用方法时不需要给出。
<obj_variable> = <class_name>()#创建一个类的对象。
Python支持类继承,创建子类。
Python面向对象的概念:
抽象--- 实现
封装--- 接口
复合 – 组合
派生--- 继承--- 继承结构
泛化--- 特化
多态--- 重载
自省--- 反射
表13.1 特殊类属性
C.__name__ 类C的名字(字符串)
C.__doc__ 类C的文档字符串
C.__bases__ 类C的所有父类构成的元组
C.__dict__ 类C的属性
C.__module__ 类C定义所在的模块
C.__class__ 实例C对应的类(仅新式类中)
方法__init__(self)是一个特殊的方法,相当于构造器方法。在创建一个类的对象时,Python自动调用这个方法做一些初始化操作。
方法__new__(),__new__()方法更像一个真正的构造器。Python 用户可以对内建类型进行派生,因此,需要一种途径来实例化不可变对象,比如,派生字符串,数字,等等。 在这种情况下,解释器则调用类的__new__()方法,一个静态方法,并且传入的参数是在类实例化操作时生成的。__new__()会调用父类的__new__()来创建对象。为何我们认为__new__()比__init__()更像构造器呢?这是因为__new__()必须返回一个合法的实例,这样解释器在调用__init__()时,就可以把这个实例作为 self 传给它。调用父类的__new__()来创建对象,正像其它语言中使用 new 关键字一样。
方法__del__()解构器方法,在对象被“销毁“(对象的所有的引用都清除)时调用该方法,做一些首尾工作。调用 del x 不表示调用了 x.__del__() -----前面也看到,它仅仅是减少 x 的引用计数。
类属性和实例属性:
属性更广义的理解属于另一个对象的对象,包括数据或函数。即数据属性和函数属性。
数据属性是用来存储数据的。
函数属性是用来提供计算的。
具体来说: 数据属性是变量,函数属性是方法。
属性是一个对象,而对象又有属性,进而形成一个属性链。
这里用数据属性用属性表示, 函数属性用方法表示。
类中定义的数据属性是类属性,也可以通过实例访问,但只有通过类访问类属性时,才可以修改类属性。类属性是静态成员,与实例无关,独立于实例。类中定义的常量数据。
常量数据即Python中不可修改数据类型,如数值,字符串,元组。
查看类/对象的属性:
dir()返回的仅是对象的属性的一个名字列表,而__dict__返回的是一个字典,
它的键(keys)是属性名,键值(values)是相应的属性对象的数据值。
实例属性:
实例只包含数据属性。实例属性只能同过构造器用self关键字指定:
class f(object):
'thisis parent class'
ver=1.0
a=[1,2,4]
def__init__(self):
self.ver1='2.0'
self.a1=['a','b','c']
defshow(self):
printself.ver1
printself.a1
print "----class----"
print f.ver
print f.a
obj=f()
print'----objclass----'
print obj.ver
print obj.a
print "----obj----"
print obj.ver1
print obj.a1
print'----method----'
obj.show()
上例中:ver,a在类中声明定义的是类属性,ver1, a1通过self关键字声明定义为实例属性。
类属性可以通过类名引用访问,也可以通过对象名引用访问,但只有通过类名引用访问时才能改变类属性的值。类方法无法访问类属性-存疑??
实例属性只能通过对象引用访问,在对象内部通过self指明是当前对象访问,在对象外部要用对象名引用访问。
方法调用:Python的方法调用一定要绑定到某个对象上。通过对象名调用方法即说明该方法是在当前对象上执行,即该方法绑定到了当前对象上。要调用还没有创建实例的类中的方法,就需要给该方法指定一个对象进行绑定。常见的场景:子类继承父类,重载父类的方法时,如果需要保留父类方法的功能,则需要先调用父类方法,而此时并没有一个父类的实例被创建,这时就需要把被调用的父类方法绑定到当前对象上才能正常执行。 当前对象用self表示,C,Java 中用this表示。绑定语法示例如下—重载父类的__init__()方法:
class <child_class_name>(<parent_class_name>):
def__init__(self):
<parent_class_name>.__init_(self)
[othercode…]
非绑定方法被调用,即直接通过类名引用调用方法,调用时必须将方法绑定到一个对象上,而且这个对象必须是当前作用域中已创建的定义该方法的类的实例或其子类的实例。
因为类的方法在定义时的第一个参数必须是self,即方法所绑定的对象,在对象名引用调用方法时该参数可以省略而默认是当前对象。如果通过类名引用访问方法则要显示指明一个该类或其子类的对象名作为该参数的值。
class F(objet):
defshow():
print‘This is a method’
f=F()
f.show()
F.show(f)
以上两中方法调用是等价的。一种是绑定方法调用,一种是非绑定方法调用。
经典类(没有继承任何基类的自定义类)通过两个内建函数将方法设为静态方法、类方法。定义经典类时不需要括号()。
<func_name > = staticmethod(<func_name>)
<func_name > = classmethod(<func_name>)
新式类(继承了某个父类,object是所有类的基类)中也可以如此使用。
静态方法和类方法是通过类来调用的,不需要指定所属的对象,因为此时还没有对象创建。
在新式类中使用decorators装饰器来指明方法是静态方法或类方法:
@staticmethod
def <func_name>():
@staticmethod
def <func_name>()
多元继承:
如果一个对象有多级的多个父类,则调用该对象的父类方法时,是如何找到应该调用哪一个父类的方法呢?
方法解释顺序(MRO):目前是找到距离继承最近的父类的方法。在继承树上查找所调用的方法时,经典类采用深度优先,新式类采用广度优先。
实例及其它对象的内建函数
issubclass(sub, sup) 如果类 sub 是类 sup 的子类,则返回 True,反之,为 False。
isinstance(obj1, obj2) 如果实例obj1是类obj2或者obj2子类的一个实例;或者如果 obj1
是obj2 的类型,则返回 True;反之,为False。
hasattr(obj, attr) 如果 obj 有属性 attr(用字符串给出),返回 True
getattr(obj, attr[,default]) 获取 obj 的 attr 属性;与返回 obj.attr 类似;如果 attr 不是 obj 的属性,如果提供了默认值,则返回默认值;不然,就会引发一个 AttributeError 异常。
setattr(obj, attr, val) 设置 obj 的 attr 属性值为 val,替换任何已存在的属性值;不然,就创建属性;类似于 obj.attr=val
delattr(obj, attr) 从 obj 中删除属性 attr(以字符串给出);类似于 del obj.attr。
dir(obj=None) 返回 obj 的属性的一个列表;如果没有给定 obj,dir()则显示局部名字空间空间中的属性,也就是 locals().keys()
super(type, obj=None) 返回一个表示父类类型的代理对象;如果没有传入obj,则返 回的super 对象是非绑定的;反之,如果 obj 是一个type,issubclass(obj,type) 必 为True ; 否 则 ,isinstance(obj,type)就必为 True。
vars(obj=None) 返回 obj 的属性及其值的一个字典;如果没有给出 obj,vars()显示局部命名空间字典(属性及其值),也就是locals()。
Python类包含了一些特殊含义的方法,可以通过重载这些方法,让自定义类有特殊的功能:
基本定制型
C.__init__(self[, arg1,...]) 构造器(带一些可选的参数)
C.__new__(self[, arg1, ...])a 构造器(带一些可选的参数);通常用在设置不变数据类
型的子类。
C.__del__(self) 解构器
C.__str__(self) 可打印的字符输出;内建 str()及 print 语句
C.__repr__(self) 运行时的字符串输出;内建 repr() 和‘‘ 操作符
C.__unicode__(self) b Unicode 字符串输出;内建 unicode()
www.Linuxidc.com
Linux公社(www.LinuxIDC.com)是专业的Linux系统门户网站,实时发布最新Linux资讯。C.__call__(self, *args) 表示可调用的实例
C.__nonzero__(self) 为 object 定义 False 值;内建 bool() (从 2.2 版开始)
C.__len__(self) “长度”(可用于类);内建 len()
-----------------------------------------
(待续)
表13.4 可以定制类的特殊方法(续)
特殊方法 描述
对象(值)比较 c
C.__cmp__(self, obj) 对象比较;内建 cmp()
C.__lt__(self, obj) and 小于/小于或等于;对应<及<=操作符
C.__gt__(self, obj) and 大于/大于或等于;对应>及>=操作符
C.__eq__(self, obj) and 等于/不等于;对应==,!=及<>操作符
属性
C.__getattr__(self, attr) 获取属性;内建 getattr();仅当属性没有找到时调用
C.__setattr__(self, attr,val) 设置属性
C.__delattr__(self, attr) 删除属性
C.__getattribute__(self,attr) a 获取属性;内建 getattr();总是被调用
C.__get__(self, attr) a (描述符)获取属性
C.__set__(self, attr, val) a (描述符)设置属性
C.__delete__(self, attr) a (描述符)删除属性
定制类/模拟类型
数值类型:二进制操作符
C.__*add__(self, obj) 加;+操作符
C.__*sub__(self, obj) 减;-操作符
C.__*mul__(self, obj) 乘;*操作符
C.__*div__(self, obj) 除;/操作符
C.__*truediv__(self, obj) e True 除;/操作符
C.__*floordiv__(self, obj) e Floor 除;//操作符
C.__*mod__(self, obj) 取模/取余;%操作符
C.__*divmod__(self, obj) 除和取模;内建 divmod()
C.__*pow__(self, obj[,mod]) 乘幂;内建 pow();**操作符
C.__*lshift__(self, obj) 左移位;<<操作符
表13.4 可定制类的特殊方法(续)
特殊方法 描述
定制类/模拟类型
数值类型:二进制操作符
www.Linuxidc.com
Linux公社(www.LinuxIDC.com)是专业的Linux系统门户网站,实时发布最新Linux资讯。C.__*rshift__(self, obj) 右移;>>操作符
C.__*and__(self, obj) 按位与;&操作符
C.__*or__(self, obj) 按位或;|操作符
C.__*xor__(self, obj) 按位与或;^操作符
数值类型:一元操作符
C.__neg__(self) 一元负
C.__pos__(self) 一元正
C.__abs__(self) 绝对值;内建 abs()
C.__invert__(self) 按位求反;~操作符
数值类型:数值转换
C.__complex__(self, com) 转为 complex(复数);内建 complex()
C.__int__(self) 转为 int;内建 int()
C.__long__(self) 转为 long;内建 long()
C.__float__(self) 转为 float;内建 float()
数值类型:基本表示法(String)
C.__oct__(self) 八进制表示;内建 oct()
C.__hex__(self) 十六进制表示;内建 hex()
数值类型:数值压缩
C.__coerce__(self, num) 压缩成同样的数值类型;内建 coerce()
C.__index__(self) g 在有必要时,压缩可选的数值类型为整型(比如:用于切片
索引等等)
----------------------------------------
续
表13.4 定制类的特殊方法(续)
序列类型
C.__len__(self) 序列中项的数目
C.__getitem__(self, ind) 得到单个序列元素
C.__setitem__(self,ind,val) 设置单个序列元素
C.__delitem__(self, ind) 删除单个序列元素
特殊方法 描述
序列类型
C.__getslice__(self,ind1,ind2) 得到序列片断
C.__setslice__(self, i1,i2,val) 设置序列片断
C.__delslice__(self,ind1,ind2) 删除序列片断
C.__contains__(self, val) f 测试序列成员;内建 in 关键字
C.__*add__(self,obj) 串连;+操作符
C.__*mul__(self,obj) 重复;*操作符
C.__iter__(self) 创建迭代类;内建 iter()
www.Linuxidc.com
Linux公社(www.LinuxIDC.com)是专业的Linux系统门户网站,实时发布最新Linux资讯。映射类型
C.__len__(self) mapping 中的项的数目
C.__hash__(self) 散列(hash)函数值
C.__getitem__(self,key) 得到给定键(key)的值
C.__setitem__(self,key,val) 设置给定键(key)的值
C.__delitem__(self,key) 删除给定键(key)的值
C.__missing__(self,key) 给定键如果不存在字典中,则提供一个默认值
自定义一个迭代器类:
__init__()方法执行前述的赋值操作。__iter__()仅返回 self,这就是如何将一个对象声明为
迭代器的方式,最后,调用 next()来得到迭代器中连续的值。
class anyiter(object):
def __init__(self, a1,a2,a3,a4,a5):
self.a=a1
self.b=a2
self.c=a3
self.d=a4
self.e=a5
self.idx =1
def __iter__(self):
return self
def next(self, howmany=1):
ret =0
#print self.idx
if self.idx==1:
ret = self.a
elif self.idx==2:
ret = self.b
elif self.idx ==3:
ret = self.c
elif self.idx==4:
ret = self.d
elif self.idx==5:
ret = self.e
else:
raise StopIteration
self.idx = self.idx +1
return ret
ai = anyiter(1,2,3,4,5)
#ai.next()
for i in ai:
print i