加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

如何找出一个函数是否已被`lambda`或`def`声明?

发布时间:2020-12-20 11:09:08 所属栏目:Python 来源:网络整理
导读:如果我声明两个函数a和b: def a(x): return x**2b = lambda x: x**2 我不能使用类型来区分它们,因为它们都是相同的类型. assert type(a) == type(b) 另外,types.LambdaType没有帮助: import types isinstance(a,types.LambdaType)True isinstance(b,types.
如果我声明两个函数a和b:

def a(x):
    return x**2

b = lambda x: x**2

我不能使用类型来区分它们,因为它们都是相同的类型.

assert type(a) == type(b)

另外,types.LambdaType没有帮助:

>>> import types
>>> isinstance(a,types.LambdaType)
True
>>> isinstance(b,types.LambdaType)
True

可以像__name__一样使用:

def is_lambda_function(function):
    return function.__name__ == "<lambda>"

>>> is_lambda_function(a)
False
>>> is_lambda_function(b)
True

但是,由于__name__可能已被修改,因此无法保证is_lambda_function返回正确的结果:

>>> a.__name__ = '<lambda>'
>>> is_lambda_function(a)
True

有没有一种方法可以产生比__name__属性更可靠的结果?

解决方法

AFAIK,你无法在Python 3中可靠地使用.

Python 2用于定义一堆函数类型.因此,方法,lambda和普通函数各有各自的类型.

Python 3只有一种类型是函数.确实使用def和lambda声明常规函数确实存在不同的副作用:def将名称设置为函数的名称(和限定名称),并且可以设置docstring,而lambda将名称(和限定名称)设置为< lambda>,并将docstring设置为None.但是这可以改变……

如果函数是从常规Python源加载的(而不是在交互式环境中键入),则inspect模块允许访问原始Python代码:

import inspect

def f(x):
    return x**2

g = lambda x: x**2

def is_lambda_func(f):
    """Tests whether f was declared as a lambda.

Returns: True for a lambda,False for a function or method declared with def
Raises:
    TypeError if f in not a function
    OSError('could not get source code') if f was not declared in a Python module
                                         but (for example) in an interactive session
"""
    if not inspect.isfunction(f):
        raise TypeError('not a function')
    src = inspect.getsource(f)
    return not src.startswith('def') and not src.startswith('@') # provision for decorated funcs

g.__name__ = 'g'
g.__qualname__ = 'g'

print(f,is_lambda_func(f))
print(g,is_lambda_func(g))

这将打印:

<function f at 0x00000253957B7840> False
<function g at 0x00000253957B78C8> True

顺便说一下,如果问题是函数的序列化,声明为lambda的函数可以成功地被pickle,只要你给它一个唯一的限定名:

>>> g = lambda x: 3*x
>>> g.__qualname__ = "g"
>>> pickle.dumps(g)
b'x80x03c__main__ngnqx00.'

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读