周四:作用域
今天我们要讨论一个重要的概念,叫做作用域。作用域负责处理程序中声明的变量的可访问性。我们会讲解不同类型的作用域以及如何处理它们。
要继续学习这一课,让我们继续前面的notebook文件“Week_05”,并在底部添加一个名为“作用域”的markdown单元格。
作用域的类型
在Python中,有三种作用域类型:全局作用域、函数作用域和类作用域。我们还没有讲到类,所以我们将在以后的章节中讨论类作用域。暂时不讨论类作用域,我们先讨论了另外两种类型的作用域。全局作用域是指你声明一个变量可以被整个文件或应用程序访问。到目前为止,我们已声明的大多数变量都是全局变量;但是,在编写的大多数程序中,都希望避免使用全局变量。不过现在在Jupyter Notebook中还可以。函数作用域是指仅在函数内部声明和可访问的变量。函数内声明的变量不能在函数之外访问,因为一旦函数终止,函数内部声明的变量也会终止。
全局作用域访问
定义了全局属性后,文件的其余部分就可以访问它们。但是,我们必须知道函数作用域是如何工作的。即使你声明了一个可被整个文件访问的变量,它也不能在函数中被访问和修改。让我们来看一个例子:
# 访问全局变量
number = 5
def scopeTest( ):
number += 1 # 由于函数级作用域所以无法访问
scopeTest()
继续并运行单元格。我们最终会收到一个错误,因为函数仅限于内部声明或传入的变量。
注意 当传入时,它只传递值,而不是变量。
处理函数作用域
当处理函数中声明的变量时,通常不需要在函数外访问它。然而,为了访问该值,最佳实践是return返回它的值:
# 访问在函数内部定义的变量
def scopeTest():
word = "function"
return word
value = scopeTest()
print(value)
继续并运行单元格。现在我们可以访问函数中定义的单词了,我们只需将返回值赋给另一个变量即可。
就地算法
当向函数传递变量时,你只是传递变量的值,而不是变量本身。这样,下面的代码将不会改变变量num:
>>> num = 5
>>> def changeNum(n):
>>> n += 5
>>> print(num)
但是,通过索引改变信息时情况就不同了。由于索引的工作方式,通过内存位置而不是引用,通过索引位置改变列表中的元素将改变原始变量。让我们来看一个例子:
# 通过索引改变值
sports = [ "baseball", "football", "hockey", "basketball" ]
def change(aList):
aList[ 0 ] = "soccer"
print("Before Altering: { }".format(sports))
change(sports)
print("After Altering: { }".format(sports))
继续并运行单元格。请注意调用函数时运动列表中的第一项是如何变化的。这是因为在传入列表时,索引本身的值发生了变化。这些被称为原地算法,因为无论你在哪里修改信息,它都会直接改变内存位置中的值。
- Names:创建一个函数,向该函数传入含有names的列表,以实现该函数将更改在指定索引位置的值的功能。例如传递“Bill”和索引1,它会把“Rich”变成“Bill”。使用列表和函数定义如下:
>>> names = ['Bob', 'Rich', 'Amanda']
>>> def changeValue(aList, name, index):
理解变量可访问性很重要。了解此信息将确保我们的变量安全。