@property 方法上的 `inspect.getmembers` 引发异常的意外行为

问题描述 投票:0回答:1

我觉得我在 Python 中遇到了一种相当奇怪的行为。自己尝试一下:

import inspect

class SomeClass:
    def __init__(self):
        inspect.getmembers(self, predicate=inspect.ismethod)

    def this_is_okay(self):
        raise Exception('an error that may be thrown')

    @property
    def this_is_not_okay(self):
        raise Exception('an error that may be thrown')

    @property
    def but_this_is_okay(self):
        if True:
            raise Exception('an error that may be thrown')

如果存在用

@property
修饰的方法,则检查类的方法将导致错误,但前提是它在第一个缩进级别引发错误。

怎么会这样?我该如何解决这个问题?

附注我这样检查的原因是我试图按照类中定义的顺序获取类方法(实际可调用对象)的数组。

python class properties decorator abstract-syntax-tree
1个回答
0
投票

但是您实际上并没有在类上调用

inspect.getmembers
,因为
self
指的是类的实例。错误会发生,因为它将尝试使用
getattr
getter(您可以从
Traceback
推断出),并且考虑到
SomeClass().this_is_not_okay
将有效地引发异常,这将破坏
inspect.getmembers
。这实际上是一个已知问题,自 2018 年以来一直处于开放状态。此外,您的断言“但仅当它在第一个缩进级别引发错误时”是不正确的,因为
inspect.getmembers
只是在早些时候因异常而中止
this_is_not_okay
(尽管将条件更改为
if False
会使其起作用,因为它将停止
raise
语句的执行)。

现在,您描述了您的既定目标是获得类中定义事物的顺序,那么,您必须将其传递给类。示例:

import inspect

class SomeClass:
    def this_is_okay(self):
        raise Exception('an error that may be thrown')

    @property
    def this_is_not_okay(self):
        raise Exception('an error that may be thrown')

    @property
    def but_this_is_okay(self):
        if False:
            raise Exception('an error that may be thrown')

some_ins = SomeClass()
print(inspect.getmembers(type(some_ins), predicate=inspect.isfunction))

上面应该产生类似的结果:

[('this_is_okay', <function SomeClass.this_is_okay at 0x7f166ae1a980>)]

如果使用Python 3.11或更高版本,可以使用

inspect.getmembers_static
来代替:

print(inspect.getmembers_static(some_ins, predicate=inspect.isfunction))

这实际上起到了同样的作用。

请注意,我将谓词更改为

inspect.isfunction
,因为类定义通常没有方法,但这些函数通常会成为类实例中的函数,因此区别应该很小。

如果必须使用

inspect.isfunction
谓词,则可能必须获取类实例的每个成员,然后应用所需的过滤。

© www.soinside.com 2019 - 2024. All rights reserved.