In Python können Klassenmethoden und statische Methoden mithilfe von Dekoratoren wie "@ classmethod" und "@ staticmethod" definiert werden. Auf der anderen Seite kann eine normale Methode (Instanzmethode) normal definiert werden, aber tatsächlich kann sie auf zwei Arten aufgerufen werden:
class MyClass:
def mymethod(self,x):
print(x)
x = 1
myclass = MyClass()
myclass.mymethod(x) #Normaler Gebrauch
MyClass(None,1) # !?!?
Die zweite Verwendung besteht darin, die definierte Funktion so zu verwenden, wie sie ist (das erste Argument ist "self", aber da es in der Funktion nicht verwendet wird, ist "None" in Ordnung).
Obwohl es sich um eine Instanzmethode handelt, führt dies zu einem verwirrenden Fehler, wenn Sie sie versehentlich wie eine Klassenmethode aufrufen.
Zum Beispiel, wenn Sie mehrere Argumente wie unten gezeigt verwenden:
class MyClass:
def mymethod(self,*x):
print(x)
x = list(range(4))
myclass = MyClass()
myclass.mymethod(*x) # [0,1,2,3]
MyClass.mymethod(*x) # [1,2,3]
Um dies zu vermeiden, möchte ich wütend sein, wenn ich es so etwas wie das zweite nenne.
](https://stackoverflow.com/questions/3589311/get-defining-class-of-unbound-method-object-in-python-3)
import functools
import inspect
# a.x -> type(a).__dict__['x'].__get__(a, type(a))
# A.x -> A.__dict__['x'].__get__(None, A)
#
# --> __get__
#.__dict__['x'][Referenz 1: stackoverflow- "Definieren der Klasse eines ungebundenen Methodenobjekts in Python 3" [Referenz 2: Beherrschen von Python - Wer konvertiert von einer Methode in eine Funktion? ](Https://python.ms/descriptor/#%E7%96%91%E5%95%8F-get-%E3%83%A1%E3%82%BD%E3%83%83%E3%83 % 89% E3% 81% A3% E3% 81% A6% E3% 81% AA% E3% 81% AB% EF% BC% 9F) Definieren Sie einen Dekorateur. Wenn das erste Argument von None ist, wenn es von der Klasse aufgerufen wird. Also zu A.__get__Wenn Sie das Objekt mit verlassen
#Sie können es gut hacken. Jedoch,__get__(obe,objtype)Achten Sie auch auf den Rückgabewert von.
# a.Für x muss der Rückgabewert eine Methode sein. Mit anderen Worten, das mit dem ersten Argument der Funktion festgelegt.
# A.Wenn es x ist, mach dir keine Sorgen (mach es zu einem Fehler).
#def pure_instancemethod(func):
# functools.wraps(func)
# def wrapped_func(self,*args,**kwargs):
# if not isinstance(self,)
# raise TypeError("Keine Klassenmethode")
class PureInstanceMethod:
def __init__(self,func):
self.func = func
def __get__(self,obj,objtype):
if obj is None: #Anruf aus der Klasse:
raise TypeError("Rufen Sie nicht aus der Klasse Octopus an")
else: #Aufruf von der Instanz
def instancemethod(*args,**kwargs):
return self.func(obj,*args,**kwargs)
return instancemethod #Ich werde die Methode zurückgeben
def __call__(self,*args,**kwargs):
return self.func(*args,**kwargs)
class MyClass:
@PureInstanceMethod
def mymethod(self,*x):
print(x)
# MyClass.__dict__["mymethod"] = pureinstancemethod(mymethod)Fast das gleiche wie.
#Mit anderen Worten, hier ist eine Instanz der von mymethod initialisierten reinen Instanzmethode.
myclass.mymethod(*[1,2,3])
# > (1, 2, 3)
MyClass.mymethod(*[1,2,3])
# > ---------------------------------------------------------------------------
# > TypeError Traceback (most recent call last)
# > <ipython-input-152-99447b4e3435> in <module>
# > ----> 1 MyClass.mymethod(*[1,2,3]) # [1,2,3]
# >
# > <ipython-input-147-39b9424a9215> in __get__(self, obj, objtype)
# > 23 def __get__(self,obj,objtype):
# > 24 if obj is None: #Anruf aus der Klasse:
# > ---> 25 raise TypeError("Rufen Sie nicht aus der Klasse Octopus an")
# > 26
# > 27 else: #Aufruf von der Instanz
# >
# > TypeError:Rufen Sie nicht aus der Klasse Octopus an
Ich war sicher wütend.