Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Style Guide properties for getters and setters

I'm curious about one of the recommendations in the Google Python style guide concerning properties.

In it, they give the following example:

class Square(object):
    """A square with two properties: a writable area and a read-only perimeter.

    To use:
    >>> sq = Square(3)
    >>> sq.area
    9
    >>> sq.perimeter
    12
    >>> sq.area = 16
    >>> sq.side
    4
    >>> sq.perimeter
    16
    """

    def __init__(self, side):
         self.side = side

    def __get_area(self):
        """Calculates the 'area' property."""
        return self.side ** 2

    def ___get_area(self):
        """Indirect accessor for 'area' property."""
        return self.__get_area()

    def __set_area(self, area):
        """Sets the 'area' property."""
        self.side = math.sqrt(area)

    def ___set_area(self, area):
        """Indirect setter for 'area' property."""
        self.__set_area(area)

    area = property(___get_area, ___set_area,
                    doc="""Gets or sets the area of the square.""")

    @property
    def perimeter(self):
        return self.side * 4

I have two questions about this:

  1. What is the benefit of using the three underscore "indirection" ___get_area and ___set_area as well as two underscore ones, over just using the two underscore ones directly?

  2. Why use property() as a method with this set of double and triple underscore methods, rather than doing something like:

    @property
    def area(self):
        return self.side ** 2
    
    @area.setter
    def area(self, value):
        self.side = math.sqrt(value)
    
like image 847
mindvirus Avatar asked Feb 28 '14 22:02

mindvirus


People also ask

What is getter and setter properties?

What are Getters and Setters? Getters: These are the methods used in Object-Oriented Programming (OOPS) which helps to access the private attributes from a class. Setters: These are the methods used in OOPS feature which helps to set the value to private attributes in a class.

What is the benefit of using properties with getters and setters?

The getter and setter method gives you centralized control of how a certain field is initialized and provided to the client, which makes it much easier to verify and debug. To see which thread is accessing and what values are going out, you can easily place breakpoints or a print statement.

Should setters and getters be public?

Usually you want setters/getters to be public, because that's what they are for: giving access to data, you don't want to give others direct access to because you don't want them to mess with your implementation dependent details - that's what encapsulation is about.

What can I use instead of getters and setters?

You may use lombok - to manually avoid getter and setter method. But it create by itself. The using of lombok significantly reduces a lot number of code. I found it pretty fine and easy to use.


1 Answers

In the style guide they do give a reason:

Inheritance with properties can be non-obvious if the property itself is not overridden. Thus one must make sure that accessor methods are called indirectly to ensure methods overridden in subclasses are called by the property (using the Template Method DP).

(where Template Method DP is the Template Method Design Pattern (slides by Alex Martelli, Pythonista extraordinaire at Google).

So they want to give subclasses the chance to override the implementation, and give the property the triple-underscore versions to call the double-underscore methods so you can override these. You'd have to spell out the mangled name in that case:

class WonkySquare(Square):
    def _Square__get_area(self):
        return self.square ** 2 + 0.5

Apparently the people that came up with this scheme never knew that you can override just a getter or setter of a property, see Python overriding getter without setter:

class ProperlySubclassedSquare(Square):
    @Square.area.getter
    def area(self):
        return self.square ** 2 + (0.5 - 0.5)

Then again, the getter, setter and deleter decorator attributes were only added in Python 2.6. The style guide must've been written for an older Python version.

For 2.6 and up, stick to the @propname.setter pattern instead.

like image 153
Martijn Pieters Avatar answered Oct 11 '22 22:10

Martijn Pieters