Python - 面向對象編程 - 類變量、實例變量/類屬性、實例屬性


什么是對象和類

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

 

實例對象屬性引用的查找過程

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM