is parameter an iterable?

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

    #1

    is parameter an iterable?

    I have function which takes an argument. My code needs that argument
    to be an iterable (something i can loop over)...so I dont care if its a
    list, tuple, etc. So I need a way to make sure that the argument is an
    iterable before using it. I know I could do...

    def foo(inputVal):
    if isinstance(inpu tVal, (list, tuple)):
    for val in inputVal:
    # do stuff

    ....however I want to cover any iterable since i just need to loop over
    it.

    any suggestions?

  • Dan Sommers

    #2
    Re: is parameter an iterable?

    On 15 Nov 2005 11:01:48 -0800,
    "py" <codecraig@gmai l.com> wrote:
    [color=blue]
    > I have function which takes an argument. My code needs that argument
    > to be an iterable (something i can loop over)...so I dont care if its a
    > list, tuple, etc. So I need a way to make sure that the argument is an
    > iterable before using it. I know I could do...[/color]
    [color=blue]
    > def foo(inputVal):
    > if isinstance(inpu tVal, (list, tuple)):
    > for val in inputVal:
    > # do stuff[/color]
    [color=blue]
    > ...however I want to cover any iterable since i just need to loop over
    > it.[/color]
    [color=blue]
    > any suggestions?[/color]

    Just do it. If one of foo's callers passes in a non-iterable, foo will
    raise an exception, and you'll catch it during testing. Watch out for
    strings, though:
    [color=blue][color=green][color=darkred]
    >>> def foo(i):[/color][/color][/color]
    ... for j in i:
    ... print j[color=blue][color=green][color=darkred]
    >>> foo([1, 3, 4, 5, 6, 7])[/color][/color][/color]
    1
    3
    4
    5
    6
    7[color=blue][color=green][color=darkred]
    >>> foo("hello")[/color][/color][/color]
    h
    e
    l
    l
    o

    Regards,
    Dan

    --
    Dan Sommers
    <http://www.tombstoneze ro.net/dan/>

    Comment

    • marduk

      #3
      Re: is parameter an iterable?

      On Tue, 2005-11-15 at 11:01 -0800, py wrote:[color=blue]
      > I have function which takes an argument. My code needs that argument
      > to be an iterable (something i can loop over)...so I dont care if its a
      > list, tuple, etc. So I need a way to make sure that the argument is an
      > iterable before using it. I know I could do...
      >
      > def foo(inputVal):
      > if isinstance(inpu tVal, (list, tuple)):
      > for val in inputVal:
      > # do stuff
      >
      > ...however I want to cover any iterable since i just need to loop over
      > it.
      >
      > any suggestions?
      >[/color]

      You could probably get away with

      if hasattr(inputVa l, '__getitem__')


      Comment

      • py

        #4
        Re: is parameter an iterable?

        Dan Sommers wrote:[color=blue]
        > Just do it. If one of foo's callers passes in a non-iterable, foo will
        > raise an exception, and you'll catch it during testing[/color]

        That's exactly what I don't want. I don't want an exception, instead I
        want to check to see if it's an iterable....if it is continue, if not
        return an error code. I can't catch it during testing since this is
        going to be used by other people.

        Thanks for the suggestion though.

        Comment

        • Rocco Moretti

          #5
          Re: is parameter an iterable?

          marduk wrote:[color=blue]
          > On Tue, 2005-11-15 at 11:01 -0800, py wrote:
          >[color=green]
          >>I have function which takes an argument. My code needs that argument
          >>to be an iterable (something i can loop over)...so I dont care if its a
          >>list, tuple, etc. So I need a way to make sure that the argument is an
          >>iterable before using it. I know I could do...
          >>
          >>def foo(inputVal):
          >> if isinstance(inpu tVal, (list, tuple)):
          >> for val in inputVal:
          >> # do stuff
          >>
          >>...however I want to cover any iterable since i just need to loop over
          >>it.
          >>
          >>any suggestions?[/color]
          >
          > You could probably get away with
          >
          > if hasattr(inputVa l, '__getitem__')[/color]

          No, you probably couldn't.

          ############### ###[color=blue][color=green][color=darkred]
          >>> def g(s):[/color][/color][/color]
          for i in xrange(s):
          yield i+s

          [color=blue][color=green][color=darkred]
          >>> m = g(5)
          >>> hasattr(m, '__getitem__')[/color][/color][/color]
          False
          ############### ####

          I'd do something like:

          ############### ######
          def foo(inputVal):
          try:
          iter(inputVal) # Can you change it into an interator?
          except TypeError:
          # Return Error Code
          else:
          for val in inputVal:
          # do stuff
          ############### ########

          Again, you'll have to be careful about strings.

          Comment

          • Robert Kern

            #6
            Re: is parameter an iterable?

            py wrote:[color=blue]
            > Dan Sommers wrote:
            >[color=green]
            >>Just do it. If one of foo's callers passes in a non-iterable, foo will
            >>raise an exception, and you'll catch it during testing[/color]
            >
            > That's exactly what I don't want. I don't want an exception, instead I
            > want to check to see if it's an iterable....if it is continue, if not
            > return an error code.[/color]

            Why return an error code? Just pass along the exception (i.e. do nothing
            special). Python's exception mechanism is far superior to error codes.
            Don't try to fight the language.
            [color=blue]
            > I can't catch it during testing since this is
            > going to be used by other people.[/color]

            Then *they'll* catch it during testing.

            --
            Robert Kern
            rkern@ucsd.edu

            "In the fields of hell where the grass grows high
            Are the graves of dreams allowed to die."
            -- Richard Harter

            Comment

            • py

              #7
              Re: is parameter an iterable?

              Thanks for the replies. I agree with Jean-Paul Calderone's
              suggestion...le t the exception be raised.

              Thanks.

              Comment

              • Carl Friedrich Bolz

                #8
                Re: is parameter an iterable?

                Hi!

                py wrote:[color=blue]
                > Dan Sommers wrote:
                >[color=green]
                >>Just do it. If one of foo's callers passes in a non-iterable, foo will
                >>raise an exception, and you'll catch it during testing[/color]
                >
                >
                > That's exactly what I don't want. I don't want an exception, instead I
                > want to check to see if it's an iterable....if it is continue, if not
                > return an error code. I can't catch it during testing since this is
                > going to be used by other people.[/color]

                Note that using error codes is usually quite "unpythonic ", the way to
                signal that something is exceptional (not necessarily wrong) is, well,
                an exception.

                Anyway, one way to solve this is the following:

                def foo(input_val):
                try:
                iterator = iter(input_val)
                except TypeError:
                # do non-iterable stuff
                else:
                for val in iterator:
                # do loop stuff

                Cheers,

                Carl Friedrich Bolz

                Comment

                • Roy Smith

                  #9
                  Re: is parameter an iterable?

                  In article <1132081308.036 144.13720@g49g2 000cwa.googlegr oups.com>,
                  py <codecraig@gmai l.com> wrote:[color=blue]
                  >I have function which takes an argument. My code needs that argument
                  >to be an iterable (something i can loop over)...so I dont care if its a
                  >list, tuple, etc.[/color]

                  My first thought was to just write your loop inside a try block and
                  catch the error if it wasn't iterable, but then I noticed that you get:

                  TypeError: iteration over non-sequence

                  I was kind of hoping for a more specific exception than TypeError.
                  You can't tell the difference between:

                  try:
                  for i in 5:
                  print i + 1
                  except TypeError:
                  print "non-iterable"

                  and

                  try:
                  for i in ["one", "two", "three"]:
                  print i + 1
                  except TypeError:
                  print "can't add string and integer"

                  Unfortunately, you can't just try it in a bodyless loop to prove that
                  you can iterate before doing the real thing because not all iterators
                  are idempotent.

                  It's an interesting problem.

                  Comment

                  • Grant Edwards

                    #10
                    Re: is parameter an iterable?

                    On 2005-11-15, py <codecraig@gmai l.com> wrote:[color=blue]
                    > Dan Sommers wrote:[color=green]
                    >> Just do it. If one of foo's callers passes in a non-iterable, foo will
                    >> raise an exception, and you'll catch it during testing[/color]
                    >
                    > That's exactly what I don't want. I don't want an exception, instead I
                    > want to check to see if it's an iterable....if it is continue, if not
                    > return an error code. I can't catch it during testing since this is
                    > going to be used by other people.[/color]

                    If I were those other people, and you decided to return error
                    codes to me instead of passing up the proper exception (the
                    good, Pythonic thing to do), I'd be fairly pissed off at you.

                    An exception is the _right_ way to let the caller know
                    something is wrong.

                    --
                    Grant Edwards grante Yow! I smell like a wet
                    at reducing clinic on Columbus
                    visi.com Day!

                    Comment

                    • Dave Hansen

                      #11
                      Re: is parameter an iterable?

                      On 15 Nov 2005 11:26:23 -0800 in comp.lang.pytho n, "py"
                      <codecraig@gmai l.com> wrote:
                      [color=blue]
                      >Dan Sommers wrote:[color=green]
                      >> Just do it. If one of foo's callers passes in a non-iterable, foo will
                      >> raise an exception, and you'll catch it during testing[/color]
                      >
                      >That's exactly what I don't want. I don't want an exception, instead I
                      >want to check to see if it's an iterable....if it is continue, if not
                      >return an error code. I can't catch it during testing since this is
                      >going to be used by other people.[/color]

                      Then catch the exception yourself.
                      [color=blue][color=green][color=darkred]
                      >>> def foo2(i):[/color][/color][/color]
                      try:
                      for j in i:
                      print j
                      print "Success!"
                      return 0
                      except TypeError, e:
                      print "Bad foo. No donut.", e
                      return -1

                      [color=blue][color=green][color=darkred]
                      >>> joe = foo2([1,3,5,7,9])[/color][/color][/color]
                      1
                      3
                      5
                      7
                      9
                      Success![color=blue][color=green][color=darkred]
                      >>> print joe[/color][/color][/color]
                      0[color=blue][color=green][color=darkred]
                      >>> bob = foo2(2)[/color][/color][/color]
                      Bad foo. No donut. iteration over non-sequence[color=blue][color=green][color=darkred]
                      >>> print bob[/color][/color][/color]
                      -1[color=blue][color=green][color=darkred]
                      >>>[/color][/color][/color]

                      Regards,
                      -=Dave

                      --
                      Change is inevitable, progress is not.

                      Comment

                      • lmaycotte@gmail.com

                        #12
                        Re: is parameter an iterable?

                        Maybe this helps:
                        [color=blue][color=green][color=darkred]
                        >>> import types
                        >>> def foo(inputVal):[/color][/color][/color]
                        inValType = type(inputVal)
                        if inValType==type s.ListType or inValType==type s.TupleType:
                        for val in inputVal:
                        print val
                        else:
                        print 'Wrong input Type'

                        [color=blue][color=green][color=darkred]
                        >>> list = [1,2,3,4]
                        >>> foo(list)[/color][/color][/color]
                        1
                        2
                        3
                        4[color=blue][color=green][color=darkred]
                        >>> tup = ('a', 'b', 'c')
                        >>> foo(tup)[/color][/color][/color]
                        a
                        b
                        c[color=blue][color=green][color=darkred]
                        >>> foo(9)[/color][/color][/color]
                        Wrong input Type[color=blue][color=green][color=darkred]
                        >>>[/color][/color][/color]

                        Comment

                        • Steven D'Aprano

                          #13
                          Re: is parameter an iterable?

                          On Tue, 15 Nov 2005 14:06:45 -0500, Dan Sommers wrote:
                          [color=blue]
                          > On 15 Nov 2005 11:01:48 -0800,
                          > "py" <codecraig@gmai l.com> wrote:
                          >[color=green]
                          >> I have function which takes an argument. My code needs that argument
                          >> to be an iterable (something i can loop over)...so I dont care if its a
                          >> list, tuple, etc. So I need a way to make sure that the argument is an
                          >> iterable before using it. I know I could do...[/color][/color]

                          ....
                          [color=blue]
                          > Just do it. If one of foo's callers passes in a non-iterable, foo will
                          > raise an exception, and you'll catch it during testing.[/color]

                          It isn't during testing so much that he needs to watch out, as run-time.
                          You have three options:

                          (1) The "if the user is silly enough to pass a non-iterable to my
                          function, they deserve to have it fail" school of thought. Dan's advise
                          comes under this heading.

                          (2) The "if the user passes a non-iterable, I want to catch the exception
                          and recover gracefully" school of thought. Recovering gracefully may mean
                          raising your own exception, with a user friendly error message ("Hey
                          butthead, pass an iterable willya!!!"), or it may mean just catching the
                          exception and doing something else, depending on the needs of your
                          program. (For example, as a user-friendly feature, you might want to treat
                          ints as if they were iterables of one item only, so users can pass 5 as an
                          argument instead of [5].)

                          For the second case, what you want to do is wrap your code in a
                          try...except block and catch the exception raised when a non-iterator is
                          passed as an argument.

                          Which exception is that? I leave that as an exercise for the reader.
                          (Hint: Just Do It and read the traceback Python prints.)

                          Actually, I think "Just Do It" might make a good motto for Python.


                          --
                          Steven

                          Comment

                          • DonQuixoteVonLaMancha@gmx.net

                            #14
                            Re: is parameter an iterable?

                            How about hasattr("__iter __")?

                            Regards,
                            Karsten.

                            Comment

                            • Ben Finney

                              #15
                              Re: is parameter an iterable?

                              lmaycotte@gmail .com wrote:[color=blue]
                              > Maybe this helps:
                              >[color=green][color=darkred]
                              > >>> import types
                              > >>> def foo(inputVal):[/color][/color]
                              > inValType = type(inputVal)
                              > if inValType==type s.ListType or inValType==type s.TupleType:[/color]

                              And what of user-created types that are iterable?

                              What of user-created iterable types that don't inherit from any of the
                              built-in iterable types?

                              --
                              \ "A good politician is quite as unthinkable as an honest |
                              `\ burglar." -- Henry L. Mencken |
                              _o__) |
                              Ben Finney

                              Comment

                              Working...