Какова цель самости?
какова цель self слово в Python? Я понимаю, что это относится к конкретному объекту, созданному из этого класса, но я не могу понять, почему он явно должен быть добавлен к каждой функции в качестве параметра. К примеру, в Ruby я могу сделать это:
class myClass
def myFunc(name)
@name = name
end
end
который я понимаю, довольно легко. Однако в Python мне нужно добавить self:
class myClass:
def myFunc(self, name):
self.name = name
кто-нибудь может мне помочь? Это не то, с чем я столкнулся в своем (по общему признанию, ограниченном) опыт.
19 ответов:
причина, по которой вы должны использовать
self.- Это потому, что Python не использовать@синтаксис для ссылки на атрибуты экземпляра. Python решил сделать методы таким образом, чтобы экземпляр, к которому принадлежит метод, был принят автоматически, но не получил автоматически: первый параметр методов-это экземпляр, на котором вызывается метод. Это делает методы полностью такими же, как функции, и оставляет фактическое имя для использования до вас (хотяselfis конвенция, и люди, как правило, хмурятся на вас, когда вы используете что-то еще.)selfне является особенным для кода, это просто еще один объект.Python мог бы сделать что-то еще, чтобы отличить обычные имена от атрибутов-специальный синтаксис, такой как Ruby, или требующий объявлений, таких как C++ и Java, или, возможно, что-то еще более другое-но это не так. Python все для того, чтобы сделать вещи явными, делая очевидным, что есть что, и хотя он не делает это полностью везде, он делает это, например, атрибуты. Вот почему назначение атрибута экземпляра должно знать, какой экземпляр назначить, и именно поэтому ему нужно
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, можно повторно использовать как
Допустим у вас есть класс
ClassA, который содержит методmethodAопределено как:def methodA(self, arg1, arg2): # do somethingи
ObjectAявляется экземпляром этого класса.теперь, когда
ObjectA.methodA(arg1, arg2)называется, python внутренне преобразует его для вас как:ClassA.methodA(ObjectA, arg1, arg2)The
selfпеременная относится к самому объекту.
когда объекты создаются, сам объект передается в параметр self.
из-за этого данные объекта привязаны к объекту. Ниже приведен пример того, как можно визуализировать данные каждого объекта. Обратите внимание, как’ self ' заменяется именем объекта. Я не говорю, что эта диаграмма примера ниже полностью точна, но она, надеюсь, служит цели визуализации использования себя.
объект передается в параметр self, чтобы объект мог удерживать свои собственные данные.
см. иллюстрацию ниже:
Мне нравится этот пример:
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 )[перенесен мой ответ из дубликата закрытого вопроса]
а также все другие причины, уже указанные, это позволяет упростить доступ к переопределенным методам; вы можете вызвать
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"
следующие выдержки из документация Python о self:
Как и в Modula-3, нет сокращений [в Python] для ссылки на элементы объекта из его методов: функция метода объявляется с явным первым аргументом, представляющим объект, который неявно предоставляется вызовом.
часто первый аргумент метода называется self. Это не более чем соглашение: имя self имеет абсолютно никакого особого значения для Python. Обратите внимание, однако, что, не следуя соглашению, ваш код может быть менее читаемым для других программистов Python, и также возможно, что программа браузера классов может быть написана, которая полагается на такое соглашение.
для получения дополнительной информации см. Python документация учебник по классам.
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"самостоятельное способ также используется, чтобы обратиться к переменной поля внутри класса.
class Animal(): #animalName made in constructor def Animal(self): self.animalName = ""; def getAnimalName(self): return self.animalNameIn в этом случае self ссылается на переменную animalName всего класса. Помните: если у вас есть переменная внутри метода, self не будет работать. Эта переменная просто существует только во время работы этого метода. Для определения полей (переменных всего класса) необходимо определить их вне методов класса.
Если вы не понимаете ни одного слова из того, что я говорю, то Google "объектно-ориентированное программирование.- Как только ты это поймешь, тебе даже не нужно будет спрашивать. этот вопрос.):
его использование аналогично использованию
thisключевое слово в Java, т. е. дать ссылку на текущий объект.
это там, чтобы следовать Python zen "явное лучше, чем неявное". Это действительно ссылка на объект класса. В Java и PHP, например, это называется
this.Если
user_type_name- это поле в вашей модели, к которому вы обращаетесьself.user_type_name.
selfявляется ссылкой объекта на сам объект, поэтому они одинаковы. Методы Python не вызываются в контексте самого объекта.selfв Python может использоваться для работы с пользовательскими объектными моделями или чем-то еще.
Я удивлен, что никто не поднял Lua. Lua также использует переменную' self', однако ее можно опустить, но все же использовать. C++ делает то же самое с "этим". Я не вижу причин объявлять "себя" в каждой функции, но вы все равно должны иметь возможность использовать его так же, как вы можете с lua и C++. Для языка, который гордится своей краткостью, странно, что он требует, чтобы вы объявили переменную self.
потому что, кстати, 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получит объект, на который он вызывается через иfubarвсе еще может быть вызван с объектом в качестве параметра и работать одинаково (it и то же самое, чтоC.frobЯ думаю).
во-первых, self-это обычное имя, вы можете поставить на его место что-нибудь другое (будучи когерентным).
он относится к самому объекту, поэтому, когда вы его используете, вы объявляете that .name and .возраст-это свойства объектов 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
на
__init__метод, self ссылается на вновь созданный объект; в других методах класса он ссылается на экземпляр, метод которого был вызван.самость, как имя, есть всего, называйте это как хотите ! но при его использовании, например для удаления объекта, вы должны использовать одно и то же имя:
__del__(var), гдеvarбыл использован в__init__(var,[...])вы должны взглянуть на
clsтоже есть больше картина. Это post может быть полезным.
взгляните на следующий пример, который ясно объясняет цель
selfclass 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используется/требуется для различения экземпляров.
использование аргумента, условно называемая
selfне так сложно понять, как это необходимо? Или о том, почему явно упоминают об этом? Это, я полагаю, является большим вопросом для большинства пользователей, которые ищут этот вопрос, или если это не так, у них, безусловно, будет тот же вопрос, когда они будут продвигаться вперед, изучая python. Я рекомендую им прочитать эти пару блогов:1: Использование себя объяснил
обратите внимание, что это не ключевое слово.
первый аргумент каждого метода класса, включая init, всегда является ссылкой на текущий экземпляр класса. По соглашению, этот аргумент всегда называют себя. В методе init self ссылается на вновь созданный объект; в других методах класса он ссылается на экземпляр, метод которого был вызван. Например, приведенный ниже код совпадает с приведенным выше кодом.
еще одна вещь, которую я хотел бы добавить, это необязательный позволяет мне объявить статические методы внутри класса, не писать!--1-->.
примеры кода:
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аргумент является обязательным.



Comments