首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >python中静态变量和实例变量的区别。他们真的存在吗?

python中静态变量和实例变量的区别。他们真的存在吗?
EN

Stack Overflow用户
提问于 2009-11-09 01:36:12
回答 6查看 11.8K关注 0票数 15

一个随机的类定义:

代码语言:javascript
复制
class ABC:
    x = 6

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

代码语言:javascript
复制
abc = ABC()
abc.x = 2
ABC.x = 5

然后打印结果:

代码语言:javascript
复制
print abc.x
print ABC.x

哪种打印

代码语言:javascript
复制
2
5

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

另外,python知道实例变量和静态变量之间的区别吗?从我看到的情况来看,我会这么说。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2009-11-09 01:40:16

代码语言:javascript
复制
class SomeClass:
  x=6  # class variable

  def __init__(self):
    self.y = 666  # instance variable

声明一个类作用域变量有一个优点:它作为一个变量的默认值。将类作用域变量视为其他语言中的“静态”变量。

票数 15
EN

Stack Overflow用户

发布于 2009-11-12 01:21:44

警告:下面是一个过于简单的例子;我忽略了__new__()和其他一些特殊的类方法,并处理了很多细节。但这个解释将使您在Python中走得更远。

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

代码语言:javascript
复制
abc = ABC()

Python创建一个新的空对象,并将其设置为ABC。然后,它调用__init__() (如果有)。最后,它返回对象。

当你请求一个对象的属性时,它首先在实例中查找。如果它没有找到它,它会在实例的类中查找。然后在基类中,依此类推。如果它找不到任何定义了该属性的人,就会抛出异常。

当您为对象的属性赋值时,如果该对象还没有该属性,则会创建该属性。然后将该属性设置为该值。如果对象已经有一个同名的属性,它会删除对旧值的引用,并引用新值。

这些规则使得你观察到的行为很容易预测。在此行之后:

代码语言:javascript
复制
abc = ABC()

只有ABC对象(类)具有名为x的属性。abc实例还没有自己的x,所以如果您请求一个,您将获得ABC.x的值。但是,您可以在类和对象上重新分配属性x。当你随后检查这些属性时,你会发现你放在那里的值仍然存在。

现在您应该能够预测这段代码的作用了:

代码语言:javascript
复制
class ABC:
  x = 6

a = ABC()
ABC.xyz = 5
print(ABC.xyz, a.xyz)

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

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

代码语言:javascript
复制
class ABC:
  x = []

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

b = ABC()
print(b.x)

这将打印1。ABC()的所有实例都共享相同的列表。你可能想要的是:

代码语言:javascript
复制
class ABC:
  def __init__(self):
    self.x = []

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

b = ABC()
print(b.x)

如您所料,这将打印出一个空列表。

要回答您的确切问题:

我的问题是,在

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

我假设这意味着“为什么我要在类中分配成员,而不是在__init__方法中?”

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

作为一个纯粹的风格问题,它的代码更短,因为你不会到处都有self.的实例。除此之外,它没有太大的不同。但是,在__init__方法中分配属性可以确保它们是明确的实例变量。

我自己也不是很稳定。我唯一确定要做的事情就是在__init__方法中分配我不想要共享的所有可变对象。

另外,

知道实例变量和静态变量之间的区别吗?从我看到的情况来看,我会这么说。

Python类没有像C++那样的类静态变量。只有属性:类对象的属性和实例对象的属性。如果您请求一个属性,但实例没有该属性,则可以从类中获取该属性。

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

代码语言:javascript
复制
_x = 3
class ABC:
  def method(self):
    global _x
    # ...

它本身并不是类的一部分。但这是一种常见的Python习惯用法。

票数 25
EN

Stack Overflow用户

发布于 2009-11-09 01:42:23

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

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

然而。

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

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

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

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1697273

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档