Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我如何才能访问;“静态”;Python中类方法中的类变量?_Python_Oop_Static Variables - Fatal编程技术网

我如何才能访问;“静态”;Python中类方法中的类变量?

我如何才能访问;“静态”;Python中类方法中的类变量?,python,oop,static-variables,Python,Oop,Static Variables,如果我有以下python代码: class Foo(object): bar = 1 def bah(self): print(bar) f = Foo() f.bah() 它抱怨 NameError: global name 'bar' is not defined 如何在方法bah中访问类/静态变量bar?而不是bar使用self.bar或Foo.bar。分配给Foo.bar将创建一个静态变量,分配给self.bar将创建一个实例变量。与所有好的示例一

如果我有以下python代码:

class Foo(object):
    bar = 1

    def bah(self):
        print(bar)

f = Foo()
f.bah()
它抱怨

NameError: global name 'bar' is not defined

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

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

与所有好的示例一样,您已经简化了实际尝试执行的操作。这很好,但值得注意的是,python在类变量和实例变量之间有很大的灵活性。方法也是如此。对于一个好的可能性列表,我建议阅读,特别是第2节到第6节

class Foo(object):
    bar = 1
    def bah(self):    
        print self.bar
开始使用python时要记住的一点是,python不是java。不仅仅是陈词滥调。在java中,编译整个类,使名称空间解析变得非常简单:在方法(任何位置)之外声明的任何变量都是实例(或者,如果是静态的,则是类)变量,并且在方法内可以隐式访问

对于python,主要的经验法则是有三个名称空间按顺序搜索变量:

  • 函数/方法
  • 当前模块
  • 内置
  • {开始教学}

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

    >>> class A(object):
            foo = 'foo'
            bar = foo
    
    
    >>> A.foo
    'foo'
    >>> A.bar
    'foo'
    
    但是:

    >>B类(对象):
    foo='foo'
    def get_foo():
    返回foo
    bar=get_foo()
    回溯(最近一次呼叫最后一次):
    文件“”,第1行,在
    B类(对象):
    文件“”,第5行,在B中
    bar=get_foo()
    文件“”,第4行,在get\u foo中
    返回foo
    NameError:未定义全局名称“foo”
    
    {end education}

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

    定义类方法:

    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
    

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


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

    Foo.bar会起作用,但self.bar会创建一个实例变量,而不是静态变量。bedwyr,“print self.bar”不会创建任何实例变量(尽管会分配给self.bar)。@Constantin——我没有意识到,这是一个有趣的区别。谢谢你的更正:-)但是如果你不想有一个ivar,那么使用Foo.classmember会更清晰。当使用静态变量时,最好从这里读取gotchas:@Constantin给出了许多问题之一。关于Python和静态的更多信息可以在这里找到:IIRC,从技术上讲,搜索了3(+)个名称空间——函数本地、模块/全局和内置。嵌套作用域意味着可以搜索多个本地作用域,但这是例外情况之一。(…)另外,我会小心地说“主模块”,因为搜索的是函数的包含模块,而不是主模块。。。从实例引用中查找属性是另一回事,但这个答案确实解释了为什么需要实例/类引用。为什么不只是Foo.bar,而不是self.\uuu class\uuuu.bar?@Mk12:当你有类继承时,“类变量”可以在基类或子类中。你想提到哪一个?取决于你想做什么。bar将始终引用指定类的属性,该属性可能是基类或子类。self.\u_class\u_uuu.bar将引用实例所属的任何一个类。现在,当我们对语言的细节如此了解,以至于我们可以区分两个非常协调的用例时,我们已经达到了不幸的地步。这确实取决于你想做什么,但很多人不会注意到这些微妙之处。顺便说一句,这是“类变量”的罕见用法。更常见的是在特定类中定义它,这里是Foo。对于某些高级编程情况,这是有用的信息。但几乎可以肯定的是,这并不是原始问题想要的答案(任何需要这个答案的人都已经知道如何使用Foo.bar)+因为我从中学到了一些东西。我正在学习何时使用类变量和方法(相对于实例变量和方法)。当您想访问实例方法中的类变量时,是否需要使用self.\uuuu class\uuuu.bar?我注意到self.bar即使是类变量而不是实例变量也能工作。虽然这段代码可以解决这个问题,但它如何以及为什么解决这个问题将真正有助于提高文章的质量,并可能导致更多的投票。请记住,你是在将来回答读者的问题,而不仅仅是现在提问的人。请在回答中添加解释,并说明适用的限制和假设。考虑添加更多信息来扩展你的答案,或者考虑编辑其他答案来添加这个细节。
    class Foo(object):
         bar = 1
         def bah(self):
             print Foo.bar
    
    f = Foo() 
    f.bah()
    
    class Foo(object):    
        bar = 1
    
        def bah(object_reference):
            object_reference.var = Foo.bar
            return object_reference.var
    
    
    f = Foo() 
    print 'var=', f.bah()