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实例