Search code examples
pythonextension-modules

_functools module


How does this import work, what file does it use?

import _functools

In python 2.5:

import _functools
print _functools.__file__

Gives:

Traceback (most recent call last):
  File "D:\zjm_code\mysite\zjmbooks\a.py", line 5, in <module>
    print _functools.__file__
AttributeError: 'module' object has no attribute '__file__'

How can I get the meaning of partial (from _functools import partial) if I can't read C code?


Solution

  • C-coded modules can be built-in (lacking __file__) or live in a .so or .pyd dynamic library (which their __file__ will indicate) -- that's an implementation detail that you should not care about.

    If you want to understand how a Python-callable, C-coded function works by studying code, learning to read C is generally best (far less hard than actually productively coding in C;-). However, often you'll find (suggestive, non-authoritative) "sample Python implementations" of C-coded functionality, and you can study those.

    A particularly fruitful repository of Python-coded equivalents to Python standard library functionality that's normally coded in C is the pypy project (which does Python implementations coded in Python) -- its sources are browseable here and of course you can download and peruse them on your machine.

    In particular, this is pypy's _functools.py implementation:

    """ Supplies the internal functions for functools.py in the standard library """
    
    class partial:
        """
        partial(func, *args, **keywords) - new function with partial application
        of the given arguments and keywords.
        """
        __slots__ = ['func', 'args', 'keywords']
    
        def __init__(self, func, *args, **keywords):
            if not callable(func):
                raise TypeError("the first argument must be callable")
            self.func = func
            self.args = args
            self.keywords = keywords
    
        def __call__(self, *fargs, **fkeywords):
            newkeywords = self.keywords.copy()
            newkeywords.update(fkeywords)
            return self.func(*(self.args + fargs), **newkeywords)
    

    Pretty trivial to read and understand, I hope!