Good code patterns in Python

Discussion in 'Python' started by Will Stuyvesant, Jul 1, 2003.

  1. If you know that your source code is going to be used
    later by others, then I feel that code with the pattern:

    if some_condition:
    some_name = some_value
    else:
    some_name = other_value

    is often a mistake. Much better, safer, would be:

    some_name = some_value
    if not some_condition:
    some_name = other_value

    Why?

    Because those people reusing your code might decide to
    change or adapt the "if" part of the first example. Or
    the "else" part for that matter. And then they could end
    up with "some_name" being undefined, crashing other code
    maybe 1000's of lines away. This could happen for example
    because they use exceptions in the "if" part that jump out
    of it, etc.

    There is the small overhead of assigning something twice
    to some_name in the safer example, so if performance is
    *that* important then the first example is better, but I
    feel there should be comments with warnings around it:
    **CREATING A NEW OBJECT REFERENCE HERE!** Hmm, now that
    makes code ugly :)

    What are your thoughts about this? I am interested in
    current large scale software development practice, and
    guidelines that are used there, especially for dynamically
    typed languages like Python.

    There must be a lot of advisable code design patterns (I
    can't find a good name in English) like this for use in
    software development with many programmers. Perhaps a
    collection with good documentation would be interesting?
    Or a tool like pychecker that flags "bad" patterns?


    --
    People who miss goto now use exceptions
    Will Stuyvesant, Jul 1, 2003
    #1
    1. Advertising

  2. Will Stuyvesant

    Terry Reedy Guest

    "Will Stuyvesant" <> wrote in message
    news:...
    > If you know that your source code is going to be used
    > later by others, then I feel that code with the pattern:
    >
    > if some_condition:
    > some_name = some_value
    > else:
    > some_name = other_value
    >
    > is often a mistake. Much better, safer, would be:
    >
    > some_name = some_value
    > if not some_condition:
    > some_name = other_value


    If, bool(some_value) == True, I personally would use the near-ternary
    idiom

    some_name = some_condition and some_value or other_value

    (or equivalent form for bool(other_value)== True or either == False).

    This is both safe and efficient, avoiding both

    > Because those people reusing your code might decide to
    > change or adapt the "if" part of the first example. Or
    > the "else" part for that matter. And then they could end
    > up with "some_name" being undefined, crashing other code
    > maybe 1000's of lines away.


    and

    > There is the small overhead of assigning something twice


    (I acknowledge that some think this ugly and worse and would not be
    caught dead writing such an 'abomination', so flame repetition is not
    necessary ;-)

    Terry J. Reedy
    Terry Reedy, Jul 1, 2003
    #2
    1. Advertising

  3. Will Stuyvesant

    Jiri Barton Guest

    One, there has been a proposal for a ternary operator on python.org. You
    know that kind of (cond) ? (eval1) : (eval2) stuff.

    Two, no need to guard that code. Passing and assigning a paramater should
    always make you THINK about what's happening.

    Three, how about
    a = 1
    b = 0
    ......
    if b == 0:
    a = 0
    else:
    a = a/b
    ? You cannot replace it with your pattern. Sure enough, there are far more
    examples of this -- when you cannot evaluate the first expression.

    Jiri Barton
    Jiri Barton, Jul 1, 2003
    #3
  4. Quoth Will Stuyvesant:
    > If you know that your source code is going to be used
    > later by others, then I feel that code with the pattern:
    >
    > if some_condition:
    > some_name = some_value
    > else:
    > some_name = other_value
    >
    > is often a mistake. Much better, safer, would be:
    >
    > some_name = some_value
    > if not some_condition:
    > some_name = other_value


    I join the Ms in disagreeing strongly. The visual parallelism of
    the first reflects the conceptual parallelism of the two cases,
    while the second obscures it.

    > Because those people reusing your code might decide to
    > change or adapt the "if" part of the first example. Or
    > the "else" part for that matter. And then they could end
    > up with "some_name" being undefined, crashing other code
    > maybe 1000's of lines away. This could happen for example
    > because they use exceptions in the "if" part that jump out
    > of it, etc.


    I assume you're not speaking of local variables here -- a function
    thousands of lines long would be unconscionable.

    Presumably you're speaking of attributes, and the danger is that
    an exception in one branch would cause the object's invariants be
    broken. But I don't see how this would happen in practice, in a
    way which would (a) leave the attribute undefined and (b) imply to
    the caller that everything was fine. Do you have an example?

    (Much more serious and more common is the danger that after an
    exception is raised, the function has done half its work and left
    the object in a broken state. But this has nothing to do with
    what you're talking about.)

    > There is the small overhead of assigning something twice


    Too minor to worry about:

    $ timeit -s'def foo(): global a; a = 1' 'foo()'
    100000 loops, best of 3: 5.51 usec per loop
    $ timeit -s'def foo(): global a; a = 1; a = 1' 'foo()'
    100000 loops, best of 3: 6.1 usec per loop

    If I'm running the code a million times, and everything else in
    the loop takes less than a microsecond, this might be worth
    thinking about.

    --
    Steven Taschuk w_w
    ,-= U
    1 1
    Steven Taschuk, Jul 1, 2003
    #4
  5. | (Will Stuyvesant) wrote:
    |> if some_condition:
    |> some_name = some_value
    |> else:
    |> some_name = other_value
    |> is often a mistake. Much better, safer, would be:
    |> some_name = some_value
    |> if not some_condition:
    |> some_name = other_value

    (Michele Simionato) wrote previously:
    |I am sorry, but I feel that the first form is MUCH more readable than the
    |second one; the first form is crystal clear to me, whereas I must read
    |the second form two or three times to understand what it is going on.

    Moreover, actual code often assigns from computations, not simply one
    name to another. The harder-to-read form risks bad side effects (or
    simply a performance hit):

    some_name = some_computation()
    if not some_condition:
    some_name = other_computation()

    The straightforward if/else form avoids superfluous computations.

    Yours, Lulu...

    --
    mertz@ _/_/_/_/_/_/_/ THIS MESSAGE WAS BROUGHT TO YOU BY:_/_/_/_/ v i
    gnosis _/_/ Postmodern Enterprises _/_/ s r
    ..cx _/_/ MAKERS OF CHAOS.... _/_/ i u
    _/_/_/_/_/ LOOK FOR IT IN A NEIGHBORHOOD NEAR YOU_/_/_/_/_/ g s
    Lulu of the Lotus-Eaters, Jul 1, 2003
    #5
  6. Will Stuyvesant fed this fish to the penguins on Tuesday 01 July 2003
    02:49 am:

    >
    > some_name = some_value
    > if not some_condition:
    > some_name = other_value
    >

    Ugh... Shades of old BASIC...

    10 sn = sv
    20 if sc then 40
    30 sn = ov
    40 ...

    --
    > ============================================================== <
    > | Wulfraed Dennis Lee Bieber KD6MOG <
    > | Bestiaria Support Staff <
    > ============================================================== <
    > Bestiaria Home Page: http://www.beastie.dm.net/ <
    > Home Page: http://www.dm.net/~wulfraed/ <
    Dennis Lee Bieber, Jul 2, 2003
    #6
  7. Will Stuyvesant <> wrote:
    > If you know that your source code is going to be used
    > later by others, then I feel that code with the pattern:
    >
    > if some_condition:
    > some_name = some_value
    > else:
    > some_name = other_value
    >
    > is often a mistake. Much better, safer, would be:
    >
    > some_name = some_value
    > if not some_condition:
    > some_name = other_value
    >
    > Why?


    My personal opinion is that it depends on context. The first idiom
    is more clear when you are dealing with some kind of a switch. The
    second idiom works better if you have a default value that needs to be
    overridden in some cases.

    > Because those people reusing your code might decide to
    > change or adapt the "if" part of the first example. Or
    > the "else" part for that matter. And then they could end
    > up with "some_name" being undefined, crashing other code
    > maybe 1000's of lines away. This could happen for example
    > because they use exceptions in the "if" part that jump out
    > of it, etc.


    Of course, another alternative is to combine both approaches by setting
    a default value:

    #set default for some_value
    some_value = []
    if condition1:
    some_value = function1()
    else:
    some_value = function2()

    And then if you really want to be safe the functions using
    some_value should do reality checks as well.
    def function3(some_value=[]):
    if len(some_value):
    do something
    else:
    do something else.

    I think that an argument for the readability of if-else is that because
    the logic is made more clear, it can be more effectively replaced.


    > There is the small overhead of assigning something twice
    > to some_name in the safer example, so if performance is
    > *that* important then the first example is better, but I
    > feel there should be comments with warnings around it:
    > **CREATING A NEW OBJECT REFERENCE HERE!** Hmm, now that
    > makes code ugly :)


    The problem here is that ***creating a new object reference*** is not
    only ugly, but its ambiguous as well. (What kind of object, what is it
    used for?) If indeed some_name is an important variable in your program,
    then provide a full description.

    #some_value (string) is used to hold the widgit that will
    #be passed to a wadget and eventually passed
    #to standard output.

    --
    Kirk Job-Sluder
    http://www.jobsluder.net/~kirk/
    Kirk Job-Sluder, Jul 2, 2003
    #7
  8. Kirk Job-Sluder wrote:

    > Will Stuyvesant <> wrote:
    >
    > > If you know that your source code is going to be used
    > > later by others, then I feel that code with the pattern:
    > >
    > > if some_condition:
    > > some_name = some_value
    > > else:
    > > some_name = other_value
    > >
    > > is often a mistake. Much better, safer, would be:
    > >
    > > some_name = some_value
    > > if not some_condition:
    > > some_name = other_value
    > >
    > > Why?

    >
    > My personal opinion is that it depends on context. The first idiom
    > is more clear when you are dealing with some kind of a switch. The
    > second idiom works better if you have a default value that needs to be
    > overridden in some cases.


    I presume the "mistake" he's referring to with the first snippet is the
    potential problem that could happen if the variable is named
    incorrectly:

    if condition:
    variable = someValue
    else:
    varaible = otherValue # [sic] note the typo!

    When you really want an atomic assignment of one singular variable. The
    complete solution to this would probably be a conditional expression,
    e.g.:

    variable = (if condition: someValue else: otherValue)

    eliminating the duplication which can lead to errors. (Python, of
    course, doesn't have such a construct, and the silence after the
    conditional expression PEP vote and the long silence thereafter suggests
    that it never will.)

    I still don't think this significant of a risk to warrant widespread
    conversion of statements to the form Will suggests, especially when you
    have things like PyChecker that can check for (probable) typos. It's a
    slightly unfortunate wart in dynamic languages without conditional
    operators, but I don't think it rises to the level of something that
    should be corrected via such (what seems to me) a heavy-handed style.

    --
    Erik Max Francis && && http://www.alcyone.com/max/
    __ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
    / \ When the solution is simple, God is answering.
    \__/ Albert Einstein
    Erik Max Francis, Jul 2, 2003
    #8
  9. Erik Max Francis <> writes:

    > The
    > complete solution to this would probably be a conditional expression,
    > e.g.:
    >
    > variable = (if condition: someValue else: otherValue)
    >
    > eliminating the duplication which can lead to errors. (Python, of
    > course, doesn't have such a construct, and the silence after the
    > conditional expression PEP vote and the long silence thereafter suggests
    > that it never will.)


    Guido broke his silence at EuroPython: The ternary operator will not be
    added to Python.

    Bernhard

    --
    Intevation GmbH http://intevation.de/
    Sketch http://sketch.sourceforge.net/
    MapIt! http://www.mapit.de/
    Bernhard Herzog, Jul 2, 2003
    #9
  10. Bernhard Herzog wrote:

    > Guido broke his silence at EuroPython: The ternary operator will not
    > be
    > added to Python.


    As I said, it's hardly a big surprise.

    --
    Erik Max Francis && && http://www.alcyone.com/max/
    __ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
    / \ Divorces are made in Heaven.
    \__/ Oscar Wilde
    Erik Max Francis, Jul 2, 2003
    #10
  11. Will Stuyvesant

    Ben Finney Guest

    Conservative language design

    On Wed, 2 Jul 2003 15:43:33 +0200, holger krekel wrote:
    > Actually Guido made it pretty clear that he will be very careful about
    > adding language features especially at the syntax level.


    Thank goodness the Boolean type made it in, then. (Not a syntax-level
    change, but still a pretty fundamental one.)

    --
    \ "First they came for the verbs, and I said nothing, for verbing |
    `\ weirds language. Then, they arrival for the nouns and I speech |
    _o__) nothing, for I no verbs." -- Peter Ellis |
    http://bignose.squidly.org/ 9CFE12B0 791A4267 887F520C B7AC2E51 BD41714B
    Ben Finney, Jul 3, 2003
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Abhijit Mhatre
    Replies:
    2
    Views:
    423
  2. crichmon
    Replies:
    4
    Views:
    467
    Mabden
    Jul 7, 2004
  3. Bob Gailer

    Re: Good code patterns in Python

    Bob Gailer, Jul 1, 2003, in forum: Python
    Replies:
    33
    Views:
    787
    Eric Sosman
    Jul 29, 2003
  4. Michael Chermside

    Good code patterns in Python

    Michael Chermside, Jul 1, 2003, in forum: Python
    Replies:
    2
    Views:
    319
    Max M
    Jul 3, 2003
  5. Michael Sparks
    Replies:
    2
    Views:
    262
    Max M
    Jul 7, 2003
Loading...

Share This Page