在python里如何动态添加类的动态属性呢?

在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。




posted @ 2015-02-06 16:26  阳光树林  阅读(5689)  评论(0编辑  收藏  举报