定义
Python 的 Class 比较特别,和我们习惯的静态语言类型定义有很大区别。
1. 使用一个名为 __init__ 的方法来完成初始化。
2. 使用一个名为 __del__ 的方法来完成类似析购操作。
3. 所有的实例方法都拥有一个 self 参数来传递当前实例,类似于 this。
4. 可以使用 __class__ 来访问类型成员
>>>>>>class MyClass:
def__init__(self):
print"initialize
."
def Foo(self):
print id(self)
>>>>>>= MyClass()
initialize
.
>>>>>> a.Foo()
14412576
>>>>>> id(a)
14412576
Class 有一些特殊的属性,便于我们获得一些额外的信息。
>>>>>>class MyClass(object):
"""This is MyClass's Docoment"""
def__init__(self):
self.i =1234
>>>>>>__doc__#
"This is MyClass's Docoment""This is MyClass's Docoment"
>>>>>>__name__#
'MyClass'
>>>>>>__module__#
'__main__'
>>>>>>__bases__#
(<type 'object'>,)
>>>>>>__dict__#
<dictproxy object at 0x00DC1AD0>
>>>>>>#以下是实例拥有的属性
>>>>>>__class__#
<class'__main__.MyClass'>
>>>>>>__module__#
'__main__'
>>>>>>__dict__#
{'i': 1234}
>>>>>>
继承
Python 支持多继承,但有几点需要注意:
1. 基类 __init__ / __del__ 需显示调用。
2. 继承方法的调用和基类声明顺序有关。
>>>>>>class Base1:
def__init__(self):
print"Base1"
def test(self):
print"Base1 test
"
>>>>>>class Base2:
def__init__(self):
print"Base2"
def test(self):
print"Base2 test
"
>>>>>>class MyClass(Base2,Base1):
def__init__(self):
Base1.__init__(self)
Base2.__init__(self)
print"MyClass"
>>>>>>= MyClass()
Base1
Base2
MyClass
>>>>>> a.test()
Base2 test
>>>>>>#
>>>>>>class MyClass(Base1,Base2):
def__init__(self):
Base1.__init__(self)
Base2.__init__(self)
print"MyClass"
>>>>>>= MyClass()
Base1
Base2
MyClass
>>>>>> a.test()
Base1 test
>>>>>>
成员
Python Class 同样包含类型和实例两种成员。
>>>>>>class Class1:
i =123#
def__init__(self):
self.i =100#
>>>>>>print Class1.i
123
>>>>>>print Class1().i
100
>>>>>>
有几个很 "特殊" 的 "规则" 需要注意。
(1) 我们可以通过实例引用访问类型成员。因此下面的例子中 self.i 实际指向 Class1.i,直到我们为实例新增了一个成员 i。
>>>>>>class Class1:
i =123
def__init__(self):
print self.i
print hex(id(self.i))
>>>>>>#
'0xab5860'
>>>>>>=#
123
0xab5860
>>>>>>__dict__#
{'i': 123, '__module__': '__main__', '__doc__': None, '__init__': <function __init__0x012911B0>}
>>>>>>__dict__#
{}
>>>>>>=100#
>>>>>>#
'0xab5974'
>>>>>>__dict__#
{'i': 100}
>>>>>>
(2) 调用类型内部方法,需要省略 self 参数。
>>>>>>class Class1:
def__init__(self):
self.__test("Hello Python")
def__test(self, s):
print s
>>>>>> Class1()
Hello Python
<__main__.Class1 instance at 0x00DC3800>
>>>>>>
我们可以在成员名称前添加 "__" 使其成为私有成员。
>>>>>>class Class1:
__i=123
def__init__(self):
self.__x= 0
def__test(self):
print id(self)
>>>>>> Class1.i
Traceback (most recent call last):
File "<pyshell#203>", line 1, in<module>
Class1.i
AttributeError: class'i'
>>>>>>__x
Traceback (most recent call last):
File "<pyshell#204>", line 1, in<module>
Class1().__x
AttributeError: Class1 instance has no attribute '__x'
>>>>>>__test()
Traceback (most recent call last):
File "<pyshell#205>", line 1, in<module>
Class1().__test()
AttributeError: Class1 instance has no attribute '__test'
>>>>>>
事实上这只是一种规则,并不是编译器上的限制。我们依然可以用特殊的语法来访问私有成员。
>>>>>> Class1._Class1__i
123
>>>>>>= Class1()
>>>>>> a._Class1__x
0
>>>>>> a._Class1__test()
14432256
>>>>>>
除了静态(类型)字段,我们还可以定义静态方法。
>>>>>>class Class1:
@staticmethod
def test():
print"In Static method
"
>>>>>> Class1.test()
In Static method
>>>>>>
从设计的角度,或许更希望用属性(property)来代替字段(field)。
>>>>>>class Class1:
def__init__(self):
self.__i=1234
defreturn__i
def__i= value
defdel__i
I ="Property I")
>>>>>>= Class1()
>>>>>> a.I
1234
>>>>>>=1000
>>>>>> a.I
1000
如果只是 readonly property,还可以用另外一种方式。
>>>>>>class Class1:
def__init__(self):
self.__i=1234
@property
def I(self):
return__i
>>>>>>= Class1()
>>>>>> a.I
1234
用 __getitem__ 和 __setitem__ 可以实现 C# 索引器的功能。
>>>>>>class Class1:
def__init__(self):
self.__x="a", "b", "c"]
def__getitem__(self, key):
return__x[key]
def__setitem__(self, key, value):
self.__x[key] = value
>>>>>>= Class1()
>>>>>>1]
'b'
>>>>>>1] ="xxx"
>>>>>>1]
'xxx'
>>>>>>