类和类型
旧版本Python中,类和类型之间有明显区别:內建的对象是基于类型的,自定义的对象则是基于类的,可以创建类但不能创建类型。最近版本的Python中,可以创建内建类型的子类(或子类型),这些类型的行为也更类似于类。
1.创建类
__metaclass__ = type # 确定使用新式类
class Person: # class语句会在函数定义的地方创建自己的命名空间
def setName(self, name):
self.name = name
def getName(self):
return self.name
def greeting(self): # 对象.greet() 等同于 类.greet(对象)
print "Hello, world! I'm %s." % self.name
除非是Python 3.0之前版本中默认附带的代码,否则再继续使用旧式类已无必要。新式类需要在模块或脚本开始时放置赋值语句__metaclass__ = type,除此之外还可通过继承新式类(如Object)来实现。
2.特性、函数和方法
self参数是方法和参数的区别,方法将其第一个参数绑定到所属的实例上,因此无需显式提供该参数(不需要self参数时也可以将特性绑定到普通函数上);
>>> class Class:
def method(self):
print 'I have a self!'
>>> def function():
print "I don't..."
>>> instance = Class()
>>> instance.method()
I have a self!
>>> instance.method = function
>>> instance.mathod()
I don't...
self参数并不依赖于调用方法的方式,可以随意使用其他变量引用同一个方法;
class Bird:
song = 'Squaawk!'
def sing(self):
print self.song
>>> bird = Bird()
>>> birdsong = bird.sing
>>> birdsong()
Squaawk!
只要在其名字前面加上双下划线就可以使方法或特性变成私有(从外部无法访问),类的内部定义中,所有以双下划线开始的名字都被“翻译”成前面加上单下划线和类名的形式。
class Secretive:
def __inacessible(self):
print "Bet you can't see me..."
def acessible(self):
print "The srcret message is:"
self.__inacessible()
>>> s = Secretive()
>>> s._Secretive__inacessible()
Bet you can't see me...
若要让其他对象不要访问内部数据,可以使用单下划线,前面有下划线的名字不会被带星号的import语句(form module import *)导入。
3.类的命名空间
所有位于class语句内的代码都在特殊的命名空间中执行——类命名空间,该命名空间可由类内所有成员访问。
class MemberCounter:
mombers = 0
def init(self):
Membercounter.mombers += 1
>>> m1 = MemberCounter()
>>> m1.init()
>>> MemberCounter.members
1
>>> m2 = MemberCounter()
>>> m2.init()
>>> MemberCounter.members
2
4.指定超类
将其他类名卸载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): # SPAMFilter是Filter的子类
def init(self): # 重写Filter超类中的init方法
self.blocked = ['SPAM']
5.检查继承
- 内建的
issubclass(子类, 超类)函数可以查看一个类是否是另一个的子类; - 使用特殊特性
__bases__可以查看已知类的基类; instance(对象, 类)可以检查一个对象是否是一个类的实例;__class__特性可以查看对象所属的类;
>>> SPAMFilter.__bases__
(<class __main.Filter at 0x171e40>)
>>> Filter.__bases__
()
>>> s.__class__
<class __main.SPAMFilter at 0x1707c0>
6.多个超类
若一个方法从多个超类中继承,先继承的类中的方法会重写后继承的类中的方法