由于Python是動(dòng)態(tài)語言,根據(jù)類創(chuàng)建的實(shí)例可以任意綁定屬性竹握。
給實(shí)例綁定屬性的方法是通過實(shí)例變量,或者通過self變量:
class Student(object):
def __init__(self, name):
self.name = name
s = Student('Bob')
s.score = 90
但是,如果Student類本身需要綁定一個(gè)屬性呢克蚂?可以直接在class中定義屬性,這種屬性是類屬性,歸Student類所有:
class Student(object):
name = 'Student'
當(dāng)我們定義了一個(gè)類屬性后,這個(gè)屬性雖然歸類所有急前,但類的所有實(shí)例都可以訪問到。來測(cè)試一下:
>>> class Student(object):
... name = 'Student'
...
>>> s = Student() # 創(chuàng)建實(shí)例s
>>> print(s.name) # 打印name屬性瀑构,因?yàn)閷?shí)例并沒有name屬性裆针,所以會(huì)繼續(xù)查找class的name屬性
Student
>>> print(Student.name) # 打印類的name屬性
Student
>>> s.name = 'Michael' # 給實(shí)例綁定name屬性
>>> print(s.name) # 由于實(shí)例屬性優(yōu)先級(jí)比類屬性高,因此寺晌,它會(huì)屏蔽掉類的name屬性
Michael
>>> print(Student.name) # 但是類屬性并未消失世吨,用Student.name仍然可以訪問
Student
>>> del s.name # 如果刪除實(shí)例的name屬性
>>> print(s.name) # 再次調(diào)用s.name,由于實(shí)例的name屬性沒有找到呻征,類的name屬性就顯示出來了
Student
從上面的例子可以看出耘婚,在編寫程序的時(shí)候,千萬不要把實(shí)例屬性和類屬性使用相同的名字陆赋,因?yàn)橄嗤Q的實(shí)例屬性將屏蔽掉類屬性沐祷,但是當(dāng)你刪除實(shí)例屬性后,再使用相同的名稱攒岛,訪問到的將是類屬性赖临。
第一,slots只能限制添加屬性阵子,不能限制通過添加方法來添加屬性:
def set_city(self, city):
self.city=city
class Student(object):
slots = ('name', 'age', 'set_city')
pass
Student.set_city = MethodType(set_city, Student)
a = Student()
a.set_city(Beijing)
a.city
上段代碼中思杯,Student類限制兩個(gè)屬性name 和 age,但可以通過添加方法添加一個(gè)city屬性(甚至可以添加很多屬性挠进,只要set_city方法里有包括)
第二色乾,屬性分實(shí)例屬性和類屬性,多個(gè)實(shí)例同時(shí)更改類屬性领突,值是最后更改的一個(gè)
def set_age(self,age):
self.age=age
class Stu(object):
pass
s=Stu()
a=Stu()
from types import MethodType
Stu.set_age=MethodType(set_age,Stu)
a.set_age(15) \通過set_age方法暖璧,設(shè)置的類屬性age的值
s.set_age(11) \也是設(shè)置類屬性age的值,并把上個(gè)值覆蓋掉
print(s.age,a.age) \由于a和s自身沒有age屬性君旦,所以打印的是類屬性age的值
a.age = 10 \給實(shí)例a添加一個(gè)屬性age并賦值為10
s.age = 20 \給實(shí)例b添加一個(gè)屬性age并賦值為20
\這兩個(gè)分別是實(shí)例a和s自身的屬性澎办,僅僅是與類屬性age同名,并沒有任何關(guān)系
print(s.age,a.age) \打印的是a和s自身的age屬性值金砍,不是類age屬性值
所以局蚀,
1,slots并不能嚴(yán)格限制屬性的添加恕稠,可通過在方法里定義限制之外的屬性來添加本不能添加的屬性(當(dāng)然琅绅,前提是方法沒有被限制)
2,類屬性是公共屬性鹅巍,所有實(shí)例都可以引用的千扶,前提是實(shí)例自身沒有同名的屬性,因此類屬性不能隨意更改(別的實(shí)例可能在引用類屬性的值)骆捧,就是說不能隨便用a.set_age()更改age的值(因?yàn)檎{(diào)用此方法更改的是類屬性age的值澎羞,不是實(shí)例a自身的age屬性值)