Почему «.sort ()» заставляет список быть «Нет» в Python? - PullRequest
8 голосов
/ 20 марта 2012

Я пытаюсь отсортировать список Python из int s, а затем использовать функцию .pop(), чтобы вернуть самый высокий.Я пытался написать метод по-разному:

def LongestPath(T):    
    paths = [Ancestors(T,x) for x in OrdLeaves(T)]
    #^ Creating a lists of lists of ints, this part works
    result =[len(y) for y in paths ]
    #^ Creating a list of ints where each int is a length of the a list in paths
    result = result.sort()
    #^meant to sort the result
    return result.pop()
    #^meant to return the largest int in the list (the last one)

Я также пытался

def LongestPath(T):
    return[len(y) for y in [Ancestors(T,x) for x in OrdLeaves(T)] ].sort().pop()

В обоих случаях .sort() приводит к тому, что список будет None (который имеетнет .pop() функция и возвращает ошибку).Когда я удаляю .sort(), он работает нормально, но не возвращает наибольшее значение int, поскольку список не отсортирован.

Ответы [ 8 ]

20 голосов
/ 20 марта 2012

Просто удалите назначение из

result = result.sort()

оставляя только

result.sort()

Метод sort работает на месте (он изменяет существующий список), поэтому присваивание не требуется и возвращает None. Когда вы присваиваете его результат названию списка, вы присваиваете None.

Он может быть легко (и более эффективно) записан в виде одной строки:

max(len(Ancestors(T,x)) for x in OrdLeaves(T))

max работает за линейное время O (n), а сортировка - O (nlogn). Вам также не нужны вложенные списки, подойдет только одно выражение генератора.

9 голосов
/ 20 марта 2012

Это

result = result.sort()

должно быть таким

result.sort()

В Python существует соглашение, что методы, изменяющие последовательности, возвращают None.

Учтите:

>>> a_list = [3, 2, 1]
>>> print a_list.sort()
None
>>> a_list
[1, 2, 3]

>>> a_dict = {}
>>> print a_dict.__setitem__('a', 1)
None
>>> a_dict
{'a': 1}

>>> a_set = set()
>>> print a_set.add(1)
None
>>> a_set
set([1])

Часто задаваемые вопросы по дизайну и истории Python дает обоснование , стоящее за этим дизайнерским решением (относительно списков):

Почему нет list.sort() вернуть отсортированный список?

В ситуациях, когда производительность имеет значение, создание копии списка просто для его сортировки было бы расточительным.Поэтому list.sort() сортирует список по месту.Чтобы напомнить вам об этом факте, он не возвращает отсортированный список.Таким образом, вы не будете обмануты случайной перезаписью списка, когда вам нужна отсортированная копия, но вам также потребуется сохранить несортированную версию.

В Python 2.4 новая встроенная функция - sorted() -был добавлен.Эта функция создает новый список из предоставленной итерации, сортирует и возвращает ее.

4 голосов
/ 20 марта 2012

.sort() возвращает None и сортирует список по месту.

2 голосов
/ 20 марта 2012

На этот вопрос уже правильно ответили: list.sort() возвращает None. Причина, по которой «Разделение команд и запросов»:

http://en.wikipedia.org/wiki/Command-query_separation

Python возвращает None, потому что каждая функция должна что-то возвращать, и соглашение состоит в том, что функция, которая не выдает никакого полезного значения, должна возвращать None.

Я никогда прежде не видел вашего соглашения о том, чтобы ставить комментарий после строки, на которую он ссылается, но начинать комментарий с карата, чтобы указывать на строку. Пожалуйста, оставляйте комментарии перед строками, на которые они ссылаются.

Хотя вы можете использовать метод .pop(), вы также можете просто проиндексировать список. Последнее значение в списке всегда можно проиндексировать с помощью -1, потому что в Python отрицательные индексы «оборачиваются» и индексируются в обратном направлении от конца.

Но мы можем упростить еще больше. Единственная причина, по которой вы сортируете список, заключается в том, что вы можете найти его максимальное значение. Для этого в Python есть встроенная функция: max()

Использование list.sort() требует построения целого списка. Затем вы извлечете одно значение из списка и откажетесь от него. max() будет использовать итератор без необходимости выделять потенциально большой объем памяти для хранения списка.

Кроме того, в Python сообщество предпочитает использовать стандарт кодирования под названием PEP 8. В PEP 8 вы должны использовать строчные буквы для имен функций и подчеркивание для разделения слов, а не CamelCase.

http://www.python.org/dev/peps/pep-0008/

С учетом вышеизложенных комментариев, вот мое переписывание вашей функции:

def longest_path(T):
    paths = [Ancestors(T,x) for x in OrdLeaves(T)]
    return max(len(path) for path in paths)

Внутри вызова к max() у нас есть «выражение генератора», которое вычисляет длину для каждого значения в списке paths. max() будет извлекать значения из этого, сохраняя самое большое, пока все значения не будут исчерпаны.

Но теперь ясно, что нам даже не нужен список paths. Вот финальная версия:

def longest_path(T):
    return max(len(Ancestors(T, x)) for x in OrdLeaves(T))

Я на самом деле думаю, что версия с явной переменной paths немного более читабельна, но это не ужасно, и если может быть большое количество путей, вы можете заметить улучшение производительности из-за отсутствия сборки и уничтожить список paths.

1 голос
/ 20 марта 2012

list.sort() не возвращает список - он деструктивно изменяет сортируемый вами список:

In [177]: range(10)
Out[177]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [178]: range(10).sort()

In [179]:

Тем не менее, max находит самый большой элемент в списке и будет более эффективным, чем ваш метод.

0 голосов
/ 20 марта 2012

Вам не нужна пользовательская функция для того, чего вы хотите достичь, сначала вам нужно понять методы, которые вы используете!

sort() список в python делает это на месте, то есть возврат от sort() равен None.Сам список изменен , новый список не возвращен.

>>>results = ['list','of','items']
>>>results

['list','of','items']

>>>results.sort()
>>>type(results)

<type 'list'>

>>>results

['items','list','of']

>>>results = results.sort()
>>>results
>>>
>>>type(results)

<type 'NoneType'>

Как вы можете видеть, когда вы пытаетесь присвоить sort(), выбольше не имеет тип списка.

0 голосов
/ 20 марта 2012

Есть ли причина не использовать функцию sorted ?sort() определяется только в списках, но sorted() работает с любыми итерациями и работает так, как вы ожидаете.Подробнее о сортировке см. в этой статье .

Кроме того, поскольку внутренне он использует timsort , он очень эффективен, если вам нужно отсортировать по ключу 1, а затем отсортировать по ключу2.

0 голосов
/ 20 марта 2012

В Python sort() - операция на месте.Таким образом, result.sort() возвращает None, но изменяет result для сортировки.Поэтому, чтобы избежать вашей проблемы, не перезаписывайте result при звонке sort().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...