1、組合,將幾個橫向關系的組合在一起。所謂的組合就是將類的實例化放到新類里面,那么就將舊類組合進去了。
class Turtle:def __init__(self, x): # 注意 init 前面必須雙下劃線self.num = xclass Fish:def __init__(self, x):self.num = xclass Pool:def __init__(self, x, y):self.turtle = Turtle(x) # Pool類中實例化Turtle對象self.fish = Fish(y)def print_num(self):print('水池中共有烏龜 %d 只,小魚 %d 條!'%(self.turtle.num,self.fish.num))
調用結果:
pool = Pool(2, 7) >>> pool.print_num() 水池中共有烏龜 2 只,小魚 7 條!
?
**:在新類中實例化舊類,如:self.turtle = Turtle(x) ,個人理解為將 Turtle 對象傳遞給 self.turtle 對象(屬性),然后self.turtle 對象就具有Turtle 對象的屬性了(體現在實例化 Pool 對象后,可以調用self.turtle.num,num 在 Pool 類中是沒有定義的)。
java類和對象的區別??
2、Mixin 簡介
Mixin 編程是一種開發模式,是一種將多個類中的功能單元的進行組合的利用的方式,這聽起來就像是有類的繼承機制就可以實現,然而這與傳統的類繼承有所不同。通常 Mixin 并不作為任何類的基類,也不關心與什么類一起使用,而是在運行時動態的同其他零散的類一起組合使用。
特點
使用 Mixin 機制有如下好處:
- 可以在不修改任何源代碼的情況下,對已有類進行擴展;
- 可以保證組件的劃分;
- 可以根據需要,使用已有的功能進行組合,來實現“新”類;
- 很好的避免了類繼承的局限性,因為新的業務需要可能就需要創建新的子類。
多繼承
Python支持多繼承,即一個類可以繼承多個子類。可以利用該特性,可以方便的實現mixin繼承。如下代碼,類A,B分別表示不同的功能單元,C為A,B功能的組合,這樣類C就擁有了類A, B的功能。
class A:def get_a(self):print 'a' class B:def get_b(self):print 'b' class C(A, B): pass c = C() c.get_a() c.get_b()
派生類調用基類構造函數、?
__bases__
多繼承的實現就會創建新類,有時,我們在運行時,希望給類A添加類B的功能時,也可以利用python的元編程特性,__bases__屬性便在運行時輕松給類A添加類B的特性,如下代碼:
A.__bases__ += (B,) a.get_b()
?
其實__bases__也是繼承的機制,因為__bases__屬性存儲了類的基類。因此多繼承的方法也可以這樣實現:
class C:pass C.__bases__ += (A, B, )
?
將類實例化可以得到一個對象?插件方式
以上兩種方式,都是基于多繼承和python的元編程特性,然而在業務需求變化時,就需要新的功能組合,那么就需要重新修改A的基類,這回帶來同步的問題,因為我們改的是類的特性,而不是對象的。因此以上修改會對所有引用該類的模塊都收到影響,這是相當危險的。通常我們希望修改對象的行為,而不是修改類的。同樣的我們可以利用__dict__來擴展對象的方法。
class PlugIn(object):def __init__(self):self._exported_methods = []def plugin(self, owner):for f in self._exported_methods:owner.__dict__[f.__name__] = fdef plugout(self, owner):for f in self._exported_methods:del owner.__dict__[f.__name__] class AFeature(PlugIn):def __init__(self):super(AFeature, self).__init__()self._exported_methods.append(self.get_a_value)def get_a_value(self):print 'a feature.' class BFeature(PlugIn):def __init__(self):super(BFeature, self).__init__()self._exported_methods.append(self.get_b_value)def get_b_value(self):print 'b feature.' class Combine:pass c = Combine() AFeature().plugin(c) BFeature().plugin(c) c.get_a_value() c.get_b_value()
3、類、類對象、實例對象
?
class C:count = 0>>> a = C() >>> b = C() >>> c = C()
>>>a.count
0 >>> c.count += 10 >>> a.count 0 >>> b.count 0 >>> C.count += 100 >>> a.count 100 >>> b.count 100 >>> c.count 10
? ? ? ? ? ? ? ? ? ? ? ? ? ?
類和對象的例子、 1)python中無處不對象。類中定義的屬性時靜態屬性,類屬性和類對象是綁定的,不依賴于實例對象。
2)實例化對象后,進行實例對象屬性的修改不會影響類對象的屬性,所以 c.count += 10不會影響 C.count 的值。
3)修改類對象屬性屬性之后,實例化對象的屬性也會跟著改變,注意,經過實例對象修改過的屬性不隨著類屬性的改變而改變(見上邊染色部分代碼),原因:個人理解為此處類似變量間的復制,實例對象是一個標簽,和類對象指向同一個類屬性地址,所以:a)類屬性改變,實例對象屬性跟著改變;b)單獨修改實例對象屬性是從新開辟堆棧,覆蓋了該實例對象原本的類屬性,所以這個修改不影響類屬性,修改類屬性也不影響經過修改的實例對象屬性。
4、如果屬性名稱和方法名稱一樣,屬性名稱會覆蓋方法名稱。如下:給實例對象 c 定義 x 屬性之后,再調用 x() 方法會報錯。
? ? ? ? ? ? ? ??
java中類與對象的關系是什么、 4、綁定:Python 嚴格要求方法需要有實例才能夠被調用,這種限制就是綁定概念。 個人理解:當實例對象調用方法時,會默認再方法里加一個 self 參數,如下面調用 bb.printBB()報錯是因為 python默認的調用方式是 bb.printBB(bb),而 class BB 的printBB() 方法里面沒有 self 參數,所以出現:TypeError :...but 1 was given 這個報錯。
? ? ??
下面這段代碼驗證上面的個人理解。
class BB:def printBB(self):print('BB')>>> a = BB() >>> a.printBB() BB >>> BB.printBB() Traceback (most recent call last):File "<pyshell#35>", line 1, in <module>BB.printBB() TypeError: printBB() missing 1 required positional argument: 'self' >>> BB.printBB('b') BB
?
5、查看對象屬性:對象.__dict__??
一個類只能有一個對象、? ? ? ?