Как ограничить доступ к неопределенной переменной класса/экземпляра?

Python, разрешающий доступ к неопределенной переменной класса/экземпляра

Я определил простой/пустой класс Python, как показано ниже. Теперь, если я устанавливаю значение для неопределенной переменной либо с помощью переменной экземпляра, либо с именем класса, Python свободно позволяет мне устанавливать значение для неопределенной переменной, а также позволяет мне получить к ней доступ как к переменной экземпляра или класса без каких-либо ошибок. Итак, в двух словах, я могу без проблем установить неопределенные переменные экземпляра и класса.

  1. Как мы можем запретить пользователям устанавливать неопределенные переменные экземпляра и класса в Python.

  2. Вот как Python обрабатывает эти неопределенные переменные (undefined_variable_1 и undefined_variable_2)? Обрабатываются ли они как переменная экземпляра или переменная класса или что-то еще?

class Test:

  pass

### #Now instantiate the class and try setting & it accessing undefined variables
t1 = Test()

t1.undefined_variable_1 = "Undefined class/instance variable being set through instance variable (t1)"

### #Access the undefined variable through instance variable
print(t1.undefined_variable_1) 

Test.undefined_variable_2 = "Undefined class/instance variable being set through Class name (Test)"

### #Access the undefined variable through Class name
print(Test.undefined_variable_2) 

Как мы можем ограничить пользователя от установки/доступа к неопределенной переменной экземпляра/экземпляра?

Можете ли вы сделать шаг назад и объяснить, почему вы хотите это сделать? В чем проблема?

Blorgbeard 30.05.2019 01:46

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

juanpa.arrivillaga 30.05.2019 01:55

@juanpa.arrivillaga Я подозреваю, что они действительно хотят, чтобы код вне класса не создавал новые атрибуты.

Barmar 30.05.2019 02:00

@juanpa.arrivillaga - поведение такое же, даже если я инициализирую другие атрибуты экземпляра с помощью метода __init__() и устанавливаю неопределенные переменные, как в моем примере. Если Python позволяет нам использовать неопределенные атрибуты w.r.t. пользовательский класс, то как он поддерживает инкапсуляцию? Пожалуйста, уточните.

Vivek.N 30.05.2019 02:03

@VivekN Python построен на философии, согласно которой мы все здесь взрослые люди по обоюдному согласию. Вы не мешаете людям делать потенциально страшные вещи; вы сообщаете им ситуации, с которыми должен справиться ваш класс, и если они захотят копаться в его внутренностях и, возможно, вызвать хаос, это их дело. Даже метод __slots__, о котором я упоминал в своем ответе, имеет основную цель экономия памяти.

gmds 30.05.2019 02:04

@VivekN __init__ не имеет особого статуса. Работает точно так же в __init__. Если под «инкапсуляцией» вы подразумеваете модификаторы доступа, Python не поддерживает это. Конечно, он поддерживает инкапсуляцию в более широком смысле «объединения данных с операциями, которые работают с этими данными».

juanpa.arrivillaga 30.05.2019 02:06

@Barmar Бармар, ну, вероятно, нет способа сделать то, что не перегружено и, вероятно, в любом случае будет легко ниспровергнуто.

juanpa.arrivillaga 30.05.2019 02:11

@juanpa.arrivillaga А как насчет решения __slots__ в ответе? Кажется, это именно то, о чем просил ОП. Его можно было бы отменить, но он должен предотвращать непреднамеренное создание атрибута.

Barmar 30.05.2019 02:13

@Barmar, которого вы все еще можете назначать вне класса с помощью __slots__. Я склонен использовать слоты для предотвращения ошибок случайный, например obj.mt_var = <something> вместо obj.my_var = <something>, хотя с тех пор, как я начал использовать mypy, мне это не нужно. Как правило, я просто избегаю интерфейсов, которые требуют от вас этого в первую очередь. Так что my_obj.attribute = whateverвсегда выглядит неправильно :)

juanpa.arrivillaga 30.05.2019 02:13

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

Barmar 30.05.2019 02:15

@Barmar Бармар Я бы сказал, что вопрос плохо определен. Я вижу, как ваша интерпретация имеет смысл, но в ее нынешнем виде вопрос расплывчатый.

juanpa.arrivillaga 30.05.2019 02:16

@ juanpa.arrivillaga - ответ от Бармара полезен. Между тем я не уверен, что неясно в вопросе, как показано ниже? Как мы можем запретить пользователям устанавливать неопределенные переменные экземпляра и класса в Python. Как Python обрабатывает эти неопределенные переменные (undefined_variable_1 и undefined_variable_2)? Обрабатываются ли они как переменная экземпляра или переменная класса или что-то еще?

Vivek.N 30.05.2019 02:29

@Vivek.N, потому что в Python вы всегда устанавливаете атрибут, который не определен. Вы должны иметь в виду что-то вроде «как предотвратить установку атрибута, который не определен в операторе определения класса» или «как предотвратить установку атрибута за пределами указанного диапазона имен». Потому что, опять же, переменные (атрибуты) делают не существует, пока они не назначены. В Python нет объявлений переменных.

juanpa.arrivillaga 30.05.2019 03:01
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
13
258
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

class Restricted:

    __slots__ = ('a', 'b')

r = Restricted()
r.a = 1  # okay
r.b = 2  # okay
r.c = 3  # error

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

class RestrictedMeta(type):

    def __setattr__(self, attr, value):
        if attr in ('a', 'b'):
            super().__setattr__(attr, value)

        else:
            raise TypeError(f"Can't assign to attribute '{attr}' of class 'Restricted'")

class Restricted(metaclass=RestrictedMeta):
    pass

Restricted.a = 1  # okay
Restricted.b = 2  # okay
Restricted.c = 3  # error

@VivekN Да, я отметил это в своем ответе. Для этого вам нужен собственный метакласс, пример которого я привел.

gmds 30.05.2019 02:23

Другие вопросы по теме

Похожие вопросы

Перечислите все возможные комбинации значений фрейма данных pandas для достижения определенной суммы
Как создать новый столбец, который возвращает значение из другой таблицы по определенным критериям в Python
Как предоставить python argparse.parser с аргументами внутри кода без аргументов командной строки?
Большой (6 миллионов строк) pandas df вызывает ошибку памяти с `to_sql`, когда размер фрагмента = 100, но может легко сохранить файл размером 100 000 без размера фрагмента
Как выйти из скрипта Python, вызванного в приложении Flask?
Использовать ключ для хранения переменных из dict1 в качестве нового ключа для dict2
Не удалось разделить строку
Прогноз Knn выполняется на 100% на y_test
Возвращение местоположения первого значения в местоположении фрейма данных, которое соответствует условию в фрейме данных pandas
Не могу интегрировать мое приложение с текстовым редактором в django