Python 测试@classmethod函数的现有属性,会产生AttributeError

Python 测试@classmethod函数的现有属性,会产生AttributeError,python,class,variables,Python,Class,Variables,我有一个函数,它是一个类方法,我想测试这个类的一个属性,这个属性可能是空的,也可能不是空的,但它将始终存在 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 我得到了错误

我有一个函数,它是一个类方法,我想测试这个类的一个属性,这个属性可能是空的,也可能不是空的,但它将始终存在

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'
当我访问属性时,如我所示,但如果在命令行上,我可以看到它工作

x = classA()
x.attribute2 is None 
True
所以测试是有效的

如果我从
func
中删除
@classmethod
装饰器,问题就会消失。
如果我离开
@classmethod
装饰器,它似乎只会影响超类构造函数中提供的默认值的变量


上面的代码是怎么回事?

您应该首先测试hasattr()或类似的属性

class classA(superClass):
 def func(self,x):
  if not hasattr(self, "attributeB") or self.attributeB is None:
   do somthing  
您可能还希望确保子类正在从父类调用构造函数方法。该属性显然是在您引用它之后分配的。因此,请确保使用

parentclassName.__init__(self, ... )

这两个属性是实例属性,而不是类属性。类方法正在尝试引用类属性。类上既不存在attribute1也不存在attribute2:它们存在于实例上

我不知道如何解决这个问题,但这是问题的根源

(通过在func中将attribute2更改为attribute1进行验证。)


所以问题应该是,“如何在类方法中引用实例属性?”

self
在实例方法中就是实例<类方法中的code>self(或者更传统地说,
cls
)是类。实例上绑定的属性在类上不可见。实现这一点的唯一方法是将实例传递给类方法,此时您可以将其作为实例方法。

类属性和实例属性之间存在差异。快速演示如下:

>>> 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或新样式的类,并仔细阅读一下。

请提供一个更完整的代码示例(因为您的代码甚至无效)。+1:这是正确的方法。首先检查该属性是否存在,然后对此进行操作。如果超类具有该属性(无条件),正如断开的代码示例所示,没有理由对其进行测试。-1:虽然这会起作用,但实际上并不能解决实际问题。一般来说,我会尽量避免设计模式,这些模式有时会导致设置类属性,有时则不会。我不确定我是否完全理解这一点。为什么它对给定默认值的参数和不给定默认值的参数的反应不同?
>>> 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