如何解决非数据描述符的实际使用?
我已经阅读了有关描述符的文档并且我了解它们的用途,但我并没有真正了解非数据描述符的用法。
解决方法
我将首先简要解释什么是描述符,然后我将重点介绍与经典查找的三个主要区别,最后给出非数据描述符的一些实际应用(用法)。
如您所知,如果一个对象定义了以下方法之一:__get__()
、__set__()
或 __delete__()
,我们可以将其视为描述符。
- 如果它只定义了
__get__()
方法,我们称之为非数据 描述符。 - 如果它定义了
__set__()
或__delete__()
,我们称它为数据 描述符。
访问数据(数据查找)时使用非数据描述符。
我们将采用文档 (https://docs.python.org/3/howto/descriptor.html) 中提供的示例:
创建一个类:
class A:
x = 5
a = A()
print(a.x)
这里 x
的值是通过在对象的字典中查找获得的。
在本例中,x
的值存储在内存中。
现在,我们将创建一个名为“十”的非数据描述符:
class Ten:
def __get__(self,obj,objtype=None):
return 10
class A:
x = 5
y = Ten()
a = A()
print(a.y)
第一个主要区别:这里,y
不是通过在对象字典中查找获得的。相反,它调用描述符“十”的 __get__()
方法,该方法返回值 10
。
第二个主要区别:另一个重要区别是 10
在创建对象时没有存储在内存中。当调用 __get__()
方法时,值 10
是动态计算的。我们称之为“动态查找”。
现在,我们了解了使用或不使用非数据描述符之间的主要基本区别,我们可以更深入。
首先, 在上面的例子中,使用描述符并不是很有用(因为我们可以只使用数据属性或创建一个 getter 方法),事实上,当您只想使用第一种查找类型(通过对象的字典)时,您应该更喜欢得到一个常数。
第三个主要区别: 当您使用描述符时,您可以控制对该描述符的数据访问:该类将不再控制它。这是一个巨大的差异。数据访问是外包的。 您可以将描述符视为管理对实例数据的访问的一种方式。当您不使用描述符时,管理器就是类本身。当您使用描述符时,描述符控制访问数据时将执行的操作。当您使用描述符时,您将这项工作委托给描述符。我认为第三个区别是理解非数据描述符的实际应用的关键。
这在许多用例中都很有用:
例如,假设您必须编写 20 个类,并且对于这些类,您必须记录对特定数据的访问:而不是编写代码行来在每个类中写入日志,您只需编写一个非数据描述符并在需要时在所有类中使用它。 这是非常有用的。您将编写更少的代码行,因此您将限制犯错误/创建错误的可能性以及调试时间。您也将确保使用相同描述符的类之间的行为一致。
关于非数据描述符的知识当然不止这些,但我认为这些要点是帮助理解它们的一些实际应用的关键点。
这就是非数据描述符的全部内容。
我将在其他描述符(数据描述符)上添加一个注释:从我在上一个示例中所说的(使用日志),我们开始看到描述符在 Python 中的主要应用之一。
和很多 cs 工程师/开发人员一样,我最喜欢的爱好是不花时间调试代码。
避免这种情况的一种好做法是在错误发生之前检查代码中的不同内容,我们称之为“健全性检查”。例如,我们将要检查参数:检查它们的类型,避免“越界错误”或 ZeroDivionErrors 等,并在适当的时候引发异常。 为此,我们可以使用描述符。 我们可以使用数据描述符,而不是编写一行行代码来检查每个类的每个属性的每个参数,以避免不必要的重复。 因此,假设对于一个项目,您将在许多类中拥有许多属性,这些属性必须遵守一些约束,例如:它们的类型必须是 int 或 float,它们的值必须是正数,但小于 1000 等,而不是编写谓词并在任何地方引发异常,您只需编写一次所有这些代码并在需要的地方使用它。
这个答案和你的问题与数据描述符无关,所以我到此为止。可以在此处参考 Python 的文档以获取更多详细信息:https://docs.python.org/3/howto/descriptor.html#custom-validators。仅供参考,描述符可以影响内存、存储、删除、查找,并有助于了解 Python 内部的工作方式。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。