[Py 2/3迁移]:如何在py3中验证类方法类型?

2024-09-29 06:22:16 发布

您现在位置:Python中文网/ 问答频道 /正文

在py2/3迁移过程中,我们的测试工具发现了以下问题:

import types;

class Test(object):
  def foo(self):
    class InnerClass(object):
      def innerFn():
        pass

    innerInst = InnerClass()

    instanceRef = isinstance(innerInst.innerFn, types.MethodType)
    classRef = isinstance(InnerClass.innerFn, types.MethodType)

    print(type(innerInst.innerFn)) # py3: <class 'method'>
    print(type(InnerClass.innerFn) # py3: <class 'function'>
    # in py2: both are <type 'instancemethod'>

    assert(instanceRef) # succeeds in py2 and py3
    assert(classRef) # fails in py3 but succeeds in py2

在py3中,识别类和实例方法类型的推荐方法是什么?原始源代码具有导致问题的以下检查:


target = getTarget() # target can be either class method or instance method ref
if isinstance(target, types.MethodType):
  do_something

REPL的链接:


Tags: intargetobjectdeftypepy3methodclass
1条回答
网友
1楼 · 发布于 2024-09-29 06:22:16

InnerClass.innerFn从来都不是类方法。它是一个未绑定的方法对象。Python3中不再存在未绑定的方法对象InnerClass.innerFn现在解析为普通函数对象

根据执行此检查的原因,您可能根本不想将InnerClass.innerFn视为一种方法。如果您这样做,您可以通过检查函数的^{,获得与旧检查类似但不等价的内容:

def check(obj):
    parts = obj.__qualname__.split('.')
    return len(parts) > 1 and not parts[-2].startswith('<')

如果函数的__qualname__是在类或另一个函数作用域内定义的,则其中至少有一个.。如果它是在函数作用域中定义的,__qualname__的倒数第二个组件通常是<locals>,但它也可以是由列表理解、生成器表达式或其他类似上下文创建的函数作用域中的<listcomp><genexp>等其他一些东西。我很确定所有的函数作用域案例都是从<开始的,而类作用域案例从来没有这样做过

如果函数是在类之外定义的,然后设置为类属性,或者在其他情况下,__qualname__元数据与函数是否作为类属性访问不一致,并且我没有费心处理非函数输入类型,那么这就不等同于旧的检查

相关问题 更多 >