Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subclassing Python's `property`

In one of my classes, I have a number of properties that do very similar things on getting and setting. So I abstracted the arguments to property into a factory function:

def property_args(name):
    def getter(self):
        # do something
        return getattr(self, '_' + name)
    def setter(self, value)
        # do something
        setattr(self, '_' + name, value)
    return getter, setter

class MyClass(object):
    def __init__(self):
        self._x = None
    x = property(*property_args('x'))  # obviously there's more than one of these IRL

However, I've since discovered that property is in fact a class, and subclassing it would be perfect for this. I can't find anything in the documentation that explains what I need to override (and the argument signatures of __init__ etc), and I don't really want to have to go hunting in the C source code for it. Does anyone know where I can find this information?

like image 972
Benjamin Hodgson Avatar asked Sep 13 '12 11:09

Benjamin Hodgson


People also ask

What is property () in Python?

In Python, property() is a built-in function that creates and returns a property object. The syntax of this function is: property(fget=None, fset=None, fdel=None, doc=None)

How do you access properties in Python?

getattr() – This function is used to access the attribute of object. hasattr() – This function is used to check if an attribute exist or not. setattr() – This function is used to set an attribute. If the attribute does not exist, then it would be created.

Are Python properties inherited?

Inheritance allows us to define a class that inherits all the methods and properties from another class. Parent class is the class being inherited from, also called base class. Child class is the class that inherits from another class, also called derived class.

What is the property decorator in Python?

@property decorator is a built-in decorator in Python which is helpful in defining the properties effortlessly without manually calling the inbuilt function property(). Which is used to return the property attributes of a class from the stated getter, setter and deleter as parameters.


1 Answers

Here is a pure Python equivalent for the code in property():

class Property(object):
    "Emulate PyProperty_Type() in Objects/descrobject.c"

    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
        self.fget = fget
        self.fset = fset
        self.fdel = fdel
        if doc is None and fget is not None:
            doc = fget.__doc__
        self.__doc__ = doc

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        if self.fget is None:
            raise AttributeError("unreadable attribute")
        return self.fget(obj)

    def __set__(self, obj, value):
        if self.fset is None:
            raise AttributeError("can't set attribute")
        self.fset(obj, value)

    def __delete__(self, obj):
        if self.fdel is None:
            raise AttributeError("can't delete attribute")
        self.fdel(obj)

    def getter(self, fget):
        return type(self)(fget, self.fset, self.fdel, self.__doc__)

    def setter(self, fset):
        return type(self)(self.fget, fset, self.fdel, self.__doc__)

    def deleter(self, fdel):
        return type(self)(self.fget, self.fset, fdel, self.__doc__)
like image 156
Raymond Hettinger Avatar answered Oct 06 '22 03:10

Raymond Hettinger