11. 变量¶
11.1 目标¶
- 学习编程中使用变量的目的
- 学习使用数字,逻辑变量和字符串
- 学习定义和使用函数并返回值
- 了解全局变量与局部变量的不同
11.2 Karel的成长¶
Karel长大了,它离开父母的家开始实验自己的生活.因此,机器人的家方块不再出现在迷宫中. 另外还有一些其他变化反映Karel的成长 — 它装备了一个GPS定位器可以确定它在迷宫中的位置, 它可以打印消息,使用变量和列表,利用可以返回值的函数,使用复杂逻辑,使用随机决定等等. 功能函数的完整介绍可以参见 第十六部分 .
11.3 变量的目的¶
在编程中,变量用来储存之后可能使用的有用信息. 这些信息有可能是一个数字,一个单词,一句话或者一个逻辑值(True 或 False). 变量也会很复杂 — 我们会遇到列表(list),它可以储存多个值,比如机器人的路径,宝石的位置等.
11.4 变量的类型¶
我们每个人都使用变量.一例例子就是我们的名字.
字符串
假设你的名字叫”Melissa”.当你两岁的时候,你将它存在你的记忆中.
用计算机语言,你定义了一个变量 my_name :
my_name = "Melissa"
变量 my_name 储存了这个字符串.
数值
之后我们了解到有很多重要的数字,比如
seconds_per_minute = 60
而变量 hours_per_day 的值是24等等.
但我们同样会使用值不断变化的变量,如 days_per_year , number_of_my_pets 等.
在Karel中,我们只使用整数(不是一般的实数),因为这个语言的目的不在于解决数学问题.
逻辑变量
逻辑变量只能储存两个值, True 或 False.我们在生活中也经常使用它:
I_have_a_dog = True
I_own_a_car = False
当然,对于不同的人这个变量的值是不同的.逻辑变量和操作将在 第十三部分 详细讨论.
11.5 使用GPS装备和print命令¶
Karel可以在任意时刻通过 gpsx 和 gpsy 获得自己的坐标. 它还掌握了一项新本领: 通过 print 命令输出文本消息. 这几个命令的使用方法可以通过下面这个简单例子说明: Karel获取在迷宫中的位置并打印出来
程序如下:
print"Horizontal position:", gpsx
print"Vertical position:", gpsy
输出为
Horizontal position: 0
Vertical position: 0
迷宫的宽度为15(东西方向),高度为12(南北方向). 如果Karel站在东北角
那么程序输出为
Horizontal position: 14
Vertical position: 11
将Karel移动到迷宫的其他位置并且重新运行程序,熟悉GPS设备的用法!
print 命令可以用来输出更复杂的语句,其中变量和文本用逗号分割:
print "My GPS coordinates are", gpsx,"and", gpsy
对于上一个迷宫,程序输出:
My GPS coordinates are 14 and 11
11.6 自定义函数¶
我们可以在命令体中用 return 关键字返回一个值.这种命令被称为函数(function).函数同样用关键字 def 定义.例如,如下函数 countsteps 使机器人走到最近的墙并且返回需要的步数:
def countsteps
n = 0
while not wall
go
inc(n)
return n
要注意一些事情:
- 变量 n 被语句 n = 0 创建并初始化. 在Karel中,我们不需要事先声明变量类型,解释器会根据它首次被赋予的值自动判断其类型.
- inc() 函数为整数变量的值加1. 同样还有一个函数 dec(),为整数变量的值减1.更多解释参考11.10节.
函数可以被如下使用:
num = countsteps
print "I reached wall in", num,"steps!"
我们首先创建了新的变量 num ,并且用函数 countsteps 返回的整数初始化它.之后打印出结果.
如图2所示情形,将输出:
I reached wall in 11 steps!
11.7 度量墙的长度¶
这里Karel的任务是度量和打印输出任意墙的长度.
墙有开头和结尾,但不包含闭循环; 机器人面朝墙的第一块砖,墙总是在它的左边,如图所示:
这个问题可以用只有13行的自定义函数 measurewall 完成:
# Function to measure the length
# of an arbitrary wall:
def measurewall
l = 0
while wall
inc(l)
left
if not wall
go
right
if not wall
go
right
if not wall
return l
# Call the function:
print "Length of wall is", measurewall
运行程序后得到输出:
Length of wall is: 53
你不妨试着改变墙的形状,看看此程序是否工作正常.
11.8 创建和实例化数值变量¶
在Karel中,可以通过多种方式创建和初始化数值变量:
- 通过赋予它们整数. 新变量 a 被创建, 给它设为0:
a = 0
- 通过函数 gpsx . 新变量 posx 被创建, 赋予它 gpsx 的值:
posx = gpsx
- 通过函数 gpsy . 新变量 posy 被创建, 赋予它 gpsy 的值:
posy = gpsy
- 通过已存在的变量实例化新变量. 已存在整数变量 var1, 那么新变量 var2 可以用如下方式创建:
var2 = var1
- 通过已知函数的返回值实例化新变量. 使用我们之前定义的函数 countsteps 定义新变量:
num = countsteps
11.9 改变数值变量的值¶
数值变量的值可以被随时更新, 用上述方法之一.
11.10 使用inc()和dec()函数¶
Karel根本不懂数学符号 + 和 - .但为了计数的需要,它可以分别用函数 inc() 或 dec() 来增加或减少整数一个单位. 也可以一次性增加或减少更多的单位, 通过 inc(n,num) 或 dec(n,num) 方法. 这里 n 是变量名称, num 是一个整数.
11.11 比较运算¶
数字变量可以通过标准算符 > , < , >= , <= , == , != , <> 进行比较. 分别读作”大于”,”小于”,”大于等于”,”小于等于”,”等于”,”不等于”(后两个符号含义相同). 每次比较的结果是一个逻辑值 True 或 False ,可以被用在条件判断,条件循环,或赋予一个变量.如下:
a = 1
b = 5
printa < b
输出:
True
代码:
a = 1
b = 5
c = a > b
print c
输出:
False
代码:
a = 0
while a <= 5
print a
inc(a)
输出:
0
1
2
3
4
5
11.12 文本字符串¶
字符串变量的创建和实例化类似于数值变量:
robots_name ="Karel"
它们可以被打印:
print"Robot’s name is", robots_name
输出:
Robot’s name is Karel
一个字符串变量可以用来实例化另一个新变量.比如有人想将机器人命名为”Carlos”(西班牙版本的”Karel”), 并在变量 robots_name_orig 中储存它的的原始名字. 可通过如下方法:
robots_name_orig = robots_name
robots_name = "Carlos"
11.13 局部和全局变量¶
定义在函数中的变量叫作局部变量,它只能在这个函数内使用. 如果我们试图在函数外使用它,就会抛处错误. 以下代码, 变量 a 定义在函数 myfunction 中, 是局部变量:
def myfunction
a = 1
retur
nmyfunction
print a
当运行时,代码抛出如下错误信息:
Unknown variable/procedure "a"
另一方面,在主程序(main)中定义的变量是全局变量.它可以在函数中使用.如下所示:
def myfunction
print "b =", b
return
b = 5
myfunction
输出为:
b = 5
总之我们应该尽可能多的使用局部变量,这样可使代码更安全和更好的组织.使用全局变量要更加谨慎或避免.


