多態(tài)和封裝

  • 繼承 : 提高代碼的重用性,規(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ì)象
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,674評(píng)論 1 32
  • 一:java概述: 1,JDK:Java Development Kit,java的開發(fā)和運(yùn)行環(huán)境,java的開發(fā)...
    慕容小偉閱讀 1,948評(píng)論 0 10
  • 整理來自互聯(lián)網(wǎng) 1,JDK:Java Development Kit,java的開發(fā)和運(yùn)行環(huán)境,java的開發(fā)工具...
    Ncompass閱讀 1,618評(píng)論 0 6
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 30,262評(píng)論 8 265
  • (萬尚學(xué)習(xí)會(huì))打卡第14天 姓名:何炳 部門:業(yè)務(wù)部 組別:待定 【知~學(xué)習(xí)】 誦讀《道盛和夫自傳》第二章 直面石...
    CrisWellin閱讀 256評(píng)論 0 2

友情鏈接更多精彩內(nèi)容