__prepare__を使用してPython3.xで解決策を見つけることができました。これが私がやりたかったことを説明する実用的なコードです。
from collections import MutableMapping
class MDict(MutableMapping):
def __init__(self, *args, **kwargs):
self._d = dict(*args, **kwargs)
def __getitem__(self, key):
return self._d[key]
def __setitem__(self, key, value):
self._d[key] = value
try:
self._d[key]._key = key # Let's set the name of the object
except AttributeError: # Not a good way to handle immutable objects
pass
def __delitem__(self, key):
del self._d[key]
def __iter__(self):
return iter(self._d)
def __len__(self):
return len(self._d)
class MBase(type):
@classmethod
def __prepare__(metacls, name, bases, **kwargs):
return MDict()
def __new__(metacls, name, bases, mdct):
return super().__new__(metacls, name, bases, dict(mdct))
def __str__( self ):
return "class {0}(CSub, metaclass=MBase):".format( self.__name__ )
class CSub: # An empty class so we know when to go deeper int print_code
pass
class Integer:
def __init__( self, value ):
self._value = value
def __str__( self ):
try: # See if it's a reference
return "{0} = Integer( {1} )".format( self._key, self._value._key )
except: # Not it's a number
return "{0} = Integer( {1} )".format( self._key, self._value )
class Point:
def __init__( self, x, y ):
if type( self ) == type( x ): # Check to see if initializing with a reference
self._x, self._y = x._key, y._key
else: # It's not reference
self._x, self._y = x, y
def __str__( self ):
try:
return "{0} = Point( {1}, {2} )".format( self._key, self._x._key, self._y._key )
except:
return "{0} = Point( {1}, {2} )".format( self._key, self._x, self._y )
def print_code( cls, indent = 2 ):
# Print the header
if indent == 2:
print( "class Main(metaclass=MBase):" )
for attr, value in cls.__dict__.items():
if not attr.startswith( "_" ): # Ignore hidden attributes
print( " " * indent + str( value ) ) # Use indentation
if isinstance( value, CSub.__class__ ): # If it's a subclass then process that too
print_code( value, indent + 2 )
class Main(metaclass=MBase):
x = Integer( 0 )
y = Integer( 100 )
z = Integer( x )
p1 = Point(x,x)
p2 = Point(y,y)
class Sub(CSub, metaclass=MBase):
p = Point(1,1)
print_code( Main )
このように、オブジェクトxを変更すると、xを参照する他のすべてのオブジェクトも変更されます。さらに、後で使用するためにコードをテキストファイルに簡単に保存できます。
これにはまだ作業が必要ですが、良いスタートです。これが、似たようなものを探している他の人の助けになることを願っています。