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

时间:2013-12-08 09:14:18

标签: oop python-2.7

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

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

条款'类变量'和'静态变量'指的是同一件事?经过大约三次谷歌搜索,每次搜索我能理解的约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是局部变量。这是正确的说法,还是有些东西我不知道?


  

感谢cirosantilli,你所链接的那篇文章是我还没见过的文章。我要去看看。我想知道Python的观点,即类变量和实例变量之间并没有区别。这个观点是我应该尝试正确理解,作为一个初学者,或者我应该记住这个想法,而不是太担心将我当前的观点与那个观点调和,直到我变得更有经验?这个问题似乎过于含糊,取决于我目前对Python的理解程度。大多数情况下,我一直在运行类似于原始帖子的类示例上的命令;在按下[enter]键之前预测输出,然后在不是我预测的情况下研究输出。从那开始,我开始掌握Python中的工作原理。基本上,我最近才开始瞥见OO如何在Python中工作 - 缓慢但肯定地向前推进。

     

"但是上面只是约定:从语言的角度来看,类变量和实例变量之间没有区别。" - 只是为了帮助我更好地理解这一点,从语言的角度来看这个部分......'有点暗示Python文档在其中的某个地方解释了这个观点?如果是这样,我将重新阅读文档并专门查看这一部分,并尝试使我的思维过程符合它。 " ...在类变量和实例变量之间。"因此,尽管“类”和“实例”可以看到和访问类和实例变量的方式存在差异,但Python' s   观点是他们之间没有区别?在将来的阅读中,我会记住这个想法,这样我就可以摆脱一些困惑。在原始帖子中运行* .py之后,我使用Python 2.7.x在IDLE中获得以下输出(仅包括回溯错误的最后一行,以提高可读性):

>>> 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'>
  

&#34;但是上面只是约定:从语言的角度来看,类变量和实例变量之间没有区别。&#34; - 通过使用原始帖子中的代码,可能有一系列命令说明了这一点吗?我不怀疑你知道你在说什么;我发现很难将我目前的思维方式与上述陈述相协调。但我觉得,如果我能开始看到两种观点之间的差异,那么重要的事情就是“点击”。      作为对最后几句话的补充,我可能会在你的陈述中更多地看到与类变量和实例变量之间没有区别的事情,但前提是我的以下假设是准确的。 ..从原始帖子中的代码(类变量 - 12行),是否只有全局和本地的两个范围涉及该程序?由于我刚刚开始就如何将它们组合在一起得出结论,我认为我对范围的有限理解可能使我无法完全理解类变量和实例变量之间没有区别的想法。我现在唯一能想到的就是(只有可能) - &#39; Python在类变量和实例变量之间没有区别;但是全局范围和局部范围之间的差异可能使新手认为这两种变量之间存在差异。我不知道,这个陈述是否确定了潜在的“挂断”状态。我可以拥有它吗?


  

&#34;一切都是对象,包括类和整数:&#34; - 我已多次读过这篇文章了。这么多,我认为它是理解OO和Python的核心信念,但它并不是我完全意识到(我认为)的含义的概念。

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'
  

当我在这个回复的大约一半时,离开了Foo()类:&#39;上面的代码和命令在它下面运行,我遇到了障碍,无法继续处理我几乎没有想到的其他后续问题。所以,我暂时离开了这个问题并开始阅读那个“咖啡馆......”&#39;你发布的链接(由Shalabh Chaturvedi提供)。这真的很有趣。之前我曾看过这段摘录,但我还没有读完整篇文章,但现在看起来比一周前更容易理解了。我想我会读完整件事。不要介意这篇文章的后半部分(在&#39; ***&#39;之后),因为我仍然无法确切地指出我想要问的内容。 ......一切都是一个对象...主要只是对象类型的差异??? ...&lt;这是当我几乎想到如何构建最后一个问题时我记下来的那张纸条,但它从未实现过。我不得不等到别的什么时候点击了#39;我可以再次看到我的想法。

     

如果我浏览一下与MRO&#39; MRO&#39;绑定和未绑定方法相关的任何内容,我也会记住停下来重新阅读...我一直在接受最近这三个术语,在某种程度上感觉他们在我的学习过程中不会走得太远。

1 个答案:

答案 0 :(得分:5)

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

从会议的角度来看,你对这些变量所说的是正确的:这就是你应该在大多数时候考虑它们的方法。

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

Python不像C ++或Java。

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

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

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

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

  • 实例变量是对象的属性(self)
  • 类变量是Class对象的属性。

真正的魔法发生在.运算符搜索属性的顺序上:

  • __dict__对象
  • __dict__对象的类
  • MRO一直到父类

在你将来感到困惑之前,你应该阅读this篇文章。

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

编辑:尝试解决OP在其职位上提出的其他问题。

哇,那太大了!我会尝试阅读所有内容,但对于未来,你应该尽量让问题更加完整。更多代码,更少谈话=)。你会得到更好的答案。

  

我应该记住这个想法,而不是过分担心将我目前的观点与那个观点调和,直到我变得更有经验?“:我做的事情。

我觉得有必要。当必要性召唤,或者我不能再采取魔法行为时,我会学习。

  

有点暗示Python文档在其中的某个地方解释了这个观点?

我不知道文档,但语言本身也是这样。

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

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

  

通过使用原始帖子中的代码,是否有一系列命令可以说明这一点?

我不确定它是否可以按顺序说明。关键是:类是对象,它们的属性由点. 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
  

是否只有全球和地方参与该计划的两个范围?

这是我不太清楚的一点。

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

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

其余的是.寻找属性的方式。

  

无法准确指出我想要问的内容

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

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

你应该每次都找到答案。

示例:

def f(): pass

class C(object): pass

AHA:fc = C()不同,因为我可以f() but not c()`!

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

但我们也可以为c执行此操作:

class C(object):
    def __call__(self): pass

现在我们可以c()

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