2008-12-09 11 views
20

Comment étendre une classe interne en python? Je voudrais ajouter une méthode à la classe str.
J'ai fait quelques recherches, mais tout ce que je trouve est des messages plus anciens, j'espère que quelqu'un sait quelque chose de plus récent.Extension de classes intégrées en python

+0

possible duplicata de [Pouvez-vous des méthodes de patch singe sur les types de base en python?] (http://stackoverflow.com/questions/192649/can-you-monkey-patch-methods-on-core-types-in-python) – jfs

+0

Voir aussi sanxiyn

Répondre

20

Juste sous-classe du type

>>> 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

J'espérais que je n'aurais pas à sous-classe, mais après quelques recherches supplémentaires, je suis arrivé à la conclusion que ce n'est pas possible autrement, alors j'accepte cette réponse. – UnkwnTech

+1

@Unkwntech: Impossible d'imaginer une meilleure façon que le sous-classement. Sérieusement. Tout ce que vous avez en tête (monkeypatching?) Ne semble jamais fonctionner aussi bien qu'une sous-classe claire, précise et évidente. –

+5

@ S.Lott - Les classes ouvertes de Ruby et les méthodes d'extension C# me viennent à l'esprit. – orip

8

Une façon pourrait être d'utiliser le concept de « réouverture de classe » (native existant en Ruby) qui peut être mis en œuvre en Python à l'aide d'un décorateur de classe. Un exemple est donné dans cette page: http://www.ianbicking.org/blog/2007/08/opening-python-classes.html

Je cite:

Je pense avec des décorateurs de classe que vous pouvez faire:

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

Mis en œuvre comme ceci:

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

En supposant que vous ne pouvez pas modifier les classes intégrées. Pour simuler une « classe réouverture » comme Ruby dans python3 où __dict__ est un objet mappingproxy et non objet 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 

Je pourrais aussi écrire une fonction décorateur « ouverte » ainsi:

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