类变量不在初始化中时的行为__

2024-05-16 01:10:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个名为MyClass的类:

 def __init__(self, config):
        self.response = Response(config)
        self.utility = Utility()
        self.listl = {}

其方法如下:

 def findSt(self, lv):      
        dvp = self.listl
        if lv not in dvp:
            raise Exception("ERROR: ....", lv)
        else:
             ...

在我的主代码中,我使用同一类的另一个方法(getvalues)为self.listl ie提供正确的值:

    myobject = MyClass(config)
    myobject.listl = myobject.getvalues()
    lr = []
    for lv in lvs:
        lr.append(myobject.findSt(lv))   

这是可行的,尽管我不确定这是正确的方法。我之所以这么问是因为如果我在主代码中输入了以下错误:

myobject.listL = myobject.getvalues()

没有引发错误!当然,在这种情况下myobject.listl没有正确的运行时值,所以它不起作用,但是为什么我可以创建一个不在__init__中的变量呢


Tags: 方法代码inselfconfiginitdefmyclass
2条回答

用户定义的类实例可以在运行时添加/删除属性:

>>> class A(object): pass
... 
>>> a = A()
>>> a.something = 1   #no error. Now a has a new something attibute
>>> 

虽然内置类型通常不允许这样做:

>>> a = object()
>>> a.something = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'something'

在python中,每个对象都有一个包含其属性的关联字典:__dict__。这本词典是可变的。执行任务时:

instance.attribute = value

实际发生的情况是,您正在为对象的__dict__赋值:

instance.__dict__['attribute'] = value

事实上:

>>> class A(object):
...     def __init__(self):
...             self.something = 1
... 
>>> a = A()
>>> a.__dict__
{'something': 1}
>>> a.other = 2
>>> a.__dict__
{'other': 2, 'something': 1}
>>> a.__dict__['other2'] = 3
>>> a.other2
3

^{}在这方面并不特别。这只是一个约定所有的属性都在那里定义,但是当你把self.attribute = value放在__init__里面时,你做的事情和上面的代码完全一样:创建一个新的属性。 这是大多数时候进行初始化的正确方法

类不(通常)声明其实例的预定义属性集。使用某些元编程可以添加此类声明(例如,使用类修饰符/元类)

如果要提前定义类的属性,可以使用^{}

>>> class A(object):
...     __slots__ = ('something',)
... 
>>> a = A()
>>> a.something = 1
>>> a.other = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'other'

在类中定义__slots__时,它的实例没有关联的__dict__,因此无法在运行时添加属性

>>> a.__dict__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute '__dict__'

或者,您可以重新定义^{}方法,以便更好地控制设置属性时发生的事情

因为同样的原因,你可以设置myobject.listl你可以从任何地方设置任何实例上的任何属性*,__init__中设置的属性在任何方面都不是特别的。__init__唯一的特别之处在于,当创建新实例时,它会自动调用

这并不意味着你必须利用它,通常最好不要从类外设置这样的属性,我更喜欢有这样的方法

def setvalues(self):
    self.listl = self.getvalues()

差不多吧。一般来说,您需要小心,因为您有一个可变的属性,如果一些外部代码仍然持有对旧self.listl的引用呢?那么旧的列表就不会被那个代码改变了。这样就可以:

def setvalues(self):
    self.listl[:] = self.getvalues()

不会重新设置listl属性,而只是其中的值。但那是完全不同的讨论

*:有一些异常,比如用C实现的类,或者定义了__slots__的类,但是这些异常很少

相关问题 更多 >