Oh, the Horror! (Magie mit Symbolen)
Verfasst: Freitag 28. Februar 2014, 03:57
Wenn man in Python mit Symbolen umgeht, zB. in Sympy, dann muss das nach Pythons eigenen Regeln geschehen. Symbolische Variablen sind in Python einfach ganz normale Variablen. Deswegen muss man Symbole explizit erzeugen:Die Zeile x = symbols('x') ist nun nicht besonders schön. Besser wäre vielleicht sowas:Dazu müsste es aber ein ... geben, das jeden möglichen Variablennamen schon vordefiniert hat. Das geht also nicht. Oder doch?Und dann:Na also. Der einzige Haken dabei ist, das test ein Package sein muss und das Modul oben dessen __init__.py. Warum das so ist habe ich noch nicht verstanden.
SymbolCreator erbt nur von types.ModuleType damit derlei Anzeigen stimmen:Für die reine Funktionalität bräuchte man es nicht. Jedes Objekt kann als Modul fungieren, sofern man entsprechende Finder/Loader/Importer in den Import-Mechanismus einhängt.
Code: Alles auswählen
>>> from sympy import *
>>> x + 1
Traceback (most recent call last):
...
NameError: name 'x' is not defined
>>> x = symbols('x')
>>> x + 1
x + 1
Code: Alles auswählen
>>> from ... import x
>>> x + 1
x + 1
Code: Alles auswählen
__all__ = []
def __load__():
import imp
import sys
import types
from sympy import symbols
class SymbolCreator(types.ModuleType):
def __init__(self):
import test
self.__name__ = 'test.symbols'
self.__file__ = test.__file__
def __getattr__(self, name):
return symbols(name)
class SymbolsImporter:
def find_module(self, fullname, path):
if fullname == 'test.symbols' and path == ['test']:
return self
def load_module(self, fullname):
if fullname in sys.modules:
module = sys.modules[fullname]
else:
module = sys.modules[fullname] = imp.new_module(fullname)
sys.modules[fullname] = SymbolCreator()
module.__loader__ = self
return module
sys.meta_path.insert(0, SymbolsImporter())
import test.symbols
__load__()
del __load__
Code: Alles auswählen
$ python3
Python 3.2.3 (default, Jul 23 2012, 16:48:24)
[GCC 4.5.3] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from test.symbols import x
>>> x + 1
x + 1
>>> from test.symbols import a, b, c
>>> a ** 2 + 3 * b + c
a**2 + 3*b + c
SymbolCreator erbt nur von types.ModuleType damit derlei Anzeigen stimmen:
Code: Alles auswählen
>>> import pprint, sys
>>> pprint.pprint(sys.modules)
{'__future__': <module '__future__' from '/usr/lib/python3.2/__future__.py'>,
...
'test': <module 'test' from 'test/__init__.py'>,
'test.symbols': <module 'test.symbols' from 'test/__init__.py'>,
...
'zipimport': <module 'zipimport' (built-in)>}