Good code patterns in Python

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Will Stuyvesant

    Good code patterns in Python

    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
  • Terry Reedy

    #2
    Re: Good code patterns in Python


    "Will Stuyvesant" <hwlgw@hotmail. com> wrote in message
    news:cb035744.0 307010149.399df 2eb@posting.goo gle.com...[color=blue]
    > 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[/color]

    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_valu e)== True or either == False).

    This is both safe and efficient, avoiding both
    [color=blue]
    > 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.[/color]

    and
    [color=blue]
    > There is the small overhead of assigning something twice[/color]

    (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


    Comment

    • Jiri Barton

      #3
      Re: Good code patterns in Python

      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




      Comment

      • Steven Taschuk

        #4
        Re: Good code patterns in Python

        Quoth Will Stuyvesant:[color=blue]
        > 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[/color]

        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.
        [color=blue]
        > 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.[/color]

        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.)
        [color=blue]
        > There is the small overhead of assigning something twice[/color]

        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
        staschuk@telusp lanet.net ,-= U
        1 1

        Comment

        • Lulu of the Lotus-Eaters

          #5
          Re: Good code patterns in Python

          |hwlgw@hotmail. com (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

          mis6@pitt.edu (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_computatio n()
          if not some_condition:
          some_name = other_computati on()

          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


          Comment

          • Dennis Lee Bieber

            #6
            Re: Good code patterns in Python

            Will Stuyvesant fed this fish to the penguins on Tuesday 01 July 2003
            02:49 am:
            [color=blue]
            >
            > some_name = some_value
            > if not some_condition:
            > some_name = other_value
            >[/color]
            Ugh... Shades of old BASIC...

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

            --[color=blue]
            > =============== =============== =============== =============== == <
            > wlfraed@ix.netc om.com | Wulfraed Dennis Lee Bieber KD6MOG <
            > wulfraed@dm.net | Bestiaria Support Staff <
            > =============== =============== =============== =============== == <
            > Bestiaria Home Page: http://www.beastie.dm.net/ <
            > Home Page: http://www.dm.net/~wulfraed/ <[/color]

            Comment

            • Kirk Job-Sluder

              #7
              Re: Good code patterns in Python

              Will Stuyvesant <hwlgw@hotmail. com> wrote:[color=blue]
              > 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?[/color]

              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.
              [color=blue]
              > 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.[/color]

              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.

              [color=blue]
              > 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 :-)[/color]

              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


              Comment

              • Erik Max Francis

                #8
                Re: Good code patterns in Python

                Kirk Job-Sluder wrote:
                [color=blue]
                > Will Stuyvesant <hwlgw@hotmail. com> wrote:
                >[color=green]
                > > 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?[/color]
                >
                > 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.[/color]

                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 && max@alcyone.com && 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

                Comment

                • Bernhard Herzog

                  #9
                  Re: Good code patterns in Python

                  Erik Max Francis <max@alcyone.co m> writes:
                  [color=blue]
                  > 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.)[/color]

                  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/

                  Comment

                  • Erik Max Francis

                    #10
                    Re: Good code patterns in Python

                    Bernhard Herzog wrote:
                    [color=blue]
                    > Guido broke his silence at EuroPython: The ternary operator will not
                    > be
                    > added to Python.[/color]

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

                    --
                    Erik Max Francis && max@alcyone.com && http://www.alcyone.com/max/
                    __ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
                    / \ Divorces are made in Heaven.
                    \__/ Oscar Wilde

                    Comment

                    • Ben Finney

                      #11
                      Conservative language design

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

                      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

                      Comment

                      • Erik Max Francis

                        #12
                        Re: Good code patterns in Python

                        Bernhard Herzog wrote:
                        [color=blue]
                        > Guido broke his silence at EuroPython: The ternary operator will not
                        > be
                        > added to Python.[/color]

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

                        --
                        Erik Max Francis && max@alcyone.com && http://www.alcyone.com/max/
                        __ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
                        / \ Divorces are made in Heaven.
                        \__/ Oscar Wilde

                        Comment

                        • Ben Finney

                          #13
                          Conservative language design

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

                          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

                          Comment

                          Working...