Avoiding local variable declarations?

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

    Avoiding local variable declarations?

    I have some old Common Lisp functions I'd like to rewrite in Python
    (I'm still new to Python), and one thing I miss is not having to
    declare local variables.

    For example, I have this Lisp function:

    (defun random-char ()
    "Generate a random char from one of [0-9][a-z][A-Z]"
    (if (< 50 (random 100))
    (code-char (+ (random 10) 48)) ; ascii 48 = 0
    (code-char (+ (random 26) (if (< 50 (random 100)) 65 97))))) ;
    ascii 65 = A, 97 = a

    My Python version looks like this:

    def random_char ():
    '''Generate a random char from one of [0-9][a-z][A-Z]'''
    if random.randrang e(0, 100) 50:
    return chr( random.randrang e(0, 10) + 48 ) # ascii 48 = 0
    else:
    offset = 65 # ascii 65 = A
    if random.randrang e(0, 100) 50:
    offset = 97 # ascii 97 = a
    return chr( random.randrang e(0, 26) + offset )

    Logically, it's equivalent of the Lisp version.

    But is there any way to avoid using the local variable (offset) in the
    Python version?
  • Chris Mellon

    #2
    Re: Avoiding local variable declarations?

    On Thu, Nov 13, 2008 at 2:22 PM, dpapathanasiou
    <denis.papathan asiou@gmail.com wrote:
    I have some old Common Lisp functions I'd like to rewrite in Python
    (I'm still new to Python), and one thing I miss is not having to
    declare local variables.
    >
    For example, I have this Lisp function:
    >
    (defun random-char ()
    "Generate a random char from one of [0-9][a-z][A-Z]"
    (if (< 50 (random 100))
    (code-char (+ (random 10) 48)) ; ascii 48 = 0
    (code-char (+ (random 26) (if (< 50 (random 100)) 65 97))))) ;
    ascii 65 = A, 97 = a
    >
    My Python version looks like this:
    >
    def random_char ():
    '''Generate a random char from one of [0-9][a-z][A-Z]'''
    if random.randrang e(0, 100) 50:
    return chr( random.randrang e(0, 10) + 48 ) # ascii 48 = 0
    else:
    offset = 65 # ascii 65 = A
    if random.randrang e(0, 100) 50:
    offset = 97 # ascii 97 = a
    return chr( random.randrang e(0, 26) + offset )
    >
    Logically, it's equivalent of the Lisp version.
    >
    But is there any way to avoid using the local variable (offset) in the
    Python version?
    Any time you port between languages, it's rarely a good idea to just
    convert code verbatim. For example:

    import random, string
    def random_char():
    return random.choice(s tring.ascii_let ters + string.digits)

    Comment

    • Gary Herron

      #3
      Re: Avoiding local variable declarations?

      dpapathanasiou wrote:
      I have some old Common Lisp functions I'd like to rewrite in Python
      (I'm still new to Python), and one thing I miss is not having to
      declare local variables.
      >
      For example, I have this Lisp function:
      >
      (defun random-char ()
      "Generate a random char from one of [0-9][a-z][A-Z]"
      (if (< 50 (random 100))
      (code-char (+ (random 10) 48)) ; ascii 48 = 0
      (code-char (+ (random 26) (if (< 50 (random 100)) 65 97))))) ;
      ascii 65 = A, 97 = a
      >
      My Python version looks like this:
      >
      def random_char ():
      '''Generate a random char from one of [0-9][a-z][A-Z]'''
      if random.randrang e(0, 100) 50:
      return chr( random.randrang e(0, 10) + 48 ) # ascii 48 = 0
      else:
      offset = 65 # ascii 65 = A
      if random.randrang e(0, 100) 50:
      offset = 97 # ascii 97 = a
      return chr( random.randrang e(0, 26) + offset )
      >
      Logically, it's equivalent of the Lisp version.
      >
      But is there any way to avoid using the local variable (offset) in the
      Python version?
      >
      Yes, you can avoid using offset, but *why*. This certainly won't make
      your code cleaner or more easily read/understood/maintainable.

      return chr( random.randrang e(0, 26) + (97 if random.randrang e(0,
      100) 50 else 65)

      or

      if random.randrang e(0, 100) 50:
      return chr( random.randrang e(0, 26) + 97)
      else:
      return chr( random.randrang e(0, 26) + 65)

      or

      return chr( random.randrang e(0, 26) + [26,97][random.randrang e(0,
      100) 50]

      or

      ... probably other ways can be found ...

      but what's wrong with you original code?


      Gary Herron



      Comment

      • dpapathanasiou

        #4
        Re: Avoiding local variable declarations?

        return chr( random.randrang e(0, 26) + (97 if random.randrang e(0,
        100) 50 else 65)
        or
        >
        return chr( random.randrang e(0, 26) + [26,97][random.randrang e(0,
        100) 50]
        Ah, thanks, these are the syntax examples I was looking for.
        but what's wrong with you original code?
        I come from a functional programming school of thought, where you
        avoid local variable declarations if at all possible.

        Comment

        • dpapathanasiou

          #5
          Re: Avoiding local variable declarations?

          Any time you port between languages, it's rarely a good idea to just
          convert code verbatim. For example:
          >
          import random, string
          def random_char():
          return random.choice(s tring.ascii_let ters + string.digits)
          Good point, and thanks for the idiomatic Python example (I like the
          conciseness); I'm still wrapping my mind around how Python statements
          should be constructed.

          Comment

          • Andrew Koenig

            #6
            Re: Avoiding local variable declarations?

            "Gary Herron" <gherron@island training.comwro te in message
            news:mailman.39 59.1226608805.3 487.python-list@python.org ...
            return chr( random.randrang e(0, 26) + [26,97][random.randrang e(0,
            100) 50]
            return chr(random.rand range(0, 26) + (97 if random.randrang e(0,100) 50
            else 26))


            Comment

            • Aahz

              #7
              Re: Avoiding local variable declarations?

              In article <482bf887-b7f3-4528-badd-3605d7628881@f4 0g2000pri.googl egroups.com>,
              dpapathanasiou <denis.papathan asiou@gmail.com wrote:
              >
              >I come from a functional programming school of thought, where you
              >avoid local variable declarations if at all possible.
              Python is *so* not a functional programming language. There are a number
              of functional programming features available, but trying to push your
              Python programs into primarily a functional style will result in
              significantly poorer Python programs. Find another language if
              functional programming is critical to your style.
              --
              Aahz (aahz@pythoncra ft.com) <* http://www.pythoncraft.com/

              "It is easier to optimize correct code than to correct optimized code."
              --Bill Harlan

              Comment

              • Paul McGuire

                #8
                Re: Avoiding local variable declarations?

                On Nov 13, 2:32 pm, "Chris Mellon" <arka...@gmail. comwrote:
                On Thu, Nov 13, 2008 at 2:22 PM, dpapathanasiou
                >
                >
                >
                >
                >
                <denis.papathan as...@gmail.com wrote:
                I have some old Common Lisp functions I'd like to rewrite in Python
                (I'm still new to Python), and one thing I miss is not having to
                declare local variables.
                >
                For example, I have this Lisp function:
                >
                (defun random-char ()
                 "Generate a random char from one of [0-9][a-z][A-Z]"
                 (if (< 50 (random 100))
                     (code-char (+ (random 10) 48)) ; ascii 48 = 0
                     (code-char (+ (random 26) (if (< 50 (random 100)) 65 97)))));
                ascii 65 = A, 97 = a
                >
                My Python version looks like this:
                >
                def random_char ():
                   '''Generate a random char from one of [0-9][a-z][A-Z]'''
                   if random.randrang e(0, 100) 50:
                       return chr( random.randrang e(0, 10) + 48 ) # ascii 48 = 0
                   else:
                       offset = 65 # ascii 65 = A
                       if random.randrang e(0, 100) 50:
                           offset = 97 # ascii 97 = a
                       return chr( random.randrang e(0, 26) + offset )
                >
                Logically, it's equivalent of the Lisp version.
                >
                But is there any way to avoid using the local variable (offset) in the
                Python version?
                >
                Any time you port between languages, it's rarely a good idea to just
                convert code verbatim. For example:
                >
                import random, string
                def random_char():
                    return random.choice(s tring.ascii_let ters + string.digits)- Hide quoted text -
                >
                - Show quoted text -
                Not quite. The original Lisp function first flips a coin to see if a
                digit or alpha should be returned. If alpha, then flips a coin again
                to see if upper or lower case should be returned. The alpha branch
                could be collapsed into just returning a random selection from [A-Za-
                z], but if you combine the alpha and numeric branches, you have less
                than a 1/3 chance of getting a digit, vs. the 50-50 chance of the
                original Lisp code.

                Try this:

                import random
                import string
                coinflip = lambda : int(random.rand om()*2)
                if coinflip():
                return random.choice(s tring.digits)
                else:
                return random.choice(s tring.ascii_let ters)

                or just:

                return random.choice( (string.digits, string.ascii_le tters)[coinflip
                ()] )

                -- Paul

                Comment

                • bearophileHUGS@lycos.com

                  #9
                  Re: Avoiding local variable declarations?

                  Paul McGuire:
                  coinflip = lambda : int(random.rand om()*2)
                  I warmly suggest you to use this instead:
                  randrange(2)

                  Bye,
                  bearophile

                  Comment

                  • Paul McGuire

                    #10
                    Re: Avoiding local variable declarations?

                    On Nov 13, 6:47 pm, bearophileH...@ lycos.com wrote:
                    Paul McGuire:
                    >
                    coinflip = lambda : int(random.rand om()*2)
                    >
                    I warmly suggest you to use this instead:
                    randrange(2)
                    >
                    Bye,
                    bearophile
                    Really? Looking at randrange, it sure seems to do a lot of work in
                    pursuit of handling all possible cases for specifying range
                    boundaries, step values, etc. In fact, I think flipping a coin is a
                    common enough task that it might even merit an addition to the random
                    module API. It certainly would allow us to get rid of all of these
                    variations on the theme, such as "if randrange(100) 50", or
                    "random.cho ice([True,False])". For that matter, my own obscure int
                    (random.random( ) * 2) is better implemented using a direct comparison
                    to random.random() , no need for multiplication, or int calls or
                    anything else. Having an explicit method would also help prevent
                    minor erroneous bugs like "if random.random() 0.5", given that the
                    range of random.random() is (0.0, 1.0] (that is, the lower half would
                    be 0 inclusive to 0.5 exclusive, and the upper half 0.5 inclusive to
                    1.0 exclusive).

                    If I would change anything, I think I prefer the name coin_toss over
                    coinflip.

                    So:

                    coin_toss = lambda : random.random() >= 0.5

                    -- Paul

                    Comment

                    • Arnaud Delobelle

                      #11
                      Re: Avoiding local variable declarations?

                      dpapathanasiou <denis.papathan asiou@gmail.com writes:
                      >but what's wrong with you original code?
                      >
                      I come from a functional programming school of thought, where you
                      avoid local variable declarations if at all possible.
                      Holding on to this principle won't help you write nice Python code :)

                      Although you will acquire lots of clever-looking tricks.

                      --
                      Arnaud

                      Comment

                      • bearophileHUGS@lycos.com

                        #12
                        Re: Avoiding local variable declarations?

                        Paul McGuire:
                        Really?  Looking at randrange, it sure seems to do a lot of work in
                        pursuit of handling all possible cases for specifying range
                        boundaries, step values, etc.
                        Well, randrange is the simpler thing to read and understand here, and
                        maybe the one less likely to get wrong too.
                        But I understand your concerns. The solution is to write a C function
                        in the random module that implements the randrange in an efficient
                        way.

                        Bye,
                        bearophile

                        Comment

                        • Mark Wooding

                          #13
                          Re: Avoiding local variable declarations?

                          Chris Mellon <arkanes@gmail. comwrote:
                          Any time you port between languages, it's rarely a good idea to just
                          convert code verbatim. For example:
                          >
                          import random, string
                          def random_char():
                          return random.choice(s tring.ascii_let ters + string.digits)
                          Note that this code doesn't preserve the output distribution of the
                          original, for which once expects half the characters to be numeric. I
                          don't know if that's relevant; in fact I suspect that the original was
                          buggy.

                          -- [mdw]

                          Comment

                          • Paul McGuire

                            #14
                            Re: Avoiding local variable declarations?

                            On Nov 14, 12:08 pm, Mark Wooding <m...@distorted .org.ukwrote:
                            Chris Mellon <arka...@gmail. comwrote:
                            Any time you port between languages, it's rarely a good idea to just
                            convert code verbatim. For example:
                            >
                            import random, string
                            def random_char():
                                return random.choice(s tring.ascii_let ters + string.digits)
                            >
                            Note that this code doesn't preserve the output distribution of the
                            original, for which once expects half the characters to be numeric.  I
                            don't know if that's relevant; in fact I suspect that the original was
                            buggy.
                            >
                            -- [mdw]
                            I couldn't have said it better myself. Well, if not better, at least
                            earlier...
                            (http://groups.google.com/group/comp....779bf57e4d3a0?
                            hl=en)

                            -- Paul

                            Comment

                            • Jorgen Grahn

                              #15
                              Re: Avoiding local variable declarations?

                              On Thu, 13 Nov 2008 12:49:02 -0800 (PST), dpapathanasiou <denis.papathan asiou@gmail.com wrote:
                              ....
                              >but what's wrong with you original code?
                              >
                              I come from a functional programming school of thought, where you
                              avoid local variable declarations if at all possible.
                              I'm not sure that's universal. Using Standard ML at Uni, it was often
                              useful to use "let name = expr in expr" (or whatever the syntax was)
                              to simplify an expression. Directly borrowed from mathematics, I
                              assume.

                              'name' is not a variable, of course; there are no variables in
                              functional programming. Can't remember what it's called -- named
                              expression, maybe?

                              I think I use local names in Python about as much as I did in SML.

                              /Jorgen

                              --
                              // Jorgen Grahn <grahn@ Ph'nglui mglw'nafh Cthulhu
                              \X/ snipabacken.se R'lyeh wgah'nagl fhtagn!

                              Comment

                              Working...