Надлежащий способ наличия уникального идентификатора в Python?

Только для проявления контраста сравните следующий C++ и Java отрывки:

В C++: Примечание: Плохой код - утечки памяти! , Но это демонстрирует точку.

void cppMethod(int val, int &ref, Dog obj, Dog &objRef, Dog *objPtr, Dog *&objPtrRef)
{
    val = 7; // Modifies the copy
    ref = 7; // Modifies the original variable
    obj.SetName("obj"); // Modifies the copy of Dog passed
    objRef.SetName("objRef"); // Modifies the original Dog passed
    objPtr->SetName("objPtr"); // Modifies the original Dog pointed to 
                               // by the copy of the pointer passed.
    objPtr = new Dog("newObjPtr");  // Modifies the copy of the pointer, 
                                   // leaving the original object alone.
    objPtrRef->SetName("objRefPtr"); // Modifies the original Dog pointed to 
                                    // by the original pointer passed. 
    objPtrRef = new Dog("newObjPtrRef"); // Modifies the original pointer passed
}

int main()
{
    int a = 0;
    int b = 0;
    Dog d0 = Dog("d0");
    Dog d1 = Dog("d1");
    Dog *d2 = new Dog("d2");
    Dog *d3 = new Dog("d3");
    cppMethod(a, b, d0, d1, d2, d3);
    // a is still set to 0
    // b is now set to 7
    // d0 still have name "d0"
    // d1 now has name "objRef"
    // d2 now has name "objPtr"
    // d3 now has name "newObjPtrRef"
}

В Java,

public static void javaMethod(int val, Dog objPtr)
{
   val = 7; // Modifies the copy
   objPtr.SetName("objPtr") // Modifies the original Dog pointed to 
                            // by the copy of the pointer passed.
   objPtr = new Dog("newObjPtr");  // Modifies the copy of the pointer, 
                                  // leaving the original object alone.
}

public static void main()
{
    int a = 0;
    Dog d0 = new Dog("d0");
    javaMethod(a, d0);
    // a is still set to 0
    // d0 now has name "objPtr"
}

Java только имеет два типа передачи: значением для встроенных типов, и значением указателя для типов объектов.

6
задан tshepang 1 November 2014 в 06:30
поделиться

5 ответов

Если вы хочу объект, который ' s гарантированно уникальны и также могут быть гарантированно восстановлены с точно такой же идентификацией, если маринованные и не выбранные обратно, функции верхнего уровня, классы, экземпляры классов, и, если вы заботитесь о , является , а не == , также списки (и другие изменяемые), все в порядке. Т.е. любой из:

# 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 выиграет благодаря общности, лаконичности и легкости.

ни у кого нет особых преимуществ (в зависимости от того, заботитесь ли вы о == или просто равно ). Вероятно, def выиграет благодаря общности, лаконичности и легкости.

ни у кого нет особых преимуществ (в зависимости от того, заботитесь ли вы о == или просто равно ). Вероятно, def выиграет благодаря общности, лаконичности и легкости.

10
ответ дан 8 December 2019 в 17:23
поделиться

Вы можете определить класс Symbol для обработки START и END.

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))
2
ответ дан 8 December 2019 в 17:23
поделиться

На самом деле, мне нравится ваше решение.

Некоторое время назад я взламывал модуль 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
1
ответ дан 8 December 2019 в 17:23
поделиться

Если бы в вашем списке не было строк, я бы просто использовал «начало», «конец», поскольку Python выполняет сравнение O (1) из-за интернирования.

Если вы это делаете, нужны строки, но не кортежи, полный метод скряги таков:

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

PS: Я был уверен, что раньше в вашем списке были числа, а не строки, но я не вижу никаких изменений, поэтому я, должно быть, вообразил это

1
ответ дан 8 December 2019 в 17:23
поделиться

Я думаю, что, возможно, на этот вопрос было бы легче ответить, если бы вы более четко указали, для чего вам это нужно, но я склонен, если столкнусь с такой проблемой, будет примерно таким:

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

Плюсы этого подхода, как я его вижу

  • Ваши маркеры представляют собой строки (могут обрабатываться или иным образом легко сериализоваться, например, в JSON или БД, без каких-либо особых усилий)
  • Очень маловероятно, что они столкнутся случайно или намеренно
  • Будет сериализоваться и десериализоваться до идентичных значений даже при перезапуске процесса, что (я думаю) не будет иметь место для object () или пустого класса.

Минусы (?)

  • Каждый раз, когда их выбирают заново, они будут совершенно другими. (Я думаю, хорошо это или плохо зависит от деталей, которые вы не предоставили).
0
ответ дан 8 December 2019 в 17:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: