Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/323.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 为什么方法可以';t访问类变量?_Python - Fatal编程技术网

Python 为什么方法可以';t访问类变量?

Python 为什么方法可以';t访问类变量?,python,Python,我试图理解Python中的变量作用域,除了我不明白为什么类变量不能从其方法访问之外,大多数事情我都很清楚。 在下面的示例中,mydef1()无法访问a,但如果a在全局范围(类定义之外)中声明,则可以访问 输出 Traceback (most recent call last): File "E:\dev\Python\scope_test2.py", line 6, in <module> ins1.mydef1() File "E:\dev\Python\scope

我试图理解Python中的变量作用域,除了我不明白为什么类变量不能从其方法访问之外,大多数事情我都很清楚。
在下面的示例中,
mydef1()
无法访问
a
,但如果
a
在全局范围(类定义之外)中声明,则可以访问

输出

Traceback (most recent call last):
  File "E:\dev\Python\scope_test2.py", line 6, in <module>
    ins1.mydef1()
  File "E:\dev\Python\scope_test2.py", line 4, in mydef1
    print(a)
NameError: name 'a' is not defined
回溯(最近一次呼叫最后一次):
文件“E:\dev\Python\scope\u test2.py”,第6行,在
ins1.mydef1()
文件“E:\dev\Python\scope\u test2.py”,第4行,在mydef1中
印刷品(a)
NameError:未定义名称“a”

您需要
self.a
。没有隐式类作用域。

您需要
self.a
。没有隐式的类作用域。

重要的是要理解其中一些注释是不等价的
MyClass.a
是类本身的成员,
self.a
是类实例的成员

使用
self.a
时,它将从类返回
a
,因为实例上没有
a
。如果还有一个
a
,它是实例的成员,它将返回该实例。通常,使用
\uuuu init\uuu
构造函数设置实例a。这两者可以同时存在

class MyClass1:
    a = 25

    def __init__(self):
        self.a = 100

    def instance_a(self):
        print(self.a)

    def change_instance_a(self):
        self.a = 5

    def class_a(self):
        print(MyClass1.a)

    def change_class_a(self):
        MyClass1.a = 10


# Create two instances
ins1 = MyClass1()
ins2 = MyClass1()

# Both instances have the same Class member a, and the same instance member a
ins1.instance_a()
ins2.instance_a()
ins1.class_a()
ins2.class_a()

# Now lets change instance a on one of our instances
ins1.change_instance_a()

# Print again, see that class a values remain the same, but instance a has
# changed on one instance only
print()
ins1.instance_a()
ins2.instance_a()
ins1.class_a()
ins2.class_a()

# Lets change the class member a on just one instance
ins1.change_class_a()

# Both instances now report that new value for the class member a
print()
ins1.instance_a()
ins2.instance_a()
ins1.class_a()
ins2.class_a()
            self.a = 100

        def instance_a(self):
            print(self.a)

        def change_instance_a(self):
            self.a = 5

        def class_a(self):
            print(MyClass1.a)

        def change_class_a(self):
            MyClass1.a = 10

重要的是要理解这些评论中的一些并不等同
MyClass.a
是类本身的成员,
self.a
是类实例的成员

使用
self.a
时,它将从类返回
a
,因为实例上没有
a
。如果还有一个
a
,它是实例的成员,它将返回该实例。通常,使用
\uuuu init\uuu
构造函数设置实例a。这两者可以同时存在

class MyClass1:
    a = 25

    def __init__(self):
        self.a = 100

    def instance_a(self):
        print(self.a)

    def change_instance_a(self):
        self.a = 5

    def class_a(self):
        print(MyClass1.a)

    def change_class_a(self):
        MyClass1.a = 10


# Create two instances
ins1 = MyClass1()
ins2 = MyClass1()

# Both instances have the same Class member a, and the same instance member a
ins1.instance_a()
ins2.instance_a()
ins1.class_a()
ins2.class_a()

# Now lets change instance a on one of our instances
ins1.change_instance_a()

# Print again, see that class a values remain the same, but instance a has
# changed on one instance only
print()
ins1.instance_a()
ins2.instance_a()
ins1.class_a()
ins2.class_a()

# Lets change the class member a on just one instance
ins1.change_class_a()

# Both instances now report that new value for the class member a
print()
ins1.instance_a()
ins2.instance_a()
ins1.class_a()
ins2.class_a()
            self.a = 100

        def instance_a(self):
            print(self.a)

        def change_instance_a(self):
            self.a = 5

        def class_a(self):
            print(MyClass1.a)

        def change_class_a(self):
            MyClass1.a = 10

考虑以下类别:

class ScopeTest(object):
    classvariable = 0
    number_of_objects_created = 0

    def __init__(self, value=1):
        self.instancevariable = value
        ScopeTest.number_of_objects_created += 1

    def number_of_brothers(self):
        print(ScopeTest.number_of_objects_created)

    def confusion(self, value=2):
        self.classvariable = value
        print (f"class: {ScopeTest.classvariable}, self:{self.classvariable}")
让我们看看当你玩它时会发生什么:

>>> a = ScopeTest()
>>> a.instancevariable
1
>>> a.classvariable
0
>>> ScopeTest.classvariable
0
到目前为止还不错,但当您为
a
指定一个新属性时:

>>> a.classvariable = 2
>>> a.classvariable
2
>>> ScopeTest.classvariable
0
如果将属性添加到类的方法中,情况也是如此:

>>> a.confusion(4)
class: 0, self:4
这些类属性有助于保持所有对象的公共性,因为创建的对象的数量如下所示:

>>> b = ScopeTest()
>>> b.number_of_brothers()
2
>>> a.number_of_brothers()
2
通过向类中添加另一个方法,您可以从中获得更多:

class ScopeTest(object):
    ...
    def other_function(self, classvariable=3):
        print(f"class: {ScopeTest.classvariable}\t"
              f"instance: {self.classvariable}\t"
              f"argument:{classvariable}")
并调用它(在使用第一个“混淆”方法设置
self.classvariable
之后):


考虑以下类别:

class ScopeTest(object):
    classvariable = 0
    number_of_objects_created = 0

    def __init__(self, value=1):
        self.instancevariable = value
        ScopeTest.number_of_objects_created += 1

    def number_of_brothers(self):
        print(ScopeTest.number_of_objects_created)

    def confusion(self, value=2):
        self.classvariable = value
        print (f"class: {ScopeTest.classvariable}, self:{self.classvariable}")
让我们看看当你玩它时会发生什么:

>>> a = ScopeTest()
>>> a.instancevariable
1
>>> a.classvariable
0
>>> ScopeTest.classvariable
0
到目前为止还不错,但当您为
a
指定一个新属性时:

>>> a.classvariable = 2
>>> a.classvariable
2
>>> ScopeTest.classvariable
0
如果将属性添加到类的方法中,情况也是如此:

>>> a.confusion(4)
class: 0, self:4
这些类属性有助于保持所有对象的公共性,因为创建的对象的数量如下所示:

>>> b = ScopeTest()
>>> b.number_of_brothers()
2
>>> a.number_of_brothers()
2
通过向类中添加另一个方法,您可以从中获得更多:

class ScopeTest(object):
    ...
    def other_function(self, classvariable=3):
        print(f"class: {ScopeTest.classvariable}\t"
              f"instance: {self.classvariable}\t"
              f"argument:{classvariable}")
并调用它(在使用第一个“混淆”方法设置
self.classvariable
之后):

通过在
mydef1
中调用
print(a)
,python正在寻找一个本地(或全局,如您所发现的)变量“
a
”。也就是说,一个与
MyClass1
没有任何直接关系的变量,但这种变量尚未定义

如果您试图访问类变量“
a
”(即
a
是类本身的成员,而不是它的任何实例),则必须使用
MyClass1.a
。或者,由于没有名为“
a
”的实例变量,因此也可以使用
self.a
来达到相同的效果。但是,一旦明确定义了self.a,
self.a==MyClass1.a
,则可能不是真的。例如:

>>>class MyClass1:
...    a = 25
...
>>>my_obj = MyClass1()
>>>MyClass1.a
25
>>>my_obj.a
25
>>>MyClass1.a += 1
>>>MyClass1.a
26
>>>my_obj.a
26
>>>my_obj.a = 5  # explicitly define "a" for this instance; my_obj.a not longer synonymous with MyClass1.a
>>>MyClass1.a += 1
>>>MyClass1.a
27
>>>my_obj.a
5
通过在
mydef1
中调用
print(a)
,python正在寻找一个本地(或全局,如您所发现的)变量“
a
”。也就是说,一个与
MyClass1
没有任何直接关系的变量,但这种变量尚未定义

如果您试图访问类变量“
a
”(即
a
是类本身的成员,而不是它的任何实例),则必须使用
MyClass1.a
。或者,由于没有名为“
a
”的实例变量,因此也可以使用
self.a
来达到相同的效果。但是,一旦明确定义了self.a,
self.a==MyClass1.a
,则可能不是真的。例如:

>>>class MyClass1:
...    a = 25
...
>>>my_obj = MyClass1()
>>>MyClass1.a
25
>>>my_obj.a
25
>>>MyClass1.a += 1
>>>MyClass1.a
26
>>>my_obj.a
26
>>>my_obj.a = 5  # explicitly define "a" for this instance; my_obj.a not longer synonymous with MyClass1.a
>>>MyClass1.a += 1
>>>MyClass1.a
27
>>>my_obj.a
5

简短回答:这就是Python的作用域规则。Python中的嵌套函数是词汇范围的,但这不适用于类中嵌套的东西

class Foo:
    a = 25
    print(a)
    class Bar:
        print(a)
第一个打印,但第二个是
namererror


详细回答:

类级变量有一个函数闭包,但它都包装在
\uuuuu class\uuuu
中。(这主要用于
super()
magic,这就是为什么它不再需要Python 3中的参数。)

通常,您可以通过
self
参数访问这些内容,以允许子类重写它们,但是
\uuuuu类\uuuuuuu
甚至可以用于既没有
self
也没有
cls
的staticmethod

class MyClass1:
    a = 25
    @staticmethod
    def mydef1():
        print(__class__.a)
ins1 = MyClass1()
ins1.mydef1()  # 25

从技术上讲,类对象甚至在类声明完成执行之前都不存在,这就是为什么不能这样做

class Foo:
    a = 25
    class Bar:
        # NameError: free variable '__class__' referenced before assignment
        print(__class__.a)
甚至

class Foo:
    a = 25
    def bar():
        print(__class__.a)
    # NameError: free variable '__class__' referenced before assignment in enclosing scope
    bar()
但是,在此之前,您可以访问
locals()
dict

class Foo:
    a = 21
    locals()['a'] *= 2

Foo.a  # 42
所以这是可行的

class Foo:
    a = 25
    global foolocals
    foolocals = locals()
    def bar():
        print(foolocals['a'])
    bar()  # 25

简短回答:这就是Python的作用域规则。Python中的嵌套函数是词汇范围的,但这不适用于类中嵌套的东西

class Foo:
    a = 25
    print(a)
    class Bar:
        print(a)
第一个打印,但第二个是
namererror


详细回答:

类级变量有一个函数闭包,但它都包装在
\uuuuu class\uuuu
中。(这主要用于
super()
magic,这就是为什么它不再需要Python 3中的参数。)

通常情况下,您可以通过