确定Python模块中是否存在一个函数。

47

我正在编写一些使用socket.fromfd()函数的Python socket代码。

但是,该方法并非在所有平台上都可用,所以我正在编写一些备用代码以防该方法未定义。

在运行时确定方法是否已定义的最佳方法是什么?以下代码是否足够,还是有更好的惯用语言?

if 'fromfd' in dir(socket):
    sock = socket.fromfd(...)
else:
    sock = socket.socket(...)

我有点担心Python的dir()文档中似乎不太鼓励使用它。那么,如下使用getattr()是否是更好的选择:

if getattr(socket, 'fromfd', None) is not None:
    sock = socket.fromfd(...)
else:
    sock = socket.socket(...)

有什么想法?

编辑 正如Paolo所指出的,这个问题几乎与关于确定属性存在的问题重复了。然而,由于使用的术语不同(lk的“对象具有属性”与我的“模块具有函数”),如果不能将两者合并,则保留此问题以便搜索可能会有帮助。

3个回答

63

hasattr() 是最佳选择,建议使用它。 :)

if hasattr(socket, 'fromfd'):
    pass
else:
    pass

编辑: 实际上,根据文档,hasattr只是调用getattr并捕获异常而已。因此,如果您想切掉中间人,应该选择marcog的答案。

编辑: 我也意识到这个问题实际上是一个重复的问题。那里的一个答案讨论了两种选项的优点:捕获异常("先做再说")或事先检查("先看再跳")。老实说,我更倾向于后者,但似乎Python社区更倾向于前者的看法。


2
不应使用 hasattr,因为它会吞噬异常,包括 KeyboardInterrupt。(c) http://doc.bazaar.canonical.com/developers/code-style.html#hasattr-and-getattr,因此使用 getattr 是一个好选择。 - anatoly techtonik

26

或者简单地使用try..except块:

try:
  sock = socket.fromfd(...)
except AttributeError:
  sock = socket.socket(...)

我相信如果它不存在,会抛出AttributeError而不是NameError。 - Paolo Bergantino
1
这是最具Python风格的解决方案。 - Fábio Santos
1
如果函数存在但引发了自己的 AttributeError,那就不太好。 - Alex Peters

3

使用hasattr(obj, 'attributename')可能更好。hasattr将尝试访问属性,如果不存在,则返回false。

在Python中可以有动态方法,即在尝试访问它们时创建的方法。它们不会出现在dir(...)中。但是hasattr会检查它们。

>>> class C(object):
...   def __init__(self):
...     pass
...   def mymethod1(self):
...     print "In #1"
...   def __getattr__(self, name):
...     if name == 'mymethod2':
...       def func():
...         print "In my super meta #2"
...       return func
...     else:
...       raise AttributeError
... 
>>> c = C()
>>> 'mymethod1' in dir(c)
True
>>> hasattr(c, 'mymethod1')
True
>>> c.mymethod1()
In #1
>>> 'mymethod2' in dir(c)
False
>>> hasattr(c, 'mymethod2')
True
>>> c.mymethod2()
In my super meta #2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接