Pergunta

Basicamente, eu tenho uma lista como: [START, 'foo', 'bar', 'spam', eggs', END] eo START / identificadores finais são necessárias para mais tarde para que eu possa comparar mais tarde. Agora, eu tenho que configurar como esta:

START = object()
END = object()

Esta multa funciona, mas sofre com o problema de não trabalhar com decapagem. Eu tentei fazê-lo da seguinte maneira, mas parece que um método terrível de fazer isso:

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

poderia compartilhar qualquer um melhor meio de fazer isso? Além disso, o exemplo que eu tenha configurado acima é apenas uma simplificação de um problema diferente.

Foi útil?

Solução

Se você quer um objeto que está garantido para ser único e pode também ser garantido para se restaurado para exatamente o mesmo identificar se para trás, funções de nível superior, classes, instâncias de classe em conserva e unpickled certas, e se você se preocupa com is em vez de == também listas (e outros mutables), são todos muito bem. Ou seja, qualquer um:

# 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()

Nenhum destes é terrível, nenhum tem qualquer vantagem especial (dependendo se você se preocupa == ou apenas is). vitórias provavelmente def por força de generalidade, concisão, e mais leve.

Outras dicas

Você pode definir uma classe Symbol para lidar com início e fim.

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))

Na verdade, eu como sua solução.

Um tempo atrás eu estava cortando em um módulo Python, e eu queria ter um valor mágico especial que não poderia aparecer em qualquer outro lugar. Passei algum tempo pensando sobre isso e o melhor que eu vim com é o mesmo truque que você usou:. Declarar uma classe, e usar o objeto de classe como o valor mágico especial

Quando você está verificando para o Sentinel, você deve, naturalmente, utilizar o operador is, para a identidade do objeto:

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

Se a lista não tem cordas, eu tinha acabado de usar o "start", "fim", como Python faz a comparação O (1), devido a internar.

Se você fizer cordas precisa, mas não tuplas, o método cheapskate completa é a seguinte:

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

PS: Eu tinha certeza de sua lista estava números antes, nem cordas, mas eu não consigo ver quaisquer revisões então eu devo ter imaginado

Eu acho que talvez isso seria mais fácil de responder se você fosse mais explícito sobre o que você precisa disso para, mas a minha inclinação se depara com um problema como este seria algo como:

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

Pros desta abordagem, como eu estou vendo

  • Seus marcadores são strings (pode picles ou de outra forma facilmente serialize, por exemplo, para JSON ou um DB, sem qualquer esforço especial)
  • Muito pouco provável que colidem acidentalmente ou de propósito
  • Será serializar e desserializar para valores idênticos, mesmo através de processo é reiniciado, o que (eu acho) não seria o caso para object() ou uma classe vazia.

Contras (?)

  • Cada vez que eles são recém-escolhido que será completamente diferente. (Este ser bom ou ruim depende de detalhes que você não ter fornecido, eu acho).
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top