Почему property.fget доступен только для чтения? - PullRequest
6 голосов
/ 23 апреля 2011

В настоящее время я исправляю свойство класса из библиотеки, чтобы сделать его более универсальным.

Я делаю это, используя следующий код, который прекрасно работает:

_orig_is_xhr = BaseRequest.is_xhr.fget
_orig_is_xhr_doc = BaseRequest.is_xhr.__doc__
BaseRequest.is_xhr = property(lambda self: _orig_is_xhr(self) or
    '_iframe-xhr' in request.form, doc=_orig_is_xhr_doc)

Однако было бы намного лучше, если бы я мог просто перезаписать функцию получения, чтобы строка документа была сохранена:

_orig_is_xhr = BaseRequest.is_xhr.fget
BaseRequest.is_xhr.fget = lambda self: (_orig_is_xhr(self) or
    '_iframe-xhr' in request.form)

Это не работает, потому что property.fget является атрибутом только для чтения (TypeError: readonly attribute, когдапытаюсь присвоить ему).Мне любопытно, есть ли для этого особая причина или разработчики python просто подумали, что нет смысла изменять свойство после его создания, не заменяя его новым.

Ответы [ 2 ]

6 голосов
/ 23 апреля 2011

Вы, вероятно, правы, что это просто соглашение, чтобы сделать эти атрибуты доступными только для чтения, выбранными, чтобы сделать свойство "все или ничего".Кажется, было бы немного более «Pythonic», чтобы разрешить их назначать после факта, но не может найти обоснование в Замечаниях по выпуску Python 2.2 (когда были введены свойства).

В Objects / descrobject.c атрибуты-члены свойства определены только для чтения:

    static PyMemberDef property_members[] = {
        {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},
        {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},
        {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},
        {"__doc__",  T_OBJECT, offsetof(propertyobject, prop_doc), READONLY},
        {0}
    };

В стороне: если вы замените READONLY на 0 и скомпилируете,это все, что нужно для назначения fget, fset, ..:

class Test(object):
    def __init__(self):
        self.flag = True
    prop = property(lambda self: self.flag)

obj = Test()
print obj.prop
Test.prop.fget = lambda self: not self.flag
print obj.prop

Вывод:

True
False
0 голосов
/ 12 сентября 2017

протестировано с Anaconda 2.3.0 (Python 3.4.3) в оболочке IDLE

>>> p = property()
>>> p.fget
>>> p.__init__( lambda obj: None )
>>> p.fget
<function <lambda> at 0x0121FF18>
>>> p.fget = lambda obj: None
Tracebabk (most recent call last):
  File "<pyshell#19>", line 1, in <module>
    p.fget = lambda obj: None
AttributeError: readonly attribute
>>>

не выглядит так, только для чтения;)

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