2009-10-22 36 views
54

En Python, ¿cómo se hace una subclase de una superclase?Python: ¿Cómo hago una subclase de una superclase?

+3

Tenga en cuenta que el Python cambió la forma en que hace la creación de subclases, por lo que hay 2 formas de hacerlo y no se mezclan. Obtendrás un error si mezclas. Lea esta publicación para ver la diferencia: http: // stackoverflow.com/questions/1713038/super-failed-with-error-typeerror-argument-1-must-be-type-not-classobj –

Respuesta

1
class Subclass (SuperClass): 
     # Subclass stuff here 
8
class Class1(object): 
    pass 

class Class2(Class1): 
    pass 

Clase 2 es una sub-clase de Class1

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

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

El section on inheritance en la documentación de Python explica con más detalle

+2

Solo necesita definir ese método '__init__' si desea agregarle más código, de lo contrario el método init original se usa de todos modos (aunque vale la pena mencionarlo, y es un código perfectamente válido) – dbr

+2

Creo que la pregunta era lo suficientemente vaga como para suponer que podría haber más código agregado. Es mejor proporcionar demasiada información que no lo suficiente y terminar con otra pregunta cuando el OP la implemente. :) –

2
class Mammal(object): 
#mammal stuff 

class Dog(Mammal): 
#doggie stuff 
0

subclases en Python se realiza de la siguiente manera:

class WindowElement: 
    def print(self): 
     pass 

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

Aquí es una tutorial sobre Python que también contiene las clases y subclases.

50

Un poco heroico ejemplo:

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() 
+1

sí, por usar nombres específicos para hacer que un concepto sea más fácil de digerir. –

60

El uso de "super" (ver Python Built-in, super) puede ser un poco mejor método de llamar a los padres para la inicialización:

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

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

OTOH, algunas personas advierten contra 'super', especialmente para los nuevos programadores de Python (por ejemplo, Lutz). Lo evito – neuronet

+0

La única razón para evitar 'super' es si no comprende las diferencias entre cómo funciona' super' en Python, y cómo 'super' /' parent' funciona en otros idiomas. Es cierto que esto no es obvio para las personas que provienen de otros idiomas, pero no concluiría que eso lo califique como algo para "prevenir contra". * * Funciona * Simplemente funciona de manera diferente. Simplemente lea sobre lo que realmente hace en Python antes de quejarse sobre obtener resultados que no esperaba. – TheAtomicOption

2

Hay otra manera de hacer las subclases en pitón de forma dinámica con una función type():

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

Por lo general, desea utilizar este método cuando trabaje con metaclases. Cuando quieres hacer algunas automatizaciones de nivel inferior, eso altera la forma en que python crea la clase. Lo más probable es que nunca necesites hacerlo de esta manera, pero cuando lo haces, entonces ya sabrás lo que estás haciendo.

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()) 
+4

Esta respuesta sería más útil si incluyó una explicación de lo que hace – grooveplex

+3

Aunque este código puede ayudar a resolver el problema, no explica _por qué_ y/o_ cómo_ responde la pregunta. Proporcionar este contexto adicional mejoraría significativamente su valor educativo a largo plazo. Por favor [edite] su respuesta para agregar una explicación, incluyendo qué limitaciones y suposiciones se aplican. –

+2

Si bien este fragmento de código puede resolver la pregunta, [incluyendo una explicación] (http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) realmente ayuda a mejorar la calidad de su publicación. Recuerde que usted está respondiendo la pregunta a los lectores en el futuro, y es posible que esas personas no sepan los motivos de su sugerencia de código. – andreas

2

En las respuestas anteriores, el super se inicializa sin argumentos (palabra clave). A menudo, sin embargo, le gustaría hacer eso, así como transmitir algunos argumentos 'personalizados'. Este es un ejemplo que ilustra este caso de 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 

Esta es una subclase de list que, cuando se inicializa, ordena inmediatamente en sí en la dirección especificada por el argumento reverse palabra clave, como los siguientes ensayos ilustran:

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__]) 

Gracias a la transferencia de *args a super, la lista se puede inicializar y completar con elementos en lugar de estar vacía. (Tenga en cuenta que reverse es un argumento de palabra clave solo de acuerdo con PEP 3102).

Cuestiones relacionadas