方法可以匿名引用自身吗?
Can a method reference itself anonymously?
我刚刚写了一个小函数,returns 它自己的参数作为字典:
from inspect import signature
class MyClass:
def MyFunc(self, thing1=0, thing2=0, thing3=0, thing4="", thing5=""):
P = {}
for p in list(signature(self.MyFunc).parameters):
P[p] = eval(p)
return P
抛开 为什么 任何人都想这样做(并接受我已经从更广泛的背景中提炼出一个非常简单的例子来探索一个非常具体的问题),有那里有明确的参考 self.MyFunc。
我见过避免这种情况的复杂方法,例如:
globals()[inspect.getframeinfo(inspect.currentframe()).function]
和
globals()[sys._getframe().f_code.co_name]
但我想知道是否有像匿名 super()
构造 Python 提供引用父 class 中同名方法的东西,它可以优雅地允许一个函数匿名引用自己,即不必给自己命名。
我怀疑不是,从 Python 3.8 开始无法做到这一点。但认为这是一个值得 table 的问题,并探索并邀请纠正我的怀疑。
不存在这样的结构。函数中的代码没有特殊的方式来引用该函数。
在初始启动后,函数的执行实际上并不涉及函数本身。启动后,函数只需要代码对象,这是堆栈框架保持引用的唯一部分。您不能仅从代码对象恢复函数 - 许多函数可以共享相同的代码对象。
正如 user2357112 所说,您无法通过任何简单的方法从该函数中获取函数的名称,但是如果您 只是想要一个函数 return 它的作为 dict 的参数,你可以使用这个:
class MyClass:
def MyFunc(self,**kwargs):
return kwargs
或者如果您想要使用*args:
class MyClass:
def MyFunc(self,*args,**kwargs):
names=["thing%d"%i for i in range(1,6)]
for v,k in zip(args,names):
if k in kwargs:
raise ValueError
else:
kwargs[k]=v
return kwargs
使用包括当地人在内的骇客:
class MyClass:
def MyFunc(self, thing1=0, thing2=0, thing3=0, thing4="", thing5=""):
d=locals().copy()
del d["self"]
return d
您可以使用装饰器将参数列表添加到传递给方法的参数列表。
可以将相同的方法扩展到 class 装饰器中,该装饰器对 class.
的部分或全部方法执行此操作
这是单一方法装饰器的示例实现:
from inspect import signature
def add_paramlist(func):
paramlist = list(signature(func).parameters)
try:
paramlist.remove('paramlist')
except ValueError as exc:
raise RuntimeError(f'"paramlist" argument not declareed in signature of '
f'{func.__name__}() method') from exc
def wrapped(*args, **kwargs):
return func(paramlist, *args, **kwargs)
return wrapped
class MyClass:
@add_paramlist
def MyFunc(paramlist, self, thing1=0, thing2=0, thing3=0, thing4="", thing5=""):
P = {}
for p in paramlist:
P[p] = eval(p)
return P
from pprint import pprint
inst = MyClass()
res = inst.MyFunc(thing1=2, thing2=2, thing3=2, thing4="2", thing5="2")
pprint(res)
输出:
{'self': <__main__.MyClass object at 0x00566B38>,
'thing1': 2,
'thing2': 2,
'thing3': 2,
'thing4': '2',
'thing5': '2'}
我刚刚写了一个小函数,returns 它自己的参数作为字典:
from inspect import signature
class MyClass:
def MyFunc(self, thing1=0, thing2=0, thing3=0, thing4="", thing5=""):
P = {}
for p in list(signature(self.MyFunc).parameters):
P[p] = eval(p)
return P
抛开 为什么 任何人都想这样做(并接受我已经从更广泛的背景中提炼出一个非常简单的例子来探索一个非常具体的问题),有那里有明确的参考 self.MyFunc。
我见过避免这种情况的复杂方法,例如:
globals()[inspect.getframeinfo(inspect.currentframe()).function]
和
globals()[sys._getframe().f_code.co_name]
但我想知道是否有像匿名 super()
构造 Python 提供引用父 class 中同名方法的东西,它可以优雅地允许一个函数匿名引用自己,即不必给自己命名。
我怀疑不是,从 Python 3.8 开始无法做到这一点。但认为这是一个值得 table 的问题,并探索并邀请纠正我的怀疑。
不存在这样的结构。函数中的代码没有特殊的方式来引用该函数。
在初始启动后,函数的执行实际上并不涉及函数本身。启动后,函数只需要代码对象,这是堆栈框架保持引用的唯一部分。您不能仅从代码对象恢复函数 - 许多函数可以共享相同的代码对象。
正如 user2357112 所说,您无法通过任何简单的方法从该函数中获取函数的名称,但是如果您 只是想要一个函数 return 它的作为 dict 的参数,你可以使用这个:
class MyClass:
def MyFunc(self,**kwargs):
return kwargs
或者如果您想要使用*args:
class MyClass:
def MyFunc(self,*args,**kwargs):
names=["thing%d"%i for i in range(1,6)]
for v,k in zip(args,names):
if k in kwargs:
raise ValueError
else:
kwargs[k]=v
return kwargs
使用包括当地人在内的骇客:
class MyClass:
def MyFunc(self, thing1=0, thing2=0, thing3=0, thing4="", thing5=""):
d=locals().copy()
del d["self"]
return d
您可以使用装饰器将参数列表添加到传递给方法的参数列表。
可以将相同的方法扩展到 class 装饰器中,该装饰器对 class.
的部分或全部方法执行此操作这是单一方法装饰器的示例实现:
from inspect import signature
def add_paramlist(func):
paramlist = list(signature(func).parameters)
try:
paramlist.remove('paramlist')
except ValueError as exc:
raise RuntimeError(f'"paramlist" argument not declareed in signature of '
f'{func.__name__}() method') from exc
def wrapped(*args, **kwargs):
return func(paramlist, *args, **kwargs)
return wrapped
class MyClass:
@add_paramlist
def MyFunc(paramlist, self, thing1=0, thing2=0, thing3=0, thing4="", thing5=""):
P = {}
for p in paramlist:
P[p] = eval(p)
return P
from pprint import pprint
inst = MyClass()
res = inst.MyFunc(thing1=2, thing2=2, thing3=2, thing4="2", thing5="2")
pprint(res)
输出:
{'self': <__main__.MyClass object at 0x00566B38>,
'thing1': 2,
'thing2': 2,
'thing3': 2,
'thing4': '2',
'thing5': '2'}