How can I make a deepcopy of a function in Python?

后端 未结 6 948
我在风中等你
我在风中等你 2020-12-01 14:13

I would like to make a deepcopy of a function in Python. The copy module is not helpful, according to the documentation, which says:

This mo

6条回答
  •  一生所求
    2020-12-01 14:41

    My goal is to have two functions with the same implementation but with different docstrings.

    Most users will do this, say the original function is in old_module.py:

    def implementation(arg1, arg2): 
        """this is a killer function"""
    

    and in new_module.py

    from old_module import implementation as _implementation
    
    def implementation(arg1, arg2):
        """a different docstring"""
        return _implementation(arg1, arg2)
    

    This is the most straightforward way to reuse functionality. It is easy to read and understand the intent.

    Nevertheless, perhaps you have a good reason for your main question:

    How can I make a deepcopy of a function in Python?

    To keep this compatible with Python 2 and 3, I recommend using the function's special __dunder__ attributes. For example:

    import types
    
    def copy_func(f, name=None):
        '''
        return a function with same code, globals, defaults, closure, and 
        name (or provide a new name)
        '''
        fn = types.FunctionType(f.__code__, f.__globals__, name or f.__name__,
            f.__defaults__, f.__closure__)
        # in case f was given attrs (note this dict is a shallow copy):
        fn.__dict__.update(f.__dict__) 
        return fn
    

    And here's an example usage:

    def main():
        from logging import getLogger as _getLogger # pyflakes:ignore, must copy
        getLogger = copy_func(_getLogger)
        getLogger.__doc__ += '\n    This function is from the Std Lib logging module.\n    '
        assert getLogger.__doc__ is not _getLogger.__doc__
        assert getLogger.__doc__ != _getLogger.__doc__
    

    A commenter says:

    This can’t work for built‑in functions

    Well I wouldn't do this for a built-in function. I have very little reason to do this for functions written in pure Python, and my suspicion is that if you are doing this, you're probably doing something very wrong (though I could be wrong here).

    If you want a function that does what a builtin function does, and reuses the implementation, like a copy would, then you should wrap the function with another function, e.g.:

    _sum = sum
    def sum(iterable, start=0):
        """sum function that works like the regular sum function, but noisy"""
        print('calling the sum function')
        return _sum(iterable, start)
        
    

提交回复
热议问题