首页 > 解决方案 > 如何检查 Python 对象中是否存在方法

问题描述

上下文和意图:我想使用m_otype的对象My_object作为与另一个名为s_otype的对象交互的方式Stubborn_object。为了便于理解,它们的行为应该类似于 ifMy_object继承自Stubborn_object,就像调用 in 中不存在My_object的属性应该调用 in 中的属性一样Stubborn_object

然而,棘手的是,如果我可以简单地继承My_objectStubborn_object. 看来我不能继承它,而且由于很多原因,我也不能修改Stubborn_object类的代码,所以我不得不照原样使用它。请注意,尝试继承不是这里的问题。我知道我的实际问题存在其他解决方案,但出于多种原因,我真的希望答案保持在主题上。我怀疑其他用户可能会遇到与我不同的问题,但仍然无法继承一个类。此外,不能继承一个类并不是让人们阅读这个问题的唯一原因。事实上,这是一个相当普遍的 Python 面向对象问题。我还相信我的问题的解决方案在其他应用程序中可能很有用,例如在找不到属性时在对象本身内进行自定义错误处理,或者在线程管理中在调用属性时立即锁定实例。

除了继承的问题,假设我不能使用更高级别的条件来处理这些情况,所以一切都必须 My_object实例或其父级内部完成。这意味着我无法hasattr(m_o, attribute_name)确定是否应该调用getattr(m_o, attribute_name)getattr(s_o, attribute_name)这也意味着任何try/except块和其他先决条件都必须在My_object或其父类中。这个问题的重点不是在从My_object实例外部调用属性时检测异常。一个try/catch块通常必须在My_object课堂之外,我之前说过这是不允许的。

为了清楚起见并提供完整的可验证示例,这里是Stubborn_object该类的示例代码。我知道我说过我不能继承,Stubborn_object下面的代码包含一个可继承的类。提供一个不可继承对象的例子只会带来混乱,而且无论如何它对这个问题并没有真正的帮助,所以这里是一个可继承对象的简单例子。这样做的目的是提出一个易于理解的问题,因此请考虑您不能从中继承:

class Stubborn_object:
    def do_something(self):
        print("do_something")

    def action_to_override():
        print("action_to_override")

    def action_a(self):
        print("action_a")

    def action_b(self):
        print("action_b")

目标: 简单地说,我希望我的班级My_object自己检测到一个缺少的属性已被调用并运行一些指令而不是抛出一个AttributeError.

当前尝试:现在,我Stubborn_object像这样手动将方法调用重定向到实例(它是成功的,但由于使用了硬编码,因此不可靠也不可扩展):

class My_object():
    def __init__(self, s_o):
        self.stubborn_object = s_o

    def action_to_override(self):
        # Do stuff. This method "overrides" the Stubborn_object.action_to_override method.
        print("Here is stuff getting done instead of action_to_override")

    def action_a(self):
        return self.stubborn_object.action_a()

    def action_b(self):
        return self.stubborn_object.action_b()

s_o = Stubborn_object()
m_o = My_object(s_o)

m_o.action_to_override() # Executes Stubborn_object.do_something()
m_o.action_a()           # Executes Stubborn_object.action_a()
m_o.action_b()           # Executes Stubborn_object.action_b()

Stubborn_object与提供的代码示例一起执行此代码应打印:

Here is stuff getting done instead of action_to_override
action_a
action_b

正如您从方法中看到的那样action_aaction_b我必须从方法中手动调用Stubborn_object方法My_object来模仿Stubborn_object. 这是低效的,缺乏健壮性,AttributeError如果我们尝试执行My_object代码中未包含的操作,则会引发异常。

如果我想自动向Stubborn_object实例发送方法和属性调用,而不用重写它的所有方法和属性My_object怎么办?我相信这可以通过检测是否My_object调用了缺少的实例属性来实现。

期望(或某种):我对任何允许My_object类或其父级确定属性是否缺失的解决方案持开放态度,这一切都在其自身内部。所以我相信我已经准备好听到非常新颖的想法,所以继续吧。

就我而言,我相信使用部分代码的方法是可行的,但它仍然缺少“捕获任何被调用的属性”部分:

class My_object():
    def __init__(self, s_o):
        # __init__ stays as it was.
        self.stubborn_object = s_o

    def action_to_override(self):
        # This method also stays as it was.
        # Do stuff. This method "overrides" the stubborn_object.action_to_override method.
        print("Here is stuff getting done instead of action_to_override")

    def run_me_when_method_is_not_found(self, method_name, **kwargs):
        print("Method " + method_name + " not in 'My_object' class.")
        return getattr(self.stubborn_object, method_name)(**kwargs)

因此,使用前面的代码示例运行这些行

s_o = Stubborn_object()
m_o = My_object(s_o)

m_o.action_to_override() # Executes Stubborn_object.do_something()
m_o.action_a()           # Executes Stubborn_object.action_a()
m_o.action_b()           # Executes Stubborn_object.action_b()

将打印

Here is stuff getting done instead of action_to_override
Method action_a not in 'My_object' class.
action_a
Method action_b not in 'My_object' class.
action_b

必须为 getter 和 setter 制定一些类似的方法,但是,想法保持不变。问题是这段代码缺乏检测属性缺失的能力。

问题:run_me_when_method_is_not_found如果在 中找不到该方法,我该如何运行My_object?特别是,实例如何My_object检测到该方法在其类中不存在而不是抛出AttributeError异常?

非常感谢。

标签: pythonoop

解决方案


似乎覆盖__getattribute__将完全符合您的要求:self.stubborn_object如果在self. 将其放入My_object类定义中:

def __getattribute__(self, attr):
    try:
        return object.__getattribute__(self, attr)
    except AttributeError:
        return object.__getattribute__(self.stubborn_object, attr)

推荐阅读