类变量是否在实例方法或类方法的范围内


  • 类变量是否属于为Python类定义的方法的范围
  • 如何访问方法(类方法、实例方法或静态方法)中的类变量并可能对其进行更改
  • 最好的方法是什么?例如,我可能想统计已经创建了多少类实例

我在这里读到类变量在方法参数列表的范围内。要在那里使用类变量,我应该将其称为counter,而不是MyClass.counter,因为该类正处于定义的中间,但我可以在__init__方法中将其作为MyClass.counter访问。这是否意味着在__init__方法内部时类是完全定义的?

edit:我也想知道为什么counter在方法的参数列表中的作用域中,而不在方法体中?

class MyClass(object):
counter = 0
def __init__(self): # counter is in scope here. can be used as default argument
counter += 1  # Counter not in scope. Throws UnboundLocalError
def printCount(self):
print counter  # Counter not in scope. Throws UnboundLocalError

在方法中,可以通过两种不同的方式访问类属性:

  1. 通过引用类,然后属性:

    MyClass.counter
    
  2. 通过访问实例上的属性,self:

    self.counter
    

    只有当没有实例属性屏蔽counter时,这才有效。

问题是,当您在实例上设置属性时,类属性将无法再在self:上访问

self.counter += 1

将在第一次运行时设置实例属性,并且类属性将不再被访问。

如果你想设置一个类属性,你必须使用第一种寻址方法:

class MyClass(object):
counter = 0
def __init__(self): 
MyClass.counter += 1
def printCount(self):
# these both work:
print self.counter
print MyClass.counter

在方法中不能将counter作为局部引用。在类定义体之外,它们是而不是本地或全局名称。只有在class体内才能做到这一点:

然后在新的执行框架中执行类的套件[…],使用新创建的本地命名空间和原始全局命名空间。(通常,该套件只包含函数定义。)当类的套件完成执行时,其执行框架将被丢弃,但其本地命名空间将被保存。[…]然后使用基类的继承列表和属性字典的保存的本地命名空间创建类对象。

换句话说,当Python执行class主体时,counter__init__printCount是本地名称,在执行过程中,您可以将这些名称称为本地名称。因此,您可以使用counter为方法参数定义默认值,或基于该值进行计算。但一旦构建了类,该名称空间就不存在了,您将不得不引用MyClass.<name>

这里有另一个简单的解释:

1.类变量是否属于为Python类定义的方法的范围

这是类变量的解释:

  • 一个由类的所有实例共享的变量
  • 它是在一个类中定义的,但在该类的任何方法之外
  • Class变量可以使用类名点在变量名上进行访问

NB:类变量存储在class_name.__dict__中,即共享给所有实例。

注意:实例变量存储在instance.__dict__中,即仅存储到当前实例。

注意:用类名访问类变量总是一个好主意,这样可以减少混淆,并且不会用实例变量重写。

以下是片段:

class ClassA(object):
_counter = 0
def __init__(self, val):
self._counter = val
def show_me(self):
print 'Class variable: %d' % ClassA._counter
print 'Instance variable: %d' % self._counter
obj = ClassA(1000)
obj.show_me()
print ClassA.__dict__['_counter']
print obj.__dict__['_counter']

输出:

Class variable: 0
Instance variable: 1000
0
1000

2.如何访问方法中的类变量(类方法或实例方法或静态方法)并可能更改它

您可以使用class_name点变量名即访问类变量

ClassA._counter

3.最好的方法是什么?例如,我可能想统计已经创建了多少类实例

据我所知,最好重写__new__方法,因为__new__调用每个创建和更新类变量_counter的对象,如下所示:

#!/usr/bin/python
class ClassA(object):
# this _counter is in the class.__dict__ which shared across all instance
_counter = 0
def __new__(cls, *args, **kw):
ob = super(ClassA, cls).__new__(cls, *args, **kw)
ClassA._counter += 1
return ob
def __init__(self, val):
# this _counter is in the instance dictionary which is not shared
self._counter = val*val
def total_instance(self):
return ClassA._counter
# Lets create three instance
for i in range(1,4):
obj = ClassA(i)
print 'class variable _counter : %d' % obj.total_instance()
print 'instance variable _counter : %d' % obj._counter

输出:

class variable _counter : 1
instance variable _counter : 1
class variable _counter : 2
instance variable _counter : 4
class variable _counter : 3
instance variable _counter : 9

注意:在上面的例子中,我试图向您展示实例变量_counter和类变量_counter的区别。

如果有帮助,请告诉我。

最新更新