检测python中的空函数定义。

时间:2022-10-30 00:13:49

I need to detect whether a function is an empty definition or not. It can be like:

我需要检测一个函数是否为空定义。它可以像:

def foo():
    pass

or like:

或者像:

def foo(i, *arg, **kwargs):
    pass

or like:

或者像:

foo = lambda x: None

What is the most elegant way to detect them using the 'inspect' module? Is there a better way than this:

使用“inspect”模块检测它们最优雅的方式是什么?还有比这更好的办法吗?

def isEmptyFunction(func):
    e = lambda: None
    return func.__code__.co_code == e.__code__.co_code

3 个解决方案

#1


4  

The method you propose does not quite work because empty functions that have docstrings have a slightly different bytecode.

您建议的方法不太有效,因为具有docstring的空函数有稍微不同的字节码。

The value of func.__code__.co_code for an empty function with no docstring is 'd\x00\x00S', while the value of it for a function with a docstring is 'd\x01\x00S'.

func.__code__的价值。没有docstring的空函数的co_code是“d\x00\x00S”,而带有docstring的函数的co_code是“d\x01\ x01\x00S”。

For my purposes, it works just to add the additional case to test for:

就我的目的而言,它只对添加额外的案例进行测试:

def isEmptyFunction(func):
    def empty_func():
        pass

    def empty_func_with_doc():
        """Empty function with docstring."""
        pass

    return func.__code__.co_code == empty_func.__code__.co_code or \
        func.__code__.co_code == empty_func_with_doc.__code__.co_code

#2


1  

The way you're using works. A perhaps more "elegant" solution would be to have a list of functions, and in all your empty (or all your non-empty) functions you would add it to the list, and then check whether the function is in the list or not.

你使用的方法是有效的。一个可能更“优雅”的解决方案是拥有一个函数列表,在所有的空函数(或所有非空函数)中,您将把它添加到列表中,然后检查函数是否在列表中。

#3


-2  

Why would you do that? It looks like bad design. I would bet you wouldn't make anything faster.

你为什么要这么做?看起来设计很糟糕。我敢打赌你不会做得更快。

python -m timeit -s'def a(): pass' -s'def b(): pass' 'if a.__code__.co_code == b.__code__.co_code: pass'
1000000 loops, best of 3: 0.293 usec per loop

python -m timeit -s 'def a(): pass' -s 'def b(): pass' 'a()'
10000000 loops, best of 3: 0.0941 usec per loop

It seems like it is magnitude slower to compare than to just do call, because there were 10 times more loops in the latter timeit. The equals operator actually is surely calls a.code.co_code.eq. So you are just making things slower.

看起来它的大小比直接调用要慢,因为在后面的时间里有10倍的循环。等号操作符实际上是调用a.code.co_code.eq。所以你只是让事情变慢了。

#1


4  

The method you propose does not quite work because empty functions that have docstrings have a slightly different bytecode.

您建议的方法不太有效,因为具有docstring的空函数有稍微不同的字节码。

The value of func.__code__.co_code for an empty function with no docstring is 'd\x00\x00S', while the value of it for a function with a docstring is 'd\x01\x00S'.

func.__code__的价值。没有docstring的空函数的co_code是“d\x00\x00S”,而带有docstring的函数的co_code是“d\x01\ x01\x00S”。

For my purposes, it works just to add the additional case to test for:

就我的目的而言,它只对添加额外的案例进行测试:

def isEmptyFunction(func):
    def empty_func():
        pass

    def empty_func_with_doc():
        """Empty function with docstring."""
        pass

    return func.__code__.co_code == empty_func.__code__.co_code or \
        func.__code__.co_code == empty_func_with_doc.__code__.co_code

#2


1  

The way you're using works. A perhaps more "elegant" solution would be to have a list of functions, and in all your empty (or all your non-empty) functions you would add it to the list, and then check whether the function is in the list or not.

你使用的方法是有效的。一个可能更“优雅”的解决方案是拥有一个函数列表,在所有的空函数(或所有非空函数)中,您将把它添加到列表中,然后检查函数是否在列表中。

#3


-2  

Why would you do that? It looks like bad design. I would bet you wouldn't make anything faster.

你为什么要这么做?看起来设计很糟糕。我敢打赌你不会做得更快。

python -m timeit -s'def a(): pass' -s'def b(): pass' 'if a.__code__.co_code == b.__code__.co_code: pass'
1000000 loops, best of 3: 0.293 usec per loop

python -m timeit -s 'def a(): pass' -s 'def b(): pass' 'a()'
10000000 loops, best of 3: 0.0941 usec per loop

It seems like it is magnitude slower to compare than to just do call, because there were 10 times more loops in the latter timeit. The equals operator actually is surely calls a.code.co_code.eq. So you are just making things slower.

看起来它的大小比直接调用要慢,因为在后面的时间里有10倍的循环。等号操作符实际上是调用a.code.co_code.eq。所以你只是让事情变慢了。