python 之 面向對象基礎(組合和封裝)

来源:https://www.cnblogs.com/mylu/archive/2019/07/04/11135203.html
-Advertisement-
Play Games

7.4 組合 解決類與類之間代碼冗餘問題有兩種解決方案: 1、繼承:描述的是類與類之間,什麼是什麼的關係 2、組合:描述的是類與類之間的關係,是一種什麼有什麼的關係 一個類產生的對象,該對象擁有一個屬性,這個屬性的值是來自於另外一個類的對象 7.5 封裝 什麼是封裝: 裝就是把一堆屬性存起來,封的概 ...


7.4 組合

解決類與類之間代碼冗餘問題有兩種解決方案:

1、繼承:描述的是類與類之間,什麼是什麼的關係

2、組合:描述的是類與類之間的關係,是一種什麼有什麼的關係

一個類產生的對象,該對象擁有一個屬性,這個屬性的值是來自於另外一個類的對象

class Date:
    def __init__(self,year,mon,day):
        self.year = year
        self.mon = mon
        self.day = day
    def tell_birth(self):
        print('出生年月日<%s-%s-%s>' % (self.year, self.mon, self.day))
​
class OldboyPeople:
    school = 'oldboy'
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex
        
class OldboyTeacher(OldboyPeople):
    def __init__(self,name,age,sex,level,salary):
        super().__init__(name,age,sex)                  #重用父類功能
        self.level=level
        self.salary=salary
    def change_score(self):
        print('teacher %s is changing score' %self.name)
​
class Oldboystudent(OldboyPeople):
    def __init__(self,name,age,sex,course,):
        super().__init__(name,age,sex,)                 #重用父類功能
        self.course=course
    def choose(self):
        print('student %s choose course' %self.name)
​
​
tea1=OldboyTeacher('egon',18,'male',9,3.1)  #創建老師類的對象tea1
date_obj=Date(2000,1,1)                    #創建Date類的對象date_obj
date_obj.tell_birth()                      #date_obj可以調用綁定方法tell_birth
​
tea1.birth=date_obj                        #tea1的birth屬性來自於Date類的一個對象date_obj   
tea1.birth.tell_birth()                     #tea1的birth屬性可以調用tell_birth屬性                    
stu1=Oldboystudent('張三',16,'male','linux')
stu1.birth=Date(2002,3,3)
stu1.birth.tell_birth()
stu1.choose()                               #使用stu1將兩個類聯繫起來
View Code

7.5 封裝

什麼是封裝: 裝就是把一堆屬性存起來,封的概念就把這些屬性給隱藏起來,其實這種隱藏只是一種語法上的變形,對外不對內

註意:

為一個屬性名加__開頭(註意不要加__結尾),會在類定義階段將屬性名統一變形:_自己的類名__屬性名

class Foo:
    x=1
    __x=1111                #_Foo__x=1111
    def __init__(self,y):
        self.__y=y          #self._Foo__y=y
    def __f1(self):         #_Foo__f1
        print('Foo.f1')
    def get_y(self):
        print(self.__y)     # print(self._Foo__y)
obj=Foo(22222)
print(obj.x)               # 1          
print(obj.__x)              # 報錯
print(obj._Foo__x)         # 1111
​
obj.__f1()                 #報錯
obj._Foo__f1()             # Foo.f1
print(obj.y)               #報錯
print(obj.__y)             #報錯
print(obj._Foo__y)         # 22222
obj.get_y()                # 22222 明確地區分內外,對外是隱藏的,對內是開放的

這種語法意義上變形,只在類定義階段發生一次,類定義之後,新增的__開頭的屬性都沒有變形的效果

Foo.__aaa=1
print(obj.__aaa) # 1

如果父類不想讓子類覆蓋自己的方法,可以在方法名前加__開頭

class Foo:
    def __f1(self): #_Foo__f1
        print('Foo.f1')
    def f2(self):
        print('Foo.f2')
        self.__f1() #obj._Foo__f1()
class Bar(Foo):
    def __f1(self): #_Bar__f1
        print("Bar.f1")
​
obj=Bar()
obj.f2()    # Foo.f2 Foo.f1

7.51 封裝的作用

封裝數據屬性的目的:

把數據屬性封裝起來,然後需要開闢介面給類外部的使用者使用,好處是我們可以在介面之上添加控制邏輯,從而嚴格空間訪問者對屬性的操作

class People:
    def __init__(self,name):
            self.__name=name
​
     def tell_name(self):
                # 添加邏輯
                return self.__name
            
 obj=People('egon')
 #obj.__name
 obj.tell_name()

封裝函數屬性的目的:為了隔離複雜度

class ATM:
    def __card(self):
        print('插卡')
    def __auth(self):
        print('用戶認證')
    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()
obj=ATM()
obj.withdraw()

7.52 封裝之property

用來將類內的函數偽裝成一個數據屬性

例:

體質指數()體重()身高()

  首先需要明確 : bmi是算出來的,不是一個固定死的值,也就說我們必須編寫一個功能,每次調用該功能 都會立即計算一個值

class People:
    def __init__(self,name,weight,height):
        self.name=name
        self.weight=weight
        self.height=height
​
    @property           #於是我們需要為bmi這個函數添加裝飾器,將其偽裝成一個數據屬性
    def bmi(self):
        return self.weight / (self.height * self.height)
    
egon=People('egon',75,1.80)
yl=People('yangli',85,1.74)
# print(egon.bmi())
# print(yl.bmi())
print(egon.bmi)         # 21.604938271604937,調用egon.bmi本質就是觸發函數bmi的執行,從而拿到其返回值
print(yl.bmi)           # 把功能偽裝成一個屬性

@name.setter 和 @name.deleter

# egon.bmi=123 
# egon.bmi背後對應的是一個函數,所以不能賦值
class People:
    def __init__(self,name):
        self.__name=name
​
    @property
    def name(self): 
         # 添加邏輯
        return self.__name
​
    @name.setter
    def name(self,x):
         # 添加邏輯
        self.__name=x
​
    @name.deleter
    def name(self):
         # 添加邏輯
        del self.__name
​
obj=People('egon')
print(obj.name)  # egon
                       # 修改
obj.name='EGON'         # 現在可以賦值
print(obj.name)         # EGON
del obj.name            # 刪除
​
obj.name                # 報錯

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近公司需要開發一個公司內部使用的快遞下單系統,給我的開發任務中有一個生成電子面單功能,為了下單時更方便,利用此功能使用快遞公司給我們的印表機直接列印出電子面單,剛接到這個任務時我想這應該很簡單,不就是做一個表格列印出來嗎,原本以為使用excel或者word等工具直接生成一個文檔,後來經理說不用ex ...
  • 0x00 問題重現 VS COde 打開 .go 文件會自動安裝插件,但是出現了一些工具的下載失敗。 換上全局代理也無法下載。 找了許多教程,但可能由於一些版本的問題,目錄已經變更了,導致吾卡在這裡許久。尤其是 github.com/stamblerre/gocode 。 0x01 解決 MacOS ...
  • 一、前言 眾所周知,spring最核心的兩個功能是aop和ioc,即面向切麵和控制反轉。本文會講一講SpringBoot如何使用AOP實現面向切麵的過程原理。 二、何為aop ​ aop全稱 ,面向切麵,AOP主要實現的目的是針對業務處理過程中的切麵進行提取,它所面對的是處理過程中的某個步驟或階段, ...
  • 目錄 AOP簡介 Spring AOP的2種代理 JDK動態代理 CGLIB代理 AOP簡介 AOP全稱Aspect-Oriented Programming,即面向切麵編程,它是面向對象編程(OOP)的一種補充。 在通常的業務處理中,都會進行事務處理、日誌記錄等操作,比如: 這是一個操作用戶的類, ...
  • 一.矩陣的加減法 輸出: 這樣我們就實現了我們矩陣的加法,下麵我們來實現我們矩陣的乘法 二.矩陣的乘法 輸出: 現在開始矩陣的乘法: 得解。 三.求解逆矩陣 輸出: ...
  • 在介紹C++淺拷貝與深拷貝之前,我們先引出C++的拷貝構造函數。 C++拷貝構造函數是一種特殊的構造函數,其形參是本類對象的引用。用於在建立一個新的對象時,使用一個已經存在的對象來初始化這個新對象。因為拷貝構造函數時特殊的構造函數,所以其沒有返回值類型,且名稱與類名相同;該函數只有一個參數,即此類對 ...
  • 9-1 餐館:創建一個名為Restaurant的類,其方法__init__()設置兩個屬性:restaurant_name和cuisine_type。創建一個名為describe_restaurant()的方法和一個名為open_restaurant()的方法,其中前者列印前述兩項消息,而後者列印一 ...
  • 反射機制初探 走進沼澤 在正常的程式中,先有類,然後再有對象。 取得Class對象(類對象) 實例觀察: 運行結果 發現:調用getClass()方法輸出的是類的完整名稱,等於找到了對象出處: ——這就是“ 反 ” Class 類對象實例化 java.lang.Class是一個類,這個類就是反射操作 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...