最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2020年03月12日 08:32:30   作者:xiemanR  
這篇文章主要介紹了Python獲取對(duì)象屬性的幾種方式小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧

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

假如有以下的類:

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ì)象及屬性

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

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

>>> class Test(object):
    pass
>>> test = Test()
# 查看類屬性
>>> 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類保存的屬性
>>> 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)類屬性
>>> Spring.__dict__['season']
'the spring of class'
>>> Spring.season
'the spring of class'

發(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__': <attribute '__dict__' of 'Spring' objects>, 'season': 'the spring of class', '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Spring' objects>, '__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__': <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)用類屬性
>>> s.flower
'peach'

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

# 定義類
>>> 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)有寫出來(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ì)象,不管是類還是實(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__類屬性,在元組中存儲(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 "<stdin>", line 1, in <module>
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
<member 'flower' of 'Spring' objects>
# 如果再給類屬性賦值
>>> Spring.flower = "ziteng"
>>> t.flower
'ziteng'

如果使用的當(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é)開(kāi)頭的例子,是要報(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 "<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.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

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

屬性的獲取順序

最后我們來(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.

當(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)看到了。

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

相關(guān)文章

  • Python實(shí)現(xiàn)的序列化和反序列化二叉樹(shù)算法示例

    Python實(shí)現(xiàn)的序列化和反序列化二叉樹(shù)算法示例

    這篇文章主要介紹了Python實(shí)現(xiàn)的序列化和反序列化二叉樹(shù)算法,結(jié)合實(shí)例形式分析了Python二叉樹(shù)的構(gòu)造、遍歷、序列化、反序列化等相關(guān)操作技巧,需要的朋友可以參考下
    2019-03-03
  • python中利用numpy.array()實(shí)現(xiàn)倆個(gè)數(shù)值列表的對(duì)應(yīng)相加方法

    python中利用numpy.array()實(shí)現(xiàn)倆個(gè)數(shù)值列表的對(duì)應(yīng)相加方法

    今天小編就為大家分享一篇python中利用numpy.array()實(shí)現(xiàn)倆個(gè)數(shù)值列表的對(duì)應(yīng)相加方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-08-08
  • 一文教你解決所有Python中文亂碼問(wèn)題

    一文教你解決所有Python中文亂碼問(wèn)題

    我們?cè)诰帉懘a時(shí)總是遇到各種中文亂碼的問(wèn)題,所以本文就來(lái)為大家總結(jié)一下遇到的中文亂碼問(wèn)題和對(duì)應(yīng)的解決方案,以及為什么會(huì)出現(xiàn)中文亂碼的問(wèn)題,希望對(duì)大家有所幫助
    2023-12-12
  • 使用Python進(jìn)行圖像裁剪和直方圖分析

    使用Python進(jìn)行圖像裁剪和直方圖分析

    在數(shù)字圖像處理領(lǐng)域,裁剪和分析圖像的直方圖是兩個(gè)非?;厩抑匾牟僮?本文將通過(guò)一個(gè)簡(jiǎn)單的Python項(xiàng)目,展示如何使用skimage和matplotlib庫(kù)來(lái)裁剪圖像并分析其RGB通道的直方圖,感興趣的小伙伴跟著小編一起來(lái)看看吧
    2025-01-01
  • 使用python和pygame制作擋板彈球游戲

    使用python和pygame制作擋板彈球游戲

    這篇文章主要介紹了使用python和pygame制作擋板彈球游戲,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-12-12
  • Python列表之間的數(shù)字與字符轉(zhuǎn)化實(shí)例

    Python列表之間的數(shù)字與字符轉(zhuǎn)化實(shí)例

    在python列表操作中,面對(duì)需要把列表中的字符串轉(zhuǎn)為禮拜的操作,無(wú)需強(qiáng)轉(zhuǎn),通過(guò)簡(jiǎn)單的幾步就可以實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于Python列表之間的數(shù)字與字符轉(zhuǎn)化的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • pyspark操作MongoDB的方法步驟

    pyspark操作MongoDB的方法步驟

    這篇文章主要介紹了pyspark操作MongoDB的方法步驟,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • Python中for循環(huán)詳解

    Python中for循環(huán)詳解

    這篇文章主要介紹了Python中for循環(huán),有需要的朋友可以參考一下
    2014-01-01
  • python選擇排序算法實(shí)例總結(jié)

    python選擇排序算法實(shí)例總結(jié)

    這篇文章主要介紹了python選擇排序算法,以三個(gè)實(shí)例以不同方法分析了Python實(shí)現(xiàn)選擇排序的相關(guān)技巧,需要的朋友可以參考下
    2015-07-07
  • Python實(shí)現(xiàn)為PDF大文件批量去除水印

    Python實(shí)現(xiàn)為PDF大文件批量去除水印

    在閱讀過(guò)程中如果遇到一些帶有水印的資料是比較煩心的,而市面上去水印的功能有多要收費(fèi)且很不方便,那么,如何通過(guò)Python來(lái)對(duì)這類圖片水印進(jìn)行去除呢,本文就來(lái)和大家分享一下實(shí)現(xiàn)方法吧
    2023-05-05

最新評(píng)論

乌拉特前旗| 郧西县| 友谊县| 石嘴山市| 陈巴尔虎旗| 蒙自县| 子长县| 九江市| 兴城市| 舟曲县| 鲜城| 高密市| 双桥区| 潜江市| 东莞市| 长宁县| 内黄县| 滕州市| 白沙| 炉霍县| 陆丰市| 永仁县| 平罗县| 华阴市| 鄂托克前旗| 张家港市| 东安县| 余干县| 怀仁县| 上思县| 塔城市| 齐齐哈尔市| 舟曲县| 盐津县| 清水县| 翼城县| 景洪市| 潞西市| 昌都县| 江津市| 湖南省|