Какая функция неявно вызывается в Python при установке переменной класса через имя класса?

Скажем, у меня есть класс с «частной» переменной класса и экземпляром класса. Я хочу предотвратить установку переменной вне класса или выполнение определенной функции при изменении переменной класса.

class SomeClass (object):
    __classVar = 5
    def getClassVar():
        return SomeClass.__classVar

instance = SomeClass()

Переменная __classVar недоступна для прямого чтения вне класса (например, я не могу сделать a = SomeClass.__ClassVar или b = instance.__classVar), но тот факт, что переменная является частной, не мешает мне это сделать:

SomeClass.__classVar = 6 
instance.__classVar = 10

хотя это фактически не присваивает значение переменной. Например. приведенный ниже код по-прежнему будет выводить 5.

class SomeClass (object):
        __classVar = 5
        def getClassVar():
            return SomeClass.__classVar

instance = SomeClass()
SomeClass.__classVar = 6
instance.__classVar = 10
print (getClassVar())  #outputs 5

Я знаю, что это утверждение

instance.__classVar = 10

неявно вызывает функцию __setattr__, поэтому я могу перегрузить ее в определении класса.

class SomeClass (object):
    __classVar = 5
    def getClassVar():
            return SomeClass.__classVar

    def __setattr__(cls, name, value):
        print ("Setting a class variable via instance name")
        #do something specific

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

SomeClass.__var = 6   ##want to do something specific when this happens 

person El0    schedule 19.08.2015    source источник
comment
Краткий ответ: не делайте этого. Если люди хотят делать глупости, их ничто не остановит, а странные обходные пути просто затруднят работу с вашим кодом.   -  person Nick Johnson    schedule 19.08.2015
comment
Согласен с Ником Джонсоном. В этом нет никакого смысла, и любой порядочный программист на Python знает, что __variable должен быть закрытым. Вы не можете защититься от гнусности на любом языке.   -  person rlbond    schedule 19.08.2015
comment
Тот же метод, только вместо вызова type(instance).__setattr__ вы вызываете type(SomeClass).__setattr__.   -  person chepner    schedule 19.08.2015


Ответы (1)


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

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

class YourMeta(type):
    def __setattr__(self, name, value):
        # do your stuff here

А затем просто сделайте это метаклассом вашего другого класса, например:

class SomeClass(object):
    __metaclass__ = YourMeta

    # And so on

Итак, теперь у вас будет перегруженный __setattr__ на уровне класса.

person bagrat    schedule 19.08.2015
comment
Я думал, что это будет путь изначально, но это не работает для меня. Я ожидал, что атрибут metaclass изменит тип SomeClass, но этого не произошло. print (type(SomeClass)) #prints <class 'type'> Перегруженная функция setattr YourMeta не выполняется, когда я устанавливаю переменную SomeClass через имя класса. Что я могу делать неправильно? - person El0; 20.08.2015