[Python-ideas] Access to function objects

Nick Coghlan ncoghlan at gmail.com
Sun Aug 7 14:46:59 CEST 2011


On Sun, Aug 7, 2011 at 10:10 PM, Guido van Rossum <guido at python.org> wrote:
> On the rest of that rejected PEP:
>
> - I'm not actually sure how easy it is to implement the setting of
> __function__ when the frame is created. IIRC the frame creation is
> rather far removed from the function object, as there are various
> cases where there is no function object (class bodies, module-level
> code) and in other cases the function is called via a bound method.
> Someone should write a working patch to figure out if this is a
> problem in practice.

With a PEP 3135 closure style solution, the cell reference would be
filled in at function definition time, so that part shouldn't be an
issue.

> - The primary use case for __function__ to me seems to access function
> attributes, but I'm not sure what's wrong with referencing these via
> the function name. Maybe it's when there's a method involved, since
> then you'd have to write <classname>.<methodname>.<attrname>.

That does raise an interesting question, though: in a function wrapped
via decorators, should __function__ refer to the innermost function or
the outermost one?

Reference by name lazily accesses the outermost one, but doesn't care
how the decorators are applied (i.e. as part of the def statement or
via post decoration). A __class__ style cell reference to the result
of the 'def' statement would behave differently in the post decoration
case.

While referencing the innermost function would likely be wrong in any
case involving function attributes, having the function in a valid
state during decoration will likely mandate filling in the cell
reference before invoking any decorators. Perhaps the best solution
would be to syntactically reference the innermost function, but
provide a clean way in functools to shift the cell reference to a
different function (with functools.wraps doing that automatically).

This does seem like an area ripe for subtle decoration related bugs
though, especially by contrast with lazy name based lookup.

> - It seems that the "current class" question has already been solved
> for super(). If more is needed I'd be okay with extending the
> machinery used by super() so that you can access the magic "current
> class" variable explicitly too.

No need to extend it, that info is already available for explicit reference:

>>> class C:
...   def f(self):
...     print(__class__)
...
>>> C().f()
<class '__main__.C'>

(see postscript for more details)

> - For "current module" I've encountered a number of use cases, mostly
> having to do with wanting to define new names dynamically. Somehow I
> have found:
>
>  globals()[x] = y  # Note that x is a variable, not a literal
>
> cumbersome; I'd rather write:
>
>  setattr(__this_module__, x, y)
>
> There are IIRC also some use cases where an API expects a module
> object (or at least something whose attributes it can set and/or get)
> and passing the current module is clumsy:
>
>  foo(sys.modules[__name__])

While this may sound a little hypocritical coming from the author of
PEPs 366 and 395, I'm wary of adding new implicit module globals for
problems with relatively simple and robust alternatives. In this case,
it's fairly easy to get access to the current module using the idiom
Guido quoted:

    import sys
    _this = sys.modules[__name__]

(or using dict-style access on globals())

Cheers,
Nick.

P.S. More details on the magic __class__ closure reference:

>>> dis.show_code(C.f)
Name:              f
Filename:          <stdin>
Argument count:    1
Kw-only arguments: 0
Number of locals:  1
Stack size:        2
Flags:             OPTIMIZED, NEWLOCALS
Constants:
   0: None
Names:
   0: print
Variable names:
   0: self
Free variables:
   0: __class__
>>> C.f.__closure__[0].cell_contents
<class '__main__.C'>


-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia



More information about the Python-ideas mailing list