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

Можно ли динамически добавлять атрибуты к экземплярам класса нового стиля (класса, производного от 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 ]

5 голосов
/ 21 мая 2011

Да, если только класс не использует __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))
2 голосов
/ 21 мая 2011

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

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

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

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

0 голосов
/ 05 сентября 2012
    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
0 голосов
/ 21 мая 2011

Волшебное слово здесь - «исправление обезьян».Вот SO ответ с примерами.

...