如何让一个实例知晓自己的变量名
这段时间在写一个做提示工程的库,其中顺便实现了一套模板语言,其中一个模板实例的 repr 格式化时想了一种方式获得一个实例的变量名。如下所示:
我创建了一个 GitHub Gist
这段代码定义了一个名为 AutoNaming
的类,该类的作用是自动获取并绑定实例的名称。
-
__new__
方法:在创建新实例时,首先调用__new__
方法,它创建了一个新的实例,并调用_bind_frame
方法。 -
_bind_frame
方法:获取当前的堆栈帧,并将其存储在实例的_frame
属性中。 -
_name
方法:这是一个缓存属性,它试图从_frame
属性中找到实例的名称。如果找到,就返回这个名称。 -
class_name
属性:返回实例的类名。 -
fallback_name
属性:如果无法获取实例的名称,就返回类名作为备选名称。 -
name
属性:返回实例的名称,如果_name
属性不存在,就返回fallback_name
。 -
name
属性的 setter 方法:允许用户手动设置实例的名称,并将_frame
属性设置为None
。 -
name
属性的 deleter 方法:删除_name
属性。 -
__repr__
方法:返回实例的字符串表示形式,包含类名和实例名。 -
__str__
方法:返回实例名。
总的来说,这个类的目的是在创建实例时自动获取并绑定实例的名称,同时也支持手动设置和删除实例名。
# copied from `promplate.prompt.utils`
from functools import cached_property
from inspect import currentframe
class AutoNaming:
def __new__(cls, *args, **kwargs):
obj = super().__new__(cls)
obj._bind_frame()
return obj
def _bind_frame(self) -> None:
self._frame = currentframe()
@cached_property
def _name(self):
f = self._frame
if f and f.f_back and (frame := f.f_back.f_back):
for name, var in frame.f_locals.items():
if var is self:
return name
@property
def class_name(self):
return self.__class__.__name__
fallback_name = class_name
@property
def name(self):
return self._name or self.fallback_name
@name.setter
def name(self, name):
self._name = name
self._frame = None
@name.deleter
def name(self):
del self._name
def __repr__(self):
if self._name:
return f"<{self.class_name} {self.name}>"
else:
return f"<{self.class_name}>"
def __str__(self):
return f"<{self.name}>"