2013-08-06 12 views
7

manchmal habe ich Klasse mit statischen Methoden schreiben muß, jedoch mit der Möglichkeit, es zu initialisiert und Zustand zu halten (Objekt)Python: Hybrid zwischen regulären Verfahren und Class

etw wie:

class A: 
    @classmethod 
    def method(cls_or_self): 
    # get reference to object when A().method() or to class when A.method() 
    code 

was ich habe jetzt ist:

class A: 
    def method(self = None, *params): code 
    # or 
    def method2(self = None, **params): code 
    # but what I need is rather normal parameters, not optional and named args: 
    def method3(self_or_cls, a, b=1, c=2, *p, **kw): code 

bitte schreiben Sie nicht über die Unterschiede zwischen static und Class. Ich bin interessiert, ob ein solcher Dekorator existiert (in mehr oder weniger Standard-Bibliotheken) und ob darüber hinaus für PEP geeignet ist.

+2

bedeuten Sie ein Hybrid zwischen einem Class und einem * regelmäßige * Methode. –

Antwort

17

Funktionen und Objekte fungieren als descriptors; beide geben einen Wrapper zurück, der beim Aufruf wiederum die zugrunde liegende Funktion mit einem zusätzlichen Parameter aufruft. Der einzige Unterschied zwischen Funktionen und Objekten besteht darin, dass der zusätzliche Parameter ist.

Um ein Hybrid der beiden Ansätze zu schaffen, bauen Sie Ihre eigenen Descriptor Dekorateur:

from functools import wraps 

class hybridmethod(object): 
    def __init__(self, func): 
     self.func = func 

    def __get__(self, obj, cls): 
     context = obj if obj is not None else cls 

     @wraps(self.func) 
     def hybrid(*args, **kw): 
      return self.func(context, *args, **kw) 

     # optional, mimic methods some more 
     hybrid.__func__ = hybrid.im_func = self.func 
     hybrid.__self__ = hybrid.im_self = context 

     return hybrid 

Hier kehren wir einen Wrapper, der entweder die Klasse oder die Instanz als ersten Parameter verwenden werden, je nachdem, was ist verfügbar, wenn der Deskriptor Methode aufgerufen wird.

Demo:

>>> class Foo(object): 
...  @hybridmethod 
...  def bar(cls_or_self): 
...   print 'Called with cls_or_self={!r}'.format(cls_or_self) 
... 
>>> Foo.bar() 
Called with cls_or_self=<class '__main__.Foo'> 
>>> Foo().bar() 
Called with cls_or_self=<__main__.Foo object at 0x1043a4390> 
+0

... so schnell und erstaunlich, dass ich warten muss, um die Antwort zu akzeptieren (stackoverflow reqs), aber was ist mit der Klassenmethode? - Für mich oben Dekorator sieht sehr funktional aus, sogar zu empfehlen, die Klassierung zu überschreiben oder dritten Standard-Dekorator für Methoden hinzuzufügen. Ich weiß, dass es starke Kritik erfordert. –

+0

Der Dekorateur "Klassenmethode" dient einem anderen Ziel; Methoden, die mehrdeutig sind bezüglich ihres Verhaltens (handeln auf die eine oder andere Art basierend auf dem Kontext) sind nicht zu pythonisch. –

Verwandte Themen