在Python中,如何在类方法中访问"静态"类变量

Ros*_*ers 146 python

如果我有以下python代码:

class Foo(object):
    bar = 1

    def bah(self):
        print(bar)

f = Foo()
f.bah()
Run Code Online (Sandbox Code Playgroud)

它抱怨

NameError: global name 'bar' is not defined
Run Code Online (Sandbox Code Playgroud)

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

小智 145

而不是bar使用self.barFoo.bar.分配Foo.bar将创建一个静态变量,并且分配self.bar将创建一个实例变量.

  • bedwyr,"print self.bar"不会创建任何实例变量(虽然分配给self.bar会). (45认同)
  • Foo.bar可以工作,但是self.bar会创建一个实例变量,而不是静态变量. (9认同)
  • 使用静态变量时,最好从这里阅读陷阱:http://stackoverflow.com/questions/68645/static-class-variables-in-python。@Constantin 给出了许多陷阱之一。 (3认同)
  • 但是如果你不打算那里有一个ivar,它更清楚地使用Foo.classmember. (2认同)

var*_*tec 76

定义类方法:

class Foo(object):
    bar = 1
    @classmethod
    def bah(cls):    
        print cls.bar
Run Code Online (Sandbox Code Playgroud)

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

class Foo(object):
    bar = 1
    def bah(self):    
        print self.bar
Run Code Online (Sandbox Code Playgroud)

  • @ Mk12:当你有类继承时,"类变量"可以在基类或子类中.您要参考哪个?取决于你想要做什么.Foo.bar总是引用指定类的属性 - 可能是基类或子类.self.__class__.bar指的是实例所属的类型. (15认同)
  • 现在我们已经达到了这个不幸的地步,当我们逐渐意识到语言的细节时,我们可以区分两个精心调整的用例.它确实取决于你想做什么,但许多人不会注意这些微妙之处. (4认同)
  • 为什么不只是Foo.bar,而不是self.__class__.bar? (3认同)
  • 顺便说一句,这是"类变量"的稀有用法.将它定义在特定类中更为常见,这里是Foo.对于某些高级编程情况,这是有用的信息.但几乎可以肯定不是原始问题想要的答案(任何需要这个答案的人都会知道如何做Foo.bar).+1因为我从中学到了一些东西. (2认同)
  • 我正在学习何时使用类变量和方法(而不是实例变量和方法).如果要在实例方法中访问类变量,是否需要使用self.__class__.bar?我注意到,即使bar是类变量而不是实例变量,self.bar也能正常工作. (2认同)

Dav*_*ger 11

与所有好的例子一样,您已经简化了实际尝试的内容.这很好,但值得注意的是,python 在类与实例变量方面具有很大的灵活性.方法也是如此.对于一系列可能性,我建议阅读MichaelFö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'
Run Code Online (Sandbox Code Playgroud)

但:

>>> 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
Run Code Online (Sandbox Code Playgroud)

{end pedagogy}

最后,要记住的是,你可以访问任何你想要访问的变量,但可能不会含蓄.如果你的目标简单明了,那么去Foo.bar或self.bar可能就足够了.如果你的例子变得越来越复杂,或者你想做继承等花哨的东西(你可以继承静态/类方法!),或者在类中引用你的类名称的想法本身似乎不对,请查看介绍我联系.


All*_*gwa 9

class Foo(object):
     bar = 1
     def bah(self):
         print Foo.bar

f = Foo() 
f.bah()
Run Code Online (Sandbox Code Playgroud)