从其他文件导入类时,Python 3 isinstance意外行为? [英] Python 3 isinstance unexpected behavior when importing class from different file?

查看:42
本文介绍了从其他文件导入类时,Python 3 isinstance意外行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to import a class from one file and check if is an instance of that class in the file that it was defined in. The problem is that instead of returning True from theisinstance() function, it returns False, because it was initialised in a different file.

这是一个可行的示例.

假设您有 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())

file2.py :

from file1 import Foo

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

它输出 False ,类型为< class'file1.Foo'> .我发现有趣的是,如果在定义了 file1 Foo 类中初始化,它将返回 True .

It prints False and the type is <class 'file1.Foo'>. What I found interesting is that if you initialize the Foo class in file1 where is was defined, it returns 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))

我发现,如果在定义文件的外部初始化一个类,则与在定义文件的内部初始化该类相比,它是一个不同的类".

I found that if you initiate a class outside of the file where it is defined, it is a different "class" than if you initiate the class inside the file where it was defined.

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


所以我的问题是:


So my question is:

如何解决此问题,以便即使在 file1 外部启动的类也可以在 isinstance()函数上返回 True ?要改写它,我如何才能使 Foo 类与 file1.py file2.py 中的相同"?如果重要的话,我使用的是Python 3.6.7.

How can I work around this so that even the classes initiated outside of the file1 can return True on the isinstance() function? To reword it, how can I make it so that the Foo class is the "same" in file1.py and file2.py? I Python 3.6.7 if it matters.

推荐答案

最简单的答案是从不使用 如果__name __ =="__ main __" .可以肯定,这是一个聪明的把戏,但是它并没有像任何人认为的那样起作用.本来应该使文件成为模块,但是(由于查找和运行模块和脚本的过程非常不同),实际上是让文件成为模块脚本,单独.这个技巧包含了有关此缺点的提示:模块中的 __ name __ 应该是 sys.modules 中的键,如果它是"__main__",则不是任何正常的模块完全没有.(实际上,可以 import __main __ 并获取其属性为脚本中全局变量的模块对象!)

The starkly simple answer is to never use if __name__=="__main__". It’s a clever trick, to be sure, but it doesn’t do what anyone thinks it does. It’s supposed to make a file be a module and a script, but (because the processes for finding and running modules and scripts are so different) what it actually does is let the file be a module or a script, separately. The trick contains a hint as to this shortcoming: __name__ in a module is supposed to be its key in sys.modules, and if it’s "__main__" that’s not any normal module at all. (It is in fact possible to import __main__ and get a module object whose attributes are the global variables in the script!)

在您的情况下,其中 file1.py 被用作脚本一次,然后通过模块 file2 作为模块被实际加载两次.每次加载都会创建一个不相关(如果相似)的类 Foo 在何处使用并不重要,每个类都使用.( file1 甚至可以导入本身并获得模块版本".)请注意,这些类不必是相同的".同样的 if 技巧可以用来为它们提供不同的成员或基类,甚至可以控制执行哪个 class Foo 语句.

In your case, where file1.py gets used once as a script and then, via the module file2, as a module, it is actually loaded twice. Each load creates an unrelated (if similar) class Foo; it doesn’t matter where each class is used, just which one. (file1 could even import itself and would get the "module version".) Note that the classes need not be "the same"; the very same if trick could be used to give them different members or base classes, or could even control which class Foo statement is executed.

如果您要使用 python -m ,出于安装原因,这是一个非常合理的要求,则最省井的使用方式是通过 __ main__包中的.py ,否则可以通过 import 使用.仍然可以 导入它,这可能没有任何好处,但是没有人(除了天真的代码以递归方式导入包中的每个模块).

If you want to use python -m, which is a perfectly reasonable desire for installation reasons, the least broken way of using it is via a __main__.py in a package otherwise used via import. It’s still possible to import it, which probably doesn’t do anything good, but no one (aside from naïve code that recursively imports every module in a package) will do so.

这篇关于从其他文件导入类时,Python 3 isinstance意外行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆