Какова цель себя?

Какова цель self слово в Python? Я понимаю, что это относится к конкретному объекту, созданному из этого класса, но я не понимаю, почему его нужно явно добавлять в каждую функцию в качестве параметра. Для иллюстрации, в Ruby я могу сделать это:

class myClass
    def myFunc(name)
        @name = name
    end
end

Что я понимаю, довольно легко. Однако в Python мне нужно включить self:

class myClass:
    def myFunc(self, name):
        self.name = name

Кто-нибудь может рассказать мне об этом? Это не то, с чем я столкнулся в своем (по общему признанию ограниченном) опыте.

26 ответов

Решение

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

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

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

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

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

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

ClassA.methodA(ObjectA, arg1, arg2)

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

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

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; то, что вы пишете, это методы класса, которые должны принимать экземпляр в качестве первого параметра. И, следовательно, вам нужно будет явно указать параметр экземпляра где-нибудь.

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

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

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

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

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

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

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: []

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

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 )

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

Следующие выдержки взяты из документации Python о себе:

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

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

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

Как и все другие причины, о которых уже говорилось, это упрощает доступ к переопределенным методам; ты можешь позвонить Class.some_method(inst),

Пример того, где это полезно:

class C1(object):
    def __init__(self):
         print "C1 init"

class C2(C1):
    def __init__(self): #overrides C1.__init__
        print "C2 init"
        C1.__init__(self) #but we still want C1 to init the class too
>>> C2()
"C2 init"
"C1 init"

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

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

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

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

Тем не менее, объектный метод, который требует, чтобы вы сделали переменную, которая является животным, в этом случае нуждается в аргументе 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 всего класса. ПОМНИТЕ: Если у вас есть переменная внутри метода, self не будет работать. Эта переменная просто существует только во время работы этого метода. Для определения полей (переменных всего класса) вы должны определить их вне методов класса.

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

Прежде всего, 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

Код здесь

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

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

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

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

1: использование самообъяснения

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

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

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 аргумент обязателен.

Взгляните на следующий пример, который четко объясняет цель 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 используется / необходим для различения экземпляров

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

Дело в том, что при разработке python альтернативы вряд ли будут работать. Python предназначен для определения методов или функций в контексте, где оба неявных this (а-ля Java/C++) или явный @ (а-ля рубин) не сработает. Давайте рассмотрим пример с явным подходом с соглашениями 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 Я думаю).

Self действует как текущее имя объекта или экземпляр класса.

# Self explanation.


 class classname(object):

    def __init__(self,name):

        self.name=name
        # Self is acting as a replacement of object name.
        #self.name=object1.name

   def display(self):
      print("Name of the person is :",self.name)
      print("object name:",object1.name)


 object1=classname("Bucky")
 object2=classname("ford")

 object1.display()
 object2.display()

###### Output 
Name of the person is : Bucky
object name: Bucky
Name of the person is : ford
object name: Bucky

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

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

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

Ключевое слово self содержит ссылку на класс, и вам решать, хотите вы его использовать или нет, но если вы заметили, всякий раз, когда вы создаете новый метод в python, python автоматически напишет для вас ключевое слово self. Если вы выполните некоторые исследования и разработки, вы заметите, что если вы создадите, скажем, два метода в классе и попытаетесь вызвать один из них внутри другого, он не распознает метод, если вы не добавите self (ссылку на класс).

class testA:
def __init__(self):
    print('ads')
def m1(self):
    print('method 1')
    self.m2()
def m2(self):
    print('method 2')

Приведенный ниже код вызывает неразрешимую справочную ошибку.

class testA:
def __init__(self):
    print('ads')
def m1(self):
    print('method 1')
    m2()  #throws unresolvable reference error as class does not know if m2 exist in class scope
def m2(self):
    print('method 2')

Теперь давайте посмотрим на пример ниже

class testA:
def __init__(self):
    print('ads')
def m1(self):
    print('method 1')
def m2():
    print('method 2')

Теперь, когда вы создаете объект класса testA, вы можете вызвать метод m1(), используя объект класса, подобный этому, поскольку метод m1() включил ключевое слово self

obj = testA()
obj.m1()

Но если вы хотите вызвать метод m2(), поскольку у него нет ссылки на себя, вы можете вызвать m2 () напрямую, используя имя класса, как показано ниже

testA.m2()

Но продолжайте практиковать, чтобы жить с ключевым словом self, поскольку у него есть и другие преимущества, такие как создание глобальной переменной внутри и так далее.

selfнеизбежно

Был только вопрос должен self быть неявным или явным.Guido van Rossumрешил этот вопрос, сказавself должен остаться.

Так где жеselfжить?

Если бы мы просто придерживались функционального программирования, нам бы не понадобилось self, Как только мы входим в ООП Python, мы находим self там.

Вот типичный вариант использования class C с методом m1

class C:
    def m1(self, arg):
        print(self, ' inside')
        pass

ci =C()
print(ci, ' outside')
ci.m1(None)
print(hex(id(ci))) # hex memory address

Эта программа выведет:

<__main__.C object at 0x000002B9D79C6CC0>  outside
<__main__.C object at 0x000002B9D79C6CC0>  inside
0x2b9d79c6cc0

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


Обратите внимание, что существует три различных типа методов класса:

  • статические методы (читай: функции),
  • методы класса,
  • методы экземпляра (упомянуто).

Слово «я» относится к экземпляру класса.

      class foo:
      def __init__(self, num1, num2):
             self.n1 = num1 #now in this it will make the perimeter num1 and num2 access across the whole class
             self.n2 = num2
      def add(self):
             return self.n1 + self.n2 # if we had not written self then if would throw an error that n1 and n2 is not defined and we have to include self in the function's perimeter to access it's variables

Из документов,

Особенность методов в том, что объект-экземпляр передается как первый аргумент функции. В нашем примере вызовx.f() в точности эквивалентен MyClass.f(x). В общем случае вызов метода со списком из n аргументов эквивалентен вызову соответствующей функции со списком аргументов, который создается путем вставки объекта экземпляра метода перед первым аргументом.

перед этим связанный фрагмент,

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

x = MyClass()

Я бы сказал, что для Python, по крайней мере, параметр self можно рассматривать как заполнитель. Взгляните на это:

class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age

p1 = Person("John", 36)

print(p1.name)
print(p1.age)

В этом случае Self и многие другие использовались в качестве метода сохранения значения имени. Однако после этого мы используем p1, чтобы назначить его используемому классу. Затем, когда мы печатаем его, мы используем то же ключевое слово p1.

Надеюсь, это поможет Python!

мои маленькие 2 цента

В этом классе Person мы определили метод init с self, и здесь интересно отметить, что расположение в памяти как переменной self, так и переменной экземпляра p одинаковое. <__main__.Person object at 0x106a78fd0>

      class Person:

    def __init__(self, name, age):
        self.name = name 
        self.age = age 

    def say_hi(self):
        print("the self is at:", self)
        print((f"hey there, my name is {self.name} and I am {self.age} years old"))

    def say_bye(self):
        print("the self is at:", self)
        print(f"good to see you {self.name}")

p = Person("john", 78)
print("the p is at",p)
p.say_hi()  
p.say_bye() 

поэтому, как объяснено выше, переменная self и instance являются одним и тем же объектом.

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

Другие вопросы по тегам