Is there a way to set a default parameter equal to another parameter value?
例如,我有一个返回排列列表的基本方法。
1 2 3 4 5 6 | import itertools def perms(elements, set_length=elements): data=[] for x in range(elements): data.append(x+1) return list(itertools.permutations(data, set_length)) |
现在我明白了,在当前状态下,这段代码不会运行,因为第二个
否,函数关键字参数默认值是在定义函数时确定的,而不是在执行函数时确定的。
将默认值设置为
1 2 3 | def perms(elements, setLength=None): if setLength is None: setLength = elements |
如果需要指定
1 2 3 4 5 | _sentinel = object() def perms(elements, setLength=_sentinel): if setLength is _sentinel: setLength = elements |
。
现在呼叫者可以将
因为python处理绑定和默认参数的方式…
标准方法是:
1 2 3 | def perms(elements, setLength=None): if setLength is None: setLength = elements |
另一个选择是:
1 2 | def perms(elements, **kwargs): setLength = kwargs.pop('setLength', elements) |
号
尽管这要求您明确使用
你应该这样做:
1 2 3 | def perms(elements,setLength=None): if setLength is None: setLength = elements |
答案1:
上面的解决方案如下:好的。
1 2 3 4 | def cast_to_string_concat(a, b, c=None): c = a if c is None else c return str(a) + str(b) + str(c) |
虽然这种方法可以解决大量的潜在问题(也许还有你的问题)!我想写一个函数,其中变量"EDOCX1"(0)的可能输入实际上是单例
为了进一步解释这一点,使用以下变量调用函数:好的。
1 2 3 | A='A' B='B' my_var = None |
号
产量:好的。
1 2 | cast_to_string_concat(A, B, my_var): >>>'ABA' |
然而,用户可能期望,因为他们使用三个变量调用函数,所以它应该打印三个变量,如下所示:好的。
1 2 | cast_to_string_concat(A, B, my_var): >>> 'ABNone' # simulated and expected outcome |
。
因此,即使声明了第三个变量,这个实现也忽略了它,因此这意味着函数不再能够确定是否定义了变量"EDOCX1"〔0〕。好的。
因此,在我的用例中,默认值
有关建议此解决方案的答案,请阅读以下内容:好的。
- 是否可以将默认参数设置为其他参数值?
- 变量默认值的python快捷方式为另一个变量值(如果没有)。
- 函数参数的默认值等于另一个参数
- 如何避免默认参数为空列表?
但是,如果这对你不起作用,那就继续读吧!好的。
上面第一个链接中的注释提到使用由
因此,该解决方案取消了none的使用,并通过使用隐含的私有
1 2 3 4 5 | _sentinel = object() def cast_to_string_concat(a, b, c=_sentinel): c = a if c == _sentinel else c return str(a) + str(b) + str(c) |
1 2 3 4 5 6 7 8 9 | A='A' B='B' C='C' cast_to_string_append(A,B,C) >>> 'ABC' cast_to_string_concat(A,B) >>> 'ABA' |
。
这真是太棒了!它能正确处理上面的边缘箱!自己看看:好的。
1 2 3 4 5 6 | A='A' B='B' C = None cast_to_string_concat(A, B, C) >>> 'ABNone' |
。
所以,我们结束了,对吧?是否有任何合理的方法可能不起作用?隐马尔可夫模型。。。可能不是!但我确实说过这是一个由三部分组成的答案,所以继续!;)好的。
为了完整性起见,让我们假设我们的程序在一个空间中运行,在这个空间中,每个可能的场景都是可能的。(这可能不是一个合理的假设,但我认为,只要有足够的关于计算机架构和对象选择实现的信息,就可以得出
1 2 3 4 5 | _sentinel = object() def cast_to_string_concat(a, b, c=_sentinel): c = a if c == _sentinel else c return str(a) + str(b) + str(c) |
1 2 3 4 5 6 | A='A' B='B' S = _sentinel cast_to_string_append(A,B,S) >>> 'ABA' |
。
等一下!我输入了三个参数,所以我应该看到三个参数的字符串连接在一起!好的。
*排队进入有不可预见后果的土地*好的。
我是说,实际上不是。回答:"这是微不足道的优势领域!或者它的同类是完全有保证的。好的。
这种感觉是对的!对于这个案例(可能是大多数案例),这真的不值得担心!好的。
但是,如果值得担心,或者你只是想在数学上满足于消除你所知道的所有边缘情况…向前的!好的。
Exercise left to reader:
Ok.
Deviating from this technique, you can directly assert
c=object() , however, in honesty, I haven't gotten that way to work for me. My investigation showsc == object() isFalse , andstr(c) == str(object()) is alsoFalse , and that's why I'm using the implementation from Martin Pieters.Ok.
号
好吧,经过长时间的锻炼,我们回来了!好的。
回想一下,目标是编写一个可能有
n 输入的函数,并且只有在没有提供一个变量的情况下,您才会复制位置i 中的另一个变量。好的。如果我们改变方法允许任意数量的变量,而不是默认地定义变量呢?好的。
因此,如果您正在寻找一种不影响潜在输入的解决方案,其中有效输入可以是
None 、object() 或_sentinel …然后(只有在那时),在这一点上,我认为我的解决方案将是有帮助的。这项技术的灵感来自乔恩·克莱门茨回答的第二部分。好的。答案3:我对这个问题的解决方案是更改这个函数的命名,并用一个以前命名约定的函数包装这个函数,但是我们使用
*args ,而不是使用变量。然后在本地范围内定义原始函数(使用新名称),并且只允许您希望的几种可能性。好的。在步骤中:好的。
将函数重命名为类似的内容 删除可选参数的默认设置 开始在上面创建一个新函数,并在中标记原始函数。
1 def cast_to_string_concat(*args):确定你的函数的arity(我在搜索中找到了那个词…这是传递给给定函数的参数数目) 使用内部的case语句来确定是否输入了有效数量的变量,并相应地进行调整!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 def cast_to_string_append(*args):
def string_append(a, b, c):
# this is the original function, it is only called within the wrapper
return str(a) + str(b) + str(c)
if len(args) == 2:
# if two arguments, then set the third to be the first
return string_append(*args, args[0])
elif len(args) == 3:
# if three arguments, then call the function as written
return string_append(*args)
else:
raise Exception(f'Function: cast_to_string_append() accepts two or three arguments, and you entered {len(args)}.')号
1
2
3
4
5
6
7
8
9
10
11 # instantiation
A='A'
B='B'
C='C'
D='D'
_sentinel = object()
S = _sentinel
N = None
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 """ Answer 3 Testing"""
# two variables
cast_to_string_append(A,B)
>>> 'ABA'
# three variables
cast_to_string_append(A,B,C)
>>> 'ABC'
# three variables, one is _sentinel
cast_to_string_append(A,B,S)
>>>'AB<object object at 0x10c56f560>'
# three variables, one is None
cast_to_string_append(A,B,N)
>>>'ABNone'
# one variable
cast_to_string_append(A)
>>>Traceback (most recent call last):
>>> File"<input>", line 1, in <module>
>>> File"<input>", line 13, in cast_to_string_append
>>>Exception: Function: cast_to_string_append() accepts two or three arguments, and you entered 1.
# four variables
cast_to_string_append(A,B,C,D)
>>>Traceback (most recent call last):
>>> File"<input>", line 1, in <module>
>>> File"<input>", line 13, in cast_to_string_append
>>>Exception: Function: cast_to_string_append() accepts two or three arguments, and you entered 4.
# ten variables
cast_to_string_append(0,1,2,3,4,5,6,7,8,9)
>>>Traceback (most recent call last):
>>> File"<input>", line 1, in <module>
>>> File"<input>", line 13, in cast_to_string_append
>>>Exception: Function: cast_to_string_append() accepts two or three arguments, and you entered 10.
# no variables
cast_to_string_append()
>>>Traceback (most recent call last):
>>> File"<input>", line 1, in <module>
>>> File"<input>", line 13, in cast_to_string_append
>>>Exception: Function: cast_to_string_append() accepts two or three arguments, and you entered 0.
""" End Answer 3 Testing"""。所以,总而言之:
- 答案1-最简单的答案,适用于大多数情况。
1
2
3
4 def cast_to_string_concat(a, b, c=None):
c = a if c is None else c
return str(a) + str(b) + str(c)
- 回答2—如果
None 实际上没有通过_sentinel 切换到object() 表示空参数,则使用。
1
2
3
4
5 _sentinel = object()
def cast_to_string_concat(a, b, c=_sentinel):
c = a if c == _sentinel else c
return str(a) + str(b) + str(c)。
- 答案3:使用
*args 寻找一个使用任意数量包装函数的一般解决方案,并处理可接受的内部情况:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 def cast_to_string_append(*args):
def string_append(a, b, c):
# this is the original function, it is only called within the wrapper
return str(a) + str(b) + str(c)
if len(args) == 2:
# if two arguments, then set the third to be the first
return string_append(*args, args[0])
elif len(args) == 3:
# if three arguments, then call the function as written
return string_append(*args)
else:
raise Exception(f'Function: cast_to_string_append() accepts two or three arguments, and you entered {len(args)}.')号
用对你有用的东西!但对我来说,我将使用选项3;)好的。好啊。