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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...