6.3 類屬性和物件屬性
在類定義中,屬性按照歸屬分為物件屬性、類屬性,按照呼叫的私密性分為一般屬性和私有屬性,
6.3.1 類屬性和物件屬性
物件屬性是最常用到的一種屬性,即使我們對上面的類:MyClass1實體化了一個mc的物件,mc物件也不能進行有實質的操作,因為mc物件的類:MyClass1中既沒有定義屬性也沒有定義方法,
在定義類時還能定義類屬性,接下來我們創建一個類:MyClass2,并添加一個類屬性:class_attr和物件屬性:obj_attr,然后再通過該類實體化一個物件mc,再通過不同的方式訪問類屬性和物件屬性,以便掌握類屬性和物件屬性的區別,代碼如下:
class MyClass2:
class_attr = 'ca'
def __init__(self):
self.obj_attr = 'oa'
mc = MyClass2()
print('通過物件訪問類屬性', mc.class_attr)
print('通過物件訪問物件屬性', mc.obj_attr)
print('通過類訪問類屬性', MyClass2.class_attr)
print('通過類訪問物件屬性', MyClass2.obj_attr)
通過物件訪問類屬性 ca
通過物件訪問物件屬性 oa
通過類訪問類屬性 ca
Traceback (most recent call last):
File "E:\BaiduNetdiskWorkspace\FrbPythonFiles\study\面向物件\類的私有屬性.py", line 12, in
print('通過類訪問物件屬性', MyClass2.obj_attr)
AttributeError: type object 'MyClass2' has no attribute 'obj_attr'
代碼解釋:
def __init__(self)::表示創建一個類的建構式,所謂建構式,就是在類的實體化時會自動執行的方法,在Python類定義時,有一些是比較特殊的方法,這種方法的方法名一般以雙__開始和結尾,在Python類中有著特別的意義,基于此,我們一般在類中定義方法時,方法名最好不要以__開始,類一旦進行實體化后,就會執行__init__這個構造方法進行初始化,一般這里會進行屬性的初始化系結和一些其他初始化動作,
mc = MyClass2():對MyClass2類的實體化,實體化后的物件就是mc,接下來就可以通過mc來進行操作了,
self.obj_attr = 'oa':進行物件屬性的值系結,這里的self代表的就是實體化后的物件自己,
class_attr = 'ca':類屬性的賦值,類屬性賦值在類定義后就會生效,不需要實體化成物件,
通過物件名.屬性、類名.屬性就可以獲取到相應的屬性了,
通過上面的代碼可以看到,通過物件是可以正常訪問到物件屬性的,通過類可以訪問到類屬性,但是不能訪問到物件屬性,
物件或類對于屬性的訪問如下:
| 物件或類 | 物件屬性 | 類屬性 |
|---|---|---|
| 物件 | √ | √ |
| 類 | × | √ |
接著我們來看是否能夠對屬性進行修改:
class Person:
age = 18
def __init__(self):
self.name = '張三'
self.gender = '男'
zhangsan = Person()
print('通過物件修改物件一般屬性', '+' * 30)
print(zhangsan.gender)
zhangsan.gender = '女'
print(zhangsan.gender)
print('通過物件修改類一般屬性', '+' * 30)
print(zhangsan.age)
zhangsan.age = 30
print(zhangsan.age)
print(Person.age)
print('通過類修改類一般屬性', '+' * 30)
print(Person.age)
Person.age = 25
print(Person.age)
print(zhangsan.age)
通過物件修改物件一般屬性 ++++++++++++++++++++++++++++++
男
女
通過物件修改類一般屬性 ++++++++++++++++++++++++++++++
18
30
18
通過類修改類一般屬性 ++++++++++++++++++++++++++++++
18
25
30
通過上面的代碼可以看到,無論是物件還是類,對于能夠訪問到的屬性就可以進行修改,
但是物件修改類屬性后,通過類呼叫的屬性不變,而如果是通過類修改類屬性后,物件呼叫的類屬性也不變,也就是說,對于類屬性,物件修改后不會影響到類,類修改后也不會影響到物件,
物件或類對于屬性的修改如下:
| 物件或類 | 物件屬性 | 類屬性 |
|---|---|---|
| 物件 | √ | √ |
| 類 | × | √ |
6.3.2 一般屬性和私有屬性
平常定義類時,直接定義的都是一般屬性,就是可以通過物件名.屬性、類名.屬性直接呼叫到的,如上面例子中的:mc.class_attr和MyClass2.class_attr,
如果有些屬性名開發者不想讓其它開發人員呼叫時,則可以創建以雙__開頭的屬性名,這種屬性名稱為私有屬性,在物件、類進行屬性呼叫時,則不能通過簡單的x.屬性名的方式呼叫物件的屬性,
class Person:
__age = 18
def __init__(self):
self.name = '張三'
self.__gender = '男'
zhangsan = Person()
print(zhangsan.__gender)
在上面的定義中,通過self.__gender定義了一個私有屬性,直接運行上面的命令后會報錯,報錯如下:
Traceback (most recent call last):
File "E:\BaiduNetdiskWorkspace\FrbPythonFiles\study\面向物件\創建類.py", line 17, in
print(zhangsan.__gender)
AttributeError: 'Person' object has no attribute '__gender'
當然,在Python中沒有真正的私有屬性,通過__開頭命名的屬性,在Python類中只是被自動修改了名稱而已,我們可以通過print(dir(zhangsan))查看到zhangsan這個物件中所有的屬性和方法:
['_Person__age', '_Person__gender', 'class', 'delattr', 'dict', 'dir', 'doc', 'eq', 'format', 'ge', 'getattribute', 'gt', 'hash', 'init', 'init_subclass', 'le', 'lt', 'module', 'ne', 'new', 'reduce', 'reduce_ex', 'repr', 'setattr', 'sizeof', 'str', 'subclasshook', 'weakref']
我們看到,輸出的結果中有2個屬性:_Person__age, _Person__gender,這個屬性其實就是之前定義的__age 和__gender,因為是私有屬性,于是Python直接修改了這個屬性的名字,改成了:_類名+私有屬性,于是,其實我們可以通過該屬性名進行呼叫:
>>> print(zhangsan._Person__gender)
>>> print(zhangsan._Person__age)
>>> print(Person._Person__age)
男
18
18
私有屬性的修改
class Person:
__age = 18
def __init__(self):
self.name = '張三'
self.__gender = '男'
zhangsan = Person()
print('通過物件修改物件私有屬性', '+' * 30)
print(zhangsan._Person__gender)
zhangsan._Person__gender = '女'
print(zhangsan._Person__gender)
print('通過物件修改類私有屬性', '+' * 30)
print(zhangsan._Person__age)
zhangsan._Person__age = 30
print(zhangsan._Person__age)
print(Person._Person__age)
print('通過類修改類私有屬性', '+' * 30)
print(Person._Person__age)
Person._Person__age = 25
print(Person._Person__age)
print(zhangsan._Person__age)
通過物件修改物件私有屬性 ++++++++++++++++++++++++++++++
男
女
通過物件修改類私有屬性 ++++++++++++++++++++++++++++++
18
30
18
通過類修改類私有屬性 ++++++++++++++++++++++++++++++
18
25
30
我們可以看到,如同一般的屬性一樣,對于類屬性,物件修改后不會影響到類,類修改后也不會影響到物件,
注意:按照約定俗成的規定,以一個下劃線開頭的實體變數名(例如_age)在外部是可以直接訪問的(弱私有),但是這個形式的變數表達的意思是,“雖然我可以被訪問,但是請把我視為私有變數,不要隨意訪問”,一般地在IDE中也會有所提示:保護成員的訪問類,
6.3.3 類屬性和物件屬性的區別
現在我們來總結一下類屬性和物件屬性的區別,
在定義時,使用關鍵字self來定義物件屬性,而類屬性不需要,只需要在類最內層直接為變數賦值即可,該變數就是類屬性,
在訪問時,可以通過物件.的方式直接訪問到一般物件屬性和一般類屬性,而類.的方式只能訪問到一般類屬性,對于私有屬性無法直接訪問,但是可以通過x._類名+屬性名的方式訪問到,同樣的,不能通過類.的方式訪問到物件的私有屬性,
在修改時,可以訪問就可以修改,只不過對于類屬性,物件修改后不會影響到類,類修改后也不會影響到物件,而物件屬性,只有物件能夠訪問和修改,類則無法訪問,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/544426.html
標籤:其他
上一篇:高并發系統設計之負載均衡
