答案1:
上面的解决方案如下所示:
def cast_to_string_concat(a, b, c=None):
c = a if c is None else c
return str(a) + str(b) + str(c)
虽然这种方法将解决无数潜在的问题,(也许是你的)!我想编写一个函数,其中变量“ c
”的可能输入确实是单例None
,所以我不得不做更多的挖掘。
为了进一步解释,使用以下变量调用函数:
A='A'
B='B'
my_var = None
产量:
cast_to_string_concat(A, B, my_var):
>>>'ABA'
而用户可能期望,由于他们使用三个变量调用函数,那么它应该打印三个变量,如下所示:
cast_to_string_concat(A, B, my_var):
>>> 'ABNone' # simulated and expected outcome
所以,这个实现忽略了第三个变量,即使它被声明了,所以这意味着函数不再有能力确定变量“ c
”是否被定义。
因此,对于我的用例,默认值None
并不能完全解决问题。
有关建议此解决方案的答案,请阅读以下内容:
但是,如果这对您不起作用,那么也许继续阅读!
上面第一个链接中的评论提到使用由_sentinel
定义的object()
。
因此,此解决方案删除了 None 的使用,并使用隐含的private将其替换为object()
through 。sentinel
答案 2:
_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)
A='A'
B='B'
C='C'
cast_to_string_append(A,B,C)
>>> 'ABC'
cast_to_string_concat(A,B)
>>> 'ABA'
所以这太棒了!它正确处理了上述边缘情况!你自己看:
A='A'
B='B'
C = None
cast_to_string_concat(A, B, C)
>>> 'ABNone'
所以,我们完成了,对吧?有什么合理的方法可以使这不起作用?嗯……应该不会吧!但我确实说过这是一个由三部分组成的答案,所以继续!;)
为了完整起见,让我们假设我们的程序在一个所有可能的场景都确实可能的空间中运行。(这可能不是一个有根据的假设,但我想可以_sentinel
通过有关计算机体系结构和对象选择的实现的足够信息来推导出 的值。所以,如果您愿意,让我们假设这确实是可能的,让我们假设我们决定测试_sentinel
上面定义的假设引用。
_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)
A='A'
B='B'
S = _sentinel
cast_to_string_append(A,B,S)
>>> 'ABA'
等一下!我输入了三个参数,所以我应该看到它们三个的字符串连接在一起!
*排队进入无法预料后果的土地*
我的意思是,实际上不是。回应:“那是可以忽略不计的边缘案例领域!!” 或者它的同类是完全有根据的。
这种情绪是对的!对于这种情况(可能是大多数情况),这真的不值得担心!
但是,如果值得担心,或者如果你只是想要消除所有你知道的边缘情况的数学满足......继续!
练习留给读者:
偏离这种技术,您可以直接断言c=object()
,但是,老实说,我还没有为我工作的那种方式。我的调查显示c == object()
是False
,str(c) == str(object())
也是False
,这就是我使用Martin Pieters的实现的原因。
好的,经过长时间的锻炼,我们回来了!
回想一下,我们的目标是编写一个可能有n
输入的函数,并且只有在没有提供一个变量的情况下——然后您将在 position 中复制另一个变量i
。
如果我们改变方法以允许任意数量的变量,而不是默认定义变量,该怎么办?
因此,如果您正在寻找一种不会影响潜在输入的解决方案,其中有效输入可能是None
,object()
或_sentinel
... 那么(并且只有这样),此时,我认为我的解决方案会有所帮助. 该技术的灵感来自Jon Clements 回答的第二部分。
答案 3:
我对这个问题的解决方案是改变这个函数的命名,并 用之前命名约定的函数包装这个函数,但是我们不使用变量,而是使用*args
. 然后,您在本地范围内定义原始函数(使用新名称),并且只允许您想要的少数可能性。
在步骤:
- 将函数重命名为类似的东西
- 删除可选参数的默认设置
- 开始在上面创建一个新函数并在其中添加原始函数。
def cast_to_string_concat(*args):
- 确定你的函数的数量- (我在搜索中找到了那个词......那是传递给给定函数的参数的数量)
- 利用里面的 case 语句来确定您是否输入了有效数量的变量,并相应地进行调整!
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)}.')
# instantiation
A='A'
B='B'
C='C'
D='D'
_sentinel = object()
S = _sentinel
N = None
""" 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 """
所以,总结一下:
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 - 使用 if
None
实际上并不表示通过切换到空object()
参数_sentinel
。
_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
,并在内部处理可接受的情况:
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 ;)