7

假设我有一些对象x可能是数据类型的单个实例(比如float),或者它可能是float类型列表。

有什么我可以确保它x被包装为一个列表,如果需要的话可能是一个单例列表,而不检查它的类型或做任何类似的事情。

我想要像list(x)总是工作的东西,无论是否x是单例,但这不起作用,因为单例是不可迭代的。

编辑:有关详细信息,请参阅下面的答案

同时,我不想定义自己的函数来从单例构造列表,我也不想像这样内联地做任何事情:

from collections import Iterable
y = [x] if not isinstance(x, Iterable) else list(x)

如果没有比这更简洁的了,那也没关系。我正在寻找一些已经内置在语言中的干净的方法。

我敢肯定,有些人可能认为这种isinstance方法既干净又好,但我特意寻找更简洁的东西,不需要我事先写任何新东西。我在搜索文档页面时找不到任何东西,而且我不知道如何向搜索引擎提出这个问题。

4

3 回答 3

5

这是您没有问但也许应该问的问题的答案。我只能猜测,因为您没有提供相关的上下文。

我如何处理传递给我的违反我的接口合同的参数?

你不应该尝试。如果我打电话sum(2),我会得到

TypeError:“int”对象不可迭代

因为sum期待一个可迭代的,我没有给它一个。如果您担心有人会同时致电

my_function(2.2)
my_function([2.2, 4.4])

正确的响应是引发 TypeError,而不是尝试为调用者修补问题,因为一旦你修复了第一个案例,就会有人打电话

my_function([2.2, 'loretta'])

你也报道那个案子吗?如果他们给你一个自我参照列表怎么办?如果您来自强类型语言背景,那么很容易滥用 Python 以使其表现得像 Java。这只会产生糟糕的 Python 代码:你已经在缺陷之上堆积了一个 hack。

而且“类型安全”也有点像谣言,否则double sqrt(float)不必返回域错误,但确实如此。应该sqrt取其论点的绝对值吗?屏蔽调用签名中的错误只能确保缺陷未被发现,然后在您收到未预料到的无效参数时中断。

于 2012-08-09T23:08:17.227 回答
2

在获得更多 Python 经验后重新审视这个问题时,我想到了一个解决方案,但它违反了我当时要求的不定义函数的属性。

def make_list_containing(*args):
    return list(args)

然后make_list_containing(3)make_list_containing('foo')按预期行事(与list构造函数相反,您必须改变直觉来学习如何期望它起作用)。

令我惊讶的是,list作为构造函数是“转换为list类型”而不是“放入list对象实例”的同义词。

我可以看到构造函数的多态行为在单例也是可迭代的情况下可能是模棱两可的,比如字符串。但是,为什么不支持不可迭代单例的“放入列表”行为?

另一件事是,至少对我而言,我所描述的方法似乎一致,更符合最小惊讶。

make_list_containing你知道你总是会得到一个列表,它会包含传入的元素。只要你以你想要的格式传入它们,那么这正是你会得到的。考虑:

In [34]: make_list_containing(*'foo')
Out[34]: ['f', 'o', 'o']

In [35]: make_list_containing('foo')
Out[35]: ['foo']

或者

In [40]: make_list_containing(*enumerate(range(3)))
Out[40]: [(0, 0), (1, 1), (2, 2)]

In [41]: make_list_containing(enumerate(range(3)))
Out[41]: [<enumerate at 0x7f61a7f0fd70>]

现在对我来说似乎更直观。预先设置这*正是我应该如何“去迭代”作为参数的东西中的项目。如果我不特意选择它,那么我必须将其'foo'视为单例,并计划在函数调用内部自己处理其元素或可迭代性。

在这次谈话中令人沮丧的一件事是,仅仅因为 Python 的这种约定是老人们似乎将其与意义混为一谈,这并不奇怪。但这是对惊喜的狭义定义。是的,当我启动翻译时,我不再“惊讶”list('foo')给我['f', 'o', 'o']。但我仍然感到惊讶的是,对于构造函数来说,语言的接口选择与list. 这让我感到惊讶,因为它似乎有更多的设计弱点而不是优势,而且最初用来证明它的理由是对语法的一些固定,而不是思想的清晰。

在这一点上,它偏离了意见区太远了,我显然同意这样一个事实,即由于压倒性的历史势头,这在 Python 中不会改变。但是我的问题的精神仍然是关于这个非常合理的观点。这不是“懒惰”或“只需编写一个包装函数并继续前进”的问题,因为大多数评论似乎都希望它是。

于 2014-09-24T12:44:02.093 回答
0

我不知道内置的任何类似的东西。您的解决方案对我来说似乎是最好的选择,尽管您可能想使用序列 ABC 而不是 Iterable。

于 2012-08-09T22:30:56.980 回答