Co __init__ i ja robimy w Pythonie?

790

Uczę się języka programowania Python i znalazłem coś, czego nie do końca rozumiem.

W metodzie takiej jak:

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

Co ma selfzrobić? Co to ma być? Czy to jest obowiązkowe?

Co robi __init__metoda? Dlaczego jest to konieczne? (itp.)

Myślę, że mogą to być konstrukcje OOP, ale niewiele wiem.

ivanleoncz
źródło

Odpowiedzi:

583

W tym kodzie:

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

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

... selfzmienna reprezentuje instancję samego obiektu. Większość języków obiektowych przekazuje to jako parametr ukryty do metod zdefiniowanych na obiekcie; Python nie. Musisz to wyraźnie zadeklarować. Po utworzeniu wystąpienia Aklasy i wywołaniu jej metod zostanie ona przekazana automatycznie, jak w ...

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

Ta __init__metoda z grubsza reprezentuje konstruktor w Pythonie. Po wywołaniu A()Python tworzy dla Ciebie obiekt i przekazuje go jako pierwszy parametr do __init__metody. Wszelkie dodatkowe parametry (np. A(24, 'Hello')) Również zostaną przekazane jako argumenty - w tym przypadku powodując zgłoszenie wyjątku, ponieważ konstruktor ich nie oczekuje.

Chris B.
źródło
8
co jeśli umieścisz x = 'Hello'poza init, ale wewnątrz klasy? czy to jest jak Java, gdzie jest to samo, czy staje się jak zmienna statyczna, która jest inicjowana tylko raz?
Jayen,
15
To jest jak zmienna statyczna. Jest inicjowany tylko raz i jest dostępny przez A.xlub a.x. Należy pamiętać, że nadrzędnym go na określonej klasie nie wpłynie na bazę, więc A.x = 'foo'; a.x = 'bar'; print a.x; print A.xwypisze barnastępniefoo
Chris B.
155
Warto zauważyć, że pierwszy argument nie musi być koniecznie wywoływany self, to po prostu konwencja.
Henry Gomersall
13
Jaki jest sens objectdeklaracji klasowej? Zauważyłem, że niektóre klasy mają to, a niektóre nie
Chris
9
@Chris To jest kompatybilność z Python 2. W Pythonie 3 nie ma potrzeby jawnego dziedziczenia, objectponieważ dzieje się tak domyślnie.
Gabriel
241

Tak, masz rację, to są konstrukty oop.

__init__jest konstruktorem klasy. selfParametr odnosi się do przypadku obiektu (jak thisC ++).

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

__init__Metoda jest wywoływana, gdy pamięć dla obiektu przeznaczono:

x = Point(1,2)

Ważne jest, aby użyć selfparametru w metodzie obiektu, jeśli chcesz zachować wartość w obiekcie. Jeśli na przykład zastosujesz taką __init__metodę:

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

Twoje xi yparametry zostaną zapisane w zmiennych na stosie i zostaną odrzucone, gdy metoda init wyjdzie poza zakres. Ustawienie tych zmiennych jako self._xi self._yustawia je jako członków Pointobiektu (dostępne przez cały okres istnienia obiektu).

RedBlueThing
źródło
1
Czy jest więc jakiś powód, dla którego nie chciałbyś selfbyć konstruktorem? Dlaczego w ogóle musisz to określić, czy nie byłoby lepiej, gdyby było to dorozumiane?
Aaron Franke,
O ile wiem, __ init __ nie jest konstruktorem, jest to pierwsza metoda, która zostanie wykonana po utworzeniu dowolnego obiektu, __ init __ służy do ustawienia obiektu. __ nowy __ jest konstruktorem w Pythonie.
Deepanshu
206

Krótki przykładowy przykład

W nadziei, że to może trochę pomóc, oto prosty przykład, którego użyłem, aby zrozumieć różnicę między zmienną zadeklarowaną w klasie a zmienną zadeklarowaną w __init__funkcji:

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

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

Wynik:

345
123
Dave Everitt
źródło
7
Ciekawa obserwacja, ale myślę, że jesteś na złym torze. Z print MyClass.i wygląda to tak, jakbyś nazywał „variablie i” statyczną. Gdzie tak jak w przypadku ai wywołujesz zmienną składową, ja. Wydaje mi się, że init jest tylko konstruktorem, który jest uruchamiany po raz pierwszy podczas tworzenia obiektu klasy.
Captainspi
34
Właśnie to próbowałem „wytłumaczyć sobie” na tym przykładzie - że ustawiona zmienna __init__jest przekazywana do instancji klasy, a nie „statyczna” zmienna samej klasy o tej samej nazwie ...
Dave Everitt,
44

W skrócie:

  1. selfjak sugeruje, odnosi się do samego siebie - obiektu, który wywołał metodę. Oznacza to, że jeśli masz N obiektów wywołujących metodę, wówczas self.abędzie odwoływał się do osobnej instancji zmiennej dla każdego z N obiektów. Wyobraź sobie N kopii zmiennej adla każdego obiektu
  2. __init__to tak zwany konstruktor w innych językach OOP, takich jak C ++ / Java. Podstawową ideą jest to, że jest to specjalna metoda, która jest automatycznie wywoływana podczas tworzenia obiektu tej klasy
Acumenus
źródło
29

__init__działa jak konstruktor. Musisz przekazać „self” do dowolnej funkcji klasy jako pierwszy argument, jeśli chcesz, aby zachowywały się jak metody niestatyczne. „self” to zmienne instancji dla twojej klasy.

ewalk
źródło
1
„self” określa, czy metoda jest statyczna, czy nie! Wow, to otwieracz do oczu dla tego faceta z Java.
liwevire 18.04.18
25

Wypróbuj ten kod. Mam nadzieję, że pomoże to wielu programistom C, takim jak ja, nauczyć się 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__

Wynik:

Jay

Sum = 5

Doc - Inside Class

Doc - __init__ Constructor

Doc - Inside Show

Destructor Deleting object - Jay

Jayzcode
źródło
Nie wiem, czy to tylko ja, ale czytanie tego kodu było trochę mylące. Może dlatego, że wciąż jestem początkującym programistą Python, idk.
Linny,
Nie mam jasności co do dokumentu ... czy to wyciąga dokumentację? a jeśli to zrobię: '' 'test - mój dokument' '', czy mogę użyć: print.p .__ test__? czy doc jest konkretnym słowem kluczowym?
Thomas
@Thomas doc to słowo kluczowe dla udokumentowanych szczegółów. Potrójne cudzysłowy są używane do spisywania dokumentów, a dokument jest jednostką opcjonalną.
Jayzcode
24

Obiekty klasy obsługują dwa rodzaje operacji: odwołania do atrybutów i tworzenie instancji

Odwołania do atrybutów używają standardowej składni stosowanej dla wszystkich odniesień do atrybutów w Pythonie: obj.name. Prawidłowe nazwy atrybutów to wszystkie nazwy, które były w przestrzeni nazw klasy podczas tworzenia obiektu klasy. Jeśli więc definicja klasy wyglądała tak:

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

    def f(self):
        return 'hello world'

Następnie MyClass.ii MyClass.fsą ważne odniesienia cechę, powracający liczbę całkowitą i obiekt funkcję, odpowiednio. Można także przypisać atrybuty klas, dzięki czemu można zmienić wartość MyClass.iwedług przypisania. __doc__jest również prawidłowym atrybutem zwracającym ciąg dokumentów należący do klasy: „Prosta przykładowa klasa”.

Tworzenie instancji klasy wykorzystuje notację funkcji. Udawaj, że obiekt klasy jest funkcją bez parametrów, która zwraca nową instancję klasy. Na przykład:

x = MyClass()

Operacja tworzenia instancji („wywołanie” obiektu klasy) tworzy pusty obiekt. Wiele klas lubi tworzyć obiekty z instancjami dostosowanymi do określonego stanu początkowego. Dlatego klasa może zdefiniować specjalną metodę o nazwie __init__(), taką jak ta:

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

Kiedy klasa definiuje __init__()metodę, instancja klasy automatycznie wywołuje __init__()nowo utworzone wystąpienie klasy. W tym przykładzie nową zainicjowaną instancję można uzyskać przez:

x = MyClass()

Oczywiście __init__()metoda może zawierać argumenty za większą elastycznością. W takim przypadku argumenty podane operatorowi tworzenia instancji klasy są przekazywane do __init__(). Na przykład,

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

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

Zaczerpnięte z oficjalnej dokumentacji, która w końcu najbardziej mi pomogła.


Oto mój przykład

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 :)")

Podczas tworzenia wystąpienia klasy Bill:

purchase = Bill(5,6,7)

Dostajesz:

> Buy 5 apples 6 figs and 7 dates. Total fruitty bill is 18  pieces of
> fruit :)
Harvey
źródło
22

Miałem problem z niezrozumieniem tego samemu. Nawet po przeczytaniu tutaj odpowiedzi.

Aby właściwie zrozumieć __init__metodę, musisz zrozumieć siebie.

Parametr własny

Argumenty akceptowane przez __init__metodę to:

def __init__(self, arg1, arg2):

Ale przekazujemy mu tylko dwa argumenty:

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

Skąd wziął się dodatkowy argument?

Kiedy uzyskujemy dostęp do atrybutów obiektu, robimy to według nazwy (lub referencji). Tutaj instancja jest odniesieniem do naszego nowego obiektu. Dostęp do metody printargs obiektu instancji uzyskujemy za pomocą instance.printargs.

Aby uzyskać dostęp do atrybutów obiektu z poziomu __init__metody, potrzebujemy odwołania do obiektu.

Za każdym razem, gdy wywoływana jest metoda, pierwszy argument jest przekazywany do głównego obiektu. Zgodnie z konwencją ten pierwszy argument zawsze wywołujesz sam w swoich metodach.

Oznacza to, że w __init__metodzie możemy wykonać:

self.arg1 = arg1
self.arg2 = arg2

Tutaj ustawiamy atrybuty obiektu. Możesz to sprawdzić, wykonując następujące czynności:

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

takie wartości są znane jako atrybuty obiektu. Tutaj __init__metoda ustawia atrybuty arg1 i arg2 instancji.

źródło: http://www.voidspace.org.uk/python/articles/OOP.shtml#the-init-method

eee
źródło
17

Zauważ, że selffaktycznie może to być dowolny poprawny identyfikator Pythona. Na przykład równie dobrze moglibyśmy napisać z przykładu Chrisa B.

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

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

i działałoby dokładnie tak samo. Zaleca się jednak używanie self, ponieważ inni pythonerzy rozpoznają go łatwiej.

SingleNegationElimination
źródło
Zgadzam się, że ja byłoby polecane zamiast foo, pomaga innym programistom patrzeć na kod
Linny
15

Zasadniczo musisz użyć słowa kluczowego „self”, gdy używasz zmiennej w wielu funkcjach w tej samej klasie. Jeśli chodzi o init , służy do ustawiania wartości domyślnych, ponieważ żadne inne funkcje z tej klasy nie są wywoływane.

użytkownik1675111
źródło
6
W Pythonie nie ma słowa kluczowego „self”. Nazywanie pierwszego parametru „self” jest po prostu konwencją.
David Anderson
Zasadniczo self jest używane jako symbol zastępczy. Nie jest wymagane używanie siebie, możesz użyć „eeee” lub „foo” lub czegoś innego, jest to zalecane dla innych programistów podczas czytania twojego kodu
Linny
15
  1. __init__jest w zasadzie funkcją, która „zainicjuje” / „aktywuje” właściwości klasy dla określonego obiektu, po utworzeniu i dopasowaniu do odpowiedniej klasy.
  2. self reprezentuje obiekt, który odziedziczy te właściwości.
atlas
źródło
1
słowa kluczowego „self” nie trzeba używać, to tylko symbol zastępczy. Możesz użyć dowolnego słowa, ale zaleca się użycie self, aby poprawić czytelność programu
Linny
13

„Ja” to odniesienie do instancji klasy

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

Teraz możemy utworzyć instancję foo i wywołać na niej metodę, w tym przypadku Python dodaje parametr własny:

f = foo()
f.bar()

Ale można go również przekazać, jeśli wywołanie metody nie znajduje się w kontekście wystąpienia klasy, poniższy kod robi to samo

f = foo()
foo.bar(f)

Co ciekawe, nazwa zmiennej „self” to tylko konwencja. Poniższa definicja będzie działać dokładnie tak samo. Powiedziawszy, że jest to bardzo silna konwencja, której należy zawsze przestrzegać , ale mówi ona coś o elastycznej naturze języka

class foo:
    def bar(s):
            print "hi"
Tarn
źródło
Dlaczego to mówi cokolwiek o elastycznej naturze języka? Mówi tylko, że możesz nadać zmiennym dowolną wybraną nazwę prawną. Czym różni się to od jakiegokolwiek innego języka programowania?
Daniel
Jak napisałem w mojej odpowiedzi, „bar” jest tylko funkcją, w której instancja klasy jest pierwszym parametrem. Tak więc „bar” jest zdefiniowany jako metoda związana z „foo”, ale można go również wywołać za pomocą instancji innej klasy. Nie tak działają na przykład metody i „to” w Javie, chociaż wyobrażam sobie, że widzisz, że są to te same pojęcia, funkcje i kontekst kontekstu instancji (kontekst instancji jest pierwszym parametrem w Pythonie i „to” w Javie) Być może widzisz teraz elastyczność języka, o którym mówiłem?
Tarn
Tak, to pokazuje elastyczność języka. Sposób, w jaki sformułowałeś swoją odpowiedź, wyglądał tak, jakbyś mówił, że fakt, że możesz nazwać zmienną „ja” czymś innym (jak s), pokazuje elastyczność Pythona.
Daniel,
12

Tylko demo na pytanie.

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
odpluskwić
źródło
11

W tym kodzie:

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

Tutaj __init__działa jako konstruktor dla klasy, a gdy instancja obiektu jest tworzona, funkcja ta jest wywoływana. selfreprezentuje obiekt instancji.

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

Wynik powyższych stwierdzeń będzie następujący:

I am a cat and I am called Kitty
Anagha
źródło
11

Co robi ja ? Co to ma być? Czy to jest obowiązkowe ?

Pierwszy argument każdej metody klasy, w tym init, jest zawsze odniesieniem do bieżącej instancji klasy . Zgodnie z konwencją ten argument jest zawsze nazywany self. W metodzie init selfodnosi się do nowo utworzonego obiektu; w innych metodach klasowych odnosi się do instancji, której metoda została wywołana.

Python nie zmusza cię do używaniaja ”. Możesz nadać mu dowolną nazwę. Pamiętaj jednak, że pierwszym argumentem w definicji metody jest odwołanie do obiektu . Python dodaje selfargument do listy; nie trzeba go dołączać podczas wywoływania metod. jeśli nie podałeś metody init, pojawi się błąd

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

Co robi metoda init ? Dlaczego jest to konieczne? (itp.)

initjest skrótem od inicjalizacji. Jest to konstruktor, który jest wywoływany podczas tworzenia instancji klasy i nie jest konieczny . Ale zwykle naszą praktyką jest pisanie metody init do ustawiania domyślnego stanu obiektu. Jeśli nie chcesz początkowo ustawiać żadnego stanu obiektu, nie musisz pisać tej metody.

Muhammad Faizan Khan
źródło
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()
Manohar Reddy Poreddy
źródło
5

Python __init__iself co oni robią?

Co robi self zrobić? Co to ma być? Czy to jest obowiązkowe?

Co robi __init__metoda? Dlaczego jest to konieczne? (itp.)

Podany przykład jest niepoprawny, więc pozwól, że utworzę na nim poprawny przykład:

class SomeObject(object):

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

    def method(self):
        return self.blah 

Kiedy tworzymy instancję obiektu, __init__wywoływana jest w celu dostosowania obiektu po jego utworzeniu. To znaczy, kiedy wywołujemy SomeObjectz 'blah'dołu (co może być czymkolwiek), zostaje ono przekazane do __init__funkcji jako argument blah:

an_object = SomeObject('blah')

selfArgumentem jest instancją SomeObject, która będzie przypisana an_object.

Później możemy chcieć wywołać metodę na tym obiekcie:

an_object.method()

Wykonywanie kropkowanego wyszukiwania, to znaczy, an_object.method wiąże instancję z instancją funkcji, a metoda (jak nazywana powyżej) jest teraz metodą „powiązaną” - co oznacza, że ​​nie musimy jawnie przekazywać instancji do wywołania metody .

Wywołanie metody pobiera instancję, ponieważ została powiązana z wyszukiwaniem kropkowanym, a po wywołaniu wykonuje dowolny kod, który został zaprogramowany do wykonania.

Niejawnie przekazany selfargument jest wywoływany selfkonwencją. Możemy użyć dowolnej innej legalnej nazwy Python, ale prawdopodobnie zmienisz ją na inną.

__init__to specjalna metoda udokumentowana w dokumentacji modelu danych Pythona . Jest wywoływany natychmiast po utworzeniu instancji (zwykle za pośrednictwem __new__- chociaż __new__nie jest wymagany, chyba że podklasujesz niezmienny typ danych).

Aaron Hall
źródło
3

Tutaj facet napisał całkiem dobrze i prosto: https://www.jeffknupp.com/blog/2014/06/18/improve-your-python-python-classes-and-object-oriented-programming/

Przeczytaj powyższy link jako odniesienie do tego:

self? Więc co z tym parametrem własnym dla wszystkich metod klienta? Co to jest? Oczywiście, tak jest! Innymi słowy, metoda taka jak wypłata określa instrukcje dotyczące wypłaty pieniędzy z konta abstrakcyjnego klienta. Wywołanie jeff.withdraw (100.0) umieszcza te instrukcje w instancji jeff.

Więc kiedy mówimy def wycofać (ja, kwota) :, mówimy: „Oto, w jaki sposób wypłacasz pieniądze z obiektu klienta (który nazywamy ja) i kwoty w dolarach (którą my nazywamy kwotę). to przykład klienta, który wzywa do wypłaty. To nie ja też robię analogie. jeff.withdraw (100.0) jest po prostu skrótem dla Customer.withdraw (jeff, 100.0), co jest całkowicie ważne (jeśli nie często widywane) kod.

init self może mieć sens w przypadku innych metod, ale co z init ? Kiedy wywołujemy init , jesteśmy w trakcie tworzenia obiektu, więc jak może istnieć jaźń? Python pozwala nam rozszerzyć własny wzorzec również na obiekty, które są konstruowane, nawet jeśli nie pasują one dokładnie. Wyobraź sobie, że jeff = Customer („Jeff Knupp”, 1000.0) to to samo, co wywołanie jeff = Customer (jeff, „Jeff Knupp”, 1000.0); Jeff, który został przekazany, również jest rezultatem.

Właśnie dlatego, gdy wywołujemy init , inicjalizujemy obiekty, mówiąc takie rzeczy jak self.name = name. Pamiętaj, ponieważ ponieważ self jest instancją, jest to równoważne z wypowiedzeniem jeff.name = name, co jest takie samo jak jeff.name = 'Jeff Knupp. Podobnie self.balance = balance jest taki sam jak jeff.balance = 1000.0. Po tych dwóch wierszach uznajemy obiekt klienta za „zainicjowany” i gotowy do użycia.

Uważaj na siebie __init__

Po init osoba dzwoniąca może słusznie założyć, że obiekt jest gotowy do użycia. Oznacza to, że po jeff = Customer („Jeff Knupp”, 1000.0), możemy zacząć dokonywać wpłat i wycofywać połączenia z jeff; jeff jest w pełni zainicjowanym obiektem.

Laxmikant
źródło