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!-)