[英]Python 3 isinstance unexpected behavior when importing class from different file?
我試圖從一個文件導入一個類,並檢查它是否是在其定義的文件中的該類的實例。問題是,而不是從isinstance()
函數返回True
,它返回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'>
。 我發現有趣的是,如果在file1
中初始化Foo
類,其中定義了is,則返回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
之外啟動的類可以在isinstance()
函數上返回True
? 要重新編寫它,我怎樣才能使Foo
類在file1.py
和file2.py
“相同”? 我是Python 3.6.7如果重要的話。
簡單的答案是永遠不要使用 if __name__=="__main__"
。 當然,這是一個聰明的伎倆,但它沒有做任何人認為它做的事情。 它應該做一個文件是一個模塊和一個腳本,而是(因為查找和運行模塊和腳本是如此不同的過程),它實際上做的是讓該文件是一個模塊或腳本, 分別 。 這個技巧包含了一個關於這個缺點的提示:模塊中的__name__
應該是它在sys.modules
關鍵,如果它是“__main__”則根本不是任何正常的模塊。 (實際上可以import __main__
並獲取一個模塊對象,其屬性是腳本中的全局變量!)
在您的情況下, file1.py
作為腳本使用一次,然后通過模塊file2
作為模塊,實際上加載了兩次 。 每個加載創建一個不相關的(如果相似)類Foo
; 每個類的使用位置無關緊要,只需使用哪一個。 ( file1
甚至可以導入自己並獲得“模塊版本”。)請注意,類不必“相同”; if
可以使用技巧為它們提供不同的成員或基類,或者甚至可以控制執行哪個class Foo
語句。
如果你想使用python -m
,這是一個非常合理的安裝理由,那么使用它的最簡單的方法是通過一個包中的__main__.py
,否則通過import
。 它仍然可以導入它,這可能沒有任何好處,但沒有人(除了遞歸導入包中的每個模塊的天真代碼)將這樣做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.