Зачем мне нужно self перед атрибутом объекта класса в Python? [Дубликат]

Метод может быть вызван следующим образом. Есть также больше возможностей (проверьте отражение api), но это самый простой:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.junit.Assert;
import org.junit.Test;

public class ReflectionTest {

    private String methodName = "length";
    private String valueObject = "Some object";

    @Test
    public void testGetMethod() throws SecurityException, NoSuchMethodException, IllegalArgumentException,
            IllegalAccessException, InvocationTargetException {
        Method m = valueObject.getClass().getMethod(methodName, new Class[] {});
        Object ret = m.invoke(valueObject, new Object[] {});
        Assert.assertEquals(11, ret);
    }



}
896
задан kmario23 18 January 2018 в 02:47
поделиться

20 ответов

Причина, по которой вам нужно использовать self., заключается в том, что Python не использует синтаксис @ для ссылки на атрибуты экземпляра. Python решил делать методы таким образом, чтобы автоматически использовать экземпляр, к которому принадлежит этот метод, , переданный , но не получен : первым параметром методов является экземпляр метода вызывается. Это делает методы полностью такими же, как и функции, и оставляет фактическое имя для использования до вас (хотя self является конвенцией, и люди обычно будут хмуриться вам, когда вы используете что-то другое.) self не является особым для код, это просто еще один объект.

Python мог бы сделать что-то еще, чтобы отличить нормальные имена от атрибутов - специальный синтаксис, например Ruby, или требовать объявления, подобные C ++ и Java, или, возможно, что-то еще более отличающееся - - но это не так. Python все для того, чтобы сделать вещи явными, делая это очевидным, что к чему, и хотя он не делает это целиком повсюду, он делает это, например, атрибуты. Вот почему назначение атрибуту экземпляра должно знать, какой экземпляр присваивается, и поэтому ему нужно self..

587
ответ дан Thomas Wouters 16 August 2018 в 11:55
поделиться
  • 1
    @Georg: cls относится к объекту класса, а не к экземпляру объекта – SilentGhost 25 April 2010 в 21:33
  • 2
    Исключением является то, что он не является «обычным». метод или «метод экземпляра», но что-то еще - метод класса или статический метод или просто простая функция :) – Thomas Wouters 25 April 2010 в 21:55
  • 3
    @SilentGhost: На самом деле имя первого параметра - это то, что вы хотите. В методах класса используется соглашение cls, а self обычно используется, например, методами. Если бы я хотел, я мог бы использовать self для методов класса и cls для методов экземпляра. Я мог бы также использовать bob и fnord, если бы мне понравилось. – SingleNegationElimination 22 November 2010 в 23:13
  • 4
    Мне интересно, что сообщество не выбрало this вместо self. Есть ли у self некоторая история, о которой я не знаю на более старых языках программирования? – Julius 12 December 2012 в 22:46
  • 5
    @Julius. self пришел из соглашений Modula-3, см. этот ответ для получения дополнительной информации об этом выборе. (Отказ от ответственности: его шахта). – Bakuriu 20 September 2013 в 20:07
  • 6
    – Wes Turner 8 November 2014 в 19:42

Использование аргумента, обычно называемое self, не так сложно понять, как это необходимо? Или о том, почему прямо упоминать об этом? Это, я полагаю, является большим вопросом для большинства пользователей, которые ищут этот вопрос, или если это не так, у них, безусловно, будет тот же вопрос, что и в дальнейшем, изучая python. Я рекомендую им прочитать эти две блоги:

1: Использование self explain

Обратите внимание, что это не ключевое слово.

< blockquote>

Первый аргумент каждого метода класса, включая init, всегда является ссылкой на текущий экземпляр класса. По соглашению, этот аргумент всегда называется self. В методе init сам относится к вновь созданному объекту; в других методах класса, это относится к экземпляру, метод которого был вызван. Например, приведенный ниже код такой же, как приведенный выше код.

2: Почему у нас это так и почему мы не можем исключить его как аргумент, например Java, и вместо этого есть ключевое слово

. Еще одна вещь, которую я хотел бы добавить, - необязательный аргумент self позволяет мне объявлять статические методы внутри класса, не записывая self.

Примеры кода:

class MyClass():
    def staticMethod():
        print "This is a static method"

    def objectMethod(self):
        print "This is an object method which needs an instance of a class, and that is what self refers to"

PS: Это работает только в Python 3.x.

В предыдущих версиях вы должны явно добавить декоратор @staticmethod в противном случае аргумент self является обязательным.

1
ответ дан Bugs Buggy 16 August 2018 в 11:55
поделиться

Его использование похоже на использование ключевого слова this в Java, то есть для ссылки на текущий объект.

10
ответ дан ChickenFeet 16 August 2018 в 11:55
поделиться

В методе __init__ self относится к вновь созданному объекту; в других классах он ссылается на экземпляр, метод которого был вызван.

self, как имя, является только соглашением , назовите его так, как вы хотите! но при использовании, например, для удаления объекта, вы должны использовать одно и то же имя: __del__(var), где var использовался в __init__(var,[...])

. Вы должны взглянуть на cls, чтобы иметь большую картинку . Это сообщение может быть полезно.

1
ответ дан Community 16 August 2018 в 11:55
поделиться

Прежде всего, self - это условное имя, вы можете поставить вместо него что-то другое (быть последовательным).

Он относится к самому объекту, поэтому, когда вы его используете, вы объявляете что .name и .age являются свойствами объектов Student (обратите внимание, а не на класс Student), которые вы собираетесь создать.

class Student:
    #called each time you create a new Student instance
    def __init__(self,name,age): #special method to initialize
        self.name=name
        self.age=age

    def __str__(self): #special method called for example when you use print
        return "Student %s is %s years old" %(self.name,self.age)

    def call(self, msg): #silly example for custom method
        return ("Hey, %s! "+msg) %self.name

#initializing two instances of the student class
bob=Student("Bob",20)
alice=Student("Alice",19)

#using them
print bob.name
print bob.age
print alice #this one only works if you define the __str__ method
print alice.call("Come here!") #notice you don't put a value for self

#you can modify attributes, like when alice ages
alice.age=20
print alice

Код здесь

2
ответ дан harrypotter0 16 August 2018 в 11:55
поделиться

Допустим, у вас есть класс ClassA, который содержит метод methodA, определенный как:

def methodA(self, arg1, arg2):
    # do something

и ObjectA является экземпляром этого класса.

Теперь, когда вызывается ObjectA.methodA(arg1, arg2), python внутренне преобразует его для вас как:

ClassA.methodA(ObjectA, arg1, arg2)

Переменная self относится к самому объекту.

284
ответ дан hichris123 16 August 2018 в 11:55
поделиться
  • 1
    Я прочитал все остальные ответы и понял, я прочитал этот, и тогда все это имело смысл. – Seth 8 October 2014 в 03:37
  • 2
    Это называется магическим ответом __magic __ () – Rio 3 June 2015 в 19:13
  • 3
    Об этом уже ответили в последней части ответа Дебильского. – SIslam 13 June 2015 в 15:36
  • 4
    Почему бы не сохранить эти кишки внутри, хотя, как Рубин? – Cees Timmerman 21 September 2017 в 18:15
  • 5
    Это должен был быть ответ! Точно и точно – Spandy 12 December 2017 в 02:00

Мне нравится этот пример:

class A: 
    foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: [5]

class A: 
    def __init__(self): 
        self.foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: []
65
ответ дан kame 16 August 2018 в 11:55
поделиться
  • 1
    поэтому vars without self - это просто статические классы класса, например, в java – teddy teddy 7 September 2012 в 20:45
  • 2
    плюшевый плюшевый, ты не совсем прав. Поведение (статическое или нестатическое) зависит не только от self, но и от типа переменной. Попробуйте сделать первый пример с простым целым числом вместо списка. Результат будет совсем другим. – Konstantin 27 March 2014 в 21:18
  • 3
    На самом деле, мой вопрос заключается в том, почему вы разрешаете говорить a.foo в первом примере, а не A.foo? Ясно, что foo принадлежит классу ... – Radon Rosborough 6 August 2014 в 19:29
  • 4
    Вы можете вызывать статические члены из экземпляров объекта на большинстве языков. Почему это удивительно? – Paarth 29 October 2014 в 01:25
  • 5
    @RadonRosborough Потому что в первом примере a и b являются метками (или указателями) для A() (класс). a.foo ссылается на метод класса A().foo. Во втором примере, однако, a становится ссылкой на экземпляр из A(), как и b. Теперь, когда они являются экземплярами вместо самого объекта класса, self позволяет использовать метод foo для экземпляров. – LegendaryDude 12 July 2017 в 17:07

Возьмем простой векторный класс:

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

Мы хотим иметь метод, который вычисляет длину. Как бы это выглядело, если бы мы хотели определить его внутри класса?

    def length(self):
        return math.sqrt(self.x ** 2 + self.y ** 2)

Как это должно выглядеть, когда мы должны определять его как глобальный метод / функцию?

def length_global(vector):
    return math.sqrt(vector.x ** 2 + vector.y ** 2)

Таким образом, вся структура остается прежней. Как я могу это использовать? Если на какой-то момент мы предположим, что мы не записали метод length для нашего класса Vector, мы могли бы это сделать:

Vector.length_new = length_global
v = Vector(3, 4)
print(v.length_new()) # 5.0

Это работает, потому что первый параметр length_global, может быть повторно использован как параметр self в length_new. Это было бы невозможно без явного self.


Другой способ понять необходимость явного self - увидеть, где Python добавляет некоторый синтаксический сахар. Когда вы помните, что в основном вызов, подобный

v_instance.length()

, внутренне преобразован в

Vector.length(v_instance)

, легко увидеть, где находится self. на самом деле не пишите методы экземпляра в Python; то, что вы пишете, это методы класса, которые должны принимать экземпляр в качестве первого параметра. И поэтому вам нужно будет явно указать параметр экземпляра.

384
ответ дан Kevin Johnsrude 16 August 2018 в 11:55
поделиться
  • 1
    Vector.length_new = length_global ... Я действительно начал использовать синтаксис, подобный этому, в объявлениях классов. Всякий раз, когда я только хочу наследовать некоторые из методов из другого класса, я просто явно копирую ссылку на методы. – Jeeyoung Kim 22 November 2010 в 22:37
  • 2
    было бы справедливым сказать, что способ экземпляра python & quot; является просто синтаксическим сахаром статических глобальных методов (как в Java или C ++) с объектом экземпляра, переданным для упаковки нескольких атрибутов? --- ну это наполовину верно, поскольку в полиморфизме более важная цель "этого" (как в java) или "self" заключается в том, чтобы дать правильную реализацию методов. У Python есть это. поэтому вызов myobj.someMethod () равен классу TheClassOfMyObj.someMethod (myobj) в python. обратите внимание, что «TheClassOfMyObj» автоматически вычисляется с помощью python из «self», в противном случае вам нужно было бы это выяснить. – teddy teddy 7 September 2012 в 20:43
  • 3
    Infact - это не только методы экземпляра, но только методы класса, но методы - это просто функции, которые являются членами класса, как показывает Vector.length_new = length_global. – RussW 6 September 2013 в 10:46
  • 4
    «Это работает, потому что первый параметр length_global может быть повторно использован как параметр self в length_new. Это было бы невозможно без явного «я». - все равно будет работать. он будет повторно использоваться для неявного Я ... второй пример - круговое рассуждение - вам нужно явно разместить себя там, потому что python нуждается в явном я. – Karoly Horvath 15 March 2014 в 18:16
  • 5
    @KarolyHorvath: Конечно, также возможно иметь язык с моделью, где внутренне определенные методы не нуждаются в явном я, но внешне определенные методы делают. Но я бы сказал, что существует некоторая последовательность в требовании явного «я» в обоих случаях, что делает его законной причиной для этого. Другие языки могут выбирать разные подходы. – Debilski 16 March 2014 в 16:52

Взгляните на следующий пример, в котором четко объясняется, что цель self

class Restaurant(object):  
    bankrupt = False

    def open_branch(self):
        if not self.bankrupt:
           print("branch opened")

#create instance1
>>> x = Restaurant()
>>> x.bankrupt
False

#create instance2
>>> y = Restaurant()
>>> y.bankrupt = True   
>>> y.bankrupt
True

>>> x.bankrupt
False  

self используется / необходима для различения экземпляров.

2
ответ дан kmario23 16 August 2018 в 11:55
поделиться
  • 1
    Да, я думаю, мы знаем, почему используется сам, но вопрос в том, почему язык заставляет вас явно объявить его. Многие другие языки не требуют этого и языка, который гордится тем, что он краток, вы бы подумали, что они просто предоставят вам переменную за кулисами, чтобы использовать ее как Lua или C ++ (это). – user441521 12 January 2016 в 19:13
  • 2
    @ kmario23 Вы ответили отсюда: pythontips.com/2013/08/07/the-self-variable-in-python-explained Пожалуйста, всегда признавайте оригинальных авторов, отправляя ответы как свои собственные. – geekidharsh 13 April 2018 в 18:12

Следующие фрагменты из документации Python о self :

Как и в Modula-3, для ссылки на элементы объекта нет сокращений [в Python] из его методов: функция метода объявляется с явным первым аргументом, представляющим объект, который предоставляется неявно вызовом.

Часто первый аргумент метода называется self. Это не что иное, как соглашение: имя «я» совершенно не имеет особого значения для Python. Обратите внимание, однако, что, не соблюдая соглашение, ваш код может быть менее читаемым для других программистов на Python, и также возможно, что программа браузера классов может быть написана, которая опирается на такое соглашение.

Для получения дополнительной информации см. учебник по документации Python по классам .

16
ответ дан Matthew Rankin 16 August 2018 в 11:55
поделиться

self является объектной ссылкой на сам объект, поэтому они одинаковы. Методы Python не вызывается в контексте самого объекта. self в Python может использоваться для обработки пользовательских объектных моделей или чего-то еще.

4
ответ дан Ming-Tang 16 August 2018 в 11:55
поделиться

Я продемонстрирую код, который не использует классы:

def state_init(state):
    state['field'] = 'init'

def state_add(state, x):
    state['field'] += x

def state_mult(state, x):
    state['field'] *= x

def state_getField(state):
    return state['field']

myself = {}
state_init(myself)
state_add(myself, 'added')
state_mult(myself, 2)

print( state_getField(myself) )
#--> 'initaddedinitadded'

Классы - это всего лишь способ избежать передачи этой вещи «состояния» все время (и другие приятные вещи, такие как инициализация, класс композиция, редко требуемые метаклассы и поддержка пользовательских методов для переопределения операторов).

Теперь давайте продемонстрируем приведенный выше код, используя встроенный механизм класса python, чтобы показать, как это в основном одно и то же.

class State(object):
    def __init__(self):
        self.field = 'init'
    def add(self, x):
        self.field += x
    def mult(self, x):
        self.field *= x

s = State()
s.add('added')    # self is implicitly passed in
s.mult(2)         # self is implicitly passed in
print( s.field )

[мигрировал мой ответ из дублированного закрытого вопроса]

33
ответ дан ninjagecko 16 August 2018 в 11:55
поделиться
  • 1
    Я хочу, чтобы Python сахарировал обработчиков, а также Ruby. – Cees Timmerman 21 September 2017 в 18:18

'self' используется для ссылки на вновь созданный объект.

, например, если вы объявляете метод в классе по умолчанию, он автоматически принимает экземпляр как первый аргумент.

По соглашению мы называем это «я» в файле python.it просто сильное соглашение. Вы можете назвать это другим именем.

Если вы хотите использовать метод, который не нуждается в доступе к себе, используйте staticmethod:

class TestClass():
   @staticmethod
   def staticMethod(other_arg):
        print "This is a static method"

    def instanceMethod(self,other_arg): #This is instance method
        print "self is instance"

    ##If you want access to the class, but not to the instance, use classmethod:

    @classmethod
    def my_class_method(cls, other_arg):
        print "this is a class method"
0
ответ дан Projesh Bhoumik 16 August 2018 в 11:55
поделиться

Он должен следовать за Python zen «явный лучше, чем неявный». Это действительно ссылка на ваш объект класса. Например, в Java и PHP он называется this.

Если user_type_name является полем вашей модели, вы получаете доступ к нему через self.user_type_name.

17
ответ дан Ry- 16 August 2018 в 11:55
поделиться

это явная ссылка на объект экземпляра класса.

-2
ответ дан SilentGhost 16 August 2018 в 11:55
поделиться
  • 1
    Я не думаю, что это помогает richzilla понять причину этого. – Georg Schölly 25 April 2010 в 21:30
  • 2
    @SilentGhost: вы прибили его. Я впечатлен. если я правильно понимаю: я создаю объект как экземпляр определенного класса, а параметр self относится к этому объекту? Я понимаю, что сам относится неявным образом к самому классу, но было бы здорово, если бы вы объяснили свой ответ немного больше. – BlueTomato 9 October 2017 в 14:51

Это потому, что, кстати, дизайн python вряд ли сработает. Python предназначен для определения методов или функций в контексте, где неявные this (a-la Java / C ++) или явные @ (a-la ruby) не будут работать. Давайте рассмотрим пример с явным подходом с соглашениями python:

def fubar(x):
    self.x = x

class C:
    frob = fubar

Теперь функция fubar не будет работать, так как предположим, что self является глобальной переменной (и в frob также). Альтернативой было бы выполнить метод с замененной глобальной областью (где self - это объект).

Неявный подход будет

def fubar(x)
    myX = x

class C:
    frob = fubar

. Это будет означать, что myX будет интерпретироваться как локальная переменная в fubar (а также в frob). Альтернативой здесь будет выполнение методов с замененной локальной областью, которая сохраняется между вызовами, но это устранит возможность локальных переменных метода.

Однако текущая ситуация работает хорошо:

 def fubar(self, x)
     self.x = x

 class C:
     frob = fubar

здесь, когда вызывается как метод frob, получит объект, по которому он вызывается через параметр self, и fubar все еще можно вызвать с объектом в качестве параметра и работать одинаково (это [] совпадает с C.frob, я думаю).

2
ответ дан skyking 16 August 2018 в 11:55
поделиться

Когда объекты создаются, сам объект передается в параметр self.

enter image description here [/g0]

Из-за этого данные объекта привязаны к объекту. Ниже приведен пример того, как вам может показаться, как выглядят данные каждого объекта. Обратите внимание, что «я» заменяется именем объекта. Я не говорю, что приведенная ниже диаграмма ниже полностью точна, но, надеюсь, она служит цели визуализации использования себя.

enter image description here [/g1]

Объект передается в параметр self, чтобы объект мог сохранять свои собственные данные.

Хотя это может быть не совсем точным, подумайте о процессе создания объекта таким образом: Когда объект создан, он использует класс как шаблон для своих собственных данных и методов. Не передавая свое собственное имя в параметр self, атрибуты и методы в классе оставались бы в качестве общего шаблона и на него не ссылались бы (принадлежат) объекту. Поэтому, передавая имя объекта в параметр self, это означает, что если 100 объектов создаются из одного класса, они могут отслеживать свои собственные данные и методы.

См. Иллюстрацию ниже:

enter image description here [/g2]

153
ответ дан sw123456 16 August 2018 в 11:55
поделиться
  • 1
    Эй, при доступе к атрибутам Боба, например, с помощью «bob.name ()», вы фактически используете bob (). Self.name, так сказать, из « init » правильно? – udarH3 10 August 2015 в 08:31
  • 2
    Когда вы пишете bob.name () в приведенном выше комментарии, вы подразумеваете, что bob имеет метод под названием name () из-за того, что вы добавили скобки после имени. В этом примере, однако, такого метода нет. «bob.name» (который не имеет скобок) напрямую обращается к атрибуту, названному именем из метода init (constructor). Когда вызывается метод вызова bob, это метод, который обращается к атрибуту name и возвращает его в инструкции печати. Надеюсь это поможет. – sw123456 10 August 2015 в 08:48
  • 3
    Нет, вы получаете значение self.name, которое для объекта bob фактически является bob.name, поскольку имя объекта передается в параметр self при его создании (создается экземпляр). Опять же, надеюсь, что это поможет. Не стесняйтесь поднимать главный пост, если он есть. – sw123456 10 August 2015 в 09:18
  • 4
    Имя присваивается self.name при создании экземпляра. После создания объекта все переменные, принадлежащие объекту, имеют префикс «я». Помните, что self заменяется именем объекта, когда он создается из класса. – sw123456 10 August 2015 в 09:23
  • 5
    Вот как вы объясняете вещи! хорошая работа :) – penta 5 November 2017 в 10:44

Я удивлен, что никто не воспитывал Луа. Lua также использует переменную «self», однако ее можно опустить, но использовать. C ++ делает то же самое с «этим». Я не вижу причин, чтобы объявлять «я» в каждой функции, но вы все равно сможете использовать ее так же, как вы можете с помощью lua и C ++. Для языка, который гордится тем, что он краток, странно, что он требует, чтобы вы объявили переменную self.

3
ответ дан user441521 16 August 2018 в 11:55
поделиться

Python не является языком, созданным для объектно-ориентированного программирования, в отличие от Java или C ++.

При вызове статического метода в Python просто записывается метод с регулярными аргументами внутри него.

class Animal():
    def staticMethod():
        print "This is a static method"

Однако объектный метод, требующий от вас сделать переменную, которая является Animal, в этом случае нуждается в аргументе self

class Animal():
    def objectMethod(self):
        print "This is an object method which needs an instance of a class"

. Метод self также используется для обозначения поля переменной внутри класса.

class Animal():
    #animalName made in constructor
    def Animal(self):
        self.animalName = "";


    def getAnimalName(self):
        return self.animalName

В этом случае self относится к переменной animalName для всего класса. ПОМНИТЕ: Если у вас есть переменная внутри метода, я не буду работать. Эта переменная просто существует только тогда, когда этот метод запущен. Для определения полей (переменные всего класса) вы должны определить их OUTSIDE методами класса.

Если вы не понимаете ни слова о том, что я говорю, тогда Google «Объектно-ориентированное программирование». Как только вы это поймете, вам даже не придется задавать этот вопрос:).

11
ответ дан ytpillai 16 August 2018 в 11:55
поделиться
  • 1
    +1 из-за различия между staticMethod() и objectMethod(self). Я хотел бы добавить, что для вызова первого вы сказали бы Animal.staticMethod(), в то время как objectMethod() нуждается в экземпляре: a = Animal(); a.objectMethod() – Laryx Decidua 24 July 2015 в 09:37
  • 2
    То, что вы говорите, не соответствует действительности на 100%. Это просто конвенция. Вы все равно можете вызвать статический метод из созданного объекта. Вы просто не сможете использовать каких-либо членов класса, потому что вы не объявили себя. Я могу даже позвонить Animal.objectMethod (animalObj), чтобы вызвать нестатический. В основном это означает, что статический метод - это только метод, который не использует переменные-члены. Не должно быть необходимости декларировать себя. Думаю, это глупое требование. Языки, такие как Lua и C ++, дают вам переменные obj за кулисами. – user441521 12 January 2016 в 19:20
  • 3
    Единственный ответ, который имеет смысл! Спасибо!!!!!!!!!!!!!!!!!!!!!!! – john 25 July 2017 в 01:47
  • 4
    @ytpillai Irrelevant. Непонятный и неправильный код не должен быть представлен в качестве ответа. – Cees Timmerman 21 September 2017 в 18:34
  • 5
    def getAnimalName, чтобы не сжимать строку, которую вы пытаетесь вернуть, а self ссылается на экземпляр класса, а не на любое поле внутри него. – Cees Timmerman 21 September 2017 в 18:38
17
ответ дан Ry- 6 September 2018 в 05:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: