python 动态属性和特性
文章目錄
- 1. 使用動態屬性轉換數據
- 2. @property
- 2.1 help() 文檔
- 3. 特性工廠函數
- 4. 屬性刪除操作
- 5. 處理屬性的重要屬性和函數
- 5.1 處理屬性的內置函數
- 5.2 處理屬性的特殊方法
learn from 《流暢的python》
1. 使用動態屬性轉換數據
- 在 Python 中,數據的屬性和處理數據的方法統稱屬性(attribute)。其實,方法只是可調用的屬性
- 我們還可以創建特性 (property)
- 處理無效屬性名, 例如內置的關鍵字, keyword.iskeyword
修改類的構造函數:
def __init__(self, mapping):self.__data = {}for k,v in mapping.items():if keyword.iskeyword(k): # 如果是關鍵字,則增加下劃線后綴k += "_"self.__data[k] = v- 無效的命名,str.isidentifier()
改名
def __init__(self, mapping):self.__data = {}for k,v in mapping.items():if keyword.iskeyword(k):k += "_"if not k.isidentifier(): # 不是合法的命名,改之k = "_" + kself.__data[k] = v print(grad._2name) # Jim Bo- __init__ 方法其實是 “初始化方法”。真正的構造方法是 __new__(但是幾乎不需要自己編寫)
2. @property
https://www.liaoxuefeng.com/wiki/1016959663602400/1017502538658208
請利用 @property 給一個Screen對象加上width和height屬性,以及一個只讀屬性resolution
- 特性都是類屬性,但是特性管理的其實是實例屬性的存取
obj.attr 這樣的表達式不會從 obj 開始尋找 attr,而是從 obj.__class__ 開始,而且,僅當類中沒有名為 attr 的特性時,Python 才會在 obj 實例中尋找。
這條規則不僅適用于特性, 還適用于一整類描述符——覆蓋型描述符(overriding descriptor)
2.1 help() 文檔
使用裝飾器創建 property 對象時,讀值方法(有 @property 裝飾器 的方法)的文檔字符串作為一個整體,變成特性的文檔
>>> class Foo:@propertydef bar(self):'''說明文檔'''return self.__dict__['bar']@bar.setterdef bar(self, val):self.__dict__['bar'] = val>>> help(Foo) Help on class Foo in module __main__:class Foo(builtins.object)| Data descriptors defined here:| | __dict__| dictionary for instance variables (if defined)| | __weakref__| list of weak references to the object (if defined)| | bar| 說明文檔>>> help(Foo.bar) Help on property:說明文檔- 經典寫法,傳入 doc 參數
3. 特性工廠函數
為了減少編寫 getter,setter,可以使用特性工廠函數
def quantity(storage_name):def qty_getter(instance):return instance.__dict__[storage_name]def qty_setter(instance, value):if value > 0:instance.__dict__[storage_name] = valueelse:raise ValueError("value must be > 0")return property(qty_getter, qty_setter) class LineItem:weight = quantity('weight') # 使用特性工廠函數定義weight類屬性price = quantity('price') # price 屬性def __init__(self, description, weight, price):self.description = descriptionself.weight = weight # 激活屬性,確保不為負數和0self.price = pricedef subtotal(self):return self.weight * self.price # 使用特性中存儲的值line1 = LineItem("name1", 8, 13.5) print(line1.weight, line1.price) # 8 13.5 print(sorted(vars(line1).items())) # [('description', 'name1'), ('price', 13.5), ('weight', 8)]weight 特性 覆蓋了 weight 實例屬性,因此對 self.weight 或 obj.weight 的 每個引用都由特性函數處理,只有直接存取 __dict__ 屬性才能跳過特性的處理邏輯
4. 屬性刪除操作
del 操作,刪除屬性很少見,但是 python 支持該操作
class BlackKnight:def __init__(self):self.members = ['an arm','another arm','a leg','another leg']self.phrases = ["'Tis but a scratch.","It's just a flesh wound.","I'm invincible!","All right, we'll call it a draw."]@propertydef member(self):print("next member is:")return self.members[0]@member.deleterdef member(self):text = 'BLACK KNIGHT (loses {})\n-- {}'print(text.format(self.members.pop(0), self.phrases.pop(0)))knight = BlackKnight() print(knight.member) # next member is: # an arm del knight.member # BLACK KNIGHT (loses an arm) # -- 'Tis but a scratch. del knight.member # BLACK KNIGHT (loses another arm) # -- It's just a flesh wound. del knight.member # BLACK KNIGHT (loses a leg) # -- I'm invincible! del knight.member # BLACK KNIGHT (loses another leg) # -- All right, we'll call it a draw. del knight.member # IndexError: pop from empty list- 經典寫法,fdel 參數設置刪除函數
- 如果不使用特性,還可以實現低層特殊的 __delattr__ 方法處理 刪除屬性 的操作
5. 處理屬性的重要屬性和函數
- __class__ 對象所屬類的引用(即 obj.__class__ 與 type(obj) 的作用相 同)
Python 的某些特殊方法,例如 __getattr__,只在對象的類中尋找,而不在實例中尋找 - __dict__ 一個映射,存儲對象或類的可寫屬性。
有 __dict__ 屬性的對象, 任何時候都能隨意設置新屬性
如果類有 __slots__ 屬性,它的實例可能沒有 __dict__ 屬性 - __slots__
類可以定義這個這屬性,限制實例能有哪些屬性
__slots__ 屬性 的值是一個字符串組成的元組,指明允許有的屬性
如果 __slots__ 中沒有 '__dict__',那么該類的實例沒有 __dict__ 屬性,實例只允許有指定名稱的屬性
5.1 處理屬性的內置函數
- dir([object])
列出對象的大多數屬性,dir 函數也不會列出類的幾個特殊屬性,例如 __mro__、__bases__ 和 __name__
- getattr(object, name[, default])
從 object 對象中獲取 name 字符串對應的屬性
獲取的屬性可能來自 對象所屬的類或超類
如果沒有指定的屬性,getattr 函數拋出 AttributeError 異常,或者返回 default 參數的值(如果設定了這個參數的話) - hasattr(object, name),調用上面的函數,看是否返回異樣
- setattr(object, name, value),可能會創建一個新屬性,或者 覆蓋現有的屬性
- vars([object]),返回 object 對象的 __dict__ 屬性
如果實例所屬的類定義了 __slots__ 屬性,實例沒有 __dict__ 屬性,那么 vars 函數不能處理 那個實例
5.2 處理屬性的特殊方法
-
使用點號或內置的 getattr、hasattr 和 setattr 函數存取屬性都會 觸發下述列表中相應的特殊方法
-
但是,直接通過實例的 __dict__ 屬性讀寫屬性不會觸發這些特殊方法,通常會使用這種方式 跳過特殊方法
-
特殊方法不會被同名實例屬性 遮蓋
總結
以上是生活随笔為你收集整理的python 动态属性和特性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 主成分分析(PCA)和基于核函数的主成分
- 下一篇: websocket python爬虫_p