Безопасны ли изменяемые константы?

Существуют ли какие-либо «ошибки», связанные с наличием константы, которая является списком или любым другим изменяемым объектом?

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

Рассмотрим этот пример кода:

#!/usr/bin/env python
# This file was not tested before posting.

import subprocess

LS_FLAGS = ['-l', '-a']

def main():
    subprocess.call(['ls'] + LS_FLAGS)

if __name__ == '__main__':
    main()

Я спрашиваю об этом, потому что прекрасно осведомлен о проблемах, которые возникают из-за изменяемых объектов в определениях функций; И, хотя я понимаю, что никогда не должно быть ничего, что делало бы присваивание или изменение уважаемой константе; и что «константы» на самом деле не вещь: я спрашиваю, и далее спрашиваю, могут ли быть какие-то соглашения для семантической защиты себя от случайных мутаций?


person ThorSummoner    schedule 20.02.2015    source источник
comment
Вы можете удалить мутацию из уравнения, используя кортеж вместо списка: LS_FLAGS = ('-l', '-a') неизменяем. Если вам нужно иметь его в виде списка при последующем использовании, приведите его к списку с помощью list(LS_FLAGS). Просто обратите внимание, что хотя кортеж неизменяем, изменяемый объект внутри этого кортежа по-прежнему остается изменяемым. Это спорно для строк, но если бы у вас были списки внутри ваших кортежей, вы могли бы видоизменять списки.   -  person paidhima    schedule 21.02.2015
comment
Вы можете сделать это кортежем (они неизменны). Или вы просите что-то похожее на ключевое слово Java final, поэтому вы не можете присваивать переменным какие-либо другие значения после их создания?   -  person MeetTitan    schedule 21.02.2015
comment
Я не думаю, что python знает, что такое константы...   -  person Joran Beasley    schedule 21.02.2015
comment
Недавно я писал в блоге о том, как создать класс, в котором нельзя изменить атрибуты, как своего рода контейнер для констант... и как это на самом деле невозможно. engyrus.com/2015/02/spt-3-constant- синглтон.html   -  person kindall    schedule 21.02.2015


Ответы (2)


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

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

person kindall    schedule 20.02.2015
comment
Я не знаю, был бы у меня даже этот первый абзац (я дал вам +1, потому что ваш самый правильный ...) ... но константы - это просто переменные, вот и вывод ... кодер должен понять, может быть, я не следует менять это ALL_CAPS_VARIABLE - person Joran Beasley; 21.02.2015

Вы можете предотвратить мутацию, обратившись к своим «константам» из объекта, похожего на словарь. Что-то вроде этого, может быть:

class Config:
    _config = dict(
        LS_FLAGS=['-l', '-a']
    )
    def __getitem__(self, idx):
        return Config._config[idx].copy()  # Use copy.deepcopy 
                                           # instead if required

CONFIG=Config()

Или даже:

class Config:
    def __getitem__(self, idx):
        if idx == 'LS_FLAGS':
            return ['-l', '-a']

        raise KeyError(idx)

CONFIG=Config()

Затем используйте объект CONFIG следующим образом:

print(CONFIG['LS_FLAGS'])

Это далеко не идеально (и не очень привлекательно), но это предотвратит случайное1 удаление ваших "констант":

# Try to mutate the constant config
ls_flags = CONFIG['LS_FLAGS']
ls_flags.append('/home')

print(CONFIG['LS_FLAGS']) # unchanged

И

CONFIG['LS_FLAGS'] = ['-ls']

Поднимет TypeError: 'Config' object does not support item assignment


¹Конечно, поскольку в Python нет «настоящих» констант, это не защитит вас от вредоносного кода. Например, можно полностью заменить объект CONFIG...

person Sylvain Leroux    schedule 21.02.2015