获取函数传入参数的原始变量名:我的实现是否可行?
关于通过全局变量匹配获取函数参数原始变量名的方案疑问
你编写的通过遍历全局变量、匹配对象ID来获取参数原始变量名的代码如下:
import pandas as pd my_var = pd.DataFrame(...) def f(dataset: pd.DataFrame): for name, obj in globals().items(): if id(obj) == id(dataset): return name f(my_var)
你希望确认该方案是否合理,以及替代方案,以下是具体分析:
1. 该方案是否合理/有效?
这个方案存在多处隐患,并不合理,具体问题包括:
- 多变量指向同一对象时返回错误名称:如果有多个变量引用同一个DataFrame对象(比如
temp = data_train),调用f(temp)会返回第一个匹配到的全局变量名data_train,而非传入的变量名temp,完全不符合预期。 - 无法处理局部变量或匿名对象:如果参数是函数内的局部变量(比如在另一个函数中定义的
local_df),或者直接传入匿名对象(比如f(pd.DataFrame())),遍历globals()根本找不到匹配项,函数会返回None,导致后续逻辑报错。 - 全局变量过多时的性能损耗:如果全局作用域内有大量变量,每次遍历都会产生不必要的开销,虽然数据分析场景下变量数量通常不多,但仍是可避免的问题。
2. 更优的替代方案
最可靠且无歧义的方案是显式传入变量名作为额外参数,因为Python中变量名仅仅是对象的引用,对象本身并不存储指向它的变量名,反向查找从本质上就存在不确定性。修改你给出的数据分析示例代码如下:
import pandas as pd def f(dataset: pd.DataFrame, group_name: str): return_dataframe = do_stuff(dataset) return_dataframe["group"] = group_name return return_dataframe data_frame_for_plotting = pd.concat([f(data_train, "data_train"), f(data_test, "data_test")])
如果觉得重复输入变量名过于繁琐,可以结合inspect模块提取调用者作用域内的变量名,但仍需注意它的局限性(多变量指向同一对象时仍会返回第一个匹配项),示例代码如下:
import pandas as pd import inspect def get_arg_name(arg): # 获取调用者的栈帧 caller_frame = inspect.currentframe().f_back # 遍历调用者的局部变量 for name, obj in caller_frame.f_locals.items(): if obj is arg: return name return None def f(dataset: pd.DataFrame): return_dataframe = do_stuff(dataset) group_name = get_arg_name(dataset) if group_name: return_dataframe["group"] = group_name return return_dataframe # 调用时可以直接传变量名 data_frame_for_plotting = pd.concat([f(data_train), f(data_test)])
不过需要注意,inspect的方案仍不如显式传参可靠,在复杂调用场景(比如嵌套函数、关键字参数传递)下仍可能出现预期外的结果,因此对于数据分析这类需要稳定可预期结果的场景,优先推荐显式传入名称的方案。
内容的提问来源于stack exchange,提问作者Make42
相关产品推荐
相关产品推荐

