实现自定义属性类

实现自定义属性类,第1张

实现自定义属性

在我们教程的前一章中,我们学习了如何在类中创建和使用属性。主要目标是将它们理解为摆脱显式 getter 和 setter 并拥有简单类接口的一种方式。这对于大多数程序员和实际用例来说通常就足够了,他们不需要更多。

如果您想了解更多关于“财产”如何运作的信息,您可以与我们更进一步。通过这样做,您可以提高编码技能并更深入地了解和理解 Python。我们将看看“属性”装饰器可以在 Python 代码中实现的方式。(实际是用C代码实现的!)这样 *** 作起来就更清晰了。一切都基于描述符协议,我们将在后面解释。

我们定义了一个名为“our_property”的类,这样它就不会被误认为是现有的“property”类。此类可以像“真实”属性类一样使用。

class  our_property : 
    """
        出于教育目的模拟属性类"""

    def  __init__ ( self ,  
                 fget = None ,  
                 fset = None ,  
                 fdel = None ,  
                 doc = None ): 
        """ 'our_decorator' 的属性
        fget
            函数用于获取
            属性值
        fset
            函数用于设置
            属性值
        fdel
            函数用于删除
            属性
        doc 
            docstring 
        """ 
        self. fget  =  fget 
        self 。fset  =  fset 
        self 。FDEL  =  FDEL
        如果 文档 是 无 和 fget 是 不 无:
            DOC  =  fget 。__doc__
        自我。__doc__  = 文档

    DEF  __get__ (自, OBJ , OBJTYPE =无):
        如果 OBJ 是 无:
            返回 自
        如果 自我。fget  is  None : 
            raise  AttributeError ( "unreadable attribute" ) 
        return  self 。fget (对象)

    def  __set__ ( self ,  obj ,  value ):
        如果 self . fset 为 None :
            引发 AttributeError ( "can't set attribute" ) 
        self 。fset (对象, 值)

    def  __delete__ ( self ,  obj ):
        如果 self . fdel 是 None :
            引发 AttributeError ( "can't delete attribute" ) 
        self 。fdel (对象)

    def  getter ( self ,  fget ):
        返回 类型( self )( fget ,  self . fset ,  self . fdel ,  self . __doc__ )

    def  setter ( self ,  fset ):
        返回 类型( self )( self . fget ,  fset ,  self . fdel ,  self . __doc__ )

    高清 删除器(自我, FDEL ):
        收益 型(自)(自我。fget , 自我。FSET , FDEL , 自我。__doc__ )

我们需要另一个类来使用先前定义的类并演示属性类装饰器的工作原理。为了延续 Python 教程前几章的传统,我们将再次编写一个 Robot 类。我们将在这个示例类中定义一个属性来演示我们之前定义的属性类或更好的“our_decorator”类的用法。当您运行代码时,您可以看到__init__'our_property' 将被称为 'fget' 设置为对 'city' 的 'getter' 函数的引用。属性“city”是“our_property”类的一个实例。'our'property' 类为 setter 功能提供了另一个装饰器 'setter'。我们将其应用于“@city.setter”

 机器人类:
    
    def  __init__ ( self ,  city ): 
        self . 城市 = 城市
        
    @our_property 
    def  city ( self ): 
        print ( "The Property 'city' will be return now:" ) 
        return  self 。__城市
    
    @城市。setter 
    def  city ( self ,  city ): 
        print ( "'city' will be set" ) 
        self . __ 城市= 城市

'Robot.city' 是 'our_property' 类的一个实例,如下所示:

类型(机器人。城市)

输出:

__main__.our_property

如果您将行 '@our_property' 更改为 '@property',程序的行为将完全相同,但它将使用原始 Python 类 'property' 而不是我们的 'our_property' 类。我们将在以下 Python 代码中创建 Robot 类的实例:

打印(“实例化一个根和设置‘城市’到‘柏林’” )
ROBO  = 机器人(“柏林” )
打印(“值是:” , ROBO 。城市)
打印(“我们的机器人现在移到法兰克福:” )
机器人。city  =  "Frankfurt" 
print ( "值是:" ,  robo . city )

输出:

实例化一个根并将“城市”设置为“柏林”
'city' 将被设置
现在将返回属性“城市”:
值是:柏林
我们的机器人现在搬到法兰克福:
'city' 将被设置
现在将返回属性“城市”:
价值是:法兰克福

让我们用一些打印函数让我们的属性实现更健谈,看看发生了什么。出于显而易见的原因,我们还将名称更改为“chatty_property”:

class  chatty_property : 
    """
        出于教育目的模拟属性类"""

    def  __init__ ( self ,  
                 fget = None ,  
                 fset = None ,  
                 fdel = None ,  
                 doc = None ):
        
        自我。fget  =  fget 
        self 。fset  =  fset 
        self 。fdel  =  fdel
        打印(“ n __init__ 调用方式:)” )
        打印(f “fget= { fget } , fset= { fset } , fdel= { fdel } , doc= { doc } " )
        如果 doc 是 None 并且 fget 是 不是 无:
            打印( f "doc 设置为{ fget . __name__ }方法的docstring " ) 
            doc  =  fget 。__doc__
        自我。__doc__  = 文档

    DEF  __get__ (自, OBJ , OBJTYPE =无):
        如果 OBJ 是 无:
            返回 自
        如果 自我。fget  is  None : 
            raise  AttributeError ( "unreadable attribute" ) 
        return  self 。fget (对象)

    def  __set__ ( self ,  obj ,  value ):
        如果 self . fset 为 None :
            引发 AttributeError ( "can't set attribute" ) 
        self 。fset (对象, 值)

    def  __delete__ ( self ,  obj ):
        如果 self . fdel 是 None :
            引发 AttributeError ( "can't delete attribute" ) 
        self 。fdel (对象)

    def  getter ( self ,  fget ):
        返回 类型( self )( fget ,  self . fset ,  self . fdel ,  self . __doc__ )

    高清 二传手(自我, FSET ):
        打印(类型(个体经营))
        的返回 类型(个体经营)(自我。fget , FSET , 自我。FDEL , 自我。__doc__ )

    高清 删除器(自我, FDEL ):
        收益 型(自)(自我。fget , 自我。FSET , FDEL , 自我。__doc__ )
 机器人类:
    
    def  __init__ ( self ,  city ): 
        self . 城市 = 城市
        
    @chatty_property 
    def  city ( self ): 
        """ 机器人的城市属性 """ 
        print ( "The Property 'city' will be returned now:" ) 
        return  self 。__城市
    
    @城市。setter 
    def  city ( self ,  city ): 
        print ( "'city' will be set" ) 
        self . __ 城市= 城市

输出:

__init__ 调用:)
fget=, fset=None, fdel=None, doc=None
doc 设置为 city 方法的 docstring

__init__ 调用:)
fget=, fset=, fdel=None, doc= 机器人的城市属性 
robo  = 机器人(“柏林” )

输出:

'city' 将被设置

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5689802.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存