oop - 静态变量 vs 类变量 vs 实例变量 vs 局部变量

标签 oop python-2.7

在发帖之前,我在这个网站的搜索中阅读了半打以上的帖子(python 变量类静态实例本地)
https://stackoverflow.com/search?q=python+variables+class+static+instance+local

我为将来学习的几个结果添加了书签,但是如果我的想法是对还是错,它们似乎都没有向我澄清,所以我觉得我可能遗漏了一些关于基础知识的东西(见下文)......

术语“类变量”和“静态变量”指的是同一件事吗?在大约 3 次 Google 搜索之后,每次搜索阅读约 6 篇我能理解的文章后,我得出的结论是类和静态变量是一回事。但是,由于我只是在学习 Python 和 OOP 的基础知识,所以这个结论可能是错误的,所以我想在我继续以错误的心态继续学习之前,找出我推理中的任何缺陷。在下面的代码中:

class Variables():
    scVar = 3

    def __init__(self, a, b):
        self.iVar1 = a
        self.iVar2 = b

    def getLocalVar3(self):
        localVar1 = 17
        localVar2 = 100
        localVar3 = localVar1 + localVar2
        return localVar3

“scVar”既是类变量又是静态变量(“类”和“静态”变量是同义词)?

第二个问题是澄清我对区分类变量、实例变量和局部变量的理解。在上面的代码中,我认为 scVar 是一个类变量; iVar1 和 iVar2 是实例变量; localVar1、localVar2 和 localVar3 是局部变量。这是正确的说法,还是我错过了什么?

Thanks cirosantilli, That article that you linked to is one I haven't seen yet. I'm going to look that over. I wonder a bit about Python's point of vew that there's not a distinction between class variables and instance variables. Is this point of view one that I should try to understand correctly right up front, as a beginner, or should I just keep the idea in mind and not worry too much about reconciling my current point of view with that one until I become more experienced? That question probably seems overly vague, and dependent upon my current level of understanding Python. Mostly, I've been running commands on class examples similar to what is in the original post; predicting the output before I press the [enter] key and then studying the output when it's not what I predicted. From that, I'm starting to get some grasp of how things work in Python. Basically, I've just recently started getting a glimpse of how OO works in Python - inching forward, slowly but surely.

"However the above are just conventions: from the language point of view there is no distinction between class variables and instance variables." -- Just to help me understand this better, does the part, 'from the language point of view ...' sort of imply that the Python documentation explains this point of view somewhere within it? If so, I'll re-read through the docs and look specifically for this part, and try to conform my thinking process to it. "... between class variables and instance variables." So, even though there's the difference in the way that class and instance variables can be seen and accessed by 'classobj's and 'instance's, Python's point of view is that there is no distinction between them? I'm going to keep this idea in mind during future reading so that I can maybe get rid of some confusion on my part. After I run the *.py in the original post, I get the following outputs in IDLE, using Python 2.7.x (only the last line of the traceback error is included, for better readability):


>>> Variables.scVar
3
>>> Variables.iVar1
AttributeError: class Variables has no attribute 'iVar1'
>>> instance = Variables(5, 15)
>>> instance
<__main__.Variables instance at 0x02A0F4E0>
>>> Variables
<class __main__.Variables at 0x02A0D650>
>>> instance.scVar
3
>>> instance.iVar1
5
>>> instance2 = Variables(25, 35)
>>> instance2.scVar
3
>>> Variables.scVar = Variables.scVar * 100
>>> Variables.scVar
300
>>> instance.scVar
300
>>> instance2.scVar
300
>>> instance.scVar = 9999
>>> Variables.scVar
300
>>> instance.scVar
9999
>>> instance2.scVar
300
>>> type(Variables)
<type 'classobj'>
>>> type(instance)
<type 'instance'>

"However the above are just conventions: from the language point of view there is no distinction between class variables and instance variables." -- By using the code from the original post, is there maybe a sequence of commands that illustrates this point? I don't doubt that you know what you're talking about; I just find it difficult to reconcile my current way of thinking with the above statement. But I get the feeling that if I can start to see the difference between the two perspectives, that something important will 'click'. As an afterthought to the last few sentences, I might be on to seeing things more along the same lines as your statement about 'no distinction between class variables and instance variables', but only if my following assumption is accurate... From the code in the original post (class Variables - 12 lines), are there just the two scopes of global and local involved in that program? Since I've just started to form conclusions about how it all fits together, I think that my limited understanding of scope might be what keeps me from fully grasping the idea that there's no distinction between class variables and instance variables. The only thing I can seem to make of it now is that (only maybe) - 'Python has no distinction between class variables and instance variables; but the differences between global and local scope might make it appear to a novice that there is a distinction between these two types of variables. I don't know, does that statement identify a potential 'hang up' that I could be having about it?



"Everything is an object, including classes and integers:" -- I've read this numerous times. So much so that I take it to be a core belief to understanding OO and Python, but it's not a concept in which I fully realize the implications of yet (I think).


class Foo():
    integer = 10
    float = 6.37
    string = 'hello'
    boolean = True
    idkyet = None

    def __init__(self):
        self.a = 'iv_a'
        self.b = 'iv_b'
        self.c = 'iv_c'

    def Func(self):
        self.g = 'g'
        h = 'h'
        i = 'i'
        return 'g' + 'h' + 'i'

>>> Foo
<class __main__.Foo at 0x02A1D650>
>>> type(Foo.integer)
<type 'int'>
>>> type(Foo.float)
<type 'float'>
>>> type(Foo.string)
<type 'str'>
>>> type(Foo.boolean)
<type 'bool'>
>>> type(Foo.idkyet)
<type 'NoneType'>
>>> type(Foo)
<type 'classobj'>
>>> import os
>>> type(os.getcwd() + '\\Test.py')
<type 'str'>
>>> type(os)
<type 'module'>
>>> f = Foo()
>>> type(f)
<type 'instance'>
>>> type(f.Func)
<type 'instancemethod'>
>>> type(f.Func())
<type 'str'>
>>> f.Func
<bound method Foo.Func of <__main__.Foo instance at 0x02A25AF8>>
>>> Foo.Func
<unbound method Foo.Func>
>>> type(f.a)
<type 'str'>
>>> type(Foo.a)
AttributeError: class Foo has no attribute 'a'
>>> type(Foo.self.a)
AttributeError: class Foo has no attribute 'self'

When I was about half way through this response, leaving off with the 'class Foo():' code above and the commands ran on it below that, I hit a snag and couldn't quite continue with the other follow-up question that I barely had in mind. So, I stepped away from the problem for awhile and started to read that 'cafepy...' link that you posted (by Shalabh Chaturvedi). That's really interesting. I had seen excerpts from that before but I hadn't read the whole thing, but it seems much more understandable now than it would have been just a week ago. I think I will read the whole thing. Don't mind the last half of this post (after the '***') because I still can't pinpoint exactly what I was trying to ask. ...everything is an object...mainly just a difference in object types???... < That is the note that I had jotted down when I almost had in mind how to frame the last question, but it never came to fruition. I'll have to wait until something else 'clicks' and I can see again what I had in mind.

I'll also keep in mind to stop and re-read if I glance across anything related to 'MRO', bound and unbound methods... I have been picking up just a bit of those three terms lately, in a way that it feels like they won't be too far in the future of my learning process.

最佳答案

我相信静态变量和类变量通常用作同义词。

从惯例的角度来看,您对变量的看法是正确的:这是您大多数时候应该如何考虑它们的方式。

然而,以上只是约定:从语言的角度来看,类变量和实例变量之间没有区别。

Python 不像 C++ 或 Java。

一切都是对象,包括类和整数:

 class C(object): pass
 print id(C)
 C.a = 1
 assert C.__dict__['a'] == 1

方法和实例变量之间没有明显的区别:它们只是对象的属性。

因此,实例变量和类变量之间没有语言级别的区别:它们只是不同对象的属性:
  • 实例变量是对象(自身)的属性
  • 类变量是类对象的属性。

  • 真正的魔法发生在 . 的顺序上。运算符搜索属性:
  • __dict__对象
  • __dict__对象的类别
  • MRO 到家长类

  • 您应该阅读 this在您将来感到困惑之前,这是一篇很棒的文章。

    还要注意绑定(bind)与未绑定(bind)的方法。

    编辑 :尝试解决 OP 在他的帖子中提出的进一步问题。

    哇,好大!我会尝试阅读所有内容,但对于 future ,您应该尽量让问题更加简洁。更多代码,更少讨论 =)。你会得到更好的答案。

    should I just keep the idea in mind and not worry too much about reconciling my current point of view with that one until I become more experienced?": I do things.



    我觉得有必要就去做。当需要时,或者我不能再采取魔术行为时,我会学习。

    sort of imply that the Python documentation explains this point of view somewhere within it?



    我不了解文档,但语言本身就是这样工作的。

    当然,该语言旨在给人一种印象,即在常见情况下语法就像在 C++ 中一样工作,并且它为类添加了一层薄薄的魔法,使其看起来像这样。

    但是,由于这不是它真正的工作方式,因此您不能仅通过考虑 C++ 类语法来解释所有(有用的)行为。

    By using the code from the original post, is there maybe a sequence of commands that illustrates this point?



    我不确定它是否可以按命令顺序说明。重点是:类是对象,它们的属性通过点 . 搜索。 MRO 与对象属性的顺序相同:
    class C(object):
        i_static = 0
        def __init__(self):
            self.i = 1
    
    # i is in the __dict__ of object c
    c = C()
    assert c.__dict__['i'] == 1
    assert c.i == 1
    
    # dot finds i_static because MRO looks at class
    assert c.__class__.__dict__['i_static'] == 0
    assert c.i_static == 0
    
    # i_static is in the __dict__ of object C
    assert C.__dict__['i_static'] == 0
    assert C.i_static == 0
    
    # __eq__ is in the dict of type, which is the __class__ of C
    # By MRO, __eq__ is found. `C,C` because of bound vs unbound.
    assert C.__class__.__dict__['__eq__'](C,C)
    assert C == C
    

    are there just the two scopes of global and local involved in that program?



    这一点我不是很清楚。

    Python 中没有全局范围,只有模块级别。

    然后在函数内部有一个新的本地范围。

    剩下的就是.寻找属性。

    can't pinpoint exactly what I was trying to ask



    问:我能找到类、整数或函数之间的语法差异吗?

    如果你认为你已经找到了,请问:嗯,我怎样才能制作一个具有某些属性的对象,它的行为就像那个看起来不像一个对象的东西?

    你应该每次都能找到答案。

    例子:
    def f(): pass
    
    class C(object): pass
    

    啊哈:f不同于 c = C()因为我能做到f() but not c()`!

    但是,不,只是 f.__class__.__dict__['__call__']属性是为 f 定义的,并且可以通过 MRO 找到。

    但是我们可以为 c 做到这一点也:
    class C(object):
        def __call__(self): pass
    

    现在我们可以做c() .

    所以他们在这方面没有什么不同。

    关于oop - 静态变量 vs 类变量 vs 实例变量 vs 局部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20451696/

    相关文章:

    Python:在类主体中动态创建子类

    具有可选属性的 C++ 类

    java - Java 中的抽象?

    java - 如果只在对象初始化时分配内存,类成员变量(实例变量)如何初始化?

    opencv - 比较两个图像特定区域的直方图?打开简历

    php - 公共(public)属性无法访问面向对象的 PHP

    python - 如何避免在类似蠕虫的游戏中每帧复制水平面?

    python - 找不到请求库 - theHarvester.py

    python - 为什么Python命令 "subprocess.Popen"找不到要运行的jar文件?

    python - 从 text() 获取字符串的正则表达式