Программирование на Python

Оператор присваивания

Разбить на страницы
Показывать лекцию целиком

Проект для лекции Lecture3.rar.

Прежде чем перейти к рассмотрению операторов языка Python, напомним особенности Python, связанные с объектами и их именами.

Объекты и имена

Объекты простых типов принято называть переменными. В типизированных языках программирования переменную обычно определяют как тройку: имя, тип, значение. Имя и тип переменной определяется в момент объявления переменной и объявление должно предшествовать выполнению любых действий над переменной - действиям над значением переменной. Первоначальное значение часто может быть задано при инициализации переменной в момент ее объявления. Важно то, что переменная, получив тип при ее объявлении не может изменить этот тип. Благодаря этому возможен статический контроль типов, выявляющий множество ошибок еще на этапе компиляции программы, а не в момент выполнения, когда пользователь не в состоянии исправить ошибку.

В языке Python концепция другая. Здесь вообще нет объявлений переменных в привычном для классических языков программирования понимании, когда имя, имеющее тип, появляется раньше, чем объект, связываемый с этим именем. В Python пока нет объекта, нет и имени. Вначале рождается ребенок, затем ему дается имя. Имя рассматривается как не типизированная ссылка, которая может быть связана с объектом любого типа. В любой момент имя может быть связано с другим объектом и, соответственно, получает другой тип.

Тем, кто предпочитает строго типизированные языки, и кому концепция Python не кажется привлекательной, (я сам отношусь к таким людям) могут и на Python писать программы в типизированном стиле. Объявления переменных задавать в виде комментария, один раз присвоив переменной значение типа T, заданного в объявлении, все изменения значения этой переменной выполнять так, чтобы гарантированно сохранялся заданный тип T. К сожалению, вся ответственность за соблюдение этих правил ложится на программиста и не поддерживается компилятором (интерпретатором) языка Python.

Модули и операторы

Программа на Python состоит из модулей, каждый из которых может быть запущен на выполнение. Модуль содержит операторы, выполняемые последовательно в порядке следования текста модуля. В стиле Python каждая строка текста содержит один простой оператор - присваивания и вызова. Сложные операторы - цикла и выбора занимают несколько строк. Заголовок этих операторов занимает отдельную строку, заканчивающуюся двоеточием.

Стремясь упростить синтаксическую структуру записи операторов, при записи операторов опускаются привычные скобки, отмечающие начало и конец булевских выражений в записи if и while, скобки, задающие начало и конец составного оператора. Структура сложных операторов формируется за счет отступов в записи сложного оператора. Подряд идущие операторы, имеющие один и тот же отступ, представляют один составной оператор. Изменение отступа означает переход на другой уровень.

Подробности особенностей синтаксиса в записи операторов Python рассмотрим при описании операторов.

Оператор присваивания в языке Python

Оператор присваивания - один из основных операторов языка. Синтаксис и семантика этого оператора в его основной форме просты, интуитивно понятны, соответствуют классике.

Основная форма оператора присваивания синтаксически выглядит так:

<имя> = <выражение>

Семантически также все просто. Если выражение вычисляется без ошибок, то оно задает некоторый объект, имеющий фиксированный тип. При выполнении присваивания имя связывается с данным объектом и будет иметь его тип. Эта связь сохраняется до тех пор, пока этому имени не будет присвоено другое значение.

Присваивание в Python - это ссылочное присваивание.

Пример нескольких простых присваиваний:

def test1():
    #простое присваивание: <имя> = <выражение>
    j = 7
    d = 7.5
    k = ('one', 'two')
    p = [1, [3, 5]]
    s = {2:'two', 'two':2 }
    print ('j = ', j); print ('d = ', d); print ('k = ', k);
    print ('p = ', p); print ('s = ', s);
    k1 = k[1]
    p[1] = [3, 5, 7]
    s1 = s[2]
    print ("k1 = ", k1); print ("p = ", p); print ("s1 = ", s1)
test1()

Результаты выполнения:

Множественное присваивание

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

<имя > = <имя > = … = <выражение>

Выражение задает некоторый объект, каждое имя связывается с этим объектом. Имена являются псевдонимами объекта - разными именами одного объекта.

Пример:

def test2():
    #присваивание: <имя > = <имя > = ... = <выражение>
    #ссылки на один объект
    a = b = c = [55]
    print('a = ', a, 'b = ', b, 'c = ', c)
    a.append(66) 
    print('a = ', a, 'b = ', b, 'c = ', c)
test2()

Результат работы:

В следующем варианте множественного присваивания имена из списка имен связываются с объектами из заданного списка выражений.

<список имен> = <список выражений>

В левой части оператора задаются имена, разделенные запятой, в правой - выражения, также разделенные запятой. Понятно, что число элементов в каждом списке должно совпадать. Семантика вычислений не очевидна и может быть разной. В данном случае применяется семантика параллельного присваивания, когда, независимо вычисляются выражения в правой части, а потом параллельно происходит связывание имен списка и объектов списка. Такая семантика позволяет просто описать часто возникающую в программировании ситуацию обмена значениями двух переменных.

Примеры множественного присваивания:

def test3():
    #присваивание: <n имен> = <n выражений>
    #семантика = параллельное присваивание 
    p, s = 5, 7
    p, s = s, p     #обмен значениями
    print ('p = ', p); print ('s = ', s);
    x, y = ['a', 'b'], ['c', 'd']
    print ('x = ', x); print ('y = ', y);
    x, y = x + y, x
    print ('x = ', x); print ('y = ', y);
test3()

Результаты вычислений:

Следующий вариант синтаксиса множественного присваивания имеет вид:

<список n имен > = < выражение>

В этом варианте выражение правой части должно быть сложного типа - список, кортеж, словарь, строка. Объект, заданный выражением правой части, должен иметь n элементов. Если условия выполняются, то семантика присваивания понятна, - каждое имя из списка левой части связывается с соответствующим элементом объекта, заданного правой частью.

Пример:

def test4():
    #присваивание: <n имен> = <выражение, задающее объект из n элементов>
    x, y, z = ['one', [2, 3], 4]
    print ('x = ', x); print ('y = ', y); print ('z = ', z)
    w1, w2, w3 = "VBA"
    print ('w1 = ', w1); print ('w2 = ', w2); print ('w3 = ', w3)
    p1,p2,p3 = {1:"one", 2:"two", 3:"three"}
    print ('p1 = ', p1); print ('p2 = ', p2); print ('p3 = ', p3)
test4()

Результаты работы:

В следующем варианте присваивания объект, задающий правую часть, может иметь больше элементов, чем список имен, при условии, что список имен левой части содержит одно имя, сопровождаемое символом *. В этом случае обычные имена получают соответствующие значения, а оставшаяся часть элементов объекта, задающего выражение, связывается с именем, отмеченным звездочкой.

Пример:

def test5():
    #присваивание: <n имен, включая имя со звездочкой> = 
    #<выражение, задающее объект, с числом элементов >= n>
    x, *y, z = ['one', [2, 3], 4, 'five']
    print ('x = ', x); print ('y = ', y); print ('z = ', z)
test5()

Результаты работы:

Присваивание, изменяющее объект

Для присваивания, изменяющего объект, может использоваться краткая форма в стиле языка C++. В этом случае знаку присваивания предшествует знак операции, применяемой к объекту. Соответствующие знаки операций перегружены и зависят от типа объекта, к которому они применяются. Чаще всего такое присваивание применяется к объектам арифметического типа, так что семантика присваивания в таких случаях вполне понятна.

Пример:

def test6():
    #Присваивание в стиле С++, изменяющее объект
    x = 6; print(x)
    x += 3;  print(x)
    x //= 3;  print(x)
    x *= 5;  print(x)
test6()

Результаты работы:

Приведем несколько примеров работы с объектами сложных типов:

def test7():
    t = "текст"; print(t)
    t += " сказки"; print(t)
    s = ['C#']; print(s)
    s += [' Python ']; print(s)
    s *= 2; print(s)
    c = ('C#'); print(c)
    c += (' Python '); print(c)
    c *= 2; print(c)
    d = {'C#':" СиШарп "}; print(d)
    #d += {' Python ': " Питон "}; print(d)
    #d *= 2; print(d)
test7()

Результаты работы:

Страницы:

Проект для лекции Lecture3.rar.

Прежде чем перейти к рассмотрению операторов языка Python, напомним особенности Python, связанные с объектами и их именами.

Объекты и имена

Объекты простых типов принято называть переменными. В типизированных языках программирования переменную обычно определяют как тройку: имя, тип, значение. Имя и тип переменной определяется в момент объявления переменной и объявление должно предшествовать выполнению любых действий над переменной - действиям над значением переменной. Первоначальное значение часто может быть задано при инициализации переменной в момент ее объявления. Важно то, что переменная, получив тип при ее объявлении не может изменить этот тип. Благодаря этому возможен статический контроль типов, выявляющий множество ошибок еще на этапе компиляции программы, а не в момент выполнения, когда пользователь не в состоянии исправить ошибку.

В языке Python концепция другая. Здесь вообще нет объявлений переменных в привычном для классических языков программирования понимании, когда имя, имеющее тип, появляется раньше, чем объект, связываемый с этим именем. В Python пока нет объекта, нет и имени. Вначале рождается ребенок, затем ему дается имя. Имя рассматривается как не типизированная ссылка, которая может быть связана с объектом любого типа. В любой момент имя может быть связано с другим объектом и, соответственно, получает другой тип.

Тем, кто предпочитает строго типизированные языки, и кому концепция Python не кажется привлекательной, (я сам отношусь к таким людям) могут и на Python писать программы в типизированном стиле. Объявления переменных задавать в виде комментария, один раз присвоив переменной значение типа T, заданного в объявлении, все изменения значения этой переменной выполнять так, чтобы гарантированно сохранялся заданный тип T. К сожалению, вся ответственность за соблюдение этих правил ложится на программиста и не поддерживается компилятором (интерпретатором) языка Python.

Модули и операторы

Программа на Python состоит из модулей, каждый из которых может быть запущен на выполнение. Модуль содержит операторы, выполняемые последовательно в порядке следования текста модуля. В стиле Python каждая строка текста содержит один простой оператор - присваивания и вызова. Сложные операторы - цикла и выбора занимают несколько строк. Заголовок этих операторов занимает отдельную строку, заканчивающуюся двоеточием.

Стремясь упростить синтаксическую структуру записи операторов, при записи операторов опускаются привычные скобки, отмечающие начало и конец булевских выражений в записи if и while, скобки, задающие начало и конец составного оператора. Структура сложных операторов формируется за счет отступов в записи сложного оператора. Подряд идущие операторы, имеющие один и тот же отступ, представляют один составной оператор. Изменение отступа означает переход на другой уровень.

Подробности особенностей синтаксиса в записи операторов Python рассмотрим при описании операторов.

Оператор присваивания в языке Python

Оператор присваивания - один из основных операторов языка. Синтаксис и семантика этого оператора в его основной форме просты, интуитивно понятны, соответствуют классике.

Основная форма оператора присваивания синтаксически выглядит так:

<имя> = <выражение>

Семантически также все просто. Если выражение вычисляется без ошибок, то оно задает некоторый объект, имеющий фиксированный тип. При выполнении присваивания имя связывается с данным объектом и будет иметь его тип. Эта связь сохраняется до тех пор, пока этому имени не будет присвоено другое значение.

Присваивание в Python - это ссылочное присваивание.

Пример нескольких простых присваиваний:

def test1():
    #простое присваивание: <имя> = <выражение>
    j = 7
    d = 7.5
    k = ('one', 'two')
    p = [1, [3, 5]]
    s = {2:'two', 'two':2 }
    print ('j = ', j); print ('d = ', d); print ('k = ', k);
    print ('p = ', p); print ('s = ', s);
    k1 = k[1]
    p[1] = [3, 5, 7]
    s1 = s[2]
    print ("k1 = ", k1); print ("p = ", p); print ("s1 = ", s1)
test1()

Результаты выполнения:

Множественное присваивание

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

<имя > = <имя > = … = <выражение>

Выражение задает некоторый объект, каждое имя связывается с этим объектом. Имена являются псевдонимами объекта - разными именами одного объекта.

Пример:

def test2():
    #присваивание: <имя > = <имя > = ... = <выражение>
    #ссылки на один объект
    a = b = c = [55]
    print('a = ', a, 'b = ', b, 'c = ', c)
    a.append(66) 
    print('a = ', a, 'b = ', b, 'c = ', c)
test2()

Результат работы:

В следующем варианте множественного присваивания имена из списка имен связываются с объектами из заданного списка выражений.

<список имен> = <список выражений>

В левой части оператора задаются имена, разделенные запятой, в правой - выражения, также разделенные запятой. Понятно, что число элементов в каждом списке должно совпадать. Семантика вычислений не очевидна и может быть разной. В данном случае применяется семантика параллельного присваивания, когда, независимо вычисляются выражения в правой части, а потом параллельно происходит связывание имен списка и объектов списка. Такая семантика позволяет просто описать часто возникающую в программировании ситуацию обмена значениями двух переменных.

Примеры множественного присваивания:

def test3():
    #присваивание: <n имен> = <n выражений>
    #семантика = параллельное присваивание 
    p, s = 5, 7
    p, s = s, p     #обмен значениями
    print ('p = ', p); print ('s = ', s);
    x, y = ['a', 'b'], ['c', 'd']
    print ('x = ', x); print ('y = ', y);
    x, y = x + y, x
    print ('x = ', x); print ('y = ', y);
test3()

Результаты вычислений:

Следующий вариант синтаксиса множественного присваивания имеет вид:

<список n имен > = < выражение>

В этом варианте выражение правой части должно быть сложного типа - список, кортеж, словарь, строка. Объект, заданный выражением правой части, должен иметь n элементов. Если условия выполняются, то семантика присваивания понятна, - каждое имя из списка левой части связывается с соответствующим элементом объекта, заданного правой частью.

Пример:

def test4():
    #присваивание: <n имен> = <выражение, задающее объект из n элементов>
    x, y, z = ['one', [2, 3], 4]
    print ('x = ', x); print ('y = ', y); print ('z = ', z)
    w1, w2, w3 = "VBA"
    print ('w1 = ', w1); print ('w2 = ', w2); print ('w3 = ', w3)
    p1,p2,p3 = {1:"one", 2:"two", 3:"three"}
    print ('p1 = ', p1); print ('p2 = ', p2); print ('p3 = ', p3)
test4()

Результаты работы:

В следующем варианте присваивания объект, задающий правую часть, может иметь больше элементов, чем список имен, при условии, что список имен левой части содержит одно имя, сопровождаемое символом *. В этом случае обычные имена получают соответствующие значения, а оставшаяся часть элементов объекта, задающего выражение, связывается с именем, отмеченным звездочкой.

Пример:

def test5():
    #присваивание: <n имен, включая имя со звездочкой> = 
    #<выражение, задающее объект, с числом элементов >= n>
    x, *y, z = ['one', [2, 3], 4, 'five']
    print ('x = ', x); print ('y = ', y); print ('z = ', z)
test5()

Результаты работы:

Присваивание, изменяющее объект

Для присваивания, изменяющего объект, может использоваться краткая форма в стиле языка C++. В этом случае знаку присваивания предшествует знак операции, применяемой к объекту. Соответствующие знаки операций перегружены и зависят от типа объекта, к которому они применяются. Чаще всего такое присваивание применяется к объектам арифметического типа, так что семантика присваивания в таких случаях вполне понятна.

Пример:

def test6():
    #Присваивание в стиле С++, изменяющее объект
    x = 6; print(x)
    x += 3;  print(x)
    x //= 3;  print(x)
    x *= 5;  print(x)
test6()

Результаты работы:

Приведем несколько примеров работы с объектами сложных типов:

def test7():
    t = "текст"; print(t)
    t += " сказки"; print(t)
    s = ['C#']; print(s)
    s += [' Python ']; print(s)
    s *= 2; print(s)
    c = ('C#'); print(c)
    c += (' Python '); print(c)
    c *= 2; print(c)
    d = {'C#':" СиШарп "}; print(d)
    #d += {' Python ': " Питон "}; print(d)
    #d *= 2; print(d)
test7()

Результаты работы:

Вернуться к учебному плану