代码之家  ›  专栏  ›  技术社区  ›  Evan Fosmark

在Python中拥有唯一标识符的正确方法?

  •  6
  • Evan Fosmark  · 技术社区  · 16 年前

    [START, 'foo', 'bar', 'spam', eggs', END]

    START = object()
    END = object()
    

    class START(object):pass
    class END(object):pass
    

    5 回复  |  直到 11 年前
        1
  •  10
  •   Alex Martelli    16 年前

    如果你想要一个保证唯一的对象 is 而非 == 列表(和其他变量)都很好。即:

    # work for == as well as is
    class START(object): pass
    def START(): pass
    class Whatever(object): pass
    START = Whatever()
    
    # if you don't care for "accidental" == and only check with `is`
    START = []
    START = {}
    START = set()
    

    这些都不可怕,也没有任何特别的优势(取决于你是否关心 == 或者只是 ).可能 def 凭借通用性、简洁性和重量轻而获胜。

        2
  •  2
  •   Anand Chitipothu    16 年前

    您可以定义 Symbol 处理开始和结束的类。

    class Symbol:
        def __init__(self, value):
            self.value = value
    
        def __eq__(self, other):
            return isinstance(other, Symbol) and other.value == self.value
    
        def __repr__(self):
            return "<sym: %r>" % self.value
    
        def __str__(self):
            return str(self.value)
    
    START = Symbol("START")
    END = Symbol("END")
    
    # test pickle
    import pickle
    assert START == pickle.loads(pickle.dumps(START))
    assert END == pickle.loads(pickle.dumps(END))
    
        3
  •  1
  •   steveha    16 年前

    事实上,我喜欢你的解决方案。

    不久前,我正在开发一个Python模块,我想有一个特殊的神奇值,它不能出现在其他任何地方。我花了一些时间思考它,我想出的最好的办法就是你使用的同样的技巧:声明一个类,并将类对象用作特殊的魔法值。

    当你检查哨兵时,你当然应该使用 is 运算符,用于对象标识:

    for x in my_list:
        if x is START:
            # handle start of list
        elif x is END:
            # handle end of list
        else:
            # handle item from list
    
        4
  •  1
  •   Chillar Anand    11 年前

    如果你的列表没有字符串,我只会使用“start”、“end”,因为Python由于实习而将比较结果设为O(1)。

    如果你确实需要字符串,但不需要元组,完整的廉价方法是:

    [("START",), 'foo', 'bar', 'spam', eggs', ("END",)]
    

    PS:我以前肯定你的清单是数字,不是字符串,但我看不到任何修改,所以我一定是想象出来的

        5
  •  0
  •   Jack Lloyd    16 年前

    我认为,如果你能更明确地说明你需要这个的原因,也许这会更容易回答,但如果面临这样的问题,我的倾向是:

    >>> START = os.urandom(16).encode('hex')
    >>> END = os.urandom(16).encode('hex')
    

    在我看来,这种方法的优点

    • 你的标记是字符串(可以pickle或以其他方式轻松序列化,例如序列化为JSON或DB,无需任何特殊努力)
    • 不太可能意外或故意碰撞
    • 将序列化和反序列化为相同的值,即使在进程重启时也是如此,但(我认为)情况并非如此 object() 或者一个空的班级。

    缺点(?)