Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idiomatic python - property or method?

Tags:

python

django

I have a django model class that maintains state as a simple property. I have added a couple of helper properties to the class to access aggregate states - e.g. is_live returns false if the state is any one of ['closed', 'expired', 'deleted'] etc.

As a result of this my model has a collection of is_ properties, that do very simple lookups on internal properties of the object.

I now want to add a new property, is_complete - which is semantically the same as all the other properties - a boolean check on the state of the object - however, this check involves loading up dependent (one-to-many) child objects, checking their state and reporting back based on the results - i.e. this property actually does some (more than one) database query, and processes the results.

So, is it still valid to model as a property (using the @property decorator), or should I instead forego the decorator and leave it as a method?

Pro of using a property is that it's semantically consistent with all the other is_ properties.

Pro of using a method is that it indicates to other developers that this is something that has a more complex implementation, and so should be used sparingly (i.e. not inside a for.. loop).

from django.db import models

class MyModel(models.Model):

    state = CharField(default='new')

    @property
    def is_open(self):
        # this is a simple lookup, so makes sense as a property
        return self.state in ['new', 'open', 'sent']

    def is_complete(self):
        # this is a complex database activity, but semantically correct
        related_objects = self.do_complicated_database_lookup()
        return len(related_objects)==0

EDIT: I come from a .NET background originally, where the split is admirably defined by Jeff Atwood as

"if there's any chance at all that code could spawn an hourglass, it definitely should be a method."

EDIT 2: slight update to the question - would it be a problem to have it as a method, called is_complete, so that there are mixed properties and methods with similar names - or is that just confusing?

So - it would look something like this:

>>> m = MyModel()
>>> m.is_live
True
>>> m.is_complete()
False
like image 581
Hugo Rodger-Brown Avatar asked Jul 02 '13 15:07

Hugo Rodger-Brown


People also ask

What is the difference between property and method in Python?

Ans: A property is a named attribute of an object. Properties define the characteristics of an object such as Size, Color etc. or sometimes the way in which it behaves. A method is an action that can be performed on objects.

What is Property () in Python?

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

Which of these is the property of Python?

Getting Started With Python's property() 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.

What is Property method in Django?

The @property decorator is a built-in decorator in Python for the property() function. This function returns a special descriptor object which allows direct access to getter, setter, and deleter methods. A typical use is to define a managed attribute x : class C(object): def __init__(self): self.


1 Answers

It is okay to do that, especially if you will use the following pattern:

class SomeClass(models.Model):
    @property
    def is_complete(self):
        if not hasattr(self, '_is_complete'):
            related_objects = self.do_complicated_database_lookup()
            self._is_complete = len(related_objects) == 0
        return self._is_complete

Just remember that it "caches" the results, so first execution does calculation, but subsequent use existing results.

like image 108
Tadeck Avatar answered Oct 04 '22 10:10

Tadeck