python python中静态变量和实例变量的区别。它们甚至存在吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1697273/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Differences between static and instance variables in python. Do they even exist?
提问by devoured elysium
A random class definition:
一个随机的类定义:
class ABC:
x = 6
Setting some values, first for the abc instance, later for the static variable:
设置一些值,首先是 abc 实例,然后是静态变量:
abc = ABC()
abc.x = 2
ABC.x = 5
and then print the results:
然后打印结果:
print abc.x
print ABC.x
which prints
哪个打印
2
5
Now, I don't really get what is going on, because if i replace in the class definition x = 6 for "pass", it will just output the same thing. My question is, what is the purpose of defining a variable in the class definition in python if it seems like i can anyone set at any time any variable without doing so?
现在,我真的不明白发生了什么,因为如果我在类定义中替换 x = 6 为“pass”,它只会输出相同的东西。我的问题是,如果任何人都可以随时设置任何变量而不这样做,那么在 python 的类定义中定义变量的目的是什么?
Also, does python know the difference between instance and static variables? From what I saw, I'd say so.
另外,python 知道实例变量和静态变量之间的区别吗?就我所见,我会这么说。
回答by Larry Hastings
Warning: the following is an oversimplification; I'm ignoring __new__()
and a bunch of other special class methods, and handwaving a lot of details. But this explanation will get you pretty far in Python.
警告:以下内容过于简化;我忽略了__new__()
和一堆其他特殊的类方法,并提供了很多细节。但是这个解释会让你在 Python 中走得更远。
When you create an instance of a class in Python, like calling ABC()in your example:
当您在 Python 中创建类的实例时,例如在您的示例中调用ABC():
abc = ABC()
Python creates a new empty object and sets its classto ABC. Then it calls the __init__()
if there is one. Finally it returns the object.
Python 创建一个新的空对象并将其类设置为ABC。然后它调用__init__()
if 。最后它返回对象。
When you ask for an attribute of an object, first it looks in the instance. If it doesn't find it, it looks in the instance's class. Then in the base class(es) and so on. If it never finds anybody with the attribute defined, it throws an exception.
当您请求一个对象的属性时,它首先在实例中查找。如果没有找到,它会在实例的类中查找。然后在基类中等等。如果它从未找到具有定义的属性的任何人,则会引发异常。
When you assign to an attribute of an object, it creates that attribute if the object doesn't already have one. Then it sets the attribute to that value. If the object already had an attribute with that name, it drops the reference to the old value and takes a reference to the new one.
当您分配给对象的属性时,如果该对象还没有该属性,则它会创建该属性。然后它将属性设置为该值。如果对象已经有一个具有该名称的属性,它会删除对旧值的引用并获取对新值的引用。
These rules make the behavior you observe easy to predict. After this line:
这些规则使您观察到的行为易于预测。在这一行之后:
abc = ABC()
only the ABCobject (the class) has an attribute named x. The abcinstance doesn't have its own xyet, so if you ask for one you're going to get the value of ABC.x. But then you reassign the attribute xon both the class and the object. And when you subsequently examine those attributes you observe the values you put there are still there.
只有ABC对象(类)有一个名为x的属性。在ABC实例没有自己的X还,所以如果你问一个你会得到的值ABC.x。但是随后您在类和对象上重新分配属性x。当您随后检查这些属性时,您会观察到您放置在那里的值仍然存在。
Now you should be able to predict what this code does:
现在您应该能够预测此代码的作用:
class ABC:
x = 6
a = ABC()
ABC.xyz = 5
print(ABC.xyz, a.xyz)
Yes: it prints two fives. You might have expected it to throw an AttributeError exception. But Python finds the attribute in the class--even though it was added afterthe instance was created.
是的:它打印两个五。您可能已经预料到它会抛出 AttributeError 异常。但是 Python 会在类中找到该属性——即使它是在创建实例之后添加的。
This behavior can really get you in to trouble. One classic beginner mistake in Python:
这种行为真的会让你陷入困境。Python 中的一个经典初学者错误:
class ABC:
x = []
a = ABC()
a.x.append(1)
b = ABC()
print(b.x)
That will print [1]. All instances of ABC() are sharing the same list. What you probably wanted was this:
这将打印[1]。ABC() 的所有实例共享同一个列表。你可能想要的是这样的:
class ABC:
def __init__(self):
self.x = []
a = ABC()
a.x.append(1)
b = ABC()
print(b.x)
That will print an empty list as you expect.
这将按照您的预期打印一个空列表。
To answer your exact questions:
要回答您的确切问题:
My question is, what is the purpose of defining a variable in the class definition in python if it seems like i can anyone set at any time any variable without doing so?
我的问题是,如果任何人都可以随时设置任何变量而不这样做,那么在 python 的类定义中定义变量的目的是什么?
I assume this means "why should I assign members inside the class, instead of inside the __init__
method?"
我认为这意味着“为什么我应该在类内部而不是在__init__
方法内部分配成员?”
As a practical matter, this means the instances don't have their own copy of the attribute (or at least not yet). This means the instances are smaller; it also means accessing the attribute is slower. It also means the instances all share the same value for that attribute, which in the case of mutable objects may or may not be what you want. Finally, assignments here mean that the value is an attribute of the class, and that's the most straightforward way to set attributes on the class.
实际上,这意味着实例没有自己的属性副本(或者至少还没有)。这意味着实例更小;这也意味着访问该属性的速度较慢。这也意味着实例都共享该属性的相同值,在可变对象的情况下,这可能是您想要的,也可能不是。最后,这里的赋值意味着该值是类的一个属性,这是在类上设置属性的最直接的方式。
As a purely stylistic matter it's shorter code, as you don't have all those instances of self.all over. Beyond that it doesn't make much difference. However, assigning attributes in the __init__
method ensures they are unambiguously instance variables.
作为纯粹的风格问题,它的代码更短,因为您没有所有这些self. 遍。除此之外,它没有太大区别。但是,在__init__
方法中分配属性可确保它们是明确的实例变量。
I'm not terribly consistent myself. The only thing I'm sure to do is assign all the mutable objects that I don't want shared in the __init__
method.
我自己并不是很一致。我唯一确定要做的就是分配我不想在__init__
方法中共享的所有可变对象。
Also, does python know the difference between instance and static variables? From what I saw, I'd say so.
另外,python 知道实例变量和静态变量之间的区别吗?就我所见,我会这么说。
Python classes don't have class static variables like C++ does. There are only attributes: attributes of the class object, and attributes of the instance object. And if you ask for an attribute, and the instance doesn't have it, you'll get the attribute from the class.
Python 类没有像 C++ 那样的类静态变量。只有属性:类对象的属性和实例对象的属性。如果您要求一个属性,而实例没有它,您将从类中获取该属性。
The closest approximation of a class static variable in Python would be a hidden module attribute, like so:
Python 中类静态变量的最接近的近似值是隐藏的模块属性,如下所示:
_x = 3
class ABC:
def method(self):
global _x
# ...
It's not part of the class per se. But this is a common Python idiom.
它本身不是课程的一部分。但这是一个常见的 Python 习语。
回答by jldupont
class SomeClass:
x=6 # class variable
def __init__(self):
self.y = 666 # instance variable
There is virtue in declaring a class scoped variable: it serves as default for one. Think of class scoped variable as you would think of "static" variables in some other languages.
声明一个类作用域变量是有好处的:它作为一个变量的默认值。将类作用域变量视为其他语言中的“静态”变量。
回答by S.Lott
A class-level variable (called "static" in other languages) is owned by the class, and shared by all instances of the class.
类级变量(在其他语言中称为“静态”)归类所有,并由类的所有实例共享。
A instance variable is part of by each distinct instance of the class.
实例变量是类的每个不同实例的一部分。
However.
然而。
You can add a new instance variable any time you want.
您可以随时添加新的实例变量。
So getting abc.x
requires first checking for an instance variable. If there is no instance variable, it will try the class variable.
因此获取abc.x
需要首先检查实例变量。如果没有实例变量,它会尝试类变量。
And setting abc.x
will create (or replace) an instance variable.
并且设置abc.x
将创建(或替换)一个实例变量。
回答by RedGlyph
Python makes a distinction between the two. The purpose could be multiple, but one example is this:
Python 对两者进行了区分。目的可能有多种,但一个例子是:
class token(object):
id = 0
def __init__(self, value):
self.value = value
self.id = token.id
token.id += 1
Here, the class variable token.id
is automatically incremented at each new instance, and this instance can take a unique ID at the same time, which will be put in self.id
. Both are stored at different places - in the class object, or in the instance object, you can indeed compare that to static and instance variables in some OO languages like C++ or C#.
在这里,类变量token.id
在每次新建实例时自动递增,同时这个实例可以取一个唯一的ID,放在self.id
. 两者都存储在不同的位置 - 在类对象中,或在实例对象中,您确实可以将其与某些 OO 语言(如 C++ 或 C#)中的静态和实例变量进行比较。
In that example, if you do:
在那个例子中,如果你这样做:
print token.id
you will see the next ID to be assigned, whereas:
您将看到要分配的下一个 ID,而:
x = token(10)
print x.id
will give the id of that instance.
将给出该实例的 id。
Everyone can also put other attributes in an instance or in a class, that's right, but that wouldn't be interesting since the class code is not intended to use them. The interest with an exemple as above is that the class code uses them.
每个人也可以将其他属性放在一个实例或一个类中,这是对的,但这不会有趣,因为类代码并不打算使用它们。上面例子的有趣之处在于类代码使用它们。
回答by unutbu
Every object has a __dict__
. The class ABC and its instance, abc, are both objects, and so each has their own separate __dict__
:
每个对象都有一个__dict__
. 类 ABC 及其实例 abc 都是对象,因此每个都有自己独立的__dict__
:
In [3]: class ABC:
...: x=6
Notice ABC.__dict__
has a 'x' key:
通知ABC.__dict__
有一个“x”键:
In [4]: ABC.__dict__
Out[4]: {'__doc__': None, '__module__': '__main__', 'x': 6}
In [5]: abc=ABC()
In [6]: abc.__dict__
Out[6]: {}
Notice that if 'x' is not in abc.__dict__
, then the __dict__
's of abc's superclass(es) are searched. So abc.x
is "inherited" from ABC
:
请注意,如果 'x' 不在 中abc.__dict__
,则__dict__
搜索 abc 超类的's。所以abc.x
是“继承”自ABC
:
In [14]: abc.x
Out[14]: 6
But if we set abc.x then we are changing abc.__dict__
, not ABC.__dict__
:
但是如果我们设置 abc.x 那么我们正在改变abc.__dict__
,而不是ABC.__dict__
:
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}
Of course, we can change ABC.__dict__
if we wish:
当然,ABC.__dict__
如果我们愿意,我们可以改变:
In [10]: ABC.x = 5
In [11]: ABC.__dict__
Out[11]: {'__doc__': None, '__module__': '__main__', 'x': 5}
回答by Righteous Mullet
The benefit of a "static" or in Python a "class attribute" is that each instance of the class will have access to the same class attribute. This is not true for instance attributes as you may be aware.
“静态”或 Python 中的“类属性”的好处是类的每个实例都可以访问相同的类属性。正如您可能知道的那样,对于实例属性而言,情况并非如此。
Take for example:
举个例子:
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
As you can see the instance of the class has access to the class attribute which can be set by specifying the class name and then the class attribute.
如您所见,类的实例可以访问类属性,可以通过指定类名和类属性来设置该属性。
The tricky part is when you have a class attribute and instance attribute named the same thing. This requires an understanding of what is going on under the hood.
棘手的部分是当你有一个类属性和实例属性命名相同的东西。这需要了解幕后发生的事情。
inst.__dict__ # => {}
A.__dict__ # => {..., 'b': 5}
Notice how the instance does not have b
as an attribute? Above, when we called inst.b
Python actually checks inst.__dict__
for the attribute, if it cannot be found, then it searches A.__dict__
(the class's attributes). Of course, when Python looks up b
in the class's attributes it is found and returned.
注意实例如何没有b
作为属性?上面,当我们调用inst.b
Python时实际检查inst.__dict__
了属性,如果找不到,则搜索A.__dict__
(类的属性)。当然,当 Pythonb
在类的属性中查找时,它会被找到并返回。
You can get some confusing output if you then set an instance attribute with the same name. For example:
如果然后设置具有相同名称的实例属性,则可能会得到一些令人困惑的输出。例如:
inst.b = 10
inst.__dict__ #=> {'b': 10}
A.b # => 5
inst.b # => 10
You can see that the instance of the class now has the b
instance attribute and therefore Python returns that value.
您可以看到类的b
实例现在具有实例属性,因此 Python 返回该值。