Julia机器核心编程.作用域
当我们在Julia中定义函数时,也可以在函数体内定义变量。在这种情况下,该变量在该函数的局部范围内有效,因此称为局部变量。而未在函数体内声明的变量在全局范围内有效,因此称为全局变量。
不同代码块中的变量可以使用相同的名称,但引用的是不同的实体,这种特性就是由其范围规则所定义的。
Julia有两种主要的范围类型:全局范围和局部范围。其中局部范围可以被嵌套。除非另有说明,否则模块和REPL中的变量通常在全局范围内;循环、函数、宏、try-catch-finally块中的变量在局部范围内。
打错一个字
代码01~03行定义了一个for结构,其中声明了一个hello变量。在04行我们试图输出hello的值,但是却得到了05行的报错,报错类型是未定义变量错误,提示hello并没有被定义。这是为什么呢?
因为对于整个程序来说,for结构属于一个局部,所以在for结构中声明的hello仅在for循环的范围内可用,在for循环的范围外不可用。
我们修改上一个函数,使得在循环外部也可以访问到hello。
这段代码和上面代码几乎完全一样,唯一的区别在于添加了02行,用global关键字显式声明hello为全局变量,这样就可以在06行要求显示hello的值时,成功地将hello的值打印出来了。
Julia使用了一种称为词法作用域的机制,简单来说,就是函数的作用域不会从其调用对象的作用域继承,而是从函数定义的作用域继承。为了更清楚地理解这一点,我通过一个例子来说明。
词法作用域的例子
代码01~05行用module关键字创建了一个名为“Utility”的模块,它包含一个name变量和一个tell_name()函数。我们将Utility模块内的name变量的值设置为“Julia”。为了对比,07行我们在Utility模块外声明了另一个name变量,并将它的值设置为“Python”。
在代码10行,当调用Utility.tell_name()时,我们得到的值是“Julia”。这表明该函数使用了在Utility模块中定义的name变量的值,这是因为函数tell_name()本身被定义在Utility模块中。所以,在Utility模块外声明的另一个name变量,不会影响函数的运行结果。
Julia还提供了对局部范围的进一步分类,分为软局部范围和硬局部范围,刚才的函数介绍的是硬局部范围,我继续将注意力放在函数的范围上。
假设有一个alpha()函数,它的作用是将参数传递给一个名为“x”的局部变量并返回x。同时,我们定义了另一个全局变量x,并将它的值设置为100。
代码01行定义了一个变量x。04~07行定义了一个函数,在其中定义了另一个变量x,并通过参数赋值的形式对x的值进行了更改。在代码10行我们对该函数进行了调用,返回的x的值是50。代码14行直接输出x的值,输出的x的值是100。
如果仔细观察,就会发现x的值自始至终都是100,但是当我们调用alpha(50)函数时,函数返回的是50而不是100。这是因为在函数内部声明的变量(即函数中的局部变量x)在函数内部被赋值为参数所传递的数值(即n),而全局变量x的值对函数内部的局部变量x却无法直接造成影响。
如果想要在函数内部使用全局声明的x,该怎么办呢?我们可以使用global关键字。
在函数内部使用全局变量
我们将函数中的x变量替换为全局的x,然后观察调用函数后结果发生了怎样的改变。
这段代码和上面的代码几乎完全相同,只是在05行函数体内删除了为局部变量x指定数值的代码,取而代之的是为全局变量x指定n的值。结果很明显,和我们所期望的一样,全局变量x的值已经被改变为50,而不是原始值100了。因为在函数体中我们操作的不再是局部变量x,而是全局变量x。
其实对于一个编程语言来讲,变量的作用域并不是这么简单的事情.很多我都没有讲.比如左值右值,编译器优化这些.后面我再写,现在先这样,够用就行,太深入容易迷失自我~