Spec-Zone.ru › Octave 9

8.6 Выражения присваивания

Присваивание — это выражение, которое записывает новое значение в переменную. Например, следующее выражение присваивает значение 1 переменной z:

z = 1

После выполнения этого выражения переменная z имеет значение 1. Прежнее значение z забывается. Знак «=» называется оператором присваивания.

Присваивание может также записывать строковые значения. Например, следующее выражение записало бы значение "this food is good" в переменную message:

thing = "food"
predicate = "good"
message = [ "this " , thing , " is " , predicate ]
⇒ "this food is good"

(Это также иллюстрирует конкатенацию строк.)

Большинство операторов (сложение, конкатенация и так далее) лишь вычисляют значение, не оказывая других эффектов. Если это значение не используется, оператор можно было бы не применять. Оператор присваивания устроен иначе. Он действительно возвращает значение, но даже если это значение игнорируется, присваивание всё равно проявляет себя, изменяя переменную. Это называется побочным эффектом.

Левый операнд присваивания не обязательно должен быть переменной (см. Переменные). Это также может быть элемент матрицы (см. Индексные выражения) или список возвращаемых значений (см. Вызов функций). Всё это называется l-значениями, то есть они могут находиться в левой части оператора присваивания. Правым операндом может быть любое выражение. Оно вычисляет новое значение, которое присваивание записывает в указанную переменную, элемент матрицы или список возвращаемых значений.

Важно отметить, что у переменных нет постоянных типов. Тип переменной — это просто тип значения, которое она содержит в данный момент. В следующем фрагменте программы переменная foo сначала имеет числовое значение, а затем — строковое:

>> foo = 1
foo = 1
>> foo = "bar"
foo = bar

Когда второе присваивание задаёт foo строковое значение, прежнее числовое значение забывается.

Присваивание скалярного значения индексированной матрице устанавливает это значение для всех элементов, на которые указывают индексы. Например, если a — матрица как минимум с двумя столбцами,

a(:, 2) = 5

устанавливает значение 5 для всех элементов второго столбца a.

Если при присваивании задаётся значение элемента вектора, матрицы или массива в позиции либо измерении за пределами текущего размера этой переменной, размер массива будет увеличен, чтобы вместить новые значения:

>> a = [1, 2, 3]
a = 1 2 3
>> a(4) = 4
a = 1 2 3 4
>> a(2, :) = [5, 6, 7, 8]
a =
   1   2   3   4
   5   6   7   8

Попытка увеличить размер массива так, что требуемый размер результата становится неоднозначным, приведёт к ошибке:

>> a(9) = 10
-| error: Invalid resizing operation or ambiguous assignment to an
out-of-bounds array element

Это происходит потому, что добавление 9-го элемента создаёт неоднозначность относительно требуемой позиции значения 10 в массиве; каждый из возможных вариантов требует своего увеличения размера массива для выполнения присваивания.

Можно выполнять присваивание с меньшим числом заданных элементов, чем требуется для заполнения вновь расширенного массива, если присваивание однозначно. В таких случаях массив будет автоматически дополнен значениями null:

>> a = [1, 2]
a =   1   2
>> a(4) = 5
a =   1   2   0   5
>> a(3, :) = [6, 7, 8, 9]
a =
   1   2   0   5
   0   0   0   0
   6   7   8   9
>> a(4, 5) = 10
a =
    1    2    0    5    0
    0    0    0    0    0
    6    7    8    9    0
    0    0    0    0   10

Для всех встроенных типов значение null будет соответствовать типу объекта.

Числовые массивы:

>> a = int32 ([1, 2])
a = 1, 2
>> a(4) = 5
a = 1 2 0 5

Логические массивы:

>> a = [true, false, true]
a = 1 0 1
>> d(5) = true
d = 1 0 1 0 1

Символьные массивы:

>> a = "abc"
a = abc
>> a(5) = "d"
a = abcd
>> double (a)
ans = 97 98 99 0 100

Массивы ячеек:

>> e = {1, "foo", [3, 4]};
>> e(5) = "bar"
e =
{
  [1,1] = 1
  [1,2] = foo
  [1,3] =

     3   4

  [1,4] = [](0x0)
  [1,5] = bar
}

Массивы структур:

>> a = struct("foo",1,"bar",2);
>> a(3) = struct("foo",3,"bar",9)
a =

  1x3 struct array containing the fields:

    foo
    bar

>> a.foo
ans = 1
ans = [](0x0)
ans = 3
>> a.bar
ans = 2
ans = [](0x0)
ans = 9

Обратите внимание, что в настоящее время Octave не умеет объединять в массивы объекты произвольных типов. Такое поведение должно быть явно определено в классе объекта, иначе попытка конкатенации приведёт к ошибке. См. Объектно-ориентированное программирование

Присваивание пустой матрицы «[]» в большинстве случаев позволяет удалять строки или столбцы матриц и векторов. См. Пустые матрицы. Например, если дана матрица A размером 4 на 5, присваивание

A (3, :) = []

удаляет третью строку A, а присваивание

A (:, 1:2:5) = []

удаляет первый, третий и пятый столбцы.

Удаление части объекта-массива неизбежно изменяет его размер. Если удаление позволяет согласованно уменьшить размер вдоль одного измерения — например, удалить один элемент вектора или одну строку либо один столбец матрицы, — размер вдоль этого измерения будет уменьшен с сохранением размерности. Если же сохранить размерность невозможно, объект будет преобразован в вектор с упорядочением элементов по столбцам:

>> a = [1, 2, 3, 4; 5, 6, 7, 8]
a =
   1   2   3   4
   5   6   7   8
>> a(:, 3) = []
a =
   1   2   4
   5   6   8
>> a(4) = []
a = 1 5 2 4 8

Присваивание является выражением, поэтому имеет значение. Так, выражение z = 1 имеет значение 1. Отсюда следует, что можно объединять несколько присваиваний:

x = y = z = 0

записывает значение 0 во все три переменные. Это происходит потому, что значение z = 0, равное 0, записывается в y, а затем значение y = z = 0, также равное 0, записывается в x.

Это справедливо и для присваиваний спискам значений, поэтому следующее выражение допустимо:

[a, b, c] = [u, s, v] = svd (a)

оно полностью эквивалентно следующему:

[u, s, v] = svd (a)
a = u
b = s
c = v

В подобных выражениях количество значений в каждой части не обязано совпадать. Например, выражение

[a, b] = [u, s, v] = svd (a)

эквивалентно выражению

[u, s, v] = svd (a)
a = u
b = s

Однако количество значений в левой части выражения не может превышать количество значений в правой части. Например, следующее выражение приведёт к ошибке.

[a, b, c, d] = [u, s, v] = svd (a);
-| error: element number 4 undefined in return list

Символ ~ можно использовать в списке l-значений как заполнитель, указывающий, что соответствующее возвращаемое значение следует игнорировать и никуда не записывать:

[~, s, v] = svd (a);

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

Распространённый шаблон программирования — увеличить значение существующей переменной на заданную величину, например:

a = a + 2;

Это можно записать яснее и компактнее с помощью оператора +=:

a += 2;

Аналогичные операторы существуют также для вычитания (-=), умножения (*=) и деления (/=). Выражение вида

expr1 op= expr2

вычисляется как

expr1 = (expr1) op (expr2)

где op может быть +, -, * или /, если expr2 — простое выражение без побочных эффектов. Если expr2 также содержит оператор присваивания, это выражение вычисляется как

temp = expr2
expr1 = (expr1) op temp

где temp — временный заполнитель для сохранения результата вычисления expr2. Таким образом, выражение

a *= b+1

вычисляется как

a = a * (b+1)

а не как

a = a * b + 1

Присваивание можно использовать везде, где требуется выражение. Например, допустимо написать x != (y = 1), чтобы установить y в 1, а затем проверить, равно ли x единице. Однако такой стиль затрудняет чтение программ. За исключением одноразовых программ, следует переписать код, избавившись от подобного вложения присваиваний. Сделать это обычно несложно.

© 1996–2026 The Octave Project Developers
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions.
https://docs.octave.org/v9.4.0/Assignment-Ops.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API