另一个文件中的acess类属性

时间:2016-07-29 02:21:38

标签: python

我是python的新手。

我有一个关于访问类

中的属性的问题

t1.py

#!/usr/bin/python
import t2

class A:
        flag = False

if __name__ == "__main__":
        t2.f()
        print(A.flag)

t2.py

#!/usr/bin/python
import t1

def f():
        t1.A.flag = True
        print(t1.A.flag)

执行结果:

# ./t1.py
True
False

我希望结果必须为True,True。

t1.py中的A.flag和t2.py中的t1.A.flag不同吗?

执行此代码时python中发生了什么?

谢谢。

4 个答案:

答案 0 :(得分:2)

当你这样做时

./t1.py

您正在执行t1.py文件,但它并未作为t1模块执行。它被认为是__main__模块。 (这是if __name__ == '__main__'行检查的内容。)这意味着当这一行:

import t1
t2.py中的

尝试导入t1,Python开始再次执行t1.py文件 以创建t1模块。您最终得到了A类的两个版本,一个是__main__.A,另一个是t1.A。对t1.A的修改对__main__.A没有任何作用,因为即使它们来自同一文件中的相同代码,它们也不是同一个类。

答案 1 :(得分:0)

它们确实是两个不同的对象(在user2357112's answer中解释得非常好)。如果您希望t2使用相同的对象,则需要告诉Python您实际上正在导入导入t2的同一模块。为此,请改为导入__main__

import __main__

def f():
    __main__.A.flag = True
    print(__main__.A.flag)

答案 2 :(得分:0)

你可以自己找到它:

t1.py

#!/usr/bin/python
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
logger.debug('t1 has started')
logger.debug('t2 is being imported')
import t2

logger.debug('A is being "compiled"')
class A:
    flag = False
logger.debug('ID A: %r', id(A))
logger.debug('ID A.flag %r', id(A.flag))

logger.debug('What is __name__? %r', __name__)
if __name__ == "__main__":
    logger.debug('__name__ was "__main__"')
    logger.debug('Calling t2.f()')
    t2.f()
    logger.debug('t2.f() was called')
    logger.debug('ID A.flag: %r', id(A.flag))
    print(A.flag)

t2.py

#!/usr/bin/python
import logging
logger = logging.getLogger(__name__)
logger.debug('t2 is being imported')

logger.debug('t2 is now importing t1')
import t1

def f():
    logger.debug('f is being called')
    t1.A.flag = True
    logger.debug('ID t1: %r', id(t1))
    logger.debug('ID t1.A: %r', id(t1.A))
    logger.debug('ID t1.A.flag: %r', id(t1.A.flag))
    print(t1.A.flag)

我的输出

我用评论将其分开

DEBUG:__main__:t1 has started
DEBUG:__main__:t2 is being imported
DEBUG:t2:t2 is being imported
DEBUG:t2:t2 is now importing t1

正如您所看到的,第一次(正如其他人提到的那样)t1实际上名称为__main__。它会尝试导入t2,但会立即t2尝试导入t1

DEBUG:t1:t1 has started
DEBUG:t1:t2 is being imported

您可以看到没有t2日志记录语句运行。那是因为Python缓存导入的模块,因此它首先在缓存中查找t2并说:“啊哈!我已经导入了这个人,我只需要将它返回。然后你就去了!”

DEBUG:t1:A is being "compiled"
DEBUG:t1:ID A: 140377934341704
DEBUG:t1:ID A.flag 4312040768
DEBUG:t1:What is __name__? 't1'

所以,你会注意到它现在已经通过导入t1。并t2

DEBUG:t2:t2 is done being imported

继续执行__main__ t1

DEBUG:__main__:A is being "compiled"
DEBUG:__main__:ID A: 140377934344360
DEBUG:__main__:ID A.flag 4312040768

请注意,此idA的{​​{1}}不同!

A.flag

再次注意,这些DEBUG:__main__:What is __name__? '__main__' DEBUG:__main__:__name__ was "__main__" DEBUG:__main__:Calling t2.f() DEBUG:t2:f is being called DEBUG:t2:ID t1: 4317998840 DEBUG:t2:ID t1.A: 140377934341704 DEBUG:t2:ID t1.A.flag: 4312040736 匹配id,而不是t1.A

__main__.A

答案 3 :(得分:-1)

是的,我可以看到这有点令人困惑,但它基本上是命名空间的问题,以及__main__命名空间不被视为导入模块列表的一部分的区别。这允许作为执行点(因此占用__main__命名空间)的文件也作为模块导入。另一方面,如果同一个模块被多次导入,解释器只会让所有不同的导入指向同一个内存位置

因此,在您上面显示的代码中,您实际上有两个不同版本的A:您拥有__main__.A并且您拥有__main__.t2.t1.A。第二个问题是因为__main__正在导入t2,而t1正在导入t2.f()作为模块。

当您运行__main__.t2.t1.A.flag = True时,您正在设置print(A.flag)然后打印它。随后,当您致电__main__.A.flag时,您将打印pdb.set_trace()中未永久更改的值。

我希望这至少有点意义。

我的一位朋友总是说计算机科学是一门实验科学。 让我们调用调试器。

我在执行中添加t1.py#!/usr/bin/python import t2 class A: flag = False if __name__ == "__main__": import pdb; pdb.set_trace() t2.f() print(A.flag) 现在看起来像这样:

$ python t1.py
> /Users/martin/git/temp/t1.py(9)<module>()
-> t2.f()
(Pdb) A
<class __main__.A at 0x10ec9ba78>
(Pdb) t2.t1.A
<class t1.A at 0x10ec9ba10>
(Pdb) 

这就是我们得到的:

A

请注意,#define my_malloc_macro(size, ptr) do { \ ptr = malloc(size); \ if(!ptr) { \ printf("malloc failed\n"); \ return -1; \ } \ } while(0) 有相关的单独内存位置。