从两条不同路径导入的类不相等?

时间:2016-12-06 14:53:40

标签: python python-import python-module

似乎使用两个不同的PYTHONPATH导入的实体相同的对象。

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

我创建了源树:

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来捕获它,那么这是完全混乱。

使用python 3.4.3进行测试

2 个答案:

答案 0 :(得分:3)

在Python中,class语句是一个可执行语句,因此每次执行它时都会创建一个新类。

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

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

这通常会在人们拥有文件a.py时对其进行攻击,这些文件作为脚本运行,然后在另一个模块中尝试导入a。该脚本作为__main__加载,因此具有与导入的模块不同的类和不同的全局变量。

道德是,在你引用模块的方式上始终保持一致。

答案 1 :(得分: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相同