Python: динамически добавлять атрибуты в класс/obj нового стиля

могу ли я динамически добавлять атрибуты в экземпляры класса нового стиля (тот, который происходит от object)?

детали:

Я работаю с экземпляром sqlite3.Соединение. Просто расширение класса не является опцией, потому что я не получаю экземпляр, вызывая конструктор; я получаю его, вызывая sqlite3.connect().

создание обертки не экономит мне большую часть объема для кода, который я пишу.

Python 2.7.1

редактировать

правильные ответы на все. Но я все еще не достиг своей цели; экземпляры sqlite3.Панель соединений мои попытки установить атрибуты следующими способами (как и экземпляры ). Я всегда получаю 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 ответов


да, если класс использует __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))

простые эксперименты:

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

Итак, действительно, кажется, что это возможно сделать.

обновление:
Но от документы: SQLite-это библиотека C, которая ..., поэтому кажется, что вам действительно нужно, чтобы обернуть его.


    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-->и ответ с примерами.