Making every no-arg method a property?

Chris Angelico rosuav at gmail.com
Wed Aug 6 07:26:47 EDT 2014


On Wed, Aug 6, 2014 at 7:15 PM, Steven D'Aprano <steve at pearwood.info> wrote:
> On Wed, 06 Aug 2014 12:07:58 +1000, Chris Angelico wrote:
>
>> On Wed, Aug 6, 2014 at 10:49 AM, Steven D'Aprano
>> <steve+comp.lang.python at pearwood.info> wrote:
>>> A
>>> plethora of argument-less methods is a code smell -- that doesn't mean
>>> it's *necessarily* a bad idea, but the class design really needs a
>>> careful review.
>>
>> There are plenty of no-argument mutator methods, where the name of the
>> method (and the target object, obviously) is all the info you need. You
>> can clear() or copy() something with any more info, reverse() a list,
>> pop() from a list, etc.
>
> They don't have to be mutator methods. The same applies to string methods
> like upper(), lower(), isalpha() and many others.
>
> I'm not sure if you're agreeing or disagreeing with me.

Agreeing with your primary point, disagreeing with this subpoint.

> All these
> examples shouldn't be treated as properties either. This should be
> grounds for being slapped with a large herring:
>
> mydict.clear  # returns None, operates by side-effect

Wholeheartedly agree. These should NOT be properties. A property
should not mutate state, normally (I can imagine exceptions, but they
are *definitely* code smell, unless they're doing basic logging or
something).

What I disagree with is that argument-less methods, even a plethora
thereof, are *themselves* code smell. Mutator methods, and the string
methods that construct a "this string only different" result (which in
many ways are the immutable object's equivalent of mutators), will
often take no args, and are most definitely not properties, but IMO
aren't code smell. Something like isalpha() is borderline, but making
upper() a property implies that, conceptually, the upper-case version
of a string is an attribute the string already has, rather than
something that you construct from that string. It's debatable, but IMO
it makes perfect sense to keep that as a method - and it's fine for it
to take no args other than the object it's working on.

> As I said, zero-argument (one-argument, if you count self)
> methods are a code smell, not an error. As is so often the case in
> programming, the fundamental sin here is *coupling* -- zero-argument
> methods are bad if they require coupling to temporary attributes which
> exist only to communicate an argument to the method.
>
> In other words, one of the sins of zero-argument methods is the same as
> that of zero-argument functions. We wouldn't write this:
>
> def double():
>     return number_to_operate_on*2
>
> number_to_operate_on = 23
> print double()
> number_to_operate_on = 42
> print double()
>
>
> Turning it into a method on an instance, and turning the global into a
> "per instance global" (instead of per module, or application-wide)
> doesn't make it any better.

But if it were written as:

class float(float): pass # allow more attributes on float
def double(self):
    return self*2
float.double = double
number = float(23)
print(number.double())

Then it's not hidden global state any more, but it's still a
zero-argument method. Is that really just as bad? Surely it's the same
as "print(double(number))"?

ChrisA



More information about the Python-list mailing list