zoukankan      html  css  js  c++  java
  • 在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。




  • 相关阅读:
    剑指 Offer 30. 包含min函数的栈
    剑指 Offer 35. 复杂链表的复制
    剑指 Offer 18. 删除链表的节点
    剑指 Offer 24. 反转链表
    Jmeter
    Jmeter
    Linux搭建Jenkins
    [基金项目] 青年基金写作的历程与经验(2)
    [基金项目] 青年基金写作的历程与经验(1)
    浅析mysql存储过程
  • 原文地址:https://www.cnblogs.com/highroom/p/65bf14cdd127fb09cbc027cd4178f983.html
Copyright © 2011-2022 走看看