PyWart: More surpises via "implict conversion to boolean" (and other steaming piles!)
On Tue, 11 Feb 2014 07:36:34 -0800, Travis Griggs wrote:
> On Feb 10, 2014, at 10:30 PM, Steven D'Aprano <steve at pearwood.info>
>>> 1. Parenthesis should not be required for parameter- less
>> Of course they should. Firstly, parameter-less functions are a code-
>> smell, and ought to be discouraged. Secondly, even if you have a good
>> reason for using one -- for example, random.random -- then the
>> difference between referring to the object and calling the object
>> should be clear.
> Interesting. Can you clarify or provide some links to the
> "parameter-less functions are a code-smell? bit?
Functions map a value to another value. They can be one-to-one, or many-
to-one. (Mathematically, they cannot be one-to-many or many-to-many,
that's called a relation.) What about zero-to-one?
If the function always returns the same result, e.g.:
return "spam spam spam"
why are you using a function? Just create a constant and use that.
Calling a function which always returns the same value is a code smell.
That's not to say it is always wrong, but it smells a bit off.
How about zero-to-many functions? E.g. you have a situation where calling
function() twice might return different values. Okay, here's an example:
=> returns 42
=> returns 23
Hmmm. There's a bug in give_me_an_even_number(). How do I reproduce that
bug? What arguments do I pass? Oh, the same no-arguments as for the
Clearly, the function must have *hidden state*. Hidden state (e.g. a
global variable) makes it hard to reason about the function call, since
you don't know what the hidden state is. So that's also a bit smelly.
Hidden state is generally bad, because it makes it hard to reason about
the function call, hard to reproduce results, hard to debug, hard to
test. Think about the difference in difficulty in confirming that
math.sin() of some value x returns the value 0.5, and confirming that
random.random() of some hidden state returns a specific value:
py> assert math.sin(0.5235987755982989) == 0.5
py> state = random.getstate()
py> assert random.random() == 0.41661987254534116
> OTOH, I?m not sure I?ve heard the parameters-less functions are a code
> one? Is it just loose functions that you?re referring to? As opposed to
> methods (which are just bound functions)? I could maybe accept that. But
> methods with fewer arguments, and even none, are a desirable thing.
Methods that appear to take zero arguments actually take one argument, it
is just that it is written in a different place:
is merely different syntax for:
with the bonus that str.upper and MyClass.upper live in different
namespaces and so can do different things. So I have no problem with zero-
argument methods, or functions with default values.
Remember that a code smell does not mean the code is bad. Only that it
needs to be looked at a bit more carefully. Perhaps it is bad. Or
perhaps, like durian fruit, it smells pretty awful but tastes really good.
> There are code smells that are the opposite in fact, methods with long
> parameter lists are generally seen as code smell (?passing a
Absolutely! You'll get no disagreement from me there.