Comments 33
nonlocal и global для модификации переменных на один уровень выше
не на один уровень выше, а ближайший выше, исключая глобальную
такой код <> приводит к тому, что переменные x и y ссылаются на различные данные, а такой <> нетМожет потому что в первом случае вы присваиваете значение переменной(==ссылке) повторно, а во втором э… нет? Ничего себе идентичные ситуации. Причём тут вообще мутабельность?
Почти, но не всегда.
Мутабельные элементы, типа списка, да передаются по ссылке.
А иммутабельные, например строка, передаются по значению.
Такая вот гибридная система.
А насчет многопоточности.
В multiprocessing есть потоки, а есть процессы.
У каждого свое применение.
Для задач io лучше применять потоки, а для cpu вычислений лучше работают процессы.
А иммутабельные, например строка, передаются по значению.
Нет, строки тоже передаются по ссылке, это элементарно проверяется с помощью is
или id()
в CPython
В python все есть объекты, даже простые числа, например 1 — это тоже объект. А переменные не хранят никаких значений, python связывает их с объектами, точнее хранят ссылку на объект.
Поэтому когда вы передаете строку в функцию, передается сам объект.
Например:
mylist = [1, 2]
def func(x):
x.append(3)
print(mylist) # [1, 2, 3]
s = 'stroka_1'
def func2(x):
x = 'stroka_2'
print(s) # stroka_1
Может несколько сумбурно объяснил, но почитайте про объекты в python. На эту тему очень много публикаций.
это не из-за того, что переменная передалась по ссылке.
Я не просто так упомянул CPython — в нём реализация id()
для большинства объектов такова, что она возвращает именно что адрес в памяти, то есть по сути значение ссылки. Которая одинаковая, да.
Поэтому когда вы передаете строку в функцию, передается сам объект.
Когда я передаю строку в функцию, она принимает ссылку на объект. На тот же самый объект. Переменная — это по сути ссылка с именем. Разные переменные могут ссылаться на один и тот же объект.
Когда вы пишете x = чтототам
, вы меняете ссылку у переменной, но совершенно никак не трогаете сами объекты. Так же вы не трогаете все остальные переменные, которые ссылаются на этот объект — вы просто меняете значение этой одной переменной, и больше ничего.
Вы сами-то свой код запускали? Мало того что вы забыли вызвать функции, так даже после их вызова код будет вести себя совершенно не так, как вы показали. Вам стоит подтянуть основы питона.
Вы конечно правы, и я с вами согласен что передаются ссылки на объекты. Вот только статья называется Что нужно запомнить программисту, переходящему на Python. Ключевое слово переходящему с других языков. Такая система с объектами, что переменные не хранят никаких значений кроме ссылок на объекты вот и вводит в путаность переходящих.
Например, в C++ переменная является именованной областью памяти, хранящей значение. Поэтому передача переменной по ссылки в функцию подразумевает передачу ссылки именно на переменную, значение которой потом в функции можно изменить. В python же передается значение переменной, то есть непосредственно ссылка на объект. Из-за чего и возникает вопрос как переменные передаются в функцию, по значению или по ссылке.
Наверно хорошо сказали тут:
jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither
Я в первом своем комментарии неправильно выразился, надо было написать, что если сравнивать с языками по типу C/C++.
А иммутабельные, например строка, передаются по значению.
Иммутабельность тут ни при чем. Все передается по ссылке.
>>> s = 'abc' * 1024 * 1024
>>> id(s)
2381293081856
>>> def foo(s):
... return id(s)
...
>>> foo(s)
2381293081856
в реальной жизни ключом может быть только число или строкаКортеж координат как ключ тоже вполне востребованное решение, когда мы описываем объекты на игровой доске, например.
А вообще вопрос про ключи словаря он на понимание хешируемости, там есть не совсем очевидные вещи, когда (1, 2) — допустимый ключ, а (1, [2]) — нет, хотя оба являются кортежем!
a = (1, [2, 3], 4)
print(type(a)) # <type 'tuple'>
b = {a: 1} # TypeError: unhashable type: 'list'
однако нельзя затереть исходную ссылку в функции:В Вашем примере создалась новая локальная переменная внутри функции, из функции она сама не вернется если нет присвоения при вызове функции (последний мой пример).
def try_del(mylist): mylist = [] return mylist mylist = [1,2] try_del(mylist) print(mylist)
Можно так, даже без возврата обнулить коллекцию по ссылке:
def try_del(mylist):
mylist.clear()
mylist = [1,2]
try_del(mylist)
print(mylist) # []
А если Вы хотите возвращаемое из функции значение, нужно обязательно присвоить переменной, «в никуда» оно не вернется.
def try_del(mylist):
mylist = [4, 5]
return mylist
mylist = [1,2]
mylist = try_del(mylist)
print(mylist) # [4, 5]
в какой-то момент перл исчерпал себя
Это как? Надоело писать доллары перед именами скалярных переменных?
А если серьёзно, чего не хватило в перле, из-за чего вы перешли на питон?
Ну и перл просто умер, это и скучно (поддержка легаси кода) и сужает пространство возможностей во всем смыслах — поди найди работу на перле с каким-нибудь машинным обучением, или захочешь релоцироваться в другую страну, а там ни одной вакансии на перле.
Открыл некоторые вещи незнание которых было бомбой замедленного действия — например про ссылки, формально знал об этом, но так как в основном поведение было как у переменных — бдительность усыпило
Про деление с остатком/целой частью не совсем верно, по факту в питоне знак определяется по делителю, а не по делимому как в си например, то есть если вы будите делить например 7%-3 как в математике у вас будет 7=-3*2+1
А в питоне будет -2.
https://en.wikipedia.org/wiki/Modulo_operation
Здесь довольно хорошая картинка поясняющая суть.
Given two positive numbers, a (the dividend) and n (the divisor), a modulo n (abbreviated as a mod n) is the remainder of the Euclidean division of a by n.
…
The range of numbers for an integer modulo of n is 0 to n − 1
…
In mathematics, the result of the modulo operation is the remainder of the Euclidean division.
Если этого недостаточно, то вот ещё:
Given two integers a and b, with b ≠ 0, there exist unique integers q and r such that
a = bq + r
and
0 ≤ r < |b|,
Т.е. по математическому определению, остаток должен быть положительным, и понятное дело должно выполняться равенство и питон как раз и реализует это поведение — остаток всегда положительный и равенство выполняется, что и должен делать высокоуровневый язык.
$ python3 Python 3.5.3 (default, Jan 19 2017, 14:11:04) [GCC 6.3.0 20170118] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import math >>> print(-14 % -3) -2 >>> print(math.fmod(-14,-3)) -2.0
и питон как раз и реализует это поведение — остаток всегда положительный и равенство выполняется, что и должен делать высокоуровневый язык.Ужос сколько пафоса. А проверять — не пробовали? Это куда меньше времени бы заняло, чем написание простыней в комментариях…
Мне казалось, что времена Аристотеля, который писал трактаты на тему количества ног у мухи, вместо того, чтобы взять — и их посчитать… таки прошли… но похоже, что нет.
Что нужно запомнить программисту, переходящему на Python