Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用Pythonic方法对变量中可能为非的类进行排序_Python - Fatal编程技术网

用Pythonic方法对变量中可能为非的类进行排序

用Pythonic方法对变量中可能为非的类进行排序,python,Python,我有一个类看起来或多或少像这样: class Something(): def __init__(self,a=None,b=None): self.a = a self.b = b def __lt__(self,other): return (self.a, self.b) < (other.a, other.b) 我希望能够在列表中对其进行排序,通常我只需实现如下方法: class Something(): def __in

我有一个类看起来或多或少像这样:

class Something():
    def __init__(self,a=None,b=None):
        self.a = a
        self.b = b
def __lt__(self,other):
    return (self.a, self.b) < (other.a, other.b)
我希望能够在列表中对其进行排序,通常我只需实现如下方法:

class Something():
    def __init__(self,a=None,b=None):
        self.a = a
        self.b = b
def __lt__(self,other):
    return (self.a, self.b) < (other.a, other.b)
而我希望
None
值被视为大于或等于以下输出:

[Something(1,1),Something(1,None)]
我想到的第一件事是把
\ult\uuuu
改成:

def __lt__(self,other):
    if self.a and other.a:
        if self.a != other.a:
            return self.a < other.a
    elif self.a is None:
        return True
    elif other.a is None:
        return False

    if self.b and other.b:
        if self.b != other.b:
            return self.b < other.b
    elif self.b is None:
        return True
    return False
def\uu lt\uuu(自身、其他):
如果self.a和other.a:
如果是self.a!=其他.a:
返回自我a
这将给我正确的结果,但它只是丑陋的,python通常有一个更简单的方法,我真的不想对我在对整个类进行排序时使用的每个变量都这样做(为了让问题更清楚,从这里省略)

那么,解决这个问题的pythonic方法是什么呢

注 我也尝试过以下方法,但我认为更好的方法是可能的:

这将:

def __lt__(self,other):
    sorting_attributes = ['a', 'b']
    for attribute in sorting_attributes:
        self_value = getattr(self,attribute)
        other_value = getattr(other,attribute)
        if self_value and other_value:
            if self_value != other_value:
                return self_value  < other_value
        elif self_value   is None:
            return True
        elif self_value  is None:
            return False
def\uu lt\uuu(自身、其他):
排序_属性=['a',b']
对于排序_属性中的属性:
self\u value=getattr(self,属性)
其他值=getattr(其他,属性)
如果自我价值和其他价值:
如果自我价值!=其他价值:
返回自身值<其他值
elif self_值为无:
返回真值
elif self_值为无:
返回错误

我真的想把Pyhton的禅宗内化,我知道我的代码很难看,那么我该如何修复它呢?

一个简单的方法是将
None
转换为无穷大,即
float('inf')

def\uu lt\uuu(自身、其他):
def转换(i):
如果i不是其他i,则返回float('inf')
返回[将(i)转换为(self.a,self.b中的i)]<[将(i)转换为(其他.a,其他.b中的i)]

针对一般情况的解决方案(可能没有方便的“大于任何值”的解决方案,并且您不希望代码随着属性数量的增加而变得更复杂),在假定无
值的常见情况下,该解决方案仍然尽可能快地运行。它确实假设
TypeError
意味着
None
,因此,如果除了
None
之外,还可能有不匹配的类型,这会变得更加复杂,但坦率地说,像这样的类设计很难想象。这适用于具有两个或多个键的任何场景(因此
attrgetter
返回一个
元组
),只需要更改用于构造
attrgetter
的名称即可添加或删除要比较的字段

def __lt__(self, other, _key=operator.attrgetter('a', 'b')):
    # Get the keys once for both inputs efficiently (avoids repeated lookup)
    sattrs = _key(self)
    oattrs = _key(other)
    try:
        return sattrs < oattrs  # Fast path for no Nones or only paired Nones
    except TypeError:
        for sattr, oattr in zip(sattrs, oattrs):
            # Only care if exactly one is None, because until then, must be equal, or TypeError
            # wouldn't occur as we would have short-circuited
            if (sattr is None) ^ (oattr is None):
                # Exactly one is None, so if it's the right side, self is lesser
                return oattr is None
        # TypeError implied we should see a mismatch, so assert this to be sure
        # we didn't have a non-None related type mismatch
        assert False, "TypeError raised, but no None/non-None pair seen
定义(self,other,_key=operator.attrgetter('a','b')): #有效地为两个输入获取一次键(避免重复查找) sattrs=_键(自) oattrs=_键(其他) 尝试: 返回sattrs

此设计的一个有用特性是,在任何情况下,都不会对任何给定属性多次调用丰富的比较;在快速路径上的失败尝试证明了这一点(假设类型的不变量是兼容的或
None
golds)可以运行零个或多个具有相等值的属性对,然后是
None
/non-
None
不匹配。因为我们关心的一切都是已知的相等或
None
/non-
None
不匹配,所以我们不需要再次调用可能代价高昂的丰富比较,我们只需要进行廉价的身份测试来找到
N一个
/non-
None
不匹配,然后根据哪一方是
None
返回,这是我后来想到的一个完全不同的设计(单独发布,因为它非常不同,应该单独评估):

将所有属性映射到
元组
s,其中每个
元组
的第一个元素是基于属性的
None
-ness的
bool
,第二个元素是属性值本身。
None
/non-
None
不匹配会在表示
Nonebool
上短路de>-ness防止了
类型错误
,其他一切都将退回到比较好的类型:

def __lt__(self, other):
    def _key(attr):
        # Use attr is not None to make None less than everything, is None for greater
        return (attr is None, attr)
    return (_key(self.a), _key(self.b)) < (_key(other.a), _key(other.b))
def\uu lt\uuu(自身、其他):
def_键(属性):
#“使用属性”不是“无”表示“不少于一切”,而是“无”表示“更大”
返回(attr为None,attr)
返回(_键(self.a),_键(self.b))<(_键(other.a),_键(other.b))

可能比无
None
/non-
None
对出现的情况稍微慢一点,但代码要简单得多。它还有一个优点,就是当出现除
None
/non-
None
以外的不匹配类型时,它会继续引发
TypeError
s,而不是潜在的行为异常。我肯定会调用它这是我的Pythonic解决方案,即使它在普通情况下稍微慢一点。

您的代码会短路,并且会提前返回,而不会识别多个排序属性。这是有意的吗?为什么要比较每个元素,同时使用布尔值?使用两个属性的总和如何?预期的排序属性是什么两个值都为a时的顺序