}的类。这个对象有两个用户提供的属性(C++中的“成员”);java中的“字段或属性或方法”;在Java中,“字段或方法”)。其中一个名为data,它存储整数值42。另一个名为method,它存储一个函数对象。(Python还自动添加了几个属性。)
不过,这些属性仍然不是对象的一部分。从根本上说,一个对象只是多个名称(属性名称)的组合,直到你找到不能再分割的东西。因此,值可以在类的不同实例之间共享,甚至在不同类的对象之间共享,如果您有意设置的话。
让我们创建一个实例:x = Example()
现在我们有一个名为x的单独对象,它是Example的实例。data和method实际上并不是对象的一部分,但是我们仍然可以通过x查找它们,因为Python在幕后有一些魔力。特别是当我们查找method时,我们将得到一个“绑定方法”(当我们调用它时,x将自动作为self参数传递,如果我们直接查找Example.method则不会发生这种情况)。
当我们尝试使用x.data时会发生什么?
当我们检查它的时候,它首先在物体中被抬起。如果在对象中找不到它,Python将在类中查找。
但是,当我们将赋给x.data时,Python将在对象上创建一个属性。它将而不是替换类的属性。
这允许我们进行对象初始化。Python将在创建新实例(如果存在)时自动对其调用类‘__init__方法。在这种方法中,我们可以简单地分配给属性来设置每个对象上该属性的初始值:class Example:
name = "Ignored"
def __init__(self, name):
self.name = name
# rest as before
现在我们必须在创建Example时指定name,并且每个实例都有自己的name。每当我们查找实例的.name时,Python将忽略类属性Example.name,因为首先会找到实例的属性。
最后一个警告:修改(突变)和赋值不同耳鼻喉科的东西!
在Python中,字符串是不可变的。它们不能修改。当你这样做时:a = 'hi '
b = a
a += 'mom'
不要更改原始的“hi”字符串。这在Python中是不可能的。相反,您创建一个新的字符串'hi mom',并使a不再是'hi '的名称,而是开始成为'hi mom'的名称。我们还将b作为'hi '的名称,在重新应用a名称之后,b仍然是'hi '的名称,因为'hi '仍然存在并且没有更改。
但列表可以更改:a = [1, 2, 3]
b = a
a += [4]
现在b也是[1,2,3,4],因为我们为b命名的同一个东西命名了a,然后我们改变了那个东西。我们没有为a命名创建一个新列表,因为Python只是以不同的方式对待+=列表。
这对对象很重要,因为如果您将列表作为类属性,并使用实例来修改列表,那么更改将在所有其他实例中“可见”。这是因为(a)数据实际上是类对象的一部分,而不是任何实例对象;(b)因为您正在修改列表而不是执行简单的赋值,所以没有创建隐藏类属性的新实例属性。