Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use "property" builtin: auxiliary functions and generators

I recently discovered Python's property built-in, which disguises class method getters and setters as a class's property. I'm now being tempted to use it in ways that I'm pretty sure are inappropriate.

Using the property keyword is clearly the right thing to do if class A has a property _x whose allowable values you want to restrict; i.e., it would replace the getX() and setX() construction one might write in C++.

But where else is it appropriate to make a function a property? For example, if you have

class Vertex(object):
    def __init__(self):
        self.x = 0.0
        self.y = 1.0

class Polygon(object):
    def __init__(self, list_of_vertices):
        self.vertices = list_of_vertices
    def get_vertex_positions(self):
        return zip( *( (v.x,v.y) for v in self.vertices ) )

is it appropriate to add

    vertex_positions = property( get_vertex_positions )

?

Is it ever ok to make a generator look like a property? Imagine if a change in our code meant that we no longer stored Polygon.vertices the same way. Would it then be ok to add this to Polygon?

    @property
    def vertices(self):
        for v in self._new_v_thing:
            yield v.calculate_equivalent_vertex()
like image 970
Seth Johnson Avatar asked May 04 '10 15:05

Seth Johnson


People also ask

What is the use of property in Python?

Python's property() is the Pythonic way to avoid formal getter and setter methods in your code. This function allows you to turn class attributes into properties or managed attributes. Since property() is a built-in function, you can use it without importing anything.

What is the difference between an attribute and a property in Python?

Attributes are described by data variables for example like name, age, height etc. Properties are special kind of attributes which have getter, setter and delete methods like __get__, __set__ and __delete__ methods.

What does @property mean Python?

The @property is a built-in decorator for the property() function in Python. It is used to give "special" functionality to certain methods to make them act as getters, setters, or deleters when we define properties in a class.

How do you set a property of an object Python?

Python property() function returns the object of the property class and it is used to create property of a class. Parameters: fget() – used to get the value of attribute. fset() – used to set the value of attribute.


1 Answers

  • When you have a normal attribute and getting and/or setting it makes sense for a class's user, expose the attribute directly. One big reason that public members are anathema in some languages is that if you need to do something more complex later you would need an API change; in Python you can just define a property.

  • If you are using something you should abstract as attribute access, use property. If you want to make external state (your plot or website or something) aware of the change or if you are wrapping some library that uses members directly, properties might be the way to go.

  • If something isn't attribute-y, don't make it a property. There's no harm in making a method, and it can be advantageous: what it does is more obvious, you can pass around some bound method if you need, you can add keyword arguments without an API change.

    It's hard to imagine a situation where I would use a generator function as a property. The only way to have a normal attribute that would behave at all similarly would require quite a lot of complexity, so that case isn't very reminiscent of attribute access.

  • You point out you can use property for restricting access to some internal attribute _x. This can be true, but keep in mind

    • If you are going to do things like sanitize input for security or something important, explicit is better than implicit. You don't want to feel like code just-works when it comes to such things, because then you'll run into code that doesn't.

    • Sometimes people use property to implement read-only attributes. It's usually better just to have a normal attribute and realize you can't stop a user from doing something dumb and unsupported.

  • Nitpicking you might find interesting:

    • property isn't a keyword; it's a normal name you can rebind. This is sort of interesting since property isn't a syntax thing or anything: it's a normal class you could implement yourself in pure Python. It uses the same mechanism that makes methods work in Python—descriptors.

    • You describe what property does as "disguises class method getters and setters", which isn't quite the case. The things that property take are just normal functions, and needn't actually be defined in your class at all; property will pass self for you. Functions don't actually become methods until you look them up, when Python creates method objects on-the-fly. During the class definition, they are just functions. When you have a normal method it's called an "instance method"; in Python "class method" refers to another special thing sort of like properties that changes what happens when an attribute is looked up.

like image 89
Mike Graham Avatar answered Oct 27 '22 21:10

Mike Graham