- 繼承 : 提高代碼的重用性,規(guī)范代碼(要就繼承父類的子類都實(shí)現(xiàn)相同的方法:抽象類、接口)
- 當(dāng)你開始編寫兩個(gè)類的時(shí)候,出現(xiàn)了重復(fù)的代碼,通過繼承來簡(jiǎn)化代碼,把重復(fù)的代碼放在父類中
- 單繼承
- 重用性 :減少代碼的重復(fù),子類可以復(fù)用父類的方法
- 派生 :子類在父類的基礎(chǔ)上又創(chuàng)建了自己的新的方法和屬性
- 子類中有父類的同名方法 : 只用子類的
- 還希望用到父類中的方法 : 父類名、super調(diào)用
- 抽象類 :只能被繼承 不能被實(shí)例化 模板、規(guī)則
- 單繼承
from abc import ABCMeta,abstractmethod
class A(metaclass=ABCMeta):
@abstractmethod
def func(self):pass
-
多繼承 python / c++
- java/c#沒有
- 每個(gè)類中有每個(gè)類能完成的方法
創(chuàng)建子類的時(shí)候只需要挑選和我相符合的父類來繼承就能夠完成父類的功能了
接口 :java中的一種數(shù)據(jù)類型
-
經(jīng)典類和新式類的區(qū)別:
- 經(jīng)典類 不主動(dòng)繼承object、沒有mro方法、沒有super、繼承的時(shí)候 深度優(yōu)先
- 新式類 主動(dòng)繼承object、有mro方法、有super、繼承的時(shí)候 廣度優(yōu)先
-
方法和函數(shù)的區(qū)別
- 只有被對(duì)象調(diào)用的類中的方法才能被成為一個(gè)方法
class A:
def func(self):pass
a = A()
print(a.func)
print(A.func)
from types import MethodType,FunctionType
print(isinstance(a.func,MethodType))
print(isinstance(a.func,FunctionType))
print(isinstance(A.func,FunctionType))
print(isinstance(A.func,MethodType))
初始化函數(shù) __init__
構(gòu)造函數(shù) __new__
class User:
def __init__(self,name,pwd):
self.name = name
self.pwd = pwd
class Account:
def __init__(self):
self.user_list = []
def login(self):
username = input('username : ')
password = input('password : ')
for usr in self.user_list:
if usr.name == username and usr.pwd == password:
print('登錄成功')
return True
def register(self):
username = input('username : ')
password = input('password : ')
usr = User(username,password)
self.user_list.append(usr)
def run(self):
for i in range(2):
self.register()
for i in range(3):
if self.login():
break
else:
print('登錄失敗')
obj = Account()
obj.run()
多態(tài)
1
- 什么是多態(tài)
- 多態(tài)性是指在不考慮實(shí)例類型的情況下使用實(shí)例
- 一個(gè)類表現(xiàn)出的多種狀態(tài) : 通過繼承來實(shí)現(xiàn)的
- 在python中:函數(shù)的參數(shù)不需要指定數(shù)據(jù)類型,所以我們也不需要通過繼承的形式來統(tǒng)一一組類的類型,
換句話說 所有的對(duì)象其實(shí)都是object類型,所以在python當(dāng)中其實(shí)處處是多態(tài)
2
- 鴨子類型
- Python崇尚鴨子類型
- 如果看起來像、叫聲像而且走起路來像鴨子,那么它就是鴨子
def len(obj)
len() # str list tuple dict set range(3)
print() # 所有的對(duì)象都是鴨子類型
不是明確的通過繼承實(shí)現(xiàn)的多態(tài)
而是通過一個(gè)模糊的概念來判斷這個(gè)函數(shù)能不能接受這個(gè)類型的參數(shù)
3
封裝
- 廣義上的封裝 :對(duì)象只能調(diào)用自己類的屬性和方法
- 廣義上的封裝 :把屬性函數(shù)都放到類里
- 狹義上的封裝 :定義私有成員
class 類名:
def 方法1(self):pass
是為了只有這個(gè)類的對(duì)象才能使用定義在類中的方法
- 僅僅只是一種語法意義上的變形,主要用來限制外部的直接訪問
- 封裝的真諦在于明確地區(qū)分內(nèi)外,封裝的屬性可以直接在內(nèi)部使用,而不能被外部直接使用
- 外部要想用類隱藏的屬性,需要我們?yōu)槠溟_辟接口
把一個(gè)名字藏在類中
- 在繼承中,父類如果不想讓子類覆蓋自己的方法,可以將方法定義為私有的
#正常情況
>>> class A:
... def fa(self):
... print('from A')
... def test(self):
... self.fa()
...
>>> class B(A):
... def fa(self):
... print('from B')
...
>>> b=B()
>>> b.test()
from B
#把fa定義成私有的,即__fa
>>> class A:
... def __fa(self): #在定義時(shí)就變形為_A__fa
... print('from A')
... def test(self):
... self.__fa() #只會(huì)與自己所在的類為準(zhǔn),即調(diào)用_A__fa
...
>>> class B(A):
... def __fa(self):
... print('from B')
...
>>> b=B()
>>> b.test()
from A
- 封裝方法
- 目的:是隔離復(fù)雜度
class ATM:
def __card(self):
print('插卡')
def __auth(self):
print('用戶認(rèn)證')
def __input(self):
print('輸入取款金額')
def __print_bill(self):
print('打印賬單')
def __take_money(self):
print('取款')
def withdraw(self):
self.__card()
self.__auth()
self.__input()
self.__print_bill()
self.__take_money()
a=ATM()
a.withdraw()
私有變量不能被繼承,不能在外部定義
-
類中的私有成員:
- 私有的靜態(tài)屬性
- 私有的對(duì)象屬性
- 私有的方法
-
我為什么要定義一個(gè)私有變量呢:
- 我不想讓你看到這個(gè)值
- 我不想讓你修改這個(gè)值
- 我想讓你在修改這個(gè)值得時(shí)候有一些限制,保證了數(shù)據(jù)的安全
- 有些方法或者屬性不希望被子類繼承
property是一個(gè)裝飾器函數(shù) ---># 將一個(gè)方法偽裝成一個(gè)屬性
裝飾器的分類:
裝飾函數(shù)
裝飾方法 : property
裝飾類
class Student:
def __init__(self,name,age):
self.__name = name
self.age = age
@property # 將一個(gè)方法偽裝成一個(gè)屬性
def name(self):
return self.__name
a = Student('諸葛',20)
print(a.name)
-
判斷是函數(shù)還是方法
from types import FunctionType,MethodType property
一個(gè)方法被偽裝成屬性之后
應(yīng)該可以執(zhí)行一個(gè)屬性的增刪改查操作
那么增加和修改 就對(duì)應(yīng)這被setter裝飾的方法 :這個(gè)方法又一個(gè)必傳的參數(shù)new,表示賦值的時(shí)候等號(hào)后面的值
刪除一個(gè)屬性 對(duì)應(yīng)著 被deleter裝飾的方法,這個(gè)方法并不能在執(zhí)行的時(shí)候真的刪除這個(gè)屬性,而是你在代碼中
執(zhí)行什么就有什么效果
class Goods:
__discount = 0.8
def __init__(self,price):
self.__price = price
self.name = 'apple'
@property
def price(self):
return self.__price * Goods.__discount
@price.setter
def price(self,new):
self.__price = new #改變私有對(duì)象屬性的值
@price.deleter #刪除私有對(duì)象屬性
def price(self):
del self.__price
apple = Goods(10) #實(shí)例化
print(apple.price)
print(apple.__dict__)
del apple.price
apple.price = 8 #改變私有對(duì)象屬性
print(apple.price)
print(apple.__dict__)
del apple.name #刪除
print(apple.__dict__)
運(yùn)行結(jié)果
8.0
{'_Goods__price': 10, 'name': 'apple'}
6.4
{'name': 'apple', '_Goods__price': 8}
{'_Goods__price': 8}
Process finished with exit code 0
- @classmethod 類方法
- 類方法的特點(diǎn)
- 只使用類中的資源,且這個(gè)資源可以直接用類名引用的使用,那這個(gè)方法應(yīng)該被改為一個(gè)類方法
class Goods:
__discount = 0.8 # 靜態(tài)屬性
def __init__(self,price):
self.__price = price # 對(duì)象屬性
self.name = 'apple'
@property
def price(self):
print(self)
return self.__price * Goods.__discount
@classmethod
def change_discount(cls,new): # 類方法
cls.__discount = new
- @staticmethod 靜態(tài)方法
class Student:
@staticmethod
def login(usr,pwd):
print('IN LOGIN',usr,pwd)
Student.login('user','pwd')
- 在類中:
- 靜態(tài)屬性 類 所有的對(duì)象都統(tǒng)一擁有的屬性
- 類方法 類 如果這個(gè)方法涉及到操作靜態(tài)屬性、類方法、靜態(tài)方法 cls 表示類
- 靜態(tài)方法 類 普通方法,不使用類中的命名空間也不使用對(duì)象的命名空間 : 一個(gè)普通的函數(shù) 沒有默認(rèn)參數(shù)
- 方法 對(duì)象 self 表示對(duì)象
- property方法 對(duì)象