Reputation: 2609
I want to wrap a model class of a legacy codebase. The model class has a dictionary with meta-information and properties that access that dictionary as well as attributes. I want to unify the access to meta information, properties, and attributes with the an_object[some_key]
syntax using __getitem__
. The problem is, that some of the properties have getters but not setters. So trying to check if an attribute exists (via hasattr) returns True, but then setting that attribute fails because there is no property defined.
How can I decide if I can set an attribute safely or if it is an property that I need to set in the meta-dictionary?
Upvotes: 0
Views: 1487
Reputation: 1123420
You can detect if something is a property, by looking at the same attribute on the class:
class_attribute = getattr(type(instance), some_key, None)
if isinstance(class_attribute, property):
# this is a property
if class_attribute.fset is None:
print "Read-only"
You can also test .fget
and .fdel
to test if the property has a getter and a deleter, respectively.
However, you can always catch the AttributeError
exception to deal with the setter missing:
>>> class Foo(object):
... @property
... def bar(self):
... return 'spam'
...
>>> f = Foo()
>>> class_attribute = getattr(type(f), 'bar', None)
>>> isinstance(class_attribute, property)
True
>>> class_attribute.fget
<function bar at 0x10aa8c668>
>>> class_attribute.fset is None
True
>>> try:
... f.bar = 'baz'
... except AttributeError:
... print 'Read-only'
...
Read-only
Upvotes: 4