Какой питонический способ объявления переменных?

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

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

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

Ответ 1

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

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

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

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

Ответ 2

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

Ответ 3

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

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 лет назад в отдельных и независимых статьях - блог Eckel временно отсутствует прямо сейчас, но Martin right здесь, и когда сайт Eckel оживает, статья должна быть здесь. Тезис противоречив (например, Джефф Аттвуд и его комментаторы обсуждают это здесь), но интересно отметить, что Мартин и Эккель оба хороши известные эксперты статических языков, таких как С++ и Java (хотя и с любовью, соответственно, с Ruby и Python), и они далеко не единственные, кто обнаружил важность модульных тестов... и как хороший unit-tests suite, как побочный эффект, делает излишнюю жесткость языка.

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

Ответ 4

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

Ответ 5

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

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

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

Ответ 6

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

Ответ 7

Test.

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

#! /usr/bin/python

somevar = 5

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

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

Тогда do:

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.

Показывает переменную, объявленную неправильно.

Try:

>>> 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 научили меня, что трудный путь.)

Ответ 8

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

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

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

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

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

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

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

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

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

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

Да. Он может.

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

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

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