Как сделать константу в питоне

Добавил пользователь Дмитрий К.
Обновлено: 05.10.2024

Есть ли способ объявить константу в Python? В Java мы можем создавать постоянные значения таким образом:

Что такое эквивалент объявления Java-декларации выше в Python?

Нет, нет. Вы не можете объявить переменную или значение как константу в Python. Просто не меняйте его.

Если вы находитесь в классе, эквивалент будет:

Если нет, это просто

Но вы можете захотеть взглянуть на фрагмент кода Константы в Python от Alex Martelli.

Нет ключевого слова const , как на других языках, однако возможно создать свойство, в котором имеет функцию "getter" для чтения данных, но no "setter function" , чтобы перезаписать данные. Это существенно защищает идентификатор от изменения.

Вот альтернативная реализация, использующая свойство класса:

Обратите внимание, что код далеко не прост для читателя, интересующегося константами. См. Объяснение ниже

Объяснение кода:

  • Определите функцию constant , которая принимает выражение и использует его для построения "getter" - функции, которая возвращает значение выражения только.
  • Функция setter вызывает TypeError, поэтому он доступен только для чтения
  • Используйте функцию constant , которую мы только что создали, в качестве декора, чтобы быстро определить свойства только для чтения.

И каким-то другим более старомодным способом:

(Код довольно сложный, более подробные пояснения ниже)

Обратите внимание, что декоратор @apply кажется устаревшим.

  • Чтобы определить идентификатор FOO, firs определяют две функции (fset, fget - имена по моему выбору).
  • Затем используйте встроенную функцию property для создания объекта, который может быть "установлен" или "получить".
  • Обратите внимание, что функция property имеет два первых параметра: fset и fget .
  • Используйте тот факт, что мы выбрали эти имена для нашего собственного getter и setter и создаем словарный словарь с использованием ** (двойной звездочки), применяемый ко всем локальным определениям этой области для передачи параметров функции property

В Python вместо того, чтобы язык что-то принуждает, люди используют соглашения об именах, например __method , для частных методов и используя _method для защищенных методов.

Таким же образом вы можете просто объявить константу как все кепки, например.

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

Проблема только в том, что вам придется делать MY_CONSTANT(), но снова MY_CONSTANT = "one" является правильным способом в python (обычно).

Вы также можете использовать namedtuple для создания констант:

Мы определяем себя, как сделать себя экземпляром, а затем используем слоты, чтобы гарантировать, что никакие дополнительные атрибуты не могут быть добавлены. Это также удаляет __dict__ доступа __dict__ . Конечно, весь объект все еще может быть переопределен.

Edit - оригинальное решение

Я, вероятно, здесь не хватает трюк, но это, кажется, работает для меня:

Создание экземпляра позволяет волшебному методу __setattr__ и перехватывать попытки установить переменную FOO . Вы можете выбросить здесь исключение, если хотите. Создание экземпляра по имени класса предотвращает доступ напрямую через класс.

Это общая боль для одного значения, но вы можете присоединить много к вашему объекту CONST . Имя высшего класса также кажется немного нелепым, но я думаю, что в целом оно довольно лаконично.

Python не имеет констант.

Возможно, самая простая альтернатива - определить для нее функцию:

MY_CONSTANT() теперь имеет все функциональные возможности константы (плюс несколько раздражающих скобок).

В дополнение к двум верхним ответам (просто используйте переменные с именами UPPERCASE или используйте свойства, чтобы значения были доступны только для чтения), я хочу упомянуть, что можно использовать метаклассы для реализации именованных констант. Я предоставляю очень простое решение, используя метаклассы в GitHub, которые могут быть полезны, если вы хотите, чтобы значения были более информативными относительно их типа/имени:

Это немного более продвинутый Python, но все же очень прост в использовании и удобен. (В модуле есть еще несколько функций, включая константы, доступные только для чтения, см. Его README.)

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

Изменение: Добавлен пример кода для Python 3

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

Это предотвращает изменение свойств статики. Затем создайте другой класс, который использует этот метакласс:

Или, если вы используете Python 3:

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

Теперь реквизит, доступ к которому осуществляется напрямую или через экземпляр, должен быть постоянным:

Вот пример выше в действии. Вот еще один пример для Python 3.

Свойства - один из способов создания констант. Вы можете сделать это, объявив свойство getter, но игнорируя setter. Например:

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

Вот реализация класса "Константы", который создает экземпляры с постоянными атрибутами только для чтения. Например, можно использовать Nums.PI для получения значения, которое было инициализировано как 3.14159 , а Nums.PI = 22 вызывает исключение.

Спасибо @MikeGraham FrozenDict, который я использовал в качестве отправной точки. Изменено, поэтому вместо Nums['ONE'] используется синтаксис Nums.ONE .

И спасибо ответу @Raufio, за идею переопределить __setattr __.

Или для реализации с большей функциональностью, смотрите @Hans_meine's named_constants на GitHub

Вы можете использовать namedtuple в качестве обходного пути для эффективного создания константы, которая работает так же, как статическая конечная переменная в Java (Java-"константа"). Поскольку обходные пути идут, это отчасти изящно. (Более элегантный подход - просто улучшить язык Python - какой язык позволяет вам переопределить math.pi ? - но я отвлекся.)

(Когда я пишу это, я понимаю другой ответ на этот вопрос, упомянутый namedtuple, но я продолжу здесь, потому что я покажу синтаксис, который более точно соответствует тому, что вы ожидаете в Java, так как нет необходимости создавать именованный введите как namedtuple заставляет вас делать.)

Следуя вашему примеру, вы помните, что в Java мы должны определить константу внутри некоторого класса; потому что вы не упомянули имя класса, давайте назовем его Foo . Вот класс Java:

Здесь эквивалент Python.

Ключевой момент, который я хочу добавить, заключается в том, что вам не нужен отдельный тип Foo ("анонимный именованный кортеж" был бы хорош, даже если это звучит как оксюморон), поэтому мы называем наш namedtuple _Foo так что, надеюсь, это не ускользнет от импорта модулей.

Вторым моментом здесь является то, что мы немедленно создаем экземпляр именного кортежа, называя его Foo ; нет необходимости делать это в отдельном шаге (если вы этого не хотите). Теперь вы можете делать то же, что и в Java:

Но вы не можете назначить это:

Подтверждение: я думал, что изобрел подход именованных кортежей, но потом я вижу, что кто-то другой дал аналогичный (хотя и менее компактный) ответ. Затем я также заметил, что называются кортежами " в Python?, что указывает на то, что sys.version_info теперь именованный кортеж, поэтому, возможно, стандартная библиотека Python уже предложила эту идею гораздо раньше.

Обратите внимание, что, к сожалению (это все еще Python), вы можете полностью стереть все назначение Foo :

Конспект 4 главы с примерами написанных мной программ:

Циклы for

Мы уже знаем циклы с оператором while , и даже сделали много задач. Помните, там вводится перед циклом управляющая переменная, которая затем используется в условии, которое в свою очередь проверяется на истинность каждый круг цикла. Так вот с циклом for все немного иначе.

В цикле for не используется условная конструкция для проверки — делать или не делать. Цикл for исполняется циклично для всех элементов последовательности. Как только для каждого элемента последовательности цикла был повторен код, цикл завершается. Проще говоря, конструкция с for — это цикл с предусловием или цикл с параметром. Суть работы этого цикла сводится к перебору значений в последовательности.

Что это за последовательность цикла for , о чем вообще идет речь? Я тоже не сразу врубилась, в чем отличие этих циклов от тех, с которыми мы работали ранее. Дело в том, что for по сути просто повторяет одно и то же действие (тело цикла) для заранее указанного списка элементов (последовательности), который явно указан в самом цикле. Общий вид цикла for :

Последовательность может быть любой — числовой или строкой текста. Переменные могут вводится как до цикла for , так и внутри него. Во многих языках программирования есть циклы for, но в Python для этого цикла реализована большая свобода действий и нет необходимости использовать счетчик (инкремент / декремент).

Но если вы все-таки хотите использовать счетчик, то можно среди элементов последовательности ввести переменную-счетчик, которая в Python обычно обозначается одним из трех символов:

Цикл for позволяет организовать последовательный доступ к элементам последовательности.

Работу цикла for проще всего увидеть на примере:

В этой программе инициализация идет через переменную bukva в последовательности строкового типа word (то, что вводит пользователь). Пользователь вводит любой текст, а программа выводит этот текст по букве на каждой строке.


Функция range() для цифровой последовательности

Общий вид функции range():

Интервал может быть как положительным значением, так и отрицательным. Если интервал -1 , то программа будет вести счет, уменьшая значение каждый раз на 1.

🐍 Идея!
Если нужно просто повторить какое-то действие заданное число раз, то можно не писать переменную в цикле for , а просто использовать цикл с функцией range()


Работу функции range() в цикле for проще всего увидеть на примере:

Задача: Написать программу, которая 1) выводит все целые числа от 0 до 10 в строчку; 2) Перечисляет целые числа от 0 до 10, кратные 10; 3) Выводит все целые числа от 0 до 10 в обратном порядке.


Функция len()

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


Оператор in

Общий вид использования оператора in является условием, проверяющимся каждый раз на истинность и ложность:


Индексация элементов последовательности

Цикл for обычно просто перебирает все элементы последовательности подряд по очереди, если нам нужно достать какой-то конкретный элемент, то после имени переменной, задающей последовательность, ставим в квадратных скобках порядковый номер элемента (индекс — счет идет с нуля):

Индексы бывают двух типов:

  • с положительными номерами (счет начинается с 0 и идет вперед);
  • с отрицательными номерами (счет идет с -1 , начинается с конца строки и идет влево).

Пример использования индексации показан в задаче:

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


Задача: Написать программу, которая дает пользователю ввести текст, а потом печатает только гласными буквами.

Срезы строк

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

Срезы создаются указанием индекса начала и конца последовательности в квадратных скобках аналогично как и в индексировании:

0 1 2 3 4 5
т е к с т
-5 -4 -3 -2 -1

Общий вид среза:

Важно помнить, что число1 всегда должно быть больше номером, чем число2 , чтобы программа выдала правильное значение.

Можно сократить запись среза, опустив число1 , тогда началом среза будет считаться первый элемент. Запись будет такая:

Можно опускать и конец, тогда по умолчанию концом среда будет конец последовательности. Запись аналогична предыдущей.

Если опустить все числа, то получится text[:] и это означает срез-копию всей последовательности.

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

Кортежи

Кортеж в Python — это объединение любых типов данных в группу.

Общий вид кортежа: переменная=()

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

Кортежи — это более гибкие конструкции, чем массивы, ведь в кортеже можно хранить одновременно и текст, и числа, и мультимедиа.

Задача: Написать программу, которая выводит на экран содержимое сумочки, организованное через кортеж.

Программа получилась такая:

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

Фух! Написала программу анаграммы. Часа два писала, было много затыков. Старалась не ориентироваться на учебник, а делать так, как мне кажется. В итоге, все заработало:

Есть ли способ объявить константу в Python? В Java мы можем создавать постоянные значения следующим образом:

Что эквивалентно приведенному выше объявлению константы Java в Python?

Нет там нет. Вы не можете объявить переменную или значение как константу в Python. Просто не меняй это.

Если вы находитесь в классе, эквивалент будет:

если нет, то это просто

Но вы можете взглянуть на фрагмент кода Константы в Python Алекса Мартелли.

Здесь нет ключевого слова const , как в других языках, однако можно создать свойство, которое имеет "функцию получения" для чтения данных, но нет "функции установки" для переписать данные. Это по существу защищает идентификатор от изменения.

Вот альтернативная реализация, использующая свойство класса:

Обратите внимание, что код не так прост для читателя, интересующегося константами. Смотрите объяснение ниже

Объяснение кода:

  1. Определите функцию constant , которая принимает выражение и использует его для создания "получателя" - функции, которая возвращает только значение выражения.
  2. Функция setter вызывает TypeError, поэтому она доступна только для чтения
  3. Используйте функцию constant , которую мы только что создали в качестве украшения, для быстрого определения свойств только для чтения.

И каким-то другим более старомодным способом:

(код довольно сложный, дополнительные пояснения приведены ниже)

Обратите внимание, что декоратор @apply устарел.

  1. Для определения идентификатора FOO, firs определяют две функции (fset, fget - имена на мой выбор).
  2. Затем используйте встроенную функцию property для создания объекта, который может быть "установлен" или "получен".
  3. Обратите внимание, что первые два параметра функции property названы fset и fget .
  4. Используйте тот факт, что мы выбрали эти самые имена для наших собственных методов получения и установки и создаем словарь-ключевое слово, используя ** (двойная звездочка), применяемый ко всем локальным определениям этой области, чтобы передать параметры в функцию property

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

Таким же образом вы можете просто объявить константу как все заглавные буквы, например.

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

Единственная проблема везде, где вам придется делать MY_CONSTANT (), но опять же MY_CONSTANT = "one" - правильный путь в python (обычно).

Вы также можете использовать namedtuple для создания констант:

Мы определяем себя, как сделать себя экземпляром, а затем используем слоты, чтобы гарантировать, что никакие дополнительные атрибуты не могут быть добавлены. Это также удаляет маршрут доступа __dict__ . Конечно, весь объект все еще может быть переопределен.

Правка - Исходное решение

Я, вероятно, здесь не хватает трюк, но это, кажется, работает для меня:

Создание экземпляра позволяет волшебному методу __setattr__ включать и перехватывать попытки установить переменную FOO . Вы можете выбросить здесь исключение, если хотите. Создание экземпляра по имени класса предотвращает доступ напрямую через класс.

Это одно удовольствие, но вы можете присоединить много к своему объекту CONST . Наличие высшего класса, имя класса также кажется немного нелепым, но я думаю, что в целом оно довольно лаконично.

Python не имеет констант.

Возможно, самая простая альтернатива - определить для нее функцию:

MY_CONSTANT() теперь имеет все функциональные возможности константы (плюс некоторые раздражающие скобки).

В дополнение к двум основным ответам (просто используйте переменные с именами UPPERCASE или используйте свойства, чтобы сделать значения доступными только для чтения), я хочу упомянуть, что для реализации можно использовать метаклассы именованные константы. Я предоставляю очень простое решение с использованием метаклассов в GitHub , которое может быть полезно, если вы хотите, чтобы значения были более информативными относительно их типа/имени:

Это немного более продвинутый Python, но все же очень простой в использовании и удобный. (Модуль имеет еще несколько функций, включая константы, доступные только для чтения, см. Его README.)

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

Правка: Добавлен пример кода для Python 3

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

Это предотвращает изменение статических свойств. Затем создайте другой класс, который использует этот метакласс:

Или, если вы используете Python 3:

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

Теперь реквизиты, доступ к которым осуществляется напрямую или через экземпляр, должны быть постоянными:

Вот пример выше в действии. Вот еще один пример для Python 3.

Свойства являются одним из способов создания констант. Вы можете сделать это, объявив свойство getter, но игнорируя его. Например:

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

Вот реализация класса "Константы", который создает экземпляры с постоянными атрибутами только для чтения. Например. можно использовать Nums.PI , чтобы получить значение, которое было инициализировано как 3.14159 , и Nums.PI = 22 вызывает исключение.

Благодаря @ MikeGraham's FrozenDict , который я использовал в качестве отправной точки. Изменено, поэтому вместо Nums['ONE'] используется синтаксис Nums.ONE .

И спасибо ответу @ Raufio, за идею переопределить __setattr __.

Или для реализации с большей функциональностью, см. @Hans_meine's named_constants в GitHub

файл constants.py

Если этого недостаточно, см. Полный тестовый сценарий для этого.

Преимущества: 1. Доступ ко всем константам для всего проекта 2. Строгий контроль значений констант

Недостатки: 1. Не поддержка пользовательских типов и типа 'dict'

Протестировано с Python3.4 и Python3.5 (я использую 'tox' для него)

Я хотел бы создать класс, который переопределяет метод __setattr__ базового класса объектов, и обернуть мои константы этим, заметьте, что я использую python 2.7:

Чтобы обернуть строку:

Это довольно просто, но если вы хотите использовать свои константы так же, как и непостоянный объект (без использования constObj.value), это будет немного интенсивнее. Возможно, это может вызвать проблемы, поэтому лучше оставить .value показывать и знать, что вы выполняете операции с константами (хотя, возможно, не самым "питоническим" способом).

Вы можете использовать именованный кортеж в качестве обходного пути для эффективного создания константы, которая работает так же, как статическая конечная переменная в Java (Java "константа"). Как обходные пути идут, это вроде элегантно. (Более элегантным подходом было бы просто улучшить язык Python - какой язык позволяет переопределить math.pi ? - но я отвлекся.)

(Когда я пишу это, я понимаю другой ответ на этот вопрос, упомянутый namedtuple, но я продолжу здесь, потому что я покажу синтаксис, который более точно соответствует тому, что вы ожидаете в Java, так как нет необходимости создавать именованный введите , как вас заставит namedtuple.)

Следуя вашему примеру, вы помните, что в Java мы должны определить константу внутри некоторого класса ; потому что вы не упомянули имя класса, давайте назовем его Foo . Вот класс Java:

Вот эквивалентный Python.

Ключевой момент, который я хочу добавить здесь, заключается в том, что вам не нужен отдельный тип Foo ("анонимный по имени Tuple" будет Nice, хотя это звучит как оксюморон), поэтому мы называем наш namedtuple _Foo , чтобы, надеюсь, он победил ускользнуть от импорта модулей.

Вторым моментом здесь является то, что мы немедленно создаем экземпляр nametuple, называя его Foo ; нет необходимости делать это в отдельном шаге (если вы этого не хотите). Теперь вы можете делать то, что вы можете делать в Java:

Но вы не можете назначить это:

Подтверждение: я думал, что изобрел подход именованного кортежа, но потом я вижу, что кто-то другой дал аналогичный (хотя и менее компактный) ответ. Затем я также заметил Что такое "именованные кортежи" в Python? , что указывает на то, что sys.version_info теперь является именованным кортежем, поэтому, возможно, стандартная библиотека Python уже пришла в голову эта идея гораздо раньше.

Обратите внимание, что, к сожалению (это все еще Python), вы можете полностью стереть все назначение Foo :

Но, по крайней мере, мы предотвращаем изменение значения Foo.CONST_NAME , и это лучше, чем ничего. Удачи.

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

Чтобы проверить значение этой переменной, используйте что-то похожее на это:

Если вы попытаетесь изменить это значение, возникнет ошибка.

Pythonic способ объявления "констант" в основном является переменной уровня модуля:

А затем напишите свои классы или функции. Поскольку константы почти всегда являются целыми числами, и они также неизменны в Python, у вас очень мало шансов изменить его.

Есть ли способ объявить константу в Python? В Java мы можем создавать постоянные значения таким образом:

Что такое эквивалент объявления Java-декларации выше в Python?

на самом деле способ создания переменных только для чтения возможен через функцию / декоратор свойств python. Ответ инв является примером пользовательского использования этого. свойство более общего использования, чем это, тем не менее, хороший анализ того, как это работает, находится на атрибутах и методах Python Шалаба Чатурведи.

ИМХО, принуждение к постоянству "не пифонично". В Python 2.7 вы даже можете написать True=False , а затем (2+2==4)==True возвращает False .

Как показывают другие ответы, нет никакого способа или необходимости объявлять константы. Но вы можете прочитать этот PEP о конвенциях. например, THIS_IS_A_CONSTANT

@osa: Вы не можете сделать это в Python 3 - SyntaxError: can't assign to keyword . Это похоже на хорошую вещь.

34 ответа

Нет, нет. Вы не можете объявить переменную или значение как константу в Python. Просто не меняйте его.

Если вы находитесь в классе, эквивалент будет:

Если нет, это просто

Но вы можете захотеть взглянуть на фрагмент кода Константы в Python от Alex Martelli.

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

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

Этот ответ не эквивалентен Java, который поставил вопрос. В python при обращении к CONST_NAME в конструкторе init класса Foo выдается ошибка, тогда как в Java это не так.

Нет ключевого слова const , как на других языках, однако возможно создать свойство, в котором имеет функцию "getter" для чтения данных, но no "setter function" , чтобы перезаписать данные. Это существенно защищает идентификатор от изменения.

Вот альтернативная реализация, использующая свойство класса:

Обратите внимание, что код далеко не прост для читателя, интересующегося константами. См. Объяснение ниже

Объяснение кода:

  • Определите функцию constant , которая принимает выражение и использует его для построения "getter" - функции, которая возвращает значение выражения только.
  • Функция setter вызывает TypeError, поэтому он доступен только для чтения
  • Используйте функцию constant , которую мы только что создали, в качестве декора, чтобы быстро определить свойства только для чтения.

И каким-то другим более старомодным способом:

(Код довольно сложный, более подробные пояснения ниже)

Обратите внимание, что декоратор @apply кажется устаревшим.

  • Чтобы определить идентификатор FOO, firs определяют две функции (fset, fget - имена по моему выбору).
  • Затем используйте встроенную функцию property для создания объекта, который может быть "установлен" или "получить".
  • Обратите внимание, что функция property имеет два первых параметра: fset и fget .
  • Используйте тот факт, что мы выбрали эти имена для нашего собственного getter и setter и создаем словарный словарь с использованием ** (двойной звездочки), применяемый ко всем локальным определениям этой области для передачи параметров функции property

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

И ваше решение все еще может быть изменено определенным программистом Python с помощью CONST.__dict__['FOO'] = 7

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

В Python вместо того, чтобы язык что-то принуждает, люди используют соглашения об именах, например __method , для частных методов и используя _method для защищенных методов.

Таким же образом вы можете просто объявить константу как все кепки, например.

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

Проблема только в том, что вам придется делать MY_CONSTANT(), но снова MY_CONSTANT = "one" является правильным способом в python (обычно).

Вы также можете использовать namedtuple для создания констант:

Выполнение def MY_CONSTANT(): return "one" не остановит кого-либо, позже в коде выполнение MY_CONSTANT = "two" (или повторное выделение функции).

@MatthewSchinckel - это соглашение, также изменение MY_CONSTANT не изменит использования MY_CONSTANT (), но вызовет ошибку, а в python, если вы хотите что-то изменить, никакой хитрый трюк не сможет вас защитить.

Мне, вероятно, не хватает трюка здесь, но это, похоже, работает для меня:

Создание экземпляра позволяет магическому методу __setattr__ запускать и перехватывать попытки установить переменную FOO . Вы можете сделать исключение здесь, если хотите. Создание экземпляра над именем класса предотвращает доступ непосредственно через класс.

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

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

Как вы, наверное, уже знаете, у Python нет констант :(

Возможно, самой простой альтернативой является определение функции для нее. Например

MY_CONSTANT() теперь имеет всю функциональность константы (плюс некоторые раздражающие фигурные скобки).

В дополнение к двум верхним ответам (просто используйте переменные с именами UPPERCASE или используйте свойства, чтобы значения были доступны только для чтения), я хочу упомянуть, что можно использовать метаклассы для реализации именованных констант. Я предоставляю очень простое решение, используя метаклассы в GitHub, которые могут быть полезны, если вы хотите, чтобы значения были более информативными относительно их типа/имени:

Это немного более продвинутый Python, но все же очень прост в использовании и удобен. (В модуле есть еще несколько функций, включая константы, доступные только для чтения, см. Его README.)

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

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

Потрясающие. Я только что попробовал это. Приятно иметь это как вариант. Хотя я и не решил, достаточно ли мне важен аспект только для чтения, чтобы использовать его, а не просто выполнять def enum(**enums): return type('Enum', (), enums) . Numbers = enum(ONE=1, TWO=2, THREE='three') , согласно stackoverflow.com/a/1695250/199364 , раздел "В более ранних версиях . "

Изменение: Добавлен пример кода для Python 3

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

Это предотвращает изменение свойств статики. Затем создайте другой класс, который использует этот метакласс:

Или, если вы используете Python 3:

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

Теперь реквизит, доступ к которому осуществляется напрямую или через экземпляр, должен быть постоянным:

Вот пример выше в действии. Вот еще один пример для Python 3.

Свойства - один из способов создания констант. Вы можете сделать это, объявив свойство getter, но игнорируя setter. Например:

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

Недооцененное решение. Я только что реализовал это после того, как нашел эту страницу (а не этот ответ) и обернулся, чтобы добавить ее, если еще нет. Я хотел подчеркнуть полезность этого ответа.

Вот реализация класса "Константы", который создает экземпляры с атрибутами "только для чтения" (константа). Например. может использовать Nums.PI для получения значения, которое было инициализировано как 3.14159 , а Nums.PI = 22 вызывает исключение.

Благодаря @MikeGraham FrozenDict, который я использовал в качестве отправной точки. Изменено, поэтому вместо Nums['ONE'] синтаксис использования Nums.ONE .

И спасибо @Raufio ответ, за идею переопределить __ setattr __.

Или для реализации с большей функциональностью см. @Hans_meine 's named_constants в GitHub

Python - это язык взрослых. Там нет защиты от чего-то подобного. Nums._d['PI'] = 22 Сам язык, по-моему, не позволяет помечать вещи как неизменяемые.

файл константы .py

Если этого недостаточно, см. полный тестовый файл для него.

Преимущества: 1. Доступ ко всем константам для всего проекта 2. Строгое управление значениями констант

Недостатки: 1. Не поддерживает пользовательские типы и тип "dict"

Протестировано с Python3.4 и Python3.5 (я использую для него "tox" )

Вы можете использовать namedtuple в качестве обходного пути для эффективного создания константы, которая работает так же, как статическая конечная переменная в Java (константа Java). Как обходные пути, это вроде элегантно. (Более элегантный подход состоял бы в том, чтобы просто улучшить язык Python --- какой язык позволяет вам переопределить math.pi ?), Но я отвлекся.)

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

Следуя вашему примеру, вы запомните, что в Java мы должны определить константу внутри некоторого класса; потому что вы не упомянули имя класса, позвоните ему Foo . Здесь класс Java:

Здесь эквивалентный Python.

Ключевым моментом, который я хочу добавить здесь, является то, что вам не нужен отдельный тип Foo ( "анонимный именованный кортеж" был бы приятным, даже если это звучит как оксюморон), поэтому мы называем наш namedtuple _Foo так что, надеюсь, он не ускользнет от импорта модулей.

Вторая точка здесь заключается в том, что мы немедленно создаем экземпляр nametuple, называя его Foo ; нет необходимости делать это на отдельном шаге (если вы этого не хотите). Теперь вы можете делать то, что вы можете сделать в Java:

Но вы не можете назначить ему:

Подтверждение: я думал, что придумал метод namedtuple, но потом я вижу, что кто-то другой дал аналогичный (хотя и менее компактный) ответ. Затем я также заметил Что такое "названные кортежи" в Python?, в котором указывается, что sys.version_info теперь является именованным верхом, поэтому, возможно, стандартная библиотека Python уже придумала эта идея гораздо раньше.

Обратите внимание, что, к сожалению (это все еще Python), вы можете полностью удалить целое назначение Foo :

Читайте также: