从不同文件导入类时,Python 3 是否会出现意外行为?

2023-12-27

我正在尝试从一个文件导入一个类,并检查定义它的文件中是否是该类的实例。问题是,而不是返回True来自isinstance()函数,它返回False,因为它是在不同的文件中初始化的。

这是一个工作示例。

说你有file1.py:

class Foo:
    def __init__(self, arg1):
        self.arg1 = arg1

def main(class_obj):
    # Prints false and is type <class 'file1.Foo'>
    print(type(class_obj))
    print(isinstance(class_obj, Foo))

if __name__ == '__main__':
    from file2 import get_class
    main(get_class())

And file2.py:

from file1 import Foo

def get_class():
    foo = Foo("argument")
    return foo

它打印False类型是<class 'file1.Foo'>。我发现有趣的是,如果你初始化Foo上课于file1在哪里定义了它,它返回True.

# Add to main() function in file1
# Returns true and is type <class '__main__.Foo'>
foo_local = Foo("argument")  # Class initiated in __main__ seems to work
print(type(foo_local))
print(isinstance(foo_local, Foo))

我发现,如果您在定义它的文件之外启动一个类,那么它是一个与在定义它的文件内部启动该类不同的“类”。

# Different Classes?
<class 'file1.Foo'>  # From other file (`file2.py`)
<class '__main__.Foo'>  # From same file (`file1.py`)

所以我的问题是:

我该如何解决这个问题,以便即使是在外部启动的课程file1可以返回True on the isinstance()功能?要改写它,我怎样才能做到这一点Foo类是“相同”的file1.py and file2.py?如果重要的话我选择Python 3.6.7。


极其简单的答案是从不使用 if __name__=="__main__"。诚然,这是一个聪明的技巧,但它并没有达到任何人认为的效果。它应该使一个文件成为一个模块and一个脚本,但是(因为查找和运行模块和脚本的过程非常不同)它实际上所做的是让文件成为一个模块or一个脚本,分别地。该技巧包含有关此缺点的提示:__name__在模块中应该是它的关键sys.modules,如果它是“__main__”,那根本就不是任何正常的模块。 (实际上可以import __main__并获取一个模块对象,其属性是脚本中的全局变量!)

在你的情况下,哪里file1.py作为脚本使用一次,然后通过模块file2,作为一个模块,它实际上是被加载的twice。每个负载都会创建一个不相关(如果相似)的类Foo;没关系where每个类都被使用,只是使用哪个类。 (file1甚至可以进口itself并会得到“模块版本”。)请注意,类不需要“相同”;完全相同if技巧可以用来给他们不同的成员或基类,或者甚至可以控制哪些class Foo语句被执行。

如果你想使用python -m,出于安装原因,这是一个完全合理的愿望,最少破损使用它的方法是通过__main__.py在一个包中,否则通过import. It’s still可以导入它,这可能没有任何好处,但没有人(除了递归导入包中每个模块的简单代码)会这样做。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从不同文件导入类时,Python 3 是否会出现意外行为? 的相关文章

随机推荐