RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1338196
Accepted
Вадим Соловьев
Вадим Соловьев
Asked:2022-03-14 12:40:12 +0000 UTC2022-03-14 12:40:12 +0000 UTC 2022-03-14 12:40:12 +0000 UTC

按键值排序字典列表

  • 772

如果可能,请详细说明此代码的工作原理。我在论坛上发现了一个类似的问题,但没有解释。(我用lambda找到了很多解决方案,但完全不清楚。lambdas被搁置了很长时间,直到所有材料都很好吸收。)不要严格判断- 我是初学者。

这就是为什么不带括号调用 mykey() 函数的原因吗?这个函数实际上发生了什么?

如果函数返回字符串'age',那为什么不直接写key = 'age'呢?为什么这会引发错误?我阅读了 Byte of Python,几乎所有内容都 99% 清晰,除了这一刻,它通过 lambda 解决。

为什么所有函数都用括号调用?为什么调用不带括号的函数总是(在这种情况下除外)会导致错误,但这里是相反的?一切都很顺利,直到我遇到这个 #@%# 什么是函数对象?foo() 和只是 foo 有什么区别?这些时刻我都不清楚,也没有找到明确的解释。本书中也没有:-(

x = [{'name' : 'Homer', 'age' : 39}, {'name' : 'Bart', 'age' : 100}]

def mykey(a):
    return a['age'] 

print(sorted(x, key = mykey))
python
  • 3 3 个回答
  • 10 Views

3 个回答

  • Voted
  1. Сергей Махнёв
    2022-03-14T13:09:53Z2022-03-14T13:09:53Z

    很多问题,但我会尽力回答。

    这就是为什么不带括号调用 mykey() 函数的原因吗?

    都是 sorted 函数,它以函数作为 key 参数,如手册中所写: 可迭代对象也可以通过 key 参数中指定的函数进行排序。它可能是:

    Встроенная функция,
    Определенная пользователем функция,
    Лямбда-функция,
    itemgetter,
    attrgetter.
    

    带描述的链接已排序

    这个函数实际上发生了什么?

    该函数返回年龄,但如果你写它不会直接工作,例如

    print(mykey(x))
    

    因为 他应该在输入时一次接收一个,如下所示:

    print(mykey(x[0]))
    

    如果函数返回字符串'age',那为什么不直接写key = 'age'呢?为什么这会引发错误?

    答案给出了高一点,因为应该有一个函数作为参数。

    我希望我能够解释一些事情。

    • 2
  2. insolor
    2022-03-14T13:22:40Z2022-03-14T13:22:40Z

    如果函数返回字符串'age',那为什么不直接写key = 'age'呢?为什么这会引发错误?

    该函数不返回字符串'age',而是接收字典作为输入,并通过 key 返回该字典中写入的内容'age'。

    例子:

    def mykey(a):
        return a['age']
    
    d = {'name' : 'Homer', 'age' : 39}
    print(mykey(d))  # Выведет 39
    

    这就是为什么不带括号调用 mykey() 函数的原因吗?

    没有括号 - 因为这个函数不是直接调用的,而是作为一个对象在函数内部传递sorted,并且在它内部已经为每个排序的元素调用,那么结果值被用作排序键(对象的值已排序)。在这种情况下,从列表的每个元素中提取年龄,然后按年龄排序。

    什么是函数对象?foo() 和只是 foo 有什么区别?

    好吧,如果,作为一个非常遥远的类比,你可以想象一个函数对象就像一辆停在任何地方的公共汽车。函数调用(带括号)是将人加载到总线(函数参数),他去了,把人带到了某个地方——函数被执行了,得到了一些结果。

    将一个不带括号的函数传递给另一个函数——你把公共汽车卖给了一些将载人的公司。同时,您自己并没有将这辆公共汽车送上飞机,您只是将它“卖”给了某个公司。

    为什么这段代码不起作用:

    print(sorted(x, key = mykey(x[0])))
    

    因为在这里我们自己在航班上发送了“公共汽车”,我们试图“出售”这次调度的结果,而不是“公共汽车”本身。

    我阅读了 Byte of Python,几乎所有内容都 99% 清晰,除了这一刻,它通过 lambda 解决。

    Lambda 只是一个未命名的函数。您可以将 lambda 写入变量,它将像普通函数一样工作,即:

    mykey = lambda a: a['age']
    
    # это по сути то же самое, что 
    
    def mykey(a):
        return a['age']
    

    为什么总是调用不带括号的函数(在这种情况下除外)会导致错误

    它不会抛出错误,只是“公共汽车”不会去任何地方:)

    仅当您自己在航班上发送它(用括号调用函数)或其他人这样做(您将函数传递到将用括号调用该函数的地方)时,它才会起作用。

    • 2
  3. Best Answer
    Roman-Stop RU aggression in UA
    2022-03-14T17:12:09Z2022-03-14T17:12:09Z

    如果函数返回字符串'age',那为什么不直接写key = 'age'呢?

    这样做的原因是该函数sorted是一个库函数,旨在对任何对象进行排序。好吧,也就是说,标准库的作者在编写它时,是为了使它可以用于任何对象的列表。

    如果你想一想,对于排序对象的功能,你只需要知道列表本身和比较两个对象的方法,这样对于任何两个对象,你都可以分辨出哪个更大,哪个更小。

    假设您为普通数字编写了一个排序函数,它工作得很好,速度很快,每个人都很开心。现在您需要对字典进行排序。排序算法本身不会因为对象发生变化而改变。唯一改变的是列表元素在算法中的比较方式。

    你可能会问“好吧,我正在传递一个字典,为什么不让我指定字典中的键来排序?”

    再次,原因是多功能性。如果您不仅要按 排序age,而且要先按排序age,如果年龄相同,那么您希望这些字典按字母顺序排列name吗?在这种情况下,只传递键名是行不通的,你需要传递一个列表。如果您想按年龄降序排序,然后按姓名升序排序怎么办?现在对于每个字段名称,您还需要传递排序方向。

    这原则上是可以做到的。并且图书馆的作者可以走(但没有走这条路,而是选择了更通用和优雅的方式)。然后函数调用将如下所示:

    print(sorted(x, keys_to_sort_by = [('age', 'desc'), ('name', 'asc)]))
    

    在这里,我们传递了一个对列表(имя-поля, направление-сортировки)(asc- 升序,desc- 降序)。

    但是这种方法存在问题:

    1. 如果我们有日期字段之一并且需要按月排序怎么办?那些。如果该字段的值不是直接合适的,但我们需要从该值中提取(或以另一种方式,基于该值计算)另一个值。如本例所示,我们需要从日期中获取月份并将其用于排序。或者类似的例子,如果你需要排序让 18 岁以下的孩子按字母顺序排列,然后成人也按字母顺序排列(在这种情况下,使用年龄字段,我们必须计算符号“儿童/成人”并首先按它排序所有,算上“孩子”<“成人”)。
    2. 这仅适用于字典。对于其他类型的对象,您将不得不编写一个友元函数。另一方面,该库的作者想要编写一个可用于任何类型的通用函数。

    为了解决这些问题,使用了这个技巧:不是比较元素本身,而是比较为元素计算的值。并获得这样的值(称为排序键 - 这就是为什么调用参数key,不要与字典中的键混淆!)使用用户sorted传入参数的函数。也就是说,在排序算法内部,之前(对于数字算法)进行了比较:

    def sorted(elements):
        ....
        if el1 =< el2:
          # el1 должен быть раньше el2 в результате, продолжаем с учетом этого
        else:
          # el2 должен быть раньше el1 в результате, продолжаем с учетом этого
    

    它会是这样的:

    def sorted(elements, key):
        ....
        if key(el1) =< key(el2):
          # el1 должен быть раньше el2 в результате, продолжаем с учетом этого
        else:
          # el2 должен быть раньше el1 в результате, продолжаем с учетом этого
    

    如您所见,对于我们正在排序的序列中的元素,我们调用函数(注意我们使用括号key(el1)- 这意味着“调用存储在 key 变量中的函数并将 el1 变量中的值作为参数”),它在参数中传递key,并通过元素本身传递给它。这意味着该函数将能够从元素中“获取”值,该值已经用于比较。

    这是一种非常灵活的方式,因为它允许您根据情况比较任何元素(因为我们可能需要在不同情况下对相同的字典列表进行不同的排序,或者更改数字或字符串的排序顺序)。

    例如,如果您需要按降序对数字进行排序,则使用以下函数:

    def in_reverse(num):
       return -num
    

    如果我们想首先按年龄然后按名称对字典列表进行排序,那么以下函数将执行:

    def by_age_then_name(el):
       return (el['age'], el['name])
    

    这里的键函数返回一个元组(元组),元组将被比较,对于它们,如您所知,比较的工作方式是较小的将是第一个组件较小的那个(在这里我们放那里的年龄),或者,如果第一个组件相同,则比较后者。结果,我们得到了我们需要的东西。

    foo() 和 just foo 有什么区别

    这是一个类比。在商品销售广告中,您可以说“商品价格为 100 美元”。并且可以写“可以通过电话查到商品的价格”。在第二种情况下,广告用户必须拨打电话获取价格(即调用函数获取价值)。我们只是给了他稍后获取值的机会(即函数本身foo,而不是它计算的值)。

    • 1

相关问题

  • 是否可以以某种方式自定义 QTabWidget?

  • telebot.anihelper.ApiException 错误

  • Python。检查一个数字是否是 3 的幂。输出 无

  • 解析多个响应

  • 交换两个数组的元素,以便它们的新内容也反转

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5