我有一个带有数字字符串的列表,如下所示:
numbers = ['1', '5', '10', '8'];
我想将每个列表元素转换为整数,所以它看起来像这样:
numbers = [1, 5, 10, 8];
我可以使用循环来做到这一点,如下所示:
new_numbers = [];
for n in numbers:
new_numbers.append(int(n));
numbers = new_numbers;
有必要这么丑吗?我敢肯定有一种更 Pythonic 的方式可以在一行代码中做到这一点。请帮帮我。
这就是 list comprehensions 的用途:
numbers = [ int(x) for x in numbers ]
在 Python 2.x 中,另一种方法是使用 map
:
numbers = map(int, numbers)
注意:在 Python 3.x map
中返回一个地图对象,您可以根据需要将其转换为列表:
numbers = list(map(int, numbers))
map
返回迭代器而不是列表,因此如果需要列表,则需要将其写为 list(map(int, numbers))
。
map
具有较高的设置开销,但在参考解释器上,如果转换函数是用 C 实现的 Python 内置函数,则它的每项成本较低。仅对四个值的输入进行测试不会提供有关缩放的有用信息。也就是说,在我自己的测试中(在 Py2.7.12 和 Py3.5.2 上,后者带有 list()
包装),带有 map
的 Py2 甚至在四个元素输入时都赢了,而在 Py3 上只输了一点点;我怀疑您的测试被扭曲以支持 listcomps。
只是一点,
numbers = [int(x) for x in numbers]
列表理解更自然,而
numbers = map(int, numbers)
是比较快的。
在大多数情况下,这可能无关紧要
有用的阅读:LP vs map
如果您打算将这些整数传递给函数或方法,请考虑以下示例:
sum(int(x) for x in numbers)
这种结构故意与 adamk 提到的列表推导非常相似。没有方括号,它被称为生成器表达式,是一种将参数列表传递给方法的非常节省内存的方法。此处提供了很好的讨论:Generator Expressions vs. List Comprehension
在 Python 3 中实现它的另一种方法:
numbers = [*map(int, numbers)]
然而,理想情况下,您可能会对 map 感到满意,因为它返回了一个迭代器:
numbers = map(int, numbers)
[]
采用参数列表似乎很奇怪。而且,我不知道您可以将迭代器作为参数列表传递。我本来想做number = list(map(int, numbers))
。但是感谢您的解释!
另一种方式,
for i, v in enumerate(numbers): numbers[i] = int(v)
以为我会合并答案并显示一些 timeit
结果。
Python 2 在这方面做得很糟糕,但 map
比理解要快一些。
Python 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:42:59) [MSC v.1500 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> setup = """import random
random.seed(10)
l = [str(random.randint(0, 99)) for i in range(100)]"""
>>> timeit.timeit('[int(v) for v in l]', setup)
116.25092001434314
>>> timeit.timeit('map(int, l)', setup)
106.66044823117454
Python 3 本身的速度快了 4 倍以上,但将 map
生成器对象转换为列表仍然比理解更快,并且通过解包 map
生成器(感谢 Artem!)来创建列表仍然稍微快一些。
Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> setup = """import random
random.seed(10)
l = [str(random.randint(0, 99)) for i in range(100)]"""
>>> timeit.timeit('[int(v) for v in l]', setup)
25.133059591551955
>>> timeit.timeit('list(map(int, l))', setup)
19.705547827217515
>>> timeit.timeit('[*map(int, l)]', setup)
19.45838406513076
注意:在 Python 3 中,4 个元素似乎是理解稍快的交叉点(Python 2 中的 3 个),尽管解包生成器仍然比具有超过 1 个元素的列表更快。
还可能值得注意的是,NumPy 在创建数组时会即时执行此操作:
import numpy as np
numbers = ['1', '5', '10', '8']
numbers = np.array(numbers,
dtype=int)
numbers
array([ 1, 5, 10, 8])
不定期副业成功案例分享