测试@classmethod函数的现有属性时引发AttributeError
x = classA()
x.attribute2 is None
True
我有一个函数,它是一个类的方法,我想测试这个类的一个属性,这个属性可能是None,也可能不是,但它总是会存在。
class classA():
def __init__(self, var1, var2 = None):
self.attribute1 = var1
self.attribute2 = var2
@classmethod
def func(self,x):
if self.attribute2 is None:
do something
我在访问这个属性时遇到了错误,如我所示,但在命令行上我可以看到它是可以工作的,
AttributeError: class classA has no attribute 'attributeB'
所以测试是有效的。
如果我把@classmethod
这个装饰器从func
中去掉,问题就消失了。
如果我保留@classmethod
这个装饰器,它似乎只影响那些在超类构造函数中提供默认值的变量。
上面的代码到底发生了什么?
4 个回答
2
你首先应该用 hasattr() 这样的函数来检查一下你是否拥有这个属性。
class classA(superClass):
def func(self,x):
if not hasattr(self, "attributeB") or self.attributeB is None:
do somthing
你可能还需要确认一下子类是否在调用父类的构造方法。这个属性显然是在你引用它之后才被赋值的。所以要确保这个类是正确构造的,使用
parentclassName.__init__(self, ... )
2
在一个实例方法里,self
代表的是这个实例本身。而在一个类方法里,self
(或者更传统的说法是cls
)则代表的是这个类。实例上绑定的属性在类里是看不到的。要让这个方法正常工作,唯一的办法就是把实例传给类方法,但这样的话,你不如直接把它做成一个实例方法。
7
类属性和实例属性是有区别的。简单来说,类属性是属于整个类的,而实例属性是属于类的每一个对象的。下面是一个简单的示例:
>>> class A(object):
... x=4
... def __init__(self):
... self.y=2
>>> a=A() #a is now an instance of A
>>> A.x #Works as x is an attribute of the class
2: 4
>>> a.x #Works as instances can access class variables
3: 4
>>> a.y #Works as y is an attribute of the instance
4: 2
>>> A.y #Fails as the class A has no attribute y
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
A.y #Fails as the class A has no attribute y
AttributeError: type object 'A' has no attribute 'y'
>>>
当一个类的方法被标记为classmethod时,这表示这个方法不需要实例对象,而是需要类本身作为参数。因此,通常我们把第一个参数命名为cls,而不是self。在你的代码中,classA没有属性,所以尝试访问attribute2会失败。这个区别可以通过下面的代码来展示:
>>> class B(object):
... x=2
... def __init__(self):
... self.x=7
... def pr1(self):
... print self.x
... @classmethod
... def pr2(cls):
... print cls.x
>>> b=B()
>>> B.x
2
>>> b.x
7
>>> b.pr1()
7
>>> b.pr2()
2
>>> B.pr2()
2
我可能没有解释得很清楚,如果你还有疑问,可以搜索一下classmethod或者新式类,了解更多相关内容。