I'm currently patching a property of a class from a library to make it more versatile.
I'm doing this using the following code which works fine:
_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)
However, it would be much nicer if i could simply overwrite the getter function so the docstring is preserved:
_orig_is_xhr = BaseRequest.is_xhr.fget
BaseRequest.is_xhr.fget = lambda self: (_orig_is_xhr(self) or
'_iframe-xhr' in request.form)
This doesn't work because property.fget
is a read-only attribute (TypeError: readonly attribute
when trying to assign to it).
I'm curious if there is a special reason for this or it the python developers just thought it makes no sense to modify a property after creating it without replacing it with a new one.
To define a readonly property, you need to create a property with only the getter. However, it is not truly read-only because you can always access the underlying attribute and change it. The read-only properties are useful in some cases such as for computed properties. This code works perfectly fine.
If you need to make a read-only attribute in Python, you can turn your attribute into a property that delegates to an attribute with almost the same name, but with an underscore prefixed before the its name to note that it's private convention.
Tuples are, for most intents and purposes, 'immutable lists' - so by nature they will act as read-only objects that can't be directly set or modified.
You can create a property by calling property() with an appropriate set of arguments and assigning its return value to a class attribute. All the arguments to property() are optional. However, you typically provide at least a setter function.
You're probably right, that it's just a convention to make those attributes read-only, chosen to make the property "all-or-nothing". Seems it'd be a bit more "Pythonic" to allow these to be assigned after the fact, but can't find the rationale in the Python 2.2 release notes (when properties were introduced).
In Objects/descrobject.c the property's member attributes are defined as read-only:
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}
};
Aside: if you replace READONLY
with 0
and compile, that's all it takes to allow fget, fset, ..
to be assigned:
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
Output:
True
False
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With