added PEP 3130, Access to Current Module/Class/Function, by Jim J. Jewett

This commit is contained in:
David Goodger 2007-05-01 19:35:45 +00:00
parent 7ba16b49e0
commit 7ef3df6097
2 changed files with 216 additions and 8 deletions

View File

@ -78,7 +78,7 @@ Index by Category
Accepted PEPs (accepted; may not be implemented yet) Accepted PEPs (accepted; may not be implemented yet)
SA 358 The "bytes" Object Schemenauer, GvR SA 358 The "bytes" Object Schemenauer, GvR
SA 3106 Revamping dict.keys(), .values() and .items() GvR SA 3106 Revamping dict.keys(), .values() & .items() GvR
SA 3109 Raising Exceptions in Python 3000 Winter SA 3109 Raising Exceptions in Python 3000 Winter
SA 3110 Catching Exceptions in Python 3000 Winter SA 3110 Catching Exceptions in Python 3000 Winter
SA 3111 Simple input built-in in Python 3000 Roberge SA 3111 Simple input built-in in Python 3000 Roberge
@ -128,6 +128,7 @@ Index by Category
S 3127 Integer Literal Support and Syntax Maupin S 3127 Integer Literal Support and Syntax Maupin
S 3128 BList: A Faster List-like Type Stutzbach S 3128 BList: A Faster List-like Type Stutzbach
S 3129 Class Decorators Winter S 3129 Class Decorators Winter
S 3130 Access to Current Module/Class/Function Jewett
S 3141 A Type Hierarchy for Numbers Yasskin S 3141 A Type Hierarchy for Numbers Yasskin
Finished PEPs (done, implemented in Subversion) Finished PEPs (done, implemented in Subversion)
@ -193,7 +194,7 @@ Index by Category
SF 3104 Access to Names in Outer Scopes Yee SF 3104 Access to Names in Outer Scopes Yee
SF 3105 Make print a function Brandl SF 3105 Make print a function Brandl
SF 3107 Function Annotations Winter, Lownds SF 3107 Function Annotations Winter, Lownds
SF 3114 Renaming iterator.next() to iterator.__next__() Yee SF 3114 Renaming iterator.next() to .__next__() Yee
Empty PEPs (or containing only an abstract) Empty PEPs (or containing only an abstract)
@ -234,7 +235,7 @@ Index by Category
SW 274 Dict Comprehensions Warsaw SW 274 Dict Comprehensions Warsaw
SR 275 Switching on Multiple Values Lemburg SR 275 Switching on Multiple Values Lemburg
SR 276 Simple Iterator for ints Althoff SR 276 Simple Iterator for ints Althoff
SR 281 Loop Counter Iteration with range and xrange Hetland SR 281 Loop Counter Iteration with range & xrange Hetland
SR 284 Integer for-loops Eppstein, Ewing SR 284 Integer for-loops Eppstein, Ewing
SW 288 Generators Attributes and Exceptions Hettinger SW 288 Generators Attributes and Exceptions Hettinger
SR 294 Type Names in the types Module Tirosh SR 294 Type Names in the types Module Tirosh
@ -254,7 +255,7 @@ Index by Category
SW 321 Date/Time Parsing and Formatting Kuchling SW 321 Date/Time Parsing and Formatting Kuchling
SR 325 Resource-Release Support for Generators Pedroni SR 325 Resource-Release Support for Generators Pedroni
SR 326 A Case for Top and Bottom Values Carlson, Reedy SR 326 A Case for Top and Bottom Values Carlson, Reedy
SR 329 Treating Builtins as Constants in the Standard Library Hettinger SR 329 Treating Builtins as Constants in the StdLib Hettinger
SR 330 Python Bytecode Verification Pelletier SR 330 Python Bytecode Verification Pelletier
SR 332 Byte vectors and String/Unicode Unification Montanaro SR 332 Byte vectors and String/Unicode Unification Montanaro
SW 334 Simple Coroutines via SuspendIteration Evans SW 334 Simple Coroutines via SuspendIteration Evans
@ -377,7 +378,7 @@ Numerical Index
SF 278 Universal Newline Support Jansen SF 278 Universal Newline Support Jansen
SF 279 The enumerate() built-in function Hettinger SF 279 The enumerate() built-in function Hettinger
S 280 Optimizing access to globals GvR S 280 Optimizing access to globals GvR
SR 281 Loop Counter Iteration with range and xrange Hetland SR 281 Loop Counter Iteration with range & xrange Hetland
SF 282 A Logging System Sajip, Mick SF 282 A Logging System Sajip, Mick
IF 283 Python 2.3 Release Schedule GvR IF 283 Python 2.3 Release Schedule GvR
SR 284 Integer for-loops Eppstein, Ewing SR 284 Integer for-loops Eppstein, Ewing
@ -424,7 +425,7 @@ Numerical Index
SR 326 A Case for Top and Bottom Values Carlson, Reedy SR 326 A Case for Top and Bottom Values Carlson, Reedy
SF 327 Decimal Data Type Batista SF 327 Decimal Data Type Batista
SF 328 Imports: Multi-Line and Absolute/Relative Aahz SF 328 Imports: Multi-Line and Absolute/Relative Aahz
SR 329 Treating Builtins as Constants in the Standard Library Hettinger SR 329 Treating Builtins as Constants in the StdLib Hettinger
SR 330 Python Bytecode Verification Pelletier SR 330 Python Bytecode Verification Pelletier
S 331 Locale-Independent Float/String Conversions Reis S 331 Locale-Independent Float/String Conversions Reis
SR 332 Byte vectors and String/Unicode Unification Montanaro SR 332 Byte vectors and String/Unicode Unification Montanaro
@ -474,7 +475,7 @@ Numerical Index
SR 3103 A Switch/Case Statement GvR SR 3103 A Switch/Case Statement GvR
SF 3104 Access to Names in Outer Scopes Yee SF 3104 Access to Names in Outer Scopes Yee
SF 3105 Make print a function Brandl SF 3105 Make print a function Brandl
SA 3106 Revamping dict.keys(), .values() and .items() GvR SA 3106 Revamping dict.keys(), .values() & .items() GvR
SF 3107 Function Annotations Winter, Lownds SF 3107 Function Annotations Winter, Lownds
S 3108 Standard Library Reorganization Cannon S 3108 Standard Library Reorganization Cannon
SA 3109 Raising Exceptions in Python 3000 Winter SA 3109 Raising Exceptions in Python 3000 Winter
@ -482,7 +483,7 @@ Numerical Index
SA 3111 Simple input built-in in Python 3000 Roberge SA 3111 Simple input built-in in Python 3000 Roberge
SA 3112 Bytes literals in Python 3000 Orendorff SA 3112 Bytes literals in Python 3000 Orendorff
SA 3113 Removal of Tuple Parameter Unpacking Cannon SA 3113 Removal of Tuple Parameter Unpacking Cannon
SF 3114 Renaming iterator.next() to iterator.__next__() Yee SF 3114 Renaming iterator.next() to .__next__() Yee
SA 3115 Metaclasses in Python 3000 Talin SA 3115 Metaclasses in Python 3000 Talin
S 3116 New I/O Stutzbach, Verdone, GvR S 3116 New I/O Stutzbach, Verdone, GvR
S 3117 Postfix Type Declarations Brandl S 3117 Postfix Type Declarations Brandl
@ -498,6 +499,7 @@ Numerical Index
S 3127 Integer Literal Support and Syntax Maupin S 3127 Integer Literal Support and Syntax Maupin
S 3128 BList: A Faster List-like Type Stutzbach S 3128 BList: A Faster List-like Type Stutzbach
S 3129 Class Decorators Winter S 3129 Class Decorators Winter
S 3130 Access to Current Module/Class/Function Jewett
S 3141 A Type Hierarchy for Numbers Yasskin S 3141 A Type Hierarchy for Numbers Yasskin

206
pep-3130.txt Normal file
View File

@ -0,0 +1,206 @@
PEP: 3130
Title: Access to Current Module/Class/Function
Version: $Revision$
Last-Modified: $Date$
Author: Jim J. Jewett <jimjjewett@gmail.com>
Status: Draft
Type: Standards Track
Content-Type: text/plain
Created: 22-Apr-2007
Python-Version: 3.0
Post-History: 22-Apr-2007
Abstract
It is common to need a reference to the current module, class,
or function, but there is currently no entirely correct way to
do this. This PEP proposes adding the keywords __module__,
__class__, and __function__.
Rationale for __module__
Many modules export various functions, classes, and other objects,
but will perform additional activities (such as running unit
tests) when run as a script. The current idiom is to test whether
the module's name has been set to magic value.
if __name__ == "__main__": ...
More complicated introspection requires a module to (attempt to)
import itself. If importing the expected name actually produces
a different module, there is no good workaround.
# __import__ lets you use a variable, but... it gets more
# complicated if the module is in a package.
__import__(__name__)
# So just go to sys modules... and hope that the module wasn't
# hidden/removed (perhaps for security), that __name__ wasn't
# changed, and definitely hope that no other module with the
# same name is now available.
class X(object):
pass
import sys
mod = sys.modules[__name__]
mod = sys.modules[X.__class__.__module__]
Proposal: Add a __module__ keyword which refers to the module
currently being defined (executed). (But see open issues.)
# XXX sys.main is still changing as draft progresses. May
# really need sys.modules[sys.main]
if __module__ is sys.main: # assumes PEP (3122), Cannon
...
Rationale for __class__
Class methods are passed the current instance; from this they can
determine self.__class__ (or cls, for class methods).
Unfortunately, this reference is to the object's actual class,
which may be a subclass of the defining class. The current
workaround is to repeat the name of the class, and assume that the
name will not be rebound.
class C(B):
def meth(self):
super(C, self).meth() # Hope C is never rebound.
class D(C):
def meth(self):
# ?!? issubclass(D,C), so it "works":
super(C, self).meth()
Proposal: Add a __class__ keyword which refers to the class
currently being defined (executed). (But see open issues.)
class C(B):
def meth(self):
super(__class__, self).meth()
Note that super calls may be further simplified by the "New Super"
PEP (Spealman). The __class__ (or __this_class__) attribute came
up in attempts to simplify the explanation and/or implementation
of that PEP, but was separated out as an independent decision.
Note that __class__ (or __this_class__) is not quite the same as
the __thisclass__ property on bound super objects. The existing
super.__thisclass__ property refers to the class from which the
Method Resolution Order search begins. In the above class D, it
would refer to (the current reference of name) C.
Rationale for __function__
Functions (including methods) often want access to themselves,
usually for a private storage location or true recursion. While
there are several workarounds, all have their drawbacks.
def counter(_total=[0]):
# _total shouldn't really appear in the
# signature at all; the list wrapping and
# [0] unwrapping obscure the code
_total[0] += 1
return _total[0]
@annotate(total=0)
def counter():
# Assume name counter is never rebound:
counter.total += 1
return counter.total
# class exists only to provide storage:
class _wrap(object):
__total = 0
def f(self):
self.__total += 1
return self.__total
# set module attribute to a bound method:
accum = _wrap().f
# This function calls "factorial", which should be itself --
# but the same programming styles that use heavy recursion
# often have a greater willingness to rebind function names.
def factorial(n):
return (n * factorial(n-1) if n else 1)
Proposal: Add a __function__ keyword which refers to the function
(or method) currently being defined (executed). (But see open
issues.)
@annotate(total=0)
def counter():
# Always refers to this function obj:
__function__.total += 1
return __function__.total
def factorial(n):
return (n * __function__(n-1) if n else 1)
Backwards Compatibility
While a user could be using these names already, double-underscore
names ( __anything__ ) are explicitly reserved to the interpreter.
It is therefore acceptable to introduce special meaning to these
names within a single feature release.
Implementation
Ideally, these names would be keywords treated specially by the
bytecode compiler.
Guido has suggested [1] using a cell variable filled in by the
metaclass.
Michele Simionato has provided a prototype using bytecode hacks
[2]. This does not require any new bytecode operators; it just
modifies the which specific sequence of existing operators gets
run.
Open Issues
- Are __module__, __class__, and __function__ the right names? In
particular, should the names include the word "this", either as
__this_module__, __this_class__, and __this_function__, (format
discussed on the python-3000 and python-ideas lists) or as
__thismodule__, __thisclass__, and __thisfunction__ (inspired
by, but conflicting with, current usage of super.__thisclass__).
- Are all three keywords needed, or should this enhancement be
limited to a subset of the objects? Should methods be treated
separately from other functions?
References
[1] Fixing super anyone? Guido van Rossum
http://mail.python.org/pipermail/python-3000/2007-April/006671.html
[2] Descriptor/Decorator challenge, Michele Simionato
http://groups.google.com/group/comp.lang.python/browse_frm/thread/a6010c7494871bb1/62a2da68961caeb6?lnk=gst&q=simionato+challenge&rnum=1&hl=en#62a2da68961caeb6
Copyright
This document has been placed in the public domain.
Local Variables:
mode: indented-text
indent-tabs-mode: nil
sentence-end-double-space: t
fill-column: 70
coding: utf-8
End: