亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Python虛擬機(jī)中描述器的王炸應(yīng)用分享

 更新時(shí)間:2023年05月09日 09:45:45   作者:一無是處的研究僧  
本篇文章給大家介紹一下描述器在?python?語言當(dāng)中有哪些應(yīng)用,主要介紹如何使用?python?語言實(shí)現(xiàn)?python?內(nèi)置的?proterty?、staticmethod?和?class?method,需要的可以參考一下

property

當(dāng)你在編寫Python代碼時(shí),你可能會(huì)遇到一些需要通過方法來訪問或設(shè)置的屬性。Python中的 property 裝飾器提供了一種優(yōu)雅的方式來處理這種情況,允許你將這些方法封裝為屬性,從而使代碼更加簡(jiǎn)潔和易于閱讀。在本文中,我將向你介紹 property 裝飾器的工作原理以及如何在你的代碼中使用它。

什么是 property

Python 中的 property 是一種裝飾器,它允許你定義一個(gè)方法,使其看起來像一個(gè)屬性。換句話說,property 允許你以屬性的方式訪問或設(shè)置類的數(shù)據(jù)成員,而不必直接調(diào)用一個(gè)方法。

在 Python 中,屬性通常是一個(gè)對(duì)象的數(shù)據(jù)成員,它們可以通過直接訪問對(duì)象來獲取或設(shè)置。然而,有時(shí)候你可能需要在獲取或設(shè)置屬性時(shí)執(zhí)行某些額外的操作,例如進(jìn)行類型檢查、范圍檢查或計(jì)算屬性等。在這種情況下,使用 property 裝飾器可以讓你以屬性的方式訪問或設(shè)置這些屬性,并在訪問或設(shè)置時(shí)執(zhí)行額外的操作。

如何使用 property

讓我們看一個(gè)簡(jiǎn)單的例子,假設(shè)你正在編寫一個(gè)表示矩形的類,并且你想要在計(jì)算矩形的面積時(shí)執(zhí)行一些額外的操作。你可以使用 property 裝飾器來實(shí)現(xiàn)這個(gè)功能,如下所示:

class Rectangle:
    def __init__(self, width, height):
        self._width = width
        self._height = height
    
    @property
    def width(self):
        return self._width
    
    @width.setter
    def width(self, value):
        if value <= 0:
            raise ValueError("Width must be positive")
        self._width = value
    
    @property
    def height(self):
        return self._height
    
    @height.setter
    def height(self, value):
        if value <= 0:
            raise ValueError("Height must be positive")
        self._height = value
    
    @property
    def area(self):
        return self._width * self._height

在這個(gè)示例中,我們使用 property 裝飾器定義了三個(gè)屬性:width、height和area。每個(gè)屬性都有一個(gè) getter 方法和一個(gè) setter 方法,它們分別負(fù)責(zé)獲取和設(shè)置屬性的值。當(dāng)你使用類的實(shí)例訪問這些屬性時(shí),你會(huì)發(fā)現(xiàn)它們似乎就像是一個(gè)普通的屬性,而不是一個(gè)方法。

注意,getter 方法沒有參數(shù),而 setter 方法接受一個(gè)參數(shù)。當(dāng)你通過類的實(shí)例訪問屬性時(shí),你只需要使用點(diǎn)運(yùn)算符即可訪問這些屬性,就像這樣:

rect = Rectangle(10, 20)
print(rect.width)
print(rect.height)
print(rect.area)

輸出結(jié)果:

10
20
200

你也可以像下面這樣設(shè)置屬性的值:

rect.width = 5
rect.height = 10
print(rect.width)
print(rect.height)
print(rect.area)

輸出結(jié)果如下所示:

5
10
50

在設(shè)置 width 或 height 屬性的值時(shí),會(huì)執(zhí)行對(duì)應(yīng)的 setter 方法進(jìn)行類型檢查和范圍檢查。如果值不符合要求,將會(huì)拋出一個(gè) ValueError 異常。這使得你的代碼更加健壯和可靠。

除了在屬性的 getter 和 setter 方法中執(zhí)行額外的操作外,你還可以使用 property 裝飾器計(jì)算屬性。計(jì)算屬性是指,當(dāng)你訪問屬性時(shí),它不是從類的實(shí)例中獲取數(shù)據(jù),而是基于類的其他數(shù)據(jù)成員進(jìn)行計(jì)算。例如,如果你有一個(gè)表示溫度的類,你可以定義一個(gè)計(jì)算屬性,用于將攝氏度轉(zhuǎn)換為華氏度,如下所示:

class Temperature:
    def __init__(self, celsius):
        self._celsius = celsius
    
    @property
    def celsius(self):
        return self._celsius
    
    @celsius.setter
    def celsius(self, value):
        self._celsius = value
    
    @property
    def fahrenheit(self):
        return (self._celsius * 9/5) + 32

在這個(gè)示例中,我們定義了一個(gè) Temperature 類,它包含一個(gè) celsius 屬性和一個(gè) fahrenheit 屬性。celsius 屬性是一個(gè)普通的屬性,可以直接訪問和設(shè)置。而 fahrenheit 屬性是一個(gè)計(jì)算屬性,它基于 celsius 屬性計(jì)算而來。當(dāng)你訪問 fahrenheit 屬性時(shí),它將自動(dòng)計(jì)算出相應(yīng)的華氏度并返回。你可以會(huì)對(duì)上面的代碼有點(diǎn)疑惑celsius.setter 是什么,他是那里來的,事實(shí)上在它上面的 @property 執(zhí)行之后 celsius 已經(jīng)不再是一個(gè)函數(shù)了,而是一個(gè) property 的類產(chǎn)生的對(duì)象了,因此 celsius.setter 是 property 類中的 setter 屬性了,事實(shí)上他是一個(gè)類的方法了,而裝飾器 @celsius.setter 就是將 def celsius(self, value) 這個(gè)函數(shù)作為參數(shù)傳遞給方法 celsius.setter。

我們介紹了 Python 中的 property 裝飾器,它允許你將方法封裝為屬性,并在訪問或設(shè)置屬性時(shí)執(zhí)行額外的操作。通過使用 property 裝飾器,你可以編寫更加簡(jiǎn)潔、優(yōu)雅和可讀的代碼,同時(shí)使代碼更加健壯和可靠。

property 的本質(zhì)

property 是 python 內(nèi)置的一個(gè)類,注意它是類。在前面的內(nèi)容當(dāng)中我們已經(jīng)詳細(xì)討論過了裝飾器的原理,并且從字節(jié)碼的角度進(jìn)行了分析。因此我們可以很容易理解上面 Temperature 類。我們可以將裝飾器展開:

class Temperature:
    def __init__(self, celsius):
        self._celsius = celsius

    def celsius1(self):
        return self._celsius

    celsius = property(celsius1)

    def celsius2(self, value):
        self._celsius = value

    celsius = celsius.setter(celsius2)

    def fahrenheit(self):
        return (self._celsius * 9 / 5) + 32

    fahrenheit = property(fahrenheit)


if __name__ == '__main__':
    t = Temperature(10)
    print(t.celsius)
    t.celsius = 100
    print(t.celsius)
    print(t.fahrenheit)

上面的程序輸出結(jié)果如下所示:

10
100
212.0

可以看到上面的程序正確的輸出了結(jié)果,符合我們對(duì)與 property 的理解和使用。從上面的分析我們可以看到 property 本質(zhì)就是一個(gè) python 的類,因此我可以完全自己實(shí)現(xiàn)一個(gè)和內(nèi)置的 property 類相同功能的類。

在 python 語言層面實(shí)現(xiàn) property 機(jī)制

具體的實(shí)現(xiàn)代碼如下所示:

class Property:
    "Emulate PyProperty_Type() in Objects/descrobject.c"

    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
        self.fget = fget
        self.fset = fset
        self.fdel = fdel
        if doc is None and fget is not None:
            doc = fget.__doc__
        self.__doc__ = doc
        self._name = ''

    def __set_name__(self, owner, name):
        self._name = name

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        if self.fget is None:
            raise AttributeError(f"property '{self._name}' has no getter")
        return self.fget(obj)

    def __set__(self, obj, value):
        if self.fset is None:
            raise AttributeError(f"property '{self._name}' has no setter")
        self.fset(obj, value)

    def __delete__(self, obj):
        if self.fdel is None:
            raise AttributeError(f"property '{self._name}' has no deleter")
        self.fdel(obj)

    def getter(self, fget):
        prop = type(self)(fget, self.fset, self.fdel, self.__doc__)
        prop._name = self._name
        return prop

    def setter(self, fset):
        prop = type(self)(self.fget, fset, self.fdel, self.__doc__)
        prop._name = self._name
        return prop

    def deleter(self, fdel):
        prop = type(self)(self.fget, self.fset, fdel, self.__doc__)
        prop._name = self._name
        return prop

現(xiàn)在對(duì)上面我們自己實(shí)現(xiàn)的類對(duì)象進(jìn)行使用測(cè)試:

class Rectangle:
    def __init__(self, width, height):
        self._width = width
        self._height = height

    @Property
    def width(self):
        return self._width

    @width.setter
    def width(self, value):
        if value <= 0:
            raise ValueError("Width must be positive")
        self._width = value

    @Property
    def height(self):
        return self._height

    @height.setter
    def height(self, value):
        if value <= 0:
            raise ValueError("Height must be positive")
        self._height = value

    @Property
    def area(self):
        return self._width * self._height


if __name__ == '__main__':
    rect = Rectangle(10, 20)
    print(rect.width)
    print(rect.height)
    print(rect.area)

    rect.width = 5
    rect.height = 10
    print(rect.width)
    print(rect.height)
    print(rect.area)

上面的程序輸出結(jié)果如下所示:

10
20
200
5
10
50

可以看到正確的輸出了結(jié)果。

現(xiàn)在我們來好好分析一下我們?cè)谏厦媸褂玫降淖约簩?shí)現(xiàn)的 Property 類是如何被調(diào)用的,在前面的內(nèi)容當(dāng)中我們已經(jīng)討論過了,只有類屬性才可能是描述器,我們?cè)谑褂?@Property 的時(shí)候是獲取到對(duì)應(yīng)的函數(shù),更準(zhǔn)確的說是獲得對(duì)象的 get 函數(shù),然后使用 @Property 的類當(dāng)中的原來的函數(shù)就變成了 Property 對(duì)象了,后面就可以使用對(duì)象的 setter 方法了。

然后在使用 rect.width 或者 rect.height 方法的時(shí)候就活觸發(fā)描述器的機(jī)制, rect 對(duì)象就會(huì)被傳入到描述器的 __get__方法,然后在這個(gè)方法當(dāng)中將傳入的對(duì)象再傳給之前得到的 fget 函數(shù),就完美的實(shí)現(xiàn)了我們想要的效果。

classmethod 和 staticmethod

在 Python 中,staticmethod 和 classmethod 是兩個(gè)常用的裝飾器,它們分別用于定義靜態(tài)方法和類方法。

staticmethod

staticmethod 是一個(gè)裝飾器,它可以將一個(gè)函數(shù)定義為靜態(tài)方法。靜態(tài)方法與類實(shí)例無關(guān),可以在不創(chuàng)建類實(shí)例的情況下直接調(diào)用,但它們?nèi)匀豢梢酝ㄟ^類名訪問。

下面是一個(gè)簡(jiǎn)單的示例:

class MyClass:
    @staticmethod
    def my_static_method(x, y):
        return x + y

print(MyClass.my_static_method(1, 2))

在這個(gè)示例中,我們定義了一個(gè) MyClass 類,并使用 @staticmethod 裝飾器將 my_static_method 方法定義為靜態(tài)方法。然后我們可以通過 MyClass.my_static_method(1, 2) 直接調(diào)用該方法,而不需要?jiǎng)?chuàng)建 MyClass 的實(shí)例。需要注意的是,靜態(tài)方法沒有對(duì)類或?qū)嵗M(jìn)行任何修改,因此它們通常用于一些獨(dú)立的、無狀態(tài)的函數(shù),或者在類中定義的一些幫助函數(shù)。

那么 staticmethod 是如何在語法層面實(shí)現(xiàn)的呢?這又離不開描述器了,在上面的代碼當(dāng)中我們使用 staticmethod 裝飾函數(shù) my_static_method 然后在類 MyClass 當(dāng)中會(huì)有一個(gè)類 staticmethod 的對(duì)象,且名字為 my_static_method 。我們需要注意到的是上面的過程用一行代碼表示為 my_static_method = staticmethod(my_static_method),傳入的 my_static_method 就是 my_static_method 函數(shù),那么這就很簡(jiǎn)單了,當(dāng)使用 my_static_method 的屬性時(shí)候,我們可以在描述器的函數(shù) __get__ 當(dāng)中直接返回傳入的函數(shù)即可。

我們自己實(shí)現(xiàn)的 StaticMethod 如下所示:

class StaticMethod:
    "Emulate PyStaticMethod_Type() in Objects/funcobject.c"

    def __init__(self, f):
        self.f = f
        f = functools.update_wrapper(self, f)

    def __get__(self, obj, objtype=None):
        return self.f

    def __call__(self, *args, **kwds):
        return self.f(*args, **kwds)

我們使用上面自己實(shí)現(xiàn)的類:

class MyClass(object):
    @StaticMethod
    def demo():
        return "demo"
if __name__ == '__main__':
    a = MyClass()
    print(a.demo())

上面的程序會(huì)輸出字符串 "demo" 。

classmethod

classmethod 是另一個(gè)裝飾器,它可以將一個(gè)函數(shù)定義為類方法。類方法與靜態(tài)方法類似,但它們接收的第一個(gè)參數(shù)是類對(duì)象而不是實(shí)例對(duì)象。類方法通常用于實(shí)現(xiàn)與類有關(guān)的操作,如工廠方法或構(gòu)造函數(shù)。

下面是一個(gè)使用 classmethod 的示例:

class MyClass:
    num_instances = 0
    def __init__(self):
        MyClass.num_instances += 1
    @classmethod
    def get_num_instances(cls):
        return cls.num_instances
obj1 = MyClass()
obj2 = MyClass()
print(MyClass.get_num_instances())

在這個(gè)示例中,我們定義了一個(gè) MyClass 類,它包含一個(gè)類變量 num_instances 和一個(gè)構(gòu)造函數(shù)。然后,我們使用 @classmethod 裝飾器將 get_num_instances 方法定義為類方法,并將 cls 參數(shù)用于訪問類變量 num_instances。

在創(chuàng)建 MyClass 的兩個(gè)實(shí)例后,我們調(diào)用 MyClass.get_num_instances() 來獲取當(dāng)前創(chuàng)建的實(shí)例數(shù)。因?yàn)槲覀兪褂昧祟惙椒ǎ钥梢灾苯油ㄟ^類名調(diào)用該方法。

需要注意的是,類方法可以在類和實(shí)例之間共享,因?yàn)樗鼈兌伎梢栽L問類變量。另外,類方法可以被子類繼承和重寫,因?yàn)樗鼈兘邮盏牡谝粋€(gè)參數(shù)是類對(duì)象,而不是固定的類名。

在小節(jié)中,我們介紹了 Python 中的兩種常用裝飾器,即 staticmethod 和 classmethod。staticmethod 用于定義與類實(shí)例無關(guān)的靜態(tài)方法,而 classmethod 用于定義與類相關(guān)的操作,如工廠方法或構(gòu)造函數(shù)。兩種裝飾器都可以通過類名進(jìn)行訪問,但 classmethod 還可以被子類繼承和重寫,因?yàn)樗鼈兘邮盏牡谝粋€(gè)參數(shù)是類對(duì)象。

需要注意的是,staticmethod 和 classmethod 都可以被類或?qū)嵗{(diào)用,但它們不同的是,classmethod 的第一個(gè)參數(shù)是類對(duì)象,而 staticmethod 沒有這樣的參數(shù)。因此,classmethod 可以訪問類變量,而 staticmethod 不能訪問類變量。

下面是一個(gè)更具體的比較:

class MyClass:
    class_var = 'class_var'
    @staticmethod
    def static_method():
        print('This is a static method')
    @classmethod
    def class_method(cls):
        print('This is a class method')
        print(f'The class variable is: {cls.class_var}')
obj = MyClass()
# 靜態(tài)方法可以被類或?qū)嵗{(diào)用
MyClass.static_method()
obj.static_method()
# 類方法可以被類或?qū)嵗{(diào)用,并且可以訪問類變量
MyClass.class_method()
obj.class_method()

在這個(gè)示例中,我們定義了一個(gè) MyClass 類,并分別定義了靜態(tài)方法和類方法。在調(diào)用靜態(tài)方法時(shí),我們可以使用類名或?qū)嵗M(jìn)行調(diào)用,因?yàn)殪o態(tài)方法與類或?qū)嵗裏o關(guān)。而在調(diào)用類方法時(shí),我們必須使用類名或?qū)嵗M(jìn)行調(diào)用,并且類方法可以訪問類變量。總的來說,staticmethod 和 classmethod 是 Python 中兩個(gè)非常有用的裝飾器,它們可以幫助我們更好地組織和管理代碼。需要根據(jù)實(shí)際情況來選擇使用哪種裝飾器,以便實(shí)現(xiàn)最佳的代碼設(shè)計(jì)和可維護(hù)性。

同樣的道理我們可以實(shí)現(xiàn)自己的 ClassMethod

class ClassMethod:
    "Emulate PyClassMethod_Type() in Objects/funcobject.c"
    def __init__(self, f):
        self.f = f
        functools.update_wrapper(self, f)
    def __get__(self, obj, cls=None):
        if cls is None:
            cls = type(obj)
        return MethodType(self.f, cls)

我們對(duì)上面的代碼進(jìn)行測(cè)試:

class Myclass:
    @ClassMethod
    def demo(cls):
        return "demo"
if __name__ == '__main__':
    a = Myclass()
    print(a.demo())

上面的代碼可以正確的輸出字符串"demo" 。

總結(jié)

在本篇文章當(dāng)中主要給大家介紹了描述器的三個(gè)應(yīng)用,仔細(xì)介紹了這三個(gè)類的使用方法,并且詳細(xì)介紹了如何使用 python 實(shí)現(xiàn)同樣的效果,這對(duì)于我們深入理解 python 面向?qū)ο缶幊谭浅S袔椭?,我們可以理解很多黑科技的?nèi)容,對(duì)于整個(gè)類的語法有更加深入的理解。

以上就是Python虛擬機(jī)中描述器的王炸應(yīng)用分享的詳細(xì)內(nèi)容,更多關(guān)于Python虛擬機(jī)描述器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python 自動(dòng)化常用操作及glob使用大全

    Python 自動(dòng)化常用操作及glob使用大全

    這篇文章主要介紹了Python 自動(dòng)化常用操作,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • python+opencv實(shí)現(xiàn)動(dòng)態(tài)物體追蹤

    python+opencv實(shí)現(xiàn)動(dòng)態(tài)物體追蹤

    這篇文章主要為大家詳細(xì)介紹了python+opencv實(shí)現(xiàn)動(dòng)態(tài)物體的追蹤,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • python?繪制3D圖案例分享

    python?繪制3D圖案例分享

    這篇文章主要介紹了python?繪制3D圖案例分享,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下,希望對(duì)你的學(xué)習(xí)有所幫助
    2022-07-07
  • 詳細(xì)解析Python中的變量的數(shù)據(jù)類型

    詳細(xì)解析Python中的變量的數(shù)據(jù)類型

    這篇文章主要介紹了詳細(xì)解析Python中的變量的數(shù)據(jù)類型,是Python學(xué)習(xí)當(dāng)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-05-05
  • Python基礎(chǔ)之函數(shù)的定義與使用示例

    Python基礎(chǔ)之函數(shù)的定義與使用示例

    這篇文章主要介紹了Python基礎(chǔ)之函數(shù)的定義與使用,結(jié)合實(shí)例形式分析了Python函數(shù)的定義、參數(shù)、變量作用域、返回值等相關(guān)概念與使用技巧,需要的朋友可以參考下
    2019-03-03
  • Python logging簡(jiǎn)介詳解

    Python logging簡(jiǎn)介詳解

    這篇文章主要介紹了Python日志模塊logging簡(jiǎn)介,本文講解了Logger、Handler、Formatter、日志配置管理、通過文件配置管理日志等內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • Python實(shí)現(xiàn)人臉識(shí)別并進(jìn)行視頻跟蹤打碼

    Python實(shí)現(xiàn)人臉識(shí)別并進(jìn)行視頻跟蹤打碼

    這篇文章主要為大家詳細(xì)介紹了如何利用Python實(shí)現(xiàn)人臉識(shí)別并進(jìn)行視頻跟蹤打碼效果,羞羞的畫面統(tǒng)統(tǒng)打上馬賽克,感興趣的小伙伴可以了解一下
    2023-03-03
  • python 利用已有Ner模型進(jìn)行數(shù)據(jù)清洗合并代碼

    python 利用已有Ner模型進(jìn)行數(shù)據(jù)清洗合并代碼

    今天小編就為大家分享一篇python 利用已有Ner模型進(jìn)行數(shù)據(jù)清洗合并代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • Python實(shí)現(xiàn)根據(jù)指定端口探測(cè)服務(wù)器/模塊部署的方法

    Python實(shí)現(xiàn)根據(jù)指定端口探測(cè)服務(wù)器/模塊部署的方法

    這篇文章主要介紹了Python根據(jù)指定端口探測(cè)服務(wù)器/模塊部署的方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2014-08-08
  • python數(shù)據(jù)結(jié)構(gòu):數(shù)據(jù)類型

    python數(shù)據(jù)結(jié)構(gòu):數(shù)據(jù)類型

    這篇文章主要介紹了python數(shù)據(jù)結(jié)構(gòu)中的數(shù)據(jù)類型,在?Python?以及其他所有面向?qū)ο缶幊陶Z言中,類都是對(duì)數(shù)據(jù)的構(gòu)成(狀態(tài))以及數(shù)據(jù)?能做什么(行為)的描述,下面我們就來你看看python數(shù)據(jù)結(jié)構(gòu)中的數(shù)據(jù)類型商務(wù)詳細(xì)介紹,需要的小伙伴可以參考一下
    2021-12-12

最新評(píng)論