Python3元类:用于验证构造函数参数

时间:2018-03-23 17:55:36

标签: python python-3.x metaclass

我计划使用元类来验证Python3中的构造函数参数,但似乎__new__方法无法访问变量val,因为类A()尚未实例化然而。

播种正确的方法是什么?

class MyMeta(type):
    def __new__(cls, clsname, superclasses, attributedict):
        print("clsname: ", clsname)
        print("superclasses: ", superclasses)
        print("attributedict: ", attributedict)
        return type.__new__(cls, clsname, superclasses, attributedict)

class A(metaclass=MyMeta):
    def __init__(self, val):
        self.val = val

A(123)

2 个答案:

答案 0 :(得分:3)

  

...似乎__new__method无法访问变量val,因为类A()尚未实例化。

完全。

  

那么正确的做法是什么?

没有元类。

元类用于摆弄类对象本身的创建,您想要做的是与类的实例相关。

最佳做法:根本不要输入val。 Pythonic代码是duck-typed。简单地记录您期望类似字符串的参数,以及将垃圾放入垃圾箱的用户。

答案 1 :(得分:2)

wim is absolutely correct that this isn't a good use of metaclasses,但它确实可能(也很容易)。

考虑如何创建类的新实例。你这样做:

A(123)

换句话说:您通过调用类来创建实例。 python允许我们通过定义__call__ method来创建自定义可调用对象。所以我们要做的就是在我们的元类中实现一个合适的__call__方法:

class MyMeta(type):
    def __call__(self, val):
        if not isinstance(val, str):
            raise TypeError('val must be a string')

        return super().__call__(val)

class A(metaclass=MyMeta):
    def __init__(self, val):
        self.val = val

就是这样。简单,对吧?

>>> A('foo')
<__main__.A object at 0x007886B0>
>>> A(123)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "untitled.py", line 5, in __call__
    raise TypeError('val must be a string')
TypeError: val must be a string