如何让函数第一个未命名参数变为可选?R、Python技术问询
能不能让函数的第一个参数变为可选参数?
答案是不行——不管是R还是Python,都不会自动帮你“跳过”前面的可选参数,让后续位置参数往前匹配。
为什么你的R示例会失败?
R的参数匹配规则是先按位置顺序匹配,再按名称匹配。当你调用myFunction(1, 2)时:
- 第一个传入的
1会匹配第一个参数a(哪怕它有默认值) - 第二个传入的
2会匹配第二个参数b - 第三个必填参数
c完全没被传入,所以直接报错
R不会“聪明”到推断你是想跳过a,把1传给b、2传给c——因为这种推断会带来歧义:如果有多个带默认值的参数,程序根本没法确定你到底跳过了哪几个。
解决办法
这里有几种靠谱的处理方式:
1. 把可选参数放到最后(推荐)
这是R和Python的通用最佳实践,把必填参数放在前面,可选参数(带默认值)放在后面:
myFunction <- function(b, c, a = NULL) { if(!is.null(a)) { d <- a + c } else { d <- b + c } return(d) } myFunction(1, 2) # 正常运行,返回3(跳过a) myFunction(1, 2, 3) # 返回3+2=5 myFunction(b=1, c=2, a=3) # 和上面结果一致
2. 调用时使用命名参数
如果一定要保留参数顺序,调用时明确指定参数名,就能跳过前面的可选参数:
myFunction(b = 1, c = 2) # 跳过a,返回3 myFunction(a = 1, b = 2, c = 3) # 使用a,返回4
3. 手动处理参数匹配(不推荐)
你可以自己写逻辑来判断传入的参数数量,手动调整赋值,但这种方法会让函数逻辑变复杂,也不符合常规用法,容易让其他使用者困惑:
myFunction <- function(a = NULL, b, c) { # 获取所有传入的位置参数 args <- as.list(match.call())[-1] # 如果只传入了2个参数,说明是跳过a,把参数赋值给b和c if(length(args) == 2) { b <- args[[1]] c <- args[[2]] a <- NULL } if(!is.null(a)) { d <- a + c } else { d <- b + c } return(d) } myFunction(1, 2) # 返回3 myFunction(1, 2, 3) # 返回4
补充:Python的情况
Python在这方面更严格——它不允许你把必填参数放在可选参数后面,比如下面的代码在定义阶段就会直接报错:
# Python 3.x 会直接报错:non-default argument follows default argument def my_function(a=None, b, c): if a is not None: return a + c else: return b + c
Python强制要求必填参数(无默认值)必须排在可选参数前面,从根源上避免了这种歧义问题。
内容的提问来源于stack exchange,提问作者NicolasBourbaki
相关产品推荐
相关产品推荐

