基本上,我想创建一个带有staticmethods
的“模板”类型对象,然后创建一个继承自它的新对象,但使用父项的方法使用functools.partial
,其中子项的参数是用过的。子对象的参数与父对象的参数具有相同的名称。由此产生的范例将是这样的:
class Naked:
@staticmethod
def echo1(foo):
return f"echo1: {foo}"
@staticmethod
def echo2(bar, bla):
return f"echo2: {bar}, {bla}"
class Clothed(Naked):
def __init__(self, *args, **kwargs):
for arg in args:
setattr(self, arg, arg)
for k,v in kwargs.items():
setattr(self, k, v)
a = Clothed(foo = "Hello", bar = "World")
a.echo1 == "echo1: Hello"
a.echo2("wsup?") == "echo2: World, wsup?"
以下尝试不起作用:
from inspect import signature
from functools import partial
class Meta(type):
def __init__(cls, name, bases, attrs):
funcs = (k for k,v in attrs.items() if callable(v) and k not in dir(type)) #this doesn't work...
for func in funcs:
args = signature(func).keys() #function argument names
newargs = {arg:getattr(self, arg, None) for arg in args} #create dictionary with val from instance, how is this possible, no self here?
attrs[func] = partial(func,newargs)
return type.__init__(cls, name, bases, attrs)
class Naked(metaclass=Meta):
@staticmethod
def echo1(foo):
return f"echo1: {foo}"
@staticmethod
def echo2(bar, bla):
return f"echo2: {bar}, {bla}"
class Clothed(Naked):
def __init__(self, *args, **kwargs):
for arg in args:
setattr(self, arg, arg)
for k,v in kwargs.items():
setattr(self, k, v)
答案 0 :(得分:2)
我不知道如何使用元类进行此操作,但这是使用mixin类的可能解决方案。你可以使用这样的东西。
from inspect import signature
from functools import partialmethod, partial
class Naked:
@staticmethod
def echo1(foo):
return f"echo1: {foo}"
@staticmethod
def echo2(bla, bar):
return f"echo2: {bar}, {bla}"
class PartialMixin:
def __init__(self, **kwargs):
methods = [m for m in dir(self) if callable(getattr(self, m)) and m not in dir(type)]
for method_name in methods:
method = getattr(self, method_name)
method_kwargs = signature(method).parameters.keys()
partial_kwargs = {k:kwargs[k] for k in kwargs if k in method_kwargs}
new_method = partial(method, **partial_kwargs)
# if the methods are not static, maybe functools.partialmethod should be used.
setattr(self, method_name, new_method)
class Clothed(PartialMixin, Naked):
pass
a = Clothed(foo = "Hello", bar = "World")
a.echo1() == "echo1: Hello"
a.echo2("wsup?") == "echo2: World, wsup?"