Python - зачем использовать «я» в классе?

82

Чем отличаются эти 2 класса?

class A():
    x=3

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

Есть ли существенная разница?

ржаной
источник
6
нет, это не дубликат.
1
@hop: Интересное утверждение, но вы не представили никаких примеров или доказательств того, что это не дубликат. Почему ты это сказал?
S.Lott
2
@ S.Lott - А? Другой вопрос - зачем нам явно передавать self. Этот спрашивает о разнице, потому что переменные класса и экземпляра.
Дана
1
@ S.Lott Это не тот вопрос. Я даже посмотрел на это, прежде чем спросить.
ryeguy
2
@ S.Lott: 68282 - бесполезный вопрос о том, почему вы должны явно указывать self в качестве первого аргумента методов; этот вопрос касается разницы между членами класса и экземпляра. С.Лотт, мне очень нравится ваш вклад в SO, но на этот раз вы ошибаетесь.

Ответы:

137

A.xявляется переменной класса . Bs self.x- это переменная экземпляра .

т.е. A«s xраспределяется между экземплярами.

Было бы легче продемонстрировать разницу с помощью чего-то, что можно изменить, например, списка:

#!/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
Может быть, также опубликуйте вывод своего скрипта, тогда можно будет увидеть разницу, не копируя и не запуская его самостоятельно ...
Мартин
2
Является ли сам Python эквивалентным Java this? Извините за нубизм, пожалуйста
Жан Аззопарди
2
@Jean - Да-иш - self должно быть просто обычным именем, присвоенным первому параметру методов экземпляра - а python явно передает текущий экземпляр методов экземпляра в качестве первого аргумента методам экземпляра. Но он выполняет ту же работу, что и этот Java
Дуглас Лидер,
@Jean Azzopardi: self почти как Java (и c ++) this. Я просто требуется; это иногда аргументируется компилятором Java (в других случаях это требуется)
S.Lott
@ Дуглас Лидер - без проблем.
UnkwnTech
56

В качестве примечания: selfна самом деле это просто случайно выбранное слово, которое все используют, но вы также можете использовать this,foo или myselfили что - нибудь еще вы хотите, это только первый параметр каждого метода , не статического для класса. Это означает, что слово self- это не языковая конструкция, а просто имя:

>>> class A:
...     def __init__(s):
...        s.bla = 2
... 
>>> 
>>> a = A()
>>> a.bla
2
Андре
источник
1
Почему это ответ, а не комментарий
Габриэль Петерссон
23

Ax - это переменная класса, которая будет использоваться всеми экземплярами A, если это не будет специально переопределено в экземпляре. Bx - это переменная экземпляра, и каждый экземпляр 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
TerrorBite
источник
17

Я объяснял это на этом примере

# 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
TMOTTM
источник
3

Я только начал изучать 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означает "Я получаю color="red"отobj "

Во втором методе нет selfуказания объекта, из которого должен быть взят цвет, поэтому он получает глобальный color = 'blue'.

В третьем методе вместо того, что selfмы использовали obj2- имя другого объекта, из которого нужно получить color. Это получается color = 'green'.

Ябэ-даби
источник