Вызывать функцию int () для каждого элемента списка?


184

У меня есть список с числовыми строками, вот так:

numbers = ['1', '5', '10', '8'];

Я хотел бы преобразовать каждый элемент списка в целое число, чтобы оно выглядело так:

numbers = [1, 5, 10, 8];

Я мог бы сделать это с помощью цикла, например, так:

new_numbers = [];
for n in numbers:
    new_numbers.append(int(n));
numbers = new_numbers;

Это должно быть так ужасно? Я уверен, что есть более питонский способ сделать это в одной строке кода. Пожалуйста, помогите мне.


1
Какую версию Python вы используете?
Марк Байерс

Ответы:



131

В Python 2.x другой подход заключается в использовании map:

numbers = map(int, numbers)

Примечание: в Python 3.x mapвозвращается объект карты, который вы можете преобразовать в список, если хотите:

numbers = list(map(int, numbers))

11
В Python 3.x mapвозвращает итератор вместо списка, поэтому его нужно записать так, как list(map(int, numbers))если бы он был нужен.
Кеннитм

2
Я думаю, что в настоящее время подход к пониманию списка более предпочтителен.
Extraneon

3
@extraneon: Да ... или, возможно, рассмотрите использование генератора вместо списка, в зависимости от того, для чего вы будете его использовать. Преимущество генератора в том, что если вам не нужно смотреть на все элементы, вам не придется тратить время на их предварительный расчет.
Марк Байерс

4
Измеряется с timeit под Python 2.7.2: LC: 3.578153133392334, карта: 4.9065070152282715
AJJ

1
@AJJ: mapимеет более высокие накладные расходы на установку, но в ссылочном интерпретаторе, если функция преобразования является встроенной функцией Python, реализованной в C, она имеет меньшую стоимость на единицу. Тестирование на входе только четырех значений не даст полезной информации о масштабировании. Тем не менее, в моих собственных тестах (на Py2.7.12 и Py3.5.2, последний с list()переносом), Py2 mapвыиграл даже для четырехэлементных входов и проигрывает лишь с небольшим отрывом от Py3; Я подозреваю, что ваши тесты были искажены в пользу списков.
ShadowRanger

21

просто точка,

numbers = [int(x) for x in numbers]

понимание списка более естественно, в то время как

numbers = map(int, numbers)

быстрее.

Вероятно, это не будет иметь значения в большинстве случаев

Полезно читать: LP против карты


6
Разве это не должно быть число = карта (целое число)?
Каран

9

Если вы намереваетесь передать эти целые числа в функцию или метод, рассмотрите этот пример:

sum(int(x) for x in numbers)

Эта конструкция намеренно удивительно похожа на списки, упомянутые Адамком. Без квадратных скобок это называется выражением генератора , и это очень эффективный способ передачи списка аргументов методу. Хорошее обсуждение доступно здесь: выражения генератора и понимание списка


4

Еще один способ сделать это в Python 3:

numbers = [*map(int, numbers)]


1
Вы можете это объяснить? Я не знаком с этим синтаксисом. Спасибо!
abalter

1
Я использую распаковку списка аргументов ( docs.python.org/3/tutorial/… )
zhukovgreen

Ага, питон 3 вещь. Кажется странным иметь []список аргументов. И я не знал, что вы можете передать итератор в качестве списка аргументов. Я бы подумал сделать number = list(map(int, numbers)). Но спасибо за объяснение!
abalter

3

По-другому,

for i, v in enumerate(numbers): numbers[i] = int(v)

6
OP сказал вещий
SilentGhost

3
Этот способ очень полезен, если вы хотите выполнить операцию только над некоторыми элементами в списке. Это не относится к вопросу в этой теме, но могут быть случаи, когда это полезно
Dikla

1

Думаю, я соберу ответы и покажу некоторые 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генератора (спасибо Артему!) Еще немного быстрее.

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 элемента, по-видимому, являются точкой пересечения (3 в Python 2), где понимание происходит немного быстрее, хотя распаковка генератора все же происходит быстрее, чем для списков с более чем 1 элементом.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.