Присваивание переменным в Python значения None
Является ли хорошим тоном присваивание переменным в Python значения None? Допустим, у меня есть переменная n, в которую я хочу занести какое-то значение из списка k, путём перебора циклом и проверки условия. Но я хочу и дальше использовать переменную n в своей программе. Как я знаю, в Python при объявлении переменной обязательна инициализация, но я не знаю каким значением её инициализировать. Правильна ли такая практика?
Ответы (1 шт):
Решил написать ответ, потому что все-таки есть случаи, когда инициализация переменных значением None имеет смысл.
Как я знаю, в Python при объявлении переменной обязательна инициализация...
Начиная с Python 3.6 можно объявлять переменные с аннотацией типа без инициализации:
some_var: SomeType
Но тогда для проверки "инициализированности" переменной (для локальной или глобальной переменной, не поля класса) придется использовать конструкцию 'some_var' in locals() или 'some_var' in globals(), что не очень красиво, ИМХО (вообще практически никогда не стоит использовать locals() и globals()). Если проверять заполненность переменной не нужно, то это неплохой вариант (но объявление с инициализацией лучше).
Для проверки полей класса можно использовать hasattr, что на мой взгляд вполне допустимо (см. п.3 ниже).
В целом нет никаких правил, запрещающих инициализировать переменную значением None. Типичные варианты использования:
Начальное значение переменной в которую будет будет записано одно из значений из последовательности при проходе по ней циклом. Типичный пример - начальное значение для максимума/минимума последовательности по какому-то критерию (можно конечно брать значение первого элемента за минимум/максимум, но тогда сначала нужно проверить, что последовательность не пустая)
Начальное/неопределенное состояние для конечного автомата
Начальные значения при "объявлении" полей объекта внутри метода
__init__. Например PyCharm фактически требует, чтобы все поля объекта были инициализированы внутри__init__(попытку записи в поле не объявленное внутри__init__PyCharm выделяет как предупреждение). Можно было бы на это правило и забить (отключить в настройках), но в этом есть смысл - удобно, когда все поля объекта объявлены в одном месте.В этом случае также имеет смысл аннотацией показывать предполагаемый тип поля:
class SomeClass: def __init__(self): # >= Python 3.6 self.a: int = None # < Python 3.6 self.b = None # type: intТакже начиная с Python 3.6 поля можно объявлять с аннотацией типа просто как
self.a: intбез инициализации, инициализированность поля в этом случае можно проверять с помощьюhasattr(self, 'a')(не факт что это хороший вариант, я бы все-таки использовал вариант с инициализациейNone).
Думаю, это не все варианты, возможно что-то забыл.
Также нужно понимать, что инициализация переменной значением None "на всякий случай" не убережет вас от невнимательности, и вместо падения программы с исключением NameError или AttributeError у вас может вылезти значение None там где оно совсем не ожидалось, и возможно будет сложнее отловить откуда оно взялось, чем в случае выбрасывания исключения (см. принцип Fail Fast). Я бы рекомендовал по возможности инициализировать переменные вменяемыми значениями, а не None.