如何在 Python 中以编程方式创建类方法?

How do I programmatically create class methods in Python?

提问人:Jacob Manaker 提问时间:2/1/2023 更新时间:2/1/2023 访问量:57

问:

假设我想定义一个 Python 类,其实例具有多个类似形式的成员:

class Bar:
    def __init__(self):
        self.baz=3
        self.x=1
        self.name=4

相反,我可以使用显式操作一次创建所有成员:__dict__

class Bar:
    def __init__(self):
        self.__dict__.update({name: len(name) for name in ("baz", "x", "name")})

但是,如果关联的成员是数据成员,而不是实例成员,那么我知道没有类似的编程方式进行突变:Bar.__dict__

class Bar:
    #Fails with "AttributeError: 'mappingproxy' object has no attribute 'update'"
    Bar.__dict__.update({name: len(name) for name in ("baz", "x", "name")})

在 Javascript 中,以编程方式操作构造函数的属性是可能的,因为构造函数只是普通函数,它们只是普通对象,因此只是一个可变的字典,将属性映射到更多对象。是否可以用 Python 编写类似的代码?

Python 命名空间

评论

1赞 Iain Shelvington 2/1/2023
setattr(Bar, 'baz', 3)似乎在 Python3.10 中工作?
0赞 Jacob Manaker 2/2/2023
@IainShelvington:令人着迷。我不记得了,我很惊讶它可以修改一个不可修改的字典。setattr

答:

0赞 zaki98 2/1/2023 #1

我想你可以使用元类,一个基类或用于创建你的类。下面是一个使用基类的示例:__init_subclass__eval

class Base:
    attrs_to_set: set[str] = set()

    def __init_subclass__(cls) -> None:
        for attr in cls.attrs_to_set:
            setattr(cls, attr, cls.get_attr_value(attr))

    @classmethod
    def get_attr_value(cls, attr_name: str):
        # default, you can change it depending on your use case i guess.
        return len(attr_name)


class Bar(Base):
    attrs_to_set = {"x", "baz", "name"}


print(Bar.x, Bar.name, Bar.baz)
# prints: 1 4 3

评论

0赞 Jacob Manaker 2/2/2023
这里的关键工具是可以修改,但是您的元类提供了我不需要等到类定义之后才能应用它的细节。泰!setattrBar.__dict__