Python中的OOP相关术语:抽象/实现,封装/接口,合成,派生/继承/继承结构,泛化/特化,多态,自省/反射。
类的声明:
class ClassName(Bases):
'class documentation string'
class_suite
创建实例:
obj = ClassName()
类的数据属性
class C(object):
foo = 100
print C.foo #100
C.foo = C.foo + 1
print C.foo #101
Methods
class MyClass(object):
def myNoActionMethod(self):
pass
mc = MyClass()
mc.myNoActionMethod()
绑定(绑定及非绑定方法)
为了与OOP管理保持一致,Python严格要求,没有实例,方法是不能被调用的。这种限制即Python所描述的绑定概念(binding),在此,方法必须绑定(到一个实例)才能直接被调用。非绑定的方法可能可以被调用,但实例对象一定要明确给出,才能确保调用成功。
决定类的属性
要知道一个类有哪些属性,有两种方法。最简单的是使用dir()内建函数。另外是通过访问类的字典属性__dict__,这是所有类都具备的特殊属性之一。例:
class MyClass(object):
'MyClass class definition'
myVersion = 1.1
def showMyVersion(self):
print MyClass.myVersion
print dir(MyClass)
print MyClass.__dict__
特殊的类属性
C.__name__ 类C的名字(字符串)
C.__doc__ 类C的文档字符串
C.__bases__ 类C的所有父类构成的元组
C.__dict__ 类C的属性
C.__module__ 类C定义所在的模块
C.__class__ 实例C对应的类(仅在新式类中)
实例
(1)初始化
(2)__init__“构造器”方法
当类被调用,实例化的第一步是创建实例对象。一旦对象创建了,Python检查是否实现了__init__()方法。默认情况下,如果没有定义(或覆盖)特殊方法__init__(),对实例不会施加任何特别的操作。任何所需的特定操作,都需要程序员实现__init__(),覆盖它的默认行为。如果__init__()没有实现,则返回它的对象,实例化过程完毕。
然而,如果__init__()已经被实现,那么它将被调用,实例对象作为第一个参数(self)被传递进去,像标准方法调用一样。调用类时,传进的任何参数都交给了__init__()。实际中,你可以想像成这样:把创建实例的调用当成是对构造器的调用。
总之,(a)你没有通过调用new 来创建实例,你也没有定义一个构造器。是Python 为你创建了对象; (b) __init__(),是在解释器为你创建一个实例后调用的第一个方法,在你开始使用它之前,这一步可以让你做些准备工作。
(3)__new__()“构造器”方法
与__init__()相比,__new__()方法更像一个真正的构造器。类型和类在版本2.2 就统一了,Python 用户可以对内建类型进行派生,因此,需要一种途径来实例化不可变对象,比如,派生字符串,数字,等等。
在这种情况下,解释器则调用类的__new__()方法,一个静态方法,并且传入的参数是在类实例化操作时生成的。__new__()会调用父类的__new__()来创建对象(向上代理)。
(4)__del__()“解构器”方法
一些注意点:
不要忘记首先调用父类的__del__()。
调用 del x 不表示调用了x.__del__() -----前面也看到,它仅仅是减少x 的引用计数。
如果你有一个循环引用或其它的原因,让一个实例的引用逗留不去,该对象的__del__()可能永远不会被执行。
__del__()未捕获的异常会被忽略掉(因为一些在__del__()用到的变量或许已经被删除了)。不要在__del__()中干与实例没任何关系的事情。
除非你知道你正在干什么,否则不要去实现__del__()。
如果你定义了__del__,并且实例是某个循环的一部分,垃圾回收器将不会终止这个循环——你需要自已显式调用del。
静态方法和类方法
(1)staticmethod()和classmethod()内建函数
class TestStaticMethod:
def foo():
print "calling static method"
foo = staticmethod(foo)
class TestClassMethod:
def bar(cls):
print "calling class method"
bar = classmethod(bar)
(2)使用函数修饰符
class TestStaticMethod:
@staticmethod
def foo():
print "calling static method"
class TestClassMethod:
@classmethod
def bar(cls):
print "calling class method"
子类和派生
创建子类:
class SubClassName(ParentClass1[,ParentClass2,...]):
'optional class documentation string'
class_suite
通过继承覆盖方法
class P(object):
def foo(self):
print "Hi,I am P-foo()"
class C(P):
def foo(self):
super(C,self).foo()
print "Hi,I am C-foo()"
p = P()
c = C()
p.foo()
c.foo()
注意:重写__init__不会自动调用基类的__init__。
从标准类派生
class RoundFloat(float):
def __new__(cls,val):
return super(RoundFloat,cls).__new__(cls,round(val,2))
print RoundFloat(1.5955)
print RoundFloat(1.5945)
print RoundFloat(-1.9955)
1.6
1.59
-2.0
class SortedDict(dict):
def keys(self):
return sorted(super(SortedDict,self).keys())
d = SortedDict(zip(["hui","difalo","xxik"],[89,87,56]))
print "By iterator:".ljust(12),[keys for keys in d]
print "By keys():".ljust(12),d.keys()
By iterator: ['xxik', 'hui', 'difalo']
By keys(): ['difalo', 'hui', 'xxik']
多重继承
经典类MRO(Method Resolution Order)为深度优先(DF),新式类为广度优先(BF)。
类、实例和其他对象的内建函数
issubclass(),isinstance()
hasattr(),getattr(),setattr(),delattr()
dir()
super()
vars()
私有化
(1)双下划线
不允许对象直接访问,可以看做模块导入的保护机制,保护__xxx不与父类名字空间相冲突。
(2)单下划线
简单的模块私有化只需要在属性名前,使用一个单下划线字符,就能防止模块的属性用"from module import *"来加载。
REF:Python核心编程