列表具有单个值时的Python列表长度

时间:2011-11-29 03:56:53

标签: python list

好吧,我承认我没有很好地提出这个问题。我会更新我的问题更准确。

我正在编写一个以列表作为参数的函数。我想检查列表的长度,以便我可以遍历列表。

我遇到的问题是当列表只有一个条目时,len(myList)返回该条目的长度(字符串的长度)而不是列表的长度== 1。

如果我强制将参数解析为单个值列表['val'],我可以解决这个问题。但我更喜欢我的API允许用户解析值或值列表。

示例:

    def myMethod(self,dataHandle, data,**kwargs):

        comment = kwargs.get('comment','')

        _dataHandle= list()
        _data = list()

        _dataHandle.append(dataHandle)
        _data.append(data)

        for i in range(_dataHandle):
            # do stuff.

我希望能够通过

调用我的方法
myMethod('ed', ed.spectra,comment='down welling irradiance')

myMethod(['ed','lu'] , [ed.spectra,lu.spectra] , comments = ['downwelling', upwelling radiance'])

非常感谢任何帮助。解析['ed']似乎不是什么大不了的事,但到目前为止它破坏了我的API的一致性。

5 个答案:

答案 0 :(得分:5)

由单个项组成的列表的正确python语法是[ 'ed' ]

您对list('ed')所做的是要求python将'ed'转换为列表。这是python中的一致隐喻:当你想将某些东西转换为字符串时,你会说str(some_thing)。你用来使list('ed')返回一个只有字符串'ed'的列表的任何hack都会破坏python的内部隐喻。

当python看到list(x)时,它会尝试将x转换为列表。如果x是可迭代的,它会或多或少地与此相同:

def make_list(x):
  ret_val = []
  for item in x:
    ret_val.append(item)
  return ret_val

因为你的字符串'ed'是可迭代的,所以python会将它转换为长度为2的列表:[ 'e', 'd' ]

在这种情况下,最干净的惯用python可能是让你的函数接受可变数量的参数,所以代替这个

def my_func(itemList):
  ...
你会这样做

def my_func(*items):
  ...

而不是像这样称呼它

my_func(['ed','lu','lsky'])

你会这样称呼它:

my_func('ed', 'lu', 'lsky')

通过这种方式,您可以接受任意数量的参数,并且您的API将非常干净。

答案 1 :(得分:3)

您可以询问您的变量是否为list

def my_method(my_var):
    if isinstance(my_var, list):
        for my_elem in my_var:
            # do stuff with my_elem
    else:  # my_var is not iterable
        # do stuff with my_var

编辑:另一种选择是尝试迭代它,如果它失败(加注和异常),你认为是一个单独的元素:

def my_method(my_var):
    try:
        for my_elem in my_var:
            # do stuff with my_elem
    except TypeError:  # my_var is not iterable
        # do_stuff with my_var

关于第二个选项的好处是,它不仅可以作为第一个选项用于list,还可以用于任何可迭代的(string s,set s ,dict等等。)

答案 2 :(得分:1)

如果您希望将列表 ,您确实需要将字符串放在列表

修改

我看到在某些时候字符串前面有一个list。与您的想法相反,list不会创建一个项目的列表。它在字符串对象上调用__iter__并迭代每个项目。因此它创建了一个字符列表。

希望这更清楚:

>>> print(list('abc'))
['a', 'b', 'c']
>>> print(list(('abc',)))
['abc']

答案 3 :(得分:0)

list('ed')不会创建包含单个元素'ed'的列表。 list(x)通常不会创建包含单个元素x的列表。事实上,如果你一直在使用数字而不是字符串(或其他任何不可迭代的东西),那么这对你来说是显而易见的:

>>> list('ed')
['e', 'd']
>>> list(3)
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    list(3)
TypeError: 'int' object is not iterable
>>

所以你实际上是将一个包含多个元素的列表传递给你的方法,这就是len返回大于1的原因。它没有返回列表第一个元素的长度。

对于允许传递单个项目或列表的方法,您必须先进行一些检查以查看它是否是单个项目,如果是创建包含myVar = [myVar]的列表,然后运行你的循环。

然而,这种API实现和使用很棘手,我不推荐它。检查您是否已获得集合或项目的最自然方式是查看myVar是否可迭代。但是,对于可迭代的字符串,这会失败。不幸的是,字符串跨越集合和单个数据项之间的边界;我们经常将它们用作包含“文本块”的数据项,但它们也是字符集合,Python允许它们这样使用。

这样的API也可能会让你有一天意外地传递一个你认为是单一事物的列表,并期望该方法将其视为一件事。但它是一个列表,所以突然代码的行为会有所不同。

它还提出了有关您如何处理其他数据类型的问题。字典不是列表,但可以迭代。如果您将字典作为myVar传递,它是否会被视为包含单个字典的列表,还是会迭代字典的键?一个元组怎么样?实现__iter__的自定义类怎么样?如果实现__iter__的自定义类尝试“类似字符串”而不是“类似列表”会怎么样?

如果来电者猜错/记得错误,所有这些问题都会带来惊喜。编程导致错误时会感到惊讶。恕我直言,最好只使用额外的两个字符输入([]),让你的API干净简洁。

答案 4 :(得分:0)

我经常遇到同样的问题。正如您在使用“_dataHandle = list()”行一样,从空列表构建列表在Python中很常见,因为我们不会提前保留内存。因此,通常情况是列表的状态将从空转换为一个元素,转换为多个元素。正如您所发现的,Python将一个元素与多个元素的索引视为不同。如果您可以使用列表推导,那么解决方案可以很简单。而不是:

for i in range(_dataHandle):

使用:

for myvar in _dataHandle:

在这种情况下,如果只有一个元素,则循环只会按预期迭代一次。