我来自java背景,所以我在这里有点困惑。
考虑下面的代码段
class A():
def __init__(self, **kwargs):
self.obj_var = "I am obj var"
@classmethod
def class_method(cls):
print cls.obj_var # this line is in question here
cls.cls_obj = "I m class object"
return cls.cls_obj
这会引发错误:
In [30]: a = A()
In [31]: a.obj_var
Out[31]: 'I am obj var'
In [32]: a.class_method()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-32-3dcd9d512548> in <module>()
----> 1 a.class_method()
<ipython-input-29-9c0d341ad75f> in class_method(cls)
8 @classmethod
9 def class_method(cls):
---> 10 print cls.obj_var
11 cls.cls_obj = "I m class object"
12 return cls.cls_obj
AttributeError: class A has no attribute 'obj_var'
如果我评论@classmethod
,这将正常工作。
我的理解(不正确,确定):
当我执行a = A()
时,obj_var
中创建的所有变量(__init__
)在传递给任何其他a
时都可通过此classmethod
访问同一类。显然情况并非如此。
问题
为什么我在__init__
中无法访问var
class_method
时,方法中提到了decorater @classmethod
,但在删除decorater时,它可以正常工作细
python如何在编译时内部处理这个特定的类?
有什么办法可以用@classmethod
和__init__
vars用同样的方法吗?
答案 0 :(得分:2)
让我们来谈谈Python的方法是如何运作的。
您可能已经注意到Python方法被声明为独立函数,但在类中。那是因为Python方法确实是碰巧在类中的独立函数。 self
/ cls
参数并不特殊。它只是该函数的第一个参数。
在我们继续前进之前,我想指出您似乎并未明确继承object
。如果你在Python 2.x中工作,除非你明确地从它继承,否则图的根部没有object
。 这是一件坏事,您应该尽可能在新代码中直接或间接地从object
继承。继承Python 3中的object
是合法且无害的,但是没有必要。本讨论的其余部分假定您要么在3.x中工作,要么已修复此问题。
当您使用foo.bar
访问变量,函数,方法或任何其他类型的对象时,某些钩子称为&#34;描述符协议&#34;被调用。您不必了解其中的详细信息,以了解函数的工作原理。所有你必须知道的是:
bar
的实例变量foo
(而foo
不是类),我们只是直接返回它。(*)< / LI>
foo
是一个类,bar
是@classmethod
函数(**)在foo
或其中一个超类中声明,则第一个参数是在我们返回之前设置为foo
。否则,它将保持不变。(***)如果我们返回了某些内容,我们在这里停止。foo
。这包括foo
的类(称为type(foo)
),该类的超类,依此类推,直到我们到达object
。在多重继承的情况下,这会变得更加复杂,但同样,您不需要知道这一点。bar
变量(称之为Baz
)。Baz.bar
是常规的,未修饰的函数,请将其第一个参数设置为foo
并将其返回。Baz.bar
是@classmethod
函数,请将其第一个参数设置为type(foo)
并将其返回。Baz.bar
是@staticmethod
函数,或者根本不是函数(**),则保持不变。正如您所看到的,如果方法声明为@classmethod
,那么第一个参数始终是类,而不是实例,无论函数如何被调用。这意味着您无法访问foo
的实例变量,因为您无法访问foo
本身。 __init__()
中设置的任何变量都是实例变量,因此在这里不可见。
以下是我撒谎的所有事情:
(*):Python实际上先完成剩下的工作然后再回到这一步。但这仅适用于@property
之类的事情,它实际上可以覆盖本地实例变量。常规方法不能。
(**):这是谎言。在这种情况下,Python还对@property
函数以及实现某些特殊方法的任何其他函数进行了特殊处理。
(***):我也忽略了Python 2.x中的未绑定方法,因为除了某些非常奇怪的情况(当你尝试将错误类型的对象作为第一个参数手动传递时),它们会使没有任何区别。它们在Python 3中不存在。
答案 1 :(得分:0)
如果要从类方法访问实例变量,则需要创建存在该实例变量的类的实例。 希望下面的代码能工作。
sal < 900