【问题标题】:How to turn python method into setter with the help of metaclass?如何在元类的帮助下将python方法变成setter?
【发布时间】:2022-01-18 06:42:38
【问题描述】:

我是元类的新手,很抱歉,如果我的问题有点愚蠢。我需要创建一个元类,它采用类的特定方法并将它们转换为属性方法或设置器。所以,如果我有

class TestClass():
    def __init__(self, x: int):
        self._x = x

    def get_x(self):
        print("this is property")
        return self._x

    def set_x(self, x: int):
        print("this is setter")
        self._x = x

我希望它像这样工作:

class TestClass():
    def __init__(self, x: int):
        self._x = x

    @property
    def x(self):
        print("this is property")
        return self._x

    @x.setter
    def x(self, x: int):
        print("this is setter")
        self._x = x

现在我刚刚意识到如何将它用于财产:

class PropertyConvert(type):
    def __new__(cls, future_class_name, future_class_parents, future_class_attr):
        new_attr = {}
        for name, val in future_class_attr.items():
            if not name.startswith('__'):
                if name.startswith('get_'):
                    new_attr[name[4:]] = property(val)
                if name.startswith('set_'):
                    # ???
            else:
                new_attr[name] = val
        return type.__new__(cls, future_class_name, future_class_parents, new_attr)

但我不知道如何为二传手做这件事。

【问题讨论】:

    标签: python properties setter metaclass


    【解决方案1】:

    我强烈推荐docs about descriptors,它们写得非常好,解释了许多类似的例子。

    但要回答您的问题,要使 setter 工作,您需要使用相同的 property 函数但填充第二个参数。

    类属性(fget=None, fset=None, fdel=None, doc=None)

    所以代码可能是这样的:

    class PropertyConvert(type):
        def __new__(cls, future_class_name, future_class_parents, future_class_attr):
            new_attr = {}
            fget, fset, property_name = None, None, None
            for name, val in future_class_attr.items():
                if not name.startswith("__"):
                    if name.startswith("get_"):
                        property_name = name[4:]
                        fget = val
                    if name.startswith("set_"):
                        property_name = name[4:]
                        fset = val
                else:
                    new_attr[name] = val
            if n:
                new_attr[property_name] = property(fget, fset)
            return type.__new__(cls, future_class_name, future_class_parents, new_attr)
    
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-08
    • 2014-05-02
    • 2020-10-29
    • 2019-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多