Python __init__ и self что они делают?

466

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

В методе типа:

def method(self, blah):
    def __init__(?):
        ....
    ....

Что делает self? Что это значит? Обязательно?

Что делает метод __init__? Почему это необходимо? (И т.д.).

Я думаю, что они могут быть конструкциями ООП, но я не очень-то знаю.

Теги:
oop

18 ответов

420

В этом коде:

class A(object):
    def __init__(self):
        self.x = 'Hello'

    def method_a(self, foo):
        print self.x + ' ' + foo

... переменная self представляет экземпляр самого объекта. Большинство объектно-ориентированных языков передают это как скрытый параметр методам, определенным на объекте; Python этого не делает. Вы должны объявить это явно. Когда вы создаете экземпляр класса A и вызываете его методы, он будет передаваться автоматически, как в...

a = A()               # We do not pass any argument to the __init__ method
a.method_a('Sailor!') # We only pass a single argument

Метод __init__ примерно соответствует представлению конструктора в Python. Когда вы вызываете A(), Python создает для вас объект и передает его в качестве первого параметра методу __init__. Любые дополнительные параметры (например, A(24, 'Hello')) также передаются в качестве аргументов - в этом случае вызывают исключение, поскольку конструктор не ожидает их.

  • 8
    Какой смысл object в объявлении класса? Я заметил, что некоторые классы имеют это, а некоторые нет
  • 3
    @Chris Это для совместимости с Python 2. В Python 3 нет необходимости явно наследовать от object потому что это происходит по умолчанию.
145

Да, вы правы, это конструкции oop.

__init__ является конструктором для класса. Параметр self относится к экземпляру объекта (например, this в С++).

class Point:
    def __init__(self, x, y):
        self._x = x
        self._y = y

Метод __init__ вызывается, когда выделяется память для объекта:

x = Point(1,2)

Важно использовать параметр self внутри метода объекта, если вы хотите сохранить значение с объектом. Если, например, вы реализуете метод __init__ следующим образом:

class Point:
    def __init__(self, x, y):
        _x = x
        _y = y

Параметры x и y будут храниться в переменных в стеке и будут отброшены, если метод init выходит за рамки. Установка этих переменных как self._x и self._y устанавливает эти переменные как члены объекта Point (доступные для времени жизни объекта).

  • 0
    Итак, есть ли причина, по которой вы не хотите, чтобы self был в конструкторе? Почему вы даже должны это указать, не лучше ли было бы это неявно?
107

Краткий иллюстративный пример

В надежде, что это может помочь немного, вот простой пример, который я использовал для понимания разницы между переменной, объявленной внутри класса, и переменной, объявленной внутри функции __init__:

class MyClass(object):
     i = 123
     def __init__(self):
         self.i = 345

a = MyClass()
print a.i
345
print MyClass.i
123
  • 7
    Интересное наблюдение, но я думаю, что вы на неправильном пути. С печатью MyClass.i это выглядит так, будто вы вызываете «статическую» переменную i. Где, как и в случае с ai, вы вызываете переменную-член, т.е. Мне кажется, что init - это просто конструктор, который сначала выполняется при создании объекта класса.
  • 24
    Вот что я пытался «объяснить самому себе» с помощью этого примера - что переменная, установленная с помощью __init__ - это то, что передается экземплярам класса, а не «статическая» переменная самого класса с тем же именем ...
31

Короче:

  • self, как он предполагает, ссылается на себя - объект, который вызвал метод. То есть, если у вас есть N объектов, вызывающих метод, то self.a будет ссылаться на отдельный экземпляр переменной для каждого из N объектов. Представьте N копий переменной a для каждого объекта
  • __init__ - это то, что называется конструктором в других языках ООП, таких как С++/Java. Основная идея заключается в том, что это специальный метод, который автоматически вызывается, когда объект этого класса создается
19

__init__ действует как конструктор. Вам нужно передать "я" любым функциям класса в качестве первого аргумента, если вы хотите, чтобы они вели себя как нестатические методы. "self" - это переменные экземпляра для вашего класса.

  • 0
    'self' определяет, является ли метод статическим или нет! Ничего себе, это откровение для этого парня Java.
17

Попробуйте этот код. Надеюсь, это поможет многим программистам на C, например, мне узнать Py.

#! /usr/bin/python2

class Person:

    '''Doc - Inside Class '''

    def __init__(self, name):
        '''Doc - __init__ Constructor'''
        self.n_name = name        

    def show(self, n1, n2):
        '''Doc - Inside Show'''
        print self.n_name
        print 'Sum = ', (n1 + n2)

    def __del__(self):
        print 'Destructor Deleting object - ', self.n_name

p=Person('Jay')
p.show(2, 3)
print p.__doc__
print p.__init__.__doc__
print p.show.__doc__

Вывод:

Jay

Sum = 5

Doc - Inside Class

Doc - __init__ Constructor

Doc - Inside Show

Destructor Deleting object - Jay

  • 0
    Я не знаю, только ли это я, но чтение этого кода было немного запутанным. Может быть, это потому, что я все еще начинающий программист Python, ИДК.
  • 0
    Я не совсем понимаю насчет документации ... она тянет документацию? и если я сделаю: '' 'test - my doc' '', могу ли я использовать: print.p .__ test__? или документ является конкретным ключевым словом?
16

Если бы это не было проблемой. Даже после прочтения ответов здесь.

Чтобы правильно понять метод __init__, вам нужно понять себя.

Самостоятельный параметр

Аргументы, принятые методом __init__, следующие:

def __init__(self, arg1, arg2):

Но мы фактически передаем только два аргумента:

instance = OurClass('arg1', 'arg2')

Откуда появился дополнительный аргумент?

Когда мы обращаемся к атрибутам объекта, мы делаем это по имени (или по ссылке). Здесь экземпляр является ссылкой на наш новый объект. Мы обращаемся к методу printargs объекта экземпляра, используя instance.printargs.

Чтобы получить доступ к атрибутам объекта из метода __init__, нам нужна ссылка на объект.

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

Это означает, что в методе __init__ мы можем сделать:

self.arg1 = arg1
self.arg2 = arg2

Здесь мы устанавливаем атрибуты объекта. Вы можете проверить это, выполнив следующие действия:

instance = OurClass('arg1', 'arg2')
print instance.arg1
arg1

значения, подобные этому, известны как атрибуты объектов. Здесь метод __init__ задает атрибуты arg1 и arg2 экземпляра.

источник: http://www.voidspace.org.uk/python/articles/OOP.shtml#the-init-method

13

В принципе, вам нужно использовать ключевое слово "self" при использовании переменной в нескольких функциях внутри одного класса. Что касается init, он использовал для установки значений по умолчанию, если другие функции из этого класса не вызываются.

  • 5
    В Python нет ключевого слова self. Называть первый параметр «self» - это просто соглашение.
  • 0
    Self используется в качестве заполнителя в основном. Вам не обязательно использовать self, вы можете использовать "eeee" или "foo" или что-то еще, это просто рекомендуется для других программистов при чтении вашего кода
13

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

class A(object):
    def __init__(foo):
        foo.x = 'Hello'

    def method_a(bar, foo):
        print bar.x + ' ' + foo

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

  • 0
    Я согласен, что self будет рекомендоваться вместо foo, помогает другим программистам смотреть на код
12

"Я" - это ссылка на экземпляр класса

class foo:
    def bar(self):
            print "hi"

Теперь мы можем создать экземпляр foo и вызвать метод на нем, сам параметр добавляется Python в этом случае:

f = foo()
f.bar()

Но он также может быть передан, если вызов метода не находится в контексте экземпляра класса, код ниже делает то же самое

f = foo()
foo.bar(f)

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

class foo:
    def bar(s):
            print "hi"
  • 0
    Почему это говорит о гибкости языка? Он просто говорит, что вы можете дать переменным любое допустимое имя. Чем это отличается от любого другого языка программирования?
  • 0
    Как я уже писал в своем ответе, «bar» - это просто функция, в которой в качестве первого параметра указывается экземпляр класса. Таким образом, хотя "bar" определяется как метод, связанный с "foo", он также может вызываться с экземпляром какого-либо другого класса. Это не то, как методы и «this» работают, например, в Java, хотя я предполагаю, что вы видите, что это одна и та же концепция, функции и некоторый контекст экземпляра (контекст экземпляра является первым параметром в Python и «this» в Java ») Возможно, теперь вы можете увидеть гибкость языка, на который я ссылался?
Показать ещё 1 комментарий
10
  • __init__ - это в основном функция, которая будет "инициализировать" / "активировать" свойства класса для определенного объекта, после создания и сопоставления с соответствующим классом.
  • self представляет объект, который наследует эти свойства.
  • 1
    ключевое слово "self" не нужно использовать, это просто заполнитель. Вы можете использовать любое слово, но рекомендуется использовать self, чтобы улучшить читаемость программы.
10

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

4
# Source: Class and Instance Variables
# https://docs.python.org/2/tutorial/classes.html#class-and-instance-variables

class MyClass(object):
    # class variable
    my_CLS_var = 10

    # sets "init'ial" state to objects/instances, use self argument
    def __init__(self):
        # self usage => instance variable (per object)
        self.my_OBJ_var = 15

        # also possible, class name is used => init class variable
        MyClass.my_CLS_var = 20


def run_example_func():
    # PRINTS    10    (class variable)
    print MyClass.my_CLS_var

    # executes __init__ for obj1 instance
    # NOTE: __init__ changes class variable above
    obj1 = MyClass()

    # PRINTS    15    (instance variable)
    print obj1.my_OBJ_var

    # PRINTS    20    (class variable, changed value)
    print MyClass.my_CLS_var


run_example_func()
4

В этом коде:

class Cat: def __init__(self, name): self.name = name def info(self): print 'I am a cat and I am called', self.name

Здесь __init__ выступает в качестве конструктора для класса, и когда объект создается, эта функция вызывается. self представляет объект-экземпляр.

c = Cat('Kitty') c.info()

Результат приведенных выше утверждений будет следующим:

I am a cat and I am called Kitty

3

Раздел 9.3 в этот учебник по Python дает краткое введение в основные элементы класса Python: переменные класса, методы класса и роли __init__ и __self__.

3

Здесь парень написал довольно хорошо и просто: https://www.jeffknupp.com/blog/2014/06/18/improve-your-python-python-classes-and-object-oriented-programming/

Прочтите ссылку выше в качестве ссылки на это:

self? Итак, что с этим параметром для всех клиентов методы? Что это? Конечно, это пример! Положите другое метод, такой как отзыв, определяет инструкции для снятия деньги из какой-то абстрактной учетной записи клиента. призвание jeff.withdraw(100.0) помещает эти инструкции для использования на jeff экземпляр.

Итак, когда мы говорим, что def def (self, amount):, мы говорим: "вот как вы снимаете деньги с объекта Customer (который мы будем называть самим) и долларовой цифрой (которую мы будем называть суммой). Я - это пример Клиент, который снимает, вызывается. Это не меня аналогий. jeff.withdraw(100.0) является просто сокращением для Customer.withdraw(jeff, 100.0), что совершенно верно (если не часто видел) код.

init сам может иметь смысл для других методов, но как насчет init? Когда мы вызываем init, мы находимся в процессе создания объекта, так как может быть уже само? Python позволяет нам расширять сам шаблон, когда объекты также построены, хотя он не совсем подходит. Только представьте, что jeff = Customer ('Jeff Knupp ', 1000.0) совпадает с вызовом jeff = Customer (jeff,' Jeff Knupp ', 1000,0); в результате получился также jeff.

Вот почему, когда мы вызываем init, мы инициализируем объекты, говоря: такие вещи, как self.name = name. Помните, что, поскольку я - это экземпляр, это эквивалентно выражению jeff.name = name, которое является таким же, как jeff.name = 'Джефф Кнупп. Аналогично, self.balance = баланс одинаковый как jeff.balance = 1000.0. После этих двух строк мы рассмотрим Объект клиента" инициализирован "и готов к использованию.

Будьте осторожны, что вы __init__

После завершения init, вызывающий может по праву предположить, что объект готов к использованию. То есть, после jeff = Customer (" Jeff Knupp", 1000.0), мы можем начать делать депозиты и отзывать звонки в jeff; jeff - полностью инициализированный объект.

1

Python __init__ и self что они делают?

Что делает self? Что это значит? Обязательно?

Что делает метод __init__? Почему это необходимо? (И т.д.).

Приведенный пример неверен, поэтому позвольте мне создать на нем правильный пример:

class SomeObject(object):

    def __init__(self, blah):
        self.blah = blah

    def method(self):
        return self.blah 

Когда мы создаем экземпляр объекта, __init__ вызывается для настройки объекта после его создания. То есть, когда мы вызываем SomeObject с 'blah' ниже (что может быть что угодно), оно передается функции __init__ в качестве аргумента blah:

an_object = SomeObject('blah')

Аргумент self - это экземпляр SomeObject, который будет присвоен an_object.

Позже мы можем вызвать метод для этого объекта:

an_object.method()

Выполнение пунктирного поиска, т.е. an_object.method, связывает экземпляр с экземпляром функции, а метод (называемый выше) теперь является "связанным" методом, что означает, что нам не нужно явно пропускать экземпляр вызова метода.

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

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

__init__ - специальный метод, задокументированный в документации Datamodel Python. Он вызывается сразу после создания экземпляра (обычно через __new__ - хотя __new__ не требуется, если вы не подклассифицируете неизменяемый тип данных).

1

Что делает self? Что означает означает? Является ли он обязательным?

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

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

TypeError: __init___() takes no arguments (1 given)

Что делает метод init? Почему это необходимо? (И т.д.).

init для инициализации. Это конструктор, вызываемый при создании экземпляра класса, а не нужен. Но обычно наша практика заключается в том, чтобы написать метод init для установки состояния объекта по умолчанию. Если вы не хотите устанавливать какое-либо состояние объекта изначально, вам не нужно писать этот метод.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню