什么是對象和類
https://www.cnblogs.com/poloyy/p/15178423.html
什么是 Python 類、類對象、實例對象
https://www.cnblogs.com/poloyy/p/15178456.html
類變量、實例變量/類屬性、實例屬性
前言
只是叫法不一樣
實例屬性 = 實例變量
類屬性 = 類變量
個人認為叫屬性更恰當
類屬性和實例屬性區別
- 類屬性,所有實例對象共享該屬性
- 實例屬性,屬於某一個實例對象的屬性,用於描述具體的對象
從實際栗子了解類屬性、實例屬性
有一個表格,四個常見的明星
姓名 | 年齡 |
---|---|
周潤發 | 58 |
成龍 | 55 |
劉德華 | 53 |
周星馳 | 54 |
總結一下
- 四個人歸類為明星
- 每個明星都有兩個屬性:姓名、年齡
- 明星這個群體具有一個屬性:明星數量,在這張表是 4
- 姓名和年齡等屬性是用來描述具體的一個對象
- 明星的數量是用於描述明星這個類別的
使用面向對象編程思想來總結的話
- 周潤發、成龍、劉德華、周星馳都是實例對象
- 他們都屬於明星,明星是類
- 屬於實例對象的屬性有:姓名、年齡,所以也叫實例屬性
- 屬於明星類的屬性有:數量,所以也叫類屬性
類里面的三種類型變量
- 在所有方法之外定義的變量,稱為類屬性/類變量
- 在方法內部,通過 self.變量名 方式定義的變量,稱為實例屬性/實例變量
- 在方法內部,通過 變量名=變量值 方式定義的變量,稱為局部變量
類屬性
類屬性在類中的定義
class 類名: 類屬性1 = 值 類屬性2 = 值 def func(self): ...
類屬性、類方法注意點
- 無論是類屬性還是類方法,都無法像普通變量或者函數那樣,在類的外部直接使用它們(類方法后面詳解)
- 可以將類看做一個獨立的空間,類屬性其實也是在類體中定義的變量,類方法是在類體中定義的函數
- 需要通過類對象/實例對象來調用類屬性 ClassName.classProperty (類方法后面詳解)
類屬性的栗子
# 類屬性 class PoloBlog: # 這就是在所有方法之外 下面定義了 2 個類變量 name = "小菠蘿測試筆記" blog = "https://www.cnblogs.com/poloyy/" # 通過類名調用類屬性 print(PoloBlog.name) print(PoloBlog.blog) # 輸出結果 小菠蘿測試筆記 https://www.cnblogs.com/poloyy/
通過 Pycharm 的代碼聯想,可以看到 blog、name、__doc__ 三個類屬性
類屬性的調用方式
有兩種
- 直接通過類名調用
- 也可以通過類的實例對象調用
調用類屬性的栗子
# 調用類屬性的兩種方式 class PoloBlog: # 這就是在所有方法之外 下面定義了 2 個類變量 name = "小菠蘿測試筆記" blog = "https://www.cnblogs.com/poloyy/" # 通過類名直接調用 print(PoloBlog.name) print(PoloBlog.blog) # 修改類屬性 PoloBlog.name = "blogyuan" PoloBlog.blog = "https://www.cnblogs.com/" # 通過實例對象調用修改后的類屬性 poloBlog = PoloBlog() print(poloBlog.name) print(poloBlog.blog) # 輸出結果 小菠蘿測試筆記 https://www.cnblogs.com/poloyy/ blogyuan https://www.cnblogs.com/
通過類名修改類屬性的值,會影響所有的實例化對象
實例對象修改類屬性
# 修改類屬性 poloBlog.name = "小菠蘿回來了" # 再看看類對象調用修改后的類屬性 print(PoloBlog.name) print(poloBlog.name) # 輸出結果 blogyuan 小菠蘿回來了
- 會發現,類名.name 仍然返回之前的值,而 實例對象.name 會返回修改的值
- 原因: 實例對象.name 本質上並不是修改類屬性的值,而是在定義一個新的實例屬性(下面詳解)
動態添加類屬性
PoloBlog.age = 24 print(PoloBlog.age) print(poloBlog.age) # 輸出結果 24 24
- age 沒有在類體中定義
- 可以直接通過 類名.new_property_name 的方式定義一個新的類屬性
實例屬性
- 屬於具體對象的屬性,用於描述具體的對象
- 只能通過實例對象訪問,無法通過類名訪問
實例屬性的栗子
class PoloBlog: def __init__(self): # 在方法內部,通過 self.name 的方式定義的變量就是實例變量 self.name = "小菠蘿測試筆記" self.add = "https://www.cnblogs.com/poloyy/" # 下面定義了一個 say 實例方法 def say(self): self.age = 13 # 實例化對象 blog = PoloBlog() blog.say() print(blog.name, blog.add, blog.age) # 輸出結果 小菠蘿測試筆記 https://www.cnblogs.com/poloyy/ 13
- 重點:__init__ 會在實例化對象的時候自動調用,因此 blog 創建成功就有 name、add 兩個實例屬性
- 調用 say() 方法之后才有第三個實例屬性 age
修改實例屬性的栗子
blog.name = "小菠蘿" blog.add = "xiaopolo.com" blog.age = 24 print(blog.name, blog.add, blog.age) # 輸出結果 小菠蘿 xiaopolo.com 24
動態添加實例屬性
blog.phone = 13501489999 print(blog.phone) # 輸出結果 13501489999
上面也有說到,通過 實例對象.屬性名 的方式並不會給類變量賦值,而是定義一個新的實例變量
綜合栗子
# 綜合栗子 class PoloBlogObjectTest: # 類變量 sum = 0 # 初始化方法 def __init__(self, name, age): # 實例變量 self.name = name self.age = age # 類變量 PoloBlogObjectTest.sum += 1 # 實例方法 def printNameAge(self): print(self.name, self.age) poloTest1 = PoloBlogObjectTest("小菠蘿一號", 24) poloTest2 = PoloBlogObjectTest("小菠蘿二號", 14) print(PoloBlogObjectTest.sum) # 調用實例方法 poloTest1.printNameAge() poloTest2.printNameAge() # 輸出結果 2 小菠蘿一號 24 小菠蘿二號 14
不推薦實例屬性和類屬性同名
- 類中,實例屬性和類屬性可以同名
- 但這種情況下使用實例對象將無法調用類變量,它會首選實例變量,無論這個變量是否已定義
- 實例獨享綁定新的實例屬性時,會直接覆蓋掉重名的類屬性
實例屬性、類屬性同名栗子
class Person: # 只有一個類變量 name = "cool guy" # 實例化一個對象 p = Person() # 打印實例屬性 name,因為實例對象並沒有name屬性,所以會繼續查找class的name屬性 print(p.name) # 打印類屬性 name print(Person.name) # 給實例綁定 name、age 屬性 p.name = "bad guy" p.age = 12 # 打印 name、age 屬性 print(p.age) # 由於實例屬性優先級比類屬性高,因此,它會屏蔽掉類的 name 屬性 print(p.name) # 仍然打印類的 name 屬性 print(Person.name) # 輸出結果 cool guy cool guy 12 bad guy cool guy
實例對象屬性引用的查找過程