【问题标题】:python - how to reference Class declared inside a functionpython - 如何引用函数内声明的类
【发布时间】:2020-12-10 10:04:57
【问题描述】:

我正在使用来自第三方库的类。

def funcA(base):
    class ClassA(base):
        def __init__(self, obj):
        ....

我有一个 ClassA 的实例a

type(a)

# prints <class 'path.to.module.funcA.<locals>.ClassA'>

如何检查变量是否是 ClassA 的实例? 我不确定如何引用 ClassA,因为它在一个函数之下....

import module
isinstance(a, module.funcA.ClassA?) <--- how to reference ClassA?

【问题讨论】:

  • 为什么需要做这样的测试?定义接口,采用鸭子类型。顺便说一句,如果该类是函数的本地类,则要么是糟糕的 OO 设计,要么您正在尝试调整
  • 不可能进行这样的检查,至少不能以任何通常的方式进行。没有办法直接引用类,实际上每次调用函数时都会创建一个全新的类对象。所有类都具有相同的名称,并且行为相同 - 但一个类版本的实例无法通过 isinstance 与任何其他版本的检查。你能做的最好的事情就是type(a).__name__ == "ClassA"
  • 你可以返回一个 ClassA 对象,但这是我能从我的发现中得到的最好的结果。不知何故相关:stackoverflow.com/questions/2024566/…
  • Python 没有类声明(或任何声明,真的)。类定义语句本质上是调用type 构造函数的语法糖,将生成的类对象分配给ClassA 局部变量。像任何局部变量一样,它不能在函数外部访问
  • 现在,如果你有一个类ClassA = type(a),你可以恢复类,现在你可以在那个范围内引用ClassA

标签: python python-3.x


【解决方案1】:

如果您无法更改 funcA 本身,因为它不在您自己的代码中,那么测试实例的一种巧妙方法是给它一个超类并测试超类。将funcA 替换为一个包装版本,它使用一个扩展base 和您自己的ClassABase 的类调用原始funcA

import functools

class ClassABase:
    pass

def funcAwrapper(f):
    @functools.wraps(f)
    def wrapper(base):
        class WrappedBase(base, ClassABase):
            pass
        return f(WrappedBase)
    return wrapper

funcA = funcAwrapper(funcA)

现在funcA 创建的所有ClassA 实例也将是您自己的ClassABase 实例,因此您可以测试isinstance(obj, ClassABase)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-05
    • 1970-01-01
    • 1970-01-01
    • 2013-10-23
    • 1970-01-01
    • 2015-03-23
    • 2012-10-30
    相关资源
    最近更新 更多