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

dev*_*ium 11 python

随机类定义:

class ABC:
    x = 6
Run Code Online (Sandbox Code Playgroud)

首先为abc实例设置一些值,稍后为静态变量设置一些值:

abc = ABC()
abc.x = 2
ABC.x = 5
Run Code Online (Sandbox Code Playgroud)

然后打印结果:

print abc.x
print ABC.x
Run Code Online (Sandbox Code Playgroud)

打印

2
5
Run Code Online (Sandbox Code Playgroud)

现在,我真的不知道发生了什么,因为如果我在类定义x = 6中替换"pass",它将只输出相同的东西.我的问题是,在python的类定义中定义变量的目的是什么,如果看起来我可以随时设置任何变量而不这样做?

另外,python是否知道实例和静态变量之间的区别?从我所看到的,我会这样说.

Lar*_*ngs 19

警告:以下是过于简单化; 我忽略__new__()了一些其他特殊的类方法,并且手工操作了很多细节.但是这个解释会让你在Python中走得很远.

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

abc = ABC()
Run Code Online (Sandbox Code Playgroud)

Python创建一个新的空对象并将其设置为ABC.然后它调用__init__()if是否有一个.最后它返回对象.

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

分配给对象的属性时,如果对象尚未具有该属性,则会创建该属性.然后它将属性设置为该值.如果对象已具有具有该名称的属性,则会删除对旧值的引用并引用新值.

这些规则使您观察到的行为易于预测.在此之后:

abc = ABC()
Run Code Online (Sandbox Code Playgroud)

只有ABC对象(该类)具有名为x的属性.在ABC实例没有自己的X还,所以如果你问一个你会得到的值ABC.x.但是,然后在类和对象上重新分配属性x.当您随后检查这些属性时,您会观察到您放置的值仍然存在.

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

class ABC:
  x = 6

a = ABC()
ABC.xyz = 5
print(ABC.xyz, a.xyz)
Run Code Online (Sandbox Code Playgroud)

是的:它会打印两个五.您可能希望它抛出AttributeError异常.但Python在类中找到了属性 - 即使它是创建实例添加的.

这种行为确实会让你陷入困境.Python中一个经典的初学者错误:

class ABC:
  x = []

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

b = ABC()
print(b.x)
Run Code Online (Sandbox Code Playgroud)

那将打印[1].ABC()的所有实例共享相同的列表.你可能想要的是这个:

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

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

b = ABC()
print(b.x)
Run Code Online (Sandbox Code Playgroud)

这将按预期打印一个空列表.

要回答您的确切问题:

我的问题是,在python的类定义中定义变量的目的是什么,如果看起来我可以随时设置任何变量而不这样做?

我认为这意味着"我为什么要在类中分配成员,而不是在__init__方法内?"

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

作为一个纯粹的风格问题,它是更短的代码,因为你没有所有这些自我的实例.遍.除此之外,它没有太大的区别.但是,在__init__方法中分配属性可确保它们是明确的实例变量.

我自己并不是非常一致.我唯一要做的就是分配我不想在__init__方法中共享的所有可变对象.

另外,python是否知道实例和静态变量之间的区别?从我所看到的,我会这样说.

Python类没有像C++那样的类静态变量.只有属性:类对象的属性和实例对象的属性.如果你要求一个属性,而实例没有它,你将从类中获取属性.

Python中类静态变量的最接近的近似值是隐藏的模块属性,如下所示:

_x = 3
class ABC:
  def method(self):
    global _x
    # ...
Run Code Online (Sandbox Code Playgroud)

这不是班级本身的一部分.但这是一个常见的Python习语.


jld*_*ont 12

class SomeClass:
  x=6  # class variable

  def __init__(self):
    self.y = 666  # instance variable
Run Code Online (Sandbox Code Playgroud)

声明一个类范围的变量是有道理的:它作为一个变量的默认值.考虑类范围的变量,就像在其他一些语言中想到的"静态"变量一样.