Если вы пришли из C или C ++ фона, то, вероятно, проще объяснить, что все переменные в Python действительно являются указателями.Таким образом, оператор
a = 1
действительно примерно похож на
Object *a = new Integer(1);
. Оператор is
проверяет равенство указателей, а оператор ==
вместо этого включает вычисления, которые зависят от типа.объектов.
Небольшое усложнение этой схемы состоит в том, что если объекты являются неизменяемыми (например, целое число), то из соображений эффективности приведенный выше код действительно немного больше похож на
int *a = getFromCacheOrCreateNewInteger(1);
, поэтомуиногда (но это деталь реализации) неизменяемые объекты могут быть одним и тем же объектом для is
, даже если они созданы независимо с логической точки зрения (например, это может быть 1+1 is 2-1
, но без гарантий):
>>> 1+2 is 2+1
True
>>> 99999+1 is 1+99999
False
>>>
Чтобы добавить еще больше недоразумений, нужно сказать, что даже если переменные alla в Python действительно являются указателями, довольно удивительно, что в Python нет концепции указателя, другими словами, нет способа передать функцию, в которой из ваших переменных что-тодолжны быть сохранены.
Для этого вам нужно либо передать имя (если переменная является глобальной), либо передатьвызывающая функция (если переменная является локальной).Это на самом деле не является большим раздражением, так как в большинстве случаев вам просто нужно несколько возвращаемых значений, и это уже хорошо обрабатывается Python:
def foo(x):
return x+1, x-1
a, b = foo(12)
Еще одно дополнительное раздражение заключается в том, что если вам действительно нужно передать установщик дляЛокальная переменная без имени (например, элемент списка) не может быть анонимной lambda
, поскольку присваивание является оператором , а lambda
допускается только одно выражение .Однако вы можете определить локальные функции для этого ...
def foo(x, setter):
setter(x + 1)
def bar():
mylocal = [1,2,3]
def setFirst(value):
mylocal[0] = value
foo(32, setFirst)
(ОК. Я соврал ... действительно возможно использовать lambda value: mylocal.__setitem__(0, value)
, но это более или менее нежелательный инцидент; lambda
- этонастолько ненавистный в Python, что, вероятно, когда они обнаружат, что это возможно, в язык будет добавлено еще одно ограничение, запрещающее это ;-)).
Если вы хотите изменить именованный локальный код, это просто невозможно в Python 2.x (но возможно с Python 3.x и nonlocal
).
По вопросу о том, когда выполняются копии и когда вместо этого копируется только указатель, ответ очень прост.Python никогда не делает копию автоматически ... если вы хотите сделать копию, вы должны явно сделать это самостоятельно.Вот почему, например, часто можно увидеть код, подобный следующему:
class Polygon:
def __init__(pointlist):
self.pointlist = pointlist[:]
Здесь обозначение [:]
означает, что экземпляр класса хочет сохранить копию переданного списка, так что есливы создаете экземпляр Polygon
со списком точек, а затем модифицируете этот список, тогда геометрия не меняется.