31天Python入門——第17天:初識面向對象

在這里插入圖片描述

你好,我是安然無虞。

文章目錄

    • 面向對象編程
      • 1. 什么是面向對象
      • 2. 類(class)
      • 3. 類的實例
        • 關于self
      • 4. 對象的初始化
      • 5. `__str__`
      • 6. 類之間的關系
        • 繼承關系
        • 組合關系
      • 7. 補充練習

在這里插入圖片描述

面向對象編程

1. 什么是面向對象

面向對象編程是一種編程思想,它將現實世界的概念和關系映射到代碼中.
在面向對象編程中,我們通過創建對象來表示現實世界中的事物,并通過定義對象的屬性方法來描述它們的狀態行為.

面向對象編程強調了代碼的模塊化、封裝、抽象、繼承和多態等概念.

例如, 在現實世界中我們需要去記錄一名學生的基本信息, 如果使用文本來記錄: 例如

有一名學生叫張三, 來自北京, 性別男. 這樣可以輕松記錄一名學生的信息.

但是使用如下表格, 結構會更加的清晰.

姓名張三
年齡20
籍貫北京
性別

在現實世界中我們需要去記錄一輛車的基本信息, 需要用到如下表格:

品牌
型號
排量
車架號

上述都表格都可以很清晰的描述學生和車輛的基本信息.

表格相當于是 一個藍圖或者模板. 每個學生都可以拿著這個表格, 填寫自己對應的信息, 在程序中, 上面的表格就相當于是一個類, 通過這個類可以創建多個學生對象.

2. 類(class)

類和對象是面向對象編程的核心概念.
類是一個抽象的概念,用于描述對象的屬性(數據)和方法(行為).
對象則是類的具體實例,表示一個具體的實體.
類(class)

類是一種模板或藍圖,用于創建對象.它定義了對象的屬性和方法,描述了對象的狀態和行為.類通過定義一組相關的屬性和方法來封裝數據和操作,從而提供了一種組織和管理代碼的方式.

Python 中的一切對象都有各自的類型,比如:

整數對象   的類型是   int
字符串對象 的類型是   str
列表對象   的類型是   list
元組對象   的類型是   tuple
字典對象   的類型是   dict

Python 的內置函數type可以查看對象的類型:

>>> type(12)
<class 'int'>    # 整數類型
>>> type('12')
<class 'str'>    # 字符類型
>>> type([1,2])
<class 'list'>   # 列表類型
>>> type((1,2))
<class 'tuple'>  # 元組類型
>>> type({1:2})
<class 'dict'>   # 字典類型

我們掌握了這些內置的數據類型,通常就可以開發Python程序了.

但是當我們要開發的軟件系統 更加復雜的時候,尤其是系統里面的對象 和現實世界的對象 存在對應關系的時候,如果只能用這些內置類型,就會感覺很不方便.

比如,我們的程序要表示一個 奔馳汽車 這樣的對象類型,屬性有:品牌,國家,價格.

如果只用Python的內置類型,大家想想怎么表示.

當然,我們可以定義一個字典類型的對象,比如:

benzCar = {'brand'   : '奔馳','country' : '德國','price'   : 300000
}

如果這個汽車對象還需要有自己特定的行為,比如 按喇叭會發出嘟嘟的聲音。那又該怎么定義呢?

有人說,可以定義一個函數對象作為它的屬性,像這樣:

def  pressHorn():print('嘟嘟~~~~~~')benzCar = {'brand'   : '奔馳','country' : '德國','price'   : 300000,'pressHorn' : pressHorn # 字典對象的值可以是一個函數對象
}# 我可以這樣執行它的行為
benzCar['pressHorn']()

似乎也可以.

但是這里 benzCar 更像是一個具體的對象,并不是一種 對象類型.

而且 這個 benzCar 汽車的 行為的定義 ,要在外面定義一個函數, 然后benzCar字典的內部去引用它,這樣也比較麻煩.

為了解決這樣的普遍問題,Python語言可以讓我們 自己定義對象類型.

Python中自定義對象類型,就是 定義一個類 , 類 就是 類型 的意思.

比如 : 奔馳汽車, 可以這樣定義:

使用 class 關鍵字定義一個類.類名通常使用大寫字母開頭,遵循大駝峰命名規范.

class BenzCar:    brand   = '奔馳'  # 品牌屬性country = '德國'  # 產地屬性@staticmethoddef pressHorn(): print('嘟嘟~~~~~~')

定義一個類 用關鍵字 class 后面加 類的名稱.

類名的規范 和 變量命名規范一樣。 通常我們會把類名 首字母大寫, 這里定義的類名就是 BenzCar

下面定義的 brand, country 都是 BenzCar 類的 屬性.

這種屬性被稱為類屬性

如果我們要得到屬性的值可以這樣用 類名.屬性名 的方式,如下

print(BenzCar.brand)

而 pressHorn 則是該類型的一個 方法.
請注意上面的 @staticmethod 的修飾, 說明這是該類的一個 靜態方法

要調用執行該類的靜態方法,像這樣就可以了:

BenzCar.pressHorn()

類的屬性

類的屬性是與類相關聯的數據,用于描述對象的特征或狀態.
類的屬性可以通過類名或對象訪問.類屬性在類級別上定義,被所有類的實例共享.

類屬性的定義實際上就是寫在類中的變量. (成員變量) - 注意不是實例屬性哦

class Student:name = '張三'age = 0

在上面的示例中, Student類定義了2個類屬性, nameage,它被所有Student類的實例共享. 類屬性可以通過類名或者實例對象訪問.

class Student:name = '張三'age = 18# 類屬性可以通過**類名或者實例對象**訪問print(Student.name)print(Student.age)print("-----------------------------")stu = Student()print(stu.name)print(stu.age)

類的方法

類的方法是與類相關聯的函數,用于定義對象的行為.方法在類中定義,并通過對象調用.方法可以訪問和操作對象的屬性.

class Student:name = '張三'age = 0def introduce(self):print(f'大家好, 我的名字叫{self.name}, 今年{self.age}歲')def study(self):print(f'{self.name}正在努力學習.')stu = Student()stu.introduce()stu.study()

以上示例在Student類中定義了2個方法, introducestudy. 用于定義對象的2個行為: 自我介紹和學習.

上述示例中方法中第一個形參是self的方法叫做實例方法. 類屬性可以通過實例對象self來訪問.

3. 類的實例

Python中 類 是 某種對象的類型.

比如 int 是 整數對象的類型, str是字符串對象的類型, list是 列表對象的類型.

我們把一個個具體的 對象稱為 該類型的 實例,

比如,我們可以說

數字對象 3 是 int 類型的的實例,具有int類型的特征

字符串對象 ‘abc’ 是 str 類型的實例,具有str類型的特性(比如可以執行str的所有方法,比如 find, split等)

列表對象 [1,2,3] 是 list 類型的的實例,具有list類型的特性(比如可以執行list的所有方法,比如 reverse,append等)

同樣的,我們自定義的類,也可以產生該類的實例對象. 每個實例對象就是該類的一個實例,具有該類的一切特征.

要產生一個類的實例對象,只需要 在類名后面加上括號,就可以了,就會返回一個該類的實例對象.

比如:

car1 = BenzCar()

car1 變量就對應了一個 BenzCar 類型 的實例對象,具有 BenzCar 類的一切屬性和方法.大家可以執行下面的代碼試試。

class BenzCar:    brand   = '奔馳'  country = '德國'  @staticmethoddef pressHorn(): print('嘟嘟~~~~~~')car1 = BenzCar()       
print(car1.brand) 
car1.pressHorn()

同樣,我們也可以用 type 函數查看 car1 這個實例的類型,如下所示:

>>> type(car1)
<class '__main__.BenzCar'>

說明 car1 是 __main__ 模塊里面定義的 BenzCar 類型.

大家一定要搞清楚 類 和 實例 的關系.

比如 :

人 就是 一個 類, 而 關羽、張飛 就是 人 這個類的 具體實例.

狗 也是 一個 類, 而 你們家的阿黃 和 隔壁家的旺財 就是狗 這個類的 具體實例.

Python中 定義一個類型 就是描述 這些類型的實例的 公共特征. 后面根據這個類創建的實例 都具有這個類的 特征,就是 具體什么 屬性、方法.

在面向對象編程中,類的對象(Class Object)是類的具體實例, 所以類的對象也叫做實例對象.類定義了對象的屬性和方法,而對象是類的實體,具有自己的屬性值和對類中方法的訪問權限.

實例屬性和實例方法

剛才我們定義的類里面的屬性都是 類屬性 ,里面的方法都是類的 靜態方法 .

所有BenzCar類的實例對象,其 品牌名 brand ,對應的類屬性應該是相同的.

就是說下面這樣的兩個實例:

car1 = BenzCar()     
car2 = BenzCar()

car1 和 car2 的 brand屬性 都是一樣的 值, 都是字符串 ‘奔馳’

很好理解,因為品牌這樣的屬性 對于所有的 奔馳車都是一樣的,都是 ‘奔馳’.

類屬性 是類的共同特征屬性.

但是有些屬性,比如顏色、發動機編號 是每一輛奔馳車 都不同的.

所以,在我們定義的 類BenzCar 里面, 顏色、發動機編號 是 不應該 作為類屬性的.

每個實例獨有的屬性,稱之為 類的實例屬性

實例屬性通常是在類的 初始化方法 init 里面定義的.

比如:

class BenzCar:    brand   = '奔馳'  country = '德國'  @staticmethoddef pressHorn(): print('嘟嘟~~~~~~')# 初始化方法, 注意前后各有兩個下劃線def __init__(self):self.color  =  'red'        # 顏色self.engineSN = '837873398' # 發動機編號

上面的初始化方法 __init__ ,就創建了兩個實例屬性 color 和 engineSN。

為什么 __init__ 方法 叫初始化方法呢?

解釋器在執行 像下面這樣的 實例化類對象 的代碼時,

car1 = BenzCar()

首先,解釋器會 在內存中 創建一個該類 的 實例對象;

然后,解釋器會查看這個類是否有 __init__方法,如果有,就會去調用它.

__init__ 是 創建好實例后 立即就要 執行 的方法,所以稱之為初始化方法.

通常我們會在__init__方法里面 執行一些初始化的動作,主要就是創建該實例的 實例屬性.

__init__ 方法的第一個參數是 self, 它 是干什么用的呢?

剛才說了, 解釋器執行實例化代碼,會先在內存中創建該類實例對象,然后調用類 的__init__方法.

調用 __init__方法時,就將實例對象 傳遞給 self參數.

self 參數變量 指向的 就是 實例對象 本身, 所以下面的代碼就是創建該實例的屬性color 和 engineSN 了

self.color  =  'red'         # 顏色
self.engineSN = '8378738398' # 發動機編號

類的靜態方法要在方法定義 上面加上 @staticmethod 的修飾.

而 類的 實例方法 不需要任何修飾.

通常類的實例方法,都是要 訪問類的實例屬性的. 包括: 創建、修改、刪除 類的實例屬性.

因為 實例方法 就是要操作 實例獨有的屬性,否則不操作任何實例屬性的話,就應該定義為 類方法.

比如 __init__ 初始化方法,就是一個實例方法,它通常要創建一些實例屬性.

而 pressHorn 方法是類的靜態方法, 靜態方法是不能訪問實例屬性的.

有時候,實例屬性的取值,不是固定寫在初始化方法的代碼里面.

比如這里,每輛車的顏色、發動機號都是不同的,我們應該作為參數傳進去.

所以修改代碼為這樣:

class BenzCar:    brand   = '奔馳'  country = '德國'  @staticmethoddef pressHorn(): print('嘟嘟~~~~~~')def __init__(self,color,engineSN):self.color  =  color     # 顏色self.engineSN = engineSN # 發動機編號

這樣我們在創建實例的時候,就可以根據需要指定不同的實例屬性了,比如:

car1 = BenzCar('白色','24503425527866')
car2 = BenzCar('黑色','34598423586877')
print(car1.color)
print(car2.color)
print(car1.engineSN)
print(car2.engineSN)

雖然定義的時候, init 方法 有3個參數 : self,color,engineSN

但是我們這樣調用 BenzCar() 實例化的時候, 只需要傳入后面兩個參數即可,

因為self 參數 需要傳入實例對象本身,解釋器會自動幫我們傳入.

其它的 實例方法也是這樣, 比如我們定義一個 修改車身顏色的方法 changeColor:

class BenzCar:     brand   = '奔馳'  country = '德國'  @staticmethoddef pressHorn(): print('嘟嘟~~~~~~')def __init__(self,color,engineSN):self.color  =  color     # 顏色self.engineSN = engineSN # 發動機編號def changeColor(self,newColor):self.color = newColorcar1 = BenzCar('白色','24503425527866')       
car1.changeColor('黑色')print (car1.color)

調用 changeColor方法的時候,只需要傳入參數 newColor 對應新的顏色即可.

不需要我們傳入self參數,self 參數是實例對象本身,解釋器會自動幫我們傳入.

注意: 如果你的實例屬性名稱 和 靜態屬性(類屬性) 重復了 ,通過類實例訪問該屬性,訪問的是實例屬性通過類名訪問該屬性,訪問的是類屬性.

比如:

class Car:brand = '奔馳'name = 'Car'def __init__(self):# 可以通過實例訪問到類屬性print(self.brand)# 定義實例屬性和類屬性重名self.name = 'benz car'c1 = Car()print(f'通過實例名訪問name:{c1.name}')
print(f'通過類名  訪問name:{Car.name}')

一旦創建了 和類屬性同名的 實例屬性,通過實例訪問的就是實例屬性了

實例方法是指定義在類中的方法, 它可以訪問和操作對象的實例屬性, 并且在調用時會自動傳入對象自身(通常用 self 來表示)作為第一個參數.

實例方法是與類的實例(對象)關聯的, 并且可以訪問和修改對象的狀態.

使用實例方法時, 需要先創建類的實例(對象), 然后通過對象調用方法, 在調用實例方法時, 不需要手動傳入 self 參數, Python會自動將對象本身傳遞給方法.

關于self
  1. 在實例方法中, 第一個參數通常是 self, 表示對象自身. 定義實例方法時, 必須將 self 作為方法的第一個參數.通過 self, 方法可以訪問對象的屬性和其他方法.
  2. 在創建類的實例(對象)時, Python會自動傳遞 self 參數給實例方法, 不需要手動傳入.當調用對象的方法時, 無需顯式傳遞 self, Python會自動將對象本身傳遞給方法.
  3. 在實例方法內部, 可以通過 self 來訪問對象的屬性和方法.例如, self.attribute 可以訪問對象的屬性, self.method() 可以調用對象的其他方法

4. 對象的初始化

__init__ 是Python中一個特殊的方法, 用于初始化對象的屬性.它是在創建對象時自動調用的構造方法, 也叫做魔法方法.

在類的定義中, __init__ 方法用于初始化對象的屬性.通常, 在創建對象時需要對對象的屬性進行初始化操作, 比如設置默認值或接收外部傳入的參數.

__init__ 方法的命名是固定的, 必須使用雙下劃線 __ 前綴和后綴.在調用類創建對象時, Python會自動調用類的 __init__ 方法來初始化對象的屬性.

注意: __init__方法只能返回None, 不能有其他返回值.

實例屬性

實例屬性是指定義在類的實例(對象)中的屬性, 每個對象都有自己獨立的實例屬性.實例屬性用于存儲對象的狀態和數據, 并且在類的實例化過程中被賦予特定的值.

在Python中, 實例屬性通常是在類的構造方法 __init__ 中使用 self 關鍵字定義的.(類的實例屬性在類外(或者說是__init__方法外定義的實例屬性)也有定義的情況)

每個實例屬性都是一個對象獨有的變量, 不同的對象之間互不干擾.

class Student:def __init__(self, name, age):self.name = nameself.age = agedef introduce(self):print(f"大家好, 我的名字叫{self.name}, 今年{self.age}歲")self.study_course('英語')def study_course(self, course):print(f"{self.name}正在努力學習{course}")stu1 = Student("李四", 18)
stu1.introduce()
stu1.study_course("english")stu2 = Student("張三", 20)
stu2.introduce()
stu2.study_course("maths")

實例屬性和類屬性總結

  1. 定義位置:

    • 實例屬性:實例屬性是定義在類的方法中(通常是在構造函數 __init__ 中)通過 self 關鍵字定義的, 每個實例(對象)都有自己的一份實例屬性.
    • 類屬性:類屬性是定義在類的方法之外的屬性, 直接在類的內部定義的, 屬于整個類, 所有實例共享同一份類屬性.
  2. 存儲位置:

    • 實例屬性:每個實例(對象)都有自己獨立的實例屬性, 存儲在對象中.

    • 類屬性:類屬性屬于整個類, 存儲在類中.

  3. 值的獨立性:

    • 實例屬性:不同實例的同名實例屬性是相互獨立的, 一個實例的實例屬性修改不會影響其他實例.
    • 類屬性:所有實例共享同一份類屬性, 但是通過一個實例修改類屬性時, 這個修改不會影響其他實例的類屬性.類屬性是屬于類的, 而不是屬于實例的, 因此每個實例都擁有獨立的類屬性副本, 互不影響.
  4. 訪問方式:

    • 實例屬性:通過對象訪問, 使用表達式 對象名.屬性名.

    • 類屬性:可以通過類名訪問, 也可以通過對象訪問.使用表達式 類名.屬性名對象名.屬性名.

5. __str__

__str__是Python中的特殊方法(魔法方法), 用于定義類的實例對象的字符串表示.

當我們使用print函數或str()函數打印一個類的實例對象時, 實際上是調用了該對象的__str__方法來獲取其字符串表示.

如果在類中定義了__str__方法, 那么當我們打印該類的實例時, 會輸出__str__方法返回的字符串.這對于自定義類的字符串表示非常有用, 可以讓我們以更加直觀和可讀的方式展示對象的內容.

主要用途包括:

  1. 打印:當你使用print函數打印一個對象時, 實際上是調用該對象的__str__方法來獲取其字符串表示, 從而以更直觀和易讀的方式顯示對象的信息.
  2. 字符串轉換:當你使用str()函數來將一個對象轉換為字符串時, 同樣會調用該對象的__str__方法, 以獲得其字符串表示.
  3. 字符串格式化:在字符串格式化時, 如果包含了對象, Python會自動調用對象的__str__方法, 以便獲取對象的字符串表示.
class Student:# 類屬性gender = '男'def __init__(self, name, age):# 實例屬性self.name = nameself.age = agedef introduce(self):print(f"大家好, 我的名字叫{self.name}, 今年{self.age}歲")self.study_course()def study_course(self, course="英語"):print(f"我正在努力學習{course}")def __str__(self):return f"學生: {self.name}, {self.age}, {self.gender}"# 1. 打印
stu = Student("李四", 18)
print(stu)
# 2. 字符串轉換
stu_string1 = str(stu)
print(stu_string1)
# 3. 字符串格式化
stu_string2 = f'{stu}'
print(stu_string2)# 輸出結果:
學生: 李四, 18, 男
學生: 李四, 18, 男
學生: 李四, 18,

6. 類之間的關系

繼承關系

真實世界中,類型之間 可能存在 范圍 包含關系.

比如:人 這個類型 和 亞洲人 這個類型.

人 是包括了 亞洲人 的。 如果 某人 是一個 亞洲人,那么它必定是一個 人.

這種關系,編程語言中稱之為 繼承關系.

比如上面的例子, 亞洲人 這個類 就 繼承 了 人 這個類.

通常我們把被繼承的類稱之為 父類 或者叫 基類.

把繼承類稱之為 子類 或者 派生類.

同樣的,以車為例, 上面我們定義了奔馳車 這個類, 我們還可以定義兩個 子類: 奔馳2016 和 奔馳2018 對應兩種不同款的奔馳車.

如下所示:

class BenzCar:    brand   = '奔馳'  country = '德國'  @staticmethoddef pressHorn(): print('嘟嘟~~~~~~')def __init__(self,color,engineSN):self.color  =  color  # 顏色self.engineSN = engineSN # 發動機編號def changeColor(self,newColor):self.color = newColorclass Benz2016(BenzCar):price   = 580000model   = 'Benz2016'   class Benz2018(BenzCar):price   = 880000model   = 'Benz2018'

大家可以發現定義子類的時候,必須指定它的父類是什么.

指定的方法就是在類名的后面的括號里寫上父類的名字.

大家注意: 子類會自動擁有父類的一切屬性和方法

為什么? 因為一個子類的實例對象 ,必定也是一個父類的實例對象. 當然需要擁有父類的一切屬性和方法.

就像 一個亞洲人 當然 擁有一個 人 所應該具有的一切特性.

比如,執行下面的代碼:

car1 = Benz2016('red','234234545622')    
car2 = Benz2018('blue','111135545988')   print (car1.brand)
print (car1.country)
car1.changeColor('black')print (car2.brand)
print (car2.country)
car2.pressHorn()

輸出結果如下:

奔馳
德國
奔馳
德國
嘟嘟~~~~~~

一個子類在繼承父類的一切特性的基礎上,可以有自己的屬性和方法.
比如:

class Benz2018(BenzCar):price   = 880000model   = 'Benz2018'     def __init__(self,color,engineSN,weight):# 先調用父類的初始化方法BenzCar.__init__(self,color,engineSN)self.weight = weight # 車的重量self.oilweight = 0  # 油的重量# 加油def fillOil(self, oilAdded):self.oilweight +=  oilAdded self.weight    +=  oilAdded

這里 子類 Benz2018 ,新增了兩個 類屬性

價格: price 
型號: model

新增了兩個實例屬性

整車重量:weight 
油的重量:oilweight

新增了一個實例方法 fillOil , 對應 加油這個行為.

這個行為會導致 實例屬性 weight 和 oilweight 變化,所以必須是 實例方法.

這樣定義好了以后, 就可以創建該類的實例,并訪問其新的方法和屬性了.

car2 = Benz2018('blue','111135545988',1500)   
print (car2.oilweight)
print (car2.weight)
car2.fillOil(50) 
print (car2.oilweight)
print (car2.weight)

要特別注意的是, 子類的初始化方法里面,如果有一部分的初始化代碼和父類的初始化相同(通常都是這樣),需要顯式的 調用父類的初始化方法 __init__

而且要傳入相應的參數, 像上面那樣,然后可以加上自己的特有的初始化代碼. 如下所示:

def __init__(self,color,engineSN,weight):# 先調用父類的初始化方法BenzCar.__init__(self,color,engineSN)self.weight = weight self.oilweight = 0

如果子類 沒有 自己的初始化方法,實例化子類對象時,解釋器會自動調用父類初始化方法,如下:

class Rect:def __init__(self):print('初始化 rect')class Squre(Rect):passs = Squre()

運行結果,會打印出 ‘初始化 rect’

但是,如果子類 有自己 的初始化方法,實例化子類對象時,解釋器就不會自動化調用父類的初始化方法,如下

class Rect:def __init__(self):print('初始化 rect')class Square(Rect):def __init__(self):print('初始化 square')s = Squre()

運行結果只會打印 初始化 square.

調用父類的方法,除了直接用父類的名字 BenzCar, 還可以使用 函數 super()

像這樣:

def __init__(self,color,engineSN,weight):# 同樣是調用父類的初始化方法super().__init__(color, engineSN)self.weight = weight self.oilweight = 0

這樣使用的時候,方法參數中 不需要加上 self 參數.

使用 super 的好處之一就是:子類中調用父類的方法,不需要 顯式指定 父類的名字. 代碼的可維護性更好.

想象一下,如果 BenzCar 有很多子類,如果哪一天 BenzCar 類改了名字,采用 super 這樣的寫法,就不需要修改子類的代碼了.

注意 super不僅僅可以調用父類的初始化方法,也可以調用父類的其他方法.

一個子類,同時還可以是另一個類的父類,

比如 亞洲人 可以是 人 的子類, 同時可以是 中國人 的父類.

因為一個中國人,一定是一個亞洲人, 當然也一定是一個 人.

同樣的,上面的車的例子, 我們還可以定義 奔馳2018混合動力 作為 奔馳2018 的 子類.

定義的語法還是一樣的:

class Benz2018Hybrid(Benz2018):model = 'Benz2018Hybrid' price = 980000def __init__(self,color,engineSN,weight):Benz2018.__init__(self,color,engineSN,weight)

同樣,類 Benz2018Hybrid 也會擁有其父類 Benz2018 的一切屬性和方法,自然也包括 父類的父類 BenzCar 的一切屬性和方法

car2 = Benz2018Hybrid('blue','111135545988',1500)   
print (car2.oilweight)
print (car2.weight)
car2.fillOil(50) 
print (car2.oilweight)
print (car2.weight)
組合關系

除了上面的繼承關系, 類之間還有一種常見的組合關系.

所謂組合關系,就是一個類實例的屬性里面包含另外一個類實例.

比如:

class BenzCar:    brand   = '奔馳'  country = '德國'  def __init__(self,color,engineSN):self.color  =  color     # 顏色self.engineSN = engineSN # 發動機編號

這樣的定義,類 BenzCar 中

brand 屬性就是一個字符串對象 奔馳

country 屬性就是一個字符串對象 德國

而該類的實例對象中,就包含了 兩個屬性 color 和 engineSN, 都是字符串對象

我們可以說 該類由 一些字符串對象 組合 而成.

甚至還可以包含 我們自己定義的類的實例,比如:

# 輪胎
class Tire:    def __init__(self,size,createDate):self.size  =  size  # 尺寸self.createDate = createDate # 出廠日期class BenzCar:    brand   = '奔馳'  country = '德國'  def __init__(self,color,engineSN,tires):self.color  =  color  # 顏色self.engineSN = engineSN # 發動機編號self.tires   =  tires# 創建4個輪胎實例對象
tires = [Tire(20,'20160808')  for i in range(4)]
car = BenzCar('red','234342342342566',tires)

上面的例子里,奔馳汽車對象就 包含 了4個輪胎 Tire 對象.

我們可以說奔馳汽車對象是由 4個輪胎對象 組合 而成,形成了對象的組合關系.

對象的 屬性 變量 保存了 組合它的那些對象.

組合關系,可以通過上層對象的屬性一步的訪問到內部對象的屬性

比如,我們可以通過 BenzCar 對象 訪問其內部的輪胎對象

print(car.tires[0].size)

Python解釋器對這個表達式 car.tires[0].size 是從左到右依次執行的,如下所示:

car.tires   # BenzCar實例的tires屬性,得到一個列表,里面是四個 Tire 實例對象car.tires[0]   # 得到BenzCar實例的tires屬性列表里面的第1個Tire 實例對象car.tires[0].size  # 得到BenzCar實例的tires屬性列表里面的第1個Tire 實例對象的size屬性

7. 補充練習

"""
創建一個簡單的學生管理系統,包含以下功能:定義一個Student類,包含以下屬性:學號(number),姓名(name),年齡(age),性別(gender)和成績(score)。實現類的初始化方法__init__,用于初始化學生的屬性。實現類的__str__方法,用于返回學生信息的字符串表示,格式為:學號:[學號],姓名:[姓名],年齡:[年齡],性別:[性別],成績:[成績]。定義一個學生管理類StudentManager,用于管理學生信息。該類應該包含以下功能:添加學生:能夠添加一個學生的信息到學生列表中。
顯示所有學生:能夠打印出所有學生的信息。
因為之前我們已經做過了類似的管理系統, 所以這里就不再做很復雜的功能, 只做兩個小功能達到練習的目的即可.
"""# 學生類
class Student:def __init__(self, number, name, age, gender, score):self.number = numberself.name = nameself.age = ageself.gender = genderself.score = scoredef __str__(self):return f"學號:[{self.number}],姓名:[{self.name}],年齡:[{self.age}],性別:[{self.gender}],成績:[{self.score}]"# 學生管理類
class StudentManager:def __init__(self):self.stu_list = []def add_stu(self, student):self.stu_list.append(student)print(f'添加學生{student.name}成功')def show_all_stu(self):for stu in self.stu_list:print(stu)def main():# 主流程student_manager = StudentManager()print('歡迎進入學生管理系統')while True:print('1: 添加學生')print('2: 展示所有學生')print('0: 退出系統')choice = int(input("請輸入操作編號: "))if choice == 1:number = input('請輸入學生學號')name = input('請輸入學生姓名')age = input('請輸入學生年齡')gender = input('請輸入學生性別')score = input('請輸入學生分數')student = Student(number, name, age, gender, score)student_manager.add_stu(student)elif choice == 2:student_manager.show_all_stu()elif choice == 0:print(f"退出學生管理系統")breakelse:print('您輸入的指令是無效指令')if __name__ == '__main__':main()
遇見安然遇見你,不負代碼不負卿。
謝謝老鐵的時間,咱們下篇再見~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/76242.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/76242.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/76242.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring Boot中常用內嵌數據庫(H2、HSQLDB、Derby)的對比,包含配置示例和關鍵差異總結

以下是Spring Boot中常用內嵌數據庫的對比&#xff0c;包含配置示例和關鍵差異總結&#xff1a; 一、主流內嵌數據庫對比 1. H2 數據庫 特點&#xff1a; 支持內存模式&#xff08;速度快&#xff09;和文件模式&#xff08;數據持久化&#xff09;。支持SQL方言&#xff08…

Apache Hive和Snowflake的`CREATE VIEW`語法和功能特性整理的對比表

寫一個Apache Hive中CREATE VIEW語句轉換為對應Snowflake中CREATE VIEW語句的程序&#xff0c;現在需要一個根據功能的相似性對應的Apache HiveQL和Snowflake SQL的CREATE VIEW語句的表。 以下是基于Apache Hive的CREATE VIEW語法規則構造的所有可能合法語句實例及其功能說明&…

個人博客網站從搭建到上線教程

步驟1:設計個人網站 設計個人博客網站的風格樣式,可以在各個模板網站上多瀏覽瀏覽,以便有更多設計網站風格樣式的經驗。 設計個人博客網站的內容,你希望你的網站包含哪些內容如你的個人基本信息介紹、你想分享的項目、你想分享的技術文檔等等。 步驟2:選擇開發技術棧 因…

PHP回調后門

1.系統命令執行 直接windows或liunx命令 各個程序 相應的函數 來實現 system exec shell_Exec passshru 2.執行代碼 eval assert php代碼 系統 <?php eval($_POST) <?php assert($_POST) 簡單的測試 回調后門函數call_user_func(1,2) 1是回調的函數 2是回調…

Raspberry 樹莓派 CM4模塊的底板設計注意事項

1&#xff0c; 樹莓派CM4底板設計 樹莓派CM4模塊集成了CPU&#xff0c; 存儲器&#xff0c;以太網&#xff0c; 無線模塊&#xff0c;電源等等&#xff0c; 大大降低了硬件設計的要求。對我們使用樹莓派提供了很好的便利性。 本人近期因為項目的需要設計了一款CM4的底板&#x…

Java后端開發(十八)-- 使用JAXB,將JavaBean轉換XML文本

下面是測試時的運行環境: 1.jdk8 2.Maven,可能需要需要的依賴,如下: <dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.1</version></dependency><dependency><gr…

【一起來學kubernetes】30、k8s的java sdk怎么用

Kubernetes Java SDK 是開發者在 Java 應用中與 Kubernetes 集群交互的核心工具&#xff0c;支持資源管理、服務發現、配置操作等功能。 一、主流 Java SDK 對比與選擇 官方 client-java 庫 特點&#xff1a;由 Kubernetes 社區維護&#xff0c;API 與 Kubernetes 原生對象嚴格…

PHP開發者2025生存指南

PHP&#xff0c;這個曾經被戲稱為“世界上最好的語言”的腳本語言&#xff0c;依舊在網絡世界占據著重要的地位。然而&#xff0c;技術發展日新月異&#xff0c;面向2025年&#xff0c;PHP開發者要想保持競爭力甚至實現職業生涯的飛躍&#xff0c;需要不斷學習和提升自身技能。…

MySQL與Redis數據一致性保障方案詳解

前言 在現代分布式系統中&#xff0c;MySQL和Redis的結合使用非常普遍。MySQL作為關系型數據庫負責持久化存儲&#xff0c;而Redis則作為高性能緩存層提升系統的響應速度。然而&#xff0c;在這種架構下&#xff0c;如何保證MySQL與Redis之間的數據一致性是一個重要的挑戰。本…

MySQL響應慢是否由堵塞或死鎖引起?

目錄標題 **1. 檢查當前運行的查詢和進程****2. 查看死鎖日志****方法一&#xff1a;通過錯誤日志****方法二&#xff1a;通過InnoDB狀態** **3. 檢查鎖信息****查看表鎖****查看行鎖&#xff08;InnoDB&#xff09;** **4. 分析慢查詢****開啟慢查詢日志****分析慢查詢** **5.…

【計算機網絡】記錄一次校園網無法上網的解決方法

問題現象 環境&#xff1a;實訓室教室內時間&#xff1a;近期突然出現 &#xff08;推測是學校在施工&#xff0c;部分設備可能出現問題&#xff09;癥狀&#xff1a; 連接校園網 SWXY-WIFI 后&#xff1a; 連接速度極慢偶發無 IP 分配&#xff08;DHCP 失敗&#xff09;即使分…

JavaScript函數式編程思想

1. 相關面試題 1.1. 什么是純函數&#xff1f; 純函數是一種函數&#xff0c;其返回值僅由其輸入參數決定&#xff0c;不產生任何可觀察的副作用&#xff0c;如修改全局對象或外部狀態。 純函數具有以下特性&#xff1a; 1. 確定性&#xff1a;相同的輸入永遠得到相同的輸…

Elasticsearch安全與權限控制指南

在Elasticsearch維護中&#xff0c;安全管理是保障數據合規性和集群穩定性的關鍵。本文將詳細介紹用戶與角色管理、索引/字段級權限控制、HTTPS加密通信、審計日志與合規性檢查等核心安全實踐&#xff0c;希望可以幫助你構建更安全的Elasticsearch環境。 1 用戶與角色管理 1.1…

『VUE』快速入門配置環境使用tailwind css 記憶tailwind css常見規則 (詳細圖文注釋)

目錄 效果預覽快速入門環境配置配置 tailwind.config.js 設置文件添加 Tailwind 的基礎樣式引入樣式到項目檢查構建工具配置測試 Tailwind CSS 效果 使用插件tailwind.config.js的最終內容app.vue演示 為什么不需要記憶 Tailwind 的類名&#xff1f;1. 類名直觀2. 文檔全面3. 工…

StdioIterator

參考這種用法&#xff1a; int a[3]{1,2,3}; copy(a,a3,ostream_iterator<int>(cout," ")); 以及 ostream_iterator 類 | Microsoft Learn 中的函數簽名&#xff0c;可以編寫出 StdioIterator&#xff0c;同樣支持 copy 函數的調用。 #include <stdio.h&…

制作service列表并打印出來

制作service列表并打印出來 在Linux中&#xff0c;服務&#xff08;Service&#xff09;是指常駐在內存中的進程&#xff0c;這些進程通常監聽某個端口&#xff0c;等待其他程序的請求。服務也被稱為守護進程&#xff08;Daemon&#xff09;&#xff0c;它們提供了系統所需的各…

CKS認證 | Day3 K8s容器運行環境安全加固

一、最小特權原則&#xff08;POLP&#xff09; 1&#xff09;最小特權原則 (Principle of least privilege&#xff0c;POLP) &#xff1a; 是一種信息安全概念&#xff0c;即為用戶提供執行其工作職責所需的最 小權限等級或許可。 最小特權原則被廣泛認為是網絡安全的最佳實…

Linux wifi 驅動移植適配流程詳解

基礎內容概要 將tplink wn725n 無線網卡驅動移植到ubuntu將tplink wn725n 無線網卡驅動移植到Linux開發板&#xff08;交叉編譯&#xff09;將tplink wn725n 無線網卡驅動移植到Linux開發板&#xff0c;在開發板中編譯 為什么還要包涵交叉編譯&#xff1f; 目標設備是ARM架構…

Day14 動態規劃(3)

一.746. 使用最小花費爬樓梯 FS記憶化搜索優化: const int N 1010;class Solution { public:int mem[N];int dfs(vector<int>& cost, int x){if(mem[x]) return mem[x];int sum 0;if(x 0 || x 1) return 0;else{sum min(dfs(cost, x - 1) cost[x - 1], dfs(c…

解鎖AI潛能:模型上下文協議(MCP)的革新與應用

解鎖AI潛能:模型上下文協議(MCP)的革新與應用 在人工智能發展的當下,大語言模型(LLM)正逐步滲透到各個領域。從智能客服快速響應客戶咨詢,到智能編程助手協助開發者高效編寫代碼,LLM展現出強大的能力。然而,隨著應用的深入會面臨一個問題:模型與數據之間的連接困境。…