r - 直接调用对象时获取传递给`print`的对象名称(不表示`print`函数)
问题描述
我正在尝试为我的新对象定义打印方法,并使用传递给print
using的对象名称deparse(substitute(y))
。显式使用该print
函数可以完美地工作:
obj <- structure(list(x = 1),
class = "new_obj")
print.new_obj <- function(y){
cat("New object name:\n")
print(deparse(substitute(y)))
}
print(obj)
# New object name:
# [1] "obj"
但是,当对象自己按名称调用时,生成的print
函数不会检测到名称:
obj
# New object name:
# [1] "x"
是否有一种标准方法可以在单独print
传递对象名称时更改隐式调用的行为?
编辑:已将函数参数更改y
为表示正在传递的对象,以证明无论第二次调用如何都返回“x”。
解决方案
解释发生了什么比修复它更容易。如果我们从查看泛型开始,print
我们可以看到它只是print
通过以下方式调度适合类的方法UseMethod("print")
:
print
#> function (x, ...)
#> UseMethod("print")
因此,当您调用时print(obj)
,您首先调用通用函数print(obj)
,然后调用print.new_obj(obj)
. print(sys.calls())
我们可以通过添加到您的打印方法来确认这一点:
print.new_obj <- function(y){
print(sys.calls())
cat("New object name:\n")
cat(deparse(substitute(y)))
}
print(obj)
#> [[1]]
#> print(obj)
#>
#> [[2]]
#> print.new_obj(obj)
#>
#> New object name:
#> obj
到目前为止,一切都很好,我怀疑你已经知道了这一切。
现在,当您obj
在控制台中输入时会发生什么?
obj
#> [[1]]
#> (function (x, ...)
#> UseMethod("print"))(x)
#>
#> [[2]]
#> print.new_obj(x)
#>
#> New object name:
#> x
现在我们可以看到它的x
来源。它取自对泛型的幕后调用,泛型print
实际上被称为未命名函数。因此,变量的名称实际上并不包含在调用堆栈中。SO还有其他问题,它说这使问题无法解决。这不是真的;这只是意味着您需要在调用堆栈之外查看您的对象:
print.new_obj <- function(y){
obj_name <- deparse(substitute(x, parent.frame()))
if (obj_name != "x")
{
obj_name <- names(which(sapply(ls(envir = parent.frame(2)), function(v)
identical(y, get(v, envir = parent.frame(2))))))[1]
cat("New object name:\n", obj_name)
}
else cat("New object name:\n", deparse(substitute(y)))
}
print(obj)
#> New object name:
#> obj
obj
#> New object name:
#> obj
当然,出于各种原因,您不希望在生产代码中使用它。对于数据结构来说,知道它在特定环境中被分配了什么名称并不是特别有用或合乎逻辑的,也不是为其他用户编写包的惯用方式。
不过,很高兴知道这是可能的。
推荐阅读
- python - 标记熊猫数据框中日期范围内的日期时间列表
- javascript - 为什么我的测验无法在触摸屏上开始?
- android-arrayadapter - 在listview android java中使用毕加索设置imageview
- react-native - 布尔数组作为复选框值?
- php - 在 sql 查询中选择具有多个 OR 的 DISTINCT
- java - 有没有办法在没有 AsyncPlayerChatEvent 的情况下捕捉玩家聊天输入?
- python - 如何确保终止多处理池?
- c# - 在 Asp.NET Web Forms Endpoint 上发送 Ajax 请求时收到错误(内部服务器错误)
- c# - 如何用 oledb 调用 as400 存储过程?
- android - AndroidX Preferences 异常:“您需要在此活动中使用 Theme.AppCompat 主题(或后代)。”