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

796

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

В методе, как:

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

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

Что делает __init__метод? Зачем это нужно? (так далее.)

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

ivanleoncz
источник

Ответы:

585

В этом коде:

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
Что делать, если вы положили x = 'Hello'вне init, но внутри класса? это как Java, где это то же самое, или это становится как статическая переменная, которая инициализируется только один раз?
Jayen
15
Это как статическая переменная. Он инициализируется только один раз и доступен через A.xили a.x. Обратите внимание , что перекрывая его на определенный класс не повлияет на базу, так A.x = 'foo'; a.x = 'bar'; print a.x; print A.xбудет печатать barзатемfoo
Chris B.
156
Стоит отметить, что первый аргумент не обязательно вызывать self, это просто условно.
Генри Гомерсалл
13
Какой смысл objectв объявлении класса? Я заметил, что некоторые классы имеют это, а некоторые нет
Крис
9
@Chris Это для совместимости с Python 2. В Python 3 нет необходимости явно наследовать, objectпотому что это происходит по умолчанию.
Габриэль
241

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

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

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параметры будут сохранены в переменных в стеке и будут отброшены , когда метод инициализации выходит из области видимости. Установка этих переменных как self._xи self._yустанавливает эти переменные в качестве членов Pointобъекта (доступны для жизни объекта).

RedBlueThing
источник
1
Итак, есть ли причина, по которой вы не хотели selfбы быть в конструкторе? Почему вы даже должны указывать это, не лучше ли было бы это неявно?
Аарон Франке
Насколько я знаю, __ init __ не является конструктором, это первый метод, который будет выполняться при создании любого объекта, __ init __ используется для настройки объекта. __ new __ это конструктор в python.
Дипаншу
207

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

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

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

a = MyClass()
print(a.i)
print(MyClass.i)

Вывод:

345
123
Дейв Эверитт
источник
7
Интересное наблюдение, но я думаю, что вы на неправильном пути. С печатью MyClass.i это выглядит так, будто вы вызываете «статическую» переменную i. Где, как и в случае с ai, вы вызываете переменную-член, т.е. Мне кажется, что init - это просто конструктор, который сначала выполняется при создании объекта класса.
Captainspi
34
Это то, что я пытался «объяснить самому себе» с помощью этого примера - что переменная, установленная с помощью переменной, __init__передается экземплярам класса, а не «статическая» переменная самого класса с тем же именем ...
Дейв Эверитт
44

Короче говоря:

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

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

ewalk
источник
1
'self' определяет, является ли метод статическим или нет! Ничего себе, это откровение для этого парня Java.
liwevire
25

Попробуйте этот код. Надеюсь, это поможет многим программистам на Си, таким как я, освоить 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

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

Объекты класса поддерживают два вида операций: ссылки на атрибуты и создание экземпляров.

Ссылки на атрибуты используют стандартный синтаксис, используемый для всех ссылок на атрибуты в Python: obj.name. Допустимые имена атрибутов - это все имена, которые были в пространстве имен класса при создании объекта класса. Итак, если определение класса выглядело так:

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

    def f(self):
        return 'hello world'

затем MyClass.iи MyClass.fявляются действительными ссылками на атрибуты, возвращая целое число и объект функции, соответственно. Атрибуты класса также могут быть назначены, так что вы можете изменить значение MyClass.iприсваивания. __doc__также является допустимым атрибутом, возвращающим строку документации, принадлежащую классу: «Простой пример класса».

Реализация класса использует функцию обозначения. Просто представьте, что объект класса является функцией без параметров, которая возвращает новый экземпляр класса. Например:

x = MyClass()

Операция создания экземпляра («вызов» объекта класса) создает пустой объект. Многие классы любят создавать объекты с экземплярами, настроенными на конкретное начальное состояние. Поэтому класс может определять специальный метод с именем __init__(), например:

def __init__(self):
    self.data = []

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

x = MyClass()

Конечно, __init__()метод может иметь аргументы для большей гибкости. В этом случае аргументы, данные оператору создания класса, передаются в __init__(). Например,

class Complex:
    def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart

x = Complex(3.0, -4.5)
x.r, x.i

Взято из официальной документации, которая мне больше всего помогла в итоге.


Вот мой пример

class Bill():
    def __init__(self,apples,figs,dates):
        self.apples = apples
        self.figs = figs
        self.dates = dates
        self.bill = apples + figs + dates
        print ("Buy",self.apples,"apples", self.figs,"figs 
                and",self.dates,"dates. 
                Total fruitty bill is",self.bill," pieces of fruit :)")

Когда вы создаете экземпляр класса Bill:

purchase = Bill(5,6,7)

Ты получаешь:

> Buy 5 apples 6 figs and 7 dates. Total fruitty bill is 18  pieces of
> fruit :)
Харви
источник
22

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

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

Параметр собственной личности

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

def __init__(self, arg1, arg2):

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

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

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

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

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

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

Это означает, что в __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

еее
источник
17

обратите внимание, что это selfможет быть любой действительный идентификатор Python. Например, мы могли бы так же легко написать на примере Криса Б.

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

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

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

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

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

user1675111
источник
6
В Python нет ключевого слова self. Называть первый параметр «self» - это просто соглашение.
Дэвид Андерсон
Self используется в качестве заполнителя в основном. Не обязательно, чтобы вы использовали self, вы могли бы использовать «eeee» или «foo» или что-то еще, это просто рекомендуется для других программистов при чтении вашего кода
Линни
15
  1. __init__в основном это функция, которая будет «инициализировать» / «активировать» свойства класса для конкретного объекта, после того как он создан и сопоставлен с соответствующим классом.
  2. self представляет тот объект, который будет наследовать эти свойства.
атлас
источник
1
ключевое слово "self" не нужно использовать, это просто заполнитель. Вы можете использовать любое слово, но рекомендуется использовать self, чтобы улучшить читаемость программы
Линни
13

«Я» является ссылкой на экземпляр класса

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

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

f = foo()
f.bar()

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

f = foo()
foo.bar(f)

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

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

Просто демо на вопрос.

class MyClass:

    def __init__(self):
        print('__init__ is the constructor for a class')

    def __del__(self):
        print('__del__ is the destructor for a class')

    def __enter__(self):
        print('__enter__ is for context manager')
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print('__exit__ is for context manager')

    def greeting(self):
        print('hello python')


if __name__ == '__main__':
    with MyClass() as mycls:
        mycls.greeting()

$ python3 class.objects_instantiation.py
__init__ is the constructor for a class
__enter__ is for context manager
hello python
__exit__ is for context manager
__del__ is the destructor for a class
отлаживать
источник
11

В этом коде:

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
Anagha
источник
11

Что делает сам ? Что это значит ? Это обязательно ?

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

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

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

Что делает метод init ? Зачем это нужно? (так далее.)

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

Мухаммед Файзан Хан
источник
8
# 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()
Манохар Редди Поредди
источник
5

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

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

Аарон Холл
источник
3

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

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

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

Поэтому, когда мы говорим, что defdraw (self, amount) :, мы говорим: «вот как вы снимаете деньги с объекта Customer (который мы назовем self) и цифру в долларах (которую мы назовем sum). это тот случай, когда вызывается запрос клиента, и я тоже не подхожу к аналогиям. jeff.withdraw (100.0) является просто сокращением для Customer.withdraw (jeff, 100.0), что вполне допустимо (если его не часто видели) код.

init self может иметь смысл для других методов, но как насчет init ? Когда мы вызываем init , мы находимся в процессе создания объекта, так как же может существовать самость? Python позволяет нам расширять собственный шаблон, когда объекты также создаются, даже если он не совсем подходит. Просто представьте, что jeff = Customer ('Jeff Knupp', 1000.0) - это то же самое, что вызов jeff = Customer (jeff, 'Jeff Knupp', 1000.0); Джефф, который был передан, также является результатом.

Вот почему, когда мы вызываем init , мы инициализируем объекты, говоря что-то вроде self.name = name. Помните, поскольку self является экземпляром, это эквивалентно произнесению jeff.name = name, которое совпадает с jeff.name = 'Jeff Knupp. Аналогично, self.balance = баланс такой же, как jeff.balance = 1000.0. После этих двух строк мы считаем объект Customer «инициализированным» и готовым к использованию.

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

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

Laxmikant
источник