我希望能够执行以下操作:
class PrintName:
def __init__( self, obj ):
print obj._name
class SetName:
def __init__( self, name = None ): # Default name is None
self._name = name
class Test:
f = SetName( ) # No explicit name given
g = PrintName( f )
此时我希望 python 打印“f”,因此在执行 PrintName( f ) 时 f 应该知道它的名称。
我发现的每个自动命名解决方案都会在创建后给出属性的名称。 我一直在尝试用元类来解决这个问题,但即使这样似乎也不起作用。
我想这样做是为了能够“保存”和“重新加载”Python代码以供以后使用(有点像原始脚本语言,可以在使用时评估的程序中进行更改)
例如:
x = 0
y = 0
p = ( x, y )
打印 p 结果为 (0,0),然后对 x 和 y 执行一些操作,结果
x = 124
y = -32
p = ( x, y )
打印p变成(124,-32)。
最简单的方法是使用
p = ( 'x', 'y' )
但在这种情况下,我们如何知道“x”是变量的名称而不是字符串“x”
我尝试为此目的编写一种简单的脚本语言,但这需要大量工作,如果上述方法可行,那么整个 python 语言都可以在脚本中使用。
我正在尝试为我的问题找到一个简单而灵活的解决方案。
预先感谢您的帮助。
最佳答案
我设法使用 __prepare__ 在 Python 3.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 的所有其他对象也会更改。 此外,我可以轻松地将代码保存到文本文件中以供以后使用。
这仍然需要工作,但这是一个好的开始。 我希望这能帮助其他人寻找类似的东西。
关于Python:在 Foo 类中:x = MyClass() MyClass 可以知道它所分配的变量的名称吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14667373/