Python:动态为新风格类/对象添加属性

6 投票
3 回答
3707 浏览
提问于 2025-04-16 18:05

我可以动态地给新式类的实例(也就是从 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'

有人能帮忙吗?

3 个回答

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
1

简单实验:

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

所以,确实看起来是可以做到的。

更新:
但是根据文档的说法:SQLite是一个C语言库...,所以看起来你确实需要对它进行封装。

4

是的,除非这个类使用了 __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))

撰写回答