阻止/更改对类变量的访问

elh*_*efe 8 python class-variables

有没有办法防止或改变Python中类变量的访问,因为可以通过覆盖__setattr__实例变量?

请注意,此问题是错误的,实际上是指实例变量,而不是类变量.

在阅读关于(明显的)死亡陷阱的多篇帖子的基础上__slots__,我宁愿不去那条路(而且我没有足够深入地了解它是否符合我的要求).

例:

class A(object):

    foo = "don't change me"

    def __setattr__(self, name, value):
        raise ValueError

if __name__ == '__main__':
a1 = A()
print a1.foo # don't change me
print A.foo  # don't change me

A.foo = 'bar' # ideally throw an exception or something here
print A.foo   # bar
a2 = A()
print a1.foo  # bar
print a2.foo  # bar
Run Code Online (Sandbox Code Playgroud)

Ben*_*Ben 6

是的!你用完全相同的方式来做。

__setattr__类上的方法控制该类实例上的属性设置。在Python中,一切都是对象。对象有类。因此,您只需将您的类安排为某个__setattr__具有方法的类的实例,就像您想要防止实例的属性被修改时所做的那样!

类的类称为元类。默认元类是type:“类型的类型”,或“类的类”。您想要创建一个type不允许设置其实例属性的子类(正如您创建一个object不允许在实例级别执行此操作时设置其实例属性的子类一样)。

class CantTouchThis(type):
    def __setattr__(cls, attr, value):
        raise Exception("NO!")

class SomeClass(object):
    __metaclass__ = CantTouchThis
Run Code Online (Sandbox Code Playgroud)

仔细注意 的基类SomeClass和的之间的区别SomeClassSomeClass是 的子类object。它是 的一个实例CantTouchThis

几乎所有在实例级别工作的其他内容都可以类似地应用于具有元类的类级别;类只是像其他所有东西一样的实例。他们仅因方法和实施而具有独特的优雅行为type(正如......等等)。


Dun*_*can 3

你已经快到了,你只需要把你的__setattr__方法移到元类:

class ReadOnlyClass(type):
    def __setattr__(self, name, value):
        raise ValueError(name)
    
class A(object, metaclass=ReadOnlyClass):
    foo = "don't change me"
    
>>> a1 = A()
>>> a1.foo
"don't change me"
>>> A.foo
"don't change me"
>>> A.foo = 'bar'

Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    A.foo = 'bar'
  File "<pyshell#4>", line 3, in __setattr__
    raise ValueError, name
ValueError: foo
>>> print A.foo
don't change me
>>> a2 = A()
>>> a2.foo
"don't change me"
>>> a2.foo = 'x'
>>> a2.foo
'x'
Run Code Online (Sandbox Code Playgroud)

请注意,虽然元类__setattr__阻​​止您更改类中的属性,但它不会阻止您使用实例属性隐藏它们:如果这是您想要的,那么您需要__setattr__在两个位置进行定义。

编辑:更新为使用 Python 3.x 语法而不是古老的 Python 2.x