Question

I'd like to have some data descriptors as part of a class. Meaning that I'd like class attributes to actually be properties, whose access is handled by class methods.

It seems that Python doesn't directly support this, but that it can be implemented by subclassing the type class. So adding a property to a subclass of type will cause its instances to have descriptors for that property. Its instances are classes. Thus, class descriptors.

Is this advisable? Are there any gotchas I should watch out for?

Was it helpful?

Solution

It is convention (usually), for a descriptor, when accessed on a class, to return the descriptor object itself. This is what property does; if you access a property object on a class, you get the property object back (because that's what it's __get__ method chooses to do). But that's a convention; you don't have to do it that way.

So, if you only need to have a getter descriptor on your class, and you don't mind that a an attempt to set will overwrite the descriptor, you can do something like this with no metaclass programming:

def classproperty_getter_only(f):
    class NonDataDescriptor(object):
        def __get__(self, instance, icls):
            return f(icls)
    return NonDataDescriptor()

class Foo(object):

    @classproperty_getter_only
    def flup(cls):
        return 'hello from', cls

print Foo.flup
print Foo().flup

for

('hello from', <class '__main__.Foo'>)
('hello from', <class '__main__.Foo'>)

If you want a full fledged data descriptor, or want to use the built-in property object, then you're right you can use a metaclass and put it there (realizing that this attribute will be totally invisible from instances of your class; metaclasses are not examined when doing attribute lookup on an instance of a class).

Is it advisable? I don't think so. I wouldn't do what you're describing casually in production code; I would only consider it if I had a very compelling reason to do so (and I can't think of such a scenario off the top of my head). Metaclasses are very powerful, but they aren't well understood by all programmers, and are somewhat harder to reason about, so their use makes your code harder to maintain. I think this sort of design would be frowned upon by the python community at large.

OTHER TIPS

Is this what you mean by "class attributes to actually be properties, whose access is handled by class methods"?

You can use a decorator property to make an accessor appear to be an actual data member. Then, you can use the x.setter decorator to make a setter for that attribute.

Be sure to inherit from object, or this won't work.

class Foo(object):
    def __init__(self):
            self._hiddenx = 3
    @property
    def x(self):
            return self._hiddenx + 10
    @x.setter
    def x(self, value):
            self._hiddenx = value

p = Foo()

p.x #13

p.x = 4
p.x #14
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top