在python里如何动态添加类的动态属性呢?
2010-10-19 08:49:20| 分类: 技术文章 | 标签:class 动态增加属性 python |举报|字号 订阅
在python里如何动态添加类的动态属性呢?看下面的例子
class A(object):
a = 1
b = 2
def fun1(self):
print 'fun1'
def fun2(self):
print 'fun2'
a1 = A()
a1.c = 1
这里我们定义了一个类A,还有一个实例a1。a1.c = 1 只是增加实例的属性而不是增加类的属性。
我们知道python对象有一__dict__属性,那我们尝试这样操作:
setattr( A.__dict__, 'd', 1)
这样的操作会得到一下的错误:
TypeError: 'dictproxy' object has only read-only attributes (assign to .d)
这是什么意思呢?其实python对象里的获取“__dict__”属性,实际上获取的并不是实际的dict,获取的只是一个dictproxy。
在源码里typeobject.c里
static PyGetSetDef type_getsets[] = {
{"__name__", (getter)type_name, (setter)type_set_name, NULL},
{"__bases__", (getter)type_get_bases, (setter)type_set_bases, NULL},
{"__module__", (getter)type_module, (setter)type_set_module, NULL},
{"__dict__", (getter)type_dict, NULL, NULL},
{"__doc__", (getter)type_get_doc, NULL, NULL},
{0}
};
这里定义了__dict__对应的c的获取方法。
我们找到type_dict方法的实现
static PyObject *
type_dict(PyTypeObject *type, void *context)
{
if (type->tp_dict == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
return PyDictProxy_New(type->tp_dict);
}
可以看到其实每次获取__dict__熟悉时,都是new一个dictproxy。
正确的操作应该是:
setattr( A, 'd', 1)
或者
setattr( a1.__class__, 'd', 1)
具体实现可以看classobject.c里的方法:
static int class_setattr(PyClassObject *op, PyObject *name, PyObject *v)
该函数会对非“__”开头的属性自动转到op->tp_dict。