類
class A(object):
# 類屬性
name = 'cong'
# 類方法
@classmethod
def cm(cls, p1):
print(p1)
# 構造函數
def __init__(self, n):
# 定義實例對象屬性並賦值
self.age = 20
# 定義實例對象的私有屬性,雙下劃線開頭表示私有訪問,外部訪問不到
self.__city = 'shanghai'
A.name = n # 給類對象屬性賦值
# 靜態方法
@staticmethod
def sm(p1, p2):
print(p1, p2)
# 實例方法
def do_something(self):
print('hello')
# 定義實例對象的私有方法,雙下劃線開頭表示私有訪問,外部訪問不到
def __set_city(self, city):
self.__city = city
# 對屬性進行的封裝
def get_city(self):
print('he is from %s' % self.__city)
a = A('congcong')
print(A.name) # cong,使用類對象調用
print(a.name) # cong,當使用實例去調的時候,實際指向類對象的引用
print(a.age) # 20
A.cm('a') # 類對象調用類方法
a.cm('a') # 實例對象調用類方法
A.sm('a', 'b') # 類對象調用靜態方法
a.sm('a', 'b') # 實例對象調用靜態方法
a.do_something() # 使用實例去調用函數
# ---------------在外部設置新的屬性-------------------------
A.sex = 'Male' # 在類的外部定義新的類屬性
a.birthday = '2019-6-16' # 在類的外部定義新的實例屬性
print(A.sex)
print(a.sex)
print(a.birthday)
# ---------------在外部設置新的方法-------------------------
# 在外部,定義一個函數作爲實例方法
def newF1(self):
print('this is external method 1')
# 第一種方法,給類對象設置此實例方法
A.newF1 = newF1
a.newF1()
# 第二種方法,行不通,給實例對象設置此實例方法
# a.newF1 = newF1 # 不能這樣設置,會報TypeError: newF1() missing 1 required positional argument: 'self'
# 第三種辦法,動態綁定實例方法
from types import MethodType
a.newF1 = MethodType(newF1, a)
a.newF1()
繼承、重寫,MRO
"""
Python所有的類都繼承一個統一的基類object
Python子類可以繼承多個父類,這是與JAVA/C# 最大的不同,子類會繼續所有直接父類和間接父類的所有方法和屬性,包括類方法,靜態方法等
如果兩個父類中有兩個相同的方法,Python是通過MRO(Method Resolution Order方法解析順序)來解決的
"""
# A是根父類
class A(object):
def f(self):
print('A.f')
# B繼承於A
class B(A):
# 如果對繼承於父類的訪問不滿意,可以對此方法進行重寫,重寫的方式是:在子類中定義與父類中同名的屬性或方法(包括裝飾器)
def f(self):
print('B.f')
# C繼承於A
class C(A):
def f(self):
print('C.f')
# D繼承於兩個父類B和C
class D(B, C):
def f(self):
# 可以通過super()來調用父類的方法
super().f() # B.f
super(D, self).f() # B.f, super的第一個參數是類對象,第二個參數是實例對象
# 根據D的MRO順序是D->B->C->A,那如果想改這個順序呢
super(B, self).f() # C.f, 以B的下一個類對象作爲被指定的父類
super(C, self).f() # A.f
d = D()
d.f() # B.f 如果兩個父類中有兩個相同的方法,Python是通過MRO來解決的
# 通過調用類對象上的mro()方法,可以查看到解析順序
# [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
print(D.mro())
多態
"""
多態性意味着有多重形式。在面向對象編程範式中,多態性往往表現爲"一個接口,多個功能"
具體主要使用方法是在父類中定義了一個方法,在不同的子類中對此方法進行重寫,在運行過程中根據變量所引用對象的類型,動態地決定調用哪個對象中的方法
"""
class ParentClass(object):
def f(self):
print('ParentClass.f')
class ChildClass1(ParentClass):
def f(self):
print('ChildClass1.f')
class ChildClass2(ParentClass):
def f(self):
print('ChildClass2.f')
def exec(obj):
obj.f()
"""
在JAVA/C#中,調用於必須用
ParentClass p = new ParentClass(); p.f();
ParentClass p = new ChildClass1(); p.f();
ParentClass p = new ChildClass2(); p.f();
這種方法來明確指定p的類型後,才能調用f方法,但在Python中不必要這樣
Python是動態語言,它崇尚"鴨子類型":當看到一隻鳥走起來像鴨子,游泳起來像鴨子,叫起來像鴨子,那這隻鳥就是鴨子,而在JAVA/C#中必須先明確知道對象的類型是什麼,然後纔會執行對應的方法
在鴨子類型中,我們並不關心對象的類型是什麼,到底是不是鴨子,只關心對象的行爲,代碼如下
"""
a = ParentClass()
exec(a) # ParentClass.f
a = ChildClass1()
exec(a) # ChildClass1.f
a = ChildClass2()
exec(a) # ChildClass2.f