2016-10-12 5 views
0

Kann ich mit einer Mixinklasse ein benanntes Schlüsselwort zur Signatur einer Funktion in der Basis hinzufügen? Im Moment kann ich nicht herausfinden, wie die Unterschrift des Basisfunktionsüberschreiben zu vermeiden:Hinzufügen eines benannten Schlüsselworts zu einer Funktionssignatur

from inspect import signature 

class Base(object): 
    def __init__(self, foo='bar', **kwargs): 
     pass 

class Mixin(base): 
    def __init__(self, foo2='bar2', **kwargs): 
     super(Mixin, self).__init__(**kwargs) 

class P(Mixin, Base): 
    pass 

print(signature(P.__init__)) 


# Output: (self, foo2='bar2', **kwargs) 

$ Desired output: (self, foo1='bar1', foo2='bar2', **kwargs) 

bearbeiten Danke für die Antworten bisher leider muss ich tatsächlich den benannten Parameter an die Funktion Signatur hinzuzufügen, während Außerdem werden die benannten Parameter von der ursprünglichen Basisfunktionssignatur beibehalten (und diese variieren abhängig von der Basis). Der Grund ist, dass die signature is used elsewhere for intraspection to extract the parameter names.: Wird dies in der __init__ Methode möglich sein? Hier

ist eine (schreckliche) Teillösung, die die Unterschrift auf Instanzen ändert, aber nicht auf die Klasse selbst, auch ist es **kwargs aus irgendeinem Grund fehlt:

class Mixin(Base): 
    def __init__(self, foo2='bar2', **kwargs): 
     super(Mixin, self).__init__(**kwargs) 
     sig = signature(super(Mixin, self).__init__) 
     params = {k:v.default for k,v in sig.parameters.items() if v.default != _empty} 
     params['foo2'] = 'bar2' 
     argstring = ",".join("{}='{}'".format(k,v) for k,v in params.items()) 
     exec("def new_init({}, **kwargs): self.__init__(**kwargs)".format(argstring)) 
     self.__init__ = new_init 


class P(Mixin, Base): 
    pass 

p = P() 
print(signature(p.__init__)) 
# (foo2='bar2', foo='bar') 
+0

Sie nicht die Basis Signatur zu überschreiben vermeiden, können Sie überschreibe die ganze Sache. – jonrsharpe

Antwort

0

Wenn Subklassen, können Sie entweder erweitern oder Überschreiben Sie die Methoden der Superklasse, aber Sie können sie nicht direkt modifizieren. Das Überschreiben wird erreicht, indem einfach eine neue Methode mit demselben Namen geschrieben wird; Die Erweiterung wird erreicht, indem Sie die Methode überschreiben und dann die Methode der Oberklasse als Teil Ihrer Ersetzung aufrufen.

Hier sind zwei Klassen, von denen die zweite eine Methode überschreibt und sich eine andere:

class A: 
    def method1(self): 
     print("Method A.1 called") 
    def method2(self, arg1): 
     print("Method A.2 called with argument", arg1) 

class B(A): 
    def method1(self): 
     print("Method B.1 called") 
    def method2(self, arg1, arg2="keyword arg"): 
     print("Method B.1 called with arg1=", arg1, "arg2=", arg2) 
     super().method2(arg1) 
     print("Extended method complete") 

diese Verwendung in einem interaktiven Kontext wir folgendes sehen:

>>> b = B() 
>>> b.method1() 
Method B.1 called 
>>> b.method2("first", arg2="second") 
Method B.1 called with arg1= first arg2= second 
Method A.2 called with argument first 
Extended method complete 

* Technisch möglich ist es in Python, aber der Code wäre hässlich und sowieso würden alle Änderungen an der Oberklasse von allem gesehen werden, der Oberklasse verwendet.

0

@jonrsharpe beantwortet dies im Kommentar, aber wenn Sie einen Parameter benötigen möchten können Sie dies als eine dynamische Kontrolle in der Methode des mixin tun:

class Base(object): 
    def __init__(self, foo='bar', **kwargs): 
     pass 

class Mixin(base): 
    def __init__(self, **kwargs): 
     kwargs.pop('required_param') 
     kwargs.pop('optional_param', None) 
     super(Mixin, self).__init__(**kwargs) 

class P(Mixin, Base): 
    pass 
+0

danke für die Antwort, ich habe meine Frage mit ein wenig mehr Klarstellung bearbeitet, ist es möglich, den neuen Schlüsselwortparameter in der Signatur selbst genannt zu bekommen? – maxymoo

Verwandte Themen