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