1、python中多重繼承
除了從一個父類繼承外,Python允許從多個父類繼承,稱為多重繼承。
多重繼承的繼承鏈就不是一棵樹了,它像這樣:
class A(object): def __init__(self, a): print 'init A...' self.a = a class B(A): def __init__(self, a): super(B, self).__init__(a) print 'init B...' class C(A): def __init__(self, a): super(C, self).__init__(a) print 'init C...' class D(B, C): def __init__(self, a): super(D, self).__init__(a) print 'init D...'
看下圖:
像這樣,D 同時繼承自 B 和 C,也就是 D 擁有了 A、B、C 的全部功能。多重繼承通過 super()調用__init__()方法時,A 雖然被繼承了兩次,但__init__()只調用一次:
>>> d = D('d') init A... init C... init B... init D...
多重繼承的目的是從兩種繼承樹中分別選擇並繼承出子類,以便組合功能使用。
舉個例子,Python的網絡服務器有TCPServer、UDPServer、UnixStreamServer、UnixDatagramServer,而服務器運行模式有 多進程ForkingMixin 和 多線程ThreadingMixin兩種。
要創建多進程模式的 TCPServer:
class MyTCPServer(TCPServer, ForkingMixin) pass
要創建多線程模式的 UDPServer:
class MyUDPServer(UDPServer, ThreadingMixin): pass
如果沒有多重繼承,要實現上述所有可能的組合需要 4x2=8 個子類。
2、python獲取多重對象
拿到一個變量,除了用 isinstance() 判斷它是否是某種類型的實例外,還有沒有別的方法獲取到更多的信息呢?
例如,已有定義:
class Person(object): def __init__(self, name, gender): self.name = name self.gender = gender class Student(Person): def __init__(self, name, gender, score): super(Student, self).__init__(name, gender) self.score = score def whoAmI(self): return 'I am a Student, my name is %s' % self.name
首先可以用 type() 函數獲取變量的類型,它返回一個 Type 對象:
>>> type(123) <type 'int'> >>> s = Student('Bob', 'Male', 88) >>> type(s) <class '__main__.Student'>
其次,可以用 dir() 函數獲取變量的所有屬性:
>>> dir(123) # 整數也有很多屬性... ['__abs__', '__add__', '__and__', '__class__', '__cmp__', ...] >>> dir(s) ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'gender', 'name', 'score', 'whoAmI']
對於實例變量,dir()返回所有實例屬性,包括`__class__`這類有特殊意義的屬性。注意到方法`whoAmI`也是 s 的一個屬性。
如何去掉`__xxx__`這類的特殊屬性,只保留我們自己定義的屬性?回顧一下filter()函數的用法。
dir()返回的屬性是字符串列表,如果已知一個屬性名稱,要獲取或者設置對象的屬性,就需要用 getattr() 和 setattr( )函數了:
>>> getattr(s, 'name') # 獲取name屬性 'Bob' >>> setattr(s, 'name', 'Adam') # 設置新的name屬性 >>> s.name 'Adam' >>> getattr(s, 'age') # 獲取age屬性,但是屬性不存在,報錯: Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Student' object has no attribute 'age' >>> getattr(s, 'age', 20) # 獲取age屬性,如果屬性不存在,就返回默認值20: 20
實例:
class Person(object):
def __init__(self, name, gender, **kw):
self.name = name
self.gender = gender
self.__dict__.update(kw)
p = Person('Bob', 'Male', age=18, course='Python')
print (p.age)
print (p.course)
結果:
18
Python

