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

发布于 2024-11-09 01:37:55 字数 840 浏览 0 评论 0原文

我可以动态地将属性添加到新样式类(派生自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'

Help?

Can I dynamically add attributes to instances of a new-style class (one that derives from object)?

Details:

I'm working with an instance of sqlite3.Connection. Simply extending the class isn't an option because I don't get the instance by calling a constructor; I get it by calling sqlite3.connect().

Building a wrapper doesn't save me much of the bulk for the code I'm writing.

Python 2.7.1

Edit

Right answers all. But I still am not reaching my goal; instances of sqlite3.Connection bar my attempts to set attributes in the following ways (as do instances of object itself). I always get an 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'

Help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

懵少女 2024-11-16 01:37:55

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

Yes, unless the class is using __slots__ or preventing attribute writing by overriding __setattr__, or an internal Python class, or a Python class implemented natively (usually in C).

You can always try setting an attribute. Except for seriously weird __setattr__ implementations, assigning an attribute to an instance of a class of one of the types mentioned above should raise an AttributeError.
In these cases, you'll have to use a wrapper, like this:

class AttrWrapper(object):
  def __init__(self, wrapped):
    self._wrapped = wrapped
  def __getattr__(self, n):
    return getattr(self._wrapped, n)
conn = AttrWrapper(sqlite3.connect(filepath))
痴意少年 2024-11-16 01:37:55

简单的实验:

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

所以,确实似乎可以做到这一点。

更新:
但从 文档来看: SQLite 是一个 C 库,...,看来你确实需要包装它。

Simple experimentation:

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

So, indeed it seems to be possible to do that.

Update:
But from the documentation: SQLite is a C library that ..., so it seems that you really need to wrap it.

念﹏祤嫣 2024-11-16 01:37:55
    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
    conn.a = 'foo',

or any dynamic assignment is valid, if conn is

    <type 'classobj'>.

Things like:

    c=object() 
    c.e=1

will raise an Attribute error. On the otherhand: Python allows you to do fantastic Metaclass programming:

    >>>from new import classobj
    >>>Foo2 = classobj('Foo2',(Foo,),{'bar':lambda self:'bar'})
    >>>Foo2().bar()
    >>>'bar'
    >>>Foo2().say_foo()
    >>>foo
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文