Co je __init__ v Pythonu? [With Examples]

Chcete začít s objektově orientovaným návrhem v Pythonu? Udělejte první kroky ještě dnes tím, že se dozvíte o metodě __init__ Pythonu.

V tomto tutoriálu si projdeme základy tříd a objektů Pythonu a poté se seznámíme s metodou __init__.

Na konci tohoto tutoriálu budete schopni odpovědět na následující otázky:

  • Co jsou proměnné instance nebo atributy instance?
  • Jak metoda init pomáhá při inicializaci atributů instance?
  • Jak můžeme nastavit výchozí hodnoty atributů?
  • Jak můžeme použít metody tříd jako konstruktory k vytváření objektů?

Začněme.

Třídy a objekty Pythonu

Třídy jsou základem objektově orientovaného programování v Pythonu. Můžeme vytvořit třídu a definovat atributy a metody – abychom spojili data a související funkce.

Jakmile vytvoříme třídu, můžeme ji použít jako plán (nebo šablonu) k vytváření objektů (instancí).

👩‍🏫Ukázkový čas! Vytvořme třídu Employee, kde každý objekt této třídy má následující atributy:

  • celé_jméno: celé jméno zaměstnance ve formátu jméno příjmení
  • emp_id: id zaměstnance
  • oddělení: oddělení, ke kterému patří
  • zkušenosti: počet let zkušeností, které mají

Co to znamená? 🤔

Každý jednotlivý zaměstnanec bude instancí nebo objektem třídy Zaměstnanec. A každý objekt bude mít svou vlastní hodnotu pro full_name, emp_id, department a experience.

Tyto atributy se také nazývají proměnné instance a termíny atributy a proměnné instance budeme používat zaměnitelně.

Za chvíli se dostaneme k přidávání atributů. Prozatím vytváříme třídu zaměstnanců takto:

class Employee:
    pass

Použití pass (jako zástupný symbol) nám pomáhá vyhnout se chybám při spouštění skriptu.

Ačkoli aktuální verze třídy Zaměstnanec není příliš užitečná, je stále platnou třídou. Můžeme tedy vytvořit objekty třídy Employee:

employee_1 = Employee()

print(employee_1)
#Output: <__main__.Employee object at 0x00FEE7F0>

Můžeme také přidat atributy a inicializovat je hodnotami, jak je znázorněno:

employee_1.full_name="Amy Bell"
employee_1.department="HR"

Tento přístup k přidávání atributů instance je však neefektivní a náchylný k chybám. Také to neumožňuje použití třídy jako šablony pro vytváření objektů. Zde pomáhá metoda __init__.

Pochopení role metody __init__ ve třídě Pythonu

Měli bychom být schopni inicializovat proměnné instance při vytváření instance objektu a metoda __init__ nám v tom pomáhá. Metoda __init__ je volána pokaždé, když je vytvořen nový objekt třídy, aby se inicializovaly hodnoty proměnných instance.

  Jak převést webovou stránku do PDF: 12 nejlepších nástrojů

Pokud jste programovali v jazyce jako C++, uvidíte, že metoda __init__ funguje podobně jako konstruktory.

Definování metody __init__

Přidejme metodu __init__ do třídy Employee:

class Employee:
    def __init__(self, full_name,emp_id,department,experience):
        self.full_name = full_name
        self.emp_id = emp_id
        self.department = department
        self.experience = experience

Parametr self odkazuje na instanci třídy a atribut self.attribute inicializuje atribut instance na hodnotu na pravé straně.

Nyní můžeme vytvářet objekty jako:

employee_2 = Employee('Bella Joy','M007','Marketing',3)
print(employee_2)
# Output: <__main__.Employee object at 0x017F88B0>

Když vytiskneme objekty zaměstnanců, nezískáme žádné užitečné informace kromě třídy, do které patří. Pojďme přidat metodu __repr__, která definuje reprezentační řetězec pro třídu:

 def __repr__(self):
        return f"{self.full_name},{self.emp_id} from {self.department} with {self.experience} years of experience."

Přidáním __repr__ do třídy Zaměstnanec máme:

class Employee:
    def __init__(self, full_name,emp_id,department,experience):
        self.full_name = full_name
        self.emp_id = emp_id
        self.department = department
        self.experience = experience
    
     def __repr__(self):
        return f"{self.full_name},{self.emp_id} from {self.department} with {self.experience} years of experience."

Nyní mají objekty zaměstnanců užitečný reprezentační řetězec:

print(employee_2)
# Output: Bella Joy,M007 from Marketing with 3 years of experience.

Některé úmluvy

Než budeme pokračovat dále, zde je několik poznámek:

  • Self jsme použili jako první parametr v metodě __init__ k odkazování na samotnou instanci třídy a použili jsme self.attribute_name k inicializaci různých atributů. Preferovanou konvencí je použití self (můžete však použít jakékoli jiné jméno).
  • Při definici metody __init__ nastavujeme názvy parametrů v definicích __init__ tak, aby odpovídaly jménům atributů. To zlepšuje čitelnost.

Jak přidat výchozí hodnoty pro atributy

V příkladu, který jsme dosud kódovali, jsou všechny atributy povinné. To znamená, že vytvoření objektu je úspěšné pouze tehdy, když konstruktoru předáme hodnoty všech polí.

Pokuste se vytvořit instanci objektu třídy Employee, aniž byste předali hodnotu pro atribut experience:

employee_3 = Employee('Jake Lee','E001','Engineering')

Zobrazí se následující chyba:

Traceback (most recent call last):
  File "main.py", line 22, in <module>
    employee_3 = Employee('Jake Lee','E001','Engineering')
TypeError: __init__() missing 1 required positional argument: 'experience'

Pokud však chcete, aby některé atributy byly nepovinné, můžete tak učinit zadáním výchozích hodnot pro tyto atributy při definování metody __init__.

Zde poskytujeme výchozí hodnotu 0 pro atribut experience:

class Employee:
    def __init__(self, full_name,emp_id,department,experience=0):
        self.full_name = full_name
        self.emp_id = emp_id
        self.department = department
        self.experience = experience
    
     def __repr__(self):
        return f"{self.full_name},{self.emp_id} from {self.department} with {self.experience} years of experience."

Objekt zaměstnanec_3 je vytvořen bez hodnoty pro atribut experience; výchozí hodnota 0 se používá pro zkušenost.

employee_3 = Employee('Jake Lee','E001','Engineering')
print(employee_3.experience)
# Output: 0

Alternativní konstruktory tříd pomocí metod tříd

Zatím jsme viděli pouze to, jak definovat metodu __init__ a nastavit výchozí hodnoty atributů, když je to potřeba. Víme také, že musíme v konstruktoru předat hodnoty pro požadované atributy.

  9 vývojářských hostitelských platforem pro nasazení aplikací SaaS

Někdy však mohou být hodnoty pro tyto proměnné instance (nebo atributy) dostupné v jiné datové struktuře, jako je n-tice, slovník nebo řetězec JSON.

Tak co budeme dělat?

Vezměme si příklad. Předpokládejme, že máme hodnoty proměnné instance ve slovníku Pythonu:

dict_fanny = {'name':'Fanny Walker','id':'H203','dept':'HR','exp':2}

Můžeme klepnout do slovníku a získat všechny atributy takto:

name = dict_fanny['name']
id = dict_fanny['id']
dept = dict_fanny['dept']
exp = dict_fanny['exp']

Poté můžete vytvořit objekt předáním těchto hodnot konstruktoru třídy:

employee_4 = Employee(name, id, dept, exp)
print(employee_4)
# Output: Fanny Walker,H203 from HR with 2 years of experience.

Pamatujte: musíte to udělat pro každý nový objekt, který vytvoříte. Tento přístup je neefektivní a rozhodně můžeme udělat lépe. Ale jak?

V Pythonu můžeme použít metody třídy jako konstruktory k vytvoření objektů třídy. K vytvoření metody třídy používáme dekorátor @classmethod.

Pojďme definovat metodu, která analyzuje slovník, získá hodnoty proměnných instance a použije je ke konstrukci objektů Employee.

    @classmethod
    def from_dict(cls,data_dict):
        full_name = data_dict['name']
        emp_id = data_dict['id']
        department = data_dict['dept']
        experience = data_dict['exp']
        return cls(full_name, emp_id, department, experience)

Když potřebujeme vytvořit objekty pomocí dat ze slovníku, můžeme použít metodu třídy from_dict().

💡 Všimněte si použití cls v metodě třídy místo self. Stejně jako používáme self k odkazování na instanci, cls se používá k odkazování na třídu. Také metody třídy jsou vázány na třídu a ne na objekty.

Když tedy zavoláme metodu třídy from_dict() k vytvoření objektů, zavoláme ji ve třídě Employee:

emp_dict = {'name':'Tia Bell','id':'S270','dept':'Sales','exp':3}
employee_5 = Employee.from_dict(emp_dict)
print(employee_5)
# Output: Tia Bell,S270 from Sales with 3 years of experience.

Nyní, pokud máme slovník pro každého z n zaměstnanců, můžeme použít metodu třídy from_dict() jako konstruktor pro vytváření instancí v objektech – aniž bychom museli získávat hodnoty instantních proměnných ze slovníku.

  19 Nejlepší Screen Recorder pro Mac

📝Poznámka k proměnným tříd

Zde jsme definovali metodu třídy, která je vázána na třídu a ne na jednotlivé instance. Podobně jako u metod tříd můžeme mít také proměnné třídy.

Stejně jako metody třídy jsou proměnné třídy vázány na třídu a ne na instanci. Když má atribut pevnou hodnotu pro všechny instance třídy, můžeme zvážit jejich definování jako proměnné třídy.

Nejčastější dotazy

1. Proč potřebujete metodu __init__ v Pythonu?

Metoda __init__ v definici třídy nám umožňuje inicializovat atributy nebo proměnné instance všech instancí třídy. Metoda __init__ je volána pokaždé, když je vytvořena nová instance třídy.

2. Můžete mít více metod __init__ ve třídě Pythonu?

Cílem více metod __init__ ve třídě Pythonu je poskytnout více konstruktorů, které vytvářejí instanci objektů. Nemůžete však definovat více metod __init__. Pokud definujete více metod __init__, druhá a nejnovější implementace přepíše první. Můžete však použít dekorátor @classmethod k definování metod třídy, které lze použít jako konstruktory pro vytváření instance objektů.

3. Co se stane, když nedefinujete metodu __init__ ve třídě?

Pokud nedefinujete metodu __init__, stále můžete vytvářet instance objektů. Budete však muset ručně přidat proměnné instance a přiřadit hodnoty každé z nich. Nebudete moci předat hodnoty pro proměnné instance v konstruktoru. To je nejen náchylné k chybám, ale také maří účel mít třídu jako plán, ze kterého můžeme vytvářet instance objektů.

4. Můžete mít výchozí hodnoty pro argumenty v metodě __init__?

Ano, při definování metody __init__ je možné zadat výchozí hodnoty pro jeden nebo více atributů. Poskytnutí výchozích hodnot pomáhá učinit tyto atributy v konstruktoru volitelnými. Atributy nabývají výchozích hodnot, když hodnoty těchto atributů nezadáme do konstruktoru.

5. Můžete upravit atributy mimo metodu __init__?

Ano, vždy můžete aktualizovat hodnotu atributu mimo metodu __init__. Po vytvoření konkrétní instance můžete také dynamicky přidávat nové atributy do instance.

Závěr

V tomto tutoriálu jsme se naučili používat metodu __init__ k inicializaci hodnot instančních proměnných. I když je to jednoduché, může se to opakovat – zvláště když máte hodně atributů.

Pokud máte zájem, můžete prozkoumat modul dataclasses. V Pythonu 3.7 a novějších můžete použít vestavěný modul datových tříd k vytvoření datových tříd, které ukládají data. Kromě výchozích implementací __init__ a dalších běžně používaných metod; přicházejí se spoustou skvělých funkcí pro tipy na typ, komplexní výchozí hodnoty a optimalizaci.

Dále se dozvíte více o if __name__==’__main__‘ v Pythonu.