# 如何检查列表是否为空？

## 问题：如何检查列表是否为空？

``a = []``

For example, if passed the following:

``````a = []
``````

How do I check to see if `a` is empty?

## 回答 0

``````if not a:
print("List is empty")``````

``````if not a:
print("List is empty")
``````

Using the implicit booleanness of the empty `list` is quite pythonic.

## 回答 1

``````Yes: if not seq:
if seq:

No:  if len(seq):
if not len(seq):``````

The pythonic way to do it is from the PEP 8 style guide (where Yes means “recommended” and No means “not recommended”):

For sequences, (strings, lists, tuples), use the fact that empty sequences are false.

``````Yes: if not seq:
if seq:

No:  if len(seq):
if not len(seq):
``````

## 回答 2

``````if len(li) == 0:
print('the list is empty')``````

I prefer it explicitly:

``````if len(li) == 0:
print('the list is empty')
``````

This way it’s 100% clear that `li` is a sequence (list) and we want to test its size. My problem with `if not li: ...` is that it gives the false impression that `li` is a boolean variable.

# 其他方法不适用于NumPy数组

### “ pythonic”方式无效：第1部分

NumPy数组的“ pythonic”方法失败，因为NumPy尝试将数组转换为`bool`s 的数组，并`if x`尝试`bool`一次对所有这些s 求值，以获得某种合计的真值。但这没有任何意义，因此您得到了`ValueError`

``````>>> x = numpy.array([0,1])
>>> if x: print("x")
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()``````

### “ pythonic”方式无效：第2部分

``````>>> x = numpy.array([0,])
>>> if x: print("x")
... else: print("No x")
No x``````

### 使用`len`会产生意想不到的结果

``len( numpy.zeros((1,0)) )``

### numpythonic方式

SciPy常见问题解答中所述，在您知道拥有NumPy数组的所有情况下，正确的方法是使用`if x.size`

``````>>> x = numpy.array([0,1])
>>> if x.size: print("x")
x

>>> x = numpy.array([0,])
>>> if x.size: print("x")
... else: print("No x")
x

>>> x = numpy.zeros((1,0))
>>> if x.size: print("x")
... else: print("No x")
No x``````

``x = numpy.asarray(x, dtype=numpy.double)``

This is the first google hit for “python test empty array” and similar queries, plus other people seem to be generalizing the question beyond just lists, so I thought I’d add a caveat for a different type of sequence that a lot of people might use.

# Other methods don’t work for NumPy arrays

You need to be careful with NumPy arrays, because other methods that work fine for `list`s or other standard containers fail for NumPy arrays. I explain why below, but in short, the preferred method is to use `size`.

### The “pythonic” way doesn’t work: Part 1

The “pythonic” way fails with NumPy arrays because NumPy tries to cast the array to an array of `bool`s, and `if x` tries to evaluate all of those `bool`s at once for some kind of aggregate truth value. But this doesn’t make any sense, so you get a `ValueError`:

``````>>> x = numpy.array([0,1])
>>> if x: print("x")
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
``````

### The “pythonic” way doesn’t work: Part 2

But at least the case above tells you that it failed. If you happen to have a NumPy array with exactly one element, the `if` statement will “work”, in the sense that you don’t get an error. However, if that one element happens to be `0` (or `0.0`, or `False`, …), the `if` statement will incorrectly result in `False`:

``````>>> x = numpy.array([0,])
>>> if x: print("x")
... else: print("No x")
No x
``````

But clearly `x` exists and is not empty! This result is not what you wanted.

### Using `len` can give unexpected results

For example,

``````len( numpy.zeros((1,0)) )
``````

returns 1, even though the array has zero elements.

### The numpythonic way

As explained in the SciPy FAQ, the correct method in all cases where you know you have a NumPy array is to use `if x.size`:

``````>>> x = numpy.array([0,1])
>>> if x.size: print("x")
x

>>> x = numpy.array([0,])
>>> if x.size: print("x")
... else: print("No x")
x

>>> x = numpy.zeros((1,0))
>>> if x.size: print("x")
... else: print("No x")
No x
``````

If you’re not sure whether it might be a `list`, a NumPy array, or something else, you could combine this approach with the answer @dubiousjim gives to make sure the right test is used for each type. Not very “pythonic”, but it turns out that NumPy intentionally broke pythonicity in at least this sense.

If you need to do more than just check if the input is empty, and you’re using other NumPy features like indexing or math operations, it’s probably more efficient (and certainly more common) to force the input to be a NumPy array. There are a few nice functions for doing this quickly — most importantly `numpy.asarray`. This takes your input, does nothing if it’s already an array, or wraps your input into an array if it’s a list, tuple, etc., and optionally converts it to your chosen `dtype`. So it’s very quick whenever it can be, and it ensures that you just get to assume the input is a NumPy array. We usually even just use the same name, as the conversion to an array won’t make it back outside of the current scope:

``````x = numpy.asarray(x, dtype=numpy.double)
``````

This will make the `x.size` check work in all cases I see on this page.

## 检查列表是否为空的最佳方法

``a = []``

## 简短答案：

``````if not a:                           # do this!
print('a is an empty list')``````

## 人教版8

PEP 8是Python标准库中Python代码的官方Python样式指南，它断言：

``````Yes: if not seq:
if seq:

No: if len(seq):
if not len(seq):``````

## 说明

``````if len(a) == 0:                     # Don't do this!
print('a is an empty list')``````

``````if a == []:                         # Don't do this!
print('a is an empty list')``````

• 定义为false的常量：`None``False`
• 任何数值类型的零：`0``0.0``0j``Decimal(0)``Fraction(0, 1)`
• 空序列和集合：`''``()``[]``{}``set()``range(0)`

`object.__bool__(self)`

`object.__len__(self)`

``````if len(a) == 0:                     # Don't do this!
print('a is an empty list')``````

``````if a == []:                     # Don't do this!
print('a is an empty list')``````

``````if not a:
print('a is an empty list')``````

## 做Pythonic通常可以提高性能：

``````>>> import timeit
>>> min(timeit.repeat(lambda: len([]) == 0, repeat=100))
0.13775854044661884
>>> min(timeit.repeat(lambda: [] == [], repeat=100))
0.0984637276455409
>>> min(timeit.repeat(lambda: not [], repeat=100))
0.07878462291455435``````

``````>>> min(timeit.repeat(lambda: [], repeat=100))
0.07074015751817342``````

``````>>> import dis
>>> dis.dis(lambda: len([]) == 0)
2 BUILD_LIST               0
4 CALL_FUNCTION            1
8 COMPARE_OP               2 (==)
10 RETURN_VALUE``````

``````>>> dis.dis(lambda: [] == [])
1           0 BUILD_LIST               0
2 BUILD_LIST               0
4 COMPARE_OP               2 (==)
6 RETURN_VALUE``````

``````>>> dis.dis(lambda: not [])
1           0 BUILD_LIST               0
2 UNARY_NOT
4 RETURN_VALUE``````

## 来自C源代码和文档的证据

`PyVarObject`

``````typedef struct {
/* Vector of pointers to list elements.  list[0] is ob_item[0], etc. */
PyObject **ob_item;

/* ob_item contains space for 'allocated' elements.  The number
* currently in use is ob_size.
* Invariants:
*     0 <= ob_size <= allocated
*     len(list) == ob_size``````

## 对评论的回应：

IPython的魔术`%timeit`在这里并非完全没有用：

``````In [1]: l = []

In [2]: %timeit l
20 ns ± 0.155 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)

In [3]: %timeit not l
24.4 ns ± 1.58 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [4]: %timeit not not l
30.1 ns ± 2.16 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)``````

``````In [5]: %timeit if l: pass
22.6 ns ± 0.963 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [6]: %timeit if not l: pass
24.4 ns ± 0.796 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [7]: %timeit if not not l: pass
23.4 ns ± 0.793 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)``````

``````In [8]: l = [1]

In [9]: %timeit if l: pass
23.7 ns ± 1.06 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [10]: %timeit if not l: pass
23.6 ns ± 1.64 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [11]: %timeit if not not l: pass
26.3 ns ± 1 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)``````

Python是用C编写的；它在C级别使用其逻辑。您用Python编写的任何内容都会变慢。除非您直接使用Python内置的机制，否则这可能会慢几个数量级。

## Best way to check if a list is empty

For example, if passed the following:

``````a = []
``````

How do I check to see if a is empty?

Place the list in a boolean context (for example, with an `if` or `while` statement). It will test `False` if it is empty, and `True` otherwise. For example:

``````if not a:                           # do this!
print('a is an empty list')
``````

## PEP 8

PEP 8, the official Python style guide for Python code in Python’s standard library, asserts:

For sequences, (strings, lists, tuples), use the fact that empty sequences are false.

``````Yes: if not seq:
if seq:

No: if len(seq):
if not len(seq):
``````

We should expect that standard library code should be as performant and correct as possible. But why is that the case, and why do we need this guidance?

## Explanation

I frequently see code like this from experienced programmers new to Python:

``````if len(a) == 0:                     # Don't do this!
print('a is an empty list')
``````

And users of lazy languages may be tempted to do this:

``````if a == []:                         # Don't do this!
print('a is an empty list')
``````

These are correct in their respective other languages. And this is even semantically correct in Python.

But we consider it un-Pythonic because Python supports these semantics directly in the list object’s interface via boolean coercion.

From the docs (and note specifically the inclusion of the empty list, `[]`):

By default, an object is considered true unless its class defines either a `__bool__()` method that returns `False` or a `__len__()` method that returns zero, when called with the object. Here are most of the built-in objects considered false:

• constants defined to be false: `None` and `False`.
• zero of any numeric type: `0`, `0.0`, `0j`, `Decimal(0)`, `Fraction(0, 1)`
• empty sequences and collections: `''`, `()`, `[]`, `{}`, `set()`, `range(0)`

And the datamodel documentation:

`object.__bool__(self)`

Called to implement truth value testing and the built-in operation `bool()`; should return `False` or `True`. When this method is not defined, `__len__()` is called, if it is defined, and the object is considered true if its result is nonzero. If a class defines neither `__len__()` nor `__bool__()`, all its instances are considered true.

and

`object.__len__(self)`

Called to implement the built-in function `len()`. Should return the length of the object, an integer >= 0. Also, an object that doesn’t define a `__bool__()` method and whose `__len__()` method returns zero is considered to be false in a Boolean context.

``````if len(a) == 0:                     # Don't do this!
print('a is an empty list')
``````

or this:

``````if a == []:                     # Don't do this!
print('a is an empty list')
``````

Do this:

``````if not a:
print('a is an empty list')
``````

## Doing what’s Pythonic usually pays off in performance:

Does it pay off? (Note that less time to perform an equivalent operation is better:)

``````>>> import timeit
>>> min(timeit.repeat(lambda: len([]) == 0, repeat=100))
0.13775854044661884
>>> min(timeit.repeat(lambda: [] == [], repeat=100))
0.0984637276455409
>>> min(timeit.repeat(lambda: not [], repeat=100))
0.07878462291455435
``````

For scale, here’s the cost of calling the function and constructing and returning an empty list, which you might subtract from the costs of the emptiness checks used above:

``````>>> min(timeit.repeat(lambda: [], repeat=100))
0.07074015751817342
``````

We see that either checking for length with the builtin function `len` compared to `0` or checking against an empty list is much less performant than using the builtin syntax of the language as documented.

Why?

For the `len(a) == 0` check:

First Python has to check the globals to see if `len` is shadowed.

Then it must call the function, load `0`, and do the equality comparison in Python (instead of with C):

``````>>> import dis
>>> dis.dis(lambda: len([]) == 0)
2 BUILD_LIST               0
4 CALL_FUNCTION            1
8 COMPARE_OP               2 (==)
10 RETURN_VALUE
``````

And for the `[] == []` it has to build an unnecessary list and then, again, do the comparison operation in Python’s virtual machine (as opposed to C)

``````>>> dis.dis(lambda: [] == [])
1           0 BUILD_LIST               0
2 BUILD_LIST               0
4 COMPARE_OP               2 (==)
6 RETURN_VALUE
``````

The “Pythonic” way is a much simpler and faster check since the length of the list is cached in the object instance header:

``````>>> dis.dis(lambda: not [])
1           0 BUILD_LIST               0
2 UNARY_NOT
4 RETURN_VALUE
``````

## Evidence from the C source and documentation

`PyVarObject`

This is an extension of `PyObject` that adds the `ob_size` field. This is only used for objects that have some notion of length. This type does not often appear in the Python/C API. It corresponds to the fields defined by the expansion of the `PyObject_VAR_HEAD` macro.

From the c source in Include/listobject.h:

``````typedef struct {
/* Vector of pointers to list elements.  list[0] is ob_item[0], etc. */
PyObject **ob_item;

/* ob_item contains space for 'allocated' elements.  The number
* currently in use is ob_size.
* Invariants:
*     0 <= ob_size <= allocated
*     len(list) == ob_size
``````

I would point out that this is also true for the non-empty case though its pretty ugly as with `l=[]` then `%timeit len(l) != 0` 90.6 ns ± 8.3 ns, `%timeit l != []` 55.6 ns ± 3.09, `%timeit not not l` 38.5 ns ± 0.372. But there is no way anyone is going to enjoy `not not l` despite triple the speed. It looks ridiculous. But the speed wins out
I suppose the problem is testing with timeit since just `if l:` is sufficient but surprisingly `%timeit bool(l)` yields 101 ns ± 2.64 ns. Interesting there is no way to coerce to bool without this penalty. `%timeit l` is useless since no conversion would occur.

IPython magic, `%timeit`, is not entirely useless here:

``````In [1]: l = []

In [2]: %timeit l
20 ns ± 0.155 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)

In [3]: %timeit not l
24.4 ns ± 1.58 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [4]: %timeit not not l
30.1 ns ± 2.16 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
``````

We can see there’s a bit of linear cost for each additional `not` here. We want to see the costs, ceteris paribus, that is, all else equal – where all else is minimized as far as possible:

``````In [5]: %timeit if l: pass
22.6 ns ± 0.963 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [6]: %timeit if not l: pass
24.4 ns ± 0.796 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [7]: %timeit if not not l: pass
23.4 ns ± 0.793 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
``````

Now let’s look at the case for an unempty list:

``````In [8]: l = [1]

In [9]: %timeit if l: pass
23.7 ns ± 1.06 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [10]: %timeit if not l: pass
23.6 ns ± 1.64 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [11]: %timeit if not not l: pass
26.3 ns ± 1 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
``````

What we can see here is that it makes little difference whether you pass in an actual `bool` to the condition check or the list itself, and if anything, giving the list, as is, is faster.

Python is written in C; it uses its logic at the C level. Anything you write in Python will be slower. And it will likely be orders of magnitude slower unless you’re using the mechanisms built into Python directly.

## 回答 5

``````a = []
if a:
print "not empty"``````

@达伦·托马斯

An empty list is itself considered false in true value testing (see python documentation):

``````a = []
if a:
print "not empty"
``````

@Daren Thomas

EDIT: Another point against testing the empty list as False: What about polymorphism? You shouldn’t depend on a list being a list. It should just quack like a duck – how are you going to get your duckCollection to quack ”False” when it has no elements?

Your duckCollection should implement `__nonzero__` or `__len__` so the if a: will work without problems.

## 回答 6

Python代码和Python社区都有非常强大的习惯用法。遵循这些惯用法可以使您的代码更容易为有Python经验的人阅读。当您违反这些习惯用法时，这是一个强烈的信号。

Patrick’s (accepted) answer is right: `if not a:` is the right way to do it. Harley Holcombe’s answer is right that this is in the PEP 8 style guide. But what none of the answers explain is why it’s a good idea to follow the idiom—even if you personally find it’s not explicit enough or confusing to Ruby users or whatever.

Python code, and the Python community, has very strong idioms. Following those idioms makes your code easier to read for anyone experienced in Python. And when you violate those idioms, that’s a strong signal.

It’s true that `if not a:` doesn’t distinguish empty lists from `None`, or numeric 0, or empty tuples, or empty user-created collection types, or empty user-created not-quite-collection types, or single-element NumPy array acting as scalars with falsey values, etc. And sometimes it’s important to be explicit about that. And in that case, you know what you want to be explicit about, so you can test for exactly that. For example, `if not a and a is not None:` means “anything falsey except None”, while `if len(a) != 0:` means “only empty sequences—and anything besides a sequence is an error here”, and so on. Besides testing for exactly what you want to test, this also signals to the reader that this test is important.

But when you don’t have anything to be explicit about, anything other than `if not a:` is misleading the reader. You’re signaling something as important when it isn’t. (You may also be making the code less flexible, or slower, or whatever, but that’s all less important.) And if you habitually mislead the reader like this, then when you do need to make a distinction, it’s going to pass unnoticed because you’ve been “crying wolf” all over your code.

# 为什么要检查？

``````a = []

for item in a:
<do something with item>

<rest of code>``````

# Why check at all?

No one seems to have addressed questioning your need to test the list in the first place. Because you provided no additional context, I can imagine that you may not need to do this check in the first place, but are unfamiliar with list processing in Python.

I would argue that the most pythonic way is to not check at all, but rather to just process the list. That way it will do the right thing whether empty or full.

``````a = []

for item in a:
<do something with item>

<rest of code>
``````

This has the benefit of handling any contents of a, while not requiring a specific check for emptiness. If a is empty, the dependent block will not execute and the interpreter will fall through to the next line.

If you do actually need to check the array for emptiness, the other answers are sufficient.

## 回答 8

`len()`用于Python列表，字符串，字典和集合的O（1）操作。Python在内部跟踪这些容器中元素的数量。

JavaScript 有一个true / falsy的类似概念

`len()` is an O(1) operation for Python lists, strings, dicts, and sets. Python internally keeps track of the number of elements in these containers.

JavaScript has a similar notion of truthy/falsy.

## 回答 9

``````if isinstance(a, (list, some, other, types, i, accept)) and not a:
do_stuff``````

``````if isinstance(a, numpy.ndarray) and not a.size:
do_stuff
elif isinstance(a, collections.Sized) and not a:
do_stuff``````

``elif isinstance(a, (list, tuple)) and not a:``

``elif isinstance(a, (list, tuple)) and not len(a):``

``````if isinstance(a, (list, some, other, types, i, accept)) and not a:
do_stuff
``````

which was voted -1. I’m not sure if that’s because readers objected to the strategy or thought the answer wasn’t helpful as presented. I’ll pretend it was the latter, since—whatever counts as “pythonic”—this is the correct strategy. Unless you’ve already ruled out, or are prepared to handle cases where `a` is, for example, `False`, you need a test more restrictive than just `if not a:`. You could use something like this:

``````if isinstance(a, numpy.ndarray) and not a.size:
do_stuff
elif isinstance(a, collections.Sized) and not a:
do_stuff
``````

the first test is in response to @Mike’s answer, above. The third line could also be replaced with:

``````elif isinstance(a, (list, tuple)) and not a:
``````

if you only want to accept instances of particular types (and their subtypes), or with:

``````elif isinstance(a, (list, tuple)) and not len(a):
``````

You can get away without the explicit type check, but only if the surrounding context already assures you that `a` is a value of the types you’re prepared to handle, or if you’re sure that types you’re not prepared to handle are going to raise errors (e.g., a `TypeError` if you call `len` on a value for which it’s undefined) that you’re prepared to handle. In general, the “pythonic” conventions seem to go this last way. Squeeze it like a duck and let it raise a DuckError if it doesn’t know how to quack. You still have to think about what type assumptions you’re making, though, and whether the cases you’re not prepared to handle properly really are going to error out in the right places. The Numpy arrays are a good example where just blindly relying on `len` or the boolean typecast may not do precisely what you’re expecting.

## 回答 10

• `None`
• `False`
• 任何数值类型的零，例如`0``0.0``0j`
• 任何空序列，例如`''``()``[]`
• 任何空映射，例如`{}`
• 用户定义的类的实例，如果该类定义了`__bool__()``__len__()`方法，则该方法返回整数0或bool value时`False`

``````if not a:
print('"a" is empty!')``````

From documentation on truth value testing:

All values other than what is listed here are considered `True`

• `None`
• `False`
• zero of any numeric type, for example, `0`, `0.0`, `0j`.
• any empty sequence, for example, `''`, `()`, `[]`.
• any empty mapping, for example, `{}`.
• instances of user-defined classes, if the class defines a `__bool__()` or `__len__()` method, when that method returns the integer zero or bool value `False`.

As can be seen, empty list `[]` is falsy, so doing what would be done to a boolean value sounds most efficient:

``````if not a:
print('"a" is empty!')
``````

## 回答 11

``a = [] #the list``

1）非常简单的pythonic方式：

``````if not a:
print("a is empty")``````

2）一种非常明确的方法：使用`len()`来查找长度并检查其是否等于`0`

``````if len(a) == 0:
print("a is empty")``````

3）或将其与匿名空列表进行比较：

``````if a == []:
print("a is empty")``````

4）另一种愚蠢的做法是使用`exception``iter()`

``````try:
next(iter(a))
# list has elements
except StopIteration:
print("Error: a is empty")``````

Here are a few ways you can check if a list is empty:

``````a = [] #the list
``````

1) The pretty simple pythonic way:

``````if not a:
print("a is empty")
``````

In Python, empty containers such as lists,tuples,sets,dicts,variables etc are seen as `False`. One could simply treat the list as a predicate (returning a Boolean value). And a `True` value would indicate that it’s non-empty.

2) A much explicit way: using the `len()` to find the length and check if it equals to `0`:

``````if len(a) == 0:
print("a is empty")
``````

3) Or comparing it to an anonymous empty list:

``````if a == []:
print("a is empty")
``````

4) Another yet silly way to do is using `exception` and `iter()`:

``````try:
next(iter(a))
# list has elements
except StopIteration:
print("Error: a is empty")
``````

## 回答 12

``````if a == []:
print "The list is empty."``````

I prefer the following:

``````if a == []:
print "The list is empty."
``````

## 回答 13

``````if not a :
print ("Empty") ``````

``````if len(a) == 0 :
print( "Empty" )``````

``````if a == [] :
print ("Empty")``````

Method 1 (Preferred):

``````if not a :
print ("Empty")
``````

Method 2 :

``````if len(a) == 0 :
print( "Empty" )
``````

Method 3:

``````if a == [] :
print ("Empty")
``````

## 回答 14

``````def list_test (L):
if   L is None  : print('list is None')
elif not L      : print('list is empty')
else: print('list has %d elements' % len(L))

list_test(None)
list_test([])
list_test([1,2,3])``````

``````list is None
list is empty
list has 3 elements``````

``````def list_test2 (L):
if not L      : print('list is empty')
else: print('list has %d elements' % len(L))

list_test2(None)
list_test2([])
list_test2([1,2,3])``````

``````list is empty
list is empty
list has 3 elements``````
``````def list_test (L):
if   L is None  : print('list is None')
elif not L      : print('list is empty')
else: print('list has %d elements' % len(L))

list_test(None)
list_test([])
list_test([1,2,3])
``````

It is sometimes good to test for `None` and for emptiness separately as those are two different states. The code above produces the following output:

``````list is None
list is empty
list has 3 elements
``````

Although it’s worth nothing that `None` is falsy. So if you don’t want to separate test for `None`-ness, you don’t have to do that.

``````def list_test2 (L):
if not L      : print('list is empty')
else: print('list has %d elements' % len(L))

list_test2(None)
list_test2([])
list_test2([1,2,3])
``````

produces expected

``````list is empty
list is empty
list has 3 elements
``````

## 回答 15

``not a``

``````if isinstance(a, list) and len(a)==0:

Many answers have been given, and a lot of them are pretty good. I just wanted to add that the check

``````not a
``````

will also pass for `None` and other types of empty structures. If you truly want to check for an empty list, you can do this:

``````if isinstance(a, list) and len(a)==0:
``````

## 回答 16

``````item_list=[]
if len(item_list) == 0:
print("list is empty")
else:
print("list is not empty")``````

we could use a simple if else:

``````item_list=[]
if len(item_list) == 0:
print("list is empty")
else:
print("list is not empty")
``````

## 回答 17

``````l = []
if l:

``````l = ["", False, 0, '', [], {}, ()]
if all(bool(x) for x in l):

``````def empty_list(lst):
if len(lst) == 0:
return False
else:
return all(bool(x) for x in l)``````

``````if empty_list(lst):

If you want to check if a list is empty:

``````l = []
if l:
``````

If you want to check whether all the values in list is empty. However it will be `True` for an empty list:

``````l = ["", False, 0, '', [], {}, ()]
if all(bool(x) for x in l):
``````

If you want to use both cases together:

``````def empty_list(lst):
if len(lst) == 0:
return False
else:
return all(bool(x) for x in l)
``````

Now you can use:

``````if empty_list(lst):
``````

## 回答 18

``````import collections
def is_empty(a):
return not a and isinstance(a, collections.Iterable)``````

``````>>> is_empty('sss')
False
>>> is_empty(555)
False
>>> is_empty(0)
False
>>> is_empty('')
True
>>> is_empty([3])
False
>>> is_empty([])
True
>>> is_empty({})
True
>>> is_empty(())
True``````

Being inspired by @dubiousjim’s solution, I propose to use an additional general check of whether is it something iterable

``````import collections
def is_empty(a):
return not a and isinstance(a, collections.Iterable)
``````

Note: a string is considered to be iterable. – add `and not isinstance(a,(str,unicode))` if you want the empty string to be excluded

Test:

``````>>> is_empty('sss')
False
>>> is_empty(555)
False
>>> is_empty(0)
False
>>> is_empty('')
True
>>> is_empty([3])
False
>>> is_empty([])
True
>>> is_empty({})
True
>>> is_empty(())
True
``````

## 回答 19

``print('not empty' if a else 'empty')``

``a.pop() if a else None``

``if a: a.pop() ``
``````print('not empty' if a else 'empty')
``````

a little more practical:

``````a.pop() if a else None
``````

and shertest version:

``````if a: a.pop()
``````

## 回答 20

``a == []``

From python3 onwards you can use

``````a == []
``````

to check if the list is empty

EDIT : This works with python2.7 too..

I am not sure why there are so many complicated answers. It’s pretty clear and straightforward

## 回答 21

``````    a = [1,2,3];
print bool(a); # it will return True
a = [];
print bool(a); # it will return False``````

You can even try using bool() like this

``````    a = [1,2,3];
print bool(a); # it will return True
a = [];
print bool(a); # it will return False
``````

I love this way for checking list is empty or not.

Very handy and useful.

## 回答 22

``````def is_empty(any_structure):
if any_structure:
print('Structure is not empty.')
return True
else:
print('Structure is empty.')
return False  ``````

Simply use is_empty() or make function like:-

``````def is_empty(any_structure):
if any_structure:
print('Structure is not empty.')
return True
else:
print('Structure is empty.')
return False
``````

It can be used for any data_structure like a list,tuples, dictionary and many more. By these, you can call it many times using just `is_empty(any_structure)`.

## 回答 23

``````if len(a) == 0:
print("a is empty")``````

Simple way is checking the length is equal zero.

``````if len(a) == 0:
print("a is empty")
``````

## 回答 24

The truth value of an empty list is `False` whereas for a non-empty list it is `True`.

## 回答 25

``foo = itertools.takewhile(is_not_empty, (f(x) for x in itertools.count(1)))``

``foo = itertools.takewhile(bool, (f(x) for x in itertools.count(1)))``

What brought me here is a special use-case: I actually wanted a function to tell me if a list is empty or not. I wanted to avoid writing my own function or using a lambda-expression here (because it seemed like it should be simple enough):

``````foo = itertools.takewhile(is_not_empty, (f(x) for x in itertools.count(1)))
``````

And, of course, there is a very natural way to do it:

``````foo = itertools.takewhile(bool, (f(x) for x in itertools.count(1)))
``````

Of course, do not use `bool` in `if` (i.e., `if bool(L):`) because it’s implied. But, for the cases when “is not empty” is explicitly needed as a function, `bool` is the best choice.

## 回答 26

``````def enquiry(list1):
if len(list1) == 0:
return 0
else:
return 1

# ––––––––––––––––––––––––––––––––

list1 = []

if enquiry(list1):
print ("The list isn't empty")
else:
print("The list is Empty")

# Result: "The list is Empty".``````

``````def enquiry(list1):
if not list1:
return True
else:
return False

# ––––––––––––––––––––––––––––––––

list1 = []

if enquiry(list1):
print ("The list is Empty")
else:
print ("The list isn't empty")

# Result: "The list is Empty"``````

To check whether a list is empty or not you can use two following ways. But remember, we should avoid the way of explicitly checking for a type of sequence (it’s a `less pythonic` way):

``````def enquiry(list1):
if len(list1) == 0:
return 0
else:
return 1

# ––––––––––––––––––––––––––––––––

list1 = []

if enquiry(list1):
print ("The list isn't empty")
else:
print("The list is Empty")

# Result: "The list is Empty".
``````

The second way is a `more pythonic` one. This method is an implicit way of checking and much more preferable than the previous one.

``````def enquiry(list1):
if not list1:
return True
else:
return False

# ––––––––––––––––––––––––––––––––

list1 = []

if enquiry(list1):
print ("The list is Empty")
else:
print ("The list isn't empty")

# Result: "The list is Empty"
``````

Hope this helps.

# 在列表中查找项目的索引

## 问题：在列表中查找项目的索引

Given a list `["foo", "bar", "baz"]` and an item in the list `"bar"`, how do I get its index (`1`) in Python?

## 回答 0

``````>>> ["foo", "bar", "baz"].index("bar")
1``````

# 注意事项

``list.index(x[, start[, end]])``

## 列表长度的线性时间复杂度

``````>>> import timeit
>>> timeit.timeit('l.index(999_999)', setup='l = list(range(0, 1_000_000))', number=1000)
9.356267921015387
>>> timeit.timeit('l.index(999_999, 999_990, 1_000_000)', setup='l = list(range(0, 1_000_000))', number=1000)
0.0004404920036904514``````

## 仅将第一个匹配项的索引返回到其参数

``````>>> [1, 1].index(1)
0
>>> [i for i, e in enumerate([1, 2, 1]) if e == 1]
[0, 2]
>>> g = (i for i, e in enumerate([1, 2, 1]) if e == 1)
>>> next(g)
0
>>> next(g)
2``````

## 如果元素不在列表中则抛出

``````>>> [1, 1].index(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 2 is not in list``````

1. 首先使用`item in my_list`（干净，可读的方法）进行检查，或者
2. `index`呼叫包裹在一个`try/except`可以捕获的块中`ValueError`（可能更快，至少在要搜索的列表较长且通常存在该项目的情况下。）
``````>>> ["foo", "bar", "baz"].index("bar")
1
``````

Reference: Data Structures > More on Lists

# Caveats follow

Note that while this is perhaps the cleanest way to answer the question as asked, `index` is a rather weak component of the `list` API, and I can’t remember the last time I used it in anger. It’s been pointed out to me in the comments that because this answer is heavily referenced, it should be made more complete. Some caveats about `list.index` follow. It is probably worth initially taking a look at the documentation for it:

``````list.index(x[, start[, end]])
``````

Return zero-based index in the list of the first item whose value is equal to x. Raises a `ValueError` if there is no such item.

The optional arguments start and end are interpreted as in the slice notation and are used to limit the search to a particular subsequence of the list. The returned index is computed relative to the beginning of the full sequence rather than the start argument.

## Linear time-complexity in list length

An `index` call checks every element of the list in order, until it finds a match. If your list is long, and you don’t know roughly where in the list it occurs, this search could become a bottleneck. In that case, you should consider a different data structure. Note that if you know roughly where to find the match, you can give `index` a hint. For instance, in this snippet, `l.index(999_999, 999_990, 1_000_000)` is roughly five orders of magnitude faster than straight `l.index(999_999)`, because the former only has to search 10 entries, while the latter searches a million:

``````>>> import timeit
>>> timeit.timeit('l.index(999_999)', setup='l = list(range(0, 1_000_000))', number=1000)
9.356267921015387
>>> timeit.timeit('l.index(999_999, 999_990, 1_000_000)', setup='l = list(range(0, 1_000_000))', number=1000)
0.0004404920036904514
``````

## Only returns the index of the first match to its argument

A call to `index` searches through the list in order until it finds a match, and stops there. If you expect to need indices of more matches, you should use a list comprehension, or generator expression.

``````>>> [1, 1].index(1)
0
>>> [i for i, e in enumerate([1, 2, 1]) if e == 1]
[0, 2]
>>> g = (i for i, e in enumerate([1, 2, 1]) if e == 1)
>>> next(g)
0
>>> next(g)
2
``````

Most places where I once would have used `index`, I now use a list comprehension or generator expression because they’re more generalizable. So if you’re considering reaching for `index`, take a look at these excellent Python features.

## Throws if element not present in list

A call to `index` results in a `ValueError` if the item’s not present.

``````>>> [1, 1].index(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 2 is not in list
``````

If the item might not be present in the list, you should either

1. Check for it first with `item in my_list` (clean, readable approach), or
2. Wrap the `index` call in a `try/except` block which catches `ValueError` (probably faster, at least when the list to search is long, and the item is usually present.)

## 回答 1

``````>>> help(["foo", "bar", "baz"])
Help on list object:

class list(object)
...

|
|  index(...)
|      L.index(value, [start, [stop]]) -> integer -- return first index of value
|``````

One thing that is really helpful in learning Python is to use the interactive help function:

``````>>> help(["foo", "bar", "baz"])
Help on list object:

class list(object)
...

|
|  index(...)
|      L.index(value, [start, [stop]]) -> integer -- return first index of value
|
``````

which will often lead you to the method you are looking for.

## 回答 2

``````for i, j in enumerate(['foo', 'bar', 'baz']):
if j == 'bar':
print(i)``````

`index()`函数仅返回第一个匹配项，而`enumerate()`返回所有匹配项。

``[i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar']``

``````from itertools import izip as zip, count # izip for maximum efficiency
[i for i, j in zip(count(), ['foo', 'bar', 'baz']) if j == 'bar']``````

``````\$ python -m timeit -s "from itertools import izip as zip, count" "[i for i, j in zip(count(), ['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 174 usec per loop
\$ python -m timeit "[i for i, j in enumerate(['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 196 usec per loop``````

The majority of answers explain how to find a single index, but their methods do not return multiple indexes if the item is in the list multiple times. Use `enumerate()`:

``````for i, j in enumerate(['foo', 'bar', 'baz']):
if j == 'bar':
print(i)
``````

The `index()` function only returns the first occurrence, while `enumerate()` returns all occurrences.

As a list comprehension:

``````[i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar']
``````

Here’s also another small solution with `itertools.count()` (which is pretty much the same approach as enumerate):

``````from itertools import izip as zip, count # izip for maximum efficiency
[i for i, j in zip(count(), ['foo', 'bar', 'baz']) if j == 'bar']
``````

This is more efficient for larger lists than using `enumerate()`:

``````\$ python -m timeit -s "from itertools import izip as zip, count" "[i for i, j in zip(count(), ['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 174 usec per loop
\$ python -m timeit "[i for i, j in enumerate(['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 196 usec per loop
``````

## 回答 3

``indexes = [i for i,x in enumerate(xs) if x == 'foo']``

To get all indexes:

``````indexes = [i for i,x in enumerate(xs) if x == 'foo']
``````

## 回答 4

`index()`返回值的第一个索引！

| 索引（…）
| L.index（value，[start，[stop]]）->整数-返回值的第一个索引

``````def all_indices(value, qlist):
indices = []
idx = -1
while True:
try:
idx = qlist.index(value, idx+1)
indices.append(idx)
except ValueError:
break
return indices

all_indices("foo", ["foo","bar","baz","foo"])``````

`index()` returns the first index of value!

| index(…)
| L.index(value, [start, [stop]]) -> integer — return first index of value

``````def all_indices(value, qlist):
indices = []
idx = -1
while True:
try:
idx = qlist.index(value, idx+1)
indices.append(idx)
except ValueError:
break
return indices

all_indices("foo", ["foo","bar","baz","foo"])
``````

## 回答 5

``````# if element is found it returns index of element else returns None

def find_element_in_list(element, list_element):
try:
index_element = list_element.index(element)
return index_element
except ValueError:
return None``````

A problem will arise if the element is not in the list. This function handles the issue:

``````# if element is found it returns index of element else returns None

def find_element_in_list(element, list_element):
try:
index_element = list_element.index(element)
return index_element
except ValueError:
return None
``````

## 回答 6

``````a = ["foo","bar","baz",'bar','any','much']

indexes = [index for index in range(len(a)) if a[index] == 'bar']``````
``````a = ["foo","bar","baz",'bar','any','much']

indexes = [index for index in range(len(a)) if a[index] == 'bar']
``````

## 回答 7

``````if 'your_element' in mylist:
print mylist.index('your_element')
else:
print None``````

You have to set a condition to check if the element you’re searching is in the list

``````if 'your_element' in mylist:
print mylist.index('your_element')
else:
print None
``````

## 回答 8

``````[i for i in range(len(mylist)) if mylist[i]==myterm]  # get the indices

[each for each in mylist if each==myterm]             # get the items

mylist.index(myterm) if myterm in mylist else None    # get the first index and fail quietly``````

All of the proposed functions here reproduce inherent language behavior but obscure what’s going on.

``````[i for i in range(len(mylist)) if mylist[i]==myterm]  # get the indices

[each for each in mylist if each==myterm]             # get the items

mylist.index(myterm) if myterm in mylist else None    # get the first index and fail quietly
``````

Why write a function with exception handling if the language provides the methods to do what you want itself?

## 回答 9

``````import numpy as np

array = [1, 2, 1, 3, 4, 5, 1]
item = 1
np_array = np.array(array)
item_index = np.where(np_array==item)
print item_index
# Out: (array([0, 2, 6], dtype=int64),)``````

If you want all indexes, then you can use NumPy:

``````import numpy as np

array = [1, 2, 1, 3, 4, 5, 1]
item = 1
np_array = np.array(array)
item_index = np.where(np_array==item)
print item_index
# Out: (array([0, 2, 6], dtype=int64),)
``````

## 在Python中给定包含该项目的列表的情况下查找项目的索引

``````>>> l = ["foo", "bar", "baz"]
>>> l.index('bar')
1``````

• 如果该值不在列表中，则会得到一个 `ValueError`
• 如果列表中有多个值，则仅获取第一个的索引

### 没有值

``````def index(a_list, value):
try:
return a_list.index(value)
except ValueError:
return None``````

``````>>> print(index(l, 'quux'))
None
>>> print(index(l, 'bar'))
1``````

``````result = index(a_list, value)
if result is not None:
do_something(result)``````

### 列表中有多个值

``````>>> l.append('bar')
>>> l
['foo', 'bar', 'baz', 'bar']
>>> l.index('bar')              # nothing at index 3?
1``````

``````>>> [index for index, v in enumerate(l) if v == 'bar']
[1, 3]
>>> [index for index, v in enumerate(l) if v == 'boink']
[]``````

``````indexes = [index for index, v in enumerate(l) if v == 'boink']
for index in indexes:
do_something(index)``````

### 用熊猫更好地处理数据

``````>>> import pandas as pd
>>> series = pd.Series(l)
>>> series
0    foo
1    bar
2    baz
3    bar
dtype: object``````

``````>>> series == 'bar'
0    False
1     True
2    False
3     True
dtype: bool``````

``````>>> series[series == 'bar']
1    bar
3    bar
dtype: object``````

``````>>> series[series == 'bar'].index
Int64Index([1, 3], dtype='int64')``````

``````>>> list(series[series == 'bar'].index)
[1, 3]``````

``````>>> [i for i, value in enumerate(l) if value == 'bar']
[1, 3]``````

## 这是XY问题吗？

XY问题是在询问您尝试的解决方案，而不是您的实际问题。

`idlelib`GUI和文本解析中，有很多用途。

`keyword`模块使用它在模块中查找注释标记，以通过元编程自动重新生成其中的关键字列表。

``key_list[key_list.index(old)] = new``

``del key_list[key_list.index(key)]``

``mon = MONTHS_LOWER.index(mon.lower())+1``

``members = members[:members.index(tarinfo)]``

``numtopop = before.index(markobject)``

## Finding the index of an item given a list containing it in Python

For a list `["foo", "bar", "baz"]` and an item in the list `"bar"`, what’s the cleanest way to get its index (1) in Python?

Well, sure, there’s the index method, which returns the index of the first occurrence:

``````>>> l = ["foo", "bar", "baz"]
>>> l.index('bar')
1
``````

There are a couple of issues with this method:

• if the value isn’t in the list, you’ll get a `ValueError`
• if more than one of the value is in the list, you only get the index for the first one

### No values

If the value could be missing, you need to catch the `ValueError`.

You can do so with a reusable definition like this:

``````def index(a_list, value):
try:
return a_list.index(value)
except ValueError:
return None
``````

And use it like this:

``````>>> print(index(l, 'quux'))
None
>>> print(index(l, 'bar'))
1
``````

And the downside of this is that you will probably have a check for if the returned value `is` or `is not` None:

``````result = index(a_list, value)
if result is not None:
do_something(result)
``````

### More than one value in the list

If you could have more occurrences, you’ll not get complete information with `list.index`:

``````>>> l.append('bar')
>>> l
['foo', 'bar', 'baz', 'bar']
>>> l.index('bar')              # nothing at index 3?
1
``````

You might enumerate into a list comprehension the indexes:

``````>>> [index for index, v in enumerate(l) if v == 'bar']
[1, 3]
>>> [index for index, v in enumerate(l) if v == 'boink']
[]
``````

If you have no occurrences, you can check for that with boolean check of the result, or just do nothing if you loop over the results:

``````indexes = [index for index, v in enumerate(l) if v == 'boink']
for index in indexes:
do_something(index)
``````

### Better data munging with pandas

If you have pandas, you can easily get this information with a Series object:

``````>>> import pandas as pd
>>> series = pd.Series(l)
>>> series
0    foo
1    bar
2    baz
3    bar
dtype: object
``````

A comparison check will return a series of booleans:

``````>>> series == 'bar'
0    False
1     True
2    False
3     True
dtype: bool
``````

Pass that series of booleans to the series via subscript notation, and you get just the matching members:

``````>>> series[series == 'bar']
1    bar
3    bar
dtype: object
``````

If you want just the indexes, the index attribute returns a series of integers:

``````>>> series[series == 'bar'].index
Int64Index([1, 3], dtype='int64')
``````

And if you want them in a list or tuple, just pass them to the constructor:

``````>>> list(series[series == 'bar'].index)
[1, 3]
``````

Yes, you could use a list comprehension with enumerate too, but that’s just not as elegant, in my opinion – you’re doing tests for equality in Python, instead of letting builtin code written in C handle it:

``````>>> [i for i, value in enumerate(l) if value == 'bar']
[1, 3]
``````

## Is this an XY problem?

Why do you think you need the index given an element in a list?

If you already know the value, why do you care where it is in a list?

If the value isn’t there, catching the `ValueError` is rather verbose – and I prefer to avoid that.

I’m usually iterating over the list anyways, so I’ll usually keep a pointer to any interesting information, getting the index with enumerate.

If you’re munging data, you should probably be using pandas – which has far more elegant tools than the pure Python workarounds I’ve shown.

I do not recall needing `list.index`, myself. However, I have looked through the Python standard library, and I see some excellent uses for it.

There are many, many uses for it in `idlelib`, for GUI and text parsing.

The `keyword` module uses it to find comment markers in the module to automatically regenerate the list of keywords in it via metaprogramming.

In Lib/mailbox.py it seems to be using it like an ordered mapping:

``````key_list[key_list.index(old)] = new
``````

and

``````del key_list[key_list.index(key)]
``````

In Lib/http/cookiejar.py, seems to be used to get the next month:

``````mon = MONTHS_LOWER.index(mon.lower())+1
``````

In Lib/tarfile.py similar to distutils to get a slice up to an item:

``````members = members[:members.index(tarinfo)]
``````

In Lib/pickletools.py:

``````numtopop = before.index(markobject)
``````

What these usages seem to have in common is that they seem to operate on lists of constrained sizes (important because of O(n) lookup time for `list.index`), and they’re mostly used in parsing (and UI in the case of Idle).

While there are use-cases for it, they are fairly uncommon. If you find yourself looking for this answer, ask yourself if what you’re doing is the most direct usage of the tools provided by the language for your use-case.

## 回答 11

``````get_indexes = lambda x, xs: [i for (y, i) in zip(xs, range(len(xs))) if x == y]

print get_indexes(2, [1, 2, 3, 4, 5, 6, 3, 2, 3, 2])
print get_indexes('f', 'xsfhhttytffsafweef')``````

All indexes with the `zip` function:

``````get_indexes = lambda x, xs: [i for (y, i) in zip(xs, range(len(xs))) if x == y]

print get_indexes(2, [1, 2, 3, 4, 5, 6, 3, 2, 3, 2])
print get_indexes('f', 'xsfhhttytffsafweef')
``````

## 回答 12

### 获取列表中一个或多个（相同）项目的所有出现次数和位置

``````>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>``````

### 让我们使函数findindex

``````def indexlist(item2find, list_or_string):
"Returns all indexes of an item in a list or a string"
return [n for n,item in enumerate(list_or_string) if item==item2find]

print(indexlist("1", "010101010"))``````

``[1, 3, 5, 7]``

## 简单

``````for n, i in enumerate([1, 2, 3, 4, 1]):
if i == 1:
print(n)``````

``````0
4``````

### Getting all the occurrences and the position of one or more (identical) items in a list

With enumerate(alist) you can store the first element (n) that is the index of the list when the element x is equal to what you look for.

``````>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>
``````

### Let’s make our function findindex

This function takes the item and the list as arguments and return the position of the item in the list, like we saw before.

``````def indexlist(item2find, list_or_string):
"Returns all indexes of an item in a list or a string"
return [n for n,item in enumerate(list_or_string) if item==item2find]

print(indexlist("1", "010101010"))
``````

Output

``````[1, 3, 5, 7]
``````

## Simple

``````for n, i in enumerate([1, 2, 3, 4, 1]):
if i == 1:
print(n)
``````

Output:

``````0
4
``````

## 回答 13

``````a = [['hand', 'head'], ['phone', 'wallet'], ['lost', 'stock']]
b = ['phone', 'lost']

res = [[x[0] for x in a].index(y) for y in b]``````

Simply you can go with

``````a = [['hand', 'head'], ['phone', 'wallet'], ['lost', 'stock']]
b = ['phone', 'lost']

res = [[x[0] for x in a].index(y) for y in b]
``````

## 回答 14

``````>>> a = ['red', 'blue', 'green', 'red']
>>> b = 'red'
>>> offset = 0;
>>> indices = list()
>>> for i in range(a.count(b)):
...     indices.append(a.index(b,offset))
...     offset = indices[-1]+1
...
>>> indices
[0, 3]
>>> ``````

Another option

``````>>> a = ['red', 'blue', 'green', 'red']
>>> b = 'red'
>>> offset = 0;
>>> indices = list()
>>> for i in range(a.count(b)):
...     indices.append(a.index(b,offset))
...     offset = indices[-1]+1
...
>>> indices
[0, 3]
>>>
``````

# 而现在，对于完全不同的东西…

…就像在获取索引之前确认项目的存在。这种方法的好处是，该函数始终返回一个索引列表-即使它是一个空列表。它也适用于字符串。

``````def indices(l, val):
"""Always returns a list containing the indices of val in the_list"""
retval = []
last = 0
while val in l[last:]:
i = l[last:].index(val)
retval.append(last + i)
last += i + 1
return retval

l = ['bar','foo','bar','baz','bar','bar']
q = 'bar'
print indices(l,q)
print indices(l,'bat')
print indices('abcdaababb','a')``````

``````Python 2.7.6 (v2.7.6:3a1db0d2747e, Nov 10 2013, 00:42:54)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
>>> def indices(the_list, val):
...     """Always returns a list containing the indices of val in the_list"""
...     retval = []
...     last = 0
...     while val in the_list[last:]:
...             i = the_list[last:].index(val)
...             retval.append(last + i)
...             last += i + 1
...     return retval
...
>>> l = ['bar','foo','bar','baz','bar','bar']
>>> q = 'bar'
>>> print indices(l,q)
[0, 2, 4, 5]
>>> print indices(l,'bat')
[]
>>> print indices('abcdaababb','a')
[0, 4, 5, 7]
>>> ``````

# 更新资料

``````def indices(l, val):
"""Always returns a list containing the indices of val in the_list"""
return [index for index, value in enumerate(l) if value == val]

l = ['bar','foo','bar','baz','bar','bar']
q = 'bar'
print indices(l,q)
print indices(l,'bat')
print indices('abcdaababb','a')``````

``````Python 2.7.14 |Anaconda, Inc.| (default, Dec  7 2017, 11:07:58)
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
>>> def indices(l, val):
...     """Always returns a list containing the indices of val in the_list"""
...     return [index for index, value in enumerate(l) if value == val]
...
>>> l = ['bar','foo','bar','baz','bar','bar']
>>> q = 'bar'
>>> print indices(l,q)
[0, 2, 4, 5]
>>> print indices(l,'bat')
[]
>>> print indices('abcdaababb','a')
[0, 4, 5, 7]
>>> ``````

# And now, for something completely different…

… like confirming the existence of the item before getting the index. The nice thing about this approach is the function always returns a list of indices — even if it is an empty list. It works with strings as well.

``````def indices(l, val):
"""Always returns a list containing the indices of val in the_list"""
retval = []
last = 0
while val in l[last:]:
i = l[last:].index(val)
retval.append(last + i)
last += i + 1
return retval

l = ['bar','foo','bar','baz','bar','bar']
q = 'bar'
print indices(l,q)
print indices(l,'bat')
print indices('abcdaababb','a')
``````

When pasted into an interactive python window:

``````Python 2.7.6 (v2.7.6:3a1db0d2747e, Nov 10 2013, 00:42:54)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
>>> def indices(the_list, val):
...     """Always returns a list containing the indices of val in the_list"""
...     retval = []
...     last = 0
...     while val in the_list[last:]:
...             i = the_list[last:].index(val)
...             retval.append(last + i)
...             last += i + 1
...     return retval
...
>>> l = ['bar','foo','bar','baz','bar','bar']
>>> q = 'bar'
>>> print indices(l,q)
[0, 2, 4, 5]
>>> print indices(l,'bat')
[]
>>> print indices('abcdaababb','a')
[0, 4, 5, 7]
>>>
``````

# Update

After another year of heads-down python development, I’m a bit embarrassed by my original answer, so to set the record straight, one can certainly use the above code; however, the much more idiomatic way to get the same behavior would be to use list comprehension, along with the enumerate() function.

Something like this:

``````def indices(l, val):
"""Always returns a list containing the indices of val in the_list"""
return [index for index, value in enumerate(l) if value == val]

l = ['bar','foo','bar','baz','bar','bar']
q = 'bar'
print indices(l,q)
print indices(l,'bat')
print indices('abcdaababb','a')
``````

Which, when pasted into an interactive python window yields:

``````Python 2.7.14 |Anaconda, Inc.| (default, Dec  7 2017, 11:07:58)
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
>>> def indices(l, val):
...     """Always returns a list containing the indices of val in the_list"""
...     return [index for index, value in enumerate(l) if value == val]
...
>>> l = ['bar','foo','bar','baz','bar','bar']
>>> q = 'bar'
>>> print indices(l,q)
[0, 2, 4, 5]
>>> print indices(l,'bat')
[]
>>> print indices('abcdaababb','a')
[0, 4, 5, 7]
>>>
``````

And now, after reviewing this question and all the answers, I realize that this is exactly what FMc suggested in his earlier answer. At the time I originally answered this question, I didn’t even see that answer, because I didn’t understand it. I hope that my somewhat more verbose example will aid understanding.

If the single line of code above still doesn’t make sense to you, I highly recommend you Google ‘python list comprehension’ and take a few minutes to familiarize yourself. It’s just one of the many powerful features that make it a joy to use Python to develop code.

## 回答 16

FMc和user7177的答案的变体将给出一个字典，该字典可以返回任何条目的所有索引：

``````>>> a = ['foo','bar','baz','bar','any', 'foo', 'much']
>>> l = dict(zip(set(a), map(lambda y: [i for i,z in enumerate(a) if z is y ], set(a))))
>>> l['foo']
[0, 5]
>>> l ['much']
[6]
>>> l
{'baz': [2], 'foo': [0, 5], 'bar': [1, 3], 'any': [4], 'much': [6]}
>>> ``````

A variant on the answer from FMc and user7177 will give a dict that can return all indices for any entry:

``````>>> a = ['foo','bar','baz','bar','any', 'foo', 'much']
>>> l = dict(zip(set(a), map(lambda y: [i for i,z in enumerate(a) if z is y ], set(a))))
>>> l['foo']
[0, 5]
>>> l ['much']
[6]
>>> l
{'baz': [2], 'foo': [0, 5], 'bar': [1, 3], 'any': [4], 'much': [6]}
>>>
``````

You could also use this as a one liner to get all indices for a single entry. There are no guarantees for efficiency, though I did use set(a) to reduce the number of times the lambda is called.

## 回答 17

``````def find_element(p,t):
i = 0
for e in p:
if e == t:
return i
else:
i +=1
return -1``````

This solution is not as powerful as others, but if you’re a beginner and only know about `for`loops it’s still possible to find the first index of an item while avoiding the ValueError:

``````def find_element(p,t):
i = 0
for e in p:
if e == t:
return i
else:
i +=1
return -1
``````

## 回答 18

``idx = L.index(x) if (x in L) else -1``

Finding index of item x in list L:

``````idx = L.index(x) if (x in L) else -1
``````

## 回答 19

``>>> [i for i,j in zip(range(len(haystack)), haystack) if j == 'needle' ]``

（注意：这里我们使用i进行迭代以获取索引，但是如果我们需要专注于项目，可以切换到j。）

Since Python lists are zero-based, we can use the zip built-in function as follows:

``````>>> [i for i,j in zip(range(len(haystack)), haystack) if j == 'needle' ]
``````

where “haystack” is the list in question and “needle” is the item to look for.

(Note: Here we are iterating using i to get the indexes, but if we need rather to focus on the items we can switch to j.)

## 回答 20

``````name ="bar"
list = [["foo", 1], ["bar", 2], ["baz", 3]]
new_list=[]
for item in list:
new_list.append(item[0])
print(new_list)
try:
location= new_list.index(name)
except:
location=-1
print (location)``````

``````name ="bar"
list = [["foo", 1], ["bar", 2], ["baz", 3]]
new_list=[]
for item in list:
new_list.append(item[0])
print(new_list)
try:
location= new_list.index(name)
except:
location=-1
print (location)
``````

This accounts for if the string is not in the list too, if it isn’t in the list then `location = -1`

## 回答 21

`index()`如果找不到该项目，Python 方法将引发错误。因此，相反，您可以使其类似于`indexOf()`JavaScript 的功能，`-1`如果未找到该项目，它将返回：

``````try:
index = array.index('search_keyword')
except ValueError:
index = -1``````

Python `index()` method throws an error if the item was not found. So instead you can make it similar to the `indexOf()` function of JavaScript which returns `-1` if the item was not found:

``````try:
index = array.index('search_keyword')
except ValueError:
index = -1
``````

## 回答 22

``list(filter(lambda x: x[1]=="bar",enumerate(["foo", "bar", "baz", "bar", "baz", "bar", "a", "b", "c"])))``

``````def get_index_of(lst, element):
return list(map(lambda x: x[0],\
(list(filter(lambda x: x[1]==element, enumerate(lst))))))``````

There is a more functional answer to this.

``````list(filter(lambda x: x[1]=="bar",enumerate(["foo", "bar", "baz", "bar", "baz", "bar", "a", "b", "c"])))
``````

More generic form:

``````def get_index_of(lst, element):
return list(map(lambda x: x[0],\
(list(filter(lambda x: x[1]==element, enumerate(lst))))))
``````

## 回答 23

``````import numpy as np

lst = ["foo", "bar", "baz"]  #lst: : 'list' data type
print np.where( np.array(lst) == 'bar')[0][0]

>>> 1``````

Let’s give the name `lst` to the list that you have. One can convert the list `lst` to a `numpy array`. And, then use numpy.where to get the index of the chosen item in the list. Following is the way in which you will implement it.

``````import numpy as np

lst = ["foo", "bar", "baz"]  #lst: : 'list' data type
print np.where( np.array(lst) == 'bar')[0][0]

>>> 1
``````

## 回答 24

``````mylist = ["foo", "bar", "baz", "bar"]
newlist = enumerate(mylist)
for index, item in newlist:
if item == "bar":
print(index, item)``````

For those coming from another language like me, maybe with a simple loop it’s easier to understand and use it:

``````mylist = ["foo", "bar", "baz", "bar"]
newlist = enumerate(mylist)
for index, item in newlist:
if item == "bar":
print(index, item)
``````

I am thankful for So what exactly does enumerate do?. That helped me to understand.

## 回答 25

``````import bisect
from timeit import timeit

def bisect_search(container, value):
return (
index
if (index := bisect.bisect_left(container, value)) < len(container)
and container[index] == value else -1
)

data = list(range(1000))
# value to search
value = 666

# times to test
ttt = 1000

t1 = timeit(lambda: data.index(value), number=ttt)
t2 = timeit(lambda: bisect_search(data, value), number=ttt)

print(f"{t1=:.4f}, {t2=:.4f}, diffs {t1/t2=:.2f}")``````

``t1=0.0400, t2=0.0020, diffs t1/t2=19.60``

If you are going to find an index once then using “index” method is fine. However, if you are going to search your data more than once then I recommend using bisect module. Keep in mind that using bisect module data must be sorted. So you sort data once and then you can use bisect. Using bisect module on my machine is about 20 times faster than using index method.

Here is an example of code using Python 3.8 and above syntax:

``````import bisect
from timeit import timeit

def bisect_search(container, value):
return (
index
if (index := bisect.bisect_left(container, value)) < len(container)
and container[index] == value else -1
)

data = list(range(1000))
# value to search
value = 666

# times to test
ttt = 1000

t1 = timeit(lambda: data.index(value), number=ttt)
t2 = timeit(lambda: bisect_search(data, value), number=ttt)

print(f"{t1=:.4f}, {t2=:.4f}, diffs {t1/t2=:.2f}")
``````

Output:

``````t1=0.0400, t2=0.0020, diffs t1/t2=19.60
``````

# 如果性能值得关注：

``````myList = ["foo", "bar", "baz"]

# Create the dictionary
myDict = dict((e,i) for i,e in enumerate(myList))

# Lookup
myDict["bar"] # Returns 1
# myDict.get("blah") if you don't want an error to be raised if element not found.``````

``````from collections import defaultdict as dd
myList = ["foo", "bar", "bar", "baz", "foo"]

# Create the dictionary
myDict = dd(list)
for i,e in enumerate(myList):
myDict[e].append(i)

# Lookup
myDict["foo"] # Returns [0, 4]``````

# If performance is of concern:

It is mentioned in numerous answers that the built-in method of `list.index(item)` method is an O(n) algorithm. It is fine if you need to perform this once. But if you need to access the indices of elements a number of times, it makes more sense to first create a dictionary (O(n)) of item-index pairs, and then access the index at O(1) every time you need it.

If you are sure that the items in your list are never repeated, you can easily:

``````myList = ["foo", "bar", "baz"]

# Create the dictionary
myDict = dict((e,i) for i,e in enumerate(myList))

# Lookup
myDict["bar"] # Returns 1
# myDict.get("blah") if you don't want an error to be raised if element not found.
``````

If you may have duplicate elements, and need to return all of their indices:

``````from collections import defaultdict as dd
myList = ["foo", "bar", "bar", "baz", "foo"]

# Create the dictionary
myDict = dd(list)
for i,e in enumerate(myList):
myDict[e].append(i)

# Lookup
myDict["foo"] # Returns [0, 4]
``````

## 回答 27

`more_itertools`是一个第三方库，具有用于在可迭代对象中定位多个索引的工具。

``````import more_itertools as mit

iterable = ["foo", "bar", "baz", "ham", "foo", "bar", "baz"]``````

``````list(mit.locate(iterable, lambda x: x == "bar"))
# [1, 5]``````

``````list(mit.locate(iterable, lambda x: x in {"bar", "ham"}))
# [1, 3, 5]``````

As indicated by @TerryA, many answers discuss how to find one index.

`more_itertools` is a third-party library with tools to locate multiple indices within an iterable.

Given

``````import more_itertools as mit

iterable = ["foo", "bar", "baz", "ham", "foo", "bar", "baz"]
``````

Code

Find indices of multiple observations:

``````list(mit.locate(iterable, lambda x: x == "bar"))
# [1, 5]
``````

Test multiple items:

``````list(mit.locate(iterable, lambda x: x in {"bar", "ham"}))
# [1, 3, 5]
``````

See also more options with `more_itertools.locate`. Install via `> pip install more_itertools`.

## 回答 28

``````from collections import defaultdict

index_dict = defaultdict(list)
word_list =  ['foo','bar','baz','bar','any', 'foo', 'much']

for word_index in range(len(word_list)) :
index_dict[word_list[word_index]].append(word_index)

word_index_to_find = 'foo'
print(index_dict[word_index_to_find])

# output :  [0, 5]``````

using dictionary , where process the list first and then add the index to it

``````from collections import defaultdict

index_dict = defaultdict(list)
word_list =  ['foo','bar','baz','bar','any', 'foo', 'much']

for word_index in range(len(word_list)) :
index_dict[word_list[word_index]].append(word_index)

word_index_to_find = 'foo'
print(index_dict[word_index_to_find])

# output :  [0, 5]
``````

## 回答 29

``````def find_index(arr, name):
try:
return arr.index(name)
except ValueError:
return -1

if __name__ == '__main__':
print(find_index(["foo", "bar", "baz"], "bar"))``````

1个

-1

in my opinion the `["foo", "bar", "baz"].index("bar")` is good but it isn’t enough!because if “bar” isn’t in dictionary,`ValueError` raised.So you can use this function:

``````def find_index(arr, name):
try:
return arr.index(name)
except ValueError:
return -1

if __name__ == '__main__':
print(find_index(["foo", "bar", "baz"], "bar"))
``````

and the result is:

1

and if name wasn’t at arr,the function return -1.for example:

print(find_index([“foo”, “bar”, “baz”], “fooo”))

-1

# Python的list方法append和extend有什么区别？

## 问题：Python的list方法append和extend有什么区别？

What’s the difference between the list methods `append()` and `extend()`?

## 回答 0

`append`：在末尾追加对象。

``````x = [1, 2, 3]
x.append([4, 5])
print (x)``````

`extend`：通过附加来自iterable的元素来扩展列表。

``````x = [1, 2, 3]
x.extend([4, 5])
print (x)``````

`append`: Appends object at the end.

``````x = [1, 2, 3]
x.append([4, 5])
print (x)
``````

gives you: `[1, 2, 3, [4, 5]]`

`extend`: Extends list by appending elements from the iterable.

``````x = [1, 2, 3]
x.extend([4, 5])
print (x)
``````

gives you: `[1, 2, 3, 4, 5]`

## 回答 1

`append`将元素添加到列表，并将`extend`第一个列表与另一个列表（或另一个可迭代的列表，不一定是列表）连接。

``````>>> li = ['a', 'b', 'mpilgrim', 'z', 'example']
>>> li
['a', 'b', 'mpilgrim', 'z', 'example']

>>> li.append("new")
>>> li
['a', 'b', 'mpilgrim', 'z', 'example', 'new']

>>> li.append(["new", 2])
>>> li
['a', 'b', 'mpilgrim', 'z', 'example', 'new', ['new', 2]]

>>> li.insert(2, "new")
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', ['new', 2]]

>>> li.extend(["two", "elements"])
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', ['new', 2], 'two', 'elements']``````

`append` adds an element to a list, and `extend` concatenates the first list with another list (or another iterable, not necessarily a list.)

``````>>> li = ['a', 'b', 'mpilgrim', 'z', 'example']
>>> li
['a', 'b', 'mpilgrim', 'z', 'example']

>>> li.append("new")
>>> li
['a', 'b', 'mpilgrim', 'z', 'example', 'new']

>>> li.append(["new", 2])
>>> li
['a', 'b', 'mpilgrim', 'z', 'example', 'new', ['new', 2]]

>>> li.insert(2, "new")
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', ['new', 2]]

>>> li.extend(["two", "elements"])
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', ['new', 2], 'two', 'elements']
``````

## 列表方法追加和扩展之间有什么区别？

• `append`将其参数作为单个元素添加到列表的末尾。列表本身的长度将增加一。
• `extend`遍历其参数，将每个元素添加到列表，扩展列表。无论迭代参数中有多少元素，列表的长度都会增加。

## `append`

`list.append`方法将一个对象附加到列表的末尾。

``my_list.append(object) ``

``````>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']``````

``````>>> another_list = [1, 2, 3]
>>> my_list.append(another_list)
>>> my_list
['foo', 'bar', 'baz', [1, 2, 3]]
#^^^^^^^^^--- single item at the end of the list.``````

## `extend`

`list.extend`方法通过附加来自可迭代对象的元素来扩展列表：

``my_list.extend(iterable)``

``````>>> my_list
['foo', 'bar']
>>> another_list = [1, 2, 3]
>>> my_list.extend(another_list)
>>> my_list
['foo', 'bar', 1, 2, 3]``````

``````>>> my_list.extend('baz')
>>> my_list
['foo', 'bar', 1, 2, 3, 'b', 'a', 'z']``````

## 运算符重载，`__add__`（`+`）和`__iadd__`（`+=`）

`my_list + another_list` 在内存中创建第三个列表，因此您可以返回它的结果，但是它要求第二个可迭代的列表。

`my_list += another_list`就地修改列表（如我们所见，它就地运算符，并且列表是可变对象），因此不会创建新列表。它也像扩展一样工作，因为第二个可迭代对象可以是任何一种可迭代对象。

## 性能

``````def append(alist, iterable):
for item in iterable:
alist.append(item)

def extend(alist, iterable):
alist.extend(iterable)``````

``````import timeit

>>> min(timeit.repeat(lambda: append([], "abcdefghijklmnopqrstuvwxyz")))
2.867846965789795
>>> min(timeit.repeat(lambda: extend([], "abcdefghijklmnopqrstuvwxyz")))
0.8060121536254883``````

### 在时间上发表评论

``````def append_one(a_list, element):
a_list.append(element)

def extend_one(a_list, element):
"""creating a new list is semantically the most direct
way to create an iterable to give to extend"""
a_list.extend([element])

import timeit``````

``````>>> min(timeit.repeat(lambda: append_one([], 0)))
0.2082819009956438
>>> min(timeit.repeat(lambda: extend_one([], 0)))
0.2397019260097295``````

## What is the difference between the list methods append and extend?

• `append` adds its argument as a single element to the end of a list. The length of the list itself will increase by one.
• `extend` iterates over its argument adding each element to the list, extending the list. The length of the list will increase by however many elements were in the iterable argument.

## `append`

The `list.append` method appends an object to the end of the list.

``````my_list.append(object)
``````

Whatever the object is, whether a number, a string, another list, or something else, it gets added onto the end of `my_list` as a single entry on the list.

``````>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']
``````

So keep in mind that a list is an object. If you append another list onto a list, the first list will be a single object at the end of the list (which may not be what you want):

``````>>> another_list = [1, 2, 3]
>>> my_list.append(another_list)
>>> my_list
['foo', 'bar', 'baz', [1, 2, 3]]
#^^^^^^^^^--- single item at the end of the list.
``````

## `extend`

The `list.extend` method extends a list by appending elements from an iterable:

``````my_list.extend(iterable)
``````

So with extend, each element of the iterable gets appended onto the list. For example:

``````>>> my_list
['foo', 'bar']
>>> another_list = [1, 2, 3]
>>> my_list.extend(another_list)
>>> my_list
['foo', 'bar', 1, 2, 3]
``````

Keep in mind that a string is an iterable, so if you extend a list with a string, you’ll append each character as you iterate over the string (which may not be what you want):

``````>>> my_list.extend('baz')
>>> my_list
['foo', 'bar', 1, 2, 3, 'b', 'a', 'z']
``````

## Operator Overload, `__add__` (`+`) and `__iadd__` (`+=`)

Both `+` and `+=` operators are defined for `list`. They are semantically similar to extend.

`my_list + another_list` creates a third list in memory, so you can return the result of it, but it requires that the second iterable be a list.

`my_list += another_list` modifies the list in-place (it is the in-place operator, and lists are mutable objects, as we’ve seen) so it does not create a new list. It also works like extend, in that the second iterable can be any kind of iterable.

Don’t get confused – `my_list = my_list + another_list` is not equivalent to `+=` – it gives you a brand new list assigned to my_list.

## Time Complexity

Append has constant time complexity, O(1).

Extend has time complexity, O(k).

Iterating through the multiple calls to `append` adds to the complexity, making it equivalent to that of extend, and since extend’s iteration is implemented in C, it will always be faster if you intend to append successive items from an iterable onto a list.

## Performance

You may wonder what is more performant, since append can be used to achieve the same outcome as extend. The following functions do the same thing:

``````def append(alist, iterable):
for item in iterable:
alist.append(item)

def extend(alist, iterable):
alist.extend(iterable)
``````

So let’s time them:

``````import timeit

>>> min(timeit.repeat(lambda: append([], "abcdefghijklmnopqrstuvwxyz")))
2.867846965789795
>>> min(timeit.repeat(lambda: extend([], "abcdefghijklmnopqrstuvwxyz")))
0.8060121536254883
``````

### Addressing a comment on timings

A commenter said:

Perfect answer, I just miss the timing of comparing adding only one element

Do the semantically correct thing. If you want to append all elements in an iterable, use `extend`. If you’re just adding one element, use `append`.

Ok, so let’s create an experiment to see how this works out in time:

``````def append_one(a_list, element):
a_list.append(element)

def extend_one(a_list, element):
"""creating a new list is semantically the most direct
way to create an iterable to give to extend"""
a_list.extend([element])

import timeit
``````

And we see that going out of our way to create an iterable just to use extend is a (minor) waste of time:

``````>>> min(timeit.repeat(lambda: append_one([], 0)))
0.2082819009956438
>>> min(timeit.repeat(lambda: extend_one([], 0)))
0.2397019260097295
``````

We learn from this that there’s nothing gained from using `extend` when we have only one element to append.

Also, these timings are not that important. I am just showing them to make the point that, in Python, doing the semantically correct thing is doing things the Right Way™.

It’s conceivable that you might test timings on two comparable operations and get an ambiguous or inverse result. Just focus on doing the semantically correct thing.

## Conclusion

We see that `extend` is semantically clearer, and that it can run much faster than `append`, when you intend to append each element in an iterable to a list.

If you only have a single element (not in an iterable) to add to the list, use `append`.

## 回答 3

`append`追加一个元素。`extend`追加元素列表。

``````>>> a = [1, 2, 3]
>>> a.append([4, 5, 6])
>>> a
[1, 2, 3, [4, 5, 6]]``````

`append` appends a single element. `extend` appends a list of elements.

Note that if you pass a list to append, it still adds one element:

``````>>> a = [1, 2, 3]
>>> a.append([4, 5, 6])
>>> a
[1, 2, 3, [4, 5, 6]]
``````

# 追加与扩充

``````>>> a = [1,2]
>>> a.append(3)
>>> a
[1,2,3]``````

``````>>> a.append([4,5])
>>> a
>>> [1,2,3,[4,5]]``````

``````>>> a = [1,2]
>>> a.extend([3])
>>> a
[1,2,3]``````

``````>>> a.extend([4,5,6])
>>> a
[1,2,3,4,5,6]``````

# 两种方法都添加一个元素

## 追加1个元素

``````>>> x = [1,2]
>>> x.append(3)
>>> x
[1,2,3]``````

## 扩展一个元素

``````>>> x = [1,2]
>>> x.extend([3])
>>> x
[1,2,3]``````

# 添加更多元素…结果不同

``````>>> x = [1,2]
>>> x.append([3,4])
>>> x
[1,2,[3,4]]``````

``````>>> z = [1,2]
>>> z.extend([3,4])
>>> z
[1,2,3,4]``````

# Append vs Extend

With append you can append a single element that will extend the list:

``````>>> a = [1,2]
>>> a.append(3)
>>> a
[1,2,3]
``````

If you want to extend more than one element you should use extend, because you can only append one elment or one list of element:

``````>>> a.append([4,5])
>>> a
>>> [1,2,3,[4,5]]
``````

So that you get a nested list

Instead with extend, you can extend a single element like this

``````>>> a = [1,2]
>>> a.extend([3])
>>> a
[1,2,3]
``````

Or, differently, from append, extend more elements in one time without nesting the list into the original one (that’s the reason of the name extend)

``````>>> a.extend([4,5,6])
>>> a
[1,2,3,4,5,6]
``````

# Adding one element with both methods

Both append and extend can add one element to the end of the list, though append is simpler.

## append 1 element

``````>>> x = [1,2]
>>> x.append(3)
>>> x
[1,2,3]
``````

## extend one element

``````>>> x = [1,2]
>>> x.extend([3])
>>> x
[1,2,3]
``````

# Adding more elements… with different results

If you use append for more than one element, you have to pass a list of elements as arguments and you will obtain a NESTED list!

``````>>> x = [1,2]
>>> x.append([3,4])
>>> x
[1,2,[3,4]]
``````

With extend, instead, you pass a list as an argument, but you will obtain a list with the new element that is not nested in the old one.

``````>>> z = [1,2]
>>> z.extend([3,4])
>>> z
[1,2,3,4]
``````

So, with more elements, you will use extend to get a list with more items. However, appending a list will not add more elements to the list, but one element that is a nested list as you can clearly see in the output of the code.

## 回答 5

``````for item in iterator:
a_list.append(item)``````

``a_list.extend(iterator)``

The following two snippets are semantically equivalent:

``````for item in iterator:
a_list.append(item)
``````

and

``````a_list.extend(iterator)
``````

The latter may be faster as the loop is implemented in C.

## 回答 6

`append()`方法将单个项目添加到列表的末尾。

``````x = [1, 2, 3]
x.append([4, 5])
x.append('abc')
print(x)
# gives you
[1, 2, 3, [4, 5], 'abc']``````

`extend()`方法采用一个参数，一个列表，并将该参数的每个项目附加到原始列表中。（列表以类的形式实现。“创建”列表实际上是在实例化一个类。因此，列表具有对其进行操作的方法。）

``````x = [1, 2, 3]
x.extend([4, 5])
x.extend('abc')
print(x)
# gives you
[1, 2, 3, 4, 5, 'a', 'b', 'c']``````

The `append()` method adds a single item to the end of the list.

``````x = [1, 2, 3]
x.append([4, 5])
x.append('abc')
print(x)
# gives you
[1, 2, 3, [4, 5], 'abc']
``````

The `extend()` method takes one argument, a list, and appends each of the items of the argument to the original list. (Lists are implemented as classes. “Creating” a list is really instantiating a class. As such, a list has methods that operate on it.)

``````x = [1, 2, 3]
x.extend([4, 5])
x.extend('abc')
print(x)
# gives you
[1, 2, 3, 4, 5, 'a', 'b', 'c']
``````

From Dive Into Python.

## 回答 7

``````l1=range(10)

l1+[11]

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11]

l2=range(10,1,-1)

l1+l2

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2]``````

`+=`就地行为类似，但与`append`＆略有不同`extend`。其中一个最大的不同`+=`，从`append``extend`是当它在功能范围时，看到这个博客帖子

You can use “+” for returning extend, instead of extending in place.

``````l1=range(10)

l1+[11]

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11]

l2=range(10,1,-1)

l1+l2

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2]
``````

Similarly `+=` for in place behavior, but with slight differences from `append` & `extend`. One of the biggest differences of `+=` from `append` and `extend` is when it is used in function scopes, see this blog post.

## 回答 8

`append(object)` -通过将对象添加到列表来更新列表。

``````x = [20]
# List passed to the append(object) method is treated as a single object.
x.append([21, 22, 23])
# Hence the resultant list length will be 2
print(x)
--> [20, [21, 22, 23]]``````

`extend(list)` -本质上是串联两个列表。

``````x = [20]
# The parameter passed to extend(list) method is treated as a list.
# Eventually it is two lists being concatenated.
x.extend([21, 22, 23])
# Here the resultant list's length is 4
print(x)
[20, 21, 22, 23]``````

`append(object)` – Updates the list by adding an object to the list.

``````x = [20]
# List passed to the append(object) method is treated as a single object.
x.append([21, 22, 23])
# Hence the resultant list length will be 2
print(x)
--> [20, [21, 22, 23]]
``````

`extend(list)` – Essentially concatenates two lists.

``````x = [20]
# The parameter passed to extend(list) method is treated as a list.
# Eventually it is two lists being concatenated.
x.extend([21, 22, 23])
# Here the resultant list's length is 4
print(x)
[20, 21, 22, 23]
``````

## 回答 9

`extend()`可以与迭代器参数一起使用。这是一个例子。您希望通过以下方式从列表列表中列出一个列表：

``list2d = [[1,2,3],[4,5,6], [7], [8,9]]``

``````>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]``````

``````def from_iterable(iterables):
# chain.from_iterable(['ABC', 'DEF']) --> A B C D E F
for it in iterables:
for element in it:
yield element``````

``````import itertools
list2d = [[1,2,3],[4,5,6], [7], [8,9]]
merged = list(itertools.chain.from_iterable(list2d))``````

``````merged = []
merged.extend(itertools.chain.from_iterable(list2d))
print(merged)
>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]``````

`extend()` can be used with an iterator argument. Here is an example. You wish to make a list out of a list of lists this way:

From

``````list2d = [[1,2,3],[4,5,6], [7], [8,9]]
``````

you want

``````>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]
``````

You may use `itertools.chain.from_iterable()` to do so. This method’s output is an iterator. Its implementation is equivalent to

``````def from_iterable(iterables):
# chain.from_iterable(['ABC', 'DEF']) --> A B C D E F
for it in iterables:
for element in it:
yield element
``````

Back to our example, we can do

``````import itertools
list2d = [[1,2,3],[4,5,6], [7], [8,9]]
merged = list(itertools.chain.from_iterable(list2d))
``````

and get the wanted list.

Here is how equivalently `extend()` can be used with an iterator argument:

``````merged = []
merged.extend(itertools.chain.from_iterable(list2d))
print(merged)
>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]
``````

## 回答 10

``````>>> x = [1,2,3]
>>> x
[1, 2, 3]
>>> x = x + [4,5,6] # Extend
>>> x
[1, 2, 3, 4, 5, 6]
>>> x = x + [[7,8]] # Append
>>> x
[1, 2, 3, 4, 5, 6, [7, 8]]``````

This is the equivalent of `append` and `extend` using the `+` operator:

``````>>> x = [1,2,3]
>>> x
[1, 2, 3]
>>> x = x + [4,5,6] # Extend
>>> x
[1, 2, 3, 4, 5, 6]
>>> x = x + [[7,8]] # Append
>>> x
[1, 2, 3, 4, 5, 6, [7, 8]]
``````

## 回答 11

append（）：基本上在Python中用于添加一个元素。

``````>> a = [1, 2, 3, 4]
>> a.append(5)
>> print(a)
>> a = [1, 2, 3, 4, 5]``````

``````>> a = [1, 2, 3, 4]
>> a.append([5, 6])
>> print(a)
>> a = [1, 2, 3, 4, [5, 6]]``````

extend（）：extend（）用于合并两个列表或在一个列表中插入多个元素。

``````>> a = [1, 2, 3, 4]
>> b = [5, 6, 7, 8]
>> a.extend(b)
>> print(a)
>> a = [1, 2, 3, 4, 5, 6, 7, 8]``````

``````>> a = [1, 2, 3, 4]
>> a.extend([5, 6])
>> print(a)
>> a = [1, 2, 3, 4, 5, 6]``````

append(): It is basically used in Python to add one element.

Example 1:

``````>> a = [1, 2, 3, 4]
>> a.append(5)
>> print(a)
>> a = [1, 2, 3, 4, 5]
``````

Example 2:

``````>> a = [1, 2, 3, 4]
>> a.append([5, 6])
>> print(a)
>> a = [1, 2, 3, 4, [5, 6]]
``````

extend(): Where extend(), is used to merge two lists or insert multiple elements in one list.

Example 1:

``````>> a = [1, 2, 3, 4]
>> b = [5, 6, 7, 8]
>> a.extend(b)
>> print(a)
>> a = [1, 2, 3, 4, 5, 6, 7, 8]
``````

Example 2:

``````>> a = [1, 2, 3, 4]
>> a.extend([5, 6])
>> print(a)
>> a = [1, 2, 3, 4, 5, 6]
``````

## 回答 12

An interesting point that has been hinted, but not explained, is that extend is faster than append. For any loop that has append inside should be considered to be replaced by list.extend(processed_elements).

Bear in mind that apprending new elements might result in the realloaction of the whole list to a better location in memory. If this is done several times because we are appending 1 element at a time, overall performance suffers. In this sense, list.extend is analogous to “”.join(stringlist).

## 回答 13

Append一次添加全部数据。整个数据将被添加到新创建的索引中。另一方面，`extend`顾名思义，扩展了当前数组。

``````list1 = [123, 456, 678]
list2 = [111, 222]``````

``result = [123, 456, 678, [111, 222]]``

`extend`我们得到：

``result = [123, 456, 678, 111, 222]``

Append adds the entire data at once. The whole data will be added to the newly created index. On the other hand, `extend`, as it name suggests, extends the current array.

For example

``````list1 = [123, 456, 678]
list2 = [111, 222]
``````

With `append` we get:

``````result = [123, 456, 678, [111, 222]]
``````

While on `extend` we get:

``````result = [123, 456, 678, 111, 222]
``````

## 回答 14

append：在书面文档的末尾添加（某些内容）。

1）之间的区别`append``extend`

`append`

• 所有Python对象原样追加到列表的末尾（即，作为列表中的最后一个元素）。
• 结果列表可以嵌套，并包含异构元素（即列表，字符串，元组，字典，集合等）。

`extend`

• 接受任何iterable作为其参数，并使列表更大
• 结果列表始终是一维列表（即无嵌套），由于apply的结果，列表中可能包含异类元素（例如，字符，整数，浮点数）`list(iterable)`

2）之间的相似性`append``extend`

• 两者都只是一个论点。
• 两者都就地修改列表。
• 结果，两个都返回`None`

``````lis = [1, 2, 3]

# 'extend' is equivalent to this
lis = lis + list(iterable)

# 'append' simply appends its argument as the last element to the list
# as long as the argument is a valid Python object
list.append(object)``````

An English dictionary defines the words `append` and `extend` as:

append: add (something) to the end of a written document.
extend: make larger. Enlarge or expand

With that knowledge, now let’s understand

1) The difference between `append` and `extend`

`append`:

• Appends any Python object as-is to the end of the list (i.e. as a the last element in the list).
• The resulting list may be nested and contain heterogeneous elements (i.e. list, string, tuple, dictionary, set, etc.)

`extend`:

• Accepts any iterable as its argument and makes the list larger.
• The resulting list is always one-dimensional list (i.e. no nesting) and it may contain heterogeneous elements in it (e.g. characters, integers, float) as a result of applying `list(iterable)`.

2) Similarity between `append` and `extend`

• Both take exactly one argument.
• Both modify the list in-place.
• As a result, both returns `None`.

Example

``````lis = [1, 2, 3]

# 'extend' is equivalent to this
lis = lis + list(iterable)

# 'append' simply appends its argument as the last element to the list
# as long as the argument is a valid Python object
list.append(object)
``````

## 回答 15

TypeError：“ Info”对象不可迭代

I hope I can make a useful supplement to this question. If your list stores a specific type object, for example `Info`, here is a situation that `extend` method is not suitable: In a `for` loop and and generating an `Info` object every time and using `extend` to store it into your list, it will fail. The exception is like below:

TypeError: ‘Info’ object is not iterable

But if you use the `append` method, the result is OK. Because every time using the `extend` method, it will always treat it as a list or any other collection type, iterate it, and place it after the previous list. A specific object can not be iterated, obviously.

## 回答 16

``````l1 = ['a', 'b', 'c']
l2 = ['d', 'e', 'f']
l1.append(l2)
l1
['a', 'b', 'c', ['d', 'e', 'f']]``````

``````# Reset l1 = ['a', 'b', 'c']
l1.extend(l2)
l1
['a', 'b', 'c', 'd', 'e', 'f']``````

``````list_methods = {'Add': {'extend', 'append', 'insert'},
'Remove': {'pop', 'remove', 'clear'}
'Sort': {'reverse', 'sort'},
'Search': {'count', 'index'},
'Copy': {'copy'},
}``````

To distinguish them intuitively

``````l1 = ['a', 'b', 'c']
l2 = ['d', 'e', 'f']
l1.append(l2)
l1
['a', 'b', 'c', ['d', 'e', 'f']]
``````

It’s like `l1` reproduce a body inside her body(nested).

``````# Reset l1 = ['a', 'b', 'c']
l1.extend(l2)
l1
['a', 'b', 'c', 'd', 'e', 'f']
``````

It’s like that two separated individuals get married and construct an united family.

Besides I make an exhaustive cheatsheet of all list’s methods for your reference.

``````list_methods = {'Add': {'extend', 'append', 'insert'},
'Remove': {'pop', 'remove', 'clear'}
'Sort': {'reverse', 'sort'},
'Search': {'count', 'index'},
'Copy': {'copy'},
}
``````

## 回答 17

`extend(L)`通过在给定列表中追加所有项目来扩展列表`L`

``````>>> a
[1, 2, 3]
a.extend([4])  #is eqivalent of a[len(a):] = [4]
>>> a
[1, 2, 3, 4]
a = [1, 2, 3]
>>> a
[1, 2, 3]
>>> a[len(a):] = [4]
>>> a
[1, 2, 3, 4]``````

`extend(L)` extends the list by appending all the items in the given list `L`.

``````>>> a
[1, 2, 3]
a.extend([4])  #is eqivalent of a[len(a):] = [4]
>>> a
[1, 2, 3, 4]
a = [1, 2, 3]
>>> a
[1, 2, 3]
>>> a[len(a):] = [4]
>>> a
[1, 2, 3, 4]
``````

## 回答 18

`append`列表仅将一项 “扩展”（就地），即传递的单个对象（作为参数）。

`extend`“扩展”的名单（到位）尽可能多的项目对象传递（作为参数）包含的内容。

1. 如果您将字符串作为参数传递： `append`将在末尾添加单个字符串项，但 `extend`将添加与该字符串的长度一样多的“单个”“ str”项。
2. 如果您将字符串列表作为参数传递：： `append`仍将在末尾添加单个“列表”项， `extend`并将添加与所传递列表的长度一样多的“列表”项。
``````def append_o(a_list, element):
a_list.append(element)
print('append:', end = ' ')
for item in a_list:
print(item, end = ',')
print()

def extend_o(a_list, element):
a_list.extend(element)
print('extend:', end = ' ')
for item in a_list:
print(item, end = ',')
print()
append_o(['ab'],'cd')

extend_o(['ab'],'cd')
append_o(['ab'],['cd', 'ef'])
extend_o(['ab'],['cd', 'ef'])
append_o(['ab'],['cd'])
extend_o(['ab'],['cd'])``````

``````append: ab,cd,
extend: ab,c,d,
append: ab,['cd', 'ef'],
extend: ab,cd,ef,
append: ab,['cd'],
extend: ab,cd,``````

`append` “extends” the list (in place) by only one item, the single object passed (as argument).

`extend` “extends” the list (in place) by as many items as the object passed (as argument) contains.

This may be slightly confusing for `str` objects.

1. If you pass a string as argument: `append` will add a single string item at the end but `extend` will add as many “single” ‘str’ items as the length of that string.
2. If you pass a list of strings as argument: `append` will still add a single ‘list’ item at the end and `extend` will add as many ‘list’ items as the length of the passed list.
``````def append_o(a_list, element):
a_list.append(element)
print('append:', end = ' ')
for item in a_list:
print(item, end = ',')
print()

def extend_o(a_list, element):
a_list.extend(element)
print('extend:', end = ' ')
for item in a_list:
print(item, end = ',')
print()
append_o(['ab'],'cd')

extend_o(['ab'],'cd')
append_o(['ab'],['cd', 'ef'])
extend_o(['ab'],['cd', 'ef'])
append_o(['ab'],['cd'])
extend_o(['ab'],['cd'])
``````

produces:

``````append: ab,cd,
extend: ab,c,d,
append: ab,['cd', 'ef'],
extend: ab,cd,ef,
append: ab,['cd'],
extend: ab,cd,
``````

## 回答 19

``my_list = [1,2,3,4]``

``my_list.append(5)``

insert（index，object）的方法描述符。它有两个参数，第一个是我们要插入元素的索引，第二个是元素本身。

``````Example: my_list = [1,2,3,4]
my_list[4, 'a']
my_list
[1,2,3,4,'a']``````

``````a = [1,2]
b = [3]
a.append(b)
print (a)
[1,2,[3]]``````

``````a = [1,2]
b = [3]
a.extend(b)
print (a)
[1,2,3]``````

``````a = [1]
b = [2]
c = [3]
a.extend(b+c)
print (a)
[1,2,3]``````

Append and extend are one of the extensibility mechanisms in python.

Append: Adds an element to the end of the list.

``````my_list = [1,2,3,4]
``````

To add a new element to the list, we can use append method in the following way.

``````my_list.append(5)
``````

The default location that the new element will be added is always in the (length+1) position.

Insert: The insert method was used to overcome the limitations of append. With insert, we can explicitly define the exact position we want our new element to be inserted at.

Method descriptor of insert(index, object). It takes two arguments, first being the index we want to insert our element and second the element itself.

``````Example: my_list = [1,2,3,4]
my_list[4, 'a']
my_list
[1,2,3,4,'a']
``````

Extend: This is very useful when we want to join two or more lists into a single list. Without extend, if we want to join two lists, the resulting object will contain a list of lists.

``````a = [1,2]
b = [3]
a.append(b)
print (a)
[1,2,[3]]
``````

If we try to access the element at pos 2, we get a list ([3]), instead of the element. To join two lists, we’ll have to use append.

``````a = [1,2]
b = [3]
a.extend(b)
print (a)
[1,2,3]
``````

To join multiple lists

``````a = [1]
b = [2]
c = [3]
a.extend(b+c)
print (a)
[1,2,3]
``````

# 如何克隆或复制列表？

## 问题：如何克隆或复制列表？

What are the options to clone or copy a list in Python?

While using `new_list = my_list`, any modifications to `new_list` changes `my_list` everytime. Why is this?

## 回答 0

• 您可以使用内建`list.copy()`方法（自Python 3.3起可用）：

``new_list = old_list.copy()``
• 您可以将其切片：

``new_list = old_list[:]``

Alex Martelli对此看法（至少是在2007年）是，这是一种怪异的语法，永远不要使用它。;）（在他看来，下一个更具可读性）。

• 您可以使用内置`list()`函数：

``new_list = list(old_list)``
• 您可以使用generic `copy.copy()`

``````import copy
new_list = copy.copy(old_list)``````

这比`list()`因为必须找出`old_list`first 的数据类型慢一些。

• 如果列表包含对象，并且您也想复制它们，请使用generic `copy.deepcopy()`

``````import copy
new_list = copy.deepcopy(old_list)``````

显然，这是最慢且最需要内存的方法，但有时是不可避免的。

``````import copy

class Foo(object):
def __init__(self, val):
self.val = val

def __repr__(self):
return 'Foo({!r})'.format(self.val)

foo = Foo(1)

a = ['foo', foo]
b = a.copy()
c = a[:]
d = list(a)
e = copy.copy(a)
f = copy.deepcopy(a)

# edit orignal list and instance
a.append('baz')
foo.val = 5

print('original: %r\nlist.copy(): %r\nslice: %r\nlist(): %r\ncopy: %r\ndeepcopy: %r'
% (a, b, c, d, e, f))``````

``````original: ['foo', Foo(5), 'baz']
list.copy(): ['foo', Foo(5)]
slice: ['foo', Foo(5)]
list(): ['foo', Foo(5)]
copy: ['foo', Foo(5)]
deepcopy: ['foo', Foo(1)]``````

With `new_list = my_list`, you don’t actually have two lists. The assignment just copies the reference to the list, not the actual list, so both `new_list` and `my_list` refer to the same list after the assignment.

To actually copy the list, you have various possibilities:

• You can use the builtin `list.copy()` method (available since Python 3.3):

``````new_list = old_list.copy()
``````
• You can slice it:

``````new_list = old_list[:]
``````

Alex Martelli’s opinion (at least back in 2007) about this is, that it is a weird syntax and it does not make sense to use it ever. ;) (In his opinion, the next one is more readable).

• You can use the built in `list()` function:

``````new_list = list(old_list)
``````
• You can use generic `copy.copy()`:

``````import copy
new_list = copy.copy(old_list)
``````

This is a little slower than `list()` because it has to find out the datatype of `old_list` first.

• If the list contains objects and you want to copy them as well, use generic `copy.deepcopy()`:

``````import copy
new_list = copy.deepcopy(old_list)
``````

Obviously the slowest and most memory-needing method, but sometimes unavoidable.

Example:

``````import copy

class Foo(object):
def __init__(self, val):
self.val = val

def __repr__(self):
return 'Foo({!r})'.format(self.val)

foo = Foo(1)

a = ['foo', foo]
b = a.copy()
c = a[:]
d = list(a)
e = copy.copy(a)
f = copy.deepcopy(a)

# edit orignal list and instance
a.append('baz')
foo.val = 5

print('original: %r\nlist.copy(): %r\nslice: %r\nlist(): %r\ncopy: %r\ndeepcopy: %r'
% (a, b, c, d, e, f))
``````

Result:

``````original: ['foo', Foo(5), 'baz']
list.copy(): ['foo', Foo(5)]
slice: ['foo', Foo(5)]
list(): ['foo', Foo(5)]
copy: ['foo', Foo(5)]
deepcopy: ['foo', Foo(1)]
``````

## 回答 1

Felix已经提供了一个很好的答案，但是我想我将对各种方法进行速度比较：

1. 10.59秒（105.9us / itn）- `copy.deepcopy(old_list)`
2. 10.16秒（101.6us / itn）-使用Deepcopy `Copy()`复制类的纯python 方法
3. 1.488秒（14.88us / itn）-纯python `Copy()`方法不复制类（仅字典/列表/元组）
4. 0.325秒（3.25us / itn）- `for item in old_list: new_list.append(item)`
5. 0.217秒（2.17us / itn）- `[i for i in old_list]`列表理解
6. 0.186秒（1.86us / itn）- `copy.copy(old_list)`
7. 0.075秒（0.75us / itn）- `list(old_list)`
8. 0.053秒（0.53us / itn）- `new_list = []; new_list.extend(old_list)`
9. 0.039秒（0.39us / itn）- `old_list[:]`列表切片

（如果有人有兴趣或想提出任何问题，请使用以下脚本：）

``````from copy import deepcopy

class old_class:
def __init__(self):
self.blah = 'blah'

class new_class(object):
def __init__(self):
self.blah = 'blah'

dignore = {str: None, unicode: None, int: None, type(None): None}

def Copy(obj, use_deepcopy=True):
t = type(obj)

if t in (list, tuple):
if t == tuple:
# Convert to a list if a tuple to
# allow assigning to when copying
is_tuple = True
obj = list(obj)
else:
# Otherwise just do a quick slice copy
obj = obj[:]
is_tuple = False

# Copy each item recursively
for x in xrange(len(obj)):
if type(obj[x]) in dignore:
continue
obj[x] = Copy(obj[x], use_deepcopy)

if is_tuple:
# Convert back into a tuple again
obj = tuple(obj)

elif t == dict:
# Use the fast shallow dict copy() method and copy any
# values which aren't immutable (like lists, dicts etc)
obj = obj.copy()
for k in obj:
if type(obj[k]) in dignore:
continue
obj[k] = Copy(obj[k], use_deepcopy)

elif t in dignore:
# Numeric or string/unicode?
# It's immutable, so ignore it!
pass

elif use_deepcopy:
obj = deepcopy(obj)
return obj

if __name__ == '__main__':
import copy
from time import time

num_times = 100000
L = [None, 'blah', 1, 543.4532,
['foo'], ('bar',), {'blah': 'blah'},
old_class(), new_class()]

t = time()
for i in xrange(num_times):
Copy(L)
print 'Custom Copy:', time()-t

t = time()
for i in xrange(num_times):
Copy(L, use_deepcopy=False)
print 'Custom Copy Only Copying Lists/Tuples/Dicts (no classes):', time()-t

t = time()
for i in xrange(num_times):
copy.copy(L)
print 'copy.copy:', time()-t

t = time()
for i in xrange(num_times):
copy.deepcopy(L)
print 'copy.deepcopy:', time()-t

t = time()
for i in xrange(num_times):
L[:]
print 'list slicing [:]:', time()-t

t = time()
for i in xrange(num_times):
list(L)
print 'list(L):', time()-t

t = time()
for i in xrange(num_times):
[i for i in L]
print 'list expression(L):', time()-t

t = time()
for i in xrange(num_times):
a = []
a.extend(L)
print 'list extend:', time()-t

t = time()
for i in xrange(num_times):
a = []
for y in L:
a.append(y)
print 'list append:', time()-t

t = time()
for i in xrange(num_times):
a = []
a.extend(i for i in L)
print 'generator expression extend:', time()-t``````

Felix already provided an excellent answer, but I thought I’d do a speed comparison of the various methods:

1. 10.59 sec (105.9us/itn) – `copy.deepcopy(old_list)`
2. 10.16 sec (101.6us/itn) – pure python `Copy()` method copying classes with deepcopy
3. 1.488 sec (14.88us/itn) – pure python `Copy()` method not copying classes (only dicts/lists/tuples)
4. 0.325 sec (3.25us/itn) – `for item in old_list: new_list.append(item)`
5. 0.217 sec (2.17us/itn) – `[i for i in old_list]` (a list comprehension)
6. 0.186 sec (1.86us/itn) – `copy.copy(old_list)`
7. 0.075 sec (0.75us/itn) – `list(old_list)`
8. 0.053 sec (0.53us/itn) – `new_list = []; new_list.extend(old_list)`
9. 0.039 sec (0.39us/itn) – `old_list[:]` (list slicing)

So the fastest is list slicing. But be aware that `copy.copy()`, `list[:]` and `list(list)`, unlike `copy.deepcopy()` and the python version don’t copy any lists, dictionaries and class instances in the list, so if the originals change, they will change in the copied list too and vice versa.

(Here’s the script if anyone’s interested or wants to raise any issues:)

``````from copy import deepcopy

class old_class:
def __init__(self):
self.blah = 'blah'

class new_class(object):
def __init__(self):
self.blah = 'blah'

dignore = {str: None, unicode: None, int: None, type(None): None}

def Copy(obj, use_deepcopy=True):
t = type(obj)

if t in (list, tuple):
if t == tuple:
# Convert to a list if a tuple to
# allow assigning to when copying
is_tuple = True
obj = list(obj)
else:
# Otherwise just do a quick slice copy
obj = obj[:]
is_tuple = False

# Copy each item recursively
for x in xrange(len(obj)):
if type(obj[x]) in dignore:
continue
obj[x] = Copy(obj[x], use_deepcopy)

if is_tuple:
# Convert back into a tuple again
obj = tuple(obj)

elif t == dict:
# Use the fast shallow dict copy() method and copy any
# values which aren't immutable (like lists, dicts etc)
obj = obj.copy()
for k in obj:
if type(obj[k]) in dignore:
continue
obj[k] = Copy(obj[k], use_deepcopy)

elif t in dignore:
# Numeric or string/unicode?
# It's immutable, so ignore it!
pass

elif use_deepcopy:
obj = deepcopy(obj)
return obj

if __name__ == '__main__':
import copy
from time import time

num_times = 100000
L = [None, 'blah', 1, 543.4532,
['foo'], ('bar',), {'blah': 'blah'},
old_class(), new_class()]

t = time()
for i in xrange(num_times):
Copy(L)
print 'Custom Copy:', time()-t

t = time()
for i in xrange(num_times):
Copy(L, use_deepcopy=False)
print 'Custom Copy Only Copying Lists/Tuples/Dicts (no classes):', time()-t

t = time()
for i in xrange(num_times):
copy.copy(L)
print 'copy.copy:', time()-t

t = time()
for i in xrange(num_times):
copy.deepcopy(L)
print 'copy.deepcopy:', time()-t

t = time()
for i in xrange(num_times):
L[:]
print 'list slicing [:]:', time()-t

t = time()
for i in xrange(num_times):
list(L)
print 'list(L):', time()-t

t = time()
for i in xrange(num_times):
[i for i in L]
print 'list expression(L):', time()-t

t = time()
for i in xrange(num_times):
a = []
a.extend(L)
print 'list extend:', time()-t

t = time()
for i in xrange(num_times):
a = []
for y in L:
a.append(y)
print 'list append:', time()-t

t = time()
for i in xrange(num_times):
a = []
a.extend(i for i in L)
print 'generator expression extend:', time()-t
``````

## 回答 2

`newlist = old_list.copy()`

I’ve been told that Python 3.3+ adds `list.copy()` method, which should be as fast as slicing:

`newlist = old_list.copy()`

# 在Python中克隆或复制列表有哪些选项？

``a_copy = a_list.copy()``

``a_copy = a_list[:]``

## 浅表副本

### Python 2

``a_copy = a_list[:]``

``a_copy = list(a_list)``

``````>>> timeit
>>> l = range(20)
>>> min(timeit.repeat(lambda: l[:]))
0.30504298210144043
>>> min(timeit.repeat(lambda: list(l)))
0.40698814392089844``````

### Python 3

``a_copy = a_list.copy()``

``````>>> import timeit
>>> l = list(range(20))
>>> min(timeit.repeat(lambda: l[:]))
0.38448613602668047
>>> min(timeit.repeat(lambda: list(l)))
0.6309100328944623
>>> min(timeit.repeat(lambda: l.copy()))
0.38122922903858125``````

## 制作另一个指针并没有进行复制

`my_list`只是指向内存中实际列表的名称。当您说不`new_list = my_list`制作副本时，只是在添加另一个名称，该名称指向内存中的原始列表。复制列表时，我们可能会遇到类似的问题。

``````>>> l = [[], [], []]
>>> l_copy = l[:]
>>> l_copy
[[], [], []]
>>> l_copy[0].append('foo')
>>> l_copy
[['foo'], [], []]
>>> l
[['foo'], [], []]``````

## 深拷贝

``````import copy
a_deep_copy = copy.deepcopy(a_list)``````

``````>>> import copy
>>> l
[['foo'], [], []]
>>> l_deep_copy = copy.deepcopy(l)
>>> l_deep_copy[0].pop()
'foo'
>>> l_deep_copy
[[], [], []]
>>> l
[['foo'], [], []]``````

## 不要使用 `eval`

``problematic_deep_copy = eval(repr(a_list))``
1. 这很危险，特别是如果您正在评估来自不信任来源的内容时。
2. 这是不可靠的，如果您要复制的子元素没有可以用来复制等效元素的表示形式。
3. 它的性能也较差。

``````>>> import timeit
>>> import copy
>>> l = range(10)
>>> min(timeit.repeat(lambda: copy.deepcopy(l)))
27.55826997756958
>>> min(timeit.repeat(lambda: eval(repr(l))))
29.04534101486206``````

``````>>> import timeit
>>> import copy
>>> l = list(range(10))
>>> min(timeit.repeat(lambda: copy.deepcopy(l)))
16.84255409205798
>>> min(timeit.repeat(lambda: eval(repr(l))))
34.813894678023644``````

# What are the options to clone or copy a list in Python?

In Python 3, a shallow copy can be made with:

``````a_copy = a_list.copy()
``````

In Python 2 and 3, you can get a shallow copy with a full slice of the original:

``````a_copy = a_list[:]
``````

## Explanation

There are two semantic ways to copy a list. A shallow copy creates a new list of the same objects, a deep copy creates a new list containing new equivalent objects.

## Shallow list copy

A shallow copy only copies the list itself, which is a container of references to the objects in the list. If the objects contained themselves are mutable and one is changed, the change will be reflected in both lists.

There are different ways to do this in Python 2 and 3. The Python 2 ways will also work in Python 3.

### Python 2

In Python 2, the idiomatic way of making a shallow copy of a list is with a complete slice of the original:

``````a_copy = a_list[:]
``````

You can also accomplish the same thing by passing the list through the list constructor,

``````a_copy = list(a_list)
``````

but using the constructor is less efficient:

``````>>> timeit
>>> l = range(20)
>>> min(timeit.repeat(lambda: l[:]))
0.30504298210144043
>>> min(timeit.repeat(lambda: list(l)))
0.40698814392089844
``````

### Python 3

In Python 3, lists get the `list.copy` method:

``````a_copy = a_list.copy()
``````

In Python 3.5:

``````>>> import timeit
>>> l = list(range(20))
>>> min(timeit.repeat(lambda: l[:]))
0.38448613602668047
>>> min(timeit.repeat(lambda: list(l)))
0.6309100328944623
>>> min(timeit.repeat(lambda: l.copy()))
0.38122922903858125
``````

## Making another pointer does not make a copy

Using new_list = my_list then modifies new_list every time my_list changes. Why is this?

`my_list` is just a name that points to the actual list in memory. When you say `new_list = my_list` you’re not making a copy, you’re just adding another name that points at that original list in memory. We can have similar issues when we make copies of lists.

``````>>> l = [[], [], []]
>>> l_copy = l[:]
>>> l_copy
[[], [], []]
>>> l_copy[0].append('foo')
>>> l_copy
[['foo'], [], []]
>>> l
[['foo'], [], []]
``````

The list is just an array of pointers to the contents, so a shallow copy just copies the pointers, and so you have two different lists, but they have the same contents. To make copies of the contents, you need a deep copy.

## Deep copies

``````import copy
a_deep_copy = copy.deepcopy(a_list)
``````

To demonstrate how this allows us to make new sub-lists:

``````>>> import copy
>>> l
[['foo'], [], []]
>>> l_deep_copy = copy.deepcopy(l)
>>> l_deep_copy[0].pop()
'foo'
>>> l_deep_copy
[[], [], []]
>>> l
[['foo'], [], []]
``````

And so we see that the deep copied list is an entirely different list from the original. You could roll your own function – but don’t. You’re likely to create bugs you otherwise wouldn’t have by using the standard library’s deepcopy function.

## Don’t use `eval`

You may see this used as a way to deepcopy, but don’t do it:

``````problematic_deep_copy = eval(repr(a_list))
``````
1. It’s dangerous, particularly if you’re evaluating something from a source you don’t trust.
2. It’s not reliable, if a subelement you’re copying doesn’t have a representation that can be eval’d to reproduce an equivalent element.
3. It’s also less performant.

In 64 bit Python 2.7:

``````>>> import timeit
>>> import copy
>>> l = range(10)
>>> min(timeit.repeat(lambda: copy.deepcopy(l)))
27.55826997756958
>>> min(timeit.repeat(lambda: eval(repr(l))))
29.04534101486206
``````

on 64 bit Python 3.5:

``````>>> import timeit
>>> import copy
>>> l = list(range(10))
>>> min(timeit.repeat(lambda: copy.deepcopy(l)))
16.84255409205798
>>> min(timeit.repeat(lambda: eval(repr(l))))
34.813894678023644
``````

## 回答 4

Python不会将值存储在变量中。它将名称绑定到对象。您的原始任务采用了所引用的对象并将其`my_list`绑定到该对象`new_list`。无论您使用哪个名称，都只有一个列表，因此将其引用为时所做的更改`my_list`将保持不变`new_list`。该问题的其他每个答案都为您提供了不同的方法来创建要绑定的新对象`new_list`

``````new_list = list(my_list)  # or my_list[:], but I prefer this syntax
# is simply a shorter way of:
new_list = [element for element in my_list]``````

``````import copy
# each element must have __copy__ defined for this...
new_list = [copy.copy(element) for element in my_list]``````

``````import copy
# each element must have __deepcopy__ defined for this...
new_list = copy.deepcopy(my_list)``````

There are many answers already that tell you how to make a proper copy, but none of them say why your original ‘copy’ failed.

Python doesn’t store values in variables; it binds names to objects. Your original assignment took the object referred to by `my_list` and bound it to `new_list` as well. No matter which name you use there is still only one list, so changes made when referring to it as `my_list` will persist when referring to it as `new_list`. Each of the other answers to this question give you different ways of creating a new object to bind to `new_list`.

Each element of a list acts like a name, in that each element binds non-exclusively to an object. A shallow copy creates a new list whose elements bind to the same objects as before.

``````new_list = list(my_list)  # or my_list[:], but I prefer this syntax
# is simply a shorter way of:
new_list = [element for element in my_list]
``````

To take your list copy one step further, copy each object that your list refers to, and bind those element copies to a new list.

``````import copy
# each element must have __copy__ defined for this...
new_list = [copy.copy(element) for element in my_list]
``````

This is not yet a deep copy, because each element of a list may refer to other objects, just like the list is bound to its elements. To recursively copy every element in the list, and then each other object referred to by each element, and so on: perform a deep copy.

``````import copy
# each element must have __deepcopy__ defined for this...
new_list = copy.deepcopy(my_list)
``````

## 回答 5

``````>>> a = [1,2]
>>> b = a[:]
>>> a += [3]
>>> a
[1, 2, 3]
>>> b
[1, 2]
>>> ``````

Use `thing[:]`

``````>>> a = [1,2]
>>> b = a[:]
>>> a += [3]
>>> a
[1, 2, 3]
>>> b
[1, 2]
>>>
``````

## 回答 6

``````list_1=['01','98']
list_2=[['01','98']]``````

``copy=list_1``

``````print(id(copy))
print(id(list_1))``````

``````4329485320
4329485320``````

``````copy[0]="modify"

print(copy)
print(list_1)``````

``````['modify', '98']
['modify', '98']``````

``copy_1=list_1[:]``

``````print(id(copy_1))
print(id(list_1))

4338792136
4338791432``````

``````copy_1[0]="modify"

print(list_1)
print(copy_1)``````

``````['01', '98']
['modify', '98']``````

``copy_2=list_2[:]``

`list_2`应该引用另一个对象，即的副本`list_2`。让我们检查：

``print(id((list_2)),id(copy_2))``

``4330403592 4330403528``

``````copy_2[0][1]="modify"

print(list_2,copy_2)``````

``[['01', 'modify']] [['01', 'modify']]``

``copy_2=list_2[:]``

``````print(id(copy_2[0]))
print(id(list_2[0]))``````

``````4329485832
4329485832``````

``````from copy import deepcopy
deep=deepcopy(list_2)``````

``````print(id((list_2)),id(deep))

4322146056 4322148040``````

``````print(id(deep[0]))
print(id(list_2[0]))``````

``````4322145992
4322145800``````

``````deep[0][1]="modify"
print(list_2,deep)``````

``[['01', '98']] [['01', 'modify']]``

Let’s start from the beginning and explore this question.

So let’s suppose you have two lists:

``````list_1=['01','98']
list_2=[['01','98']]
``````

And we have to copy both lists, now starting from the first list:

So first let’s try by setting the variable `copy` to our original list, `list_1`:

``````copy=list_1
``````

Now if you are thinking copy copied the list_1, then you are wrong. The `id` function can show us if two variables can point to the same object. Let’s try this:

``````print(id(copy))
print(id(list_1))
``````

The output is:

``````4329485320
4329485320
``````

Both variables are the exact same argument. Are you surprised?

So as we know python doesn’t store anything in a variable, Variables are just referencing to the object and object store the value. Here object is a `list` but we created two references to that same object by two different variable names. This means that both variables are pointing to the same object, just with different names.

When you do `copy=list_1`, it is actually doing:

Here in the image list_1 and copy are two variable names but the object is same for both variable which is `list`

So if you try to modify copied list then it will modify the original list too because the list is only one there, you will modify that list no matter you do from the copied list or from the original list:

``````copy[0]="modify"

print(copy)
print(list_1)
``````

output:

``````['modify', '98']
['modify', '98']
``````

So it modified the original list :

Now let’s move onto a pythonic method for copying lists.

``````copy_1=list_1[:]
``````

This method fixes the first issue we had:

``````print(id(copy_1))
print(id(list_1))

4338792136
4338791432
``````

So as we can see our both list having different id and it means that both variables are pointing to different objects. So what actually going on here is:

Now let’s try to modify the list and let’s see if we still face the previous problem:

``````copy_1[0]="modify"

print(list_1)
print(copy_1)
``````

The output is:

``````['01', '98']
['modify', '98']
``````

As you can see, it only modified the copied list. That means it worked.

Do you think we’re done? No. Let’s try to copy our nested list.

``````copy_2=list_2[:]
``````

`list_2` should reference to another object which is copy of `list_2`. Let’s check:

``````print(id((list_2)),id(copy_2))
``````

We get the output:

``````4330403592 4330403528
``````

Now we can assume both lists are pointing different object, so now let’s try to modify it and let’s see it is giving what we want:

``````copy_2[0][1]="modify"

print(list_2,copy_2)
``````

This gives us the output:

``````[['01', 'modify']] [['01', 'modify']]
``````

This may seem a little bit confusing, because the same method we previously used worked. Let’s try to understand this.

When you do:

``````copy_2=list_2[:]
``````

You’re only copying the outer list, not the inside list. We can use the `id` function once again to check this.

``````print(id(copy_2[0]))
print(id(list_2[0]))
``````

The output is:

``````4329485832
4329485832
``````

When we do `copy_2=list_2[:]`, this happens:

It creates the copy of list but only outer list copy, not the nested list copy, nested list is same for both variable, so if you try to modify the nested list then it will modify the original list too as the nested list object is same for both lists.

What is the solution? The solution is the `deepcopy` function.

``````from copy import deepcopy
deep=deepcopy(list_2)
``````

Let’s check this:

``````print(id((list_2)),id(deep))

4322146056 4322148040
``````

Both outer lists have different IDs, let’s try this on the inner nested lists.

``````print(id(deep[0]))
print(id(list_2[0]))
``````

The output is:

``````4322145992
4322145800
``````

As you can see both IDs are different, meaning we can assume that both nested lists are pointing different object now.

This means when you do `deep=deepcopy(list_2)` what actually happens:

Both nested lists are pointing different object and they have separate copy of nested list now.

Now let’s try to modify the nested list and see if it solved the previous issue or not:

``````deep[0][1]="modify"
print(list_2,deep)
``````

It outputs:

``````[['01', '98']] [['01', 'modify']]
``````

As you can see, it didn’t modify the original nested list, it only modified the copied list.

## 回答 7

Python这样做的习惯是 `newList = oldList[:]`

Python’s idiom for doing this is `newList = oldList[:]`

## Python 3.6计时

``````METHOD                  TIME TAKEN
b = [*a]                2.75180600000021
b = a * 1               3.50215399999990
b = a[:]                3.78278899999986  # Python2 winner (see above)
b = a.copy()            4.20556500000020  # Python3 "slice equivalent" (see above)
b = []; b.extend(a)     4.68069800000012
b = a[0:len(a)]         6.84498999999959
*b, = a                 7.54031799999984
b = list(a)             7.75815899999997
b = [i for i in a]      18.4886440000000
b = copy.copy(a)        18.8254879999999
b = []
for item in a:
b.append(item)        35.4729199999997``````

`b = a * 1` 也做得很好。

``````import timeit

COUNT = 50000000
print("Array duplicating. Tests run", COUNT, "times")
setup = 'a = [0,1,2,3,4,5,6,7,8,9]; import copy'

print("b = list(a)\t\t", timeit.timeit(stmt='b = list(a)', setup=setup, number=COUNT))
print("b = copy.copy(a)\t", timeit.timeit(stmt='b = copy.copy(a)', setup=setup, number=COUNT))
print("b = a.copy()\t\t", timeit.timeit(stmt='b = a.copy()', setup=setup, number=COUNT))
print("b = a[:]\t\t", timeit.timeit(stmt='b = a[:]', setup=setup, number=COUNT))
print("b = a[0:len(a)]\t\t", timeit.timeit(stmt='b = a[0:len(a)]', setup=setup, number=COUNT))
print("*b, = a\t\t\t", timeit.timeit(stmt='*b, = a', setup=setup, number=COUNT))
print("b = []; b.extend(a)\t", timeit.timeit(stmt='b = []; b.extend(a)', setup=setup, number=COUNT))
print("b = []; for item in a: b.append(item)\t", timeit.timeit(stmt='b = []\nfor item in a:  b.append(item)', setup=setup, number=COUNT))
print("b = [i for i in a]\t", timeit.timeit(stmt='b = [i for i in a]', setup=setup, number=COUNT))
print("b = [*a]\t\t", timeit.timeit(stmt='b = [*a]', setup=setup, number=COUNT))
print("b = a * 1\t\t", timeit.timeit(stmt='b = a * 1', setup=setup, number=COUNT))``````

## Python 3.6 Timings

Here are the timing results using Python 3.6.8. Keep in mind these times are relative to one another, not absolute.

I stuck to only doing shallow copies, and also added some new methods that weren’t possible in Python2, such as `list.copy()` (the Python3 slice equivalent) and two forms of list unpacking (`*new_list, = list` and `new_list = [*list]`):

``````METHOD                  TIME TAKEN
b = [*a]                2.75180600000021
b = a * 1               3.50215399999990
b = a[:]                3.78278899999986  # Python2 winner (see above)
b = a.copy()            4.20556500000020  # Python3 "slice equivalent" (see above)
b = []; b.extend(a)     4.68069800000012
b = a[0:len(a)]         6.84498999999959
*b, = a                 7.54031799999984
b = list(a)             7.75815899999997
b = [i for i in a]      18.4886440000000
b = copy.copy(a)        18.8254879999999
b = []
for item in a:
b.append(item)        35.4729199999997
``````

We can see the Python2 winner still does well, but doesn’t edge out Python3 `list.copy()` by much, especially considering the superior readability of the latter.

The dark horse is the unpacking and repacking method (`b = [*a]`), which is ~25% faster than raw slicing, and more than twice as fast as the other unpacking method (`*b, = a`).

`b = a * 1` also does surprisingly well.

Note that these methods do not output equivalent results for any input other than lists. They all work for sliceable objects, a few work for any iterable, but only `copy.copy()` works for more general Python objects.

Here is the testing code for interested parties (Template from here):

``````import timeit

COUNT = 50000000
print("Array duplicating. Tests run", COUNT, "times")
setup = 'a = [0,1,2,3,4,5,6,7,8,9]; import copy'

print("b = list(a)\t\t", timeit.timeit(stmt='b = list(a)', setup=setup, number=COUNT))
print("b = copy.copy(a)\t", timeit.timeit(stmt='b = copy.copy(a)', setup=setup, number=COUNT))
print("b = a.copy()\t\t", timeit.timeit(stmt='b = a.copy()', setup=setup, number=COUNT))
print("b = a[:]\t\t", timeit.timeit(stmt='b = a[:]', setup=setup, number=COUNT))
print("b = a[0:len(a)]\t\t", timeit.timeit(stmt='b = a[0:len(a)]', setup=setup, number=COUNT))
print("*b, = a\t\t\t", timeit.timeit(stmt='*b, = a', setup=setup, number=COUNT))
print("b = []; b.extend(a)\t", timeit.timeit(stmt='b = []; b.extend(a)', setup=setup, number=COUNT))
print("b = []; for item in a: b.append(item)\t", timeit.timeit(stmt='b = []\nfor item in a:  b.append(item)', setup=setup, number=COUNT))
print("b = [i for i in a]\t", timeit.timeit(stmt='b = [i for i in a]', setup=setup, number=COUNT))
print("b = [*a]\t\t", timeit.timeit(stmt='b = [*a]', setup=setup, number=COUNT))
print("b = a * 1\t\t", timeit.timeit(stmt='b = a * 1', setup=setup, number=COUNT))
``````

# 编辑：揭露新信息

All of the other contributors gave great answers, which work when you have a single dimension (leveled) list, however of the methods mentioned so far, only `copy.deepcopy()` works to clone/copy a list and not have it point to the nested `list` objects when you are working with multidimensional, nested lists (list of lists). While Felix Kling refers to it in his answer, there is a little bit more to the issue and possibly a workaround using built-ins that might prove a faster alternative to `deepcopy`.

While `new_list = old_list[:]`, `copy.copy(old_list)'` and for Py3k `old_list.copy()` work for single-leveled lists, they revert to pointing at the `list` objects nested within the `old_list` and the `new_list`, and changes to one of the `list` objects are perpetuated in the other.

# Edit: New information brought to light

As was pointed out by both Aaron Hall and PM 2Ring using `eval()` is not only a bad idea, it is also much slower than `copy.deepcopy()`.

This means that for multidimensional lists, the only option is `copy.deepcopy()`. With that being said, it really isn’t an option as the performance goes way south when you try to use it on a moderately sized multidimensional array. I tried to `timeit` using a 42×42 array, not unheard of or even that large for bioinformatics applications, and I gave up on waiting for a response and just started typing my edit to this post.

It would seem that the only real option then is to initialize multiple lists and work on them independently. If anyone has any other suggestions, for how to handle multidimensional list copying, it would be appreciated.

As others have stated, there are significant performance issues using the `copy` module and `copy.deepcopy` for multidimensional lists.

## 回答 10

``````old_list = [1, 2, 3]

new_list = [*old_list]

new_list.append(4)
old_list == [1, 2, 3]
new_list == [1, 2, 3, 4]``````

``````x = [random.random() for _ in range(1000)]

%timeit a = list(x)
%timeit a = x.copy()
%timeit a = x[:]

%timeit a = [*x]

#: 2.47 µs ± 38.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
#: 2.47 µs ± 54.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
#: 2.39 µs ± 58.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

#: 2.22 µs ± 43.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)``````

It surprises me that this hasn’t been mentioned yet, so for the sake of completeness…

You can perform list unpacking with the “splat operator”: `*`, which will also copy elements of your list.

``````old_list = [1, 2, 3]

new_list = [*old_list]

new_list.append(4)
old_list == [1, 2, 3]
new_list == [1, 2, 3, 4]
``````

The obvious downside to this method is that it is only available in Python 3.5+.

Timing wise though, this appears to perform better than other common methods.

``````x = [random.random() for _ in range(1000)]

%timeit a = list(x)
%timeit a = x.copy()
%timeit a = x[:]

%timeit a = [*x]

#: 2.47 µs ± 38.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
#: 2.47 µs ± 54.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
#: 2.39 µs ± 58.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

#: 2.22 µs ± 43.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
``````

## 回答 11

``new_list = my_list * 1       #Solution 1 when you are not using nested lists``

``````import copy
new_list = copy.deepcopy(my_list)   #Solution 2 when you are using nested lists``````

``new_list = my_list[:]``

``````>>> a = range(5)
>>> b = a*1
>>> a,b
([0, 1, 2, 3, 4], [0, 1, 2, 3, 4])
>>> a[2] = 55
>>> a,b
([0, 1, 55, 3, 4], [0, 1, 2, 3, 4])``````

``````>>> from copy import deepcopy
>>> a = [range(i,i+4) for i in range(3)]
>>> a
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
>>> b = a*1
>>> c = deepcopy(a)
>>> for i in (a, b, c): print i
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
>>> a[2].append('99')
>>> for i in (a, b, c): print i
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99]]   #Solution#1 didn't work in nested list
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]       #Solution #2 - DeepCopy worked in nested list``````

A very simple approach independent of python version was missing in already given answers which you can use most of the time (at least I do):

``````new_list = my_list * 1       #Solution 1 when you are not using nested lists
``````

However, If my_list contains other containers (for eg. nested lists) you must use deepcopy as others suggested in the answers above from the copy library. For example:

``````import copy
new_list = copy.deepcopy(my_list)   #Solution 2 when you are using nested lists
``````

.Bonus: If you don’t want to copy elements use (aka shallow copy):

``````new_list = my_list[:]
``````

Let’s understand difference between Solution#1 and Solution #2

``````>>> a = range(5)
>>> b = a*1
>>> a,b
([0, 1, 2, 3, 4], [0, 1, 2, 3, 4])
>>> a[2] = 55
>>> a,b
([0, 1, 55, 3, 4], [0, 1, 2, 3, 4])
``````

As you can see Solution #1 worked perfectly when we were not using the nested lists. Let’s check what will happen when we apply solution #1 to nested lists.

``````>>> from copy import deepcopy
>>> a = [range(i,i+4) for i in range(3)]
>>> a
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
>>> b = a*1
>>> c = deepcopy(a)
>>> for i in (a, b, c): print i
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
>>> a[2].append('99')
>>> for i in (a, b, c): print i
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99]]   #Solution#1 didn't work in nested list
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]       #Solution #2 - DeepCopy worked in nested list
``````

## 回答 12

``````import copy

class MyList(list):
pass

lst = MyList([1,2,3])

lst.name = 'custom list'

d = {
'original': lst,
'slicecopy' : lst[:],
'lstcopy' : lst.copy(),
'copycopy': copy.copy(lst),
'deepcopy': copy.deepcopy(lst)
}

for k,v in d.items():
print('lst: {}'.format(k), end=', ')
try:
name = v.name
except AttributeError:
name = 'NA'
print('name: {}'.format(name))``````

``````lst: original, name: custom list
lst: slicecopy, name: NA
lst: lstcopy, name: NA
lst: copycopy, name: custom list
lst: deepcopy, name: custom list``````

Note that there are some cases where if you have defined your own custom class and you want to keep the attributes then you should use `copy.copy()` or `copy.deepcopy()` rather than the alternatives, for example in Python 3:

``````import copy

class MyList(list):
pass

lst = MyList([1,2,3])

lst.name = 'custom list'

d = {
'original': lst,
'slicecopy' : lst[:],
'lstcopy' : lst.copy(),
'copycopy': copy.copy(lst),
'deepcopy': copy.deepcopy(lst)
}

for k,v in d.items():
print('lst: {}'.format(k), end=', ')
try:
name = v.name
except AttributeError:
name = 'NA'
print('name: {}'.format(name))
``````

Outputs:

``````lst: original, name: custom list
lst: slicecopy, name: NA
lst: lstcopy, name: NA
lst: copycopy, name: custom list
lst: deepcopy, name: custom list
``````

## 回答 13

``new_list = my_list[:]``

`new_list = my_list` 尝试了解这一点。假设my_list位于X位置的堆内存中，即my_list指向X。现在，通过分配`new_list = my_list`，让new_list指向X。这称为浅拷贝。

• `new_list = list(old_list)`
• ```import copy new_list = copy.deepcopy(old_list)```
``````new_list = my_list[:]
``````

`new_list = my_list` Try to understand this. Let’s say that my_list is in the heap memory at location X i.e. my_list is pointing to the X. Now by assigning `new_list = my_list` you’re Letting new_list pointing to the X. This is known as shallow Copy.

Now if you assign `new_list = my_list[:]` You’re simply copying each object of my_list to new_list. This is known as Deep copy.

The Other way you can do this are :

• `new_list = list(old_list)`
• ```import copy new_list = copy.deepcopy(old_list)```

## 回答 14

``````def deepcopy(x):
immutables = (str, int, bool, float)
mutables = (list, dict, tuple)
if isinstance(x, immutables):
return x
elif isinstance(x, mutables):
if isinstance(x, tuple):
return tuple(deepcopy(list(x)))
elif isinstance(x, list):
return [deepcopy(y) for y in x]
elif isinstance(x, dict):
values = [deepcopy(y) for y in list(x.values())]
keys = list(x.keys())
return dict(zip(keys, values))``````

Python自己的内置Deepcopy是基于该示例的。唯一的区别是，它支持其他类型，并且通过将属性复制到新的重复类中来支持用户类，并且还可以通过使用备忘录列表或字典对已经看到的对象的引用来阻止无限递归。制作深拷贝确实就是这样。从本质上讲，深层复制只是浅层复制。我希望这个答案可以为问题增添一些内容。

``[x for x in _list]``

``[deepcopy_list(x) for x in _list]``

``````def deepcopy_list(x):
if isinstance(x, (str, bool, float, int)):
return x
else:
return [deepcopy_list(y) for y in x]``````

TLDR：Deepcopy使用递归来复制对象，并且仅返回与以前相同的不可变对象，因为不能复制不可变对象。但是，它将深层复制可变对象的最内层，直到到达对象的最外层可变层。

I wanted to post something a bit different then some of the other answers. Even though this is most likely not the most understandable, or fastest option, it provides a bit of an inside view of how deep copy works, as well as being another alternative option for deep copying. It doesn’t really matter if my function has bugs, since the point of this is to show a way to copy objects like the question answers, but also to use this as a point to explain how deepcopy works at its core.

At the core of any deep copy function is way to make a shallow copy. How? Simple. Any deep copy function only duplicates the containers of immutable objects. When you deepcopy a nested list, you are only duplicating the outer lists, not the mutable objects inside of the lists. You are only duplicating the containers. The same works for classes, too. When you deepcopy a class, you deepcopy all of its mutable attributes. So, how? How come you only have to copy the containers, like lists, dicts, tuples, iters, classes, and class instances?

It’s simple. A mutable object can’t really be duplicated. It can never be changed, so it is only a single value. That means you never have to duplicate strings, numbers, bools, or any of those. But how would you duplicate the containers? Simple. You make just initialize a new container with all of the values. Deepcopy relies on recursion. It duplicates all the containers, even ones with containers inside of them, until no containers are left. A container is an immutable object.

Once you know that, completely duplicating an object without any references is pretty easy. Here’s a function for deepcopying basic data-types (wouldn’t work for custom classes but you could always add that)

``````def deepcopy(x):
immutables = (str, int, bool, float)
mutables = (list, dict, tuple)
if isinstance(x, immutables):
return x
elif isinstance(x, mutables):
if isinstance(x, tuple):
return tuple(deepcopy(list(x)))
elif isinstance(x, list):
return [deepcopy(y) for y in x]
elif isinstance(x, dict):
values = [deepcopy(y) for y in list(x.values())]
keys = list(x.keys())
return dict(zip(keys, values))
``````

Python’s own built-in deepcopy is based around that example. The only difference is it supports other types, and also supports user-classes by duplicating the attributes into a new duplicate class, and also blocks infinite-recursion with a reference to an object it’s already seen using a memo list or dictionary. And that’s really it for making deep copies. At its core, making a deep copy is just making shallow copies. I hope this answer adds something to the question.

EXAMPLES

Say you have this list: [1, 2, 3]. The immutable numbers cannot be duplicated, but the other layer can. You can duplicate it using a list comprehension: [x for x in [1, 2, 3]

Now, imagine you have this list: [[1, 2], [3, 4], [5, 6]]. This time, you want to make a function, which uses recursion to deep copy all layers of the list. Instead of the previous list comprehension:

``````[x for x in _list]
``````

It uses a new one for lists:

``````[deepcopy_list(x) for x in _list]
``````

And deepcopy_list looks like this:

``````def deepcopy_list(x):
if isinstance(x, (str, bool, float, int)):
return x
else:
return [deepcopy_list(y) for y in x]
``````

Then now you have a function which can deepcopy any list of strs, bools, floast, ints and even lists to infinitely many layers using recursion. And there you have it, deepcopying.

TLDR: Deepcopy uses recursion to duplicate objects, and merely returns the same immutable objects as before, as immutable objects cannot be duplicated. However, it deepcopies the most inner layers of mutable objects until it reaches the outermost mutable layer of an object.

## 回答 15

``````>>> b = a = ['hell', 'word']
>>> c = ['hell', 'word']

>>> id(a), id(b), id(c)
(4424020872, 4424020872, 4423979272)
|           |
-----------

>>> id(a[0]), id(b[0]), id(c[0])
(4424018328, 4424018328, 4424018328) # all referring to same 'hell'
|           |           |
-----------------------

>>> id(a[0][0]), id(b[0][0]), id(c[0][0])
(4422785208, 4422785208, 4422785208) # all referring to same 'h'
|           |           |
-----------------------

>>> a[0] += 'o'
>>> a,b,c
(['hello', 'word'], ['hello', 'word'], ['hell', 'word'])  # b changed too
>>> id(a[0]), id(b[0]), id(c[0])
(4424018384, 4424018384, 4424018328) # augmented assignment changed a[0],b[0]
|           |
-----------

>>> b = a = ['hell', 'word']
>>> id(a[0]), id(b[0]), id(c[0])
(4424018328, 4424018328, 4424018328) # the same hell
|           |           |
-----------------------

>>> import gc
>>> gc.get_referrers(a[0])
[['hell', 'word'], ['hell', 'word']]  # one copy belong to a,b, the another for c
>>> gc.get_referrers(('hell'))
[['hell', 'word'], ['hell', 'word'], ('hell', None)] # ('hello', None) ``````

A slight practical perspective to look into memory through id and gc.

``````>>> b = a = ['hell', 'word']
>>> c = ['hell', 'word']

>>> id(a), id(b), id(c)
(4424020872, 4424020872, 4423979272)
|           |
-----------

>>> id(a[0]), id(b[0]), id(c[0])
(4424018328, 4424018328, 4424018328) # all referring to same 'hell'
|           |           |
-----------------------

>>> id(a[0][0]), id(b[0][0]), id(c[0][0])
(4422785208, 4422785208, 4422785208) # all referring to same 'h'
|           |           |
-----------------------

>>> a[0] += 'o'
>>> a,b,c
(['hello', 'word'], ['hello', 'word'], ['hell', 'word'])  # b changed too
>>> id(a[0]), id(b[0]), id(c[0])
(4424018384, 4424018384, 4424018328) # augmented assignment changed a[0],b[0]
|           |
-----------

>>> b = a = ['hell', 'word']
>>> id(a[0]), id(b[0]), id(c[0])
(4424018328, 4424018328, 4424018328) # the same hell
|           |           |
-----------------------

>>> import gc
>>> gc.get_referrers(a[0])
[['hell', 'word'], ['hell', 'word']]  # one copy belong to a,b, the another for c
>>> gc.get_referrers(('hell'))
[['hell', 'word'], ['hell', 'word'], ('hell', None)] # ('hello', None)
``````

## 回答 16

``````    list1 = ['apples','bananas','pineapples']
list2 = list1``````

List2不是存储实际的列表，而是对list1的引用。因此，当您对list1执行任何操作时，list2也会发生变化。使用复制模块（不是默认值，可从pip下载）制作列表的原始副本（`copy.copy()`用于简单列表，`copy.deepcopy()`用于嵌套列表）。这将使副本不会随第一个列表更改。

Remember that in Python when you do:

``````    list1 = ['apples','bananas','pineapples']
list2 = list1
``````

List2 isn’t storing the actual list, but a reference to list1. So when you do anything to list1, list2 changes as well. use the copy module (not default, download on pip) to make an original copy of the list(`copy.copy()` for simple lists, `copy.deepcopy()` for nested ones). This makes a copy that doesn’t change with the first list.

## 回答 17

deepcopy选项是唯一适用于我的方法：

``````from copy import deepcopy

a = [   [ list(range(1, 3)) for i in range(3) ]   ]
b = deepcopy(a)
b[0][1]=[3]
print('Deep:')
print(a)
print(b)
print('-----------------------------')
a = [   [ list(range(1, 3)) for i in range(3) ]   ]
b = a*1
b[0][1]=[3]
print('*1:')
print(a)
print(b)
print('-----------------------------')
a = [   [ list(range(1, 3)) for i in range(3) ] ]
b = a[:]
b[0][1]=[3]
print('Vector copy:')
print(a)
print(b)
print('-----------------------------')
a = [   [ list(range(1, 3)) for i in range(3) ]  ]
b = list(a)
b[0][1]=[3]
print('List copy:')
print(a)
print(b)
print('-----------------------------')
a = [   [ list(range(1, 3)) for i in range(3) ]  ]
b = a.copy()
b[0][1]=[3]
print('.copy():')
print(a)
print(b)
print('-----------------------------')
a = [   [ list(range(1, 3)) for i in range(3) ]  ]
b = a
b[0][1]=[3]
print('Shallow:')
print(a)
print(b)
print('-----------------------------')``````

``````Deep:
[[[1, 2], [1, 2], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------
*1:
[[[1, 2], [3], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------
Vector copy:
[[[1, 2], [3], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------
List copy:
[[[1, 2], [3], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------
.copy():
[[[1, 2], [3], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------
Shallow:
[[[1, 2], [3], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------``````

The deepcopy option is the only method that works for me:

``````from copy import deepcopy

a = [   [ list(range(1, 3)) for i in range(3) ]   ]
b = deepcopy(a)
b[0][1]=[3]
print('Deep:')
print(a)
print(b)
print('-----------------------------')
a = [   [ list(range(1, 3)) for i in range(3) ]   ]
b = a*1
b[0][1]=[3]
print('*1:')
print(a)
print(b)
print('-----------------------------')
a = [   [ list(range(1, 3)) for i in range(3) ] ]
b = a[:]
b[0][1]=[3]
print('Vector copy:')
print(a)
print(b)
print('-----------------------------')
a = [   [ list(range(1, 3)) for i in range(3) ]  ]
b = list(a)
b[0][1]=[3]
print('List copy:')
print(a)
print(b)
print('-----------------------------')
a = [   [ list(range(1, 3)) for i in range(3) ]  ]
b = a.copy()
b[0][1]=[3]
print('.copy():')
print(a)
print(b)
print('-----------------------------')
a = [   [ list(range(1, 3)) for i in range(3) ]  ]
b = a
b[0][1]=[3]
print('Shallow:')
print(a)
print(b)
print('-----------------------------')
``````

``````Deep:
[[[1, 2], [1, 2], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------
*1:
[[[1, 2], [3], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------
Vector copy:
[[[1, 2], [3], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------
List copy:
[[[1, 2], [3], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------
.copy():
[[[1, 2], [3], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------
Shallow:
[[[1, 2], [3], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------
``````

# 访问“ for”循环中的索引？

## 问题：访问“ for”循环中的索引？

``````ints = [8, 23, 45, 12, 78]
for i in ints:
print('item #{} = {}'.format(???, i))``````

``````item #1 = 8
item #2 = 23
item #3 = 45
item #4 = 12
item #5 = 78``````

How do I access the index in a `for` loop like the following?

``````ints = [8, 23, 45, 12, 78]
for i in ints:
print('item #{} = {}'.format(???, i))
``````

I want to get this output:

``````item #1 = 8
item #2 = 23
item #3 = 45
item #4 = 12
item #5 = 78
``````

When I loop through it using a `for` loop, how do I access the loop index, from 1 to 5 in this case?

## 回答 0

``````for idx, val in enumerate(ints):
print(idx, val)``````

Using an additional state variable, such as an index variable (which you would normally use in languages such as C or PHP), is considered non-pythonic.

The better option is to use the built-in function `enumerate()`, available in both Python 2 and 3:

``````for idx, val in enumerate(ints):
print(idx, val)
``````

Check out PEP 279 for more.

# 使用for循环，在这种情况下如何访问循环索引（从1到5）？

``````for index, item in enumerate(items):
print(index, item)``````

``````for count, item in enumerate(items, start=1):
print(count, item)``````

# 单项控制流

``````index = 0            # Python's indexing starts at zero
for item in items:   # Python's for loops are a "for each" loop
print(index, item)
index += 1``````

``````index = 0
while index < len(items):
print(index, items[index])
index += 1``````

``````for index in range(len(items)):
print(index, items[index])``````

# 使用枚举功能

Python的`enumerate`功能通过隐藏索引的记帐，并将可迭代项封装到另一个可迭代项（一个`enumerate`对象）中，从而减少了视觉混乱，该可迭代项产生了两个索引元组以及原始可迭代项将提供的项目。看起来像这样：

``````for index, item in enumerate(items, start=0):   # default is zero
print(index, item)``````

## 计数

``````for count, item in enumerate(items, start=1):   # default is zero
print(item)

print('there were {0} items printed'.format(count))``````

## 分解-逐步说明

``items = ['a', 'b', 'c', 'd', 'e']``

``enumerate_object = enumerate(items) # the enumerate object``

``````iteration = next(enumerate_object) # first iteration from enumerate
print(iteration)``````

``(0, 'a')``

``````index, item = iteration
#   0,  'a' = (0, 'a') # essentially this.``````

``````>>> print(index)
0
>>> print(item)
a``````

# 结论

• Python索引从零开始
• 要在迭代过程中从迭代器获取这些索引，请使用枚举函数
• 以惯用方式使用枚举（以及元组拆包）将创建更易读和可维护的代码：

``````for index, item in enumerate(items, start=0):   # Python indexes start at zero
print(index, item)``````

# Using a for loop, how do I access the loop index, from 1 to 5 in this case?

Use `enumerate` to get the index with the element as you iterate:

``````for index, item in enumerate(items):
print(index, item)
``````

And note that Python’s indexes start at zero, so you would get 0 to 4 with the above. If you want the count, 1 to 5, do this:

``````for count, item in enumerate(items, start=1):
print(count, item)
``````

# Unidiomatic control flow

What you are asking for is the Pythonic equivalent of the following, which is the algorithm most programmers of lower-level languages would use:

``````index = 0            # Python's indexing starts at zero
for item in items:   # Python's for loops are a "for each" loop
print(index, item)
index += 1
``````

Or in languages that do not have a for-each loop:

``````index = 0
while index < len(items):
print(index, items[index])
index += 1
``````

or sometimes more commonly (but unidiomatically) found in Python:

``````for index in range(len(items)):
print(index, items[index])
``````

# Use the Enumerate Function

Python’s `enumerate` function reduces the visual clutter by hiding the accounting for the indexes, and encapsulating the iterable into another iterable (an `enumerate` object) that yields a two-item tuple of the index and the item that the original iterable would provide. That looks like this:

``````for index, item in enumerate(items, start=0):   # default is zero
print(index, item)
``````

This code sample is fairly well the canonical example of the difference between code that is idiomatic of Python and code that is not. Idiomatic code is sophisticated (but not complicated) Python, written in the way that it was intended to be used. Idiomatic code is expected by the designers of the language, which means that usually this code is not just more readable, but also more efficient.

## Getting a count

Even if you don’t need indexes as you go, but you need a count of the iterations (sometimes desirable) you can start with `1` and the final number will be your count.

``````for count, item in enumerate(items, start=1):   # default is zero
print(item)

print('there were {0} items printed'.format(count))
``````

The count seems to be more what you intend to ask for (as opposed to index) when you said you wanted from 1 to 5.

## Breaking it down – a step by step explanation

To break these examples down, say we have a list of items that we want to iterate over with an index:

``````items = ['a', 'b', 'c', 'd', 'e']
``````

Now we pass this iterable to enumerate, creating an enumerate object:

``````enumerate_object = enumerate(items) # the enumerate object
``````

We can pull the first item out of this iterable that we would get in a loop with the `next` function:

``````iteration = next(enumerate_object) # first iteration from enumerate
print(iteration)
``````

And we see we get a tuple of `0`, the first index, and `'a'`, the first item:

``````(0, 'a')
``````

we can use what is referred to as “sequence unpacking” to extract the elements from this two-tuple:

``````index, item = iteration
#   0,  'a' = (0, 'a') # essentially this.
``````

and when we inspect `index`, we find it refers to the first index, 0, and `item` refers to the first item, `'a'`.

``````>>> print(index)
0
>>> print(item)
a
``````

# Conclusion

• Python indexes start at zero
• To get these indexes from an iterable as you iterate over it, use the enumerate function
• Using enumerate in the idiomatic way (along with tuple unpacking) creates code that is more readable and maintainable:

So do this:

``````for index, item in enumerate(items, start=0):   # Python indexes start at zero
print(index, item)
``````

## 回答 2

``````for index, item in enumerate(iterable, start=1):
print index, item``````

## 注意

It’s pretty simple to start it from `1` other than `0`:

``````for index, item in enumerate(iterable, start=1):
print index, item
``````

## Note

Important hint, though a little misleading since `index` will be a `tuple` `(idx, item)` here. Good to go.

## 回答 3

``````for i in range(len(ints)):
print i, ints[i]``````
``````for i in range(len(ints)):
print i, ints[i]
``````

## 1.使用枚举（被认为是最惯用的）

``````for index, element in enumerate(lst):
# do the things that need doing here``````

## 2.创建一个变量来保存索引（使用`for`）

``````for index in range(len(lst)):   # or xrange
# you will have to write extra code to get the element``````

## 3.创建一个变量来保存索引（使用`while`）

``````index = 0
while index < len(lst):
# you will have to write extra code to get the element
index += 1  # escape infinite recursion``````

## 4.总有另一种方法

As is the norm in Python there are several ways to do this. In all examples assume: `lst = [1, 2, 3, 4, 5]`

## 1. Using enumerate (considered most idiomatic)

``````for index, element in enumerate(lst):
# do the things that need doing here
``````

This is also the safest option in my opinion because the chance of going into infinite recursion has been eliminated. Both the item and its index are held in variables and there is no need to write any further code to access the item.

## 2. Creating a variable to hold the index (using `for`)

``````for index in range(len(lst)):   # or xrange
# you will have to write extra code to get the element
``````

## 3. Creating a variable to hold the index (using `while`)

``````index = 0
while index < len(lst):
# you will have to write extra code to get the element
index += 1  # escape infinite recursion
``````

## 4. There is always another way

As explained before, there are other ways to do this that have not been explained here and they may even apply more in other situations. e.g using `itertools.chain` with for. It handles nested loops better than the other examples.

## 回答 5

``````for ix in range(len(ints)):
print ints[ix]``````

``````[ (ix, ints[ix]) for ix in range(len(ints))]

>>> ints
[1, 2, 3, 4, 5]
>>> for ix in range(len(ints)): print ints[ix]
...
1
2
3
4
5
>>> [ (ix, ints[ix]) for ix in range(len(ints))]
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
>>> lc = [ (ix, ints[ix]) for ix in range(len(ints))]
>>> for tup in lc:
...     print tup
...
(0, 1)
(1, 2)
(2, 3)
(3, 4)
(4, 5)
>>> ``````

Old fashioned way:

``````for ix in range(len(ints)):
print ints[ix]
``````

List comprehension:

``````[ (ix, ints[ix]) for ix in range(len(ints))]

>>> ints
[1, 2, 3, 4, 5]
>>> for ix in range(len(ints)): print ints[ix]
...
1
2
3
4
5
>>> [ (ix, ints[ix]) for ix in range(len(ints))]
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
>>> lc = [ (ix, ints[ix]) for ix in range(len(ints))]
>>> for tup in lc:
...     print tup
...
(0, 1)
(1, 2)
(2, 3)
(3, 4)
(4, 5)
>>>
``````

## 回答 6

Python 2.7中访问循环内列表索引的最快方法是对小列表使用range方法，对中型和大型列表使用枚举方法

``````from timeit import timeit

# Using range
def range_loop(iterable):
for i in range(len(iterable)):
1 + iterable[i]

# Using xrange
def xrange_loop(iterable):
for i in xrange(len(iterable)):
1 + iterable[i]

# Using enumerate
def enumerate_loop(iterable):
for i, val in enumerate(iterable):
1 + val

# Manual indexing
def manual_indexing_loop(iterable):
index = 0
for item in iterable:
1 + item
index += 1``````

``````from timeit import timeit

def measure(l, number=10000):
print "Measure speed for list with %d items" % len(l)
print "xrange: ", timeit(lambda :xrange_loop(l), number=number)
print "range: ", timeit(lambda :range_loop(l), number=number)
print "enumerate: ", timeit(lambda :enumerate_loop(l), number=number)
print "manual_indexing: ", timeit(lambda :manual_indexing_loop(l), number=number)

measure(range(1000))
# Measure speed for list with 1000 items
# xrange:  0.758321046829
# range:  0.701184988022
# enumerate:  0.724966049194
# manual_indexing:  0.894635915756

measure(range(10000))
# Measure speed for list with 100000 items
# xrange:  81.4756360054
# range:  75.0172479153
# enumerate:  74.687623024
# manual_indexing:  91.6308541298

measure(range(10000000), number=100)
# Measure speed for list with 10000000 items
# xrange:  82.267786026
# range:  84.0493988991
# enumerate:  78.0344707966
# manual_indexing:  95.0491430759``````

The fastest way to access indexes of list within loop in Python 2.7 is to use the range method for small lists and enumerate method for medium and huge size lists.

Please see different approaches which can be used to iterate over list and access index value and their performance metrics (which I suppose would be useful for you) in code samples below:

``````from timeit import timeit

# Using range
def range_loop(iterable):
for i in range(len(iterable)):
1 + iterable[i]

# Using xrange
def xrange_loop(iterable):
for i in xrange(len(iterable)):
1 + iterable[i]

# Using enumerate
def enumerate_loop(iterable):
for i, val in enumerate(iterable):
1 + val

# Manual indexing
def manual_indexing_loop(iterable):
index = 0
for item in iterable:
1 + item
index += 1
``````

See performance metrics for each method below:

``````from timeit import timeit

def measure(l, number=10000):
print "Measure speed for list with %d items" % len(l)
print "xrange: ", timeit(lambda :xrange_loop(l), number=number)
print "range: ", timeit(lambda :range_loop(l), number=number)
print "enumerate: ", timeit(lambda :enumerate_loop(l), number=number)
print "manual_indexing: ", timeit(lambda :manual_indexing_loop(l), number=number)

measure(range(1000))
# Measure speed for list with 1000 items
# xrange:  0.758321046829
# range:  0.701184988022
# enumerate:  0.724966049194
# manual_indexing:  0.894635915756

measure(range(10000))
# Measure speed for list with 100000 items
# xrange:  81.4756360054
# range:  75.0172479153
# enumerate:  74.687623024
# manual_indexing:  91.6308541298

measure(range(10000000), number=100)
# Measure speed for list with 10000000 items
# xrange:  82.267786026
# range:  84.0493988991
# enumerate:  78.0344707966
# manual_indexing:  95.0491430759
``````

As the result, using `range` method is the fastest one up to list with 1000 items. For list with size > 10 000 items `enumerate` is the winner.

## 回答 7

``for x in range(0, 5):``

``list[index]``

First of all, the indexes will be from 0 to 4. Programming languages start counting from 0; don’t forget that or you will come across an index out of bounds exception. All you need in the for loop is a variable counting from 0 to 4 like so:

``````for x in range(0, 5):
``````

Keep in mind that I wrote 0 to 5 because the loop stops one number before the max. :)

To get the value of an index use

``````list[index]
``````

# 这是`for`循环访问索引时得到的结果：

`for i in enumerate(items): print(i)`

``````items = [8, 23, 45, 12, 78]

for i in enumerate(items):
print("index/value", i)``````

``````# index/value (0, 8)
# index/value (1, 23)
# index/value (2, 45)
# index/value (3, 12)
# index/value (4, 78)``````

`for i, val in enumerate(items): print(i, val)`

``````items = [8, 23, 45, 12, 78]

for i, val in enumerate(items):
print("index", i, "for value", val)``````

``````# index 0 for value 8
# index 1 for value 23
# index 2 for value 45
# index 3 for value 12
# index 4 for value 78``````

`for i, val in enumerate(items): print(i)`

``````items = [8, 23, 45, 12, 78]

for i, val in enumerate(items):
print("index", i)``````

``````# index 0
# index 1
# index 2
# index 3
# index 4``````

# Here’s what you get when you’re accessing index in `for` loops:

`for i in enumerate(items): print(i)`

``````items = [8, 23, 45, 12, 78]

for i in enumerate(items):
print("index/value", i)
``````

Result:

``````# index/value (0, 8)
# index/value (1, 23)
# index/value (2, 45)
# index/value (3, 12)
# index/value (4, 78)
``````

`for i, val in enumerate(items): print(i, val)`

``````items = [8, 23, 45, 12, 78]

for i, val in enumerate(items):
print("index", i, "for value", val)
``````

Result:

``````# index 0 for value 8
# index 1 for value 23
# index 2 for value 45
# index 3 for value 12
# index 4 for value 78
``````

`for i, val in enumerate(items): print(i)`

``````items = [8, 23, 45, 12, 78]

for i, val in enumerate(items):
print("index", i)
``````

Result:

``````# index 0
# index 1
# index 2
# index 3
# index 4
``````

## 回答 9

``````for i in range(len(sequence)):
# work with index i``````

``````for i in range(len(sequence)):
e = sequence[i]
# work with index i and element e``````

``````for i, e in zip(range(len(sequence)), sequence):
# work with index i and element e``````

Loop counter iteration

The current idiom for looping over the indices makes use of the built-in `range` function:

``````for i in range(len(sequence)):
# work with index i
``````

Looping over both elements and indices can be achieved either by the old idiom or by using the new `zip` built-in function:

``````for i in range(len(sequence)):
e = sequence[i]
# work with index i and element e
``````

or

``````for i, e in zip(range(len(sequence)), sequence):
# work with index i and element e
``````

## 回答 10

``````ints = [8, 23, 45, 12, 78]
index = 0

for value in (ints):
index +=1
print index, value``````

``````ints = [8, 23, 45, 12, 78]
index = 0

for value in (ints):
index +=1
print index, value
if index >= len(ints)-1:
index = 0``````

You can do it with this code:

``````ints = [8, 23, 45, 12, 78]
index = 0

for value in (ints):
index +=1
print index, value
``````

Use this code if you need to reset the index value at the end of the loop:

``````ints = [8, 23, 45, 12, 78]
index = 0

for value in (ints):
index +=1
print index, value
if index >= len(ints)-1:
index = 0
``````

## 回答 11

``````In [1]: ints = [8, 23, 45, 12, 78]

In [2]: for idx, val in enumerate(ints):
...:         print(idx, val)
...:
(0, 8)
(1, 23)
(2, 45)
(3, 12)
(4, 78)``````

Best solution for this problem is use enumerate in-build python function.
enumerate return tuple
first value is index
second value is element of array at that index

``````In [1]: ints = [8, 23, 45, 12, 78]

In [2]: for idx, val in enumerate(ints):
...:         print(idx, val)
...:
(0, 8)
(1, 23)
(2, 45)
(3, 12)
(4, 78)
``````

## 回答 12

``````alist = [1, 2, 3, 4, 5]

for n, a in enumerate(alist):
print("%d %d" % (n, a))``````

``````0 1
1 2
2 3
3 4
4 5``````

``````for n, a in enumerate(alist[1:-1]):
print("%d %d" % (n, a))``````

``````0 2
1 3
2 4``````

``````for n, a in enumerate(alist, start=1):
print("%d %d" % (n, a))``````

``````1 1
2 2
3 3
4 4
5 5``````

In your question, you write “how do I access the loop index, from 1 to 5 in this case?”

However, the index for a list runs from zero. So, then we need to know if what you actually want is the index and item for each item in a list, or whether you really want numbers starting from 1. Fortunately, in Python, it is easy to do either or both.

First, to clarify, the `enumerate` function iteratively returns the index and corresponding item for each item in a list.

``````alist = [1, 2, 3, 4, 5]

for n, a in enumerate(alist):
print("%d %d" % (n, a))
``````

The output for the above is then,

``````0 1
1 2
2 3
3 4
4 5
``````

Notice that the index runs from 0. This kind of indexing is common among modern programming languages including Python and C.

If you want your loop to span a part of the list, you can use the standard Python syntax for a part of the list. For example, to loop from the second item in a list up to but not including the last item, you could use

``````for n, a in enumerate(alist[1:-1]):
print("%d %d" % (n, a))
``````

Note that once again, the output index runs from 0,

``````0 2
1 3
2 4
``````

That brings us to the `start=n` switch for `enumerate()`. This simply offsets the index, you can equivalently simply add a number to the index inside the loop.

``````for n, a in enumerate(alist, start=1):
print("%d %d" % (n, a))
``````

for which the output is

``````1 1
2 2
3 3
4 4
5 5
``````

## 回答 13

``````for i, num in enumerate(nums, start=1):
print(i, num)``````

``````for i in range(l):
print(i+1, nums[i])``````

If I were to iterate `nums = [1, 2, 3, 4, 5]` I would do

``````for i, num in enumerate(nums, start=1):
print(i, num)
``````

Or get the length as `l = len(nums)`

``````for i in range(l):
print(i+1, nums[i])
``````

## 回答 14

``````for i in ints:
indx = ints.index(i)
print(i, indx)``````

If there is no duplicate value in the list:

``````for i in ints:
indx = ints.index(i)
print(i, indx)
``````

## 回答 15

``````data = ['itemA.ABC', 'itemB.defg', 'itemC.drug', 'itemD.ashok']
x = []
for (i, item) in enumerate(data):
a = (i, str(item).split('.'))
x.append(a)
for index, value in x:
print(index, value)``````

``````0 ['itemA', 'ABC']
1 ['itemB', 'defg']
2 ['itemC', 'drug']
3 ['itemD', 'ashok']``````

You can also try this:

``````data = ['itemA.ABC', 'itemB.defg', 'itemC.drug', 'itemD.ashok']
x = []
for (i, item) in enumerate(data):
a = (i, str(item).split('.'))
x.append(a)
for index, value in x:
print(index, value)
``````

The output is

``````0 ['itemA', 'ABC']
1 ['itemB', 'defg']
2 ['itemC', 'drug']
3 ['itemD', 'ashok']
``````

## 回答 16

``````ints = [8, 23, 45, 12, 78]
inds = [ints.index(i) for i in ints]``````

``````ints = [8, 8, 8, 23, 45, 12, 78]
inds = [tup[0] for tup in enumerate(ints)]``````

``````ints = [8, 8, 8, 23, 45, 12, 78]
inds = [tup for tup in enumerate(ints)]``````

You can use the `index` method

``````ints = [8, 23, 45, 12, 78]
inds = [ints.index(i) for i in ints]
``````

EDIT Highlighted in the comment that this method doesn’t work if there are duplicates in `ints`, the method below should work for any values in `ints`:

``````ints = [8, 8, 8, 23, 45, 12, 78]
inds = [tup[0] for tup in enumerate(ints)]
``````

Or alternatively

``````ints = [8, 8, 8, 23, 45, 12, 78]
inds = [tup for tup in enumerate(ints)]
``````

if you want to get both the index and the value in `ints` as a list of tuples.

It uses the method of `enumerate` in the selected answer to this question, but with list comprehension, making it faster with less code.

## 回答 17

``````arr = [8, 23, 45, 12, 78]
i = 0
while i<len(arr):
print("Item ",i+1," = ",arr[i])
i +=1``````

``````arr = [8, 23, 45, 12, 78]
i = 0
while i<len(arr):
print("Item ",i+1," = ",arr[i])
i +=1
``````

Output:

## 回答 18

``````ints = [8, 23, 45, 12, 78]
print [(i,ints[i]) for i in range(len(ints))]``````

``[(0, 8), (1, 23), (2, 45), (3, 12), (4, 78)]``

To print tuple of (index, value) in list comprehension using a `for` loop:

``````ints = [8, 23, 45, 12, 78]
print [(i,ints[i]) for i in range(len(ints))]
``````

Output:

``````[(0, 8), (1, 23), (2, 45), (3, 12), (4, 78)]
``````

## 回答 19

``````list1 = [10, 'sumit', 43.21, 'kumar', '43', 'test', 3]
for x in list1:
print('index:', list1.index(x), 'value:', x)``````

This serves the purpose well enough:

``````list1 = [10, 'sumit', 43.21, 'kumar', '43', 'test', 3]
for x in list1:
print('index:', list1.index(x), 'value:', x)
``````

# 如何从列表列表中制作平面列表？

## 问题：如何从列表列表中制作平面列表？

``````l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
reduce(lambda x, y: x.extend(y), l)``````

``````Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
AttributeError: 'NoneType' object has no attribute 'extend'``````

I wonder whether there is a shortcut to make a simple list out of list of lists in Python.

I can do that in a `for` loop, but maybe there is some cool “one-liner”? I tried it with `reduce()`, but I get an error.

Code

``````l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
reduce(lambda x, y: x.extend(y), l)
``````

Error message

``````Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
AttributeError: 'NoneType' object has no attribute 'extend'
``````

## 回答 0

`flat_list = [item for sublist in l for item in sublist]`

``````flat_list = []
for sublist in l:
for item in sublist:
flat_list.append(item)``````

``flatten = lambda l: [item for sublist in l for item in sublist]``

``````\$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 3: 143 usec per loop
\$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 969 usec per loop
\$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 3: 1.1 msec per loop``````

Given a list of lists `l`,

`flat_list = [item for sublist in l for item in sublist]`

which means:

``````flat_list = []
for sublist in l:
for item in sublist:
flat_list.append(item)
``````

is faster than the shortcuts posted so far. (`l` is the list to flatten.)

Here is the corresponding function:

``````flatten = lambda l: [item for sublist in l for item in sublist]
``````

As evidence, you can use the `timeit` module in the standard library:

``````\$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 3: 143 usec per loop
\$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 969 usec per loop
\$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 3: 1.1 msec per loop
``````

Explanation: the shortcuts based on `+` (including the implied use in `sum`) are, of necessity, `O(L**2)` when there are L sublists — as the intermediate result list keeps getting longer, at each step a new intermediate result list object gets allocated, and all the items in the previous intermediate result must be copied over (as well as a few new ones added at the end). So, for simplicity and without actual loss of generality, say you have L sublists of I items each: the first I items are copied back and forth L-1 times, the second I items L-2 times, and so on; total number of copies is I times the sum of x for x from 1 to L excluded, i.e., `I * (L**2)/2`.

The list comprehension just generates one list, once, and copies each item over (from its original place of residence to the result list) also exactly once.

## 回答 1

``````import itertools
list2d = [[1,2,3], [4,5,6], [7], [8,9]]
merged = list(itertools.chain(*list2d))``````

``````import itertools
list2d = [[1,2,3], [4,5,6], [7], [8,9]]
merged = list(itertools.chain.from_iterable(list2d))``````

You can use `itertools.chain()`:

``````import itertools
list2d = [[1,2,3], [4,5,6], [7], [8,9]]
merged = list(itertools.chain(*list2d))
``````

Or you can use `itertools.chain.from_iterable()` which doesn’t require unpacking the list with the `*` operator:

``````import itertools
list2d = [[1,2,3], [4,5,6], [7], [8,9]]
merged = list(itertools.chain.from_iterable(list2d))
``````

## 回答 2

``````>>> sum(l, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]``````

Note from the author: This is inefficient. But fun, because monoids are awesome. It’s not appropriate for production Python code.

``````>>> sum(l, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
``````

This just sums the elements of iterable passed in the first argument, treating second argument as the initial value of the sum (if not given, `0` is used instead and this case will give you an error).

Because you are summing nested lists, you actually get `[1,3]+[2,4]` as a result of `sum([[1,3],[2,4]],[])`, which is equal to `[1,3,2,4]`.

Note that only works on lists of lists. For lists of lists of lists, you’ll need another solution.

## 回答 3

``functools.reduce(operator.iconcat, a, [])``

``````import functools
import itertools
import numpy
import operator
import perfplot

def forfor(a):
return [item for sublist in a for item in sublist]

def sum_brackets(a):
return sum(a, [])

def functools_reduce(a):
return functools.reduce(operator.concat, a)

def functools_reduce_iconcat(a):
return functools.reduce(operator.iconcat, a, [])

def itertools_chain(a):
return list(itertools.chain.from_iterable(a))

def numpy_flat(a):
return list(numpy.array(a).flat)

def numpy_concatenate(a):
return list(numpy.concatenate(a))

perfplot.show(
setup=lambda n: [list(range(10))] * n,
# setup=lambda n: [list(range(n))] * 10,
kernels=[
forfor,
sum_brackets,
functools_reduce,
functools_reduce_iconcat,
itertools_chain,
numpy_flat,
numpy_concatenate,
],
n_range=[2 ** k for k in range(16)],
xlabel="num lists (of length 10)",
# xlabel="len lists (10 lists total)"
)``````

I tested most suggested solutions with perfplot (a pet project of mine, essentially a wrapper around `timeit`), and found

``````functools.reduce(operator.iconcat, a, [])
``````

to be the fastest solution, both when many small lists and few long lists are concatenated. (`operator.iadd` is equally fast.)

Code to reproduce the plot:

``````import functools
import itertools
import numpy
import operator
import perfplot

def forfor(a):
return [item for sublist in a for item in sublist]

def sum_brackets(a):
return sum(a, [])

def functools_reduce(a):
return functools.reduce(operator.concat, a)

def functools_reduce_iconcat(a):
return functools.reduce(operator.iconcat, a, [])

def itertools_chain(a):
return list(itertools.chain.from_iterable(a))

def numpy_flat(a):
return list(numpy.array(a).flat)

def numpy_concatenate(a):
return list(numpy.concatenate(a))

perfplot.show(
setup=lambda n: [list(range(10))] * n,
# setup=lambda n: [list(range(n))] * 10,
kernels=[
forfor,
sum_brackets,
functools_reduce,
functools_reduce_iconcat,
itertools_chain,
numpy_flat,
numpy_concatenate,
],
n_range=[2 ** k for k in range(16)],
xlabel="num lists (of length 10)",
# xlabel="len lists (10 lists total)"
)
``````

## 回答 4

``````from functools import reduce #python 3

>>> l = [[1,2,3],[4,5,6], [7], [8,9]]
>>> reduce(lambda x,y: x+y,l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]``````

`extend()`您的示例中的方法将修改`x`而不是返回有用的值（期望值`reduce()`）。

`reduce`版本的更快方法是

``````>>> import operator
>>> l = [[1,2,3],[4,5,6], [7], [8,9]]
>>> reduce(operator.concat, l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]``````
``````from functools import reduce #python 3

>>> l = [[1,2,3],[4,5,6], [7], [8,9]]
>>> reduce(lambda x,y: x+y,l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
``````

The `extend()` method in your example modifies `x` instead of returning a useful value (which `reduce()` expects).

A faster way to do the `reduce` version would be

``````>>> import operator
>>> l = [[1,2,3],[4,5,6], [7], [8,9]]
>>> reduce(operator.concat, l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
``````

# 如果您使用Django，请不要重新发明轮子：

``````>>> from django.contrib.admin.utils import flatten
>>> l = [[1,2,3], [4,5], [6]]
>>> flatten(l)
>>> [1, 2, 3, 4, 5, 6]``````

``````>>> from pandas.core.common import flatten
>>> list(flatten(l))``````

Itertools

``````>>> import itertools
>>> flatten = itertools.chain.from_iterable
>>> list(flatten(l))``````

Matplotlib

``````>>> from matplotlib.cbook import flatten
>>> list(flatten(l))``````

Unipath

``````>>> from unipath.path import flatten
>>> list(flatten(l))``````

Setuptools

``````>>> from setuptools.namespaces import flatten
>>> list(flatten(l))``````

# Don’t reinvent the wheel if you use Django:

``````>>> from django.contrib.admin.utils import flatten
>>> l = [[1,2,3], [4,5], [6]]
>>> flatten(l)
>>> [1, 2, 3, 4, 5, 6]
``````

Pandas:

``````>>> from pandas.core.common import flatten
>>> list(flatten(l))
``````

Itertools:

``````>>> import itertools
>>> flatten = itertools.chain.from_iterable
>>> list(flatten(l))
``````

Matplotlib

``````>>> from matplotlib.cbook import flatten
>>> list(flatten(l))
``````

Unipath:

``````>>> from unipath.path import flatten
>>> list(flatten(l))
``````

Setuptools:

``````>>> from setuptools.namespaces import flatten
>>> list(flatten(l))
``````

## 回答 6

``````#from typing import Iterable
from collections import Iterable                            # < py38

def flatten(items):
"""Yield items from any nested iterable; see Reference."""
for x in items:
if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
for sub_x in flatten(x):
yield sub_x
else:
yield x``````

• 在Python 3中，`yield from flatten(x)`可以替换`for sub_x in flatten(x): yield sub_x`
• 在Python 3.8，抽象基类移动`collection.abc`所述`typing`模块。

``````lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(flatten(lst))                                         # nested lists
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

mixed = [[1, [2]], (3, 4, {5, 6}, 7), 8, "9"]              # numbers, strs, nested & mixed
list(flatten(mixed))
# [1, 2, 3, 4, 5, 6, 7, 8, '9']``````

• 此解决方案是根据Beazley，D.和B. Jones的食谱修改的。食谱4.14，Python Cookbook第三版，O’Reilly Media Inc.，塞巴斯托波尔，加利福尼亚：2013年。
• 找到了较早的SO帖子，可能是原始的演示。

Here is a general approach that applies to numbers, strings, nested lists and mixed containers.

Code

``````#from typing import Iterable
from collections import Iterable                            # < py38

def flatten(items):
"""Yield items from any nested iterable; see Reference."""
for x in items:
if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
for sub_x in flatten(x):
yield sub_x
else:
yield x
``````

Notes:

• In Python 3, `yield from flatten(x)` can replace `for sub_x in flatten(x): yield sub_x`
• In Python 3.8, abstract base classes are moved from `collection.abc` to the `typing` module.

Demo

``````lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(flatten(lst))                                         # nested lists
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

mixed = [[1, [2]], (3, 4, {5, 6}, 7), 8, "9"]              # numbers, strs, nested & mixed
list(flatten(mixed))
# [1, 2, 3, 4, 5, 6, 7, 8, '9']
``````

Reference

• This solution is modified from a recipe in Beazley, D. and B. Jones. Recipe 4.14, Python Cookbook 3rd Ed., O’Reilly Media Inc. Sebastopol, CA: 2013.
• Found an earlier SO post, possibly the original demonstration.

## 回答 7

``````>>> from iteration_utilities import deepflatten

>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(deepflatten(l, depth=1))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> l = [[1, 2, 3], [4, [5, 6]], 7, [8, 9]]
>>> list(deepflatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]``````

``````>>> from iteration_utilities import flatten
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(flatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]``````

``````from itertools import chain
from functools import reduce
from collections import Iterable  # or from collections.abc import Iterable
import operator
from iteration_utilities import deepflatten

def nested_list_comprehension(lsts):
return [item for sublist in lsts for item in sublist]

def itertools_chain_from_iterable(lsts):
return list(chain.from_iterable(lsts))

def pythons_sum(lsts):
return sum(lsts, [])

return reduce(lambda x, y: x + y, lsts)

def pylangs_flatten(lsts):
return list(flatten(lsts))

def flatten(items):
"""Yield items from any nested iterable; see REF."""
for x in items:
if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
yield from flatten(x)
else:
yield x

def reduce_concat(lsts):
return reduce(operator.concat, lsts)

def iteration_utilities_deepflatten(lsts):
return list(deepflatten(lsts, depth=1))

from simple_benchmark import benchmark

b = benchmark(
pylangs_flatten, reduce_concat, iteration_utilities_deepflatten],
arguments={2**i: [[0]*5]*(2**i) for i in range(1, 13)},
argument_name='number of inner lists'
)

b.plot()``````

1免责声明：我是该图书馆的作者

If you want to flatten a data-structure where you don’t know how deep it’s nested you could use `iteration_utilities.deepflatten`1

``````>>> from iteration_utilities import deepflatten

>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(deepflatten(l, depth=1))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> l = [[1, 2, 3], [4, [5, 6]], 7, [8, 9]]
>>> list(deepflatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
``````

It’s a generator so you need to cast the result to a `list` or explicitly iterate over it.

To flatten only one level and if each of the items is itself iterable you can also use `iteration_utilities.flatten` which itself is just a thin wrapper around `itertools.chain.from_iterable`:

``````>>> from iteration_utilities import flatten
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(flatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
``````

Just to add some timings (based on Nico Schlömer answer that didn’t include the function presented in this answer):

It’s a log-log plot to accommodate for the huge range of values spanned. For qualitative reasoning: Lower is better.

The results show that if the iterable contains only a few inner iterables then `sum` will be fastest, however for long iterables only the `itertools.chain.from_iterable`, `iteration_utilities.deepflatten` or the nested comprehension have reasonable performance with `itertools.chain.from_iterable` being the fastest (as already noticed by Nico Schlömer).

``````from itertools import chain
from functools import reduce
from collections import Iterable  # or from collections.abc import Iterable
import operator
from iteration_utilities import deepflatten

def nested_list_comprehension(lsts):
return [item for sublist in lsts for item in sublist]

def itertools_chain_from_iterable(lsts):
return list(chain.from_iterable(lsts))

def pythons_sum(lsts):
return sum(lsts, [])

return reduce(lambda x, y: x + y, lsts)

def pylangs_flatten(lsts):
return list(flatten(lsts))

def flatten(items):
"""Yield items from any nested iterable; see REF."""
for x in items:
if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
yield from flatten(x)
else:
yield x

def reduce_concat(lsts):
return reduce(operator.concat, lsts)

def iteration_utilities_deepflatten(lsts):
return list(deepflatten(lsts, depth=1))

from simple_benchmark import benchmark

b = benchmark(
pylangs_flatten, reduce_concat, iteration_utilities_deepflatten],
arguments={2**i: [[0]*5]*(2**i) for i in range(1, 13)},
argument_name='number of inner lists'
)

b.plot()
``````

1 Disclaimer: I’m the author of that library

## 回答 8

``````>>> timeit.Timer(
'[item for sublist in l for item in sublist]',
'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10000'
).timeit(100)
2.0440959930419922``````

sum版本仍在运行一分钟以上，尚未处理！

``````>>> timeit.Timer(
'[item for sublist in l for item in sublist]',
'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
).timeit()
20.126545906066895
>>> timeit.Timer(
'reduce(lambda x,y: x+y,l)',
'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
).timeit()
22.242258071899414
>>> timeit.Timer(
'sum(l, [])',
'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
).timeit()
16.449732065200806``````

``````>>> timeit.Timer(
'[item for sublist in l for item in sublist]',
'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
).timeit()
2.4598159790039062
>>> timeit.Timer(
'reduce(lambda x,y: x+y,l)',
'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
).timeit()
1.5289170742034912
>>> timeit.Timer(
'sum(l, [])',
'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
).timeit()
1.0598428249359131``````

I take my statement back. sum is not the winner. Although it is faster when the list is small. But the performance degrades significantly with larger lists.

``````>>> timeit.Timer(
'[item for sublist in l for item in sublist]',
'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10000'
).timeit(100)
2.0440959930419922
``````

The sum version is still running for more than a minute and it hasn’t done processing yet!

For medium lists:

``````>>> timeit.Timer(
'[item for sublist in l for item in sublist]',
'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
).timeit()
20.126545906066895
>>> timeit.Timer(
'reduce(lambda x,y: x+y,l)',
'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
).timeit()
22.242258071899414
>>> timeit.Timer(
'sum(l, [])',
'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
).timeit()
16.449732065200806
``````

Using small lists and timeit: number=1000000

``````>>> timeit.Timer(
'[item for sublist in l for item in sublist]',
'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
).timeit()
2.4598159790039062
>>> timeit.Timer(
'reduce(lambda x,y: x+y,l)',
'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
).timeit()
1.5289170742034912
>>> timeit.Timer(
'sum(l, [])',
'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
).timeit()
1.0598428249359131
``````

## 回答 9

``````>>> from functools import reduce
>>> list2d = ((1, 2, 3), (4, 5, 6), (7,), (8, 9))
>>> reduce(operator.concat, list2d)
(1, 2, 3, 4, 5, 6, 7, 8, 9)``````

``````>>> list2d = [[1, 2, 3],[4, 5, 6], [7], [8, 9]]
>>> reduce(operator.concat, list2d)
[1, 2, 3, 4, 5, 6, 7, 8, 9]``````

``````>>> list2d = [[1, 2, 3],[4, 5, 6], [7], [8, 9]]
>>> %timeit list(itertools.chain.from_iterable(list2d))
1000000 loops, best of 3: 1.36 µs per loop``````

`from_iterable`相当快！但这是无法与相比的`concat`

``````>>> list2d = ((1, 2, 3),(4, 5, 6), (7,), (8, 9))
>>> %timeit reduce(operator.concat, list2d)
1000000 loops, best of 3: 492 ns per loop``````

There seems to be a confusion with `operator.add`! When you add two lists together, the correct term for that is `concat`, not add. `operator.concat` is what you need to use.

If you’re thinking functional, it is as easy as this::

``````>>> from functools import reduce
>>> list2d = ((1, 2, 3), (4, 5, 6), (7,), (8, 9))
>>> reduce(operator.concat, list2d)
(1, 2, 3, 4, 5, 6, 7, 8, 9)
``````

You see reduce respects the sequence type, so when you supply a tuple, you get back a tuple. Let’s try with a list::

``````>>> list2d = [[1, 2, 3],[4, 5, 6], [7], [8, 9]]
>>> reduce(operator.concat, list2d)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
``````

Aha, you get back a list.

``````>>> list2d = [[1, 2, 3],[4, 5, 6], [7], [8, 9]]
>>> %timeit list(itertools.chain.from_iterable(list2d))
1000000 loops, best of 3: 1.36 µs per loop
``````

`from_iterable` is pretty fast! But it’s no comparison to reduce with `concat`.

``````>>> list2d = ((1, 2, 3),(4, 5, 6), (7,), (8, 9))
>>> %timeit reduce(operator.concat, list2d)
1000000 loops, best of 3: 492 ns per loop
``````

## 回答 10

``reduce(lambda x, y: x+y, l)``

Why do you use extend?

``````reduce(lambda x, y: x+y, l)
``````

This should work fine.

## 回答 11

``> pip install more_itertools``

``````import more_itertools

lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.flatten(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]``````

``````lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.collapse(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

lst = [[1, 2, 3], [[4, 5, 6]], [[[7]]], 8, 9]              # complex nesting
list(more_itertools.collapse(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]``````

Consider installing the `more_itertools` package.

``````> pip install more_itertools
``````

It ships with an implementation for `flatten` (source, from the itertools recipes):

``````import more_itertools

lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.flatten(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
``````

As of version 2.4, you can flatten more complicated, nested iterables with `more_itertools.collapse` (source, contributed by abarnet).

``````lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.collapse(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

lst = [[1, 2, 3], [[4, 5, 6]], [[[7]]], 8, 9]              # complex nesting
list(more_itertools.collapse(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
``````

## 回答 12

``reduce(lambda x,y: x.extend(y) or x, l)``

The reason your function didn’t work is because the extend extends an array in-place and doesn’t return it. You can still return x from lambda, using something like this:

``````reduce(lambda x,y: x.extend(y) or x, l)
``````

Note: extend is more efficient than + on lists.

## 回答 13

``````def flatten(l, a):
for i in l:
if isinstance(i, list):
flatten(i, a)
else:
a.append(i)
return a

print(flatten([[[1, [1,1, [3, [4,5,]]]], 2, 3], [4, 5],6], []))

# [1, 1, 1, 3, 4, 5, 2, 3, 4, 5, 6]``````
``````def flatten(l, a):
for i in l:
if isinstance(i, list):
flatten(i, a)
else:
a.append(i)
return a

print(flatten([[[1, [1,1, [3, [4,5,]]]], 2, 3], [4, 5],6], []))

# [1, 1, 1, 3, 4, 5, 2, 3, 4, 5, 6]
``````

## 回答 14

``````x = [1,2,[3,4],[5,[6,[7]]],8,9,[10]]

def flatten_list(k):
result = list()
for i in k:
if isinstance(i,list):

#The isinstance() function checks if the object (first argument) is an
#instance or subclass of classinfo class (second argument)

result.extend(flatten_list(i)) #Recursive call
else:
result.append(i)
return result

flatten_list(x)
#result = [1,2,3,4,5,6,7,8,9,10]``````

Recursive version

``````x = [1,2,[3,4],[5,[6,[7]]],8,9,[10]]

def flatten_list(k):
result = list()
for i in k:
if isinstance(i,list):

#The isinstance() function checks if the object (first argument) is an
#instance or subclass of classinfo class (second argument)

result.extend(flatten_list(i)) #Recursive call
else:
result.append(i)
return result

flatten_list(x)
#result = [1,2,3,4,5,6,7,8,9,10]
``````

## 回答 15

`matplotlib.cbook.flatten()` 即使嵌套列表比示例嵌套更深，它也适用于嵌套列表。

``````import matplotlib
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
print(list(matplotlib.cbook.flatten(l)))
l2 = [[1, 2, 3], [4, 5, 6], [7], [8, [9, 10, [11, 12, [13]]]]]
print list(matplotlib.cbook.flatten(l2))``````

``````[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]``````

``````Average time over 1000 trials of matplotlib.cbook.flatten: 2.55e-05 sec
Average time over 1000 trials of underscore._.flatten: 4.63e-04 sec
(time for underscore._)/(time for matplotlib.cbook) = 18.1233394636``````

`matplotlib.cbook.flatten()` will work for nested lists even if they nest more deeply than the example.

``````import matplotlib
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
print(list(matplotlib.cbook.flatten(l)))
l2 = [[1, 2, 3], [4, 5, 6], [7], [8, [9, 10, [11, 12, [13]]]]]
print list(matplotlib.cbook.flatten(l2))
``````

Result:

``````[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
``````

This is 18x faster than underscore._.flatten:

``````Average time over 1000 trials of matplotlib.cbook.flatten: 2.55e-05 sec
Average time over 1000 trials of underscore._.flatten: 4.63e-04 sec
(time for underscore._)/(time for matplotlib.cbook) = 18.1233394636
``````

## 回答 16

``l = ['aaa', 'bb', 'cccccc', ['xx', 'yyyyyyy']]``

### 接受的答案无效：

``````flat_list = [item for sublist in l for item in sublist]
print(flat_list)
['a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c', 'xx', 'yyyyyyy']``````

### 新提出的解决方案，没有工作对我来说：

``````flat_list = []
_ = [flat_list.extend(item) if isinstance(item, list) else flat_list.append(item) for item in l if item]
print(flat_list)
['aaa', 'bb', 'cccccc', 'xx', 'yyyyyyy']``````

The accepted answer did not work for me when dealing with text-based lists of variable lengths. Here is an alternate approach that did work for me.

``````l = ['aaa', 'bb', 'cccccc', ['xx', 'yyyyyyy']]
``````

### Accepted answer that did not work:

``````flat_list = [item for sublist in l for item in sublist]
print(flat_list)
['a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c', 'xx', 'yyyyyyy']
``````

### New proposed solution that did work for me:

``````flat_list = []
_ = [flat_list.extend(item) if isinstance(item, list) else flat_list.append(item) for item in l if item]
print(flat_list)
['aaa', 'bb', 'cccccc', 'xx', 'yyyyyyy']
``````

## 回答 17

``````def list_flatten(l, a=None):
#check a
if a is None:
#initialize with empty list
a = []

for i in l:
if isinstance(i, list):
list_flatten(i, a)
else:
a.append(i)
return a``````

``````In [2]: lst = [1, 2, [3], [[4]],[5,[6]]]

In [3]: lst
Out[3]: [1, 2, [3], [[4]], [5, [6]]]

In [11]: list_flatten(lst)
Out[11]: [1, 2, 3, 4, 5, 6]``````

An bad feature of Anil’s function above is that it requires the user to always manually specify the second argument to be an empty list `[]`. This should instead be a default. Due to the way Python objects work, these should be set inside the function, not in the arguments.

Here’s a working function:

``````def list_flatten(l, a=None):
#check a
if a is None:
#initialize with empty list
a = []

for i in l:
if isinstance(i, list):
list_flatten(i, a)
else:
a.append(i)
return a
``````

Testing:

``````In [2]: lst = [1, 2, [3], [[4]],[5,[6]]]

In [3]: lst
Out[3]: [1, 2, [3], [[4]], [5, [6]]]

In [11]: list_flatten(lst)
Out[11]: [1, 2, 3, 4, 5, 6]
``````

## 回答 18

``````>>> import numpy as np
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> print (np.concatenate(l))
[1 2 3 4 5 6 7 8 9]``````

Following seem simplest to me:

``````>>> import numpy as np
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> print (np.concatenate(l))
[1 2 3 4 5 6 7 8 9]
``````

## 回答 19

``````import numpy as np
list(np.array(l).flat)``````

One can also use NumPy’s flat:

``````import numpy as np
list(np.array(l).flat)
``````

Edit 11/02/2016: Only works when sublists have identical dimensions.

## 回答 20

`flat_list = list(np.concatenate(list_of_list))`

You can use numpy :
`flat_list = list(np.concatenate(list_of_list))`

## 回答 21

``````import numpy

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]] * 99

%timeit numpy.concatenate(l).ravel().tolist()
1000 loops, best of 3: 313 µs per loop

%timeit numpy.concatenate(l).tolist()
1000 loops, best of 3: 312 µs per loop

%timeit [item for sublist in l for item in sublist]
1000 loops, best of 3: 31.5 µs per loop``````

If you are willing to give up a tiny amount of speed for a cleaner look, then you could use `numpy.concatenate().tolist()` or `numpy.concatenate().ravel().tolist()`:

``````import numpy

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]] * 99

%timeit numpy.concatenate(l).ravel().tolist()
1000 loops, best of 3: 313 µs per loop

%timeit numpy.concatenate(l).tolist()
1000 loops, best of 3: 312 µs per loop

%timeit [item for sublist in l for item in sublist]
1000 loops, best of 3: 31.5 µs per loop
``````

You can find out more here in the docs numpy.concatenate and numpy.ravel

## 回答 22

``````import numpy as np
#turn list into an array and flatten()
np.array(l).flatten()``````

Fastest solution I have found (for large list anyway):

``````import numpy as np
#turn list into an array and flatten()
np.array(l).flatten()
``````

Done! You can of course turn it back into a list by executing list(l)

## 回答 23

`underscore.py`包装风扇的简单代码

``````from underscore import _
_.flatten([[1, 2, 3], [4, 5, 6], [7], [8, 9]])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]``````

``````from underscore import _
# 1 is none list item
# [2, [3]] is complex nesting
_.flatten([1, [2, [3]], [4, 5, 6], [7], [8, 9]])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]``````

``pip install underscore.py``

Simple code for `underscore.py` package fan

``````from underscore import _
_.flatten([[1, 2, 3], [4, 5, 6], [7], [8, 9]])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
``````

It solves all flatten problems (none list item or complex nesting)

``````from underscore import _
# 1 is none list item
# [2, [3]] is complex nesting
_.flatten([1, [2, [3]], [4, 5, 6], [7], [8, 9]])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
``````

You can install `underscore.py` with pip

``````pip install underscore.py
``````

## 回答 24

``````def flatten(alist):
if alist == []:
return []
elif type(alist) is not list:
return [alist]
else:
return flatten(alist[0]) + flatten(alist[1:])``````
``````def flatten(alist):
if alist == []:
return []
elif type(alist) is not list:
return [alist]
else:
return flatten(alist[0]) + flatten(alist[1:])
``````

## 回答 25

``>>> obj = [[1, 2, 3], [4, 5], 6, 'abc', [7], [8, [9, 10]]]``

• 一个元素`6`只是一个标量。它是不可迭代的，因此上述路由将在此处失败。
• 其中一个要素，`'abc'`技术上可迭代（所有`str` s为）。但是，在行与行之间进行一点阅读时，您并不想这样处理-您希望将其视为单个元素。
• 最后一个元素`[8, [9, 10]]`本身就是嵌套的可迭代对象。基本列表理解，`chain.from_iterable`仅提取“下一级”。

``````>>> from collections import Iterable
>>> from six import string_types

>>> def flatten(obj):
...     for i in obj:
...         if isinstance(i, Iterable) and not isinstance(i, string_types):
...             yield from flatten(i)
...         else:
...             yield i

>>> list(flatten(obj))
[1, 2, 3, 4, 5, 6, 'abc', 7, 8, 9, 10]``````

Note: Below applies to Python 3.3+ because it uses `yield_from`. `six` is also a third-party package, though it is stable. Alternately, you could use `sys.version`.

In the case of `obj = [[1, 2,], [3, 4], [5, 6]]`, all of the solutions here are good, including list comprehension and `itertools.chain.from_iterable`.

However, consider this slightly more complex case:

``````>>> obj = [[1, 2, 3], [4, 5], 6, 'abc', [7], [8, [9, 10]]]
``````

There are several problems here:

• One element, `6`, is just a scalar; it’s not iterable, so the above routes will fail here.
• One element, `'abc'`, is technically iterable (all `str`s are). However, reading between the lines a bit, you don’t want to treat it as such–you want to treat it as a single element.
• The final element, `[8, [9, 10]]` is itself a nested iterable. Basic list comprehension and `chain.from_iterable` only extract “1 level down.”

You can remedy this as follows:

``````>>> from collections import Iterable
>>> from six import string_types

>>> def flatten(obj):
...     for i in obj:
...         if isinstance(i, Iterable) and not isinstance(i, string_types):
...             yield from flatten(i)
...         else:
...             yield i

>>> list(flatten(obj))
[1, 2, 3, 4, 5, 6, 'abc', 7, 8, 9, 10]
``````

Here, you check that the sub-element (1) is iterable with `Iterable`, an ABC from `itertools`, but also want to ensure that (2) the element is not “string-like.”

## 回答 26

``````flat_list = []
for i in list_of_list:
flat_list+=i``````

``````flat_list = []
for i in list_of_list:
flat_list+=i
``````

This Code also works fine as it just extend the list all the way. Although it is much similar but only have one for loop. So It have less complexity than adding 2 for loops.

## 回答 27

``````from nltk import flatten

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
flatten(l)``````

``l = [1, [2, 3], [4, 5, 6], [7], [8, 9]]``

``````from nltk import flatten

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
flatten(l)
``````

The advantage of this solution over most others here is that if you have a list like:

``````l = [1, [2, 3], [4, 5, 6], [7], [8, 9]]
``````

while most other solutions throw an error this solution handles them.

## 回答 28

``````def make_list_flat (l):
flist = []
flist.extend ([l]) if (type (l) is not list) else [flist.extend (make_list_flat (e)) for e in l]
return flist

a = [[1, 2], [[[[3, 4, 5], 6]]], 7, [8, [9, [10, 11], 12, [13, 14, [15, [[16, 17], 18]]]]]]
flist = make_list_flat(a)
print (flist)``````

``[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]``

``````a = [[1, 2], [[[[3, 4, 5], 6]]], 7, [8, [9, [10, 11], 12, [13, 14, [15, [[16, 17], 18]]]]]]
flist = []
def make_list_flat (l):
flist.extend ([l]) if (type (l) is not list) else [make_list_flat (e) for e in l]

make_list_flat(a)
print (flist)``````

``[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]``

This may not be the most efficient way but I thought to put a one-liner (actually a two-liner). Both versions will work on arbitrary hierarchy nested lists, and exploits language features (Python3.5) and recursion.

``````def make_list_flat (l):
flist = []
flist.extend ([l]) if (type (l) is not list) else [flist.extend (make_list_flat (e)) for e in l]
return flist

a = [[1, 2], [[[[3, 4, 5], 6]]], 7, [8, [9, [10, 11], 12, [13, 14, [15, [[16, 17], 18]]]]]]
flist = make_list_flat(a)
print (flist)
``````

The output is

``````[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
``````

This works in a depth first manner. The recursion goes down until it finds a non-list element, then extends the local variable `flist` and then rolls back it to the parent. Whenever `flist` is returned, it is extended to the parent’s `flist` in the list comprehension. Therefore, at the root, a flat list is returned.

The above one creates several local lists and returns them which are used to extend the parent’s list. I think the way around for this may be creating a gloabl `flist`, like below.

``````a = [[1, 2], [[[[3, 4, 5], 6]]], 7, [8, [9, [10, 11], 12, [13, 14, [15, [[16, 17], 18]]]]]]
flist = []
def make_list_flat (l):
flist.extend ([l]) if (type (l) is not list) else [make_list_flat (e) for e in l]

make_list_flat(a)
print (flist)
``````

The output is again

``````[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
``````

Although I am not sure at this time about the efficiency.

## 回答 29

``````from typing import List

def flatten(l: list) -> List[int]:
"""Flatten an arbitrary deep nested list of lists of integers.

Examples:
>>> flatten([1, 2, [1, [10]]])
[1, 2, 1, 10]

Args:
l: Union[l, Union[int, List[int]]

Returns:
Flatted list of integer
"""
return [int(i.strip('[ ]')) for i in str(l).split(',')]``````

Another unusual approach that works for hetero- and homogeneous lists of integers:

``````from typing import List

def flatten(l: list) -> List[int]:
"""Flatten an arbitrary deep nested list of lists of integers.

Examples:
>>> flatten([1, 2, [1, [10]]])
[1, 2, 1, 10]

Args:
l: Union[l, Union[int, List[int]]

Returns:
Flatted list of integer
"""
return [int(i.strip('[ ]')) for i in str(l).split(',')]
``````

# 了解切片符号

## 问题：了解切片符号

I need a good explanation (references are a plus) on Python’s slice notation.

To me, this notation needs a bit of picking up.

It looks extremely powerful, but I haven’t quite got my head around it.

## 回答 0

``````a[start:stop]  # items start through stop-1
a[start:]      # items start through the rest of the array
a[:stop]       # items from the beginning through stop-1
a[:]           # a copy of the whole array``````

``a[start:stop:step] # start through not past stop, by step``

``````a[-1]    # last item in the array
a[-2:]   # last two items in the array
a[:-2]   # everything except the last two items``````

``````a[::-1]    # all items in the array, reversed
a[1::-1]   # the first two items, reversed
a[:-3:-1]  # the last two items, reversed
a[-3::-1]  # everything except the last two items, reversed``````

### 与`slice()`对象的关系

`[]`上面的代码中实际上将切片运算符与`slice()`使用`:`符号的对象一起使用（仅在内有效`[]`），即：

``a[start:stop:step]``

``a[slice(start, stop, step)]``

It’s pretty simple really:

``````a[start:stop]  # items start through stop-1
a[start:]      # items start through the rest of the array
a[:stop]       # items from the beginning through stop-1
a[:]           # a copy of the whole array
``````

There is also the `step` value, which can be used with any of the above:

``````a[start:stop:step] # start through not past stop, by step
``````

The key point to remember is that the `:stop` value represents the first value that is not in the selected slice. So, the difference between `stop` and `start` is the number of elements selected (if `step` is 1, the default).

The other feature is that `start` or `stop` may be a negative number, which means it counts from the end of the array instead of the beginning. So:

``````a[-1]    # last item in the array
a[-2:]   # last two items in the array
a[:-2]   # everything except the last two items
``````

Similarly, `step` may be a negative number:

``````a[::-1]    # all items in the array, reversed
a[1::-1]   # the first two items, reversed
a[:-3:-1]  # the last two items, reversed
a[-3::-1]  # everything except the last two items, reversed
``````

Python is kind to the programmer if there are fewer items than you ask for. For example, if you ask for `a[:-2]` and `a` only contains one element, you get an empty list instead of an error. Sometimes you would prefer the error, so you have to be aware that this may happen.

### Relation to `slice()` object

The slicing operator `[]` is actually being used in the above code with a `slice()` object using the `:` notation (which is only valid within `[]`), i.e.:

``````a[start:stop:step]
``````

is equivalent to:

``````a[slice(start, stop, step)]
``````

Slice objects also behave slightly differently depending on the number of arguments, similarly to `range()`, i.e. both `slice(stop)` and `slice(start, stop[, step])` are supported. To skip specifying a given argument, one might use `None`, so that e.g. `a[start:]` is equivalent to `a[slice(start, None)]` or `a[::-1]` is equivalent to `a[slice(None, None, -1)]`.

While the `:`-based notation is very helpful for simple slicing, the explicit use of `slice()` objects simplifies the programmatic generation of slicing.

## 回答 1

Python的教程谈论它（稍微向下滚动，直到你得到关于切片的部分）。

ASCII艺术图也有助于记住切片的工作方式：

`````` +---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0   1   2   3   4   5   6
-6  -5  -4  -3  -2  -1``````

The Python tutorial talks about it (scroll down a bit until you get to the part about slicing).

The ASCII art diagram is helpful too for remembering how slices work:

`````` +---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0   1   2   3   4   5   6
-6  -5  -4  -3  -2  -1
``````

One way to remember how slices work is to think of the indices as pointing between characters, with the left edge of the first character numbered 0. Then the right edge of the last character of a string of n characters has index n.

## 回答 2

``````>>> seq[:]                # [seq[0],   seq[1],          ..., seq[-1]    ]
>>> seq[low:]             # [seq[low], seq[low+1],      ..., seq[-1]    ]
>>> seq[:high]            # [seq[0],   seq[1],          ..., seq[high-1]]
>>> seq[low:high]         # [seq[low], seq[low+1],      ..., seq[high-1]]
>>> seq[::stride]         # [seq[0],   seq[stride],     ..., seq[-1]    ]
>>> seq[low::stride]      # [seq[low], seq[low+stride], ..., seq[-1]    ]
>>> seq[:high:stride]     # [seq[0],   seq[stride],     ..., seq[high-1]]
>>> seq[low:high:stride]  # [seq[low], seq[low+stride], ..., seq[high-1]]``````

``````>>> seq[::-stride]        # [seq[-1],   seq[-1-stride],   ..., seq[0]    ]
>>> seq[high::-stride]    # [seq[high], seq[high-stride], ..., seq[0]    ]
>>> seq[:low:-stride]     # [seq[-1],   seq[-1-stride],   ..., seq[low+1]]
>>> seq[high:low:-stride] # [seq[high], seq[high-stride], ..., seq[low+1]]``````

``````>>> class slicee:
...     def __getitem__(self, item):
...         return repr(item)
...
>>> slicee()[0, 1:2, ::5, ...]
'(0, slice(1, 2, None), slice(None, None, 5), Ellipsis)'``````