ещё можно положить в стек ссылку на переменную, которую мы передаём в функцию.
Именно это я и имел ввиду, когда писал
положить ссылку на объект в динамической памяти (или на более высоких уровнях стека).
не понял, о чем речь — на стеке значение переменной?
Мы создали переменную, например int32, где-то (на стеке или в памяти), при вызове ф-ции мы можем положить на стек само значение int32, или ссылку на него в памяти (или верхнем уровне стека), соответственно от этого зависит, увидим мы или нет изменения переменной по выходу из функции.
уточните, пожалуйста, от какого именно механизма отказались
Весь комментарий про это, внизу есть ссылки, или вас интересует реализация?
Если вкратце там словарь (имя переменной: ссылка на объект). ideone.com/LPrD5j
Вчера тупил интернет, не получилось вставить этот комментарий в тред, а сегодня все его игнорируют, может здесь он позаметнее будет. :)
Текст статьи тоже изменил.
Возможно, я не совсем понятно объяснил, что ж, попытаюсь быть понятнее.
В таких языках как C++ есть переменные, хранящиеся на стеке и в динамической памяти. При вызове ф-ции мы помещаем все аргументы на стек, после чего передаём управление ф-ции. Ф-ция знает размеры и смещения переменных на стеке, соответственно может их правильно интерпретировать.
При этом у нас есть два варианта: скопировать на стек память переменной или положить ссылку на объект в динамической памяти (или на более высоких уровнях стека).
Очевидно, что при изменении значений на стеке ф-ции, значения в динамической памяти не поменяются, а при изменении области памяти по ссылке, мы модифицируем общую память, соответственно все ссылки на эту же область памяти «увидят» новое значение.
В python отказались от подобного механизма, заменой служит механизм связывания(assignment) имени переменной с объектом, например при создании переменной:
var = "john"
Интерпретатор создаёт объект «john» и «имя» var, а потом связывает объект с данным именем.
При вызове ф-ции, новых объектов не создаётся, вместо этого в области видимости ф-ции создаётся имя, которое связывается с существующим объектом.
Но в python есть изменяемые и неизменяемые типы. К первым, например, относятся числа: при арифметических операциях существующие объекты не меняются, а создаётся новый объект с соответствующим значением, с которым потом связывается существующее имя. Если же со старым объектом после этого не связано ни одного имени, оно будет удалено с помощью механизма подсчёта ссылок.
Если же имя связано с переменной изменяемого типа, то при операциях с ней изменяется память объекта, соответственно все имена, связанные с данной областью памяти «увидят» изменения.
Можно почитать про это в документации, более подробно изложенно здесь.
Честно говоря, не знаю, введено ли подобное поведение в спецификацию языка или является особенностью реализации CPython. Но многие языки явно требуют наличие подобного механизма. Например.
Вот здесь небольшой список, где ещё это поведение является стандартом.
Если мне не изменяет память, в Delphi, Java и C# так же.
даже после удаления всех объектов класса вся коллекция остается в памяти со всеми аттрибутами, созданными для каждого объекта.
Не удаляйте объекты. :)
А если серьёзно, то и так сложно придумать пример, когда такое может быть полезно (вот для форм или эмуляции физических систем), вряд ли мы захотим удалять такие объекты, а если и захотим, то удалять скорее всего будем с помощью метода класса.
Я бы вообще переменные отдельных экземпляров не хранил в таких случаях:
def init_system():
Class(1)
Class(2)
Class(3)
Но метод потенциально опасный, нужно весьма аккуратно подходить к подобным реализациям.
Не совсем понимаю, каким образом.
И изначальная идея сферических объектов в памяти, которые обмениваются сообщениями и сами решают, когда им сообщение обработать и в какое состояние перейти, тоже довольно далековата от чего-то хранящее методы и переменные, которые может дёргать любой дурак.
Какого принципа? Инкапсуляции? Как уже было сказано, этот принцип нарушается и в хвост, и в гриву.
И как можно быть не объектно-ориентируемым, но поддерживать создание классов и объектов?)
Вообще существует множество видений ООП, и видение Java, насколько я могу судить, ни чуть не ближе к Smalltalk, чем python и Java между собой.
Ну с точки зрения математики умножение на скаляр N — это сложение объекта с самим собой N раз. Вот python и складывает строку саму с собой 2 раза, со списками и кортежами так тоже можно.
Спасибо, я именно это и хотел сказать, но у вас получилось понятнее.
Про __slots__ думал в следующих статьях написать, но пока не придумал, как это получше сделать, наверно, стоило прямо здесь и сказать сразу после примера с добавлением полей, но по хорошему, надо ещё и механизм, как это обеспечивается описать, а я пока не разбирался.
В предыдущей статье приводились подобные примеры, пожалуй, не соглашусь, типизация строгая, просто тяжёлое наследство в виде отсутствия выделенного булевого типа при создании языка и решение создать его как класс, наследуемый от целых чисел привёл к таким последствиям.
Я вам даже больше скажу, изначально там именно так и было, только при предфинальной вычитке заметил, была даже идея, поставить там строчную «Р», но вы правы, оба слова подходят.
Без оценки статестической значимости пост смотрится пустенько, как-то я уже отвык верить статистическим отчётам без неё.
Результаты опроса были сопоставлены с результатами аналогичного опроса апреля 2017 года. Был сделан вывод, что самая распространенная зарплата за 1.5 года не изменилась, при этом по сравнению с 2017-04, к 2018-08 уменьшилось количество людей с зарплатой 80 тысяч рублей, увеличилось количество людей с зарплатой 60 тысяч рублей, уменьшилось количество людей с зарплатой 40 тысяч рублей, увеличилось количество людей с зарплатой 20 тысяч рублей.
По хорошему, после каждого такого утверждение должно идти p-value в скобках с поправкой на множественные сравнения.
Но начало хорошее, продолжайте, только выборки больше делайте.
Основная суть такая: если после звёздочки идёт имя — то все неименованные позиционные аргументы будут упакованы в кортеж с таким именем, если вы ничего дополнительно не указали, то кортеж будет пустой, а просто звёздочка запрещает передачу дополнительные параметров.
В вашем примере вы должны будете вызывать ф-цию именно так, вы её и вызвали, то есть передав первый аргумент по ключу или без него и второй только без ключа, если передать только один параметр или передать три, то программа упадёт.
Я учил python, наверно, языком 8. Просто гуглив синтаксические конструкции, согласен, лучше учить язык по хорошим учебникам или записям лекций, но иногда тебе просто надо сдать курсач через неделю\ты изменил место работы\перекинули на другой проект\решили, написать вспомогательную часть текущего на python.
Собственно статья для тех, у кого нет недели на чтение книги, но есть время на чтение статейки другой.
Но материала ещё много, надеюсь в последующих статьях вы тоже узнаете что-то новое.
Именно это я и имел ввиду, когда писал
Мы создали переменную, например int32, где-то (на стеке или в памяти), при вызове ф-ции мы можем положить на стек само значение int32, или ссылку на него в памяти (или верхнем уровне стека), соответственно от этого зависит, увидим мы или нет изменения переменной по выходу из функции.
Весь комментарий про это, внизу есть ссылки, или вас интересует реализация?
Если вкратце там словарь (имя переменной: ссылка на объект).
ideone.com/LPrD5j
Текст статьи тоже изменил.
Изменила, в Java и C# коллекции, поддерживающие CoW, вынесены в отдельные пакеты.
В таких языках как C++ есть переменные, хранящиеся на стеке и в динамической памяти. При вызове ф-ции мы помещаем все аргументы на стек, после чего передаём управление ф-ции. Ф-ция знает размеры и смещения переменных на стеке, соответственно может их правильно интерпретировать.
При этом у нас есть два варианта: скопировать на стек память переменной или положить ссылку на объект в динамической памяти (или на более высоких уровнях стека).
Очевидно, что при изменении значений на стеке ф-ции, значения в динамической памяти не поменяются, а при изменении области памяти по ссылке, мы модифицируем общую память, соответственно все ссылки на эту же область памяти «увидят» новое значение.
В python отказались от подобного механизма, заменой служит механизм связывания(assignment) имени переменной с объектом, например при создании переменной:
Интерпретатор создаёт объект «john» и «имя» var, а потом связывает объект с данным именем.
При вызове ф-ции, новых объектов не создаётся, вместо этого в области видимости ф-ции создаётся имя, которое связывается с существующим объектом.
Но в python есть изменяемые и неизменяемые типы. К первым, например, относятся числа: при арифметических операциях существующие объекты не меняются, а создаётся новый объект с соответствующим значением, с которым потом связывается существующее имя. Если же со старым объектом после этого не связано ни одного имени, оно будет удалено с помощью механизма подсчёта ссылок.
Если же имя связано с переменной изменяемого типа, то при операциях с ней изменяется память объекта, соответственно все имена, связанные с данной областью памяти «увидят» изменения.
Можно почитать про это в документации, более подробно изложенно здесь.
Вот здесь небольшой список, где ещё это поведение является стандартом.
Если мне не изменяет память, в Delphi, Java и C# так же.
Не удаляйте объекты. :)
А если серьёзно, то и так сложно придумать пример, когда такое может быть полезно (вот для форм или эмуляции физических систем), вряд ли мы захотим удалять такие объекты, а если и захотим, то удалять скорее всего будем с помощью метода класса.
Я бы вообще переменные отдельных экземпляров не хранил в таких случаях:
Но метод потенциально опасный, нужно весьма аккуратно подходить к подобным реализациям.
И изначальная идея сферических объектов в памяти, которые обмениваются сообщениями и сами решают, когда им сообщение обработать и в какое состояние перейти, тоже довольно далековата от чего-то хранящее методы и переменные, которые может дёргать любой дурак.
И как можно быть не объектно-ориентируемым, но поддерживать создание классов и объектов?)
Вообще существует множество видений ООП, и видение Java, насколько я могу судить, ни чуть не ближе к Smalltalk, чем python и Java между собой.
Про __slots__ думал в следующих статьях написать, но пока не придумал, как это получше сделать, наверно, стоило прямо здесь и сказать сразу после примера с добавлением полей, но по хорошему, надо ещё и механизм, как это обеспечивается описать, а я пока не разбирался.
В предыдущей статье приводились подобные примеры, пожалуй, не соглашусь, типизация строгая, просто тяжёлое наследство в виде отсутствия выделенного булевого типа при создании языка и решение создать его как класс, наследуемый от целых чисел привёл к таким последствиям.
По хорошему, после каждого такого утверждение должно идти p-value в скобках с поправкой на множественные сравнения.
Но начало хорошее, продолжайте, только выборки больше делайте.
В вашем примере вы должны будете вызывать ф-цию именно так, вы её и вызвали, то есть передав первый аргумент по ключу или без него и второй только без ключа, если передать только один параметр или передать три, то программа упадёт.
Собственно статья для тех, у кого нет недели на чтение книги, но есть время на чтение статейки другой.
Но материала ещё много, надеюсь в последующих статьях вы тоже узнаете что-то новое.