【问题标题】:How to determine if the variable is a function in Python? [duplicate]如何确定变量是否是Python中的函数? [复制]
【发布时间】:2010-03-17 01:22:44
【问题描述】:

既然函数在 Python 中是值,那么如何判断变量是否是函数呢?

例如:

boda = len   # boda is the length function now
if ?is_var_function(boda)?:
  print "Boda is a function!"
else:
  print "Boda is not a function!"

如果x 是一个可调用函数,这里假设的?is_var_function(x)? 应该返回true,否则返回false。

【问题讨论】:

  • 您是否希望它也为类返回 true,因为它们是可调用的?
  • 是什么阻止你阅读代码?
  • 是的,但有时您实际上需要使用反射——例如,MVC 框架可能需要加载一个类并检查其成员。但这肯定是您的日常代码应该避免的。
  • 感谢您的精彩回答!我实际上是想确定这个东西是否可以调用,而不仅仅是一个函数。对不起,我还是 Python 新手。

标签: python function


【解决方案1】:

其他答案中提到的callable 内置函数无法回答您提出的问题,因为除了函数之外,它还返回True,用于定义__call__ 方法的方法、类、类的实例。如果您的问题的标题和文本是错误的,并且您不在乎某些东西是否实际上是一个函数,但只要它是 callable,那么请使用该内置函数。但是对您提出的问题的最佳答案是:导入Python标准库的inspect方法,并使用inspect.isfunction。 (还有其他较低抽象的方法,但最好使用 inspect 模块的功能进行自省,而不是较低级别的方法:inspect 有助于保持代码简洁、清晰,强大且面向未来)。

【讨论】:

  • SO 接受的另一个错误答案。我应该列出一个清单。正如我在其他几个答案中提到的那样,内置函数和类方法失败了。您还需要检查inspect.isbuiltin() 和inspect.ismmethod(),有这么多特殊情况并没有什么“面向未来”的。
  • 为什么不 type(a) == types.functionType ?
【解决方案2】:

您可以使用inspect.isfunction(object)。见:docs.python.org

也就是说,您应该避免在日常代码中使用这种技术。有时您实际上需要使用反射——例如,MVC 框架可能需要加载一个类并检查其成员。但通常你应该返回/传递/处理具有相同“接口”的对象。例如,不要返回可能是整数或函数的对象 - 始终返回相同“类型”的对象,以便您的代码保持一致。

【讨论】:

  • 它提供了关于如何在没有上下文的情况下做一些通常很糟糕的事情的建议,以及如何构建好的、健壮的、惯用的 Python 代码。
  • 正好也回答了这个问题,这就是本站的目的。
  • 帮助人们、提供好的建议以及为更好的项目做出贡献都是回答问题的最佳目标。
  • 我希望这个网站的目的是盲目地回答问题,即使这个人很可能问错了问题。无论如何回答这个问题都很好(他可能真的想要他所说的他想要的,而且提出一个问题并让每个人都拒绝回答它是令人抓狂的——这确实发生了),但是一个好的答案应该跟上一个解释为什么这可能不是他想要的。
  • 抛开网站理念不谈,这个答案是不正确的。 inspect.isfunction(sys.exit) 和 inspect.isfunction((1.0).hex) 都是 false(内置方法和绑定方法)。
【解决方案3】:

python中有一个callable函数。

 if callable(boda):

【讨论】:

  • 函数/方法是每个实现__call__ 方法的对象。 callable() 是测试这种调用方法是否存在的好方法。
  • 但是 callable 也会为一个类返回 true,不是吗?目前尚不清楚 OP 是否也希望这样做。
  • 我怀疑 OP 不知道区别,实际上确实想要任何可调用的东西。如果您不知道如何检查某个东西是否是 Python 中的函数,那么很有可能您实际上并不想这样做。
【解决方案4】:

使用callable(boda) 来确定@​​987654322@ 是否可调用。

Callable 在这里意味着一个函数、方法甚至一个类。但是由于您只想区分变量和函数,因此它应该可以很好地工作。

您的代码将如下所示:

boda = len   # boda is the length function now
if callable(boda):
  print "Boda is a function!"
else:
  print "Boda is not a function!"

【讨论】:

    【解决方案5】:
    >>> import types
    >>> def f(): pass
    ...
    >>> x = 0
    >>> type(f) == types.FunctionType
    True
    >>> type(x) == types.FunctionType
    False
    

    这将检查它是否是一个函数。 callable() 将检查它是否可调用(也就是说,它有一个 __call__ 方法),因此它会在类以及函数或方法上返回 true。

    【讨论】:

    • isinstance 通常首选用于类型检查。在检查单例时,is 通常比 == 更受欢迎。需要一个函数而不是其他与函数完全一样的东西是一个糟糕的策略。
    • type(sys.exit) == types.FunctionTypetype((1.0).hex) == types.FunctionType 都是假的。 (isinstance 仍然失败;我不知道为什么 BuiltinFunctionType 和 MethodType 不是 FunctionType 的子类。)
    【解决方案6】:

    这不是一个 100% 完美的解决方案,但您可能想查看“可调用”内置函数:

    http://docs.python.org/library/functions.html

    【讨论】:

    • 完美的解决方案当然是什么都没有。
    【解决方案7】:

    对于property,它应该返回什么,您可以像访问值属性一样访问它,但实际上调用的是函数?您看似简单的问题实际上在 Python 中打开了一大堆蠕虫。这意味着像 callableisfunction 这样的东西很适合你的教育和内省,但可能不是你在与其他代码交互时想要依赖的东西。

    切线:请参阅Turtles All The Way Down 演示文稿,了解有关如何组合 Python 的更多信息。

    【讨论】:

    • 属性是一个奇怪的例子。属性的行为与函数不太相似,更重要的是,在正常情况下,您不会访问实际的属性对象,而是访问它为您获取的对象。
    【解决方案8】:

    如何在 Python 程序中使用不同对象的哲学称为鸭子类型——如果它看起来像鸭子,叫起来像鸭子,走路像鸭子,那就是鸭子。对象不是按照它们的类型而是按照它们能够做什么来分组的,这甚至扩展到了函数。在编写 Python 程序时,您应该始终知道所有对象可以做什么,并且无需检查即可使用它们。

    例如,我可以定义一个函数

    def add_three(a, b c):
        return a + b + c
    

    并意味着它与三个浮点数一起使用。但是通过不检查这个,我有一个更有用的函数——例如,我可以将它与 ints、decimal.Decimals 或 fractions.Fractions 一起使用。

    这同样适用于拥有一个功能。如果我知道我有一个函数并想调用它,我应该调用它。也许我拥有的是一个函数,也许我有一个不同的可调用对象(如绑定方法或定义__call__ 的任意类的实例),它可能同样好。通过不检查任何内容,我使我的代码能够处理我什至可能没有事先想到的各种情况。

    在可调用对象的情况下,我可以非常可靠地确定我是否有一个,但为了我的代码的简单性,我不应该这样做。如果有人传入了不可调用的东西,那么无论如何调用它都会出错。如果我正在编写的代码接受一个可能是可调用或不可调用的参数并且我根据它做不同的事情,听起来我应该通过定义两个函数来完成这两个不同的事情来改进我的 API。

    如果您确实有办法处理调用者传入的不是类似函数的东西(这不仅仅是疯狂 API 的结果),那么正确的解决方案是捕获 @ 987654323@ 当您尝试调用无法调用的东西时引发。一般来说,最好尝试做某事并在失败时恢复,而不是提前检查。 (回想一下陈词滥调,“请求宽恕比请求许可更容易。”)提前检查可能会导致基于细微逻辑错误的意外问题,并可能导致竞争条件。

    您认为为什么需要进行类型检查?

    【讨论】:

      猜你喜欢
      • 2011-04-17
      • 1970-01-01
      • 2010-09-13
      • 2022-01-25
      • 1970-01-01
      • 2014-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多