面向物件程式設計——動靜態方法、繼承、屬性查詢、多繼承、派生類
阿新 • • 發佈:2022-04-08
- 動態方法與靜態方法
- 面向物件的三大特性之一:繼承
- 屬性查詢
- 多繼承問題
- 派生類
動態方法與靜態方法
動態方法
# 1.繫結給物件的方法
class Card:
def attack(self):
print(self)
# 類呼叫繫結給物件的方法:有幾個引數就需要傳幾個引數
Card.attack(100) # 100
# 物件呼叫繫結給物件的方法:會自動將當前物件當作第一個引數傳入
obj1 = Card()
obj1.attack() # <__main__.Card object at 0x0000023F96396430>
# 2.繫結給類的方法 class Card: @classmethod def defense(self): print(self) # 類呼叫繫結給類的方法:會自動將當前類當作第一個引數傳入 print(Card) # <class '__main__.Card'> Card.defense() # <class '__main__.Card'> # 物件呼叫繫結給類的方法:也不需要傳參 會將產生該物件的類自動當作第一個引數傳入 obj2 = Card() obj2.defense() # <class '__main__.Card'>
靜態方法
class Card:
@staticmethod
def level(a):
print(a)
1.普通函式:無論誰調都有傳固定的引數個數
# 類呼叫靜態方法:要自己傳值
Card.level(9) # 9
# 物件呼叫靜態方法:也有自己傳值
obj3 = Card()
obj3.level(12) # 12
面向物件的三大特性之一:繼承
""" 面向物件有三大特性 其中最重要的就是繼承!!! 繼承、封裝、多型 """ # 繼承的含義 生活中:子承父業 繼承家產 面向物件中:繼承是子類複用父類的屬性和方法的機制 類A繼承了類B 那麼類A就可以使用類B中所有的資料(資料、功能...) # 繼承的目的 生活中:認多個爹 就能繼承多個爹的財產 面向物件中:通過繼承可以減少程式碼冗餘 提升開發效率 同樣也支援多繼承 eg:類A可以繼承多個類同時擁有多個類裡面的程式碼使用權 class Father: money = '100000w' class Son(Father): pass ''' 我們將被繼承的類稱為:父類或者基類 Father 繼承別人的類稱為:子類或者派生類 Son ''' obj11 = Son() print(obj11.money) # 100000w
名字的查詢順序
不繼承的情況下
# 不繼承的情況下
名字的查詢順序是
先從物件自己的名稱空間中查詢 沒有則去類裡面的名稱空間查詢
物件 >>> 類
# 先從物件自己的名稱空間中找
class Son():
money = 1000
def __init__(self):
self.money = 100
obj11 = Son()
print(obj11.__dict__) # {'money': 100}
print(obj11.money) # 100
# 物件自己的名稱空間內找不到則去物件所在類的名稱空間找 class Son(): money = 1000 obj11 = Son() print(obj11.__dict__) # {} print(obj11.money) # 1000
'''注意設定值的情況下是在自身的名稱空間中新增或者修改資料'''
單繼承的情況下
# 單繼承的情況下
名字的查詢順序是
先從物件自己的名稱空間中查詢 沒有擇取產生物件的類中查詢
如果還沒有並且類有父類則去父類中查詢 以此往復下去!!!
物件 >>> 類 >>> 父類
class Father:
money = '100000w'
car = '勞斯萊斯'
def c(self):
print(f'座駕:{self.car}')
class Son(Father):
car = 'ae-86'
obj11 = Son()
print(obj11.__dict__) # {}
print(obj11.money) # 100000w
print(obj11.car) # ae-86
obj11.c() # 座駕:ae-86
'''當前obj11名稱空間內啥也沒
找money在obj11名稱空間內找不到 則先去的所在類Son裡找
還找不到則去所在父類Father裡找
找car 自身名稱空間內沒有 則取所在類Son裡找 找到了
'''
多繼承的情況下
"""
在python2中存在經典類與新式類
在python3中只有新式類
區分的關鍵在於是否繼承了一個預設的object類
新式類:直接或者間接繼承了object或者其子類的類
經典類:不繼承任何的類
"""
class A:
pass
# print A.__bases__ # 空的
# print(A.__bases__) # (<class 'object'>,)
"""
有時候我們在定義類的時候會習慣性的寫
class MyClass(object):
pass
為了相容python2和python3
"""
強度:研究菱形和非菱形問題object不參與圖形構建
非菱形繼承的情況下
父類中名字的查詢順序就是按照繼承時從左往右依次查詢
如果多個父類還有分類 那麼遵循"深度優先"
ADBECF
菱形繼承的情況下
父類中名字的查詢順序就是按照繼承時從左往右依次查詢
如果多個父類還有分類 那麼遵循"廣度優先"
ADBECFM
派生類
class Card:
def __init__(self, name, attribute):
self.name = name # 卡名
self.attribute = attribute # 屬性
class MonsterCard(Card):
def __init__(self, name, attribute, level, attack, defense):
# 用了Card類裡面的__init__方法之後
super().__init__(name, attribute) # 子類呼叫父類 精簡語法
# super(Monster,self).__init__(name,attribute) 子類呼叫父類完整語法
# 自身還要新增的內容
self.level = level # 等級
self.attack = attack # 攻擊力
self.defense = defense # 防禦力
class TrapCard(Card):
def __init__(self, name, attribute, ctype, effect):
super().__init__(name, attribute)
self.ctype = ctype
self.effect = effect
obj1 = MonsterCard('No.39 希望皇 霍普', '光', '4', 2500, 2000)
print(obj1.__dict__)
# {'name': 'No.39 希望皇 霍普', 'attribute': '光', 'level': '4', 'attack': 2500, 'defense': 2000}
obj2 = TrapCard('神聖防護罩-反射鏡力-', '罠', '通常陷阱', '對方怪獸的攻擊宣言時才能發動。對方場上的攻擊表示怪獸全部破壞。')
print(obj2.__dict__)
# {'name': '神聖防護罩-反射鏡力-', 'attribute': '罠', 'ctype': '通常陷阱', 'effect': '對方怪獸的攻擊宣言時才能發動。對方場上的攻擊表示怪獸全部破壞。'}
"""
如果自己寫的子類需要使用父類的方法 並且還需要基於該方法做擴充套件
這樣的子類我們稱之為派生類(本質還是子類)
那麼可以使用super關鍵字來實現
"""
派生功能前瞻
class MyClass(list):
def append(self,args):
if args == 123:
print('數字123不能追加')
return
super(MyClass, self).append(args)
obj1 = MyClass()
obj1.append(333)
obj1.append(222)
obj1.append(123)
print(obj1)