Как назначить свойство экземпляру в Python? - PullRequest
5 голосов
/ 19 августа 2011

Используя python, можно установить атрибут экземпляра одним из следующих двух способов:

>>> class Foo(object):
    pass

>>> a = Foo()
>>> a.x = 1
>>> a.x
1
>>> setattr(a, 'b', 2)
>>> a.b
2

Можно также назначать свойства через декоратор свойств.

>>> class Bar(object):
    @property
    def x(self):
        return 0


>>> a = Bar()
>>> a.x
0

У меня вопрос, как я могу назначить свойство экземпляру?

Моя интуиция состояла в том, чтобы попробовать что-то подобное ...

>>> class Doo(object):
    pass

>>> a = Doo()
>>> def k():
    return 0

>>> a.m = property(k)
>>> a.m
<property object at 0x0380F540>

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

Ответы [ 4 ]

4 голосов
/ 19 августа 2011

Возможно динамическое добавление свойств в класс после того, как он уже создан:

class Bar(object):
    def x(self):
        return 0

setattr(Bar, 'x', property(Bar.x))

print Bar.x
# <property object at 0x04D37270>
print Bar().x
# 0

Однако вы не можете установить свойство для экземпляра, только для класса.Для этого можно использовать экземпляр:

class Bar(object):
    def x(self):
        return 0

bar = Bar()

setattr(bar.__class__, 'x', property(bar.__class__.x))

print Bar.x
# <property object at 0x04D306F0>
print bar.x
# 0

См. Как динамически добавлять свойство в класс? для получения дополнительной информации.

3 голосов
/ 19 августа 2011

Свойства используют дескрипторы , которые работают только на классах и, следовательно, для всех случаев. Но вы можете использовать комбинацию дескриптора на класс, который будет обращаться к функции за экземпляр.

>>> class Foo(object):
...     @property
...     def x(self):
...         if 'x' in self.__dict__:
...             return self.__dict__['x'](self)
... 
>>> a = Foo()
>>> def k(self):
...     return 0
... 
>>> a.__dict__['x'] = k
>>> a.x
0
1 голос
/ 19 августа 2011

Вы можете назначить свойство непосредственно объекту класса:

>>> class Foo(object):
    pass    
>>> a = Foo()
>>> a.__class__
__main__.Foo    
>>> setattr(a.__class__, 'm', property(lambda self: 0))
>>> a.m
0 
>>> a.m = 24
AttributeError: can't set attribute
0 голосов
/ 22 июня 2017

Здесь мы взяли решение @ agf и использовали функцию lambda для определения свойства класса.

class A(object):
    pass

a = A()
a.__class__.f = property(lambda self: 57)
a.f  # 57

Следующий пост содержит больше контекста: https://crosscompute.com/n/jAbsB6OIm6oCCJX9PBIbY5FECFKCClyV/_/Assign%20a%20class%20property%20to%20an%20instance

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...