Just curious what the rule-of-thumb is for when it comes to using
model methods vs. properties. For example:
[code]
@property
def is_modified(self):
if self.modified > self.created:
return True
return False
def get_separator(self):
return ' :: '
[/code]
I feel like I have seen so many examples of methods and properties
that return the same type of stuff, I am just confused about when to
use one over the other.
Just hoping some of the pro Django/Python users on this list could
school me on this one. :D
Thanks so much!
Cheers,
Micky
Actually, here's an example that I am working on now.
In my model, I have a CharField that holds the latitude/longitude with
values that look like:
44.08577787869324,-123.052459359169
I would like to write model methods to return latitude and longitude.
[code]
def lat(self):
# ...
def lng(self):
# ...
[code]
Should I use a property decorator?
Also, what is the difference between this:
[code]
def _get_lat(self):
# ...
lat = property(_get_lat)
[/code]
... and this:
[code]
@property
def lat(self):
# ...
[/code]
Sorry if stupid questions.
Thanks!
Micky
On Thu, Jun 16, 2011 at 1:42 PM, bruno desthuilliers
<bruno.des...@gmail.com> wrote:
> <ot>
> This could be written much more simply as "return self.modified >
> self.created"
> </ot>
Omg, thanks! That's way better. :D
>> def get_separator(self):
>> return ' :: '
> In this case (returning a constant), it would be much simpler to make
> it a class (or instance) attribute.
Ah, I think I get it.
Just to clarify things for me, does attribute equal a property or method? :D
I am guessing that attribute = property, so you're saying that I
could/should do this:
@property
def separator(self):
return ' :: '
> Properties are for computed attributes - that is, things that are the
> semantically (conceptually, whatever) attributes, but requires any
> computation, either on get, set or del.
Ah, interesting... I think I need to let this all sink in a little. :)
> But well, if you prefer java-
> like getters/setters, then choice is yours... Depends on the
> programmer's background,
I have a little experience with Actionscipt 3 and PHP5 OOP... I guess
I am used to the concept/practice of getters/setters,
(public/private/other) class methods and properties.
Are you saying that a non-property model class method is equivalent to
getter/setter? Or, maybe you are saying that the "lat =
property(_get_lat)" python property syntax is like
getters/setters/accessors in other programming langs?
Again, sorry if stupid questions... sorry if this is getting OT for
the Django list.
> and of course of whether the code was written
> before new-style classes and the descriptor protocol....
I have not heard of this before. Googling "new-style classes and the
descriptor protocol" now. ;)
Looks like I have a lot of learning to do! :D
Thanks again, I greatly appreciate your time and assistance.
Have a great day.
Cheers,
Micky
1. Use a property (class/instance attribute) when an argument(s) is not needed.
2. If an argument(s) is needed (for runtime(?) calculations and/or
class/instance attributes need to be sanitized/checked/other), then
use a method (or getter/setter/descriptor).
No?
Hehe, thanks again!!!
Cheers,
Micky
Sorry to bug the list with my ramblings.
Thanks again Bruno!
Have a great day all!
Cheers,
Micky
No, he's saying that is ridiculous overkill for a constant attribute.
class MyModel(models.Model):
SEPARATOR = '::'
Access it with MyModel.SEPARATOR or my_model_instance.SEPARATOR
I use property() when either the setting or modification of an
attribute requires me to run actual code in order to manipulate the
supplied value into a different format. Eg, if I am storing a comma
separated list of IP addresses as strings in a database field, I don't
want to have to deal with splitting, parsing and turning it into a
list of proper objects in every different place. Instead, I supply a
property that serializes/deserializes the data as needed.
Another reason to use property() is when you remove an attribute that
is part of your public API, you can provide a property with the same
name as the attribute. Eg:
class MyModel(models.Model):
@property
def SEPARATOR(self):
if self.foo:
return '::'
return '||'
The behaviour is now dynamic, but any old code using
instance.SEPARATOR will get still work, and use the new dynamic
definition.
Cheers
Tom
Replying to both of you in this one e-mail... See inline replies below.
On Fri, Jun 17, 2011 at 1:42 AM, Tom Evans <teva...@googlemail.com> wrote:
> Access it with MyModel.SEPARATOR or my_model_instance.SEPARATOR
Ahhh, I see now. Thanks for the clarification!
I now plan on re-factoring my simple "category/sub-category" model:
https://gist.github.com/1031882
> ...<snip>...
> list of proper objects in every different place. Instead, I supply a
> property that serializes/deserializes the data as needed.
Awesome. That's a good description.
I have a few spots in my latest app that needs this type of
functionality, I will be sure to use property().
Not to state the obvious, but I just learned/realized that the
property decorator is Python 2.4's version of foo =
property(get_foo)... For some reason, up until now, I was under the
assumption that the property decorator was a Django thing! :D
> ...<snip>...
> The behaviour is now dynamic, but any old code using
> instance.SEPARATOR will get still work, and use the new dynamic
> definition.
Ooh, that is interesting too! Thank you for the explanations and code
examples, that really helps clear things up for me. :)
On Fri, Jun 17, 2011 at 3:18 AM, bruno desthuilliers
<bruno.des...@gmail.com> wrote:
> Python's object model is a bit peculiar (wrt/ most OOPLs at least),
> and I won't start to explain it here (this would require a full book
> FWIW).
Hehe!
Yah, you know, I am one of those few folks that learned (er, is
learning) Django before getting to know Python...
:: hangs head in shame ::
I am planning on spending a few upcoming weekends reading through the
online version of Dive into Python. :)
> To make a long story short, you have class and instance
> attributes, and since a small code snippet can say more than a
> thousand words:
> ...<snip>...
> # this is a class method
> @classmethod
> def yuu(cls):
> print "%s.yuu" % cls
Oh, perfect! That really helps clarify things! Thanks for the code example. :)
I have never used the @classmethod decorator before. I will have to
read up on that one.
Looks like there's also @staticmethod... Interesting stuff! Thanks!
>> I am guessing that attribute = property
> Nope. "property" is a builtin Python class that implements the
> descriptor protocol and give support for simple computed attributes.
Ahh, I see now! Thanks for the clarification.
> ...<snip>...
> you can transparently turn it
> into a computed one later if needed so no need to waste time with
> getters/setters.
Awesome! I get it now. :)
> ...<snip>...
> wrt/ "public/private", there's no such thing in Python anyway. The
> (*very* strong) convention is to prefix implementation stuff with a
> single leading underscore which means "don't touch or your on your own
> if something breaks", but nothing prevents client code to mess with
> some object's internals.
I am reminded of a sidebar that I read in the Dive Into Python book:
"There are no constants in Python. Everything can be changed if you
try hard enough. This fits with one of the core principles of Python:
bad behavior should be discouraged but not banned. If you really want
to change the value of None, you can do it, but don't come running to
me when your code is impossible to debug."
-- <http://diveintopython.org/object_oriented_framework/class_attributes.html>
... specifically, that last two sentences! :)
> Mostly, yes - with the exception that since Python can let you turn a
> plain attribute into a computed one without breaking client code, you
> don't have to use getters / setters "just in case" - you only use them
> if and when needed, and encapsulate them into a property (or a custom
> descriptor) so the client code don't have to care.
That's a great explanation. Thanks!
> Well, I usually redirect this kind of questions to c.l.py, since it's
> about Python and not Django...
I have not hear of c.l.py... I assume that it is a Python listserv?
Googling now. :)
I am a member of the Google Python group, but I am not a huge fan of
digest e-mails... I would love to find a python list that allowed for
e-mail for every message.
> Warning: this (and metaclasses) can be a bit mind-bending at first,
> and tend to become highly addictive once you get it ;)
> If I may suggest another related reading:
> http://wiki.python.org/moin/FromFunctionToMethod
Ooooh, interesting! Thanks for the linkage! Much appreciated.
Looks like my weekend is going to be full of pure python coding!
Also, thanks for pointing towards the wiki:
That site looks useful.
> FWIW, Django relies quite a lot on metaclasses and descriptors for the
> ORM part.
Good to know. All of this information will give me stuff to research
over then next several weeks.
Thanks again Tom and Bruno! You folks ROCK! :D
I owe you one.
Have a nice day.
Cheers,
Micky
Hello,
Just curious what the rule-of-thumb is for when it comes to using
model methods vs. properties. For example:
[code]
@property
def is_modified(self):
if self.modified > self.created:
return True
return False
def get_separator(self):
return ' :: '
[/code]
I feel like I have seen so many examples of methods and properties
that return the same type of stuff, I am just confused about when to
use one over the other.
On 2011-06-18, at 15:05 , Ethan Jucovy wrote:
> I tend to avoid @property -- it adds conceptual overhead for code
> readers (hiding the fact that a function call is taking place) for little
> gain.
You *do* realize that django model (and form) fields are descriptors, and any access to a model or form field will result in a bunch of method calls right?
Would you say that the way the attribute lookup mechanism anddescriptor protocol are used to turn function class attributes into
methods "adds conceptual overhead for little gain"
But even then, since adding extra params means you'll have to fix
client code, the "less refactoring" argument doesn't stand IMHO.
All this being said, I wholefully agree that while computed attributes
are very handy, one should not go over the top and use them for no
good reason - simple code is hard enough to maintain.
I really appreciate all of the professional help.
I have a lot to research and need to practice some of these newly
learned techniques/concepts... I may be back with more (this time,
Django-centric) questions. :D
Thanks! Have a great week!
Cheers,
Micky