关于全球和不可变的混乱

时间:2016-11-08 14:06:12

标签: python python-3.x

我对global和不可变变量感到困惑。我有这段代码:

class ProcessObject:
    RR = 0
    def b(self):
        self.RR=5
        print("valor: ", self.RR)

    def c(self):
        print("final: ", self.RR)

    def d(self):
        global RR
        RR = 3
        print("valor: ", RR)

    print(RR)

proce = ProcessObject()
proce.b()
proce.c()
proce.d()
proce.c()

它有这个输出:

0
value:  5
final:  5
value:  3
final:  5

但我不明白为什么用" c"如果RR是不可变的对象,则值为5。为什么" d"使用全局静音RR的值。

3 个答案:

答案 0 :(得分:2)

函数d将在全局命名空间中改变(创建它之后)RR的值,而不是self.RR这是实例变量;即你不会改变 self.RR

因此,当您在RR中打印d时,3将会打印,您已分配给全局RR的值。

如果您在self.RR中打印出d,您会发现这些只是位于不同名称空间中的两个相似名称(每个名称都包含相应的值) :

 def d(self):
    global RR
    RR = 3
    print("valor: ", RR)
    print("self.RR ", self.RR)

打印出来:

valor   : 3
self.RR : 5

答案 1 :(得分:1)

这与不变性无关......但无论如何:

class ProcessObject:
    # this "RR" lives in the `class` statement namespace, 
    # it's accessible as 'RR' in this namespace. After the
    # `class` statement is executed, it becomes an attribute
    # of the `ProcessObject` class, accessible as `ProcessObject.RR`,
    # and thru instances as `ProcessObject().RR`. 
    #  
    RR = 0

    def b(self):
        # this creates an "RR" instance attribute
        # on the current instance (`self`), which shadows
        # the "RR" class attribute
        self.RR=5
        print("valor: ", self.RR)

    def c(self):
        print("final: ", self.RR)

    def d(self):
        # The two following lines creates a module-global
        # name "RR", which is distinct from the two previous
        # ones.  
        global RR
        RR = 3
        print("valor: ", RR)

    # this prints the value of the `RR` living in the class
    # statement scope - NOT the value of the yet non-existing
    # global RR
    print(RR)

proce = ProcessObject()
proce.b() # this creates the `proce.RR` instance attribute
proce.c()
proce.d()
proce.c()
  

但我不明白为什么用" c"如果RR是a,则值为5   对象不可变。

它打印' 5'因为您在调用proce.RR时已将该值指定给proce.b()。您将名称和值混淆... RR不是对象,它是绑定到对象的名称。它在某一点上与一个不可变对象绑定的事实并不意味着你不能将它重新绑定到另一个对象(可变或不可变,这与此无关)。

  

为什么" d"使用全局no静音RR的值

在这里你混淆了绑定(赋值)和变异。绑定(赋值)意味着"使该名称指向此对象",变异意味着"更改此对象的状态"。突变的一个示例是在列表中添加元素或从列表中删除元素,或者在适当的位置反转列表。

FWIW,对proce.d的调用DO重新绑定(并在第一次调用时实际绑定)模块 - 全局" RR"。

你可能想要运行这个""扩展"你的脚本版本,以找出真正发生的事情:

print("before : globals = {}".format(globals()))

class ProcessObject:
    RR = 0
    print "RR defined in the class namespace - not in globals: {}".format(globals())

    def __init__(self):
        print("in init")
        print("   self.__dict__ : {}".format(self.__dict__))
        print("   ProcessObject.__dict__ : {}".format(ProcessObject.__dict__))



    def b(self):
        print("before calling b - self.__dict__ : {}".format(self.__dict__))
        self.RR=5
        print("valor: ", self.RR)
        print("after calling b - self.__dict__ : {}".format(self.__dict__))

    def c(self):
        print("before calling c - self.__dict__ : {}".format(self.__dict__))
        print("final: ", self.RR)

    def d(self):
        print("before calling d : globals = {}".format(globals()))
        global RR
        RR = 3
        print("valor: ", RR)
        print("after calling d : globals = {}".format(globals()))

    print(RR)

print("after class statement: globals : {}".format(globals()))



proce = ProcessObject()
proce.c()
proce.b()
proce.c()
proce.d()
proce.c()

答案 2 :(得分:0)

非常感谢!!现在我明白了。现在通过您的示例,我更加了解python的工作原理和他的上下文。但是,我仍然需要了解一个小问题,这是关于不变性的。如何使变量不可变?如果我更改了他的值并再次调用此变量,则值已更改。使用此代码,您可以知道我的意思。

def e(self):
    print("before calling e - ProcessObject.__dict__ : {}".format(ProcessObject.__dict__))
    ProcessObject.RR = -7
    print("after calling e - ProcessObject.__dict__ : {}".format(ProcessObject.__dict__))
    print("=================") 

返回;

=================
before calling e - ProcessObject.__dict__ : {'b': <function ProcessObject.b at 0x006850C0>, '__module__': '__main__', 'RR': 0, '__weakref__': <attribute '__weakref__' of 'ProcessObject' objects>, 'd': <function ProcessObject.d at 0x00685150>, '__doc__': None, 'e': <function ProcessObject.e at 0x00685198>, '__init__': <function ProcessObject.__init__ at 0x00685078>, 'c': <function ProcessObject.c at 0x00685108>, '__dict__': <attribute '__dict__' of 'ProcessObject' objects>}
after calling e - ProcessObject.__dict__ : {'b': <function ProcessObject.b at 0x006850C0>, '__module__': '__main__', 'RR': -7, '__weakref__': <attribute '__weakref__' of 'ProcessObject' objects>, 'd': <function ProcessObject.d at 0x00685150>, '__doc__': None, 'e': <function ProcessObject.e at 0x00685198>, '__init__': <function ProcessObject.__init__ at 0x00685078>, 'c': <function ProcessObject.c at 0x00685108>, '__dict__': <attribute '__dict__' of 'ProcessObject' objects>}
=================
before calling e - ProcessObject.__dict__ : {'b': <function ProcessObject.b at 0x006850C0>, '__module__': '__main__', 'RR': -7, '__weakref__': <attribute '__weakref__' of 'ProcessObject' objects>, 'd': <function ProcessObject.d at 0x00685150>, '__doc__': None, 'e': <function ProcessObject.e at 0x00685198>, '__init__': <function ProcessObject.__init__ at 0x00685078>, 'c': <function ProcessObject.c at 0x00685108>, '__dict__': <attribute '__dict__' of 'ProcessObject' objects>}
after calling e - ProcessObject.__dict__ : {'b': <function ProcessObject.b at 0x006850C0>, '__module__': '__main__', 'RR': -7, '__weakref__': <attribute '__weakref__' of 'ProcessObject' objects>, 'd': <function ProcessObject.d at 0x00685150>, '__doc__': None, 'e': <function ProcessObject.e at 0x00685198>, '__init__': <function ProcessObject.__init__ at 0x00685078>, 'c': <function ProcessObject.c at 0x00685108>, '__dict__': <attribute '__dict__' of 'ProcessObject' objects>}
=================

bruno desthuilliers的代码中,我添加了一个新功能来查看,并且RR的值从RR=0更改为RR=-7,但我想要RR不可变的,当有人试图改变RR的值时,阻止这个动作。