【问题标题】:Questions regarding Python and Class specific variables关于 Python 和类特定变量的问题
【发布时间】:2013-12-02 19:00:34
【问题描述】:

我有一个关于 python 和类初始化变量的问题。

所以我最近在 Python (2.7.X) 中注意到,如果您设置了一个尚未定义或初始化的类变量,您仍然可以调用和访问该变量中的数据。

例如:

class Test:
    def __init__(self):
        self.a = "Hello"


t = Test()
print t.a
t.b = "World"
print t.b

输出:

Hello
World

我希望 'print t.b' 出错,因为 b 尚未在 Test() 类中定义,但它运行时没有任何问题。为什么会这样?谁能解释一下?

http://ideone.com/F2LxLh

感谢您的宝贵时间。

【问题讨论】:

  • ab 之间的唯一区别是,一个是在调用Test.__init__ 时动态创建的,另一个是在Test.__init__ 返回之后创建的。 __init__ 没有什么特别之处,可让您分配给 self.a

标签: python python-2.7


【解决方案1】:

来自instance objects 上的文档(t 是一个实例对象,因为它是自定义类Test 的一个实例):

数据属性不需要声明;像局部变量一样,它们在第一次被赋值时就立即存在。

但是,您可以通过使用 __slots__new-style class 来获得预期的行为。这会覆盖属性的默认字典存储以提高对象的内存效率,如果您尝试分配给__slots__ 中未定义的属性,也会导致 AttributeError,例如:

>>> class Test(object):
...     __slots__ = ['a']
...
>>> t = Test()
>>> t.a = "Hello"
>>> t.b = "World"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute 'b'

【讨论】:

  • 啊,我明白了。非常感谢。
【解决方案2】:

这是预期的行为。您可以随时在 Python 中添加属性而不会出错。即使没有在__init__ 中设置属性,您也可以即时添加新属性:

>>> class Test:
...     pass
...
>>> t = Test()
>>> t.foo = '3'
>>> t.foo
'3'

【讨论】:

    【解决方案3】:

    如果您愿意,可以通过编写自己的 __setattr__ 方法来更改此行为(请参阅 docs

    class Test:
        def __init__(self):
            self.__dict__[ 'a' ] = "Hello"
    
        def __setattr__( self, name, value ):
            if name not in self.__dict__:
                raise Exception( 'No attribute: ' + name )
            else:
                self.__dict__[ name ] = value
    
    t = Test()
    t.a  = 'hello world'
    print ( t.a )
    t.b = "World"   # <<< this will throw exception
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-10
      • 1970-01-01
      • 2012-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-03
      相关资源
      最近更新 更多