日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

python属性_深入理解python对象及属性

發(fā)布時(shí)間:2023/12/10 python 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python属性_深入理解python对象及属性 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

類屬性和實(shí)例屬性

首先來(lái)看看類屬性和類實(shí)例的屬性在python中如何存儲(chǔ),通過(guò)__dir__方法來(lái)查看對(duì)象的屬性

>>> class Test(object):

pass

>>> test = Test(http://www.my516.com)

# 查看類屬性

>>> dir(Test)

['__class__','__delattr__','__dict__','__doc__','__format__',

'__getattribute__', '__hash__', '__init__', '__module__',

'__new__', '__reduce__', '__reduce_ex__', '__repr__',

'__setattr__', '__sizeof__', '__str__', '__subclasshook__',

'__weakref__']

# 查看實(shí)例屬性

>>> dir(test)

['__class__', '__delattr__', '__dict__', '__doc__', '__format__',

'__getattribute__', '__hash__', '__init__', '__module__',

'__new__', '__reduce__', '__reduce_ex__', '__repr__',

'__setattr__', '__sizeof__', '__str__', '__subclasshook__',

'__weakref__']

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

我們主要看一個(gè)屬性__dict__,因?yàn)?__dict__保存的對(duì)象的屬性,看下面一個(gè)例子

>>> class Spring(object):

... season = "the spring of class"

...

# 查看Spring類保存的屬性

>>> Spring.__dict__

dict_proxy({'__dict__': ,

'season': 'the spring of class',

'__module__': '__main__',

'__weakref__': ,

'__doc__': None})

# 通過(guò)兩種方法訪問(wèn)類屬性

>>> Spring.__dict__['season']

'the spring of class'

>>> Spring.season

'the spring of class'

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

發(fā)現(xiàn)__dict__有個(gè)’season’鍵,這就是這個(gè)類的屬性,其值就是類屬性的數(shù)據(jù).

接來(lái)看,看看它的實(shí)例屬性

>>> s = Spring()

# 實(shí)例屬性的__dict__是空的

>>> s.__dict__

{}

# 其實(shí)是指向的類屬性

>>> s.season

'the spring of class'

# 建立實(shí)例屬性

>>> s.season = "the spring of instance"

# 這樣,實(shí)例屬性里面就不空了。這時(shí)候建立的實(shí)例屬性和類屬性重名,并且把它覆蓋了

>>> s.__dict__

{'season': 'the spring of instance'}

>>> s.__dict__['season']

'the spring of instance'

>>> s.season

'the spring of instance'

# 類屬性沒(méi)有受到實(shí)例屬性的影響

>>> Spring.__dict__['season']

'the spring of class'

>>> Spring.__dict__

dict_proxy({'__dict__': , 'season': 'the spring of class', '__module__': '__main__', '__weakref__': , '__doc__': None})

# 如果將實(shí)例屬性刪除,又會(huì)調(diào)用類屬性

>>> del s.season

>>> s.__dict__

{}

>>> s.season

'the spring of class'

# 自定義實(shí)例屬性,對(duì)類屬性沒(méi)有影響

>>> s.lang = "python"

>>> s.__dict__

{'lang': 'python'}

>>> s.__dict__['lang']

'python'

# 修改類屬性

>>> Spring.flower = "peach"

>>> Spring.__dict__

dict_proxy({'__module__': '__main__',

'flower': 'peach',

'season': 'the spring of class',

'__dict__': , '__weakref__': , '__doc__': None})

>>> Spring.__dict__['flower']

'peach'

# 實(shí)例中的__dict__并沒(méi)有變化

>>> s.__dict__

{'lang': 'python'}

# 實(shí)例中找不到flower屬性,調(diào)用類屬性

>>> s.flower

'peach'

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

下面看看類中包含方法,__dict__如何發(fā)生變化

# 定義類

>>> class Spring(object):

... def tree(self, x):

... self.x = x

... return self.x

...

# 方法tree在__dict__里面

>>> Spring.__dict__

dict_proxy({'__dict__': ,

'__weakref__': ,

'__module__': '__main__',

'tree': ,

'__doc__': None})

>>> Spring.__dict__['tree']

# 建立實(shí)例,但是__dict__中沒(méi)有方法

>>> t = Spring()

>>> t.__dict__

{}

# 執(zhí)行方法

>>> t.tree("xiangzhangshu")

'xiangzhangshu'

# 實(shí)例方法(t.tree('xiangzhangshu'))的第一個(gè)參數(shù)(self,但沒(méi)有寫出來(lái))綁定實(shí)例 t,透過(guò) self.x 來(lái)設(shè)定值,即給 t.__dict__添加屬性值。

>>> t.__dict__

{'x': 'xiangzhangshu'}

# 如果沒(méi)有將x 賦值給 self 的屬性,而是直接 return,結(jié)果發(fā)生了變化

>>> class Spring(object):

... def tree(self, x):

... return x

>>> s = Spring()

>>> s.tree("liushu")

'liushu'

>>> s.__dict__

{}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

需要理解python中的一個(gè)觀點(diǎn),一切都是對(duì)象,不管是類還是實(shí)例,都可以看成是對(duì)象,符合object.attribute ,都會(huì)有自己的屬性

使用__slots__優(yōu)化內(nèi)存使用

默認(rèn)情況下,python在各個(gè)實(shí)例中為名為__dict__的字典里存儲(chǔ)實(shí)例屬性,而字典會(huì)消耗大量?jī)?nèi)存(字典要使用底層散列表提升訪問(wèn)速度), 通過(guò)__slots__類屬性,在元組中存儲(chǔ)實(shí)例屬性,不用字典,從而節(jié)省大量?jī)?nèi)存

# 在類中定義__slots__屬性就是說(shuō)這個(gè)類中所有實(shí)例的屬性都在這兒了,如果幾百萬(wàn)個(gè)實(shí)例同時(shí)活動(dòng),能節(jié)省大量?jī)?nèi)存

>>> class Spring(object):

... __slots__ = ("tree", "flower")

...

# 仔細(xì)看看 dir() 的結(jié)果,還有__dict__屬性嗎?沒(méi)有了,的確沒(méi)有了。也就是說(shuō)__slots__把__dict__擠出去了,它進(jìn)入了類的屬性。

>>> dir(Spring)

['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'flower', 'tree']

>>> Spring.__slots__

('tree', 'flower')

# 實(shí)例化

>>> t = Spring()

>>> t.__slots__

('tree', 'flower')

# 通過(guò)類賦予屬性值

>>> Spring.tree = "liushu"

# tree這個(gè)屬性是只讀的, 實(shí)例不能修改

>>> t.tree = "guangyulan"

Traceback (most recent call last):

File "", line 1, in

AttributeError: 'Spring' object attribute 'tree' is read-only

>>> t.tree

'liushu'

# 對(duì)于用類屬性賦值的屬性,只能用來(lái)修改

>>> Spring.tree = "guangyulan"

>>> t.tree

'guangyulan'

# 對(duì)于沒(méi)有用類屬性賦值的屬性,可以通過(guò)實(shí)例來(lái)修改

>>> t.flower = "haitanghua"

>>> t.flower

'haitanghua'

# 實(shí)例屬性的值并沒(méi)有傳回到類屬性,你也可以理解為新建立了一個(gè)同名的實(shí)例屬性

>>> Spring.flower

# 如果再給類屬性賦值

>>> Spring.flower = "ziteng"

>>> t.flower

'ziteng'

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

如果使用的當(dāng),__slots__可以顯著節(jié)省內(nèi)存,按需要注意一下問(wèn)題

在類中定義__slots__之后,實(shí)例不能再有__slots__所列名稱之外的其他屬性

每個(gè)子類都要定義__slots__熟悉,因?yàn)榻忉屍鲿?huì)忽略繼承__slots__屬性

如果不把__werkref__加入__slots__,實(shí)例不能作為弱引用的目標(biāo)

屬性的魔術(shù)方法

來(lái)看幾個(gè)魔術(shù)方法

__setattr__(self,name,value):如果要給 name 賦值,就調(diào)用這個(gè)方法。

__getattr__(self,name):如果 name 被訪問(wèn),同時(shí)它不存在的時(shí)候,此方法被調(diào)用。

__getattribute__(self,name):當(dāng) name被訪問(wèn)時(shí)自動(dòng)被調(diào)用(注意:這個(gè)僅能用于新式類),無(wú)論 name 是否存在,都要被調(diào)用。

__delattr__(self,name):如果要?jiǎng)h除 name,這個(gè)方法就被調(diào)用。

>>> class A(object):

... def __getattr__(self, name):

... print "You use getattr"

... def __setattr__(self, name, value):

... print "You use setattr"

... self.__dict__[name] = value

# a.x,按照本節(jié)開頭的例子,是要報(bào)錯(cuò)的。但是,由于在這里使用了__getattr__(self, name) 方法,當(dāng)發(fā)現(xiàn) x 不存在于對(duì)象的__dict__中的時(shí)候,就調(diào)用了__getattr__,即所謂“攔截成員”。

>>> a = A()

>>> a.x

You use getattr

# 給對(duì)象的屬性賦值時(shí)候,調(diào)用了__setattr__(self, name, value)方法,這個(gè)方法中有一句 self.__dict__[name] = value,通過(guò)這個(gè)語(yǔ)句,就將屬性和數(shù)據(jù)保存到了對(duì)象的__dict__中

>>> a.x = 7

You use setattr

# 測(cè)試__getattribute__(self,name)

>>> class B(object):

... def __getattribute__(self, name):

... print "you are useing getattribute"

... return object.__getattribute__(self, name)

# 返回的內(nèi)容用的是 return object.__getattribute__(self, name),而沒(méi)有使用 return self.__dict__[name]。因?yàn)槿绻眠@樣的方式,就是訪問(wèn) self.__dict__,只要訪問(wèn)這個(gè)屬性,就要調(diào)用`getattribute``,這樣就導(dǎo)致了無(wú)限遞歸

# 訪問(wèn)不存在的成員,可以看到,已經(jīng)被__getattribute__攔截了,雖然最后還是要報(bào)錯(cuò)的。

>>> b = B()

>>> b.y

you are useing getattribute

Traceback (most recent call last):

File "", line 1, in

File "", line 4, in __getattribute__

AttributeError: 'B' object has no attribute 'y'

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

Property函數(shù)

porperty可以作為裝飾器使用把方法標(biāo)記為特性

class Vector(object):

def __init__(self, x, y):

# 使用兩個(gè)前導(dǎo)下劃線,把屬性標(biāo)記為私有

self.__x = float(x)

self.__y = float(y)

# porperty裝飾器把讀值方法標(biāo)記為特性

@property

def x(self):

return self.__x

@property

def y(self):

return self.__y

vector = Vector(3,4)

print(vector.x, vector.y)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

使用property可以將函數(shù)封裝為屬性

class Rectangle(object):

"""

the width and length of Rectangle

"""

def __init__(self):

self.width = 0

self.length = 0

def setSize(self, size):

self.width, self.length = size

def getSize(self):

return self.width, self.length

if __name__ == "__main__":

r = Rectangle()

r.width = 3

r.length = 4

print r.getSize() # (3,4)

r.setSize( (30, 40) )

print r.width # 30

print r.length # 40

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

這段代碼可以正常運(yùn)行,但是屬性的調(diào)用方式可以改進(jìn),如下:

class Rectangle(object):

"""

the width and length of Rectangle

"""

def __init__(self):

self.width = 0

self.length = 0

def setSize(self, size):

self.width, self.length = size

def getSize(self):

return self.width, self.length

# 使用property方法將函數(shù)封裝為屬性,更優(yōu)雅

size = property(getSize, setSize)

if __name__ == "__main__":

r = Rectangle()

r.width = 3

r.length = 4

print r.size # (30, 40)

r.size = 30, 40

print r.width # 30

print r.length # 40

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

使用魔術(shù)方法實(shí)現(xiàn):

class NewRectangle(object):

def __init__(self):

self.width = 0

self.length = 0

def __setattr__(self, name, value):

if name == 'size':

self.width, self, length = value

else:

self.__dict__[name] = value

def __getattr__(self, name):

if name == 'size':

return self.width, self.length

else:

raise AttrubuteErrir

if __name__ == "__main__":

r = Rectangle()

r.width = 3

r.length = 4

print r.size # (30, 40)

r.size = 30, 40

print r.width # 30

print r.length # 40

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

屬性的獲取順序

最后我們來(lái)看看熟悉的獲得順序:通過(guò)實(shí)例獲取其屬性,如果在__dict__中有相應(yīng)的屬性,就直接返回其結(jié)果;如果沒(méi)有,會(huì)到類屬性中找。

看下面一個(gè)例子:

class A(object):

author = "qiwsir"

def __getattr__(self, name):

if name != "author":

return "from starter to master."

if __name__ == "__main__":

a = A()

print a.author # qiwsir

print a.lang # from starter to master.

1

2

3

4

5

6

7

8

9

10

當(dāng) a = A() 后,并沒(méi)有為實(shí)例建立任何屬性,或者說(shuō)實(shí)例的__dict__是空的。但是如果要查看 a.author,因?yàn)閷?shí)例的屬性中沒(méi)有,所以就去類屬性中找,發(fā)現(xiàn)果然有,于是返回其值 “qiwsir”。但是,在找 a.lang的時(shí)候,不僅實(shí)例屬性中沒(méi)有,類屬性中也沒(méi)有,于是就調(diào)用了__getattr__()方法。在上面的類中,有這個(gè)方法,如果沒(méi)有__getattr__()方法呢?如果沒(méi)有定義這個(gè)方法,就會(huì)引發(fā) AttributeError,這在前面已經(jīng)看到了。

---------------------

總結(jié)

以上是生活随笔為你收集整理的python属性_深入理解python对象及属性的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。