在我的工作中,我的Python脚本从非Python专业用户那里获得了很多输入。 所以,例如,如果我的函数需要处理单个值和一系列值(Polymorphism / Duck Typing,哟!),我想做一些像这样的伪代码:
def duck_typed(args):
"""
args - Give me a single integer or a list of integers to work on.
"""
for li in args:
<do_something>
如果用户向我传递了一个列表:
[1,2]
一个元组:
(1,2)
甚至是单身元组(请在此处提供术语帮助)
(1,)
一切都按预期工作。但是一旦用户传入一个整数,一切都会转到$%^&amp;:
1
TypeError: 'int' object is not iterable
现在,我立刻想到,&#34;没问题,我只需要聪明一点!&#34;我做了这样的事情:
def duck_typed(args):
"""
args - Give me a single integer or a list of integers to work on.
"""
args = (args,) # <= Ha ha! I'm so clever!
for li in args:
<do_something>
好吧,现在它适用于单个整数情况:
args = (1,)
(1)
但是当用户传入一个iterable时,$%^&amp; * s再次出现。我的技巧给了我一个嵌套的可迭代:
args = ((1,2),)
((1,2),)
哎呀!
当然有通常的解决方法。尝试/除外条款:
try:
args = tuple(args)
except TypeError:
args = tuple((args,))
这些工作,但我遇到了这个问题 A LOT 。这实际上是一个问题,try / except是一个4行解决方案。如果我能打电话,我真的很喜欢它:
tuple(1)
让它返回(1,)并将其称为一天。
现在我意识到我在Python编程领域的小角落里的需求并不适用于Python世界的其他部分。动态类型化使得Python成为一种优秀的语言 - 特别是在C等神经质语言的多年工作之后。(对不起,对不起。我不是在抨击C.它非常擅长于它擅长,但你知道:xkcd)
我非常确定Python语言的创建者有充分理由不允许tuple(1)
。
有人请解释为什么创作者选择不允许tuple(1)
和/或list(1)
工作?我确信这完全是理智的,对很多人来说都很明显。我可能在我在Hard Knocks学校任职期间错过了它。 (它位于霍格沃茨山的另一边。)
是否有更实际的 - 希望是1行 - 进行以下转换?
X(1) - &gt; (1)
X((1,2)) - > (1,2)
如果没有,我想我可以分解并自己动手。
答案 0 :(得分:3)
Duck typing 解释并验证 list(1)
失败的原因。
该方法期待鸭子,但是给了仓鼠,仓鼠不能游泳 1 。
在鸭子打字中,程序员只关心确保对象在给定的上下文中按其所需的行为,而不是确保它们是特定的类型
但并非所有对象/类型都表现相同或“按要求”。在这种情况下,整数不的行为类似于iterable并导致异常。但是,list("quack")
正是因为一个字符串 就像一个可迭代的行为而去了Quack - ['q','u','a','c','k']!要使list
采用不可迭代实际上意味着特殊套管,而不是鸭子打字。
期望整数“可迭代”听起来像设计问题,因为这需要隐含的多重性变化。也就是说,[零>或更多]值的值和序列的概念应该保持分开。多态性在这种情况下不适用,因为多态(任何类型)只适用于统一 - 并且没有统一来“迭代不可迭代”。
此外,只有list(itr)
接受迭代才能适应强类型Python模型并避免边缘情况。考虑如果list(x)
以一种允许非迭代的方式编写,则无法确定结果是[x]还是[x 0 .. x n ],不知道提供的值。 Python只是禁止这个操作并将改变多重性的负担 - 或者传递一个Duck - 放在调用代码上。
参见In Python, how do I determine if an object is iterable?,它提供了几个解包(或以其他方式处理)不可迭代值的解决方案。
虽然我不推荐这种方法,因为它改变了多样性,我可能会编写如下强制函数。与isinstance
检查不同,它将处理所有不可迭代的值。但是,您必须制定ensure_iterable(None)
上应该发生的事情的规则。
def ensure_iterable(x):
try:
return iter(x)
except TypeError:
return (x,)
然后“一行”用法:
for li in ensure_iterable(args):
pass
1 仓鼠可以游泳..或至少保持漂浮一点点。然而,我发现这个比喻很容易(而且更难忘),因为湿漉漉的仓鼠是一种悲伤的想法。保持那些小动物的安全和干燥!
答案 1 :(得分:2)
试试这个:
if isinstance(variable, int):
variable = (variable, )