Python: come si crea una sottoclasse da una superclasse?


Risposte:


89
# Initialize using Parent
#
class MySubClass(MySuperClass):
    def __init__(self):
        MySuperClass.__init__(self)

O, ancora meglio, l'uso della funzione incorporata di Python super()(vedere la documentazione di Python 2 / Python 3 per questo) potrebbe essere un metodo leggermente migliore per chiamare il genitore per l'inizializzazione:

# Better initialize using Parent (less redundant).
#
class MySubClassBetter(MySuperClass):
    def __init__(self):
        super(MySubClassBetter, self).__init__()

Oppure, la stessa identica cosa appena sopra, tranne che usando la forma di argomento zero di super(), che funziona solo all'interno di una definizione di classe:

class MySubClassBetter(MySuperClass):
    def __init__(self):
        super().__init__()

6
OTOH, alcune persone mettono in guardia super, specialmente per i nuovi programmatori Python (ad esempio, Lutz). Lo evito.
eric

6
L'unico motivo per evitare superè se non capisci le differenze tra come superfunziona in Python e come super/ parentfunziona in altri linguaggi. Certamente questo non è ovvio per le persone che provengono da altre lingue, ma non concluderei che questo lo qualifichi come qualcosa da "mettere in guardia". Si fa il lavoro. Funziona solo diversamente. Leggi cosa fa effettivamente in Python prima di lamentarti di ottenere risultati che non ti aspettavi.
TheAtomicOption

3
Qual è la differenza tra i due?
Tiwtiw


65

Un piccolo esempio eroico:

class SuperHero(object): #superclass, inherits from default object
    def getName(self):
        raise NotImplementedError #you want to override this on the child classes

class SuperMan(SuperHero): #subclass, inherits from SuperHero
    def getName(self):
        return "Clark Kent"

class SuperManII(SuperHero): #another subclass
    def getName(self):
       return "Clark Kent, Jr."

if __name__ == "__main__":
    sm = SuperMan()
    print sm.getName()
    sm2 = SuperManII()
    print sm2.getName()

37
class MySubClass(MySuperClass):
    def __init__(self):
        MySuperClass.__init__(self)

        # <the rest of your custom initialization code goes here>

La sezione sull'ereditarietà nella documentazione di python lo spiega in maggior dettaglio


5
Hai solo bisogno di definire quel __init__metodo se vuoi aggiungere ulteriore codice ad esso, altrimenti viene utilizzato comunque il metodo originale init (anche se vale la pena menzionarlo ed è un codice perfettamente valido)
dbr

2
Penso che la domanda fosse abbastanza vaga da presumere che potesse essere aggiunto ulteriore codice. Meglio fornire troppe informazioni che non abbastanza e finire con un'altra domanda quando l'OP le implementa. :)
Matt Dewey

15
class Class1(object):
    pass

class Class2(Class1):
    pass

Class2 è una sottoclasse di Class1


Freddo. Questo è quello che stavo effettivamente cercando, cioè una sottoclasse senza estensioni / sostituzioni al super.
BuvinJ

9

Nelle risposte precedenti, superviene inizializzato senza argomenti (parola chiave). Spesso, tuttavia, ti piacerebbe farlo, oltre a trasmettere alcuni tuoi argomenti "personalizzati". Ecco un esempio che illustra questo caso d'uso:

class SortedList(list):
    def __init__(self, *args, reverse=False, **kwargs):
        super().__init__(*args, **kwargs)       # Initialize the super class
        self.reverse = reverse
        self.sort(reverse=self.reverse)         # Do additional things with the custom keyword arguments

Questa è una sottoclasse di listcui, una volta inizializzata, si ordina immediatamente nella direzione specificata reversedall'argomento della parola chiave, come illustrano i seguenti test:

import pytest

def test_1():
    assert SortedList([5, 2, 3]) == [2, 3, 5]

def test_2():
    SortedList([5, 2, 3], reverse=True) == [5, 3, 2]

def test_3():
    with pytest.raises(TypeError):
        sorted_list = SortedList([5, 2, 3], True)   # This doesn't work because 'reverse' must be passed as a keyword argument

if __name__ == "__main__":
    pytest.main([__file__])

Grazie al passaggio di *argsa super, la lista può essere inizializzata e popolata con elementi invece di essere solo vuota. (Notare che reverseè un argomento di sola parola chiave in conformità con PEP 3102 ).


4

C'è un altro modo per creare sottoclassi in Python dinamicamente con una funzione type():

SubClass = type('SubClass', (BaseClass,), {'set_x': set_x})  # Methods can be set, including __init__()

Di solito si desidera utilizzare questo metodo quando si lavora con le metaclassi. Quando vuoi fare alcune automazioni di livello inferiore, questo cambia il modo in cui python crea la classe. Molto probabilmente non avrai mai bisogno di farlo in questo modo, ma quando lo farai, saprai già cosa stai facendo.


3
class Subclass (SuperClass):
      # Subclass stuff here



1
class BankAccount:

  def __init__(self, balance=0):
    self.balance = int(balance)

  def checkBalance(self): ## Checking opening balance....
    return self.balance

  def deposit(self, deposit_amount=1000): ## takes in cash deposit amount and updates the balance accordingly.
    self.deposit_amount = deposit_amount
    self.balance += deposit_amount
    return self.balance

  def withdraw(self, withdraw_amount=500): ## takes in cash withdrawal amount and updates the balance accordingly
    if self.balance < withdraw_amount: ## if amount is greater than balance return `"invalid transaction"`
        return 'invalid transaction'
    else:
      self.balance -= withdraw_amount
      return self.balance


class MinimumBalanceAccount(BankAccount): #subclass MinimumBalanceAccount of the BankAccount class

    def __init__(self,balance=0, minimum_balance=500):
        BankAccount.__init__(self, balance=0)
        self.minimum_balance = minimum_balance
        self.balance = balance - minimum_balance
        #print "Subclass MinimumBalanceAccount of the BankAccount class created!"

    def MinimumBalance(self):
        return self.minimum_balance

c = BankAccount()
print(c.deposit(50))
print(c.withdraw(10))

b = MinimumBalanceAccount(100, 50)
print(b.deposit(50))
print(b.withdraw(10))
print(b.MinimumBalance())

5
Questa risposta sarebbe più utile se includessi una spiegazione di ciò che fa
grooveplex

4
Sebbene questo codice possa aiutare a risolvere il problema, non spiega perché e / o come risponde alla domanda. Fornire questo contesto aggiuntivo migliorerebbe notevolmente il suo valore educativo a lungo termine. Si prega di modificare la risposta di aggiungere spiegazioni, tra cui quello che si applicano le limitazioni e le assunzioni.
Toby Speight

2
Sebbene questo frammento di codice possa risolvere la domanda, includere una spiegazione aiuta davvero a migliorare la qualità del tuo post. Ricorda che stai rispondendo alla domanda per i lettori in futuro e quelle persone potrebbero non conoscere i motivi del tuo suggerimento sul codice.
andreas

0

La creazione di sottoclassi in Python viene eseguita come segue:

class WindowElement:
    def print(self):
        pass

class Button(WindowElement):
    def print(self):
        pass

Ecco un tutorial su Python che contiene anche classi e sottoclassi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.