判断函数是否在Python模块中可用

47 投票
3 回答
31870 浏览
提问于 2025-04-15 11:10

我正在写一些使用Python套接字的代码,里面用到了socket.fromfd()这个函数。

不过,这个方法并不是在所有平台上都能用,所以我正在写一些备用代码,以防这个方法不存在。

在运行时,怎么判断一个方法是否被定义了呢?下面的代码够用吗,还是有更好的写法呢?

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

我有点担心dir()的文档似乎不太推荐使用这个方法。那getattr()会不会是更好的选择呢,比如:

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

大家有什么想法吗?

编辑 正如Paolo指出的,这个问题几乎和一个关于判断属性存在性的问题重复了。不过,由于使用的术语不同(lk说的是"对象有一个属性",而我说的是"模块有一个函数"),所以保留这个问题可能对搜索有帮助,除非这两个问题能合并在一起。

3 个回答

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
26

或者直接使用一个try..except代码块:

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

hasattr() 是最好的选择。就用这个吧。:)

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

编辑:其实,根据文档,所有 hasattr 做的就是调用 getattr 并捕获异常。所以如果你想省去中间环节,可以参考 marcog 的回答。

编辑:我刚刚意识到这个问题其实是一个 重复问题。那里的一个回答讨论了你可以选择的两种方式:捕获异常(“事后求情比事前请求更简单”)或者事先检查(“三思而后行”)。老实说,我更倾向于后者,但似乎 Python 社区更倾向于前者的想法。

撰写回答