日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
Python屬性自省:深入了解屬性訪問(wèn)與限制

在Python中,屬性自省是一種強(qiáng)大的特性,它允許我們?cè)谶\(yùn)行時(shí)檢查和操作對(duì)象的屬性。在本文中,我們將探討Python中的屬性自省,并結(jié)合實(shí)際場(chǎng)景和代碼來(lái)展示其用法。

10年積累的成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問(wèn)題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先網(wǎng)站設(shè)計(jì)后付款的網(wǎng)站建設(shè)流程,更有興平免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

1. 私有屬性與訪問(wèn)限制

Python中的私有屬性是指以下劃線開(kāi)頭的變量或方法,例如 _name 或 _method()。盡管這種命名約定并非強(qiáng)制性的,只是一種慣例,但它用于提示該屬性或方法應(yīng)該只在類(lèi)內(nèi)部使用,而不應(yīng)該在外部直接訪問(wèn)。

Python中的私有屬性具有以下特點(diǎn):

  • 私有屬性不能被外部直接訪問(wèn),但可以通過(guò)類(lèi)內(nèi)部的方法間接地訪問(wèn)。
  • 在類(lèi)內(nèi)部定義的方法可以訪問(wèn)所有屬性,包括私有屬性,因?yàn)樗鼈兌荚谕粋€(gè)作用域內(nèi)。
  • 子類(lèi)無(wú)法繼承父類(lèi)的私有屬性,但可以通過(guò)公有方法來(lái)訪問(wèn)父類(lèi)的私有屬性。

接下來(lái)勇哥帶你探討如何訪問(wèn)和修改私有屬性:

class YongeGe:
    name= '勇哥' # 普通屬性
    _ager = 100   # 普通屬性
    __money = 109  # 私有屬性
    __money_empty__ = 1  # 不推薦做法

yongge = YongeGe()
print(yongge .name)  # 輸出: 勇哥
print(yongge ._ager )  # 輸出: 100
print(yongge ._YongeGe__money )  # 輸出: 109  
print(yongge .__money_empty__ )  # 輸出: 1
print(yongge .__money )  # 輸出: AttributeError: 'YongeGe' object has no attribute '__money'

很明顯看到 Python 中沒(méi)有真正的私有屬性,實(shí)際上雙下劃線開(kāi)頭的屬性被名稱(chēng)重整了,即將屬性名轉(zhuǎn)換為 _ClassName__name的形式,使其難以在外部被訪問(wèn)。通過(guò)_YongGe__money可以間接訪問(wèn)私有屬性__money 。但是一般不要用,就比如你爹告訴你剩100塊了,要省點(diǎn)花,你非要點(diǎn)個(gè)海底撈一把梭哈!

總之,Python的私有屬性機(jī)制主要基于命名約定,其作用是限制屬性的可見(jiàn)性和訪問(wèn)性,從而提高代碼的封裝性和安全性。然而,需要注意的是,這種機(jī)制只是一種建議性的規(guī)范,并不能完全避免私有屬性被訪問(wèn)的可能性。

2. 屬性自省與對(duì)象內(nèi)部狀態(tài)查看

在實(shí)際開(kāi)發(fā)中,我們經(jīng)常需要查看對(duì)象的屬性和方法,以便理解其內(nèi)部狀態(tài)。Python提供了幾種屬性自省的方法,使我們能夠方便地檢查對(duì)象的屬性。

(1) 使用__dict__屬性

__dict__是對(duì)象的一個(gè)屬性,它包含了對(duì)象的所有屬性和方法。通過(guò)訪問(wèn)__dict__,我們可以查看對(duì)象的內(nèi)部狀態(tài)。

例如,我們定義了一個(gè)名為Person的類(lèi),其中包含name和age兩個(gè)屬性,以及一個(gè)say_hello方法。下面的代碼展示了如何通過(guò)訪問(wèn)__dict__來(lái)查看對(duì)象的屬性和方法:

class YongeGe:
    def __init__(self, name, money):
        self.name = name
        self.money= money

    def money(self):
        print(f"Hello, my name is {self.name}.I have {self.money} dollar ")

yongge = YongeGe("勇哥", "10")
yongge .money= "1010"
yongge .__dict__["age"] = "18"

輸出結(jié)果為:

{'name': '勇哥', 'money': '1010', 'age': '18'}

我們可以看到對(duì)象yongge的屬性和方法,包括name、age、money以及money方法。

需要注意的是,實(shí)例對(duì)象的__dict__屬性只能訪問(wèn)和修改其自身的屬性和方法,而無(wú)法訪問(wèn)其所屬類(lèi)的屬性和方法。如果需要訪問(wèn)類(lèi)的屬性和方法,可以通過(guò)類(lèi)的__dict__屬性來(lái)實(shí)現(xiàn)。

例如,我們可以通過(guò)訪問(wèn)Person.__dict__來(lái)查看類(lèi)Person的所有屬性和方法:

print(yongge .__dict__)

輸出結(jié)果為:

{'__module__': '__main__', '__init__': , 'money': , '__dict__': , '__weakref__': , '__doc__': None}

上述輸出結(jié)果中,除了__init__、say_hello和__dict__之外,還包括其他一些特殊屬性和方法。通過(guò)查看類(lèi)的__dict__,我們可以獲取到類(lèi)的所有成員。

(2) 使用dir()函數(shù)

除了訪問(wèn)對(duì)象的__dict__屬性外,我們還可以使用dir()函數(shù)來(lái)查看對(duì)象的屬性和方法。

dir()函數(shù)返回一個(gè)包含對(duì)象所有屬性和方法名稱(chēng)的列表。它不僅可以用于普通對(duì)象,還可以用于模塊、類(lèi)和內(nèi)置類(lèi)型等。

例如,下面的代碼展示了如何使用dir()函數(shù)查看對(duì)象的屬性和方法:

print(dir(p1))

輸出結(jié)果為:

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__

str__', '__subclasshook__', '__weakref__', 'age', 'gender', 'hometown', 'name', 'say_hello']

從輸出結(jié)果中,我們可以看到對(duì)象p1的屬性和方法的名稱(chēng)列表。

(3) 使用__slots__ 屬性

在默認(rèn)情況下,Python 類(lèi)的實(shí)例會(huì)使用一個(gè)字典來(lái)存儲(chǔ)它們的屬性。這種方式對(duì)于屬性很少的對(duì)象來(lái)說(shuō)可能會(huì)浪費(fèi)空間。特別是在創(chuàng)建大量實(shí)例時(shí),這種空間消耗會(huì)變得更明顯。

為了解決這個(gè)問(wèn)題,我們可以通過(guò)在類(lèi)定義中使用__slots__來(lái)覆蓋默認(rèn)的__dict__行為。slots__是一個(gè)特殊屬性,它接受一個(gè)屬性名稱(chēng)的序列,并且在每個(gè)實(shí)例中只為這些屬性保留足夠的空間來(lái)存儲(chǔ)屬性值。因?yàn)闆](méi)有為每個(gè)實(shí)例創(chuàng)建__dict,所以可以節(jié)省空間。

class YongeGe:
    # 定義 __slots__屬性,讓類(lèi)實(shí)例只能綁定 __slots__中指定的屬性,且不能添加其他屬性
    __slots__ = ('name', 'money')

    def __init__(self, name_, money_):
        self.name = name_
        self.money = money_


if __name__ == '__main__':
    yongge = YongeGe('勇哥', 100)
    print(yongge.name) 
    setattr(yongge, 'new_attr', 100) # 輸出:AttributeError: 'YongeGe' object has no attribute 'new_attr'

從上面的代碼可以看到,在類(lèi)中綁定了__slots__后,會(huì)限制類(lèi)實(shí)例的靈活性,不能動(dòng)態(tài)添加新的屬性,所以在使用這玩意的時(shí)候,要仔細(xì)想想要靈活還是要內(nèi)存?

(4) 自定義屬性訪問(wèn)

還可以通過(guò)定義一些特殊方法來(lái)自定義類(lèi)實(shí)例的屬性訪問(wèn)行為。這些特殊方法可以控制屬性的獲取、設(shè)置和刪除操作。

  • __getattribute__ 方法:獲取一個(gè)屬性時(shí),Python 會(huì)首先調(diào)用該方法。我們可以在這個(gè)方法中自定義屬性的獲取行為。例如,可以在方法中檢查屬性是否存在,并返回相應(yīng)的值。
def __getattribute__(self, data):
    value = super().__getattribute__(data)
    return value
  • setattr 方法:設(shè)置一個(gè)屬性時(shí),Python 會(huì)調(diào)用該方法。我們可以在這個(gè)方法中自定義屬性的設(shè)置行為。例如,可以在方法中對(duì)屬性進(jìn)行類(lèi)型檢查,然后使用 super().setattr() 方法設(shè)置屬性的值。 
def __setattr__(self, key, value):
    super().__setattr__(key, value)
  • __delattr__ 方法:刪除一個(gè)屬性時(shí),Python 會(huì)調(diào)用該方法。我們可以在這個(gè)方法中自定義屬性的刪除行為。例如,可以在方法中執(zhí)行一些清理操作或拋出異常。
def __delattr__(self, item):
    super().__delattr__(item)
  • __getattr__ 方法:獲取一個(gè)不存在的屬性時(shí),Python 會(huì)調(diào)用該方法。我們可以在這個(gè)方法中自定義對(duì)不存在屬性的處理邏輯。例如,可以返回默認(rèn)值或者拋出異常。
def __getattr__(self, item):
    pass

以上是一些常用的自定義屬性訪問(wèn)的方法。瞧瞧下面語(yǔ)句的執(zhí)行順序:

class MyClass:
    def __init__(self):
        self._data = {}

    def __getattribute__(self, name):
        # 自定義獲取屬性的行為
        if name == 'attribute1':
            return 'Custom Value'
        elif name == 'attribute2':
            return self._data[name]  # 注意,這里會(huì)繼續(xù)執(zhí)行一次 __getattribute__
        else:
            return super().__getattribute__(name)

    def __setattr__(self, name, value):
        # 自定義設(shè)置屬性的行為
        if name == 'attribute2':
            print("__setattr__", name, value)
            self._data[name] = value + 10
        else:
            super().__setattr__(name, value)

    def __delattr__(self, name):
        # 自定義刪除屬性的行為
        if name == 'attribute3':
            self._data.pop(name, None)
        else:
            super().__delattr__(name)

    def __getattr__(self, name):
        # 處理不存在的屬性
        return f'Attribute "{name}" does not exist.'


if __name__ == '__main__':
    obj = MyClass()
    obj.attribute2 = 5
    res = obj.attribute2
    print(res)  # 輸出: __setattr__ attribute2 5 ;15

    print(obj.attribute1)  # 輸出: Custom Value

    del obj.attribute3
    print(obj.attribute3)  # 輸出: Attribute "attribute3" does not exist.

在上面的示例中,我們創(chuàng)建了一個(gè)名為 MyClass 的類(lèi),其中定義了 __getattribute__、__setattr__、

__delattr__ 和 __getattr__ 四個(gè)方法來(lái)自定義屬性訪問(wèn)行為。通過(guò)在這些方法中編寫(xiě)相應(yīng)的邏輯,我們可以控制屬性的獲取、設(shè)置和刪除操作,從而實(shí)現(xiàn)自定義的屬性訪問(wèn)行為。

通過(guò)自定義屬性訪問(wèn),我們可以更靈活地控制類(lèi)實(shí)例的屬性操作,滿足特定的需求,并增強(qiáng)代碼的可讀性和可維護(hù)性。

(5) 使用getattr()、setattr()和hasattr()函數(shù)

除了查看對(duì)象的屬性和方法外,我們還可以使用getattr()、setattr()和hasattr()函數(shù)來(lái)動(dòng)態(tài)地訪問(wèn)和修改對(duì)象的屬性。

  • getattr(obj, attr)函數(shù)用于獲取對(duì)象obj的屬性attr的值。
  • setattr(obj, attr, value)函數(shù)用于設(shè)置對(duì)象obj的屬性attr的值為value。
  • hasattr(obj, attr)函數(shù)用于檢查對(duì)象obj是否具有屬性attr,如果有返回True,否則返回False。

這些函數(shù)提供了一種靈活的方式來(lái)操作對(duì)象的屬性,特別適用于需要在運(yùn)行時(shí)根據(jù)條件訪問(wèn)或修改屬性的情況。

例如,我們可以通過(guò)調(diào)用getattr()函數(shù)來(lái)獲取對(duì)象的屬性值:

name_value = getattr(yongge, "name")
print(name_value)

輸出結(jié)果為:

勇哥

上述代碼中,我們使用getattr(yongge, "name")來(lái)獲取對(duì)象p1的name屬性的值。

類(lèi)似地,我們可以使用setattr()函數(shù)來(lái)設(shè)置對(duì)象的屬性值:

setattr(yongge, "age", 40)
print(yongge.age)

輸出結(jié)果為:

40

上述代碼中,我們使用setattr(yongge, "age", 40)將對(duì)象yongge的age屬性值設(shè)置為30,然后再次打印yongge.age,可以看到屬性值已被修改。

另外,我們還可以使用hasattr()函數(shù)來(lái)檢查對(duì)象是否具有某個(gè)屬性:

has_money = hasattr(yongge, "money")
print(has_money)

輸出結(jié)果為:

True

使用hasattr(yongge, "money")檢查對(duì)象yongge是否具有money屬性,結(jié)果為T(mén)rue,說(shuō)明對(duì)象具有該屬性。

通過(guò)上述幾種方法,我們可以方便地進(jìn)行屬性自省,查看和修改對(duì)象的屬性,從而更好地理解和操作代碼。

3. 來(lái)點(diǎn)實(shí)際場(chǎng)景

假設(shè)我們正在開(kāi)發(fā)一個(gè)電商網(wǎng)站,需要處理用戶購(gòu)物車(chē)的相關(guān)邏輯。購(gòu)物車(chē)中的商品信息以字典的形式存儲(chǔ)在用戶對(duì)象的屬性中。我們需要編寫(xiě)一個(gè)函數(shù),用于計(jì)算購(gòu)物車(chē)中商品的總價(jià)值。

定義一個(gè)User類(lèi),包含一個(gè)cart屬性用于存儲(chǔ)購(gòu)物車(chē)中的商品信息:

class User:
    def __init__(self, name):
        self.name = name
        self.cart = {}

    def add_to_cart(self, item, price):


        self.cart[item] = price

定義一個(gè)calculate_cart_value()函數(shù),用于計(jì)算購(gòu)物車(chē)中商品的總價(jià)值。在函數(shù)內(nèi)部,我們可以通過(guò)屬性自省來(lái)獲取購(gòu)物車(chē)中的商品信息,并計(jì)算總價(jià)值:

def calculate_cart_value(user):
    cart = user.__dict__.get("cart", {})
    total_value = sum(cart.values())
    return total_value

在上述代碼中,我們使用user.__dict__.get("cart", {})來(lái)獲取購(gòu)物車(chē)信息,如果用戶對(duì)象中不存在cart屬性,則返回一個(gè)空字典。然后,我們使用sum(cart.values())來(lái)計(jì)算購(gòu)物車(chē)中商品價(jià)格的總和。

下面是使用上述代碼的示例:

# 創(chuàng)建用戶對(duì)象
user = User("勇哥")

# 添加商品到購(gòu)物車(chē)
user.add_to_cart("apple", 10)
user.add_to_cart("banana", 5)
user.add_to_cart("orange", 8)

# 計(jì)算購(gòu)物車(chē)總價(jià)值
total_value = calculate_cart_value(user)
print(total_value)  # 輸出: 23

通過(guò)使用屬性自省,我們可以方便地訪問(wèn)購(gòu)物車(chē)信息,并計(jì)算總價(jià)值。屬性自省還是挺重要的,面試也問(wèn)得多,實(shí)在不會(huì)用也要背好飛機(jī)大炮的制作流程。但是這個(gè)玩意也不要濫用喲,頻繁動(dòng)態(tài)訪問(wèn),會(huì)有一定的性能開(kāi)銷(xiāo)喲~


當(dāng)前文章:Python屬性自?。荷钊肓私鈱傩栽L問(wèn)與限制
分享網(wǎng)址:http://www.5511xx.com/article/dpgshho.html