[Python-ideas] Allow function __globals__ to be arbitrary mapping not just dict

Terry Reedy tjreedy at udel.edu
Tue Mar 20 03:37:54 CET 2012

On 3/19/2012 7:51 PM, Steven D'Aprano wrote:
> Terry Reedy wrote:
>> On 3/18/2012 8:27 AM, Steven D'Aprano wrote:
>>> Currently, if you try to construct a function from parts, the mapping
>>> that becomes func.__globals__ must be an actual dict:
> [...]
>> The API of internal classes is intentionally not documented in the
>> types module doc. I take this to mean that the api, if not the
>> existence, of such classes, is implementation specific. Hence any such
>> call is a 'cpython' rather than generic python call.
> Are you sure that they are *intentionally* not documented, or merely
> haven't been due to lack of time and interest?

100% absolutely sure, no. 90% fairly sure, yes. Less that half of the 
internal types even *are* Python-level callables with Python-object 
APIs: FunctionType, CodeType, MethodType, ModuleType. The rest are not.

I think there once may have been a discussion of how much to expose 
them. While the last two are trivial, the help for CodeType says "Not 
for the faint of heart."  I suspect that some of these accessible APIs 
are new since 1.3, or may have changed. It is hard to know since they 
are not documented ;-).

> The types themselves are documented as public, they aren't given _single
> underscore private names,

The module says, "Typical use is for isinstance() or issubclass() checks."

Exposing the internal types was done to do once and do correctly things 
that people did (and sometimes still do) in their code, such as

isinstance(f, type(lambda: None)).

The module has similar code to get the types.

def _f(): pass
FunctionType = type(_f)
LambdaType = type(lambda: None)         # Same as FunctionType
CodeType = type(_f.__code__)

So there is not way for the objects themselves to not be public. The 
names bound to them in types are not their .__name__ attributes. It is 
certainly intentional that they are not bound to their names in builtins.

Getting traceback and frame types is trickier to get right:

     raise TypeError
except TypeError:
     tb = sys.exc_info()[2]
     TracebackType = type(tb)
     FrameType = type(tb.tb_frame)
     tb = None; del tb

> and FunctionType has a minimal but useful doc
> string with nothing about it being implementation specific.

Marking *anything* other than ref-counting and gc behavior as 
implementation specific in the docs is fairly recent. The same goes for 
cpython-only tests in the test suite. Some of this splitting has been 
prompted by questions from Iron-py and pypy developers.

Terry Jan Reedy

More information about the Python-ideas mailing list