Только для проявления контраста сравните следующий 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 только имеет два типа передачи: значением для встроенных типов, и значением указателя для типов объектов.
Если вы хочу объект, который ' 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
выиграет благодаря общности, лаконичности и легкости. Вы можете определить класс 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))
На самом деле, мне нравится ваше решение.
Некоторое время назад я взламывал модуль 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
Если бы в вашем списке не было строк, я бы просто использовал «начало», «конец», поскольку Python выполняет сравнение O (1) из-за интернирования.
Если вы это делаете, нужны строки, но не кортежи, полный метод скряги таков:
[("START",), 'foo', 'bar', 'spam', eggs', ("END",)]
PS: Я был уверен, что раньше в вашем списке были числа, а не строки, но я не вижу никаких изменений, поэтому я, должно быть, вообразил это
Я думаю, что, возможно, на этот вопрос было бы легче ответить, если бы вы более четко указали, для чего вам это нужно, но я склонен, если столкнусь с такой проблемой, будет примерно таким:
>>> START = os.urandom(16).encode('hex')
>>> END = os.urandom(16).encode('hex')
Плюсы этого подхода, как я его вижу
object ()
или пустого класса. Минусы (?)