【问题标题】:Which function is implicitly called in Python when setting a class variable via a class name?通过类名设置类变量时,Python 中隐式调用了哪个函数?
【发布时间】:2015-11-13 00:53:29
【问题描述】:

假设我有一个带有“私有”类变量和该类实例的类。我想防止从类外部设置变量或在更改类变量时执行特定函数。

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 

【问题讨论】:

  • 简短回答:不要这样做。如果人们想做愚蠢的事情,没有办法阻止他们,奇怪的变通办法只会让你的代码难以使用。
  • 同意尼克·约翰逊的观点。这没有任何意义,任何半途而废的 Python 程序员都知道__variable 应该是私有的。你无法防御任何语言的恶意。
  • 同样的技术,只是调用type(instance).__setattr__,而不是调用type(SomeClass).__setattr__

标签: python python-3.4 setter static-variables class-variables


【解决方案1】:

我建议关注Nick Johnson's advice,但是如果您处于极度需要该功能的情况,您可能有兴趣查看 Python 元类。

您可以做的是创建自己的自定义类,继承自 type 类,并在那里重载 __setattr__

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

然后简单地把它变成你其他类的元类,就像这样:

class SomeClass(object):
    __metaclass__ = YourMeta

    # And so on

所以现在,您将在班级级别拥有一个重载的__setattr__

【讨论】:

  • 我认为这将是一种最初的方式,但它对我不起作用。我希望 metaclass 属性会更改 SomeClass 的类型,但事实并非如此。 print (type(SomeClass)) #prints <class 'type'> 当我通过类名设置 SomeClass 的变量时,YourMeta 的重载 setattr 函数不执行。我可能做错了什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-21
  • 1970-01-01
  • 2011-03-07
  • 2021-12-25
相关资源
最近更新 更多