2016-06-29 14 views
8

Ich versuche, eine Funktion an anderer Stelle zu einer Klassenvariablen definiert zuweisen, damit ich es später in eine der Methoden der Instanz aufrufen können, wie folgt aus:zuordnen externe Funktion Klassenvariable in Python

from module import my_func 

class Bar(object): 
    func = my_func 
    def run(self): 
     self.func() # Runs my function 

Die Problem ist, dass dies fehlschlägt, denn wenn self.func() getan wird, dann wird die Instanz als erster Parameter übergeben.

Ich bin mit einem Hack gekommen, aber scheint hässlich zu mir, hat jeder eine Alternative?

In [1]: class Foo(object): 
    ...:  func = lambda *args: args 
    ...:  def __init__(self): 
    ...:   print(self.func()) 
    ...: 

In [2]: class Foo2(object): 
    ...:  funcs = [lambda *args: args] 
    ...:  def __init__(self): 
    ...:   print(self.funcs[0]()) 
    ...: 

In [3]: f = Foo() 
(<__main__.Foo object at 0x00000000044BFB70>,) 

In [4]: f2 = Foo2() 
() 

Edit: Das Verhalten unterscheidet sich mit eingebauten Funktionen! ihnen eine Instanz veranlasst sie gebunden zu sein als Methoden

In [13]: from math import pow 

In [14]: def pow_(a, b): 
    ....:  return pow(a, b) 
    ....: 

In [15]: class Foo3(object): 
    ....:  func = pow_ 
    ....:  def __init__(self): 
    ....:   print(self.func(2, 3)) 
    ....: 

In [16]: f3 = Foo3() 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-16-c27c8778655e> in <module>() 
----> 1 f3 = Foo3() 

<ipython-input-15-efeb6adb211c> in __init__(self) 
     2  func = pow_ 
     3  def __init__(self): 
----> 4   print(self.func(2, 3)) 
     5 

TypeError: pow_() takes exactly 2 arguments (3 given) 

In [17]: class Foo4(object): 
    ....:  func = pow 
    ....:  def __init__(self): 
    ....:   print(self.func(2, 3)) 
    ....: 

In [18]: f4 = Foo4() 
8.0 

Antwort

13

Python Funktionen sind descriptor objects, und als Attribute für eine Klasse zugreift.

Wenn Sie dies verhindern wollen, verwenden Sie die staticmethod function die Funktion in einem anderen Deskriptor zu wickeln, die nicht auf die Instanz nicht bindet:

class Bar(object): 
    func = staticmethod(my_func) 
    def run(self): 
     self.func() 

Alternativ greifen Sie auf die ungebundene Funktion über das __func__ Attribut auf die Methode:

def run(self): 
    self.func.__func__() 

oder direkt auf die Klasse __dict__ Attribut gehen, um das Deskriptor-Protokoll ganz zu umgehen:

Wie für math.pow, das ist keine Python Funktion, in der es in C-Code geschrieben wird. Die meisten eingebauten Funktionen sind in C geschrieben und die meisten sind keine Deskriptoren.

+0

Der letzte Codeblock schlägt fehl ('Balkenobjekt hat keine Attributleiste') und wenn ich' self' lösche, dann bekomme ich 'TypeError: ungebundene Methode muss mit Instanz als erstes Argument aufgerufen werden' – astrojuanlu

+0

@astrojuanlu: ah, yes , Entschuldigung, Python 2. Ich werde diese Option aktualisieren, um das Deskriptor-Protokoll zu umgehen. –

+0

Funktioniert jetzt, danke! – astrojuanlu

Verwandte Themen