Correct way to detect sequence parameter?

后端 未结 12 1469
情书的邮戳
情书的邮戳 2020-11-28 13:48

I want to write a function that accepts a parameter which can be either a sequence or a single value. The type of value is str, int, etc., but I don\'t want

相关标签:
12条回答
  • 2020-11-28 14:09

    Revised answer:

    I don't know if your idea of "sequence" matches what the Python manuals call a "Sequence Type", but in case it does, you should look for the __Contains__ method. That is the method Python uses to implement the check "if something in object:"

    if hasattr(X, '__contains__'):
        print "X is a sequence"
    

    My original answer:

    I would check if the object that you received implements an iterator interface:

    if hasattr(X, '__iter__'):
        print "X is a sequence"
    

    For me, that's the closest match to your definition of sequence since that would allow you to do something like:

    for each in X:
        print each
    
    0 讨论(0)
  • 2020-11-28 14:10

    Sequences are described here: https://docs.python.org/2/library/stdtypes.html#sequence-types-str-unicode-list-tuple-bytearray-buffer-xrange

    So sequences are not the same as iterable objects. I think sequence must implement __getitem__, whereas iterable objects must implement __iter__. So for example string are sequences and don't implement __iter__, xrange objects are sequences and don't implement __getslice__.

    But from what you seen to want to do, I'm not sure you want sequences, but rather iterable objects. So go for hasattr("__getitem__", X) you want sequences, but go rather hasattr("__iter__", X) if you don't want strings for example.

    0 讨论(0)
  • 2020-11-28 14:11

    If strings are the problem, detect a sequence and filter out the special case of strings:

    def is_iterable(x):
      if type(x) == str:
        return False
      try:
        iter(x)
        return True
      except TypeError:
        return False
    
    0 讨论(0)
  • 2020-11-28 14:13

    IMHO, the python way is to pass the list as *list. As in:

    myfunc(item)
    myfunc(*items)
    
    0 讨论(0)
  • 2020-11-28 14:13

    The simplest method would be to check if you can turn it into an iterator. ie

    try:
        it = iter(X)
        # Iterable
    except TypeError:
        # Not iterable
    

    If you need to ensure that it's a restartable or random access sequence (ie not a generator etc), this approach won't be sufficient however.

    As others have noted, strings are also iterable, so if you need so exclude them (particularly important if recursing through items, as list(iter('a')) gives ['a'] again, then you may need to specifically exclude them with:

     if not isinstance(X, basestring)
    
    0 讨论(0)
  • 2020-11-28 14:18

    You could pass your parameter in the built-in len() function and check whether this causes an error. As others said, the string type requires special handling.

    According to the documentation the len function can accept a sequence (string, list, tuple) or a dictionary.

    You could check that an object is a string with the following code:

    x.__class__ == "".__class__
    
    0 讨论(0)
提交回复
热议问题