实现自定义属性类

在我们教程的前一章中,我们学习了如何在类中创建和使用属性。主要目标是将它们理解为摆脱显式 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=<function Robot.city at 0x000002825C9420D8>, fset=None, fdel=None, doc=None
doc 设置为 city 方法的 docstring
<class '__main__.chatty_property'>
__init__ 调用:)
fget=<function Robot.city at 0x000002825C9420D8>, fset=<function Robot.city at 0x000002825C9425E8>, fdel=None, doc= 机器人的城市属性 
robo  = 机器人(“柏林” 

输出:

'city' 将被设置
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值