Что такое pythonic способ объявления переменных?

Обычно объявление переменных при назначении считается лучшей практикой в ​​VBScript или JavaScript, например, хотя это разрешено.

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

Как бы вы избежали такой ситуации?

В python это помогает думать об объявлении переменных как обязательных значений для имен.

Старайтесь не ошибаться, или у вас появятся новые (при условии, что вы говорите о заявлениях о присваивании – ссылки на них вызовут исключение).

Если вы говорите об переменных экземпляра, вы не сможете использовать их впоследствии.

Например, если у вас был класс myclass и в его методе __init__ написано self.myvar = 0 , то попытка обращения к self.myvare вызовет ошибку, а не даст вам значение по умолчанию.

Это глупый артефакт вдохновения Python «преподаванием языков», и он помогает сделать язык более доступным, полностью удалив камень преткновения «объявления». По какой бы то ни было причине (вероятно, представленной как «простота»), Python никогда не получал необязательного ограничения, такого как VB «Option Explicit», чтобы ввести обязательные декларации. Да, это может быть источником ошибок, но, как показывают другие ответы, хорошие кодеры могут разрабатывать привычки, которые позволяют им компенсировать практически любой недостаток на этом языке – и, как недостатки, это довольно незначительный.

Если вам нужен класс с атрибутами экземпляра «заблокирован», его нетрудно сделать, например:

 class LockedDown(object): __locked = False def __setattr__(self, name, value): if self.__locked: if name[:2] != '__' and name not in self.__dict__: raise ValueError("Can't set attribute %r" % name) object.__setattr__(self, name, value) def _dolock(self): self.__locked = True class Example(LockedDown): def __init__(self): self.mistakes = 0 self._dolock() def onemore(self): self.mistakes += 1 print self.mistakes def reset(self): self.mitsakes = 0 x = Example() for i in range(3): x.onemore() x.reset() 

Как вы увидите, вызовы x.onemore работают нормально, но reset вызывает исключение из-за неправильного написания атрибута как mitsakes . Правила взаимодействия здесь состоят в том, что __init__ должен установить все атрибуты на начальные значения, а затем вызвать self._dolock() чтобы запретить дальнейшее добавление атрибутов. Я освобождаю «супер-частные» атрибуты (те, которые начинаются с __ ), которые стилистически следует использовать очень редко, для совершенно определенных ролей и с крайне ограниченными возможностями (что делает тривиальным выявлять опечатки в тщательном осмотре, который необходим во всяком случае, чтобы подтвердить необходимость супер-конфиденциальности), но это стилистический выбор, легко меняющийся; аналогично для выбора сделать «заблокированное» состояние «необратимым» (под «нормальным» означает – т.е. требует очень явного обходного пути для обхода).

Это не относится к другим типам имен, таких как функционально-локальные; опять же, не имеет большого значения, потому что каждая функция должна быть очень малой и полностью автономной областью, тривиально легко проверяемой (если вы пишете функции на 100 строк, у вас есть другие серьезные проблемы ;-).

Стоит ли это беспокоиться? Нет, потому что полуприличные модульные тесты должны, очевидно, лучше всего улавливать все такие опечатки, как естественный побочный эффект, который полностью выполняет функциональность класса. Другими словами, это не так, как будто вам нужно иметь больше модульных тестов, чтобы улавливать опечатки: вам нужно все же тестировать юниты, чтобы поймать тривиальные семантические ошибки (по одному, +1, где -1 означает, и т. Д. и т. д.) уже поймают все опечатки.

Роберт Мартин и Брюс Эккель сформулировали этот момент 7 лет назад в отдельных и независимых статьях – блог Экеля временно отсутствует прямо сейчас, но Мартин прямо здесь , и когда сайт Экеля оживает, статья должна быть здесь . Тезис спорный (например, Джефф Этвуд и его комментаторы обсуждают его здесь ), но интересно отметить, что Мартин и Эккель являются известными экспертами статических языков, таких как C ++ и Java (хотя и с любовью, соответственно, с Ruby и Python), и они далеки от единственных, которые обнаружили важность модульных тестов … и как хороший набор модульных тестов, как побочный эффект, делает жесткость статического языка излишней.

Кстати, один из способов проверить ваши тестовые комплекты – это «ввод ошибок»: систематически переходите через свою кодовую базу, вводя одну неправильную орфографию, – запустите тесты, чтобы убедиться, что они не сработают, если они не добавят один, который не срабатывает, исправьте орфографическую ошибку, повторите. Может быть довольно хорошо автоматизирован (а не «добавить тестовую» часть, а найти возможные ошибки, которые не покрываются пакетом), а также некоторые другие формы ошибок при введении (каждый раз меняйте каждую целую константу еще один, и еще один, измените каждый < to <= т. д., замените каждое, if и в while условие на его обратное; …), в то время как другие формы инъекции ошибок требуют гораздо более человеческого понимания. К сожалению, я не знаю общедоступных наборов фреймворков ошибок (для любого языка) – может стать отличным проектом с открытым исходным кодом ;-).

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

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

  python -c "import py_compile; py_compile.compile('{filename}')" 

на функцию, которая будет вызываться при сохранении файла.

Если вы будете серьезно заниматься разработкой, вы будете использовать (интегрированную) среду разработки. Пилинт будет частью этого и расскажет вам все ваши орфографические ошибки. Не нужно делать такую ​​особенную часть langauge.

Контрольная работа.

Например, с файлом variable.py :

 #! /usr/bin/python somevar = 5 

Затем сделайте файл variable.txt (чтобы провести тесты):

 >>> import variables >>> variables.somevar == 4 True 

Затем выполните:

 python -m doctest variable.txt 

И получить:

 ********************************************************************** File "variables.txt", line 2, in variables.test Failed example: variables.somevar == 4 Expected: True Got: False ********************************************************************** 1 items had failures: 1 of 2 in variables.test ***Test Failed*** 1 failures. 

Это показывает неверную переменную.

Пытаться:

 >>> import variables >>> variables.someothervar == 5 True 

Обратите внимание, что переменная не называется одинаковой.

 ********************************************************************** File "variables.test", line 2, in variables.test Failed example: variables.someothervar == 5 Exception raised: Traceback (most recent call last): File "/usr/local/lib/python2.6/doctest.py", line 1241, in __run compileflags, 1) in test.globs File "<doctest variables.test[1]>", line 1, in <module> variables.someothervar == 5 AttributeError: 'module' object has no attribute 'someothervar' ********************************************************************** 1 items had failures: 1 of 2 in variables.test ***Test Failed*** 1 failures. 

Это показывает переменную с ошибкой.

 >>> import variables >>> variables.somevar == 5 True 

И это возвращается без ошибок.

Я сделал достаточно VBScript-разработки, чтобы знать, что опечатки являются проблемой в имени переменной, и достаточно VBScript-разработки, чтобы знать, что Option Explicit – это костыль в лучшем случае. (<- 12 лет опыта ASP VBScript научили меня, что трудный путь.)

Объявление переменной не предотвращает ошибок. Больше, чем отсутствие объявления переменных, вызывает ошибки.

Объявления переменных предотвращают один конкретный тип ошибок, но он создает ошибки других типов.

Предотвратить . Написание кода, где есть попытка установить (или изменить) переменную с неправильным типом данных.

Причины . Глупые обходные пути, чтобы объединить несколько несвязанных типов, чтобы задания «просто работали». Пример: union языка C. Кроме того, объявления переменных заставляют нас использовать броски. Который также заставляет нас подавлять предупреждения о приведениях во время компиляции, потому что мы «знаем», что это «просто сработает». И это не так.

Недостаток объявлений переменных не вызывает ошибок. Наиболее распространенный «сценарий угрозы» – это своего рода «неправильное присвоение» переменной.

  1. Была ли переменная «повторно использована»? Это глупо, но законно и работает.

  2. Была ли некоторая часть программы неправильно назначать неправильный тип?

    Это приводит к тонкому вопросу о том, «что неправильно значит?» На утином языке неверные средства «Не предлагают правильные методы или атрибуты». Которая все еще туманна. В частности, это означает, что «типу будет предложено предоставить метод или атрибут, которого он не имеет». Это вызовет исключение, и программа остановится.

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

«не может ли это вызвать ошибки, потому что вы ошибочно написали имя переменной»

Да. Оно может.

Но рассмотрим этот Java-код.

 public static void maine( String[] argv ) { int main; int mian; } 

Опечатка здесь также смертельна. Статически типизированная Java ничего не сделала, чтобы предотвратить появление ошибки с ошибкой.