【问题标题】:Python: Why return-type of itemgetter is not consistentPython:为什么 itemgetter 的返回类型不一致
【发布时间】:2018-02-26 12:41:40
【问题描述】:

Python itemgetter 不返回长度为 0 或 1 的元组。 例如:

from operator import itemgetter

def get_something(keys):
    d = {
        "a": 1,
        "b": 2,
        "c": 3
    }
    return itemgetter(*keys)(d)

print(type(get_something(["a", "b"])))
# <class 'tuple'>
print(type(get_something(["a"])))
# <class 'int'>
print(type(get_something([])))
# TypeError: itemgetter expected 1 arguments, got 0 
  • itemgetter 这样写有什么好的理由吗?而不是(1,) 是倒数第二个() 和最后一个?

  • 如果我总是想在给定键的情况下返回元组/列表,还有其他内置选项吗?

【问题讨论】:

  • 你的prints实际上return是做什么的?
  • 我在上面加了
  • itemgetter 是一个非常简单的辅助函数。如果它的工作方式不适合您,您应该编写自己的工作方式以您想要的方式工作。 FWIW 我同意你关于不一致的返回类型。
  • @SpoonMeiser 是的,但对我来说这看起来像是一个明显的设计缺陷,但我仍然意识到创建 Python 的人比我聪明 100 倍。所以我想了解我在这里缺少什么。

标签: python python-3.x


【解决方案1】:

如果我总是想返回一个 给定键的元组/列表?

只需使用理解:

[d[k] for k in keys]

在上下文中:

from operator import itemgetter

def get_something(keys):
    d = {
        "a": 1,
        "b": 2,
        "c": 3
    }
    return [d[k] for k in keys]

print(get_something(["a", "b"]))
#[1, 2]
print(get_something(["a"]))
#[1]
print(get_something([]))
#[]

【讨论】:

  • 如果已经走这条路,请考虑使用.get 以避免潜在的KeyError
  • @DeepSpace Yah 可以做或[d[k] for k in keys if k in d],取决于他们在这种情况下想要什么
  • 好的。那么为什么我们有itemgetter 内置呢?我的意思是这是一个很好的方法,但我很难想象我会使用实际的 itemgetter 来做任何事情。
  • @Pekka itemgetter 适用于一些任务,比如基于第二项排序sorted([('a', 2), ('b', 1)], key=itemgetter(1))
  • @Pekka 使用 lambda 有效,但性能较差(较慢)stackoverflow.com/questions/17243620/…
【解决方案2】:

您的部分困惑来自这样一个事实:您的 get_something() 函数接受一个参数(预计是一个可迭代的)并在将其传递给 itemgetter() 时将其解包。这导致get_something() 的返回值与其参数不是“对称的”。

如果您将 get_something() 定义为使用可变参数(如 itemgetter() 所做的那样):

def get_something(*keys):
    d = {
        "a": 1,
        "b": 2,
        "c": 3
    }
    return itemgetter(*keys)(d)

返回值会与参数更一致,即:

# ask for 3 keys, get 3 values:
>>> get_something("a", "b", "c")
(1, 2, 3)

# ask for 2 keys, get 2 values:
>>> get_something("a", "b")
(1, 2)

# ask for one key, get 1 value
>>> get_something("a")
1

# all of this with tuple unpacking in mind:

a, b = get_something("a", "b")
a = get_something("a") 

现在的重点是很少有人会费心使用 itemgetter() 来实现您的 get_something 函数 - itemgetter 主要被设计为用作 sorted() 的回调和类似的函数/方法(它是当前的行为是有道理的),并且get_something 将更规范地使用列表表达式来实现,即:

def get_something(keys):
    d = {
        "a": 1,
        "b": 2,
        "c": 3
    }
    return [d[k] for k in keys]

这将接受一个可迭代并返回一个(可能为空的)列表。

【讨论】:

    【解决方案3】:

    docs 中记录了这种行为(重点是我的):

    返回一个可调用对象,该对象使用 操作数获取项目 操作数的__getitem__() 方法。如果指定了多个项目, 返回查找值的元组

    itemgetter不决定返回类型,它是操作数的__getitem__()方法。

    会不会更容易/更好

    “更好”是主观的。你可以随时换行itemgetter

    def get_something(keys):
        def my_itemgetter():
            r = itemgetter(*keys)(d)
            return (r,) if type(r) is not tuple else r
    
        d = {
            "a": 1,
            "b": 2,
            "c": 3
        }
    
        return my_itemgetter()
    

    【讨论】:

    • 好吧,也许这部分问题是主观的,但我的意思是对每个人都更好。我会把问题改得更客观:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-20
    • 1970-01-01
    • 2015-06-26
    相关资源
    最近更新 更多