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"
Run Code Online (Sandbox Code Playgroud)
但是,当对象本身通过名称调用时,生成的print函数不会检测到该名称:
obj
# New object name:
# [1] "x"
Run Code Online (Sandbox Code Playgroud)
print当单独传递对象名称时,是否有一种标准方法可以更改隐式调用的行为?
编辑:已将函数参数更改为y表示正在传递的对象,以证明无论第二次调用中如何,都会返回“x”。
解释发生了什么比解决它更容易。如果我们首先查看泛型,我们可以看到它只是通过以下方式print调度适合类的方法:printUseMethod("print")
print
#> function (x, ...)
#> UseMethod("print")
Run Code Online (Sandbox Code Playgroud)
因此,当您调用 时,您首先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
Run Code Online (Sandbox Code Playgroud)
到目前为止,一切都很好,我怀疑你已经知道这一切了。
obj当您在控制台中输入内容时,现在会发生什么?
obj
#> [[1]]
#> (function (x, ...)
#> UseMethod("print"))(x)
#>
#> [[2]]
#> print.new_obj(x)
#>
#> New object name:
#> x
Run Code Online (Sandbox Code Playgroud)
现在我们可以看到它x来自哪里。它取自对泛型的幕后调用,print该泛型实际上作为未命名函数调用。因此,变量的名称实际上并不包含在调用堆栈中。还有其他关于 SO 的问题,它说这使得问题无法解决。这不是真的;这只是意味着您需要在调用堆栈之外查找您的对象:
obj
#> [[1]]
#> (function (x, ...)
#> UseMethod("print"))(x)
#>
#> [[2]]
#> print.new_obj(x)
#>
#> New object name:
#> x
Run Code Online (Sandbox Code Playgroud)
当然,出于各种原因,您不想在生产代码中使用它。对于数据结构来说,知道它在特定环境中分配的名称并不是特别有用或不符合逻辑,并且也不是为其他用户编写包的惯用方式。
不过,很高兴知道这是可能的。