2016-12-06 38 views
3

看来,使用两个不同的进口实体PYTHONPATH s是而不是相同的对象。从两条不同路径导入的类是不相等的?

我在我的代码中遇到了一个小问题,我想用一个小测试用例来解释它。

我创建的源代码树:

a/ 
    __init__.py 
    b/ 
    __init__.py 
    example.py 

在example.py:

class Example: 
    pass 

,并从文件夹a的父母,我运行Python和这个测试:

>>> import sys 
>>> sys.path.append("/home/marco/temp/a") 
>>> 
>>> import a.b.example as example1 
>>> import b.example as example2 
>>> 
>>> example1.Example is example2.Example 
False 

所以问题是:为什么结果是False?即使通过两条不同路径导入,类也是一样的。如果这个类是一个自定义的异常,并且你试图用except来捕捉它,这是一个完全的混乱。

测试用蟒3.4.3

回答

2

在Python中,class语句是一个可执行文件声明,所以每次执行它时,都会创建一个新类。

当您导入模块时,Python将检查sys.modules以查看指定路径上的模块是否已存在。如果确实如此,那么您将只返回相同的模块,否则它将尝试加载模块并执行其包含的代码。

因此,到同一模块的两条不同路径将加载代码两次,这会执行两次语句class,并且您将获得两个定义的独立类。

当他们有一个文件a.py时,它们通常会碰到人,他们将其作为脚本运行,然后在另一个模块中尝试导入a。该脚本加载为__main__,因此具有与导入的模块不同的类和不同的全局变量。

道德是,在参考模块的过程中始终保持一致。

+0

'当你导入一个模块时,Python会检查sys.modules,看看在指定路径上的模块是否已经存在。问题是真正的模块路径确实是一样的,它的'PYTHONPATH'不同。由于我使用python3不允许输入''',我认为真正的路径可以而且应该被检查。 –

+1

不是文件路径,模块路径,即此处为'a.b.example'或'b.example'的模块的名称。两个不同的名称,两个不同的模块。 – Duncan

0

is的操作者使用,以检查是否两个名字都指向相同的对象(存储位置)。

example1.Example is example2.Example 

显然不是指向相同的位置,因为您导入了相同的对象两次。

但是,如果你不喜欢的东西:

a, b = example1.Example, example1.Example 

a is b # True 

相反,你应该使用==操作:

example1.Example == example2.Example 
True 

需要注意的是,如果你不执行__eq____hash__,默认行为与is

+0

你试过吗?即使两个类的定义相同,两个类的平等比较也会返回“False”。对于一个类来说=='通常和'is'是完全一样的(尽管我猜你可以用一个元类覆盖这个行为,但那是不寻常的)。 – Duncan

+0

@Duncan是的,如果你没有实现'__eq__'或'__hash__'默认行为与 – user312016

+0

@Duncan相同如果情况总是如此,因为所有东西都是python中的对象,所以'=='会起作用不求回报。 – user312016

相关问题