Какова цель самости?



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



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


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



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


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

722   19  

19 ответов:

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

enter image description here

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

enter image description here

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

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

enter image description here

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

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

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

в текущая ситуация складывается хорошо:
 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 может быть полезным.

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

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

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

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

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

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

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

    Ничего не найдено.