Що __init__ та самості роблять на Python?


791

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

У такому способі, як:

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

Що робить self? Що це означає бути? Це обов’язково?

Що робить __init__метод? Чому це потрібно? (тощо)

Я думаю, що вони можуть бути конструкціями OOP, але я не знаю дуже багато.

Відповіді:


584

У цьому коді:

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

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

... selfзмінна являє собою екземпляр самого об'єкта. Більшість об'єктно-орієнтованих мов передають це як прихований параметр методам, визначеним на об'єкті; Пітон ні. Ви повинні це заявити чітко. Коли ви створюєте екземпляр 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
Кріс Б.

155
Варто зазначити, що перший аргумент не обов’язково називати self, це просто за умовою.
Генрі Гомерсалл

13
У чому сенс objectдекларації класу? Я помітив, що деякі заняття мають це, а деякі ні
Кріс

9
@Chris Це для сумісності Python 2. У Python 3 немає необхідності явно успадкувати, objectоскільки це відбувається за замовчуванням.
Габріель

241

Так, ви праві, це конструкції oop.

__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параметри зберігатимуться у змінних на стеці та будуть відкинуті, коли метод init вийде за межі області. Встановлення цих змінних як self._xі self._yвстановлення цих змінних як членів Pointоб'єкта (доступних протягом життя об'єкта).


1
Тож чи є причина, чому ви не хочете selfбути в конструкторі? Чому ви навіть повинні вказати це, чи не було б краще, якби це було неявним?
Аарон Франке

Наскільки я знаю, __ init __ не є конструктором, це перший метод, який буде виконаний, коли створюється будь-який об’єкт, __ init __ використовується для установки об'єкта. __ new __ - конструктор в python.
Deepanshu

206

Короткий ілюстративний приклад

Сподіваючись, що це може трохи допомогти, ось простий приклад, який я використовував для розуміння різниці між змінною, оголошеною всередині класу, і змінною, оголошеною всередині __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, ви викликаєте змінну члена, i. Мені здається, що init - це просто конструктор, який вперше виконується під час створення об’єкта класу.
капітани

34
Це те, що я намагався "пояснити собі" на цьому прикладі - що змінна, задана __init__тим, передається екземплярам класу, а не "статичною" змінною самого класу, яка має те саме ім'я ...
Дейв Everitt

44

Коротко:

  1. selfяк це говорить, посилається на себе - об'єкт, який назвав метод. Тобто, якщо у вас є N об'єктів, що викликають метод, то self.aбуде посилатися на окремий екземпляр змінної для кожного з N об'єктів. Уявіть N копій змінної aдля кожного об'єкта
  2. __init__це те, що називається конструктором в інших мовах OOP, таких як C ++ / Java. Основна ідея полягає в тому, що це спеціальний метод, який автоматично викликається, коли створюється об'єкт цього класу

29

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


1
'self' визначає, чи метод статичний чи ні! Нічого собі, це відкривачка для очей для цього хлопця Java.
liwevire

25

Спробуйте цей код. Сподіваюся, це допомагає багатьом програмістам на C, як я, щоб дізнатися Py 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


Я не знаю, чи це тільки я, але читання цього коду було трохи заплутаним. Можливо, це тому, що я все ще початківець програміст Python, idk.
Лінні

Мені незрозуміло в документі док .. це тягне документацію? і якщо я роблю: '' 'test - мій документ' '', чи можу я використовувати: print.p .__ test__? або doc - це певне ключове слово?
Томас

@Thomas doc - ключове слово для документально підтверджених деталей. Потрійні котирування використовуються для запису документів, а документ є необов'язковим об'єктом.
Jayzcode

24

Об'єкти класу підтримують два види операцій: посилання на атрибути та інстанції

Посилання атрибутів використовують стандартний синтаксис, який використовується для всіх посилань на атрибути в 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.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


17

зауважте, що selfнасправді може бути будь-який дійсний ідентифікатор python. Наприклад, ми могли так само легко писати з прикладу Кріса Б:

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

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

і воно працювало б точно так само. Однак рекомендується використовувати self, оскільки інші пітонери розпізнають його легше.


Я погоджуюсь, що себе рекомендують замість foo, допомагає іншим програмістам дивитись код
Лінні

15

В основному, вам потрібно використовувати ключове слово "self", коли ви використовуєте змінну у кількох функціях одного класу. Що стосується init , він використовується для встановлення значень за замовчуванням, якщо жодні інші функції з цього класу не викликаються.


6
У Python немає ключового слова "само". Викликати перший параметр "Я" - це просто умова.
Девід Андерсон

self використовується в якості заповнювача в основному. Не потрібно використовувати самості, ви можете використовувати "eeee" або "foo" або щось інше, це просто рекомендується іншим програмістам під час читання вашого коду
Linny

15
  1. __init__в основному це функція, яка буде "ініціалізувати" / "активувати" властивості класу для конкретного об'єкта, як тільки буде створена та відповідна відповідному класу.
  2. self являє собою той об'єкт, який успадкує ці властивості.

1
ключове слово "само" не потрібно використовувати, це лише заповнювач. Ви можете використовувати будь-яке слово, але рекомендується використовувати самості, щоб допомогти читати програму
Лінні

13

"Я" - це посилання на екземпляр класу

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

Тепер ми можемо створити екземпляр foo та викликати метод на ньому, параметр self додається Python у цьому випадку:

f = foo()
f.bar()

Але це може бути передано також, якщо виклик методу не в контексті екземпляра класу, код нижче робить те саме

f = foo()
foo.bar(f)

Цікаво, що назва змінної "Я" - це лише умова. Викладене нижче визначення буде працювати точно так само. Сказавши, що це дуже сильна конвенція, якої слід дотримуватися завжди , але це щось говорить про гнучку природу мови

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

Чому це говорить про гнучку природу мови? Це просто говорить, що ви можете надати змінним будь-яке обране вами юридичне ім’я. Чим це відрізняється від будь-якої іншої мови програмування?
Даніель

Як я писав у своїй відповіді, "бар" - це лише функція, де екземпляр класу надається як перший параметр. Тож як "bar" визначається як метод, пов'язаний з "foo", його також можна було б назвати екземпляром якогось іншого класу. Наприклад, не такі способи та "це" працюють у Java, хоча я думаю, ви бачите, що це одна і та сама концепція, функції та деякий контекст екземпляра (контекст екземпляра є першим параметром у Python та "цей" у Java ") Можливо, тепер ви можете побачити гнучкість мови, якою я мав на увазі?
tarn

Так, це показує гнучкість мови. Те, як ви фразували свою відповідь, здавалося, що ви говорите, що той факт, що ви можете назвати змінну "Я" щось інше (як 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

11

Що робить сам ? Що це означає бути? Це обов’язково ?

Перший аргумент кожного методу класу, включаючи init, завжди є посиланням на поточний екземпляр класу . За умовою, цей аргумент завжди називають self. У методі init selfпосилається на новостворений об'єкт; в інших методах класу він посилається на екземпляр, метод якого називався.

Python не змушує вас використовувати " self ". Ви можете дати йому будь-яке ім’я. Але пам’ятайте, що перший аргумент у визначенні методу - це посилання на об’єкт . Python додає selfаргумент до списку для вас; не потрібно включати його під час виклику методів. якщо ви не вказали метод init 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 . Він викликається відразу після створення екземпляра (як правило, через __new__- хоча __new__це не потрібно, якщо ви не підкласифікуєте незмінний тип даних).


3

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

Прочитайте вище посилання як посилання на це:

self? Отже, що з цим параметром self для всіх методів клієнта? Що це? Чому, це, звичайно, екземпляр! Інакше кажучи, такий спосіб, як зняття коштів, визначає інструкції щодо зняття грошей з якогось абстрактного рахунку клієнта. Виклик jeff.withdraw (100.0) додає ці вказівки для використання на примірник jeff.

Тож, коли ми кажемо, що дефіцит вилучення (самостійна, сума):, ми говоримо: "ось як ви вилучаєте гроші з об'єкта Клієнта (який ми називаємо самостійно) та цифри долара (яку ми називаємо сумою). це екземпляр Клієнта, який вимагає відкликання, і це не я роблю аналогії. jeff.withdraw (100.0) - це просто скорочення для Customer.withdraw (jeff, 100.0), що цілком справедливо (якщо не часто бачимо) код.

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

Ось чому, коли ми дзвонимо init , ми ініціалізуємо об'єкти, вимовляючи такі речі, як self.name = name. Пам'ятайте, оскільки self - це екземпляр, це еквівалентно вимові jeff.name = ім'я, що є тим самим, що і jeff.name = 'Jeff Knupp. Аналогічно, self.balance = баланс - це те саме, що jeff.balance = 1000.0. Після цих двох рядків ми вважаємо об’єкт Замовника "ініціалізованим" та готовим до використання.

Будь уважним, що ти __init__

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.