类变量是实例方法还是类方法的范围?

aja*_*jay 0 python methods scope class

  • 类变量是否属于为Python类定义的方法的范围?
  • 如何在方法(类方法或实例方法或静态方法)中访问类变量并可能更改它?
  • 什么是最好的方式?例如,我可能想要计算已经创建了多少个类的实例.

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

编辑:我也想知道为什么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
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 8

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

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

    MyClass.counter
    
    Run Code Online (Sandbox Code Playgroud)
  2. 通过访问实例上的属性,self:

    self.counter
    
    Run Code Online (Sandbox Code Playgroud)

    这仅在没有实例属性屏蔽时才有效counter.

问题是,当您在实例上设置属性时,不再能够访问类属性self:

self.counter += 1
Run Code Online (Sandbox Code Playgroud)

将在您第一次运行此属性时设置实例属性,并且将不再访问该类属性.

如果要设置类属性,则必须使用第一种方法来处理它:

class MyClass(object):
    counter = 0

    def __init__(self): 
        MyClass.counter += 1

    def printCount(self):
        # these both work:
        print self.counter
        print MyClass.counter
Run Code Online (Sandbox Code Playgroud)

您不能counter在方法中将其称为本地.在类定义主体之外,它们不是本地名称或全局名称.只有在class体内才能做到:

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

换句话说,当Python的执行class机构,counter__init__printCount本地名称,执行过程中可以参考这些名称为本地人.因此,您可以使用它counter来定义方法参数的默认值,或者对其进行基础计算.但是一旦构造了类,那个命名空间就消失了,你将不得不引用它MyClass.<name>.