赋值是一个将新值存储到一个变量中的表达式。例如,以下表达式将值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"
(这也说明了字符串的连接。)
大多数运算符(加法、连接等)除了计算值之外没有任何效果。如果忽略该值,则最好不要使用运算符。赋值运算符不同。它确实返回了一个值,但即使你忽略了这个值,赋值仍然会通过变量的变化而返回。我们称之为副作用.
赋值的左侧操作数不必是变量(详见变量). 它也可以是矩阵的元素(详见索引表达式)或返回值列表(详见调用函数). 这些都被称为lvalues,这意味着它们可以出现在赋值运算符的左侧。右侧操作数可以是任何表达式。它生成新值,赋值将其存储在指定的变量、矩阵元素或返回值列表中。
需要注意的是,变量确实不具有永久类型。变量的类型就是它当前所保持的值的类型。在下面的程序片段中,变量foo
先有一个数字值,后有一个字符串值:
>>foo=1foo=1>>foo=“bar”foo=bar
当第二个赋值给出foo
一个字符串值,它以前有一个数值的事实被忘记了。
将标量赋值给索引矩阵会将索引所引用的所有元素设置为标量值。例如,如果a
是具有至少两列的矩阵,
a(:, 2) = 5
设置的第二列中的所有元素a
至5。
当赋值将向量、矩阵或数组元素的值设置在变量当前大小之外的位置或维度时,数组大小将增加以适应新值:
>> 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目前无法将任意对象类型连接到数组中。这样的行为必须在对象类中明确定义,否则尝试连接将导致错误。详见面向对象程序设计
赋值一个空矩阵[]在大多数情况下允许删除矩阵和向量的行或列。详见空矩阵例如,给定一个4乘5的矩阵A,赋值
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
符号~
可以用作lvalues列表中的占位符,指示应忽略相应的返回值而不存储其中:
[~, 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
等于1。但这种风格往往会使程序难以阅读。除了在一次性程序中,您应该重写它以消除这种嵌套的任务。这从来都不是很难。
版权所有 © 2024 Octave中文网
ICP备案/许可证号:黑ICP备2024030411号