婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > Python基礎詳解之描述符

Python基礎詳解之描述符

熱門標簽:荊州云電銷機器人供應商 外呼不封號系統 電信營業廳400電話申請 悟空智電銷機器人6 溫州旅游地圖標注 遼寧400電話辦理多少錢 蘇州電銷機器人十大排行榜 江蘇房產電銷機器人廠家 幫人做地圖標注收費算詐騙嗎

一、描述符定義

描述符是一種類,我們把實現了__get__()、__set__()和__delete__()中的其中任意一種方法的類稱之為描述符。

描述符的作用是用來代理一個類的屬性,需要注意的是描述符不能定義在被使用類的構造函數中,只能定義為類的屬性,它只屬于類的,不屬于實例,我們可以通過查看實例和類的字典來確認這一點。

描述符是實現大部分Python類特性中最底層的數據結構的實現手段,我們常使用的@classmethod、@staticmethd、@property、甚至是__slots__等屬性都是通過描述符來實現的。它是很多高級庫和框架的重要工具之一,是使用到裝飾器或者元類的大型框架中的一個非常重要組件。

如下示例一個描述符及引用描述符類的代碼:

class Descriptors:
 
    def __init__(self, key, value_type):
        self.key = key
        self.value_type = value_type
 
    def __get__(self, instance, owner):
        print("===> 執行Descriptors的 get")
        return instance.__dict__[self.key]
 
    def __set__(self, instance, value):
        print("===> 執行Descriptors的 set")
        if not isinstance(value, self.value_type):
            raise TypeError("參數%s必須為%s" % (self.key, self.value_type))
        instance.__dict__[self.key] = value
 
    def __delete__(self, instance):
        print("===>  執行Descriptors的delete")
        instance.__dict__.pop(self.key)
 
 
class Person:
    name = Descriptors("name", str)
    age = Descriptors("age", int)
 
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
 
person = Person("xu", 15)
print(person.__dict__)
person.name
person.name = "xu-1"
print(person.__dict__)
# 結果:
#     ===> 執行Descriptors的 set
#     ===> 執行Descriptors的 set
#     {'name': 'xu', 'age': 15}
#     ===> 執行Descriptors的 get
#     ===> 執行Descriptors的 set
#     {'name': 'xu-1', 'age': 15}

其中,Descriptors類就是一個描述符,Person是使用描述符的類。

類的__dict__屬性是類的一個內置屬性,類的靜態函數、類函數、普通函數、全局變量以及一些內置的屬性都是放在類__dict__里。

在輸出描述符的變量時,會調用描述符中的__get__方法,在設置描述符變量時,會調用描述符中的__set__方法。

二、描述符的種類和優先級

描述符分為數據描述符和非數據描述符。

至少實現了內置__set__()和__get__()方法的描述符稱為數據描述符;實現了除__set__()以外的方法的描述符稱為非數據描述符。

描述符的優先級的高低順序:類屬性 > 數據描述符 > 實例屬性 > 非數據描述符 > 找不到的屬性觸發__getattr__()。

在上述“描述符定義”章節的例子中,實例person的屬性優先級低于數據描述符Descriptors,所以在賦值或獲取值過程中,均調用了描述符的方法。

class Descriptors:
    def __get__(self, instance, owner):
        print("===> 執行 Descriptors get")
 
    def __set__(self, instance, value):
        print("===> 執行 Descriptors set")
 
    def __delete__(self, instance):
        print("===> 執行 Descriptors delete")
 
 
class University:
    name = Descriptors()
 
    def __init__(self, name):
        self.name = name

類屬性 > 數據描述符

# 類屬性 > 數據描述符
# 在調用類屬性時,原來字典中的數據描述法被覆蓋為 XX-XX
print(University.__dict__)  # {..., 'name': __main__.Descriptors object at 0x7ff8c0eda278>,}
 
University.name = "XX-XX"
print(University.__dict__)  # {..., 'name': 'XX-XX',}

數據描述符 > 實例屬性

# 數據描述符 > 實例屬性
# 調用時會現在實例里面找,找不到name屬性,到類里面找,在類的字典里面找到 'name': __main__.Descriptors object at 0x7fce16180a58>
# 初始化時調用 Descriptors 的 __set__; un.name 調用  __get__
print(University.__dict__)
un = University("xx-xx")
un.name
# 結果:
#     {..., 'name': __main__.Descriptors object at 0x7ff8c0eda278>,}
#     ===> 執行 Descriptors set
#     ===> 執行 Descriptors get

下面是測試 實例屬性、 非數據描述符、__getattr__ 使用代碼

class Descriptors:
    def __get__(self, instance, owner):
        print("===>2 執行 Descriptors get")
 
 
class University:
    name = Descriptors()
 
    def __init__(self, name):
        self.name = name
 
    def __getattr__(self, item):
        print("---> 查找 item = {}".format(item))

實例屬性 > 非數據描述符

# 實例屬性 > 非數據描述符
# 在創建實例的時候,會在屬性字典中添加 name,后面調用 un2.name 訪問,都是訪問實例字典中的 name
un2 = University("xu2")
print(un2.name)  # xu    并沒有調用到  Descriptors 的 __get__
print(un2.__dict__)  # {'name': 'xu2'}
un2.name = "xu-2"
print(un2.__dict__)  # {'name': 'xu-2'}

非數據描述符 > 找不到的屬性觸發__getattr__

# 非數據描述符 > 找不到的屬性觸發__getattr__
# 找不到 name1 使用 __getattr__
un3 = University("xu3")
print(un3.name1)  # ---> 查找 item = name1

三、描述符的應用

使用描述符檢驗數據類型

class Typed:
    def __init__(self, key, type):
        self.key = key
        self.type = type
 
    def __get__(self, instance, owner):
        print("---> get 方法")
        # print("instance = {}, owner = {}".format(instance, owner))
        return instance.__dict__[self.key]
 
    def __set__(self, instance, value):
        print("---> set 方法")
        # print("instance = {}, value = {}".format(instance, value))
        if not isinstance(value, self.type):
            # print("設置name的值不是字符串: type = {}".format(type(value)))
            # return
            raise TypeError("設置{}的值不是{},當前傳入數據的類型是{}".format(self.key, self.type, type(value)))
        instance.__dict__[self.key] = value
 
    def __delete__(self, instance):
        print("---> delete 方法")
        # print("instance = {}".format(instance))
        instance.__dict__.pop(self.key)
 
 
class Person:
    name = Typed("name", str)
    age = Typed("age", int)
 
    def __init__(self, name, age, salary):
        self.name = name
        self.age = age
        self.salary = salary
 
 
p1 = Person("xu", 99, 100.0)
print(p1.__dict__)
p1.name = "XU1"
print(p1.__dict__)
del p1.name
print(p1.__dict__)
# 結果:
#     ---> set 方法
#     ---> set 方法
#     {'name': 'xu', 'age': 99, 'salary': 100.0}
#     ---> set 方法
#     {'name': 'XU1', 'age': 99, 'salary': 100.0}
#     ---> delete 方法
#     {'age': 99, 'salary': 100.0}

四、描述符 + 類裝飾器  (給 Person類添加類屬性)

類裝飾器,道理和函數裝飾器一樣

def Typed(**kwargs):
    def deco(obj):
        for k, v in kwargs.items():
            setattr(obj, k, v)
        return obj
    return deco
 
 
@Typed(x=1, y=2)  # 1、Typed(x=1, y=2) ==> deco   2、@deco ==> Foo = deco(Foo)
class Foo:
    pass
 
 
# 通過類裝飾器給類添加屬性
print(Foo.__dict__)  # {......, 'x': 1, 'y': 2}
print(Foo.x)

使用描述符和類裝飾器給 Person類添加類屬性

"""
描述符 + 類裝飾器
"""
class Typed:
    def __init__(self, key, type):
        self.key = key
        self.type = type
 
    def __get__(self, instance, owner):
        print("---> get 方法")
        # print("instance = {}, owner = {}".format(instance, owner))
        return instance.__dict__[self.key]
 
    def __set__(self, instance, value):
        print("---> set 方法")
        # print("instance = {}, value = {}".format(instance, value))
        if not isinstance(value, self.type):
            # print("設置name的值不是字符串: type = {}".format(type(value)))
            # return
            raise TypeError("設置{}的值不是{},當前傳入數據的類型是{}".format(self.key, self.type, type(value)))
        instance.__dict__[self.key] = value
 
    def __delete__(self, instance):
        print("---> delete 方法")
        # print("instance = {}".format(instance))
        instance.__dict__.pop(self.key)
 
 
def deco(**kwargs):
    def wrapper(obj):
        for k, v in kwargs.items():
            setattr(obj, k, Typed(k, v))
        return obj
    return wrapper
 
 
@deco(name=str, age=int)
class Person:
    # name = Typed("name", str)
    # age = Typed("age", int)
 
    def __init__(self, name, age, salary):
        self.name = name
        self.age = age
        self.salary = salary
 
 
p1 = Person("xu", 99, 100.0)
print(Person.__dict__)
print(p1.__dict__)
p1.name = "XU1"
print(p1.__dict__)
del p1.name
print(p1.__dict__)
# 結果:
#     ---> set 方法
#     ---> set 方法
#     {..., 'name': __main__.Typed object at 0x7f3d79729dd8>, 'age': __main__.Typed object at 0x7f3d79729e48>}
#     {'name': 'xu', 'age': 99, 'salary': 100.0}
#     ---> set 方法
#     {'name': 'XU1', 'age': 99, 'salary': 100.0}
#     ---> delete 方法
#     {'age': 99, 'salary': 100.0}

五、利用描述符自定義 @property

class Lazyproperty:
    def __init__(self, func):
        self.func = func
 
    def __get__(self, instance, owner):
        print("===> Lazypropertt.__get__ 參數: instance = {}, owner = {}".format(instance, owner))
        if instance is None:
            return self
        res = self.func(instance)
        setattr(instance, self.func.__name__, res)
        return self.func(instance)
 
    # def __set__(self, instance, value):
    #     pass
 
 
class Room:
 
    def __init__(self, name, width, height):
        self.name = name
        self.width = width
        self.height = height
 
    # @property  # area=property(area)
    @Lazyproperty  # # area=Lazyproperty(area)
    def area(self):
        return self.width * self.height
 
#  @property 測試代碼
# r = Room("房間", 2, 3)
# print(Room.__dict__)  # {..., 'area': property object at 0x7f8b42de5ea8>,}
# print(r.area)  # 6
 
# r2 = Room("房間2", 2, 3)
# print(r2.__dict__)  # {'name': '房間2', 'width': 2, 'height': 3}
# print(r2.area)
 
# print(Room.area)  # __main__.Lazyproperty object at 0x7faabd589a58>
 
r3 = Room("房間3", 2, 3)
print(r3.area)
print(r3.area)
# 結果(只計算一次):
#     ===> Lazypropertt.__get__ 參數: instance = __main__.Room object at 0x7fd98e3757b8>, owner = class '__main__.Room'>
#     6
#     6

六、property 補充

class Foo:
 
    @property
    def A(self):
        print("===> get A")
 
    @A.setter
    def A(self, val):
        print("===> set A, val = {}".format(val))
 
    @A.deleter
    def A(self):
        print("===> del A")
 
 
f = Foo()
f.A         # ===> get A
f.A = "a"   # ===> set A, val = a
del f.A     # ===> del A
 
 
 
class Foo:
 
    def get_A(self):
        print("===> get_A")
 
    def set_A(self, val):
        print("===> set_A, val = {}".format(val))
 
    def del_A(self):
        print("===> del_A")
 
    A = property(get_A, set_A, del_A)
 
 
f = Foo()
f.A         # ===> get_A
f.A = "a"   # ===> set_A, val = a
del f.A     # ===> del_A

到此這篇關于Python基礎詳解之描述符的文章就介紹到這了,更多相關Python描述符內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • Python描述符descriptor使用原理解析
  • python實現裝飾器、描述符
  • 詳解Python中的Descriptor描述符類
  • Python黑魔法Descriptor描述符的實例解析
  • Python 的描述符 descriptor詳解
  • 解密Python中的描述符(descriptor)
  • 詳解Python描述符的工作原理

標簽:喀什 欽州 三沙 宿遷 黃山 濟南 臺灣 景德鎮

巨人網絡通訊聲明:本文標題《Python基礎詳解之描述符》,本文關鍵詞  Python,基礎,詳解,之,描述,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《Python基礎詳解之描述符》相關的同類信息!
  • 本頁收集關于Python基礎詳解之描述符的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    日韩精品中文字幕在线不卡尤物| 久久色在线观看| 国产精品一级二级三级| 一区二区三区欧美亚洲| 欧美va亚洲va国产综合| 欧美www视频| 欧美mv日韩mv| 国产日产精品一区| 中文在线一区二区| 亚洲国产成人av网| 久久99在线观看| 高清在线成人网| 91欧美一区二区| 在线播放亚洲一区| 亚洲精品成a人| 亚洲国产日日夜夜| 狠狠v欧美v日韩v亚洲ⅴ| 久久99国产精品免费网站| 99久久精品国产观看| 欧美日韩国产一区二区三区地区| 精品99999| 亚洲人成网站精品片在线观看| 五月婷婷另类国产| 国产一区不卡精品| 在线播放欧美女士性生活| 中文字幕不卡的av| 美洲天堂一区二卡三卡四卡视频| a亚洲天堂av| 久久久www免费人成精品| 一区二区三区久久| 成人动漫中文字幕| 久久综合五月天婷婷伊人| 午夜婷婷国产麻豆精品| 欧洲人成人精品| 中文字幕人成不卡一区| 日本伦理一区二区| 欧美精品粉嫩高潮一区二区| 国产精品亲子乱子伦xxxx裸| 日本不卡视频在线观看| 欧美日韩成人综合在线一区二区| 国产免费久久精品| 国产成人精品网址| 久久精品一区四区| av在线不卡电影| 成人免费在线观看入口| 亚洲免费电影在线| 岛国av在线一区| 中文字幕亚洲区| 色域天天综合网| 午夜欧美视频在线观看| 精品国产一区二区亚洲人成毛片| 精品一区二区影视| 国产精品久久久久久妇女6080| 色婷婷综合久久久久中文一区二区 | 欧美精品一区二区三区很污很色的 | 麻豆免费看一区二区三区| 精品盗摄一区二区三区| 一本色道综合亚洲| 美女视频黄a大片欧美| 亚洲免费观看高清完整版在线观看熊 | 亚洲欧洲www| 欧美午夜精品久久久久久孕妇| 最新热久久免费视频| 欧美一区二区免费| 91丨九色丨蝌蚪富婆spa| 琪琪久久久久日韩精品| 久久奇米777| 欧美精品久久天天躁| 99国产精品久久久久久久久久 | 国产毛片精品一区| 亚洲国产一区二区视频| 日韩丝袜情趣美女图片| 色综合天天综合色综合av | 精品999在线播放| 777奇米四色成人影色区| 91丨porny丨国产入口| 一区二区三区国产精品| 国产精品沙发午睡系列990531| 欧美精品一区二区久久婷婷 | 日韩视频免费观看高清完整版| proumb性欧美在线观看| 国产高清不卡一区| 日韩电影网1区2区| 亚洲乱码国产乱码精品精的特点| 日本一区二区三级电影在线观看| 精品国产a毛片| 免费视频一区二区| 日韩专区中文字幕一区二区| 美国毛片一区二区三区| 韩国一区二区视频| 国产精品夜夜嗨| 99精品热视频| 成人美女在线观看| 欧美日韩日日摸| 精品国产伦一区二区三区观看体验| 亚洲国产高清aⅴ视频| 一卡二卡三卡日韩欧美| 久久精品国产精品亚洲精品| 国产福利不卡视频| 欧美色综合天天久久综合精品| 欧美成人福利视频| 亚洲一区二区欧美| 狠狠色丁香久久婷婷综| 日本精品一区二区三区四区的功能| 欧美卡1卡2卡| 亚洲欧美电影院| 国产福利不卡视频| 日韩免费视频线观看| 一区二区三区欧美视频| 91九色02白丝porn| 久久福利视频一区二区| 亚洲福利一区二区三区| 91久久精品一区二区二区| 精品国产免费一区二区三区四区 | 国产麻豆视频一区二区| 在线观看av一区| 国产日韩欧美高清在线| 日韩二区三区在线观看| 国产成人精品一区二区三区四区 | 亚洲视频精选在线| va亚洲va日韩不卡在线观看| 中文字幕av一区二区三区高| 国产成+人+日韩+欧美+亚洲 | 亚洲国产精品久久久久婷婷884| 亚洲一区二区av电影| 欧美日本免费一区二区三区| 亚洲狠狠丁香婷婷综合久久久| av高清不卡在线| 图片区小说区国产精品视频| 在线观看91av| 国产成人av福利| 免费精品视频最新在线| 26uuu久久天堂性欧美| 成人开心网精品视频| 无码av中文一区二区三区桃花岛| 91精品福利在线一区二区三区| 国产一区二区三区国产| 亚洲欧洲精品成人久久奇米网| 欧美丝袜丝交足nylons| 久久国产精品第一页| 中文字幕在线观看不卡| 91精品视频网| 99国产欧美另类久久久精品 | 色噜噜久久综合| 国产高清精品网站| 国产成人午夜片在线观看高清观看| 久久精品国产久精国产爱| 美国欧美日韩国产在线播放| 精品影视av免费| 成人a级免费电影| 国产亚洲欧美一级| 欧美性大战久久久久久久蜜臀 | 7777精品久久久大香线蕉| 国产成人精品一区二区三区网站观看| 国产调教视频一区| 日韩一区二区影院| 欧美日韩国产电影| 欧美日韩综合在线免费观看| 99re66热这里只有精品3直播| 国产91丝袜在线18| 久久精品国产亚洲aⅴ| 蜜桃av一区二区| 久久爱www久久做| 美国毛片一区二区| 日日夜夜免费精品视频| 日韩国产欧美在线播放| 蜜桃精品视频在线| 国产一区二区三区日韩| 国模冰冰炮一区二区| 成人永久aaa| 欧美亚男人的天堂| 日本精品一级二级| 日韩精品一区二区三区中文精品 | 久久综合九色综合97_久久久| 久久免费看少妇高潮| 国产精品毛片久久久久久| 亚洲视频在线一区观看| 日本一不卡视频| 本田岬高潮一区二区三区| 色综合久久88色综合天天6| 欧美成人高清电影在线| 国产精品嫩草影院av蜜臀| 中文字幕中文乱码欧美一区二区| 国产精品进线69影院| 亚洲成人免费影院| 国内精品伊人久久久久影院对白| 国产制服丝袜一区| 欧美三级电影精品| 中文字幕av不卡| 亚洲宅男天堂在线观看无病毒| 久久福利资源站| 欧美久久久久免费| 亚洲欧美自拍偷拍色图| 激情图片小说一区| 欧美一区二区播放| 性欧美疯狂xxxxbbbb| 欧日韩精品视频| 一区二区三区欧美视频| 色综合久久99| 亚洲电影在线播放|