Python - 類中的對象與屬性

本文整理類中對象與屬性(變量)相關知識。

類對象與實例對象

建立測試類:

class Test:
    var_of_class = 'Class Var'
    def __init__(self):
        self.var_of_instance = 'Instance Var'

類對象

建立類進行編譯後則形成了類對象,類對象僅支持兩個操作:

  • 實例化:使用instance_name = class_name()的方式實例化,實例化操作創建該類的實例。
  • 屬性引用:使用class_name.attr_name的方式引用類屬性。

實例對象

類對象實例化得到實例對象,實例對象僅支持一個操作:

  • 屬性引用;與類對象屬性引用的方式相同,使用instance_name.attr_name的方式
# 類對象
print(Test)

# 實例對象
class_instance = Test()

>>>
<class '__main__.Test'>
<__main__.Test object at 0x00000127715B4128>

類變量與實例變量

建立測試類:

class Test:
    var_of_class = 'Class Var'
    def __init__(self):
        self.var_of_instance = 'Instance Var'

類變量

可由類對象引用

由所有實例共享

# 類對象引用類變量
print(f'類對象引用類變量 :{Test.var_of_class}')
class_instance_1 = Test()
class_instance_2 = Test()
# 實例對象引用類變量
print(f'實例對象1引用類變量 :{class_instance_1.var_of_class}')
print(f'實例對象2引用類變量 :{class_instance_2.var_of_class}')
# 修改類變量實例對象共享修改
Test.var_of_class = 'Changed Class Var'
print(f'實例對象1引用類變量 :{class_instance_1.var_of_class}')
print(f'實例對象2引用類變量 :{class_instance_2.var_of_class}')

>>>
類對象引用類變量 :Class Var
實例對象1引用類變量 :Class Var
實例對象2引用類變量 :Class Var
實例對象1引用類變量 :Changed Class Var
實例對象2引用類變量 :Changed Class Var

實例變量

由實例對象引用

僅在當前實例保存

# 實例變量
class_instance_1 = Test()
class_instance_2 = Test()

print(f'實例對象1實例變量 :{class_instance_1.var_of_instance}')
print(f'實例對象2實例變量 :{class_instance_2.var_of_instance}')
class_instance_1.var_of_instance = 'changed instance var'

print(f'修改實例對象1後實例對象1實例變量 :{class_instance_1.var_of_instance}')
print(f'修改實例對象1後實例對象2實例變量 :{class_instance_2.var_of_instance}')

>>>
實例對象1實例變量 :Instance Var
實例對象2實例變量 :Instance Var
修改實例對象1後實例對象1實例變量 :changed instance var
修改實例對象1後實例對象2實例變量 :Instance Var

類對象不能引用實例變量:

# 類對象不能引用實例變量
print(Test.var_of_instance)
>>> 報錯!
type object 'Test' has no attribute 'var_of_instance'

屬性綁定

建立測試類:

class Test():
    var_of_class = 'Class Var'
    def __init__(self):
        self.var_of_instance = 'Instance Var'

在定義、使用類、實例對象屬性過程中,其實涉及兩個過程:

  • 類屬性綁定
  • 實例屬性綁定

使用綁定一詞事實上更加確切,可以理解爲屬性並不是屬於類或實例的,Python中一切皆對象,每個屬性也都是一個個現貨鮮活的對象,之所以這些對象被稱之爲、用作於屬性,是因爲我們將這部分對象綁在了類對象可使用的屬性名稱上;

換一種說法,對象就是對象,而世上本沒有屬性,當對象被綁定在類/實例上,對象也就成了類/實例的屬性

因此綁定屬性,首先需要有一個對象纔行。

類屬性綁定

Python作爲動態語言,類對象和實例對象都可以在運行時綁定任意屬性,因此類屬性綁定有兩種時機:

  • 編譯類時(寫在類中的類屬性)
  • 運行時
# 定義時綁定類屬性
print(f'定義時綁定類屬性:{Test.var_of_class}')
# 運行時綁定類屬性
Test.var_of_class_defined_during_running = 'a long var of class'
print(f'運行時綁定類屬性:{Test.var_of_class_defined_during_running}')

>>>
定義時綁定類屬性:Changed Class Var
運行時綁定類屬性:a long var of class

實例屬性綁定

實例屬性綁定也發生在兩個時機:

  • 實例生成時
  • 運行時
class_instance = Test()
# 實例生成時綁定的實例屬性
print(f'實例生成時綁定的實例屬性:{class_instance.var_of_instance}')
# 實例運行時綁定的實例屬性
class_instance.var_of_instance = 'defined during running'
print(f'實例運行時綁定的實例屬性{class_instance.var_of_instance}')

>>>
實例生成時綁定的實例屬性:Instance Var
實例運行時綁定的實例屬性: defined during running

屬性引用

上文中對屬性的使用事實上都是在引用類對象或實例對象中的屬性。

需要特別說明的是實例對象的屬性引用衝突的問題,當類中存在同名的實例屬性與類屬性時:

  • 由於類對象無法訪問實例屬性,因此對類對象的屬性引用沒有影響
  • 實例屬性有權訪問二者,實現上會優先引用實例級的屬性,即同名的類屬性會被覆蓋
class_instance = Test()
class_instance.var_of_class = 'instance var with a same name of a class var'
print(f'類對象引用衝突屬性:{Test.var_of_class}')
print(f'實例對象引用衝突屬性:{class_instance.var_of_class}')

>>>
類對象引用衝突屬性:Changed Class Var
實例對象引用衝突屬性:instance var with a same name of a class var

獲取源碼

文中測試環境與所有源碼可在Github下載。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章