sku*_*zmo 2 python program-entry-point subclass isinstance
使用 Python 的 isinstance 方法时,定义两个类(两个单独的文件中的基类“ClassA”和子类“ClassB”)会产生意外结果。输出似乎受到运行时使用的模块名称(命名空间?)的影响(__main__)。此行为出现在 Python 3.8.5 和 3.10.4 上。
文件 ClassA.py 包含:
class ClassA:
def __init__(self, id):
self.id = id
def __str__(self) -> str:
class_name = type(self).__name__
return f"{class_name} WITH id: {self.id}"
def main():
from ClassB import ClassB
id = 42
for i, instance in enumerate([ClassA(id), ClassB(id)]):
label = f"{type(instance).__name__}:"
print("#" * 50)
print(f"{label} type: {type(instance)}")
label = " " * len(label) # Convert label to appropriate number of spaces
is_a = isinstance(instance, ClassA)
is_b = isinstance(instance, ClassB)
print(f"{label} is_a/b: {is_a}/{is_b}")
print(f"{label} str: {instance}")
if __name__ == "__main__":
main()
Run Code Online (Sandbox Code Playgroud)
文件 ClassB.py 包含:
from ClassA import ClassA
class ClassB(ClassA):
def __init__(self, id):
super().__init__(id)
self.id *= -1
Run Code Online (Sandbox Code Playgroud)
文件 main.py 包含:
if __name__ == "__main__":
from ClassA import main
main()
Run Code Online (Sandbox Code Playgroud)
运行 ClassA.py 的输出给出:
01: ##################################################
02: ClassA: type: <class '__main__.ClassA'>
03: is_a/b: True/False
04: str: ClassA WITH id: 42
05: ##################################################
06: ClassB: type: <class 'ClassB.ClassB'>
07: is_a/b: False/True
08: str: ClassB WITH id: -42
Run Code Online (Sandbox Code Playgroud)
运行 main.py(调用 ClassA.main)的输出给出:
01: ##################################################
02: ClassA: type: <class 'ClassA.ClassA'>
03: is_a/b: True/False
04: str: ClassA WITH id: 42
05: ##################################################
06: ClassB: type: <class 'ClassB.ClassB'>
07: is_a/b: True/True
08: str: ClassB WITH id: -42
Run Code Online (Sandbox Code Playgroud)
请注意 ClassA 实例的类型如何(在第 02 行)从“__main__.ClassA”(从 ClassA.py 运行时)更改为“ClassA.ClassA”(从 main.py 运行时)。同样,ClassA 和 ClassB 的 isinstance 类型检查(第 07 行)从“False/True”(意外)更改为“True/True”(期望、预期)。
任何评论/建议/解释都会有帮助。谢谢。
您在这里遇到的问题是由于ClassA在主脚本中定义的,并且您有循环导入。实际上,您的脚本涉及三个模块,而不是两个:
__main__(defines __main__.ClassA),它导入...ClassB(定义ClassB.ClassB)导入...ClassA(定义ClassA.ClassA与 定义相同__main__.ClassA,但是一个唯一且独立的类)主脚本的完全独立的副本,但以不同的名称独立导入,因此__main__不会触发相关行为重要的是,ClassB.ClassB继承自ClassA.ClassA,但针对完全不相关的类main进行类型检查。__main__.ClassA
我之前已经讨论过为什么这不能按预期工作(并且在另一个上下文中再次),因此我将针对您的具体情况将此处的答案简化为:不要涉及__main__任何循环导入。它可以导入任何它喜欢的东西,但不应该从中导入任何其他东西。在这种情况下,您的重构足以解决问题(通过确保 class ,main.py仅有一个版本)。它确实有一个循环导入依赖项,这总是有点奇怪(我建议移动该函数以避免这种情况),但由于您推迟了其中一个导入,所以它足够安全。ClassAClassA.ClassAmainmain.py
| 归档时间: |
|
| 查看次数: |
115 次 |
| 最近记录: |