Python - 为什么在类中使用"self"?

88

这两个类有什么区别?

class A():
    x=3

class B():
    def __init__(self):
        self.x=3

有任何显著的区别吗?


6
不,这不是一个重复的副本。 - user3850
1
@hop:有趣的说法,但您并没有提供任何例子或证据表明它不是重复内容。为什么这么说? - S.Lott
2
@S.Lott - 哎呀?另一个问题是在问为什么我们需要明确传递 self。而这个问题是在询问类和实例变量的区别。 - Dana
1
@S.Lott 这不是同一个问题。我在提问之前甚至看了那个问题。 - ryeguy
2
@S.Lott:68282是一个无用的问题,关于为什么必须将self作为方法的第一个参数显式地放置;而这个问题询问的是类成员和实例成员之间的区别。S.Lott,我非常喜欢你在SO上的贡献,但这一次你错了。 - user3850
5个回答

147

A.x 是一个类变量。 Bself.x 是一个实例变量。

也就是说,Ax 在实例之间是共享的。

通过可以修改的列表更容易演示它们之间的区别:

#!/usr/bin/env python

class A:
    x = []
    def add(self):
        self.x.append(1)

class B:
    def __init__(self):
        self.x = []
    def add(self):
        self.x.append(1)

x = A()
y = A()
x.add()
y.add()
print("A's x:", x.x)

x = B()
y = B()
x.add()
y.add()
print("B's x:", x.x)

输出

A's x: [1, 1]
B's x: [1]

8
也许您还可以发布脚本的输出结果,这样人们就可以看到区别,而不必自己复制和运行脚本... - Martin
2
Python中的self是否等同于Java中的this呢?请原谅我的新手问题。 - Jean Azzopardi
2
@Jean - 是的,有点像 - self 只是实例方法的第一个参数的常规名称 - Python 显式地将当前实例作为实例方法的第一个参数传递给实例方法。但它与 Java 的 this 执行相同的工作。 - Douglas Leeder
@Jean Azzopardi: self几乎就像Java(和c ++)中的this。Self很简单地被要求使用;这有时是由Java编译器推理出来的(其他情况下则是必需的)。 - S.Lott
@Douglas Leeder - 没问题。 - UnkwnTech
只是一个快速提示:您可以重新分配变量以将其与类变量解耦。即,将add()更改为“self.x=self.x+[1]”。 - Deestan

61

只是一件小事情: self 实际上只是一个随意选择的单词,每个人都使用它,但你也可以使用 thisfoomyself 或者任何你想要的其他单词,它只是类的每个非静态方法的第一个参数。这意味着 self 这个词不是语言构造而只是一个名称:

>>> class A:
...     def __init__(s):
...        s.bla = 2
... 
>>> 
>>> a = A()
>>> a.bla
2

2
为什么这是一个答案而不是评论? - Gabriel Petersson

25

A.x是一个类变量,将在A的所有实例之间共享,除非在某个实例中被特别覆盖。 B.x是一个实例变量,每个B的实例都有自己的版本。

我希望以下Python示例可以说明:


    >>> class Foo():
    ...     i = 3
    ...     def bar(self):
    ...             print 'Foo.i is', Foo.i
    ...             print 'self.i is', self.i
    ... 
    >>> f = Foo() # Create an instance of the Foo class
    >>> f.bar()
    Foo.i is 3
    self.i is 3
    >>> Foo.i = 5 # Change the global value of Foo.i over all instances
    >>> f.bar()
    Foo.i is 5
    self.i is 5
    >>> f.i = 3 # Override this instance's definition of i
    >>> f.bar()
    Foo.i is 5
    self.i is 3

18

我曾经用这个例子来解释它

# By TMOTTM

class Machine:

    # Class Variable counts how many machines have been created.
    # The value is the same for all objects of this class.
    counter = 0

    def __init__(self):

        # Notice: no 'self'.
        Machine.counter += 1

        # Instance variable.
        # Different for every object of the class.
        self.id = Machine.counter

if __name__ == '__main__':
    machine1 = Machine()
    machine2 = Machine()
    machine3 = Machine()

    #The value is different for all objects.
    print 'machine1.id', machine1.id
    print 'machine2.id', machine2.id
    print 'machine3.id', machine3.id

    #The value is the same for all objects.
    print 'machine1.counter', machine1.counter
    print 'machine2.counter', machine2.counter
    print 'machine3.counter', machine3.counter

然后输出将为

machine1.id 1
machine2.id 2
machine3.id 3
machine1.counter 3 machine2.counter 3 machine3.counter 3

4

我刚开始学习Python时也很困惑。为了弄清楚它的工作原理,我编写了这段非常简单的代码:

# Create a class with a variable inside and an instance of that class
class One:
    color = 'green'

obj2 = One()


# Here we create a global variable(outside a class suite).
color = 'blue'         

# Create a second class and a local variable inside this class.       
class Two:             
    color = "red"

    # Define 3 methods. The only difference between them is the "color" part.
    def out(self):     
        print(self.color + '!')

    def out2(self):
        print(color + '!')

    def out3(self):
        print(obj2.color + '!')

# Create an object of the class One
obj = Two()

当我们调用out()时,我们得到:
>>> obj.out()

red!

当我们调用out2()时:
>>> obj.out2()

blue!

当我们调用 out3() 时:
>>> obj.out3()

green!

因此,在第一种方法中,self 指定 Python 应该使用属于我们创建的类对象的变量(属性),而不是全局变量(在类外部)。因此它使用 color = "red"。在方法中,Python 隐式地将 self 替换为我们创建的对象的名称(obj)。self.color 的意思是“我正在从 obj 中获取 color="red"”。
在第二种方法中,没有 self 来指定应该从哪个对象获取颜色,因此它获取全局变量 color = 'blue'
在第三种方法中,我们使用了 obj2 而不是 self,它是另一个对象的名称,用来获取 color。它得到了 color = 'green'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接