views:

534

answers:

7

I have written some code that uses attributes of an object:

class Foo:
    def __init__(self):
        self.bar = "baz"
myFoo = Foo()
print (myFoo.bar)

Now I want to do some fancy calculation to return bar. I could use @property to make methods act as the attribute bar, or I could refactor my code to use myFoo.bar().

Should I go back and add parens to all my bar accesses or use @property? Assume my code base is small now but due to entropy it will increase.

+9  A: 

If it's logically a property/attribute of the object, I'd say keep it as a property. If it's likely to become parametrised, by which I mean you may want to invoke myFoo.bar(someArgs) then bite the bullet now and make it a method.

Under most circumstances, performance is unlikely to be an issue.

Vinay Sajip
+2  A: 

In cases like these, I find it much better to choose the option that makes the most sense. You won't get any noticeable performance loss with small differences like these. It's much more important that your code is easy to use and maintain.

As for choosing between using a method and a @property, it's a matter of taste, but since properties disguise themselves as simple attributes, nothing elaborate should be going on. A method indicates that it might be an expensive operation, and developers using your code will consider caching the value rather than fetching it again and again.

So again, don't go on performance, always consider maintainability vs. performance. Computers get faster and faster as time goes by. The same does not stand for the readability of code.

In short, if you want to get a simple calculated value, @property is an excellent choice; if you want an elaborate value calculated, a method indicates that better.

Blixt
A: 

That's exactly what @property is meant for.

dugres
+2  A: 

I would go for the refactoring, but only for a matter of style - it seems clearer to me that "fancy calculations" might be ongoing with a method call, while I would expect a property to be almost a no-op, but this is a matter of taste.

Don't worry about the decorator's performance... if you think that it might be a problem, measure the performance in both cases and see how much it does add (my guess is that it will be totally negligible if compared to your fancy calculations).

Paolo Tedesco
A: 

Premature optimization is the root of all evil.

Yes, calling a property is somewhat slower than calling a method. This is likely to be completely overshadowed by your calculation.

Lennart Regebro
This is becoming one of those platitudes like "gotos are evil". How do you even know it is premature in this case? Maybe this is the most perf critical part of the code in question.
schickb
Yes, *maybe*. But maybe it's not. And it's premature until you *know*. And you don't know until you have profiled it. And then the question would be "I'm trying to speed up my Python program...". And it's not. He is not in the profiling stage, hence, it's premature.
Lennart Regebro
I'm in the architectural design phase. If @property costs me 10x performance and is equivalent in code complexity there is no reason to do it. Like why aren't all methods virtual by default in c++? 'cause you don't pay for it until you use it. I just want to know if @property is 10x slower, 100x slower, 10x faster, what the heck is the performance characteristic.
Paul Tarjan
1. So test it. It took me five minutes.2. Premature optimization is still a bad idea. There really is a reason that this mantra is repeated. You don't know what you need to optimize until your system is ready and you have profiled it. If you sit and optimize in the architectural design phase, you are going to constantly optimize things that either never makes it into the final system, or makes performance worse.3. If @property cost you ten times performance, do you think anybody would actually use it?
Lennart Regebro
+3  A: 

Wondering about performance is needless when it's so easy to measure it:

$ python -mtimeit -s'class X(object):
>   @property
>   def y(self): return 23
> x=X()' 'x.y'
1000000 loops, best of 3: 0.685 usec per loop
$ python -mtimeit -s'class X(object):

  def y(self): return 23
x=X()' 'x.y()'
1000000 loops, best of 3: 0.447 usec per loop
$

(on my slow laptop -- if you wonder why the 2nd case doesn't have secondary shell prompts, it's because I built it from the first with an up-arrow in bash, and that repeats the linebreak structure but not the prompts!-).

So unless you're in a case where you know 200+ nanoseconds or so will matter (a tight inner loop you're trying to optimize to the utmost), you can afford to use the property approach; if you do some computations to get the value, the 200+ nanoseconds will of course become a smaller fraction of the total time taken.

I do agree with other answers that if the computations become too heavy, or you may ever want parameters, etc, a method is preferable -- similarly, I'll add, if you ever need to stash the callable somewhere but only call it later, and other fancy functional programming tricks; but I wanted to make the performance point quantitatively, since timeit makes such measurements so easy!-)

Alex Martelli
A: 

I agree with what most people here have said, I did much measurement when building hydrologic models in Python a couple years ago and found that the speed hit from using @property was completely overshadowed by calculation.

As an example, creating method local variables (removing the "dot factor" in my calculations increased performance by almost an order of magnitude more than removing @property (these results are averaged over a mid-scale application).

I'd look elsewhere for optimization, when it's necessary, and focus initially on getting good, maintainable code written. At this point, if @property is intuitive in your case, use it. If not, make a method.

JohnMetta