如果我有以下代码:

class Foo(object):
    bar = 1

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

它抱怨

未定义全局名称“bar”

我如何访问类/静态变量栏内的方法bah?


而不是酒吧使用自我。bar或Foo.bar。赋值给Foo。Bar将创建一个静态变量,并分配给self。Bar将创建一个实例变量。


与所有好的示例一样,您已经简化了实际要做的事情。这很好,但值得注意的是,当涉及到类变量和实例变量时,python有很大的灵活性。方法也是如此。我推荐阅读Michael Fötsch的new-style类介绍,特别是第2到6节。

在开始学习时需要花很多功夫记住的一件事是python不是java。这不仅仅是陈词滥调。在java中,编译整个类,使得名称空间解析非常简单:在方法外部(任何地方)声明的任何变量都是实例变量(如果是静态的,则是类变量),并且可以在方法内隐式访问。

在python中,最重要的经验法则是依次搜索三个名称空间来查找变量:

函数/方法 当前模块 内置命令

{开始教育学}

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

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


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

but:

>>> 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

{结束教育学}

In the end, the thing to remember is that you do have access to any of the variables you want to access, but probably not implicitly. If your goals are simple and straightforward, then going for Foo.bar or self.bar will probably be sufficient. If your example is getting more complicated, or you want to do fancy things like inheritance (you can inherit static/class methods!), or the idea of referring to the name of your class within the class itself seems wrong to you, check out the intro I linked.


定义类方法:

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

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

f = Foo() 
f.bah()

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

基本上,你需要用Class name限定你的静态变量。


你可以通过对象访问类变量,也可以从类外部或类内部直接通过类名访问类变量,基本上,你应该直接通过类名访问类变量,因为如果有相同名称的类和实例变量,相同名称的实例变量将被优先考虑,而相同名称的实例变量在被对象访问时被忽略。因此,使用类名比使用对象访问类变量更安全。

例如,你可以通过对象访问类变量,也可以直接从类外部通过类名访问类变量,如下所示:

class Person:
    name = "John" # Class variable

obj = Person()
print(obj.name) # By object
print(Person.name) # By class name

输出:

John
John

但是,如果你通过object添加了与类变量相同的name实例变量:

class Person:
    name = "John" # Class variable

obj = Person()
obj.name = "Tom" # Adds the same name instance variable as class variable
print(obj.name) # By object
print(Person.name) # By class name

或者,如果你在__init__()中通过self添加与类变量相同的name实例变量:

class Person:
    name = "John" # Class variable
    
    def __init__(self, name):
        self.name = name # Adds the same name instance variable as class variable

obj = Person("Tom")
print(obj.name) # By object
print(Person.name) # By class name

当被object访问时,相同名称的实例变量将被优先排序:

Tom  # By object
John # By class name

并且,你也可以通过self和直接通过类名从实例方法内部访问类变量,如下所示:

class Person:
    name = "John" # Class variable
        
    def test(self): # Instance method
        print(self.name) # By "self"
        print(Person.name) # By class name

obj = Person()
obj.test()

输出:

John
John

但是,如果你通过object添加了与类变量相同的name实例变量:

class Person:
    name = "John" # Class variable
        
    def test(self): # Instance method
        print(self.name) # By "self"
        print(Person.name) # By class name

obj = Person()
obj.name = "Tom" # Adds the same name instance variable as the class variable
obj.test()

或者,如果你在__init__()中通过self添加与类变量相同的name实例变量:

class Person:
    name = "John" # Class variable
    
    def __init__(self, name):
        self.name = name # Adds the same name instance variable as the class variable
        
    def test(self): # Instance method
        print(self.name) # By "self"
        print(Person.name) # Directly by class name

obj = Person("Tom")
obj.test()

当被self访问时,相同名称的实例变量将被优先排序:

Tom  # By "self"
John # By class name