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

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

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

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

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

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

Ответы

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

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

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

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

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

ClassA.methodA(ObjectA, arg1, arg2)

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

Ответ 4

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

enter image description here

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

enter image description here

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

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

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

enter image description here

Ответ 5

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

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

Ответ 6

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

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 )

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

Ответ 7

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

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

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

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

Ответ 8

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

Ответ 9

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

Ответ 10

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

При вызове статического метода в 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

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

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

Ответ 12

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

Ответ 13

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

Код здесь

Ответ 14

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

Ответ 15

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

Ответ 16

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

Ответ 17

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

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

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

Первый аргумент каждого метода класса, включая 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 обязательно.

Ответ 18

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

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

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

Ответ 19

"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"

Ответ 20

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


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

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

Ответ 21

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