Python3 元类:用于验证构造函数参数
Python3 metaclass: use to validate constructor argument
我打算使用 metaclass 来验证 Python3 中的构造函数参数,但似乎 __new__
方法无法访问变量 val
,因为class A()
尚未实例化。
Sow 正确的做法是什么?
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)
... it seems __new__method has no access to the variable val, because the class A() has not been instantiated yet.
完全正确。
So what's the correct way to do it?
没有元数据class。
Metaclasses 用于摆弄 class 对象本身的创建,而你想要做的与 instances 有关class。
最佳做法: 根本不要 type-check val
。 Pythonic 代码是 duck-typed。只需记录您期望 string-like 参数,然后将垃圾放入的用户将垃圾取出。
,但肯定可能(也很容易)。
考虑如何创建 class 的新实例。你这样做:
A(123)
换句话说:您通过调用 class 创建一个实例。 python 允许我们通过定义 __call__
method 来创建自定义可调用对象。所以我们要做的就是在我们的 metaclass:
中实现一个合适的 __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
我打算使用 metaclass 来验证 Python3 中的构造函数参数,但似乎 __new__
方法无法访问变量 val
,因为class A()
尚未实例化。
Sow 正确的做法是什么?
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)
... it seems __new__method has no access to the variable val, because the class A() has not been instantiated yet.
完全正确。
So what's the correct way to do it?
没有元数据class。
Metaclasses 用于摆弄 class 对象本身的创建,而你想要做的与 instances 有关class。
最佳做法: 根本不要 type-check val
。 Pythonic 代码是 duck-typed。只需记录您期望 string-like 参数,然后将垃圾放入的用户将垃圾取出。
考虑如何创建 class 的新实例。你这样做:
A(123)
换句话说:您通过调用 class 创建一个实例。 python 允许我们通过定义 __call__
method 来创建自定义可调用对象。所以我们要做的就是在我们的 metaclass:
__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