如何检查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_onef_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中是不是存在方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查python中是不是存在文件? [复制]

Python 语法:如何检查返回值中是不是存在“x”?

如何检查 Python 中是不是同时存在两个变量? [复制]

如何检查Go中是不是存在文件?

如何检查字典python中是不是存在多个值

如何在 Python 中检查电子邮件是不是存在?