53

我有这个具有 ax 和 ay 参数(以及其他一些东西)的对象列表。

path.nodes = (
    <GSNode x=535.0 y=0.0 GSLINE GSSHARP>,
    <GSNode x=634.0 y=0.0 GSLINE GSSHARP>,
    <GSNode x=377.0 y=706.0 GSLINE GSSHARP>,
    <GSNode x=279.0 y=706.0 GSLINE GSSHARP>,
    <GSNode x=10.0 y=0.0 GSLINE GSSHARP>,
    <GSNode x=110.0 y=0.0 GSLINE GSSHARP>,
    <GSNode x=189.0 y=216.0 GSLINE GSSHARP>,
    <GSNode x=458.0 y=216.0 GSLINE GSSHARP>
)

我需要有这个列表的最大值。虽然,我试过这个:

print(max(path.nodes, key=y))

我得到这个错误:

NameError: name 'y' is not defined

我对 Python 有点陌生,文档没有给我任何线索。我认为我在关键字上做错了,因为如果像这样遍历节点:

for node in path.nodes:
    print(node.y)

我会得到 y 的值。有人可以给我一个解释吗?

4

7 回答 7

92

要获得最大值而不是整个对象,您可以使用生成器表达式:

print(max(node.y for node in path.nodes))
于 2012-10-25T11:32:29.730 回答
33

有一个内置的帮助解决这种情况。

import operator

print(max(path.nodes, key=operator.attrgetter('y')))

或者:

print(max(path.nodes, key=lambda item: item.y))

编辑:但是 Mark Byers 的回答是最 Pythonic 的。

print(max(node.y for node in path.nodes))
于 2012-10-25T11:31:20.090 回答
27

何时使用“Pythonic”样式 #1 与 lambda 样式 #2 有一个重要区别:

max(node.y for node in path.nodes)  # (style #1)

相对

max(path.nodes, key=lambda item: item.y)  # (style #2)

如果您仔细观察,您会发现样式 #1 返回属性的最大值,y而样式 #2 返回node具有最大值的属性y。这两个不相同,如果您想要迭代属性值或迭代拥有该属性的对象,代码用法很重要。

例子:

class node():
    def __init__(self,x):
        self.x = x
        self.y = self.x + 10

node_lst = [node(1), node(2), node(3), node(4), node(5)]
print([(e.x,e.y) for e in node_lst])

>>> [(1, 11), (2, 12), (3, 13), (4, 14), (5, 15)]

现在:

maxy = max(node.y for node in node_lst)
print(maxy)
>>> 15

max_node = max(node_lst, key=lambda node: node.y)
print(max_node.y)
>>> 15
于 2017-10-17T17:46:50.223 回答
5
from operator import attrgetter
print(max(path.nodes, key=attrgetter("y")))
于 2012-10-25T11:31:20.007 回答
3

也可以为__gt__对象实现比较运算符,而不是在max没有键函数的情况下使用:

class node:
    def __init__(self, y):
        self.y = y
    def __gt__(self, other):
        return self.y > other.y

而不是类似的东西:

ls = [node(3), node(5), node(11), node(0)]
print(max(ls).y)

应该输出11

于 2019-11-29T19:38:00.693 回答
0

y未定义为变量;它是单个GSNode对象的属性;您不能单独将其用作名称。

要访问各个属性,您可以使用类似key=lambda x: x.yattrgetter()来自operator模块的内容。

于 2012-10-25T11:33:00.213 回答
0

如果y是一个属性属性,那么你甚至不需要 import operator.attrgetter。您可以改用fget方法:

my_node = max(path.nodes, key=Node.y.fget)

这将返回Node从哪里获得最大值的实例y只是my_node.y

于 2019-05-15T12:24:00.197 回答