簡體   English   中英

從不同的文件導入類時,Python 3是否存在意外行為?

[英]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.pyfile2.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM