2008-12-09 19 views
20

¿Cómo puedo extender una clase incorporada en python? Me gustaría agregar un método a la clase str.
He hecho algunas búsquedas pero todo lo que estoy buscando son publicaciones antiguas, espero que alguien sepa algo más nuevo.Extendiendo clases incorporadas en python

+0

posible duplicado de [¿Puedes aplicar los métodos de parche en los tipos de núcleo en python?] (http://stackoverflow.com/questions/192649/can-you-monkey-patch-methods-on-core-types-in-python) – jfs

+0

Ver también sanxiyn

Respuesta

20

Sólo subclase del tipo

>>> class X(str): 
...  def myMethod(self): 
...    return int(self) 
... 
>>> s=X("Hi Mom") 
>>> s.lower() 
'hi mom' 
>>> s.myMethod() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 3, in myMethod 
ValueError: invalid literal for int() with base 10: 'Hi Mom' 

>>> z=X("271828") 
>>> z.lower() 
'271828' 
>>> z.myMethod() 
271828 
+1

Tenía la esperanza de no tener que subclase, pero después de un poco más de investigación he llegado a la conclusión de que no es posible de otra manera, por lo que voy a aceptar esta respuesta. – UnkwnTech

+1

@Unkwntech: No se puede imaginar una mejor manera que la subclasificación. Seriamente. Cualquier cosa que tengas en mente (¿monopatch?) Nunca parece funcionar tan bien como una subclase clara, precisa y obvia. –

+5

@ S.Lott - Las clases abiertas de Ruby y los métodos de extensión de C# vienen a la mente. – orip

8

una posible alternativa sería utilizar el concepto "reapertura de clase" (de forma nativa existente en Ruby) que puede ser implementado en Python usando un decorador clase. Un exemple se da en esta página: http://www.ianbicking.org/blog/2007/08/opening-python-classes.html

cito:

Creo que con decoradores de clase que podría hacer esto:

@extend(SomeClassThatAlreadyExists) 
class SomeClassThatAlreadyExists: 
    def some_method(self, blahblahblah): 
     stuff 

implementa de la siguiente:

def extend(class_to_extend): 
    def decorator(extending_class): 
     class_to_extend.__dict__.update(extending_class.__dict__) 
     return class_to_extend 
    return decorator 
0

Suponiendo que no puede cambiar las clases integradas. para simular una "clase reapertura" como Ruby en python3 donde __dict__ es un objeto mappingproxy y el objeto no dict:

def open(cls): 
    def update(extension): 
    for k,v in extension.__dict__.items(): 
     if k != '__dict__': 
     setattr(cls,k,v) 
    return cls 
    return update 


class A(object): 
    def hello(self): 
    print('Hello!') 

A().hello() #=> Hello! 

#reopen class A 
@open(A) 
class A(object): 
    def hello(self): 
    print('New hello!') 
    def bye(self): 
    print('Bye bye') 


A().hello() #=> New hello! 
A().bye()  #=> Bye bye 

yo también podría escribir una función decoradora 'abierta', así:

def open(cls): 
    def update(extension): 
    namespace = dict(cls.__dict__) 
    namespace.update(dict(extension.__dict__)) 
    return type(cls.__name__,cls.__bases__,namespace) 
    return update 
Cuestiones relacionadas