enumerate improvement proposal

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

    #1

    enumerate improvement proposal

    I think that it would be handy for enumerate to behave as such:

    def enumerate(itrbl , start=0, step=1):
    i = start
    for it in itrbl:
    yield (i, it)
    i += step

    This allows much more flexibility than in the current enumerate,
    tightens up code in many cases, and seems that it would break no
    existing code. Yes, I have needed this behavior with enumerate, like
    tonight and the current example. I put the "step" parameter in for
    conceptual symmetry with slicing.

    Here is a case use (or is it use case?):


    # with the proposed enumerate
    import operator
    def in_interval(tes t, bounds, first=1, reverse=False):
    op = operator.gt if reverse else operator.lt # python 2.5
    bounds = sorted(bounds, reverse=reverse )
    for i, bound in enumerate(bound s, first):
    if op(test, bound):
    return i
    return i + 1


    # with the existing enumerate
    import operator
    def in_interval(tes t, bounds, first=1, reverse=False):
    op = operator.gt if reverse else operator.lt # python 2.5
    bounds = sorted(bounds, reverse=reverse )
    for i, bound in enumerate(bound s):
    if op(test, bound):
    return i + first
    return i + first + 1


    py# eg
    ....
    pyin_interval(8 , bounds)
    2
    pyin_interval(1 , bounds)
    1
    pyin_interval(1 , bounds, reverse=True)
    5
    pyin_interval(8 , bounds, reverse=True)
    4
    pyin_interval(2 0, bounds, reverse=True)
    2

    Of course, I haven't used step here. Even in this trivial example the
    proposed enumerate cleans the code and logic, eliminating a couple of
    plus signs. For this real-world example, the practical requirement for
    reversing the bins obfuscates somewhat the de-obfuscation provided by
    the proposed enumerate. But I think that it might be obvious that the
    proposed enumerate could help significantly in cases a bit more
    complicated than this one.

    Any thoughts?

    James
  • James Stroud

    #2
    Re: enumerate improvement proposal

    James Stroud wrote:
    I think that it would be handy for enumerate to behave as such:
    >
    def enumerate(itrbl , start=0, step=1):
    i = start
    for it in itrbl:
    yield (i, it)
    i += step
    >
    This allows much more flexibility than in the current enumerate,
    tightens up code in many cases, and seems that it would break no
    existing code. Yes, I have needed this behavior with enumerate, like
    tonight and the current example. I put the "step" parameter in for
    conceptual symmetry with slicing.
    >
    Here is a case use (or is it use case?):
    >
    >
    # with the proposed enumerate
    import operator
    def in_interval(tes t, bounds, first=1, reverse=False):
    op = operator.gt if reverse else operator.lt # python 2.5
    bounds = sorted(bounds, reverse=reverse )
    for i, bound in enumerate(bound s, first):
    if op(test, bound):
    return i
    return i + 1
    >
    >
    # with the existing enumerate
    import operator
    def in_interval(tes t, bounds, first=1, reverse=False):
    op = operator.gt if reverse else operator.lt # python 2.5
    bounds = sorted(bounds, reverse=reverse )
    for i, bound in enumerate(bound s):
    if op(test, bound):
    return i + first
    return i + first + 1
    >
    >
    py# eg
    ...
    pyin_interval(8 , bounds)
    2
    pyin_interval(1 , bounds)
    1
    pyin_interval(1 , bounds, reverse=True)
    5
    pyin_interval(8 , bounds, reverse=True)
    4
    pyin_interval(2 0, bounds, reverse=True)
    2
    >
    Of course, I haven't used step here. Even in this trivial example the
    proposed enumerate cleans the code and logic, eliminating a couple of
    plus signs. For this real-world example, the practical requirement for
    reversing the bins obfuscates somewhat the de-obfuscation provided by
    the proposed enumerate. But I think that it might be obvious that the
    proposed enumerate could help significantly in cases a bit more
    complicated than this one.
    >
    Any thoughts?
    >
    James
    After a brief reflection, I realized that I just described a
    "for-to-step-do" style loop one might find in many other languages, most
    notably BASIC.

    James

    Comment

    • Fredrik Lundh

      #3
      Re: enumerate improvement proposal

      James Stroud wrote:
      def enumerate(itrbl , start=0, step=1):
      i = start
      for it in itrbl:
      yield (i, it)
      i += step
      that's spelled

      izip(count(star t), sequence)

      in today's Python.
      def in_interval(tes t, bounds, first=1, reverse=False):
      why is it this function's job to add an offset to the actual sequence index?

      </F>

      Comment

      • James Stroud

        #4
        Re: enumerate improvement proposal

        Fredrik Lundh wrote:
        why is it this function's job to add an offset to the actual sequence
        index?
        >
        </F>
        The code is for an economist. She is insistent on starting with the
        first bin as 1. I'm guessing, practically, binning linerizes data and
        the bin number may potentially become a divisor or perhaps the operand
        in a logarithm.

        James

        Comment

        • James Stroud

          #5
          Re: enumerate improvement proposal

          Fredrik Lundh wrote:
          James Stroud wrote:
          >
          >def enumerate(itrbl , start=0, step=1):
          > i = start
          > for it in itrbl:
          > yield (i, it)
          > i += step
          >
          that's spelled
          >
          izip(count(star t), sequence)
          >
          in today's Python.
          >
          def in_interval(tes t, bounds, first=1, reverse=False):
          >
          why is it this function's job to add an offset to the actual sequence
          index?
          >
          </F>
          >
          BTW, thank you for your tip.

          James

          Comment

          • Fredrik Lundh

            #6
            Re: enumerate improvement proposal

            James Stroud wrote:
            The code is for an economist. She is insistent on starting with the
            first bin as 1.
            leaky abstractions in reverse, in other words? that's not a good design
            approach.

            </F>

            Comment

            • James Stroud

              #7
              Re: enumerate improvement proposal

              Fredrik Lundh wrote:
              James Stroud wrote:
              >
              >The code is for an economist. She is insistent on starting with the
              >first bin as 1.
              >
              leaky abstractions in reverse, in other words? that's not a good design
              approach.
              >
              </F>
              >
              I'm not sure I understand what "leaky abstractions" means.

              I am helping someone with dubious programming skills make sense of a
              pile of code they wrote--code which getting a little unwieldy to debug.
              I think "design approach" can't really apply here. The idea is to make
              it comprehensible at some level.

              I'm still curious what you mean by "leaky abstractions". Please explain.

              James

              Comment

              • Peter Otten

                #8
                Re: enumerate improvement proposal

                James Stroud wrote:
                I think that it would be handy for enumerate to behave as such:
                >
                def enumerate(itrbl , start=0, step=1):
                i = start
                for it in itrbl:
                yield (i, it)
                i += step
                >
                This allows much more flexibility than in the current enumerate,
                tightens up code in many cases, and seems that it would break no
                existing code. Yes, I have needed this behavior with enumerate, like
                tonight and the current example. I put the "step" parameter in for
                conceptual symmetry with slicing.
                >
                Here is a case use (or is it use case?):
                I don' think you have a use case here:

                # untested
                def find_interval(v alue, bounds, funny_offset=0, reverse=False):
                bounds = sorted(bounds)
                if reverse:
                index = len(bounds) - bisect.bisect_l eft(bounds, value)
                else:
                index = bisect.bisect_r ight(bounds, value)
                return index + funny_offset

                You can tell by its name which of the arguments I would have omitted :-)
                Of course, I haven't used step here.
                That seems to be typical. The only use case I've ever come across is start=1
                for output aimed at a human reader.
                Even in this trivial example the
                proposed enumerate cleans the code and logic, eliminating a couple of
                plus signs. For this real-world example, the practical requirement for
                reversing the bins obfuscates somewhat the de-obfuscation provided by
                the proposed enumerate. But I think that it might be obvious that the
                proposed enumerate could help significantly in cases a bit more
                complicated than this one.
                Of course you get these claimed advantages from a self-written function,
                too.
                Any thoughts?
                You have my support for adding a start parameter to enumerate(). I fear it
                won't make a difference.

                Peter

                Comment

                • Georg Brandl

                  #9
                  Re: enumerate improvement proposal

                  James Stroud wrote:
                  I think that it would be handy for enumerate to behave as such:
                  >
                  def enumerate(itrbl , start=0, step=1):
                  i = start
                  for it in itrbl:
                  yield (i, it)
                  i += step
                  >
                  This allows much more flexibility than in the current enumerate,
                  tightens up code in many cases, and seems that it would break no
                  existing code. Yes, I have needed this behavior with enumerate, like
                  tonight and the current example. I put the "step" parameter in for
                  conceptual symmetry with slicing.
                  >
                  Here is a case use (or is it use case?):
                  Incidentally, I yesterday wrote a patch giving enumerate() a start parameter
                  (and, more importantly, changing it so that it doesn't wraparound at
                  sys.maxint). It can be found here:

                  https://sourceforge.net/tracker/?fun...&group_id=5470

                  Georg

                  Comment

                  • Ben Finney

                    #10
                    Re: enumerate improvement proposal

                    James Stroud <jstroud@mbi.uc la.eduwrites:
                    Fredrik Lundh wrote:
                    why is it this function's job to add an offset to the actual
                    sequence index?
                    >
                    The code is for an economist. She is insistent on starting with the
                    first bin as 1.
                    Note that 'enumerate' is actually a built-in type, and 'enumerate()'
                    is the constructor returning a new object of that type.

                    A special case isn't special enough to change the built-in type.
                    >>print enumerate("ABCD E")
                    <enumerate object at 0xa7d642ac>
                    >>print list(enumerate( "ABCDE"))
                    [(0, 'A'), (1, 'B'), (2, 'C'), (3, 'D'), (4, 'E')]
                    >def obstinate_econo mist_enumerate( items):
                    ... seq = [(i+1, x) for (i, x) in enumerate(items )]
                    ... return iter(seq)
                    ...
                    >>print obstinate_econo mist_enumerate( "ABCDE")
                    <listiterator object at 0xa7d6408c>
                    >>print list(obstinate_ economist_enume rate("ABCDE"))
                    [(1, 'A'), (2, 'B'), (3, 'C'), (4, 'D'), (5, 'E')]

                    This doesn't produce an 'enumerate' object; if you really want that,
                    you could subclass 'enumerate', but it seems the above function does
                    what you want.

                    --
                    \ "I installed a skylight in my apartment. The people who live |
                    `\ above me are furious!" -- Steven Wright |
                    _o__) |
                    Ben Finney

                    Comment

                    • Ben Finney

                      #11
                      Re: enumerate improvement proposal

                      Ben Finney <bignose+hate s-spam@benfinney. id.auwrites:
                      >>print enumerate("ABCD E")
                      <enumerate object at 0xa7d642ac>
                      >>print list(enumerate( "ABCDE"))
                      [(0, 'A'), (1, 'B'), (2, 'C'), (3, 'D'), (4, 'E')]
                      >
                      >def obstinate_econo mist_enumerate( items):
                      ... seq = [(i+1, x) for (i, x) in enumerate(items )]
                      ... return iter(seq)
                      ...
                      >>print obstinate_econo mist_enumerate( "ABCDE")
                      <listiterator object at 0xa7d6408c>
                      >>print list(obstinate_ economist_enume rate("ABCDE"))
                      [(1, 'A'), (2, 'B'), (3, 'C'), (4, 'D'), (5, 'E')]
                      An improvement: using a generator so as not to unnecessarily create an
                      intermediate list from the initial enumerator:
                      >>def obstinate_econo mist_enumerate( items):
                      ... enum_iter = iter((i+1, x) for (i, x) in enumerate(items ))
                      ... return enum_iter
                      ...
                      >>print obstinate_econo mist_enumerate( "ABCDE")
                      <generator object at 0xa7d6444c>
                      >>print list(obstinate_ economist_enume rate("ABCDE"))
                      [(1, 'A'), (2, 'B'), (3, 'C'), (4, 'D'), (5, 'E')]

                      --
                      \ "If sharing a thing in no way diminishes it, it is not rightly |
                      `\ owned if it is not shared." -- Saint Augustine |
                      _o__) |
                      Ben Finney

                      Comment

                      • James Stroud

                        #12
                        Re: enumerate improvement proposal

                        Fredrik Lundh wrote:
                        James Stroud wrote:
                        >
                        >The code is for an economist. She is insistent on starting with the
                        >first bin as 1.
                        >
                        >
                        leaky abstractions in reverse, in other words? that's not a good design
                        approach.
                        >
                        </F>
                        >
                        Okay, I've googled "leaky abstractions" (as was probably your intended
                        affect with your silence), read the famous essay, and still
                        don't know what you mean and how it applies to what I have described.

                        Do you plan to justify your statement or emptily accuse people of violating
                        esoteric principles?

                        James

                        --
                        James Stroud
                        UCLA-DOE Institute for Genomics and Proteomics
                        Box 951570
                        Los Angeles, CA 90095


                        Comment

                        • Anders J. Munch

                          #13
                          Re: enumerate improvement proposal

                          Ben Finney wrote:
                          >
                          >>def obstinate_econo mist_enumerate( items):
                          ... enum_iter = iter((i+1, x) for (i, x) in enumerate(items ))
                          ... return enum_iter
                          iter is redundant here.

                          def natural_enumera te_improvement( items, start=0):
                          return ((i+start, x) for (i, x) in enumerate(items ))

                          - Anders

                          Comment

                          • Diez B. Roggisch

                            #14
                            Re: enumerate improvement proposal

                            Okay, I've googled "leaky abstractions" (as was probably your intended
                            affect with your silence), read the famous essay, and still
                            don't know what you mean and how it applies to what I have described.
                            >
                            Do you plan to justify your statement or emptily accuse people of violating
                            esoteric principles?
                            While I can't claim to know what the effbot thinks (the
                            skull-socks-wearing-python-coder-mindlink-technology is yet to be
                            developed), I think it's pretty clear what he is after here:

                            Computers compute offsets into data zero-based. Some languages like
                            pascal completely abstract that away from the user, but python doesn't.

                            So if your colleague/boss/whatever insists on indices being one-based,
                            this abstraction you introduced for her pretty fast leaks pretty badly.
                            Consider this simple example:

                            for offset, item in enumerate(some_ list, start=1):
                            if item.is_the_cho sen_one():
                            chosen_one_offs et = offset

                            the_chosen_one = some_list[chosen_one_offs et]

                            And bang, its Judas not Petrus who gets the pearly gates inc. stock options.

                            Diez

                            Comment

                            • James Stroud

                              #15
                              Re: enumerate improvement proposal

                              Diez B. Roggisch wrote:
                              >Okay, I've googled "leaky abstractions" (as was probably your intended
                              >affect with your silence), read the famous essay, and still
                              >don't know what you mean and how it applies to what I have described.
                              >>
                              >Do you plan to justify your statement or emptily accuse people of
                              >violating
                              >esoteric principles?
                              >
                              >
                              While I can't claim to know what the effbot thinks (the
                              skull-socks-wearing-python-coder-mindlink-technology is yet to be
                              developed), I think it's pretty clear what he is after here:
                              >
                              Computers compute offsets into data zero-based. Some languages like
                              pascal completely abstract that away from the user, but python doesn't.
                              >
                              So if your colleague/boss/whatever insists on indices being one-based,
                              this abstraction you introduced for her pretty fast leaks pretty badly.
                              Consider this simple example:
                              >
                              for offset, item in enumerate(some_ list, start=1):
                              if item.is_the_cho sen_one():
                              chosen_one_offs et = offset
                              >
                              the_chosen_one = some_list[chosen_one_offs et]
                              >
                              And bang, its Judas not Petrus who gets the pearly gates inc. stock
                              options.
                              >
                              Diez
                              Thank you for this explanation. Very illuminating. I think understand
                              this idea well and the thought of 1 basing this function makes me cringe
                              as much as the next guy (though I lacked the vocabulary to explain
                              exactly why I cringe).

                              But you see, weaning this university faculty level economist (who
                              already has her own way of doing everything...an d to whom I happen to be
                              married) from the traditional economics tools of gauss and sas towards
                              the more sane and flexible tools of python, numarray, and rpy has been a
                              multi-stage process. Tweaking the chosen abstractions to not be as leaky
                              (thank you and thank Fredrik for introducing me to this vocabulary) is
                              still one of the things I'm working towards. I want to solidify the
                              conversion before I concentrate on nuance.

                              So, before too much criticism, I challenge even the most skilled python
                              programmer to find his or her own faculty economist (or statistician or
                              physicist) and get them to radically change their computational tools.
                              When you've walked a mile in my shoes, leaky abstractions won't seem
                              like such a big deal after all.

                              James

                              --
                              James Stroud
                              UCLA-DOE Institute for Genomics and Proteomics
                              Box 951570
                              Los Angeles, CA 90095


                              Comment

                              Working...