Python 魔法元类创建

标签 python python-3.x object inheritance metaprogramming

基本上,我想用 staticmethods 创建一个"template"类型对象,然后创建一个继承自它但使用父方法的新对象 functools.partial 使用 child 的参数的地方。 child 的参数与父方法的参数同名。由此产生的范例将是这样的:

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)

最佳答案

我不知道如何用元类做到这一点,但这里有一个使用混合类的可能解决方案。您也许可以使用类似这样的东西。

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?"

关于Python 魔法元类创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50358462/

相关文章:

python - 从嵌套字典中删除元组键;避免运行时和类型错误

python - 在 Python 中将 unix 时间戳(长度 13)字符串转换为可读日期

python - __repr__ 应该返回字节还是 unicode?

python - 使用插值重新网格化纬度和经度

java - 我们可以将 Exception 类对象分配给 Object 类对象的引用吗

c++ - 访问用户定义类型数组的特定属性

javascript - Angular JS : Pushing objects into an array. 它正在创建一个对象,然后是另一个数组。我需要它来创建单独的对象。这可能吗?

python - 如何在 aws lambda 中执行 bash 命令

python - 将 conftest.py 文件拆分为几个较小的类似 conftest 的部分

python - 如何在我的夹层元素中升级 Bootstrap ?