国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Python獲取對(duì)象屬性的幾種方式小結(jié)

瀏覽:8日期:2022-08-02 16:30:44

本文將簡(jiǎn)單介紹四種獲取對(duì)象的方法。

假如有以下的類(lèi):

class Person(object): def __init__(self, name, age): self.name = name self.age = age def __str__(self): return ’name=%s, age=%s’ % (self.name, self.age)

方法一:使用屬性運(yùn)算符

print(xmr.name)

方法二:通過(guò)屬性字典__dict__

print(xmr.__dict__[’name’])

方法三:通過(guò)getattr函數(shù)

print(getattr(xmr, ’name’))

方法四:operator.attrgetter

import operator op = operator.attrgetter(’name’)print(op(xmr))

方法四可以用于對(duì)象的排序,比如需要根據(jù)年齡age來(lái)排序Person對(duì)象:

import operator p_list = [Person(’xiemanR’, 18), Person(’zhangshan’, 17), Person(’lisi’, 20), Person(’wangwu’, 25)] r = sorted(p_list, key=operator.attrgetter(’age’)) for i in r: print(i)

輸出結(jié)果:

Person(name=zhangshan, age=17)Person(name=xiemanR, age=18)Person(name=lisi, age=20)Person(name=wangwu, age=25)

PS:其實(shí)第四種方法是調(diào)用第三種方法的,只是簡(jiǎn)單封裝了一下,我們看看operator.attrgetter實(shí)現(xiàn)就知道了:

class attrgetter: def __init__(self, attr, *attrs): if not attrs: if not isinstance(attr, str): raise TypeError(’attribute name must be a string’) names = attr.split(’.’) def func(obj): for name in names: obj = getattr(obj, name) return obj self._call = func else: getters = tuple(map(attrgetter, (attr,) + attrs)) def func(obj): return tuple(getter(obj) for getter in getters) self._call = func def __call__(self, obj): return self._call(obj)

完。

補(bǔ)充知識(shí):深入理解python對(duì)象及屬性

類(lèi)屬性和實(shí)例屬性

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

>>> class Test(object): pass>>> test = Test()# 查看類(lèi)屬性>>> 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__’]

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

>>> class Spring(object):... season = 'the spring of class'... # 查看Spring類(lèi)保存的屬性>>> Spring.__dict__dict_proxy({’__dict__’: <attribute ’__dict__’ of ’Spring’ objects>, ’season’: ’the spring of class’, ’__module__’: ’__main__’, ’__weakref__’: <attribute ’__weakref__’ of ’Spring’ objects>, ’__doc__’: None})# 通過(guò)兩種方法訪問(wèn)類(lèi)屬性>>> Spring.__dict__[’season’]’the spring of class’>>> Spring.season’the spring of class’

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

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

>>> s = Spring()# 實(shí)例屬性的__dict__是空的>>> s.__dict__{}# 其實(shí)是指向的類(lèi)屬性>>> s.season’the spring of class’# 建立實(shí)例屬性>>> s.season = 'the spring of instance'# 這樣,實(shí)例屬性里面就不空了。這時(shí)候建立的實(shí)例屬性和類(lèi)屬性重名,并且把它覆蓋了>>> s.__dict__{’season’: ’the spring of instance’}>>> s.__dict__[’season’]’the spring of instance’>>> s.season’the spring of instance’# 類(lèi)屬性沒(méi)有受到實(shí)例屬性的影響>>> Spring.__dict__[’season’]’the spring of class’>>> Spring.__dict__dict_proxy({’__dict__’: <attribute ’__dict__’ of ’Spring’ objects>, ’season’: ’the spring of class’, ’__module__’: ’__main__’, ’__weakref__’: <attribute ’__weakref__’ of ’Spring’ objects>, ’__doc__’: None})# 如果將實(shí)例屬性刪除,又會(huì)調(diào)用類(lèi)屬性>>> del s.season>>> s.__dict__{}>>> s.season’the spring of class’# 自定義實(shí)例屬性,對(duì)類(lèi)屬性沒(méi)有影響>>> s.lang = 'python'>>> s.__dict__{’lang’: ’python’}>>> s.__dict__[’lang’]’python’# 修改類(lèi)屬性>>> Spring.flower = 'peach'>>> Spring.__dict__dict_proxy({’__module__’: ’__main__’, ’flower’: ’peach’, ’season’: ’the spring of class’, ’__dict__’: <attribute ’__dict__’ of ’Spring’ objects>, ’__weakref__’: <attribute ’__weakref__’ of ’Spring’ objects>, ’__doc__’: None})>>> Spring.__dict__[’flower’]’peach’# 實(shí)例中的__dict__并沒(méi)有變化>>> s.__dict__{’lang’: ’python’}# 實(shí)例中找不到flower屬性,調(diào)用類(lèi)屬性>>> s.flower’peach’

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

# 定義類(lèi)>>> class Spring(object):... def tree(self, x):... self.x = x... return self.x... # 方法tree在__dict__里面>>> Spring.__dict__dict_proxy({’__dict__’: <attribute ’__dict__’ of ’Spring’ objects>, ’__weakref__’: <attribute ’__weakref__’ of ’Spring’ objects>, ’__module__’: ’__main__’, ’tree’: <function tree at 0xb748fdf4>, ’__doc__’: None})>>> Spring.__dict__[’tree’]<function tree at 0xb748fdf4># 建立實(shí)例,但是__dict__中沒(méi)有方法 >>> t = Spring()>>> t.__dict__{}# 執(zhí)行方法>>> t.tree('xiangzhangshu')’xiangzhangshu’# 實(shí)例方法(t.tree(’xiangzhangshu’))的第一個(gè)參數(shù)(self,但沒(méi)有寫(xiě)出來(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__{}

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

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

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

# 在類(lèi)中定義__slots__屬性就是說(shuō)這個(gè)類(lèi)中所有實(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)入了類(lèi)的屬性。>>> 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ò)類(lèi)賦予屬性值>>> Spring.tree = 'liushu'# tree這個(gè)屬性是只讀的, 實(shí)例不能修改>>> t.tree = 'guangyulan'Traceback (most recent call last): File '<stdin>', line 1, in <module>AttributeError: ’Spring’ object attribute ’tree’ is read-only>>> t.tree’liushu’# 對(duì)于用類(lèi)屬性賦值的屬性,只能用來(lái)修改>>> Spring.tree = 'guangyulan'>>> t.tree’guangyulan’# 對(duì)于沒(méi)有用類(lèi)屬性賦值的屬性,可以通過(guò)實(shí)例來(lái)修改>>> t.flower = 'haitanghua'>>> t.flower’haitanghua’# 實(shí)例屬性的值并沒(méi)有傳回到類(lèi)屬性,你也可以理解為新建立了一個(gè)同名的實(shí)例屬性>>> Spring.flower<member ’flower’ of ’Spring’ objects># 如果再給類(lèi)屬性賦值>>> Spring.flower = 'ziteng'>>> t.flower’ziteng’

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

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

每個(gè)子類(lèi)都要定義__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è)僅能用于新式類(lèi)),無(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é)開(kāi)頭的例子,是要報(bào)錯(cuò)的。但是,由于在這里使用了__getattr__(self, name) 方法,當(dāng)發(fā)現(xiàn) x 不存在于對(duì)象的__dict__中的時(shí)候,就調(diào)用了__getattr__,即所謂“攔截成員”。>>> a = A()>>> a.xYou use getattr# 給對(duì)象的屬性賦值時(shí)候,調(diào)用了__setattr__(self, name, value)方法,這個(gè)方法中有一句 self.__dict__[name] = value,通過(guò)這個(gè)語(yǔ)句,就將屬性和數(shù)據(jù)保存到了對(duì)象的__dict__中>>> a.x = 7You 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.yyou are useing getattributeTraceback (most recent call last): File '<stdin>', line 1, in <module> File '<stdin>', line 4, in __getattribute__AttributeError: ’B’ object has no attribute ’y’

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)

使用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.lengthif __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

這段代碼可以正常運(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

使用魔術(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] = valuedef __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

屬性的獲取順序

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

看下面一個(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.

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

以上這篇Python獲取對(duì)象屬性的幾種方式小結(jié)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 成人做爰视频www视频 | 国产a精品三级 | 狠狠做久久深爱婷婷97动漫 | 日本一级特黄在线播放 | 尤蜜网站在线进入免费 | 在线一区国产 | 亚洲黄色在线播放 | a级成人高清毛片 | 成人免费视频国产 | 中国一级毛片特级毛片 | 成人国内精品久久久久影院 | 日韩精品小视频 | 国产精品视频免费观看调教网 | 成年日韩片av在线网站 | 久久久久久一级毛片免费野外 | 国产精品亚洲一区二区三区在线观看 | 国产亚洲欧美在线视频 | 国产国语对白一级毛片 | 亚洲国产日韩欧美高清片a 亚洲国产日韩欧美在线 | 女人被男人躁得好爽免费视频免费 | 久久国产三级精品 | 97久久精品一区二区三区 | 久久久久久一级毛片免费野外 | 91精品国产色综合久久 | 欧美成人三级 | 欧美午夜影院 | 农村寡妇一级毛片免费播放 | 97视频在线免费播放 | 另类专区 亚洲 | 久久影院一区二区三区 | 国产l精品国产亚洲区久久 国产tv在线 | 精品中文字幕在线观看 | 亚洲人成毛片线播放 | 看欧美的一级毛片 | 免费看欧美日韩一区二区三区 | 亚洲精品日韩中文字幕久久久 | 久久草在线观看 | 国产午夜人做人视频羞羞 | a级毛片免费高清毛片视频 a级毛片免费高清视频 | 国产成人a一区二区 | 黄色毛片国产 |