python中静态变量和实例变量之间的差异。他们真的存在吗?

python中静态变量和实例变量之间的差异。他们真的存在吗?,python,Python,随机类定义: class ABC: x = 6 先为abc实例设置一些值,然后为静态变量设置一些值: abc = ABC() abc.x = 2 ABC.x = 5 然后打印结果: print abc.x print ABC.x 哪张照片 2 5 现在,我没有真正了解发生了什么,因为如果我在类定义中替换x=6作为“pass”,它将只输出相同的内容。我的问题是,如果任何人在任何时候都可以设置任何变量而不这样做,那么在python的类定义中定义变量的目的是什么 另外,python知道

随机类定义:

class ABC:
    x = 6
先为abc实例设置一些值,然后为静态变量设置一些值:

abc = ABC()
abc.x = 2
ABC.x = 5
然后打印结果:

print abc.x
print ABC.x
哪张照片

2
5
现在,我没有真正了解发生了什么,因为如果我在类定义中替换x=6作为“pass”,它将只输出相同的内容。我的问题是,如果任何人在任何时候都可以设置任何变量而不这样做,那么在python的类定义中定义变量的目的是什么

另外,python知道实例变量和静态变量之间的区别吗?据我所见,我会这么说

class SomeClass:
  x=6  # class variable

  def __init__(self):
    self.y = 666  # instance variable
声明类作用域变量有一个优点:它作为一个变量的默认值。将类范围变量视为某些其他语言中的“静态”变量。

类级别变量(在其他语言中称为“静态”)由类拥有,并由类的所有实例共享

实例变量是类的每个不同实例的一部分

不过

您可以随时添加新的实例变量

因此,获取abc.x需要首先检查实例变量。如果没有实例变量,它将尝试类变量


设置abc.x将创建(或替换)一个实例变量。

Python对这两者进行了区分。目的可能是多方面的,但一个例子是:

class token(object):
    id = 0

    def __init__(self, value):
        self.value = value
        self.id = token.id
        token.id += 1
在这里,类变量
token.id
会在每个新实例中自动递增,并且该实例可以同时获取一个唯一的id,该id将被放入
self.id
中。它们都存储在不同的地方——在类对象中,或者在实例对象中,您确实可以将它与一些类似于C++或C语言的OO语言中的静态和实例变量进行比较。 在该示例中,如果您这样做:

print token.id
您将看到下一个要分配的ID,而:

x = token(10)
print x.id
将给出该实例的id


每个人也可以在实例或类中放置其他属性,这是正确的,但这并不有趣,因为类代码并不打算使用它们。上面的例子的有趣之处在于类代码使用它们。

每个对象都有一个
\uuuu dict\uuuu
。类ABC及其实例ABC都是对象,因此每个对象都有各自独立的
\uu dict\uu

In [3]: class ABC:
   ...:     x=6
In [7]: abc.x = 2

In [8]: abc.__dict__
Out[8]: {'x': 2}

In [9]: ABC.__dict__
Out[9]: {'__doc__': None, '__module__': '__main__', 'x': 6}
注意
ABC.\uuuu dict\uuuu
有一个“x”键:

In [4]: ABC.__dict__
Out[4]: {'__doc__': None, '__module__': '__main__', 'x': 6}

In [5]: abc=ABC()

In [6]: abc.__dict__
Out[6]: {}
请注意,如果“x”不在abc中,则会搜索abc超类的
。因此,
abc.x
是从
abc
继承的:

In [14]: abc.x
Out[14]: 6
但是如果我们设置abc.x,那么我们正在改变abc,而不是abc

In [3]: class ABC:
   ...:     x=6
In [7]: abc.x = 2

In [8]: abc.__dict__
Out[8]: {'x': 2}

In [9]: ABC.__dict__
Out[9]: {'__doc__': None, '__module__': '__main__', 'x': 6}
当然,如果我们愿意,我们可以更改ABC

In [10]: ABC.x = 5

In [11]: ABC.__dict__
Out[11]: {'__doc__': None, '__module__': '__main__', 'x': 5}

警告:以下内容过于简单化;我忽略了
\uuuu new\uuuu()
和其他一些特殊的类方法,并且手工保存了很多细节。但是这个解释将使您在Python中走得更远

在Python中创建类的实例时,如在示例中调用ABC()

abc = ABC()
class A(object):
    b = 1

A.b        # => 1
inst = A()
inst2 = A()
inst.b     # => 1
inst2.b    # => 1
A.b = 5
inst.b     # => 5
inst2.b    # => 5
inst.b = 10
inst.__dict__  #=> {'b': 10}
A.b         # => 5
inst.b      # => 10
Python创建一个新的空对象,并将其类设置为ABC。然后它调用
\uuuu init\uuuu()
(如果有)。最后它返回对象

当您请求对象的属性时,首先它会在实例中查找。如果找不到,则在实例的类中查找。然后在基类中(es)等等。如果它从未找到定义了该属性的任何人,则会抛出异常

当指定给对象的属性时,如果该对象还没有属性,则会创建该属性。然后将属性设置为该值。如果对象已经具有具有该名称的属性,它将删除对旧值的引用,并引用新值

这些规则使你观察到的行为易于预测。在这一行之后:

abc = ABC()
只有ABC对象(类)具有名为x的属性。abc实例还没有自己的x,因此如果您请求一个实例,您将得到abc.x的值。但是,然后在类和对象上重新指定属性x。当你随后检查这些属性时,你会观察到你所输入的值仍然存在

现在,您应该能够预测此代码的作用:

class ABC:
  x = 6

a = ABC()
ABC.xyz = 5
print(ABC.xyz, a.xyz)
是的:它印两个五。您可能期望它抛出AttributeError异常。但是Python会在类中找到该属性——即使它是在创建实例之后添加的

这种行为真的会给你带来麻烦。Python中一个典型的初学者错误:

class ABC:
  x = []

a = ABC()
a.x.append(1)

b = ABC()
print(b.x)
将打印[1]。ABC()的所有实例共享同一个列表。你可能想要的是:

class ABC:
  def __init__(self):
    self.x = []

a = ABC()
a.x.append(1)

b = ABC()
print(b.x)
这将像您期望的那样打印一个空列表

要回答您的确切问题:

我的问题是,如果任何人在任何时候都可以设置任何变量而不这样做,那么在python的类定义中定义变量的目的是什么

我假设这意味着“为什么我应该在类内部而不是在
\uuuu init\uuuu
方法内部分配成员?”

实际上,这意味着实例没有自己的属性副本(或者至少还没有)。这意味着实例更小;这也意味着访问属性的速度较慢。这还意味着所有实例都共享该属性的相同值,在可变对象的情况下,这可能是您想要的,也可能不是您想要的。最后,这里的赋值意味着值是类的一个属性,这是在类上设置属性的最直接的方法

纯粹从风格上讲,它的代码较短,因为您没有所有的self实例