如何在方法内访问“静态”类变量?
- 2025-01-13 08:52:00
- admin 原创
- 138
问题描述:
如果我有以下代码:
class Foo(object):
bar = 1
def bah(self):
print(bar)
f = Foo()
f.bah()
它抱怨
NameError:全局名称“bar”未定义
如何bar
在方法内访问类/静态变量bah
?
解决方案 1:
不要bar
使用self.bar
或Foo.bar
。分配给Foo.bar
将创建一个静态变量,而分配给self.bar
将创建一个实例变量。
解决方案 2:
定义类方法:
class Foo(object):
bar = 1
@classmethod
def bah(cls):
print cls.bar
现在,如果bah()
必须是实例方法(即可以访问自身),您仍然可以直接访问类变量。
class Foo(object):
bar = 1
def bah(self):
print self.bar
解决方案 3:
与所有好的例子一样,您简化了实际要做的事情。这很好,但值得注意的是,python在类与实例变量方面具有很大的灵活性。方法也是如此。为了得到一个很好的可能性列表,我建议阅读Michael Fötsch 的新式类介绍,尤其是第 2 至第 6 节。
刚开始时需要花很多功夫记住的一件事是Python 不是 Java。 这可不只是一句陈词滥调。在 Java 中,整个类都会被编译,这使得命名空间解析变得非常简单:在方法之外(任何地方)声明的任何变量都是实例(或者,如果是静态的,则是类)变量,并且可以在方法内隐式访问。
对于 python 来说,主要的规则是按顺序在三个命名空间中搜索变量:
函数/方法
当前模块
内置
{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 可能就足够了。如果您的示例变得越来越复杂,或者您想要做一些像继承这样的奇特的事情(您可以继承静态/类方法!),或者在类本身中引用类名称的想法对您来说似乎是错误的,请查看我链接的简介。
解决方案 4:
class Foo(object):
bar = 1
def bah(self):
print Foo.bar
f = Foo()
f.bah()
解决方案 5:
bar
是您的静态变量,您可以使用来访问它Foo.bar
。
基本上,您需要用类名来限定您的静态变量。
解决方案 6:
您可以从类的外部或内部通过对象或直接通过类名访问类变量,基本上,您应该直接通过类名访问类变量,因为如果有同名的类和实例变量,则同名实例变量优先,而通过对象访问时同名实例变量将被忽略。因此,使用类名访问类变量比使用对象更安全。
例如,您可以通过对象访问类变量,也可以从类外部直接通过类名访问类变量,如下所示:
class Person:
name = "John" # Class variable
obj = Person()
print(obj.name) # By object
print(Person.name) # By class name
输出:
John
John
但是,如果通过对象添加与类变量同名的实例变量:
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
self
或者,如果通过以下方式添加与类变量同名的实例变量__init__()
:
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
同名实例变量在被对象访问时优先:
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
但是,如果通过对象添加与类变量同名的实例变量:
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()
self
或者,如果通过以下方式添加与类变量同名的实例变量__init__()
:
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
扫码咨询,免费领取项目管理大礼包!