按类排序对象

时间:2017-10-25 16:42:26

标签: python oop

我必须为具有任意标签集的对象建模。我考虑将标签建模为对象而不仅仅是字符串,因为我希望它们有自己的行为。

例如,标签可以是:

class Jurisdiction():
    def __init__(self,name):
        self._name = name
    #(...)

class EconomicSector():
    def __init__(self,name):
        self._name = name
    #(...)

和变量(对象)可能是农业上的私人支出。我会把它表示为

obj_1 = { EconomicSector("Agriculture"), Jurisdiction("Private")}
# It should be of its own class, but a set of labels will do for now

标签可能有不同的排序,所以我想按惯例定义一个。说,管辖权在经济委员会之前:

order = [Jurisdiction, EconomicSector]

因此,当我想要表示为字符串的对象时,我会得到" Private.Agriculture"而不是" Agriculture.Private"。

问题在于要知道标签的优先级,我必须要求它的类并在类之间进行比较。这违反了OOP原则,因为对象应该是自包含的,并由它响应的消息定义。我不应该处理他们的课程。

通过比较类来获取字符串表示的示例:

obj_1_with_precedence = [(order.index(label.__class__),label) for label in obj_1]
obj_1_sorted = [label_tuple[1] for label_tuple in sorted(obj_1_with_precedence)]
obj_1_with_strings = [label._name for label in obj_1_sorted]
obj_1_as_string = ".".join(obj_1_with_strings)
print(obj_1_as_string) # 'Private.Agriculture'

有没有更好的方法来模拟这个问题,还是应该只是在对象类之间进行比较?

1 个答案:

答案 0 :(得分:0)

这就是我要做的。给每个类一个属性,定义它们应该排序的顺序,并定义丰富的比较方法来查看该属性。例如:

from functools import total_ordering

@total_ordering
class Base:
    _sort_order = None
    def __lt__(self, other):
        return self._sort_order < other._sort_order

    def __eq__(self, other):
        return self._sort_order == other._sort_order


class Jurisdiction(Base):
    _sort_order = 1

    def __init__(self,name):
        self._name = name
    #(...)


class EconomicSector(Base):
    _sort_order = 2

    def __init__(self,name):
        self._name = name
    #(...)

(如果您尝试比较 Base 的实例和它的一个子类的实例,您会得到一个错误。Base 不应该被实例化。)如果您按照它们应该排序的顺序定义类,你可以定义一个函数来自动给你下一个数字,这样你就不用手动跟踪了,例如:

_id = 0
def _next_sort_id():
    global _id
    _id += 1
    return _id

# definition of Base class

class Jurisdiction(Base):
    _sort_order = _next_sort_id()
    #(...)

class EconomicSector(Base):
    _sort_order = _next_sort_id()
    #(...)

如果你想变得更高级,你可以定义一个元类,当你定义一个新的子类时,它会自动分配下一个排序 id,然后你只需要确保你的类以正确的顺序定义并具有正确的基类。