我有一个类A,它子类str通过kwargs添加元数据
class A(str):
def __new__(cls, value, **kwargs):
obj = str.__new__(cls, value)
obj.__dict__.update(kwargs)
return obj
喜欢使用:
x = A('test', meta=10)
x.meta
10
现在,我也想处理unicode类型,所以我采用了以下方法.动态检查类型并将其用作base_class
class B(object):
def __new__(cls, value, **kwargs):
base_class = str if isinstance(value, str) else unicode
new_type = type(cls.__name__, (base_class,), dict(cls.__dict__))
obj = base_class.__new__(new_type, value)
obj.__dict__.update(kwargs)
return obj
但是,这似乎是不正确的做法.给我一个
TypeError: descriptor ‘dict‘ for ‘B’ objects doesn’t apply to ‘B’ object
B('test', meta=10)
-----------------------------------------------------------------------
TypeError Traceback (most recent call last)
in ()
----> 1 B('tes', a=10).a
in __new__(cls, value, **kw)
11 new_type = type(cls.__name__, (base_class,), dict(cls.__dict__))
12 obj = base_class.__new__(new_type, value)
---> 13 obj.__dict__.update(kw)
14 return obj
15
TypeError: descriptor '__dict__' for 'B' objects doesn't apply to 'B' object
我可以使用setattr代替C语言,这很好.
class C(object):
def __new__(cls, value, **kw):
base_class = str if isinstance(value, str) else unicode
new_type = type(cls.__name__, (base_class,), dict(cls.__dict__))
obj = base_class.__new__(new_type, value)
for k, v in kw.items():
setattr(obj, k, v)
return obj
x = C('test', meta=10)
x.meta
10
你能帮我理解我在B级上错过了什么以及如何使用__dict__吗?
最佳答案 发生此错误的原因是您创建新类型的方式:
new_type = type(cls.__name__, (base_class,), dict(cls.__dict__))
如果你看一下裸课的__dict__:
class A(object):
pass
print(dict(A.__dict__))
{
'__dict__': ,
'__module__': '__main__',
'__weakref__': ,
'__doc__': None
}
__dict__和__weakref__是给每个类的描述符,只有在必要时才创建__dict__,以节省空间.它不适用于内置对象.它仅适用于创建它的特定类型,因为每个类在内存中的位置可能稍微不同,以存储__dict__.
解决此问题的一种方法是删除它们:
class B(object):
def __new__(cls, value, **kwargs):
base_class = str if isinstance(value, str) else unicode
__dict__ = dict(cls.__dict__)
del __dict__['__dict__'], __dict__['__weakref__']
new_type = type(cls.__name__, (base_class,), __dict__)
obj = base_class.__new__(new_type, value)
obj.__dict__.update(kwargs)
return obj
b = B(u'b', meta=10)
print(b.meta) # 10
Python会自动添加它自己的__dict__描述符.