Почему `for x в списке [None: None]:` work?
У меня есть script, который пытается прочитать начальную и конечную точку для подмножества через двоичный поиск, затем эти значения используются для создания среза для дальнейшей обработки.
Я заметил, что, когда эти переменные не были установлены (поиск вернулся Нет), код все равно будет работать, и в конце я заметил, что срез, охватывающий от None до None, работает так, как если бы он просматривал весь список (см. пример ниже).
#! /usr/bin/env python
list = [1,2,3,4,5,6,7,8,9,10]
for x in list[None:None]:
print x
Кто-нибудь знает, почему был сделан выбор, чтобы увидеть list[None:None]
просто как list[:]
, по крайней мере, то, что я думаю, что это происходит (исправьте меня, если я ошибаюсь). Я лично подумал бы, что в таком случае желательно было бы выбрасывать TypeError.
Ответы
Ответ 1
Потому что None
является по умолчанию для позиций среза. Вы можете использовать либо None
, либо полностью исключить это значение, после чего вам будет отправлен None
.
None
- это значение по умолчанию, потому что вы можете использовать отрицательный шаг, после чего изменяется начальная и конечная позиции по умолчанию. Сравните list[0:len(list):-1]
с list[None:None:-1]
, например.
Python использует None
для значения, не указанного в стандартной библиотеке; это не исключение.
Обратите внимание: если ваш класс реализует object.__getitem__
hook, вы получите переданный объект slice()
с атрибутами start, end и stride, установленными на None
:
>>> class Foo(object):
... def __getitem__(self, key):
... print key
...
>>> Foo()[:]
slice(None, None, None)
Так как Foo()
даже не реализует __len__
, использующий по умолчанию использование None
, здесь вполне логично.
Ответ 2
Я также считаю, что list[None:None]
интерпретируется как list[:]
. Это удобное поведение, потому что вы можете сделать что-то вроде этого:
return list[some_params.get('start'):some_params.get('end')]
Если раскладка списка не будет работать с None
, вам нужно будет проверить, были ли start
и end
None
сами:
if some_params.get('start') and some_params.get('end'):
return list[some_params.get('start'):some_params.get('end')]
elif some_params.get('start'):
return list[some_params.get('start'):]
elif end:
return list[:some_params.get('end')]
else:
return list[:]
К счастью, это не относится к Python:).
Ответ 3
None
является обычным представлением для параметра, не заданного, поэтому вы можете передать этот факт функции. Вы часто увидите функции или методы, объявленные таким образом
def f(p=None):
if f is None:
f = some_default_value()
Я думаю, это делает выбор понятным: используйте None
, вы можете сказать slicer использовать его значения по умолчанию.