Rant (was Re: x*x if x>10

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

    Rant (was Re: x*x if x>10

    On Sun, 27 Jul 2008 05:24:36 -0700 (PDT), alex23 <wuwei23@gmail. comwrote:
    >On Jul 27, 10:13 pm, ssecorp <circularf...@g mail.comwrote:
    >I have seen somewhere that you can write something like:
    >x*x if x>10
    >but exactly that doesn't work and I can't get any variation to work.
    >It's called a ternary operator. The format is:
    ><label= <true-valueif <conditionels e <false-value>
    I've seen the PERL saying/motto/boast, "There's more than one way to do it"
    derided on more than one occasion on this group so what's the reason for
    this additional way to put an if else statement on one line? Are "and" and
    "or" constructions to produce the same effect not supported for this use?

    And while I'm on my high horse, I'd like to bring up list concatenations. I
    recently needed to concatenate 5 lists, which doesn't sound a particularly
    rare requirement to me. My first attempt was a straightforward loop
    extending an empty list. That worked fine but looked like an awful bulky
    solution. Afterwards I tried various formulae using "reduce" , falling foul
    of the "=" catch on one occasion. Now I'm not a professional programmer, so
    there may be good reasons for a single object to have multiple names in a
    program, but it sounds like a recipe for disaster to me. Getting back to the
    list concatenation, I finally found the itertools.chain command which is the
    most compact and fastest (or second fastest by a trivial amount, I can't
    remember which). Along the way, I must have tried/used half a dozen methods,
    ....which brings me back my initial PERL comment. There's more than one way
    to do it in Python, too.

    DaveM
  • Diez B. Roggisch

    #2
    Re: Rant (was Re: x*x if x&gt;10

    DaveM schrieb:
    On Sun, 27 Jul 2008 05:24:36 -0700 (PDT), alex23 <wuwei23@gmail. comwrote:
    >
    >On Jul 27, 10:13 pm, ssecorp <circularf...@g mail.comwrote:
    >>I have seen somewhere that you can write something like:
    >
    >>x*x if x>10
    >>but exactly that doesn't work and I can't get any variation to work.
    >
    >It's called a ternary operator. The format is:
    ><label= <true-valueif <conditionels e <false-value>
    >
    I've seen the PERL saying/motto/boast, "There's more than one way to do it"
    derided on more than one occasion on this group so what's the reason for
    this additional way to put an if else statement on one line? Are "and" and
    "or" constructions to produce the same effect not supported for this use?
    You obviously aren't aware of the pitfalls regarding the mis-use of or
    and and for this usage.

    Try this:
    >>a = True
    >>b = 1
    >>c = 2
    >>a and b or c
    1
    >>a = False
    >>a and b or c
    2
    >>a = True
    >>b = None
    >>a and b or c
    2
    >>>

    Afterwards I tried various formulae using "reduce" , falling foul
    of the "=" catch on one occasion. Now I'm not a professional programmer, so
    there may be good reasons for a single object to have multiple names in a
    program, but it sounds like a recipe for disaster to me.

    Can you tell us what you mean by "several names of one object"? You mean
    this?

    a = range(10)
    b = a

    id(a) == id(b)


    ? Passing references instead of values is an extremely important concept
    of many languages, without it you would end up copying most of the time.

    Getting back to the
    list concatenation, I finally found the itertools.chain command which is the
    most compact and fastest (or second fastest by a trivial amount, I can't
    remember which). Along the way, I must have tried/used half a dozen methods,
    ...which brings me back my initial PERL comment. There's more than one way
    to do it in Python, too.
    Any non-trivial task has that property. I don't know enough perl to have
    an example ready that shows something that python has only one way of
    doing and perl has several.

    But I *do* know that taking the python zen literally is fruitless.


    Diez

    Comment

    • Marc 'BlackJack' Rintsch

      #3
      Re: Rant (was Re: x*x if x&gt;10

      On Sun, 27 Jul 2008 16:41:19 +0200, Diez B. Roggisch wrote:
      DaveM schrieb:
      >Getting back to the
      >list concatenation, I finally found the itertools.chain command which
      >is the most compact and fastest (or second fastest by a trivial amount,
      >I can't remember which). Along the way, I must have tried/used half a
      >dozen methods, ...which brings me back my initial PERL comment. There's
      >more than one way to do it in Python, too.
      >
      Any non-trivial task has that property. I don't know enough perl to have
      an example ready that shows something that python has only one way of
      doing and perl has several.
      >
      But I *do* know that taking the python zen literally is fruitless.
      I think it should be taken more literally than the wrong reduction to
      "there should be only one way". People tend to forget "obvious" and
      "preferably " all the time.

      Ciao,
      Marc 'BlackJack' Rintsch

      Comment

      • Gary Herron

        #4
        Re: Rant (was Re: x*x if x&gt;10

        DaveM wrote:
        On Sun, 27 Jul 2008 05:24:36 -0700 (PDT), alex23 <wuwei23@gmail. comwrote:
        >
        >
        >On Jul 27, 10:13 pm, ssecorp <circularf...@g mail.comwrote:
        >>
        >>I have seen somewhere that you can write something like:
        >>>
        >
        >
        >>x*x if x>10
        >>but exactly that doesn't work and I can't get any variation to work.
        >>>
        >
        >
        >It's called a ternary operator. The format is:
        ><label= <true-valueif <conditionels e <false-value>
        >>
        >
        I've seen the PERL saying/motto/boast, "There's more than one way to do it"
        derided on more than one occasion on this group so what's the reason for
        this additional way to put an if else statement on one line? Are "and" and
        "or" constructions to produce the same effect not supported for this use?
        >
        The "and" and "or" construct which is equivalent to the ternary operator
        is quite convoluted and looks nothing like a conditional computation:
        (C and [A] or [B])[0]
        This is inefficient, and nearly unreadable, which makes the highly
        useful ternary operator worthy of a syntactical construct.


        The [A], [B] and [0] parts are absolutely necessary in the general case
        where A can have values that Python would consider equivalent to False.
        If you know A will never be equivalent to False then you can use just this:
        C and A or B

        Gary Herron

        And while I'm on my high horse, I'd like to bring up list concatenations. I
        recently needed to concatenate 5 lists, which doesn't sound a particularly
        rare requirement to me. My first attempt was a straightforward loop
        extending an empty list. That worked fine but looked like an awful bulky
        solution. Afterwards I tried various formulae using "reduce" , falling foul
        of the "=" catch on one occasion. Now I'm not a professional programmer, so
        there may be good reasons for a single object to have multiple names in a
        program, but it sounds like a recipe for disaster to me. Getting back to the
        list concatenation, I finally found the itertools.chain command which is the
        most compact and fastest (or second fastest by a trivial amount, I can't
        remember which). Along the way, I must have tried/used half a dozen methods,
        ...which brings me back my initial PERL comment. There's more than one way
        to do it in Python, too.
        >
        DaveM
        --

        >

        Comment

        • Diez B. Roggisch

          #5
          Re: Rant (was Re: x*x if x&gt;10

          Marc 'BlackJack' Rintsch schrieb:
          On Sun, 27 Jul 2008 16:41:19 +0200, Diez B. Roggisch wrote:
          >
          >DaveM schrieb:
          >>Getting back to the
          >>list concatenation, I finally found the itertools.chain command which
          >>is the most compact and fastest (or second fastest by a trivial amount,
          >>I can't remember which). Along the way, I must have tried/used half a
          >>dozen methods, ...which brings me back my initial PERL comment. There's
          >>more than one way to do it in Python, too.
          >Any non-trivial task has that property. I don't know enough perl to have
          >an example ready that shows something that python has only one way of
          >doing and perl has several.
          >>
          >But I *do* know that taking the python zen literally is fruitless.
          >
          I think it should be taken more literally than the wrong reduction to
          "there should be only one way". People tend to forget "obvious" and
          "preferably " all the time.
          Good point. The OP found the obvious way of extending. I wonder what his
          reasons were to abandon it.


          Diez

          Comment

          • ssecorp

            #6
            Re: Rant (was Re: x*x if x&gt;10

            I might be misunderstandin g OP but:

            a+b+c+d+e is simple way of concatenating 5 lists...

            as a function that takes any amount of lists and concatenates them:
            def concat(*args):
            c = []
            for elem in args:
            c += elem
            return c

            don't know if extend is faster or slower or the same as + :

            def concat(*args):
            c = []
            for elem in args:
            c.extend(elem)
            return c

            I don't know of a built-in.

            Comment

            • alex23

              #7
              Re: Rant (was Re: x*x if x&gt;10

              On Jul 28, 1:26 am, ssecorp <circularf...@g mail.comwrote:
              I might be misunderstandin g OP but:
              >
              a+b+c+d+e is simple way of concatenating 5 lists...
              >
              as a function that takes any amount of lists and concatenates them:
              def concat(*args):
              c = []
              for elem in args:
              c += elem
              return c
              >
              don't know if extend is faster or slower or the same as + :
              >
              def concat(*args):
              c = []
              for elem in args:
              c.extend(elem)
              return c
              >
              I don't know of a built-in.
              Just to infuriate the OP even further, here's the list comprehension
              version :)
              >>def concat(*args):
              .... return [elem for arg in args for elem in arg]

              Hope this helps!

              Comment

              • DaveM

                #8
                Re: Rant (was Re: x*x if x&gt;10

                On Sun, 27 Jul 2008 16:57:14 +0200, "Diez B. Roggisch" <deets@nospam.w eb.de>
                wrote:
                >Marc 'BlackJack' Rintsch schrieb:
                >On Sun, 27 Jul 2008 16:41:19 +0200, Diez B. Roggisch wrote:
                >>
                >>DaveM schrieb:
                >>>Getting back to the list concatenation, I finally found the itertools.chain
                >>>command which is the most compact and fastest (or second fastest by a
                >>>trivial amount, I can't remember which). Along the way, I must have
                >>>tried/used half a dozen methods, ...which brings me back my initial PERL
                >>>comment. There's more than one way to do it in Python, too.
                >>But I *do* know that taking the python zen literally is fruitless.
                >I think it should be taken more literally than the wrong reduction to
                >"there should be only one way". People tend to forget "obvious" and
                >"preferably " all the time.
                >Good point. The OP found the obvious way of extending. I wonder what his
                >reasons were to abandon it.
                You'll have guessed, I'm sure, that I'm not a professional programmer. This
                was the third rewrite of a program to match candidate groups to examiners on
                a three day course I run, necessitated on this occasion by a change in the
                structure of the course. I originally learnt python as I wrote, and some of
                the early code was ugly and verbose, so once the current rewrite was working
                I took the opportunity to tidy the code up and document it (yes, I know, but
                as I said, I'm an amateur). The list concatenation was an itch I couldn't
                scratch:

                temp = []
                for value in sessexam.values ():
                temp.extend(val ue)
                c_exam = [name for name in set(temp)] #See what I mean about verbose?
                c_exam.sort()
                return c_exam

                Six lines just didn't feel like it ought to be the best way to do something
                so simple. I liked the attempt below better, but was foolish enough to time
                it, so that was the end of that.

                return sorted(list(set (reduce(lambda x, y: x+y, sessexam.values ()))))

                The current version (below) is a compromise, but I still feel there _ought_
                to be a simple one word command to join multiple lists.

                a = list(set(iterto ols.chain(*sess exam.values())) )
                a.sort() #As I write I'm wondering if I really need it sorted. Hmm...
                return a

                DaveM

                Comment

                • Gary Herron

                  #9
                  Re: Rant (was Re: x*x if x&gt;10

                  DaveM wrote:
                  On Sun, 27 Jul 2008 16:57:14 +0200, "Diez B. Roggisch" <deets@nospam.w eb.de>
                  wrote:
                  >
                  >
                  >Marc 'BlackJack' Rintsch schrieb:
                  >>
                  >>On Sun, 27 Jul 2008 16:41:19 +0200, Diez B. Roggisch wrote:
                  >>>
                  >>>
                  >>>DaveM schrieb:
                  >>>>
                  >>>>Getting back to the list concatenation, I finally found the itertools.chain
                  >>>>command which is the most compact and fastest (or second fastest by a
                  >>>>trivial amount, I can't remember which). Along the way, I must have
                  >>>>tried/used half a dozen methods, ...which brings me back my initial PERL
                  >>>>comment. There's more than one way to do it in Python, too.
                  >>>>>
                  >
                  >
                  >>>But I *do* know that taking the python zen literally is fruitless.
                  >>>>
                  >
                  >
                  >>I think it should be taken more literally than the wrong reduction to
                  >>"there should be only one way". People tend to forget "obvious" and
                  >>"preferably " all the time.
                  >>>
                  >
                  >
                  >Good point. The OP found the obvious way of extending. I wonder what his
                  >reasons were to abandon it.
                  >>
                  >
                  You'll have guessed, I'm sure, that I'm not a professional programmer. This
                  was the third rewrite of a program to match candidate groups to examiners on
                  a three day course I run, necessitated on this occasion by a change in the
                  structure of the course. I originally learnt python as I wrote, and some of
                  the early code was ugly and verbose, so once the current rewrite was working
                  I took the opportunity to tidy the code up and document it (yes, I know, but
                  as I said, I'm an amateur). The list concatenation was an itch I couldn't
                  scratch:
                  >
                  temp = []
                  for value in sessexam.values ():
                  temp.extend(val ue)
                  c_exam = [name for name in set(temp)] #See what I mean about verbose?
                  c_exam.sort()
                  return c_exam
                  >
                  Six lines just didn't feel like it ought to be the best way to do something
                  so simple. I liked the attempt below better, but was foolish enough to time
                  it, so that was the end of that.
                  >
                  return sorted(list(set (reduce(lambda x, y: x+y, sessexam.values ()))))
                  >
                  The current version (below) is a compromise, but I still feel there _ought_
                  to be a simple one word command to join multiple lists.
                  >
                  a = list(set(iterto ols.chain(*sess exam.values())) )
                  a.sort() #As I write I'm wondering if I really need it sorted. Hmm...
                  return a
                  >
                  Didn't someone already answer that. List addition and sum() both do
                  what you want.
                  >>A = [1,2,3]
                  >>B = [4,5,6]
                  >>C = [7,8,9]
                  >>A+B+C
                  [1, 2, 3, 4, 5, 6, 7, 8, 9]
                  >>sum([A,B,C], [])
                  [1, 2, 3, 4, 5, 6, 7, 8, 9]

                  It doesn't get any easier than that.

                  Gary Herron


                  Comment

                  • Diez B. Roggisch

                    #10
                    Re: Rant (was Re: x*x if x&gt;10

                    DaveM schrieb:
                    On Sun, 27 Jul 2008 16:57:14 +0200, "Diez B. Roggisch" <deets@nospam.w eb.de>
                    wrote:
                    >
                    >Marc 'BlackJack' Rintsch schrieb:
                    >>On Sun, 27 Jul 2008 16:41:19 +0200, Diez B. Roggisch wrote:
                    >>>
                    >>>DaveM schrieb:
                    >>>>Getting back to the list concatenation, I finally found the itertools.chain
                    >>>>command which is the most compact and fastest (or second fastest by a
                    >>>>trivial amount, I can't remember which). Along the way, I must have
                    >>>>tried/used half a dozen methods, ...which brings me back my initial PERL
                    >>>>comment. There's more than one way to do it in Python, too.
                    >
                    >>>But I *do* know that taking the python zen literally is fruitless.
                    >
                    >>I think it should be taken more literally than the wrong reduction to
                    >>"there should be only one way". People tend to forget "obvious" and
                    >>"preferably " all the time.
                    >
                    >Good point. The OP found the obvious way of extending. I wonder what his
                    >reasons were to abandon it.
                    >
                    You'll have guessed, I'm sure, that I'm not a professional programmer. This
                    was the third rewrite of a program to match candidate groups to examiners on
                    a three day course I run, necessitated on this occasion by a change in the
                    structure of the course. I originally learnt python as I wrote, and some of
                    the early code was ugly and verbose, so once the current rewrite was working
                    I took the opportunity to tidy the code up and document it (yes, I know, but
                    as I said, I'm an amateur). The list concatenation was an itch I couldn't
                    scratch:
                    >
                    temp = []
                    for value in sessexam.values ():
                    temp.extend(val ue)
                    c_exam = [name for name in set(temp)] #See what I mean about verbose?
                    c_exam.sort()
                    return c_exam
                    >
                    Six lines just didn't feel like it ought to be the best way to do something
                    so simple. I liked the attempt below better, but was foolish enough to time
                    it, so that was the end of that.
                    >
                    return sorted(list(set (reduce(lambda x, y: x+y, sessexam.values ()))))
                    >
                    The current version (below) is a compromise, but I still feel there _ought_
                    to be a simple one word command to join multiple lists.
                    >
                    a = list(set(iterto ols.chain(*sess exam.values())) )
                    a.sort() #As I write I'm wondering if I really need it sorted. Hmm...
                    return a
                    You are aware that the above is much more than "concatenat e a bunch of
                    lists?" You want unique values & sorting, which are two additional
                    requirements. I'd say 3 lines of code for three requirements is ok, so

                    all = sum(sessexam.va lues(), [])
                    unique = set(all)
                    sorted_result = sorted(unique)

                    And obviously there are more ways to skin *that* cat, some (as
                    itertools.chain ) being less memory intensive:


                    a = sorted(set(iter tools.chain(*se ssexam.values() )))

                    It's debatable if this one-liner is really the way to go, but I fail to
                    see how you expect there to be a specialized builtin for this kind of task.


                    Diez

                    Comment

                    • DaveM

                      #11
                      Re: Rant (was Re: x*x if x&gt;10

                      On Sun, 27 Jul 2008 16:41:19 +0200, "Diez B. Roggisch" <deets@nospam.w eb.de>
                      wrote:

                      >You obviously aren't aware of the pitfalls regarding the mis-use of or
                      >and and for this usage.
                      <snip example>

                      Well, yes, I am (and the way around the problem), but as its never caught me
                      out (so far), I hadn't considered it.
                      >Can you tell us what you mean by "several names of one object"? You mean
                      >this?
                      >
                      >a = range(10)
                      >b = a
                      >
                      >id(a) == id(b)
                      >
                      >
                      >? Passing references instead of values is an extremely important concept
                      >of many languages, without it you would end up copying most of the time.
                      OK. I've obviously been thinking about things the wrong way. In Forth you
                      pass the memory address around, and presumably that's essentially what's
                      happening when you pass a reference. The problem is, I get caught frequently
                      in this situation:

                      a = [1,2,3]

                      def foo(x):
                      do_something_wi th_x
                      return x

                      ....

                      Then when I call foo(a), a gets changed. It just isn't the effect I expect
                      from changing a local.

                      DaveM

                      Comment

                      • Diez B. Roggisch

                        #12
                        Re: Rant (was Re: x*x if x&gt;10

                        >
                        >Can you tell us what you mean by "several names of one object"? You mean
                        >this?
                        >>
                        >a = range(10)
                        >b = a
                        >>
                        >id(a) == id(b)
                        >>
                        >>
                        >? Passing references instead of values is an extremely important concept
                        >of many languages, without it you would end up copying most of the time.
                        >
                        OK. I've obviously been thinking about things the wrong way. In Forth you
                        pass the memory address around, and presumably that's essentially what's
                        happening when you pass a reference.
                        Pretty much, yes. And I for once can say that I've been caught by
                        modifying e.g. stack-locals instead of heap-objects in C++ by accident.

                        The problem is, I get caught frequently
                        in this situation:
                        >
                        a = [1,2,3]
                        >
                        def foo(x):
                        do_something_wi th_x
                        return x
                        >
                        ...
                        >
                        Then when I call foo(a), a gets changed. It just isn't the effect I expect
                        from changing a local.
                        It's the way things work - mutables are mutables. If you want them to be
                        modified, use the module copy.

                        As a rule of thumb, don't return objects you didn't create inside a
                        function from scratch.

                        Which is the exact reasoning for the

                        list.sort

                        method btw - returning None is supposed to make you aware of the
                        in-place modification.




                        Diez

                        Comment

                        • Terry Reedy

                          #13
                          Re: Rant (was Re: x*x if x&gt;10

                          DaveM wrote:
                          On Sun, 27 Jul 2008 16:57:14 +0200, "Diez B. Roggisch" <deets@nospam.w eb.de>
                          You'll have guessed, I'm sure, that I'm not a professional programmer. This
                          was the third rewrite of a program to match candidate groups to examiners on
                          a three day course I run, necessitated on this occasion by a change in the
                          structure of the course. I originally learnt python as I wrote, and some of
                          the early code was ugly and verbose, so once the current rewrite was working
                          I took the opportunity to tidy the code up and document it (yes, I know, but
                          as I said, I'm an amateur). The list concatenation was an itch I couldn't
                          scratch:
                          >
                          temp = []
                          for value in sessexam.values ():
                          temp.extend(val ue)
                          c_exam = [name for name in set(temp)] #See what I mean about verbose?
                          c_exam.sort()
                          return c_exam
                          >
                          Six lines just didn't feel like it ought to be the best way to do something
                          so simple. I liked the attempt below better, but was foolish enough to time
                          it, so that was the end of that.
                          >
                          return sorted(list(set (reduce(lambda x, y: x+y, sessexam.values ()))))
                          >
                          The current version (below) is a compromise, but I still feel there _ought_
                          to be a simple one word command to join multiple lists.
                          There is, as others have posted, but if you are going to dump the lists
                          into a set, there is no need to concatenate them together first, and it
                          is better not to. Just dump them directly into set.
                          >
                          a = list(set(iterto ols.chain(*sess exam.values())) )
                          This is a pretty good way of skipping the intermediate long list. Another:

                          a = set()
                          for l in sessexam.values ():
                          a.update(set(l) )

                          If course, if sessexam.values () does not need to be ordered and returns
                          sets instead, the set call in not needed.
                          a.sort() #As I write I'm wondering if I really need it sorted. Hmm...
                          return a
                          If you want all in one line...
                          return sorted(set(iter tools.chain(*se ssexam.values() )))

                          There is no virtue to calling list then .sort, since that is what sorted
                          basically does.

                          def sorted(iterable ):
                          tem = list(iterable)
                          tem.sort()
                          return tem

                          tjr


                          tjr

                          Comment

                          • Anders J. Munch

                            #14
                            Re: Rant (was Re: x*x if x&gt;10

                            Gary Herron wrote:
                            >>A = [1,2,3]
                            >>B = [4,5,6]
                            >>C = [7,8,9]
                            >
                            >>A+B+C
                            [1, 2, 3, 4, 5, 6, 7, 8, 9]
                            >
                            >>sum([A,B,C], [])
                            [1, 2, 3, 4, 5, 6, 7, 8, 9]
                            Careful now, this can be very slow. sum uses __add__, not __iadd__, which gives
                            this approach quadratic worst-case runtime.

                            - Anders

                            Comment

                            • DaveM

                              #15
                              Re: Rant (was Re: x*x if x&gt;10

                              On Sun, 27 Jul 2008 09:28:28 -0700, Gary Herron <gherron@island training.com>
                              wrote:

                              > a = list(set(iterto ols.chain(*sess exam.values())) )
                              > a.sort() #As I write I'm wondering if I really need it sorted. Hmm...
                              > return a
                              >Didn't someone already answer that. List addition and sum() both do
                              >what you want.
                              >
                              >A = [1,2,3]
                              >B = [4,5,6]
                              >C = [7,8,9]
                              >
                              >A+B+C
                              >[1, 2, 3, 4, 5, 6, 7, 8, 9]
                              True, although unsuitable for my circumstance.

                              >sum([A,B,C], [])
                              >[1, 2, 3, 4, 5, 6, 7, 8, 9]
                              Ah. I had no luck with sum, but I hadn't realised it needed the "[]" term. I
                              must read about it again.
                              >It doesn't get any easier than that.
                              Not only that, but it's exactly what I was after - and fastest, too,
                              although speed isn't really an issue. Thank you.

                              DaveM

                              Comment

                              Working...