Python'da __init__ ve ben ne yapar?


792

Python programlama dilini öğreniyorum ve tam olarak anlamadığım bir şeyle karşılaştım.

Gibi bir yöntemde:

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

Ne yapar self? Ne demek oluyor? Zorunlu mu?

__init__Yöntem ne yapar ? Neden gerekli? (vb.)

OOP yapıları olabileceğini düşünüyorum, ama çok fazla bilmiyorum.

Yanıtlar:


585

Bu kodda:

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

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

... selfdeğişken, nesnenin kendisinin örneğini temsil eder. Çoğu nesne yönelimli dil, bunu bir nesne üzerinde tanımlanan yöntemlere gizli bir parametre olarak iletir; Python yapmaz. Açıkça beyan etmelisiniz. ASınıfın bir örneğini oluşturup yöntemlerini çağırdığınızda , sınıfta olduğu gibi otomatik olarak geçirilir ...

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

__init__Yöntem Python bir yapıcı neyi temsil ettiğini kabaca olduğunu. A()Python'u çağırdığınızda sizin için bir nesne oluşturur ve bunu __init__metoda ilk parametre olarak iletir. Ek parametreler de (ör. A(24, 'Hello')) Bağımsız değişken olarak iletilir - bu durumda kurucu bunları beklemediğinden bir istisnanın yükselmesine neden olur.


8
initx = 'Hello' dışında ama sınıfın içine koyarsanız ne olur ? aynı java gibi mi, yoksa sadece bir kez başlatılan statik bir değişken gibi mi?
Jayen

15
Statik bir değişken gibi. Yalnızca bir kez başlatılır ve A.xveya aracılığıyla kullanılabilir a.x. Not belirli bir sınıfa üzerine basan tabanı etkilemeyeceğini, böylece A.x = 'foo'; a.x = 'bar'; print a.x; print A.xyazdırır barsonrafoo
Chris B.

156
İlk argümanın mutlaka aranması gerekmediğini belirtmek gerekir self, sadece kongre ile.
Henry Gomersall

13
objectSınıf bildirisindeki anlamı nedir ? Bazı sınıfların buna sahip olduğunu ve bazılarının olmadığını fark ettim
Chris

9
@Chris It's for Python 2 uyumluluğu. Python 3'te, objectvarsayılan olarak gerçekleştiği için açıkça devralmaya gerek yoktur .
Gabriel

241

Evet, haklısın, bunlar oop yapıları.

__init__bir sınıfın kurucusudur. selfParametre (şeklindeki cismin örneği ifade thisC ++).

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

__init__Nesne için bellek ayrılmış zaman yöntem çağrılan:

x = Point(1,2)

selfDeğeri nesne ile devam ettirmek istiyorsanız , parametreyi bir nesnenin yönteminin içinde kullanmak önemlidir . Örneğin, __init__yöntemi şöyle uygularsanız :

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

Sizin xve yparametreleriniz yığındaki değişkenlerde saklanır ve init yöntemi kapsam dışına çıktığında atılır. Bu değişkenleri self._xve olarak ayarlamak, bu değişkenleri nesnenin self._yüyeleri olarak ayarlar Point(nesnenin ömrü boyunca erişilebilir).


1
Öyleyse kurucuda olmak istememenizin bir nedeni var selfmı? Neden belirtmek zorundasın ki, örtük olsaydı daha iyi olmaz ki?
Aaron Franke

Bildiğim kadarıyla, __ init __ bir kurucu değil, herhangi bir nesne oluşturulduğunda çalıştırılacak ilk yöntemdir, __ init __ nesneyi ayarlamak için kullanılır. __ new __ python'un kurucusudur.
Deepanshu

206

Kısa bir açıklayıcı örnek

Biraz yardımcı olabileceği umuduyla, bir sınıf içinde bildirilen bir değişken ile bir __init__işlev içinde bildirilen bir değişken arasındaki farkı anlamak için kullandığım basit bir örnek :

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

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

Çıktı:

345
123

7
İlginç bir gözlem ama bence yanlış yoldasınız. Print MyClass.i ile daha çok 'static' variablie i diyorsunuz. Ai'de olduğu gibi bir üye değişkeni çağırdığınızda, i. Bana göre init , sadece sınıfın bir nesnesini oluşturduğunuzda yürütülen bir kurucu.
captainspi

34
Bu örnekle 'kendime açıklamaya' çalıştığım şey budur - tarafından ayarlanan değişken, sınıfın aynı ada sahip 'statik' değişkeni değil, sınıfın örneklerine__init__ geçirilen şeydir ...
Dave Everitt

44

Kısacası:

  1. selfönerdiği gibi, kendini ifade eder - yöntemi çağıran nesne. Yani, yöntemi çağıran N nesneniz varsa, N nesnelerinin self.aher biri için değişkenin ayrı bir örneğine başvurur. aHer nesne için değişkenin N kopyasını hayal edin
  2. __init__C ++ / Java gibi diğer OOP dillerinde kurucu olarak adlandırılan şeydir. Temel fikir, bu Sınıfın bir nesnesi oluşturulduğunda otomatik olarak çağrılan özel bir yöntem olmasıdır.

29

__init__yapıcı gibi davranır. Statik olmayan yöntemler gibi davranmalarını istiyorsanız, birinci bağımsız değişken olarak herhangi bir sınıf işlevine "self" iletmeniz gerekir. "self", sınıfınız için örnek değişkenlerdir.


1
'self' bir yöntemin statik olup olmadığını tanımlar! Vay canına, bu java adamı için bir göz açıcı.
liwevire

25

Bu kodu deneyin. Umarım benim gibi birçok C programcısının Py öğrenmesine yardımcı olur.

#! /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__

Çıktı:

Jay

Sum = 5

Doc - Inside Class

Doc - __init__ Constructor

Doc - Inside Show

Destructor Deleting object - Jay


Sadece ben olup olmadığını bilmiyorum, ama bu kodu okumak biraz kafa karıştırıcıydı. Belki de hala acemi bir Python programcısı olduğum için, idk.
Linny

Dokümanla ilgili net değilim .. Belgeleri çekiyor mu? ve eğer yaparsam: '' 'test - doktorum' '', şunu kullanabilir miyim: print.p .__ test__? veya doc belirli bir anahtar kelime mi?
Thomas

@Thomas doc , dokümante edilmiş ayrıntılar için anahtar kelimedir. Üçlü alıntılar dokümanları yazmak için kullanılır ve doküman isteğe bağlı bir varlıktır.
Jayzcode

24

Sınıf nesneleri iki tür işlemi destekler: öznitelik referansları ve örnekleme

Öznitelik referansları , Python: obj.name içindeki tüm öznitelik referansları için kullanılan standart sözdizimini kullanır. Geçerli öznitelik adları, sınıf nesnesi oluşturulduğunda sınıfın ad alanında bulunan tüm adlardır. Yani, sınıf tanımı şuna benziyorsa:

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

    def f(self):
        return 'hello world'

sonra MyClass.ive MyClass.fsırasıyla bir tamsayı ve bir işlev nesnesi döndüren geçerli öznitelik referanslarıdır. Sınıf öznitelikleri de atanabilir, böylece değerini MyClass.iatamaya göre değiştirebilirsiniz . __doc__ayrıca sınıfa ait öğretiyi döndüren geçerli bir özelliktir: "Basit bir örnek sınıf".

Sınıf örneği işlev gösterimini kullanır. Sınıf nesnesinin, sınıfın yeni bir örneğini döndüren parametresiz bir işlev olduğunu varsayalım. Örneğin:

x = MyClass()

İnstantiation (Bir sınıf nesnesi “çağıran”) işlemi boş bir nesne oluşturur. Birçok sınıf, belirli bir başlangıç ​​durumuna göre özelleştirilmiş örnekleri olan nesneler oluşturmayı sever. Bu nedenle, bir sınıf şöyle özel bir yöntem tanımlayabilir __init__():

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

Bir sınıf bir __init__()yöntem tanımladığında , sınıf örneği __init__()yeni oluşturulan sınıf örneği için otomatik olarak çağrılır . Bu örnekte, yeni, başlatılmış bir örnek şu yollarla elde edilebilir:

x = MyClass()

Tabii ki, __init__()yöntem daha fazla esneklik için argümanlara sahip olabilir. Bu durumda, sınıf örnekleme işlecine verilen argümanlar iletilir __init__(). Örneğin,

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

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

Sonunda bana en çok yardımcı olan resmi belgelerden alındı .


İşte benim örneğim

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 sınıfının bir örneğini oluşturduğunuzda:

purchase = Bill(5,6,7)

Şunları elde edersiniz:

> Buy 5 apples 6 figs and 7 dates. Total fruitty bill is 18  pieces of
> fruit :)

22

Bunu kendim anlama konusunda sorun yaşadım. Buradaki cevapları okuduktan sonra bile.

__init__Yöntemi doğru bir şekilde anlamak için kendini anlamanız gerekir.

Öz Parametre

__init__Yöntem tarafından kabul edilen argümanlar :

def __init__(self, arg1, arg2):

Ama biz sadece iki argümanı iletiyoruz:

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

Fazladan argüman nereden geldi?

Bir nesnenin özniteliklerine eriştiğimizde, bunu ada göre (veya referansla) yaparız. Burada örnek, yeni nesnemize bir referanstır. İnstance.printargs komutunu kullanarak örnek nesnesinin printargs yöntemine erişiyoruz.

Nesne özniteliklerine __init__yöntem içinden erişmek için nesneye bir başvuruya ihtiyacımız var.

Bir yöntem çağrıldığında, ilk bağımsız değişken olarak ana nesneye bir başvuru iletilir. Kural olarak, her zaman bu ilk argümanı kendi yöntemlerinize çağırırsınız.

Bu, __init__yöntemde yapabileceğimiz anlamına gelir :

self.arg1 = arg1
self.arg2 = arg2

Burada nesne üzerindeki özellikleri ayarlıyoruz. Aşağıdakileri yaparak bunu doğrulayabilirsiniz:

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

bunun gibi değerler nesne özellikleri olarak bilinir. Burada __init__yöntem, örneğin arg1 ve arg2 özniteliklerini ayarlar.

kaynak: http://www.voidspace.org.uk/python/articles/OOP.shtml#the-init-method


17

selfgeçerli herhangi bir python tanımlayıcısı olabileceğini unutmayın . Örneğin, Chris B'nin örneğinden kolayca yazabiliriz:

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

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

ve aynı şekilde çalışır. Bununla birlikte, kendini kullanmanız önerilir çünkü diğer pitonlar daha kolay tanıyacaktır.


Ben kendini foo yerine tavsiye olacağını kabul ediyorum, diğer programcıların koda bakarak yardımcı olur
Linny

15

Temel olarak, aynı sınıf içindeki birden çok işlevde bir değişken kullanırken 'self' anahtar sözcüğünü kullanmanız gerekir. İnit'e gelince , bu sınıfın içinden başka bir işlev çağrılmadığı takdirde varsayılan değerleri ayarlamak için kullanılır.


6
Python'da 'öz' bir anahtar kelime yok. İlk parametrenin 'benlik' olarak adlandırılması sadece bir kuraldır.
David Anderson

öz, temelde bir yer tutucu olarak kullanılır. Kendini kullanman gerekmez, "eeee" veya "foo" ya da başka bir şey kullanabilirsin, sadece kodunu okurken diğer programcılar için tavsiye edilir
Linny

15
  1. __init__temel olarak, belirli bir nesne için sınıfın özelliklerini " başlatacak " / "etkinleştirecek" , bir kez oluşturulduktan ve karşılık gelen sınıfa eşleştirildiğinde bir işlevdir .
  2. self bu özellikleri devralacak nesneyi temsil eder.

1
"öz" anahtar kelimenin kullanılması gerekmez, yalnızca bir yer tutucudur. Herhangi bir kelimeyi kullanabilirsiniz, ancak programın okunabilirliğine yardımcı olmak için kendini kullanmanız önerilir
Linny

13

'Benlik' sınıf örneğine bir göndermedir

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

Şimdi foo örneği oluşturabilir ve yöntemini çağırabiliriz, bu durumda self parametresi Python tarafından eklenir:

f = foo()
f.bar()

Ancak yöntem çağrısı sınıfın bir örneği bağlamında değilse, aşağıdaki kod da aynı şeyi yapar

f = foo()
foo.bar(f)

İlginç bir şekilde 'self' değişken adı sadece bir konvansiyon. Aşağıdaki tanım tam olarak aynı şekilde çalışacaktır .. Her zaman takip edilmesi gereken çok güçlü bir sözleşme olduğunu söylemiş olmakla birlikte, dilin esnek doğası hakkında bir şey söylüyor

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

Neden bu dilin esnek doğası hakkında bir şey söylüyor? Sadece değişkenlere seçtiğiniz herhangi bir yasal isim verebileceğinizi söylüyor. Bunun diğer programlama dillerinden farkı nedir?
Daniel

Cevabımda yazdığım gibi, "bar" sadece birinci parametre olarak bir sınıf örneğinin sağlandığı bir işlevdir. Dolayısıyla "bar", "foo" ya bağlı bir yöntem olarak tanımlanırken, başka bir sınıfın örneği ile de çağrılabilir. Bu yöntemlerin ve "bu" örneğin Java'da çalışma şekli bu değildir, ancak bunların aynı kavram, işlevler ve bazı örnek bağlamı olduğunu görmenizi hayal ediyorum (örnek bağlamı Python'daki ilk parametre ve "Java'daki" bu ") Belki de şimdi bahsettiğim dilin esnekliğini görebilirsiniz?
tarn

Evet bu dilin esnekliğini gösteriyor. Cevabınızı nasıl ifade ettiğiniz gibi, "öz" değişkenini başka bir şey (örneğin s) olarak adlandırabileceğiniz gerçeğinin python'un esnekliğini gösterdiğini söylüyordunuz .
Daniel

12

Soru için bir demo.

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

Bu kodda:

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

Burada __init__sınıf için bir yapıcı görevi görür ve bir nesne başlatıldığında bu işlev çağrılır. selförnekleme nesnesini temsil eder.

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

Yukarıdaki ifadelerin sonucu aşağıdaki gibi olacaktır:

I am a cat and I am called Kitty

11

Benlik ne yapar ? Ne demek oluyor? Öyle mi zorunlu ?

İnit de dahil olmak üzere her sınıf yönteminin ilk argümanı her zaman sınıfın geçerli örneğine bir göndermedir . Kural olarak, bu argüman her zaman adlandırılır self. İnit yönteminde, selfyeni oluşturulan nesneyi ifade eder; diğer sınıf yöntemlerinde, yöntemi çağrılan örneği ifade eder.

Python sizi " kendini " kullanmaya zorlamaz . İstediğiniz herhangi bir adı verebilirsiniz. Ancak yöntem tanımındaki ilk argümanın nesneye bir referans olduğunu unutmayın . Python selfargümanı sizin için listeye ekler ; yöntemleri çağırdığınızda eklemeniz gerekmez. self init yöntemini sağlamadıysanız bir hata mesajı alırsınız

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

Ne gelmez init yöntemi mi? Neden gerekli? (vb.)

initbaşlatma süresi kısadır. Sınıfın bir örneğini yaptığınızda çağrılan bir kurucudur ve gerekli değildir . Ancak genellikle uygulamamız, nesnenin varsayılan durumunu ayarlamak için init yöntemi yazmaktır. Başlangıçta nesnenin herhangi bir durumunu ayarlamak istemiyorsanız, bu yöntemi yazmanız gerekmez.


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__ve selfne yapıyorlar?

Ne yapar self? Ne demek oluyor? Zorunlu mu?

__init__Yöntem ne yapar ? Neden gerekli? (vb.)

Verilen örnek doğru değil, bu yüzden buna dayanarak doğru bir örnek oluşturmama izin verin:

class SomeObject(object):

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

    def method(self):
        return self.blah 

Nesnenin bir örneğini oluşturduğumuzda, nesnenin __init__oluşturulduktan sonra özelleştirilmesi için çağrılır. Yani, aşağıda (herhangi bir şey olabilir) SomeObjectile aradığımızda , argüman olarak işleve 'blah'geçer :__init__blah

an_object = SomeObject('blah')

selfArgüman örneği olan SomeObjectbu atanacaktır an_object.

Daha sonra, bu nesne üzerinde bir yöntem çağırmak isteyebiliriz:

an_object.method()

Noktalı aramayı yapmak, yani, an_object.methodörneği işlevin bir örneğine bağlar ve yöntem (yukarıda belirtildiği gibi) artık "bağlı" bir yöntemdir - yani, örneği açıkça yöntem çağrısına geçirmemiz gerekmez. .

Yöntem çağrısı, noktalı aramaya bağlı olduğu için çağrılır ve çağrıldığında, gerçekleştirilmesi için programlanan kodu çalıştırır.

Örtük olarak geçirilen selfargüman, selfkonvansiyon tarafından çağrılır . Başka bir yasal Python adı kullanabiliriz, ancak başka bir şeye değiştirirseniz muhtemelen diğer Python programcıları tarafından katlanıp tüylenirsiniz.

__init__Python veri modeli belgelerinde belgelenen özel bir yöntemdir . Örnek oluşturulduktan hemen sonra çağrılır ( değişmez bir veri türünü alt sınıflandırmadığınız sürece genellikle __new__- olmasına rağmen __new__) gerekmez.


3

Burada adam oldukça iyi ve basit yazdı: https://www.jeffknupp.com/blog/2014/06/18/improve-your-python-python-classes-and-object-oriented-programming/

Buna referans olarak yukarıdaki bağlantıyı okuyun:

self? Peki, tüm Müşteri yöntemlerinin bu kendi parametresiyle ne var? Bu ne? Tabii ki, neden bu! Başka bir deyişle, para çekme gibi bir yöntem, bazı soyut müşterilerin hesabından para çekmek için talimatları tanımlar. Jeff.withdraw (100.0) öğesini çağırmak, bu talimatları jeff örneğinde kullanır.

Bu yüzden def cayma (benlik, tutar) deriz: "diyoruz ki," işte bir Müşteri nesnesinden parayı nasıl çektiğinizi (ki buna kendimiz diyeceğiz) ve bir dolar rakamı (ki buna miktar diyeceğiz). jeff.withdraw (100.0), mükemmel bir şekilde geçerli olan (sık görülmüyorsa) Customer.withdraw (jeff, 100.0) için sadece kısaltmadır. kodu.

init benliği diğer yöntemler için anlamlı olabilir, ama init ne olacak ? İnit dediğimizde , bir nesne yaratma sürecindeyiz, peki nasıl zaten bir benlik olabilir? Python, nesneler tam olarak uymasa bile, inşa edildiğinde kendi modelini genişletmemize izin verir. Sadece jeff = Customer ('Jeff Knupp', 1000.0) 'un jeff = Customer (jeff,' Jeff Knupp ', 1000.0) ile aynı olduğunu hayal edin; sonuçlanan jeff de sonuçlanır.

Bu nedenle init dediğimizde self.name = name gibi şeyler söyleyerek nesneleri başlatırız. Benlik örneği olduğu için bu, jeff.name = 'jeff.name =' Jeff Knupp ile aynı olan demeye eşdeğerdir. Benzer şekilde, self.balance = balance jeff.balance = 1000.0 ile aynıdır. Bu iki satırdan sonra, Müşteri nesnesinin "başlatılmış" ve kullanıma hazır olduğunu düşünüyoruz.

Ne olduğuna dikkat et __init__

İnit bittikten sonra arayan haklı olarak nesnenin kullanıma hazır olduğunu varsayabilir. Yani, jeff = Müşteri'den ('Jeff Knupp', 1000.0) sonra, jeff üzerinden para yatırmaya ve çağrıları çekmeye başlayabiliriz; jeff tamamen başlatılmış bir nesnedir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.