Daniel Kornhauser writes:
> Hi after not understandig several things I decided I needed to understand
> the way python works in order to persue my documentation effort . And I
> mean REALLY works:
> How it initializes, how does it's stack works, etc....
>
> For example in C I have read several documents and books of how C works:
> You have a memory arrangement where you find diferent segments:
> text, initialized data, uninitalized data, heap, stack, stack frames and
> these components interact in other to make a program works, blah, blah,
> blah ....
> Sorry if this is a offtopic and dum question (I studied electronics not
> computer science ) but I've just lost 45 mins searching for
> such a doc of "how does python work" in the python site and I've remained
> empty handed...
>
> I would understand if there isn't such a doc and that I would have to take
> a plunge in python source code but a nice document would be very helpfull.
It's all done with mirrors, magic, and dictionaries.
Just use dir() and XX.__dict__ to understand the magic. The following
examples should help to illustrate how a definition of a class stores
the class members and class methods in a dictionary and that instances
of a class are stored in dictionaries.
Python 1.5.2 (#1, Sep 17 1999, 20:15:36) [GCC egcs-2.91.66 19990314/Linux (egcs- on
linux-i386
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>> a = 3
>>> def f(p=1, p2="string"):
... print p2
...
>>> class C:
... a = 1
... def __init__(self, b, c):
... self.b_is = b
... self.c_is = c
...
>>> c = C(1,"a string")
>>> dir()
['C', '__builtins__', '__doc__', '__name__', 'a', 'c', 'f', 'readline', 'rlcompleter']
So where did these global names come from?
>>> a
3
The name a is the global variable with the value 3
>>> f
<function f at 80c8f90>
This is the function that was declared.
The readline and rlcompleter methods are inserted into the global
namespace by my ~/.pythonrc initialization file. This file just has
two lines:
import rlcompleter, readline
readline.parse_and_bind('tab: complete')
The ~/.pythonrc file is imported whenever python is run in interactive
mode and the readline.parse_and_bind() sets up 'tab' to call a
name completion function.
>>> __builtins__.__dict__.keys()
['OverflowError', 'AttributeError', 'NotImplementedError', 'range', 'filter',
'KeyboardInterrupt', 'TypeError', 'AssertionError', 'apply', '_', '__debug__', 'ord',
'__name__', 'eval', 'ZeroDivisionError', 'callable', 'len', 'max', 'buffer', 'hash',
'None', 'map', 'ValueError', 'slice', 'exit', 'abs', 'getattr', 'reduce', 'complex',
'execfile', 'FloatingPointError', 'min', 'OSError', 'RuntimeError', 'locals', 'id',
'quit', 'EnvironmentError', 'issubclass', 'intern', 'coerce', 'KeyError', 'EOFError',
'__import__', 'ImportError', 'oct', 'MemoryError', 'cmp', 'dir', 'round', 'str',
'reload', 'compile', 'list', 'raw_input', 'setattr', 'IndexError', 'delattr',
'hasattr', 'ArithmeticError', 'xrange', 'repr', 'tuple', 'StandardError',
'isinstance', 'Exception', 'SystemExit', '__doc__', 'type', 'input', 'IOError', 'chr',
'NameError', 'long', 'hex', 'SystemError', 'open', 'LookupError', 'Ellipsis',
'divmod', 'globals', 'int', 'float', 'SyntaxError', 'pow', 'vars']
The '__builtins__' dictionary contains all of the builtin function
definitions, such as dir(), map(), and str().
The '__doc__' is the doc string for the namespace. All modules
classes and functions contain a '__doc__'. If it isn't defined by
then Python returns None as the value.
>>> `__doc__`
'None'
Finally '__name__' is the name of the module. The toplevel module is
named '__main__'.
>>> __name__
'__main__'
>>>
The test for the value of '__name__' is an idiom often found at the
end of a module. This test:
if __name__ == '__main__':
do_test()
This will only pass if the module is called as the top level script to be
executed. If the module is imported then the test fails and the
function do_test() would not be called. The idiom provides an easy
mechanism for including test code directly in a module.
>>> locals()
{'__doc__': None, 'rlcompleter': <module 'rlcompleter' from
'/usr/lib/python1.5/rlcompleter.pyc'>, 'readline': <module 'readline' from
'/usr/lib/python1.5/lib-dynload/readline.so'>, '__name__': '__main__', '__builtins__':
<module '__builtin__' (built-in)>, 'f': <function f at 80c7b60>, 'c': <__main__.C
instance at 80c7a20>, 'C': <class __main__.C at 80c7258>, 'a': 3}
The locals() command uncovers the secret of Python. It's dictionaries
all the way down. The global namespace is a dictionary. Every module
is a dictionary. A package is created by nesting dictionaries.
>>> c
<__main__.C instance at 80d5eb0>
>>> dir(c)
['c_is', 'b_is']
>>> c.__dict__
{'b_is': 1, 'c_is': 'a string'}
The instance 'c' is a dictionary. The instance is the first parameter
passed into the methods defined in a class. This parameter is traditionally
called 'self', but this is not a requirement. Note that the class
variable 'a' does not appear in this dictionary. It was not assigned
to the 'self' dictionary. The value of 'a' requires looking in the class
dictionary.
>>> C
<class __main__.C at 80c7b60>
>>> dir(C)
['__doc__', '__init__', '__module__', 'a']
>>> C.__dict__
{'__init__': <function __init__ at 80c87f0>, '__doc__': None, '__module__':
'__main__', 'a': 1}
>>>
Just typing the name 'C' shows that this is a class definition. The
dir(C) call shows the names in the class, and the C.__dict__ exposes
the full class definition dictionary.
There are a few distinctions between Python code that is written in
Python and the code that is written in C, however Python tries to hide
these distinctions as much as possible. Lets look at a module written
in C, such as gdbm. For gdbm the dir() and __init__ trick still works.
>>>
>>> import gdbm
>>> dir(gdbm)
['__doc__', '__file__', '__name__', 'error', 'open']
>>> gdbm.__dict__
{'error': <class gdbm.error at 80d5268>, '__doc__': "This module provides an interface
to the GNU DBM (GDBM) library.\012\012This module is quite similar to the dbm module,
but uses GDBM instead to\012provide some additional functionality. Please note that
the file formats\012created by GDBM and dbm are incompatible. \012\012GDBM objects
behave like mappings (dictionaries), except that keys and\012values are always
strings. Printing a GDBM object doesn't print the\012keys and values, and the items()
and values() methods are not\012supported.", 'open': <built-in function open>,
'__file__': '/usr/lib/python1.5/lib-dynload/gdbmmodule.so', '__name__': 'gdbm'}
>>> dir(gdbm.open)
['__doc__', '__name__', '__self__']
Looking at the 'error' declared defined in this module it looks like a
class definition:
>>> gdbm.error
<class gdbm.error at 80d4368>
Look in the gdbmmodule.c file in the Modules directory for the
following code:
DbmError = PyErr_NewException("gdbm.error", NULL, NULL);
if (DbmError != NULL)
PyDict_SetItemString(d, "error", DbmError);
This code creates an instance of an Exception and inserts it into the
gdbm module's dictionary with the name 'error'. All of the
functionality of the Python language (such as declaring functions,
building classes, calling methods, or creating tuples) can be accessed
from the C API. Jim Fulton from Digital Creations flushed out this
abstract Python API back around Python 1.2. As Fred mentioned some of
this API is documented in the Python "C API" and "Extending & Embedding"
documents. Some of the essential details have remained undocumented to
assure that Python consultants who know the secret handshake can all
become millionaires off of huge consulting contracts. (So far this
trick hasn't worked because Python is too easy to learn.)
The wrapping of code, such as gtk and libglade, is a bit more
involved than adding an 'error' name to the module dictionary, but the
principle is generally the same. You wrap existing C code by using
the abstract C API to make the legacy C code look like Python
objects. Like the Borg, Python is assimilating code and making it
look like it is a native part of Python.
The trick to writing C extensions in Python is to prototype them in
Python and then recode them in C using the abstract API. Achieving
Python guru status involves transcending to the level where you write C
code directly in a Python dialect.
So as you can see I lied about the mirrors and magic. It's really all
done with dictionaries.
To unsubscribe: echo "unsubscribe" | mail [EMAIL PROTECTED]