如何检查Python中是不是存在方法?
Posted
技术标签:
【中文标题】如何检查Python中是不是存在方法?【英文标题】:How to check whether a method exists in Python?如何检查Python中是否存在方法? 【发布时间】:2011-11-26 16:32:01 【问题描述】:在函数__getattr__()
中,如果未找到引用的变量,则会出错。如何检查变量或方法是否作为对象的一部分存在?
import string
import logging
class Dynamo:
def __init__(self,x):
print "In Init def"
self.x=x
def __repr__(self):
print self.x
def __str__(self):
print self.x
def __int__(self):
print "In Init def"
def __getattr__(self, key):
print "In getattr"
if key == 'color':
return 'PapayaWhip'
else:
raise AttributeError
dyn = Dynamo('1')
print dyn.color
dyn.color = 'LemonChiffon'
print dyn.color
dyn.__int__()
dyn.mymethod() //How to check whether this exist or not
【问题讨论】:
【参考方案1】:检查类是否有这样的方法?
hasattr(Dynamo, key) and callable(getattr(Dynamo, key))
或
hasattr(Dynamo, 'mymethod') and callable(getattr(Dynamo, 'mymethod'))
您可以使用self.__class__
代替Dynamo
【讨论】:
None
是不可调用的,所以你可以只做callable(getattr(Dynamo, 'mymethod', None))
。我使用这个答案是因为我的 super().mymethod() 可能会抛出 AttributeError
@sbutler 有趣的是,它有效。根据 PyCharm,getattr 的签名是 def getattr(object, name, default=None):
我怀疑这是不准确的,因为如果是这样,我希望传递 None 作为第三个参数不会改变函数的行为。
@bszom:在 python shell 中,help(getattr)
说“当给出默认参数时,当属性不存在时返回它;没有它,在这种情况下会引发异常。 " -- (事实上,如果缺少属性,您可以检查 getattr 是否会引发异常)非常清楚,无论 PyCharm 是什么,它都是错误的。
@ShreevatsaR 感谢您确认我的怀疑。 PyCharm 是一个 IDE。
SIMPLER VERSION: 如果你想检查当前类 INSTANCE 是否有一个属性并且它是可调用的,只需这样做:if hasattr(self, "work") and callable(self.work)
。这将检查实例是否具有工作属性(可以是变量或函数),然后检查它是否可调用(意味着它是一个函数)。【参考方案2】:
请求宽恕比请求许可更容易。
不要检查方法是否存在。不要在“检查”上浪费一行代码
try:
dyn.mymethod() # How to check whether this exists or not
# Method exists and was used.
except AttributeError:
# Method does not exist; What now?
【讨论】:
但也许他真的不想调用它,只是为了检查是否有那个方法(就像我的情况一样)...... 请注意,如果dyn.mymethod()
自己引发AttributeError
,这将失败。
正如@DK 所说,这将捕获任何可能由正在检查的方法引发的 AttributeError ,这可能是不可取的(更不用说在这种情况下它会错误地推断出该方法的缺失) )。
原则上很好,而且 Python 确实有一种与其他语言不同的“作为控制流的异常”文化。但是,如果您使用的是 Sentry/Raven 或 New Relic 等异常记录工具,则必须单独过滤此类异常(如果可能)或产生噪音。我宁愿检查该方法是否存在而不是调用它。
这在很多层面上都是错误的。方法本身可以引发 AttributeError 并且这将被检测为方法不存在!它还破坏了调试器对中断异常的支持。我也确信如果事情处于循环状态,这可能会影响性能。最后但不是列出我可能不想执行方法,只需验证它是否存在。你应该考虑删除这个答案,或者至少把所有这些警告都写下来,这样天真的人就不会被误导。【参考方案3】:
dir()
之前的getattr()
函数怎么样?
>>> "mymethod" in dir(dyn)
True
【讨论】:
这里不检查是方法还是变量 使用 dir 不是很好 - 它不能确认名称是一个方法,例如【参考方案4】:我使用以下实用功能。它适用于 lambda、类方法以及实例方法。
实用方法
def has_method(o, name):
return callable(getattr(o, name, None))
示例用法
让我们定义测试类
class MyTest:
b = 'hello'
f = lambda x: x
@classmethod
def fs():
pass
def fi(self):
pass
现在你可以试试了,
>>> a = MyTest()
>>> has_method(a, 'b')
False
>>> has_method(a, 'f')
True
>>> has_method(a, 'fs')
True
>>> has_method(a, 'fi')
True
>>> has_method(a, 'not_exist')
False
【讨论】:
这个答案比其他答案更合适(至少在我看来),因为它不使用通用方法(使用try
语句)并且它会检查成员是否是实际函数。很棒的分享!【参考方案5】:
您可以尝试使用“检查”模块:
import inspect
def is_method(obj, name):
return hasattr(obj, name) and inspect.ismethod(getattr(obj, name))
is_method(dyn, 'mymethod')
【讨论】:
【参考方案6】:在dyn.__dict__
中查找如何?
try:
method = dyn.__dict__['mymethod']
except KeyError:
print "mymethod not in dyn"
【讨论】:
按照惯例,带有下划线前缀的方法表示“私有”。 双下划线前缀加上双下划线后缀表示“这通常由 Python 解释器本身使用”,通常有一些方法可以从用户的程序中获得相同的效果,以用于最常见的用途情况(在这种情况下,它将对属性使用点表示法),但如果您的用例确实需要它,则使用它既不是禁止也不是错误的。 不禁止。错误是主观的:这取决于你想在多大程度上混淆遵守约定的程序员:除非你别无选择,否则不要使用它。【参考方案7】:可能是这样,假设所有方法都是可调用的
app = App(root) # some object call app
att = dir(app) #get attr of the object att #['doc', 'init', 'module', 'button', 'hi_there', 'say_hi']
for i in att:
if callable(getattr(app, i)):
print 'callable:', i
else:
print 'not callable:', i
【讨论】:
【参考方案8】:如果您的方法在一个类之外,并且您不想运行它并在它不存在时引发异常:
'mymethod' in globals()
【讨论】:
>>> def myadd(x,y): return x+y >>> 'myadd' in globals() True【参考方案9】:适合喜欢简单的人。
class ClassName:
def function_name(self):
return
class_name = ClassName()
print(dir(class_name))
# ['__init__', .... ,'function_name']
answer = 'function_name' in dir(class_name)
print("is'function_name' in class ? >> answer")
# is 'function_name' in class ? >> True
【讨论】:
【参考方案10】:我认为你应该看看inspect
包。它允许你“包装”一些东西。当您使用dir
方法时,它还会列出内置方法、继承方法和所有其他可能发生冲突的属性,例如:
class One(object):
def f_one(self):
return 'class one'
class Two(One):
def f_two(self):
return 'class two'
if __name__ == '__main__':
print dir(Two)
您从dir(Two)
获得的数组包含f_one
和f_two
以及许多内置的东西。使用inspect
,您可以这样做:
class One(object):
def f_one(self):
return 'class one'
class Two(One):
def f_two(self):
return 'class two'
if __name__ == '__main__':
import inspect
def testForFunc(func_name):
## Only list attributes that are methods
for name, _ in inspect.getmembers(Two, inspect.ismethod):
if name == func_name:
return True
return False
print testForFunc('f_two')
这个例子仍然列出了两个类中的两个方法,但是如果你想限制检查只在一个特定的类中起作用,它需要更多的工作,但这是绝对可能的。
【讨论】:
以上是关于如何检查Python中是不是存在方法?的主要内容,如果未能解决你的问题,请参考以下文章