我正在尝试从一个文件导入一个类,并检查该类是否在定义该文件的文件中作为该类的实例。问题是,这不是从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())
还有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
函数上返回isinstance()
?要改写它,如何使Foo
类在file1.py
和file2.py
中是“相同的”?如果重要,我使用Python 3.6.7。
答案 0 :(得分:1)
最简单的答案是从不使用 if __name__=="__main__"
。可以肯定,这是一个聪明的把戏,但是它并没有实现任何人认为的那样。本来应该使文件成为模块和,但是(由于查找和运行模块和脚本的过程非常不同),实际上是让文件成为模块或脚本,单独。这个技巧包含了有关此缺点的提示:模块中的__name__
应该是其在sys.modules
中的关键,如果它是“ __main__”,那根本不是任何普通模块。 (实际上可以import __main__
并获取一个属性为脚本中全局变量的模块对象!)
在您的情况下,file1.py
被用作脚本一次,然后通过模块file2
作为模块被实际加载两次。每次加载都会创建一个不相关(如果相似)的类Foo
; 在何处使用哪个类别都无所谓,而只使用哪个类别。 (file1
甚至可以导入本身并获得“模块版本”。)请注意,这些类不必是“相同的”;同样的if
技巧可以用来为他们提供不同的成员或基类,甚至可以控制执行哪个class Foo
语句。
如果您要使用python -m
,出于安装原因,这是一个非常合理的要求,则最省事的使用方式是通过软件包中的__main__.py
通过import
使用。仍然可以 导入它,这可能没有任何好处,但是没有人(除了天真的代码以递归方式导入包中的每个模块)。