在我们教程的前一章中,我们学习了如何在类中创建和使用属性。主要目标是将它们理解为摆脱显式 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' 将被设置
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)