4

我有一个文件 a.py

avariable = None

class a():

  def method(self):
    global avariable
    avariable = 100
    print "variable is", avariable

和一个文件 b.py

from a import *

class b(a,):

  def mymethod(self):
    a().method()
    print "avariable is " , avariable

if __name__ == '__main__':
  b().mymethod()

Fileb导入所有内容a并继承自a. a'smethod被调用并且avariableis 更改为 100 但是当我avariable在 b 中打印时值为None. 如何在类中使用类更改b的变量?avariablea

输出:

>python b.py 
variable is 100
avariable is  None

澄清

对我来说至关重要

from a import *

因为我已经在 b 类中编写了代码,它使用语法调用 a 类的方法

self.method()

这不能改变。

IE

from a import *
class b(a):

  def mymethod(self):
    self.method()
    print "avariable is " , avariable

if __name__ == '__main__':
  b().mymethod()

avariable那么有没有办法在不以任何方式 前缀的情况下访问变量avariable

4

4 回答 4

4

一个.py

avariable = None

class a():

    def method(self):
        global avariable
        avariable = 100
        print "variable is", avariable

b.py

import a


class b(a.a):
    def mymethod(self):
        a.a().method()
        print "avariable is ", a.avariable


if __name__ == '__main__':
    print a.avariable
    b().mymethod()
    b().mymethod()

输出:

None
variable is 100
avariable is  100
variable is 100
avariable is  100

你得到None了所有的时间,因为一旦你导入avariable你将它保存在你自己的文件中,但是a.py改变的是avariable它自己的文件中的变量(或者更恰当地说,它自己的全局命名空间),因此你看不到任何变化。

但是在上面的示例中,您可以看到更改。这是因为,我们正在导入a模块本身,从而访问它的所有对象(Python 中的一切都是一个对象)。因此,当我们调用时,a.avariable我们实际上是在调用全局命名空间avriable中的变量。a

编辑

下面的代码仍然会产生相同的输出。

import a


class b(a.a):
    def mymethod(self):
        self.method()
        print "avariable is ", a.avariable


if __name__ == '__main__':
    print a.avariable
    b().mymethod()
    b().mymethod()
于 2013-10-14T11:01:31.877 回答
1

通过直接导入定义变量的模块(如示例avariable中的模块a),您将在导入模块中获得第二个变量。这两个变量不相同(a.avariable is not b.avariable)。

您可以使用更合格的命名方案来访问其他模块的变量(如@Games Brainiac 的答案所示)。

关键字global将变量声明为module-global。Python 没有真正的全局变量的概念,这些变量对于每个模块都是相同的。(如果我在这里错了,请纠正我,但我还没有找到这样的东西。)

于 2013-10-14T11:05:48.377 回答
1

首先,继承与它无关,只会使您的示例复杂化。您可以仅使用a.py.

无论如何,当您编写 时from a import *,Python 会遍历 中的所有公共变量a,并将模块的字典更新b为(非常简化):

import a
for name in a.__dict__:
    locals()[name] = a.__dict__[name]

所以avariable只是被复制的内容,当你打印它时b.py,你正在打印一个不同的变量(你也可以通过打印ids 来检查它)。

做你想做的事,你b.py必须看起来像

import a

class b(a.a,):

  def mymethod(self):
    a.a().method()
    print "avariable is " , a.avariable

if __name__ == '__main__':
  b().mymethod()

这样您实际上正在访问相同的avariable.

但话虽如此,这绝对是一种可怕的做法。模块中的非常量全局变量会导致各种奇怪且难以检测的错误。

于 2013-10-14T11:01:46.457 回答
1

模块中的全局变量仅对该模块是全局的,而不是在导入的模块中。

因此,当您调用a().method()b.py 时,global avariable实际上会修改 a's avariablenot b

即你不能a使用globalin访问 的全局命名空间b.py


例子:

一个.py

x = 'a'
def func():
    global x
    print x

b.py:

from a import *
x = 'b'           #override `x` imported from `a`
func()            #call to func() prints 'a' not 'b'
print x           #prints 'b'

func()实际访问a' 的调用x不是当前的x,因此它按预期打印并'a'打印'b'。print xb.py

输出:

a
b

阅读: Python - 导入模块中全局变量的可见性


您可以使用类属性而不是使用全局变量:

一个.py

class a(object):
    variable = None
    def method(self):
        a.avariable = 100 #modification to `a`'s attribute will be seen in `b()`
        print "variable is", a.avariable

b.py

from a import *

class b(a):
    def mymethod(self):
        a().method()
        print "avariable is " , self.avariable

if __name__ == '__main__':
    b().mymethod()

输出:

variable is 100
avariable is  100
于 2013-10-14T11:03:11.897 回答