208

如果我有以下代码:

class Foo(object):
    bar = 1

    def bah(self):
        print(bar)
        
f = Foo()
f.bah()

它抱怨

NameError:未定义全局名称“bar”

如何访问bar方法中的类/静态变量bah

4

5 回答 5

216

而不是bar使用self.baror Foo.bar。分配给Foo.bar将创建一个静态变量,分配给self.bar将创建一个实例变量。

于 2009-04-01T21:25:28.403 回答
108

定义类方法:

class Foo(object):
    bar = 1
    @classmethod
    def bah(cls):    
        print cls.bar

现在如果bah()必须是实例方法(即可以访问self),您仍然可以直接访问类变量。

class Foo(object):
    bar = 1
    def bah(self):    
        print self.bar
于 2009-04-02T09:42:57.227 回答
20

与所有好的示例一样,您已经简化了您实际尝试做的事情。这很好,但值得注意的是,当涉及到类与实例变量时,python 具有很大的灵活性。方法也是如此。要获得一个很好的可能性列表,我建议阅读Michael Fötsch 的新式课程介绍,尤其是第 2 到第 6 节。

入门时需要做大量工作才能记住的一件事是python 不是 java。 不仅仅是陈词滥调。在 java 中,整个类都被编译,使得命名空间解析变得非常简单:在方法(任何地方)之外声明的任何变量都是实例(或者,如果是静态的,则为类)变量,并且可以在方法内隐式访问。

使用 python,经验法则是按顺序搜索三个命名空间以查找变量:

  1. 功能/方法
  2. 当前模块
  3. 内置

{begin pedagogy}

有有限的例外。我想到的主要问题是,当加载类定义时,类定义是它自己的隐式命名空间。但这仅在加载模块时才会持续,并且在方法中被完全绕过。因此:

>>> class A(object):
        foo = 'foo'
        bar = foo


>>> A.foo
'foo'
>>> A.bar
'foo'

但:

>>> class B(object):
        foo = 'foo'
        def get_foo():
            return foo
        bar = get_foo()



Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    class B(object):
  File "<pyshell#11>", line 5, in B
    bar = get_foo()
  File "<pyshell#11>", line 4, in get_foo
    return foo
NameError: global name 'foo' is not defined

{end pedagogy}

最后,要记住的是,您确实可以访问您想要访问的任何变量,但可能不是隐式的。如果您的目标简单明了,那么选择 Foo.bar 或 self.bar 可能就足够了。如果您的示例变得越来越复杂,或者您想做一些花哨的事情,例如继承(您可以继承静态/类方法!),或者在类本身中引用您的类名的想法对您来说似乎是错误的,请查看我链接的介绍。

于 2009-04-02T05:13:03.287 回答
13
class Foo(object):
     bar = 1
     def bah(self):
         print Foo.bar

f = Foo() 
f.bah()
于 2017-01-10T08:39:11.637 回答
0

bar是您的静态变量,您可以使用Foo.bar.

基本上,您需要使用类名来限定您的静态变量。

于 2021-01-05T18:26:34.643 回答