【问题标题】:Class imported from two different paths is not equal?从两个不同路径导入的类不相等?
【发布时间】:2017-04-21 06:16:46
【问题描述】:

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

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

我创建了源代码树:

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 测试

【问题讨论】:

    标签: python python-import python-module


    【解决方案1】:

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

    当你导入一个模块时,Python 会检查sys.modules 以查看指定路径中的模块是否已经存在。如果是,那么您将返回相同的模块,如果不是,它将尝试加载模块并执行它包含的代码。

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

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

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

    【讨论】:

    • When you import a module Python will check sys.modules to see whether a module at the specified path already exists 问题是真正的模块路径确实是一样的,不同的是PYTHONPATH。由于我使用的 python3 不允许 .. 导入,我认为可以而且应该检查真实路径。
    • 不是文件路径,是模块路径,即模块名称,这里是a.b.exampleb.example。两个不同的名字,两个不同的模块。
    • 关于“不是模块路径”:可能(在 python3.6 中)str(class1) == str(class2),但是 class1 != class2。 str(classX) 似乎显示了模块路径,它看起来像这样:''
    【解决方案2】:

    is 运算符用于检查两个名称是否指向同一个对象(内存位置)。

    example1.Example is example2.Example
    

    显然没有指向相同的位置,因为您要导入相同的对象两次。

    但是,如果你做了类似的事情:

    a, b = example1.Example, example1.Example
    
    a is b # True
    

    您应该使用== 运算符:

    example1.Example == example2.Example
    True
    

    注意,如果不实现__eq____hash__,默认行为与is相同

    【讨论】:

    • 你试过了吗?两个类的相等比较将返回False,即使它们的定义相同。对于一个类== 通常与is 完全相同(虽然我猜你可以用元类覆盖该行为,但这是不寻常的)。
    • @Duncan 是的,如果你不实现__eq____hash__ 默认行为和is一样
    • @Duncan 如果总是这样,因为在 python 中一切都是对象,== 将一事无成。
    • 不,您是否在一个类上定义了__eq__,然后您已经为该类的实例重新定义了比较。很多班级都是这样做的。要重新定义类本身的比较,您必须在元类上定义 __eq__。这很不寻常(任何元类的使用都是相当不寻常的)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 2020-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-06
    相关资源
    最近更新 更多