我计划使用元类来验证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)
答案 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