python - 如何检查 Python 对象中是否存在方法
问题描述
上下文和意图:我想使用m_o
type的对象My_object
作为与另一个名为s_o
type的对象交互的方式Stubborn_object
。为了便于理解,它们的行为应该类似于 ifMy_object
继承自Stubborn_object
,就像调用 in 中不存在My_object
的属性应该调用 in 中的属性一样Stubborn_object
。
然而,棘手的是,如果我可以简单地继承My_object
自Stubborn_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_a
,action_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
异常?
非常感谢。
解决方案
似乎覆盖__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)
推荐阅读
- vue.js - 是否可以在历史模式下将具有动态路由的 vue.js 应用程序托管为 S3/Cloudfront 上的静态网站?
- angular - Angular (8/9) i18n 期望看到带有特定数字 id 的翻译出错
- matlab - Matlab 现在运行速度超级慢
- java - java.security.AccessControlException:访问被拒绝(“java.net.URLPermission”“https://example.com”“*:*”)
- vba - 如何查找客户发送的所有未答复的电子邮件?
- npm - 错误:pngquant 构建失败,请确保已安装 libpng-dev
- android - Android WorkManager - 返回值
- javascript - 如何从 React-Native 上的对象中选择图像源
- java - 输入时清除RecyclerView android
- python-3.x - Rdkit:MaeMolSupplier NameError