什么是方法属性和数据属性?他们和他们有什么共同之处有什么区别?
我正在阅读python 2.7.9(https://docs.python.org/2/tutorial/classes.html#random-remarks),突然之间变得难以理解。 我会对它有所了解。
答案 0 :(得分:22)
属性是使用点语法在另一个对象上查找的变量:obj.attribute
。 Python的设计方式,属性查找可以做各种各样的事情,如果你不真正理解发生了什么,这种变化有时会导致错误(这是你链接的文档所警告的)。
最基本的问题是属性查找可以找到存储在对象实例字典中的值,或者它可以从对象的类(或基类,如果继承继续)中找到某些内容。方法是存储在类中的函数,但是通常通过在实例上查找它们来使用它们(“绑定”方法,在调用方法时将对象作为第一个方法插入)。
检查时的确切顺序有点复杂(我在an answer to another question中描述了完整过程),但在最基本的层面上,实例属性通常优先于类属性。
如果存在实例属性和具有相同名称的类属性,则通常只能访问实例属性。如果是无意的话,这可能会非常混乱。
请考虑以下代码:
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的名称修改,这是针对这种情况而设计的。
答案 1 :(得分:9)
属性是缺少绑定到对象的更好单词的任何东西,例如:
class Dog:
def __init__(self):
self.name = "Rufus"
def bark(self):
print "Woof Woof!"
在这种情况下,data属性是名称,它只是绑定到Dog实例的值。至于方法属性,一个答案是树皮方法,因为它不是一个值,而是一个动作。它和英语一样。数据属性与听起来完全一样;它的数据,它只是一个属性。方法是一个过程,一个动作,这正是方法属性。
答案 2 :(得分:3)
以下是对您的问题的直接解释,这有助于我理解属性和方法之间的区别。
类就像是如何构建许多共享特征的对象的一组指令或蓝图。
对象是根据类定义提供的规范构建的数据类型。
属性是值(特征)。将属性视为存储在对象中的变量。
方法是一组指令。方法是与对象相关联的函数。父类定义中包含的任何函数都可以由该类的对象调用。
我希望这会有所帮助。
答案 3 :(得分:2)
属性基本上是您可以instance.attribute_name
执行的任何操作。例如:
class Hello(object):
def __init__(self, word):
self.word = word
def greet(self):
print "Hello: "+self.word
__init__
,greet
和word
都属于属性。我猜想一个方法是在类范围内用def声明的任何东西(而不是做self.func = lambda x:x * x)。在这种情况下,您将进入绑定与未绑定方法等。重要的一点是,当你执行instance.method_name
时,对于一个成员属性,你会得到一个绑定方法,当你调用它时,它将调用原始方法,并将实例作为第一个参数。
此外,在阅读了部分内容后,他们的措辞有些令人困惑/错误。例如,他们说“数据属性覆盖具有相同名称的方法属性”,据我所知,最好将其作为实例属性覆盖具有相同名称的类属性。从我给出的例子中我们将其扩展为:
class Hello(object):
greeting = "Hello: "
def __init__(self, word):
self.word = word
def greet(self):
print self.greeting+self.word
然后我们可以这样做:
>>> a = Hello("world")
>>> a.greeting = "Goodbye "
>>> a.greet()
"Goodbye world"
这是因为我们将greeting的实例属性放在greeting的class属性上。由于类中定义的方法(通常的方式)是类属性,因此它们将被任何实例属性(数据或其他)覆盖。
答案 4 :(得分:0)
属性描述对象,而方法对对象起作用并对其进行更改。