Python:动态地将属性添加到新式class / obj

时间:2011-05-21 15:12:59

标签: python attributes metaprogramming

我可以动态地将属性添加到新式类的实例(一个派生自object的实例)吗?

详细说明:

我正在使用sqlite3.Connection的一个实例。简单地扩展类不是一个选项,因为我没有通过调用构造函数来获取实例;我通过致电sqlite3.connect()来获得它。

构建一个包装器并没有为我正在编写的代码节省大量的工作量。

Python 2.7.1

修改

正确回答所有问题。但我仍然没有达到我的目标; sqlite3.Connection栏的实例我尝试以下列方式设置属性(就像object本身的实例一样)。我总是得到一个AttributeError:

> conn = sqlite3.connect([filepath])
> conn.a = 'foo'
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    conn.a = 'foo'
AttributeError: 'object' object has no attribute 'a'
> conn.__setattr__('a','foo')
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    conn.__setattr__('a','foo')
AttributeError: 'object' object has no attribute 'a'

帮助?

4 个答案:

答案 0 :(得分:5)

是的,除非该类使用__slots__或通过覆盖__setattr__或内部Python类或本机实现的Python类(通常在C中)来阻止属性编写。

您始终可以尝试设置属性。除了非常奇怪的__setattr__实现之外,将属性分配给上述类型之一的类的实例应该引发AttributeError。 在这些情况下,您将必须使用包装器,如下所示:

class AttrWrapper(object):
  def __init__(self, wrapped):
    self._wrapped = wrapped
  def __getattr__(self, n):
    return getattr(self._wrapped, n)
conn = AttrWrapper(sqlite3.connect(filepath))

答案 1 :(得分:2)

简单的实验:

In []: class Tst(object): pass
   ..: 
In []: t= Tst()
In []: t.attr= 'is this valid?'
In []: t.attr
Out[]: 'is this valid?'

所以,确实似乎有可能这样做。

<强>更新
但是从documentation: SQLite是一个C库...... ,所以看起来你真的需要把它包起来。

答案 2 :(得分:0)

    conn.a = 'foo',

或任何动态分配有效,如果conn

    <type 'classobj'>.

类似的事情:

    c=object() 
    c.e=1

会引发属性错误。另一方面:Python允许您进行梦幻般的元类编程:

    >>>from new import classobj
    >>>Foo2 = classobj('Foo2',(Foo,),{'bar':lambda self:'bar'})
    >>>Foo2().bar()
    >>>'bar'
    >>>Foo2().say_foo()
    >>>foo

答案 3 :(得分:-1)

这里的神奇词是“猴子补丁”。这是an SO answer的例子。