Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #58370 > unrolled thread
| Started by | Peter Cacioppi <peter.cacioppi@gmail.com> |
|---|---|
| First post | 2013-11-02 23:09 -0700 |
| Last post | 2013-11-04 15:14 -0800 |
| Articles | 9 — 3 participants |
Back to article view | Back to comp.lang.python
zero argument member functions versus properties Peter Cacioppi <peter.cacioppi@gmail.com> - 2013-11-02 23:09 -0700
Re: zero argument member functions versus properties Peter Cacioppi <peter.cacioppi@gmail.com> - 2013-11-02 23:11 -0700
Re: zero argument member functions versus properties Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-11-03 06:52 +0000
Re: zero argument member functions versus properties Peter Cacioppi <peter.cacioppi@gmail.com> - 2013-11-03 00:19 -0700
Re: zero argument member functions versus properties Peter Cacioppi <peter.cacioppi@gmail.com> - 2013-11-03 01:06 -0700
Re: zero argument member functions versus properties Ian Kelly <ian.g.kelly@gmail.com> - 2013-11-03 01:53 -0700
Re: zero argument member functions versus properties Peter Cacioppi <peter.cacioppi@gmail.com> - 2013-11-03 13:23 -0800
Re: zero argument member functions versus properties Ian Kelly <ian.g.kelly@gmail.com> - 2013-11-03 19:27 -0700
Re: zero argument member functions versus properties Peter Cacioppi <peter.cacioppi@gmail.com> - 2013-11-04 15:14 -0800
| From | Peter Cacioppi <peter.cacioppi@gmail.com> |
|---|---|
| Date | 2013-11-02 23:09 -0700 |
| Subject | zero argument member functions versus properties |
| Message-ID | <46d5788e-f081-48d8-b839-f31a0c95bd21@googlegroups.com> |
Python makes it very easy to turn a zero argument member function into a property (hooray!) by simply adding the @property decorator. (Meme for well thought py feature - "Guido was here") But the ease with which you can do this makes the "zero argument member function or property" discussion trickier for me. Generally my sense here is there are two extremes 1-> the zero argument function is sort of factory-like. It potentially has non-trivial run time, or it substitutes calling a class constructor when building certain objects. 2-> it simply retrieves a stored value (perhaps lazily evaluating it first) so 1 should clearly be a zero argument member function. 2 should be a method. Other than that, I say "when in doubt, go with zero argument method". In particular something in my gut says that if the thing I'm returning is itself a function, than don't go with property. In other words foo.bar()(x) self documents that bar returns a function whereas foo.bar(x) looks like bar is a one argument member function of foo, as opposed to a property that returns a 1 argument function I also think that foo.size() implies that foo performs a count every time it's called, and foo.size implies that the run time will amortize to O(1) somehow (usually with lazy eval). So the implementation should drive the property or not decision. Sound a bit right? Seems like some of the energetic posters will have fun with this one, re:less.
[toc] | [next] | [standalone]
| From | Peter Cacioppi <peter.cacioppi@gmail.com> |
|---|---|
| Date | 2013-11-02 23:11 -0700 |
| Message-ID | <5735a229-1d3b-4a81-9a8b-f0558290f03f@googlegroups.com> |
| In reply to | #58370 |
I just said "1-> the zero argument function is sort of factory-like. It potentially has non-trivial run time, or it substitutes calling a class constructor when building certain objects. 2-> it simply retrieves a stored value (perhaps lazily evaluating it first) so 1 should clearly be a zero argument member function. 2 should be a method. " typo. Obviously, 2 should be a property.
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2013-11-03 06:52 +0000 |
| Message-ID | <5275f2ab$0$29972$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #58370 |
On Sat, 02 Nov 2013 23:09:09 -0700, Peter Cacioppi wrote:
> Python makes it very easy to turn a zero argument member function into a
> property (hooray!) by simply adding the @property decorator.
>
> (Meme for well thought py feature - "Guido was here")
It is well-thought out, but it's also quite late in Python's history.
Properties didn't get added until "new style classes" and descriptors,
which was in version 2.2. I'm not sure if it's Guido to thank for them.
> But the ease with which you can do this makes the "zero argument member
> function or property" discussion trickier for me.
>
> Generally my sense here is there are two extremes
>
> 1-> the zero argument function is sort of factory-like. It potentially
> has non-trivial run time, or it substitutes calling a class constructor
> when building certain objects. 2-> it simply retrieves a stored value
> (perhaps lazily evaluating it first)
I normally go with something like this:
Something with a significant overhead (e.g. memory or running time)
should be a method. The fact that you have to call it is a hint that it
may require non-trivial resources/time to perform.
On the other hand, something that "feels" like it ought to be an inherent
attribute of an object should be a property if you need it to be lazily
calculated, or a standard attribute if you want to give direct access to
it.
For example, imagine an object representing a printable page. The paper
size (A4, A3, foolscap, etc.) is an inherent attribute of a page, so it
ought to be accessed using attribute notation:
mypage.size
If this is lazily generated, or if you want to protect the attribute with
data validation, you should use a property. Otherwise, an ordinary data
attribute is acceptable. (This isn't Java or Ruby, where data-hiding is
compulsory :-)
On the other hand, the Postscript image of the page is not inherent to
the page, and it is also expensive to generate. So it ought to be
generated lazily, only when needed, but using method notation:
mypage.postscript()
Page margins are intermediate. They feel kind of inherent to a page, but
not exactly -- in a complex document, the margins may depend on the
section you are in. Margins can vary depending on whether the page is at
the left or the right. So page margins probably ought to be computed
attributes. But they probably won't be terribly expensive to compute. So
here I would again go with a property, assuming the page object knows
whether it is on the left or the right, and which section it belongs to.
But if somebody else decided that margins ought to be an explicit method,
I wouldn't consider them wrong. It is a matter of personal taste.
[...]
> I also think that foo.size() implies that foo performs a count every
> time it's called, and foo.size implies that the run time will amortize
> to O(1) somehow (usually with lazy eval). So the implementation should
> drive the property or not decision.
I think that is reasonable.
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Peter Cacioppi <peter.cacioppi@gmail.com> |
|---|---|
| Date | 2013-11-03 00:19 -0700 |
| Message-ID | <604e2aff-e455-4573-95b3-1fb115ac1f5d@googlegroups.com> |
| In reply to | #58370 |
Steve said: "(This isn't Java or Ruby, where data-hiding is compulsory :-) " (You could add C++ and C# to this list). This is golden nugget for me. The old synapses are pretty well grooved to think of data hiding as good hygiene. Even though I've read a fair bit of Python text I still need to be reminded of the little idiomatic differences between Py and all the languages made obsolete by Py ;) Thanks.
[toc] | [prev] | [next] | [standalone]
| From | Peter Cacioppi <peter.cacioppi@gmail.com> |
|---|---|
| Date | 2013-11-03 01:06 -0700 |
| Message-ID | <7266a77b-3404-4974-8364-b0cb50ed45a5@googlegroups.com> |
| In reply to | #58370 |
Steve said: "(This isn't Java or Ruby, where data-hiding is compulsory :-) " At the risk of striking a sessile equine, when the attribute shouldn't be modified directly by client code, then you hide it and use a property to allow client code access. It is the idiom of allowing client code to edit read-write data directly via attributes that is pythonic, even though discouraged (somewhat) in other languages. Actually C# is mature enough for this idiom. C# and Python both support getter/setter methods that present as direct attribute access to client code, and thus allow you to refactor the class without breaking backwards compatibility.
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2013-11-03 01:53 -0700 |
| Message-ID | <mailman.1970.1383468872.18130.python-list@python.org> |
| In reply to | #58379 |
On Sun, Nov 3, 2013 at 1:06 AM, Peter Cacioppi <peter.cacioppi@gmail.com> wrote: > Actually C# is mature enough for this idiom. C# and Python both support getter/setter methods that present as direct attribute access to client code, and thus allow you to refactor the class without breaking backwards compatibility. It's not as clear-cut as it looks in C#. Although refactoring the class in this way doesn't change the API, it does break ABI, which is significant in an environment where virtually everything is distributed in binary form. This happens because a property access compiled to CIL byte code is transformed into a call to a getter or setter method, which is a distinct operation from an ordinary attribute access. Whereas in Python, an attribute access is just compiled as an attribute access no matter what the underlying implementation of that access may end up being at run-time.
[toc] | [prev] | [next] | [standalone]
| From | Peter Cacioppi <peter.cacioppi@gmail.com> |
|---|---|
| Date | 2013-11-03 13:23 -0800 |
| Message-ID | <7612355b-ae3b-47b9-9608-0b3e993f7452@googlegroups.com> |
| In reply to | #58370 |
Ian said : " Whereas in Python, an attribute access is just compiled as an attribute access no matter what the underlying implementation of that access may end up being at run-time. " Really? Very nice. Have a good link handy for that? I'm compiling a codex of "why py is better?".
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2013-11-03 19:27 -0700 |
| Message-ID | <mailman.2003.1383532105.18130.python-list@python.org> |
| In reply to | #58409 |
On Sun, Nov 3, 2013 at 2:23 PM, Peter Cacioppi <peter.cacioppi@gmail.com> wrote: > Ian said : > > " Whereas in Python, an attribute access is just > compiled as an attribute access no matter what the underlying > implementation of that access may end up being at run-time. " > > Really? Very nice. Have a good link handy for that? I'm compiling a codex of "why py is better?". Sorry, no, but this fact should be apparent as a consequence of Python's dynamicism. Since the compiler generally can't predict what the types of objects will be, the bytecode that it generates can't depend on those types.
[toc] | [prev] | [next] | [standalone]
| From | Peter Cacioppi <peter.cacioppi@gmail.com> |
|---|---|
| Date | 2013-11-04 15:14 -0800 |
| Message-ID | <6d11ca0d-083b-469e-ba87-9fb9740c7876@googlegroups.com> |
| In reply to | #58370 |
Ian said : "Since the compiler generally can't predict what the types of objects will be, the bytecode that it generates can't depend on those types." very nice, the py is strong with you. Thanks, Pete
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web