Python - навіщо використовувати “self” у класі?


82

Чим відрізняються ці 2 класи?

class A():
    x=3

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

Чи є якась суттєва різниця?


6
ні, це не дублікат.

1
@hop: Цікаве твердження, але ви не надали жодного прикладу чи доказу, що це не дублікат. Чому ти це кажеш?
S.Lott

2
@ S.Lott - так? Інше питання - запитання, чому нам потрібно явно передавати себе. Цей запитує про різницю, оскільки змінні класу та екземпляра.
Дана

1
@ S.Lott Це не одне питання. Я навіть подивився на нього, перш ніж запитати.
ryeguy

2
@ S.Lott: 68282 - марне запитання про те, чому ви повинні явно ставити self як перший аргумент методів; це питання задає питання про різницю між членами класу та екземпляра. С.Лотт, мені дуже подобається ваш внесок у SO, але цього разу ви помиляєтесь.

Відповіді:


137

A.xє змінною класу . B's 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? Будь ласка, вибачте за нубитність
Жан Аццопарді,

2
@Jean - Так-іш - self має бути лише загальноприйнятим ім'ям, що дається першому параметру методів екземпляра - і python явно передає поточний екземпляр методів екземпляра як перший аргумент методам екземпляра. Але вона виконує ту ж роботу, що і Java
Дуглас Лідер,

@Jean Azzopardi: self - це майже як Java (і c ++). Просто потрібно себе; це іноді обгрунтовує компілятор Java (в інший раз це потрібно.)
S.Lott

@Douglas Leeder - не проблема.
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

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

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'.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.