【问题标题】:Prevent / alter access to class variables [duplicate]防止/更改对类变量的访问[重复]
【发布时间】:2012-09-03 19:01:54
【问题描述】:

有没有一种方法可以通过覆盖 __setattr__ 实例变量来阻止或更改对 Python 中类变量的访问?

请注意,this question 的名称有误,实际上指的是实例变量,而不是类变量。

基于阅读了多篇关于__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

【问题讨论】:

标签: python class-variables


【解决方案1】:

您就快到了,您只需将您的 __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'

请注意,尽管元类 __setattr__ 阻止您更改类中的属性,但它不会阻止您使用实例属性隐藏它们:如果这是您想要的,那么您需要在这两个地方定义 __setattr__

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

【讨论】:

  • 在 Python3.8 中不起作用
  • 那是因为我是在 2012 年写的,当时 Python 3 还很年轻,几乎没有使用过,而 Python 2 仍然很强大。我现在已经对其进行了编辑以使用 Python 3 语法。
【解决方案2】:

是的!你做的完全一样。

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

类的类称为元类。默认元类是type:“类型的类型”或“类的类”。您想要创建一个不允许设置其实例属性的 type 的子类(就像您创建一个不允许设置其实例属性的 object 子类一样,当您在实例级别)。

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

class SomeClass(object):
    __metaclass__ = CantTouchThis

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

几乎所有其他在实例级别工作的东西都可以类似地应用于具有元类的类级别;类只是像其他所有东西一样的实例。由于type 的方法和实现(就像...等),它们才具有独特的优雅行为。

【讨论】:

  • 在 python 3.8 中不起作用
猜你喜欢
  • 2012-10-15
  • 1970-01-01
  • 1970-01-01
  • 2017-09-10
  • 2019-02-12
  • 2015-09-26
  • 1970-01-01
  • 2019-06-12
  • 2021-09-17
相关资源
最近更新 更多