创建自己的对象(类型或者类的对象)是Python的核心概念——非常核心。事实上,Python被称为面向对象的语言。
面向对象程序设计中的属于对象(object)基本上可以看作数据(特性)以及由一系列可以存取、操作这些数据的方法所组成的集合。
多态:即使不知道变量所引用的对象类型是什么,还是能对她进行操作,而它会根据对象(或类)类型的不同而表现出不同的行为。
封装:对全局作用域中其他区域隐藏多余信息的原则。不用关心对象是如何构建的。
继承:子类可以从超类继承方法,在子类上调用方法时,程序会自动从超类调用该方法。
创建类的格式
>>> __metaclass__ = type #确定使用新式类
>>> class Person:
... def set_name(self, name):
... self.name = name
... def get_name(self):
... return self.name
... def greet(self):
... print "Hello, world! I'm %s." % self.name
...
关于类有以下说明:
1. 旧式类和新式类有区别。除非Python3.0之前默认附带的代码,没必要使用旧式类。在新式类中,要在模块或脚本开始的地方放置赋值语句metaclass = type。
2. class语句会在函数定义的地方创建自己的命名空间。
3. 方法参数的self表示对象自己。在方法被调用时,自动将对向自己传递给方法(不需要用户显式传递)。例如:
```
>>> foo=Person()
>>> foo.set_name('holly')
>>> foo.get_name()
'holly'
>>> foo.greet()
Hello, world! I'm holly.
```
4. 类的特性(例如例子中self.name)可以在外部访问。
```
>>> foo.name
'holly'
```
方法将它的第一个参数绑定到所属的实例上,调用方法时可以不必提供该参数。可以将特性绑定到普通函数上,就不会有特殊的self参数了。
>>> class Class:
... def method(self):
... print 'I have a self!'
...
>>> def function():
... print "I don't..."
...
>>> foo = Class()
>>> foo.method()
I have a self!
>>> foo.method = function
>>> foo.method()
I don't...
self参数不取决于调用方法的方式,可以随意使用引用同一个方法的其他变量。
>>> class Bird:
... song = 'Squaawk!'
... def sing(self):
... print self.song
...
>>> bird = Bird()
>>> bird.sing()
Squaawk!
>>> birdsong = bird.sing
>>> birdsong()
Squaawk!
为了让方法或特性变为私有,只要在它的名字前添加双下划线。
>>> class Secretive:
... def __inaccessible(self): #定义私有方法
... print 'Bet you can\'t see me...'
... def accessible(self):
... print 'The secret message is:'
... self.__inaccessible()
...
>>> s = Secretive()
#外部无法访问私有方法
>>> s.__inaccessible()
Traceback (most recent call last):
File "" , line 1, in
AttributeError: 'Secretive' object has no attribute '__inaccessible'
>>> s.accessible()
The secret message is:
Bet you can't see me...
★在类的内部定义中,所有双下划线开始的名字都被“翻译”称前面加上下划线和类名的形式。因此可以采用这种方式访问私有方法。
>>> Secretive._Secretive__inaccessible
method Secretive.__inaccessible>
有些语言支持多种层次的成员变量(特性)私有性。比如Java就支持4中级别。尽管单双下划线在某种程度上给出两个级别的私有性,但Python并没有真正的私有化支持。
定义类时,所有位于class语句中的代码都在特殊的命名空间中执行——类命名空间(class namespace)。该空间可由类内所有成员访问。
★Python中,类的定义就是执行代码块,例如:
>>> class C:
... print 'Class C being defined...'
...
Class C being defined...
书中对命名空间的说明有点简略,可参考
http://blog.csdn.net/heli200482128/article/details/74990347
将其他类名写在class语句后的圆括号内可以指定超类。
>>> class Filter:
... def init(self):
... self.blocked = []
... def filter(self, sequence):
... return [x for x in sequence if x not in self.blocked]
...
>>> class SPAMFilter(Filter):
... def init(self): #重载init()
... self.blocked = ['SPAM']
...
>>> s = SPAMFilter()
>>> s.init()
#filter方法是从Filter类中继承的
>>> s.filter(['SPAM', 'SPAM','eggs','bacon','SPAM'])
['eggs', 'bacon']
★参照7.2.5,假定SPAMFilter是Filter的子类。
查看一个类是否是另一个的子类,可使用内建函数issubclass()。
>>> issubclass(SPAMFilter, Filter)
True
>>> issubclass(Filter, SPAMFIlter)
False
若想知道已知类的基类,可以使用特性__bases__
>>> SPAMFilter.__bases__
(<class '__main__.Filter'>,)
检查对象是否是一个类的实例,可以使用函数isinstance()
>>> s = SPAMFilter()
>>> isinstance(s, SPAMFilter) #s是SPAMFilter类的直接实例
True
>>> isinstance(s, Filter) #s是SPAMFilter类的间接实例
True
>>> isinstance(s, str)
False
直接检查对象属于哪个类,可以使用__class__特性
>>> s.__class__
<class '__main__.SPAMFilter'>
多重继承(multiple inheritance)**:子类有多个基类
>>> class Calculator:
... def calculate(self, expression):
... self.value = eval(expression)
...
>>> class Talker:
... def talk(self):
... print 'Hi, my value is', self.value
...
>>> class TalkingCaculator(Calculator, Talker):
... pass
...
>>> tc = TalkingCaculator()
>>> tc.calculate('1+2*3*4/6')
>>> tc.talk()
Hi, my value is 5
2.多重继承需要注意多个超类的继承顺序:先继承的类中的方法会重写后继承的类的方法。 即上个例子中,若Calculator类中也有talk()方法,由于先继承Calculator后继承Talker,当外部调用talk()方法时,将调用Calculator中的talk()。
3. 若超类们共享了一个超类,在查找给定方法或者特性时,访问超类的顺序称为MRO(Method Resolution Order,方法判定顺序)。
♦将属于一类的对象放在一起。若一个函数操纵一个全局变量,两者最好作为类内的特性和方法。
♦不要让对象过于亲密。方法应只关心自己实例的特性。让其它实例管理自己的状态。
♦小心继承,尤其是多重继承。继承机制有时很有用,但某些情况下让事情变得过于复杂。多继承难以正确使用,更难以调试。
♦简单就好。让方法小巧。一般来说,多数方法都应能在30秒内被理解,尽量将代码行数控制在一页或一屏之内。
♦写下问题的描述,把名词、动词、形容词加下划线。
♦对于所有名词,用作可能的类。
♦对于所有动词,用作可能的方法。
♦对于所有形容词,用作可能的特性。
♦把所有方法和特性分配到类。
♦设计一系列使用实例——即程序应用时的场景,试着包括所有的功能。
♦逐个考虑每个场景,保证模型包含所有需要的东西。若有遗漏,则添加;若有错误,则修正。直到满意为止。