PEP 318 : Def and Class in expressions

Stephen Horne steve at ninereeds.fsnet.co.uk
Sun Mar 28 01:11:41 CET 2004


On Sat, 27 Mar 2004 15:56:18 -0500, "John Roth"
<newsgroups at jhrothjr.com> wrote:

>
>"PF" <peufeu at free.fr> wrote in message news:opr5jagci1b723ru at news.free.fr...
>>
>> Hello,
>>
>> I'm pleased to see activity on this topic as it pains me to write
>> "classmethod" two pages of code after the method definition. However I
>> find the decorators to obfuscate the syntax and lessen the expressivity
>> (ie. they restrain what can be done).
>
>Why are you writing methods that long? (That's rhetorical -
>I'd break it up so I could understand it)

While readable methods tend to be short methods, breaking up a method
without good reason can also damage readability. Also, having many
simple units doesn't remove complexity - it merely means that the
complexity is in the interaction between units. And if readers can
only understand the units one or two at a time, and don't understand
how the units interact, it follows that the code as a whole isn't
readable.

I've seen this problem more times than I care to mention. You look at
module A and it all makes sense and looks fine. You look at module B
and it all makes sense and looks fine. You look at modules A and B
together and you can spot the incompatibility - the difference in the
assumptions made in each module about the interactions between them.
But when there are 100 much simpler modules, and a dozen or more play
some role in the incompatibility, suddenly its much harder to
understand how the incompatibility arises.

Keeping related code and definitions together is a good principle. But
that applies just as much to two pieces of related function body code
as it does to a function definition and its wrapper. If you routinely
split long functions purely for reasons like keeping the wrapping
statement close to the definition of the function it wraps, or out of
the principle that methods should be short, then that's fine. But
don't expect me to read it.

All things are a balance in programming, as in life. Strong principles
can get you only so far - if you impose absolute principles on
everyone and in every case, often they will do more damage than good. 

>> mymethod = staticmethod(def(args)):
>>     method code...
>
>> is also quite ugly.
>
>Why? Except for the ':', which I would eliminate (although
>there are arguements for keeping it) I think it reads quite well.

Mainly because the method code appears to be associated with the
assignment, or the assigned variable, rather than the def. It's hard
(maybe impossible?) to name a block structure in any language that
doesn't start with a word that identifies the type of block. Probably
the only common statements of any type that don't start with an
identifying keyword are assignments. That isn't a fluke.

Anyone pointing out the streaming operators in C++ gets half a point.
Strictly they're just operators in an expression, but they get used in
such an imperitive way that I half count them as statements.

>> I don't like the decorators either.
>
>Neither do I. I don't find that any version of the syntax flows.

There is a certain lack of beauty, I agree. But while there is beauty
in simplicity, there is pragmatism in realising that not all
complexity can be avoided.


>2. How to handle multiple blocks in one expression.
<snip>
>The way to handle item 2 is with the following set of
>indentation rules:

I disagree.

There are two common cases I can think of where names are used before
they are defined. One is mathematics (y = mx + c, where x is ...) and
the other is Haskell, working on much the same principle.

There is a certain similarity of purpose in the Pascal 'with' block,
in that the Haskell 'where', like the Pascal 'with', is mainly used
for abbreviation - though the means is rather different.

Messing around with these principles, I came up with...

  with x :
    x = staticmethod(x)
  where def x (args) :
    ...

But virtually the only suggestion I prefer this to is yours, I'm
afraid :-(

>5. A suspended expression continues on the line immediately
>after the end of the function body. It must be indented to the
>left of the function body, and to the right of the indentation for
>the statement containing the expression.

This suggestion is IMO close to insane.

You are breaking up a statement and putting potentially quite large
chunks of body code in the middle of it - maybe several function
bodies. And you are doing this to avoid having code between the
function definition and its wrapping assignment.

In other words, you are deliberately splitting up closely related code
in order to avoid splitting up closely related code. And making the
lexical structure and layout of Python code more complex in order to
do it.

If you limit it to the case where a single statement containing a
single def can be followed by the body code, then it isn't actually
insane (though I'm still strongly against it) but if you have two
functions being manipulated by the same wrapping code (I don't see the
need, but lets go with it anyway) then one way or another the wrapping
code is going to be separated from at least one functions body. In
this case, referring to the functions by name is the only thing that
makes sense. We don't need any new syntax to do that.


-- 
Steve Horne

steve at ninereeds dot fsnet dot co dot uk



More information about the Python-list mailing list