数据属性和方法属性的区别

新手上路,请多包涵
阅读 469
2 个回答

属性是使用点语法在另一个对象上查找的变量: obj.attribute 。 Python 的设计方式、属性查找可以做各种各样的事情,如果您不真正了解正在发生的事情,那么这种多样性有时会导致错误(这是您链接到的文档警告的内容)。

最基本的问题是,属性查找可以找到存储在对象实例字典中的值,也可以从对象的类(或基类,如果存在继承)中找到某些内容。方法是存储在类中的函数,但您通常通过在实例上查找它们来使用它们(它“绑定”方法,在调用方法时将对象作为第一个参数插入)。

什么时候检查什么的确切顺序有点复杂(我在 另一个问题的答案中 描述了完整的过程),但在最基本的层面上,实例属性通常优先于类属性。

如果同时存在同名的实例属性和类属性,通常只能访问实例属性。如果这是无意的,这可能会非常混乱。

考虑以下代码:

 class Foo(object):
    def __init__(self, lst):
        self.lst = lst

    def sum(self):
        self.sum = sum(self.lst)
        return self.sum

f = Foo([1,2,3])

print(f.sum())
print(f.sum())

在这段代码的底部,我们进行了两次相同的调用。第一个工作得很好,但第二个会引发异常。

这是因为我们第一次查找 f.sum 我们在 Foo 类中找到了一个方法。我们可以毫无问题地调用该方法。问题来自于 sum 方法将其计算结果( self.lst 中的元素总和)分配给一个实例属性也命名为 sum .这从视图中隐藏了 sum 方法。

当第二个 f.sum() 调用查找 f.sum 时,它找到包含整数 6 的实例属性,而不是预期的方法。一个整数是不可调用的,所以我们得到一个异常。

当然,解决方案是不要对方法和属性使用相同的名称。上面的代码是一个非常简单的例子。在更复杂的代码中由这类事情引起的错误可能更难找出。

如果您正在编写向不太了解的对象添加属性的代码,则应小心避免使用通用名称。如果您正在编写一个 mixin 类,请考虑在属性名称中使用两个前导下划线来触发 Python 的名称修改,它正是为这种情况而设计的。


附录:文档试图区分数据和非数据描述符也有可能。方我不知道该语言被更广泛地使用。这两种描述符之间的重要区别在于数据描述符(如 property )在检查实例字典中的普通实例变量 之前 得到处理。如上所述,非数据描述符(如方法)仅在检查实例字典 后才 得到处理,因此它们可以被存储在实例上的数据遮蔽。

原文由 Blckknght 发布,翻译遵循 CC BY-SA 4.0 许可协议

属性是指缺少与对象绑定的更好词的任何事物,例如:

 class Dog:
    def __init__(self):
        self.name = "Rufus"

    def bark(self):
        print "Woof Woof!"

在这种情况下,数据属性是名称,它只是一个绑定到 Dog 实例的值。至于方法属性,一个答案是树皮方法,因为它与其说是一个值,不如说是一个动作。就像英语一样。数据属性顾名思义;它是数据,它只是一个属性。一个方法是一个过程,一个动作,而这正是方法属性。

原文由 Malik Brahimi 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题