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





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM