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

歡迎訪問 生活随笔!

生活随笔

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

python

python对象的三个属性_Python 对象属性的访问

發(fā)布時間:2024/7/23 python 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python对象的三个属性_Python 对象属性的访问 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在 Python 中,一切皆對象。屬性訪問可以理解為是從一個已有的對象中獲得另一個對象的方法。對象屬性的訪問涉及到對象的 __dict__ 屬性、描述符等概念,以及 __getattribute__、__getattr__ 等方法。

對象字典屬性

Python 中的對象有一個 __dict__ 屬性,其是一個字典類型,對象當(dāng)前可用的屬性和方法都保存在合格字典中。它存儲著對象屬性的名稱與值的鍵值對。示例(在 Python 2.7 環(huán)境測試):

>>> class C(object):

... x = 1

...

>>> C.__dict__

dict_proxy({

'__dict__': ,

'x': 1, '__module__': '__console__',

'__weakref__': ,

'__doc__': None

})

>>> c = C()

>>> c.__dict__

{}

>>> c.y = 1

>>> c.__dict__

{'y': 1}

>>> c.x

1

>>> c.x = 2

>>> c.x

2

>>> C.x

1

>>> c.__dict__

{'y': 1, 'x': 2}

由上例應(yīng)該注意到,類變量 x 存儲在類 C 的 dict 屬性中,而由 C 初始化的對象 c 的屬性 y 則在 c 的 dict 中。對象 c 仍然可以訪問其類型 C 中的類變量 x。但是,如果在對象 c 中重新設(shè)置屬性 x 之后,則 C 與 c 中各自有自己的 x 屬性,此時 c.x 不再訪問其類的屬性,而是訪問自己的 x 屬性。

還應(yīng)注意到,類對象的 __dict__ 屬性為普通的 dict 類型,而類定義的 __dict__ 則為 dict_proxy 類型(在 Python3 中為 mappingproxy 類型)。類對象的該屬性是可以被直接修改的,而類的卻不行。因為類的 __dict__ 是只讀的,所以其命名中被加入了 proxy 字眼,這樣做的目的是為了防止其被意外修改而導(dǎo)致意想不到的錯誤發(fā)生。

>>> c.__dict__['x'] = 5

>>> C.__dict__['x'] = 6

Traceback (most recent call last):

File "", line 1, in

C.__dict__['x'] = 6

TypeError: 'dictproxy' object does not support item assignment

>>> c.x

5

>>> C.x

1

>>> c.__dict__ = {}

>>> C.__dict__ = {}

Traceback (most recent call last):

File "", line 1, in

C.__dict__ = {}

AttributeError: attribute '__dict__' of 'type' objects is not writable

>>> c.__dict__

{}

>>> c.x

1

>>> C.x

1

并不是所有的對象都有 __dict__ 這個屬性,例如實現(xiàn)了 __slots__ 屬性的類的對象。擁有 __slots__ 屬性的類在實例化對象時不會自動分配 __dict__, 只有在 __slots__ 中的屬性才能被使用,但它的設(shè)置只對對象真正的屬性有限制作用。如果是用 property 修飾的屬性以及屬性是一個描述符對象時是不受限制的。

描述符

描述符是實現(xiàn)了描述符協(xié)議的對象,本質(zhì)上是一種擁有綁定行為的對象屬性。描述符的訪問行為被如下的描述符協(xié)議方法覆蓋:

__get__(self, obj, type=None) --> value

__set__(self, obj, value) --> None

__delete__(self, obj) --> None

描述符協(xié)議只是一種在模型中引用屬性時指定將要發(fā)生事件的方法。實現(xiàn)了以上描述符協(xié)議三個方法中任意一個的對象即是描述符。同時定義了 __get__ 和 __set__ 方法的對象就叫作數(shù)據(jù)描述符(Data Descriptor),也被成為資源描述符。而只定義了 __get__ 方法的對象被叫做非數(shù)據(jù)描述符(Non-data Descriptor)。實際上類方法(classmethod)即為一個非數(shù)據(jù)描述符。數(shù)據(jù)描述符與非數(shù)據(jù)描述會影響其被訪問的順序。如果實例中存在與數(shù)據(jù)描述符同名的屬性,則會優(yōu)先訪問數(shù)據(jù)描述符。如果實例中存在與非數(shù)據(jù)描述符同名的屬性,則優(yōu)先訪問實例屬性。一個描述符的定義類似如下形式:

class Descriptor(object):

def __init__(slef):

pass

def __get__(self, instance, owner):

"""用于訪問屬性

返回屬性的值,或者在所請求的屬性不存在的情況下出現(xiàn) AttributeError 異常

"""

pass

def __set__(self, instance, value):

"""用于設(shè)置屬性值

將在屬性分配操作中調(diào)用,不會返回任何內(nèi)容

"""

pass

def __delete__(self, ):

"""用于刪除屬性

控制刪除操作,不會返回內(nèi)容

"""

pass

描述符將某種特殊類型的類的實例指派給另一個類的屬性(注意: 這里是類屬性,而不是對象屬性,即描述符被分配給一個類,而不是實例)。描述符相當(dāng)于是一種創(chuàng)建托管屬性的方法。托管屬性可以用于保護(hù)屬性不受修改,對傳遞的值做檢查,或自動更新某個依賴屬性的值。下面是一個簡單的示例:

class Descriptor(object):

def __init__(self, m):

self.m = m

def __get__(self, instance, owner):

return instance.n * self.m

def __set__(self, instance, value):

if value < 0:

raise ValueError("Negative value not allowed:%s" % value)

instance.n = value

class Foo(object):

bar = Descriptor(0)

har = Descriptor(1)

tar = Descriptor(2)

yar = Descriptor(3)

def __init__(self, n):

self.n = n

"""

>>> f = Foo(10)

>>> f.bar

0

>>> f.bar = 100

>>> f.bar

0

>>> f.har

100

>>> f.har = 10

>>> f.har

10

>>> f.yar

30

>>> f.yar = 12345

>>> f.yar

37035

"""

Python 中的類方法裝飾器 classmethod、staticmethod 實際上是一個非數(shù)據(jù)描述符,下面是他們的純 Python 實現(xiàn)示例:

class StaticMethod(object):

def __init__(self, f):

self.f = f

def __get__(self, instance, owner):

return self.f

class ClassMethod(object):

def __init__(self, f):

self.f = f

def __get__(self, instance, owner):

if owner is None:

owner = type(instance)

def _func(*args):

return self.f(owner, *args)

return _func

此外,Python 的 property 則是一個數(shù)據(jù)描述符,它將對象屬性的訪問轉(zhuǎn)化為方法調(diào)用。類中的 property 裝飾器有一個缺陷,每次試圖訪問 property 屬性時其裝飾的函數(shù)都會被調(diào)用,而有時候可能只希望函數(shù)被調(diào)用一次。于是,可以模仿 property 來實現(xiàn)一個惰性屬性(lazy property),即在必要的時候(屬性被真正訪問到時)才初始化屬性。以下是惰性屬性描述符的實現(xiàn)示例:

class lazy_property(object):

def __init__(self, func):

self.func = func

def __get__(self, obj, cls):

if obj is None:

return self

value = obj.__dict__[self.func.__name__] = self.func(obj)

return value

上例中實現(xiàn)一個非數(shù)據(jù)描述來達(dá)到惰性初始化屬性的目的。對象惰性屬性在被訪問時會調(diào)用 func 初始化得到 value,然后再在對象的 __dict__ 中設(shè)置同名的屬性,下一次再訪問屬性時,會直接返回 __dict__ 中保存的值,而不再去訪問描述符。這里涉及到了對象屬性的訪問優(yōu)先級順序問題。

屬性訪問順序

Python 在對象屬性訪問時會無條件調(diào)用 __getttribute__() 方法。在屬性搜索的優(yōu)先級鏈中,類字典中發(fā)現(xiàn)的數(shù)據(jù)描述符的優(yōu)先級高于實例變量,實例變量優(yōu)先級高于非數(shù)據(jù)描述符。如果提供了 __getattr__(),優(yōu)先級鏈會為 __getattr__() 分配最低優(yōu)先級。除非 __getttribute__() 顯示調(diào)用或者拋出 AttributeError 異常,否則 __getattr__() 將不會被調(diào)用。

描述符的調(diào)用是通過 _getattribute__() 方法實現(xiàn)的,重寫該方法可以阻止描述符的自動調(diào)用。數(shù)據(jù)描述符總是覆蓋類實例的 __dict__,而非數(shù)據(jù)描述符可能會被類實例的 __dict__ 覆蓋。_getattribute__() 方法的實現(xiàn)大概類似如下形式:

def __getattribute__(self, key):

"Emulate type_getattro() in Objects/typeobject.c"

v = object.__getattribute__(self, key)

if hasattr(v, '__get__'):

return v.__get__(None, self)

return v

需要注意的是,重寫 __getttribute__() 方法時,不能在其實現(xiàn)中使用 self.xxx 的形式訪問自己的屬性,這樣會導(dǎo)致無限遞歸。而需要訪問自己的屬性時,應(yīng)該調(diào)用基類的方法。如 object.__getattribute__(self, name)。

下面詳細(xì)描述下對象屬性的訪問順序。假設(shè)有 class C, c = C(), 那么 c.x 的執(zhí)行順序為:

(1)如果 x 是出現(xiàn)在 C 或其基類的 __dict__ 中,且是數(shù)據(jù)描述符, 那么調(diào)用其 __get__ 方法,否則

(2)如果 x 出現(xiàn)在 c 的 __dict__ 中,那么直接返回 c.__dict__['x'],否則

(3)如果 x 出現(xiàn)在 C 或其基類的 __dict__ 中,那么

(3.1)如果 x 是非數(shù)據(jù)描述符,那么調(diào)用其 __get__ 方法,否則

(3.2)返回 __dict__['x']

(4)如果 C 有 __getattr__ 方法,調(diào)用 __getattr__ 方法,否則

(5)拋出 AttributeError

處理缺失值

默認(rèn)情況下,當(dāng)訪問的屬性在對象中不存在時,會拋出 AttributeError 異常。而在有些場景中我們并不希望這樣,比如在我工作的項目中,當(dāng)訪問一項配置時,如果該配置項不存在,我們希望其返回 None,而不是發(fā)生異常。這用 __getattr__ 方法很容易實現(xiàn),該方法通常與 __setattr__、__delattr__ 方法配合使用,__setattr__ 方法會改變屬性的復(fù)制行為:

class Foo(object):

def __init__(self):

self.x = 1

def __getattr__(self, key):

try:

return self.__dict__[key]

except KeyError:

return None

def __setattr__(self, key, value):

self.__dict__[key] = value

def __delattr__(self, key):

try:

del self.__dict__[key]

except KeyError:

return None

如果對象時一個字典,則當(dāng)訪問一個不存在的 key 時,會發(fā)生 KeyError 異常。字典也有一個方法可以用來處理缺失值,即 __missing__。這個方法雖然與屬性訪問無關(guān),這里也做一下簡單的介紹。當(dāng)訪問的鍵不存在時,dict.__getitem__() 方法會自動調(diào)用該方法。需要注意的是 dict 中并沒這個方法,需要在子類中實現(xiàn)。示例:

class FooDict(dict):

def __missing__(self, key):

self[key] = "hello"

return "hello"

fdict = FooDict()

print fdict

print fdict["bar"]

# 執(zhí)行結(jié)果:

# {}

# hello

可以用該方法來實現(xiàn)一個缺省字典:

class defaultdict(dict):

def __init__(self, default_factory=None, *a, **kw):

dict.__init__(self, *a, **kw)

self.default_factory = default_factory

def __missing__(self, key):

self[key] = value = self.default_factory()

return value

參考資料

總結(jié)

以上是生活随笔為你收集整理的python对象的三个属性_Python 对象属性的访问的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: av视屏| 福利视频在线播放 | 精品少妇爆乳无码av无码专区 | av直播在线观看 | 美国黄色一级毛片 | 一级黄色免费片 | 欧美一级做a爰片免费视频 成人激情在线观看 | 自拍毛片 | 亚洲三区在线播放 | 欧美中文字幕一区二区三区 | 欧美黑人疯狂性受xxxxx野外 | 99久久久国产精品免费蜜臀 | 国产激情图片 | 国产日韩av在线播放 | 天天曰天天 | 综合色99 | 国产精品igao | 日日碰狠狠添天天爽无码av | 女人裸体又黄 | 国产精品久久久久一区二区三区 | 电影《两个尼姑》免费播放 | 18禁裸男晨勃露j毛免费观看 | 欧美三级午夜理伦三级老人 | 青草国产 | 久久视频在线播放 | 亚洲成在人 | av福利在线免费观看 | 95视频在线 | 在线播放你懂的 | 肉丝美足丝袜一区二区三区四 | 国产成人亚洲一区二区 | 天堂在线中文8 | 2021亚洲天堂| 天天操夜夜拍 | 91国产丝袜在线播放 | 日韩中文字幕av在线 | 好色艳妇小说 | 夜久久久 | 日韩av一二三 | 神宫寺奈绪一区二区三区 | www.日韩高清 | 色屋在线 | 亚洲一区不卡 | 国产精品乱码一区二区视频 | 亚洲国内精品 | 日韩欧美一区二区一幕 | 色综合色综合网色综合 | 国产精品久久久久久久久久久久午夜片 | 隣の若妻さん波多野结衣 | 午夜色av| 日本美女视频一区 | 日本一区二区三区免费观看 | 两根大肉大捧一进一出好爽视频 | 男人插入女人阴道视频 | 麻豆亚洲精品 | 亚洲av无码一区二区三区网站 | 黄色片视频播放 | 肉大榛一进一出免费视频 | 囯产精品一品二区三区 | 青青久在线视频 | 一区二区亚洲视频 | 色老头在线一区二区三区 | 亚洲 小说区 图片区 | 欧美xxxx黑人xyx性爽 | 色婷婷av一区二区三区大白胸 | 污污视频在线免费观看 | 99有精品 | 国产成人一区二区三区别 | 久草热视频 | 巨胸喷奶水www久久久免费动漫 | 久久久精品人妻一区二区三区 | 欧美精品一区二区视频 | 俄罗斯女人裸体性做爰 | 蜜臀av无码精品人妻色欲 | 无码人妻丰满熟妇精品 | 色综合色婷婷 | 亚洲影视一区二区 | 和黑帮大佬的365 | 一级片一区 | 天天舔天天操天天干 | 欧美mv日韩mv国产网站 | 韩国美女啪啪 | 特大黑人娇小亚洲女mp4 | av资源网在线 | 日韩久久一区 | 欧美高清精品一区二区 | 户外少妇对白啪啪野战 | 美国一级黄色大片 | 亚洲精品人 | 动漫美女无遮挡免费 | 澳门三级 | 精品电影一区二区 | 亚洲欧美日韩激情 | 五月婷婷激情综合网 | 精品区| 最新在线中文字幕 | 免费黄色在线观看 | 成人福利影院 | 国产欧美激情 |