用于机器人技术的 Python第 2 单元 Python 基础- 摘要预计完成时间:2 小时在本单元中,您将学习如何在 Python 中创建变量,可以创建哪些类型的变量,以及如何对这些变量进行操作。请记住,变量就像是有趣数据的存储空间。我们将使用变量来存储传感器数据,并通过操作这些数据来了解机器人当前的状况。此外,您还将学习如何在代码中添加注释。- 摘要结束在本课程中,我们希望将重点放在 Python 上,而不是 ROS 上。不过,为了能够在隐藏所有 ROS 内容的同时与模拟机器人进行交互,我们为您提供了一个 Python 类,负责管理引擎盖下的所有 ROS 连接。该类名为 RobotControl.因此,在本课程中,您将通过调用这个 Python 类的方法来与之交互,从而从机器人那里获取数据并向它们发送命令。注意:也许其中的一些概念,比如 Python类或方法,现在对你来说听起来很奇怪,
第 2 单元 Python 基础
- 摘要
预计完成时间:2 小时
在本单元中,您将学习如何在 Python 中创建变量,可以创建哪些类型的变量,以及如何对这些变量进行操作。请记住,变量就像是有趣数据的存储空间。我们将使用变量来存储传感器数据,并通过操作这些数据来了解机器人当前的状况。此外,您还将学习如何在代码中添加注释。
- 摘要结束
在本课程中,我们希望将重点放在 Python 上,而不是 ROS 上。
不过,为了能够在隐藏所有 ROS 内容的同时与模拟机器人进行交互,我们为您提供了一个 Python 类,负责管理引擎盖下的所有 ROS 连接。该类名为 RobotControl.因此,在本课程中,您将通过调用这个 Python 类的方法来与之交互,从而从机器人那里获取数据并向它们发送命令。
注意:也许其中的一些概念,比如 Python类或方法,现在对你来说听起来很奇怪,但不用担心,你会在课程的后面学习到它们。
因此,在下一节中,您将添加这个 RobotControl类。现在理解这个类的代码并不重要,但在本课程结束时你会理解的。
另外,因为我们使用的是ROS noetic ,所以 Python 3 是默认的。这意味着您无需安装。
就是这样!现在你可以开始使用 Python3 和 ROS 了!
那么,在做了适当的自我介绍之后,现在让我们开始工作吧!
2.1 数据类型和变量
正如我们在 Ignite 学院喜欢做的那样,让我们从一些练习开始。在下面的练习中,您将创建并执行一个非常简单的 Python 脚本,让我们介绍一些与 Python 相关的重要基本概念。
- 练习 2.1 -
让我们创建一个目录来存储我们的 RobotControl 类代码。将此目录命名为 robot_control在该 robot_control目录中,我们将创建一个新的 Python 脚本,名为 robot_control_class.py的 Python 脚本。 pyscript1.py的脚本,用于测试该类。
在 Shell #1 中执行
在 [ ] 中:
cd ~/catkin_ws/src/
在 [ ] 中:
mkdir robot_control
在 [ ] 中:
cd robot_control
在 [ ] 中:
touch pyscript1.py
在 [ ] 中:
touch robot_control_class.py
备注
注意:在 Linux 中,touch 命令用于从命令行创建一个新的空文件。

或者,如果你更喜欢使用集成开发环境(代码编辑器),可以右键单击文件夹,在右键菜单中选择 "新建文件 "选项,创建一个新的空文件。

文件创建完成后,您的 robot_control文件夹中的以下文件。

注释结束
现在您已经创建了一个空文件,必须使用代码编辑器(集成开发环境)打开该文件。
要在集成开发环境中打开文件,只需用鼠标点击集成开发环境左侧边栏文件浏览器中的文件名即可。点击文件后,它将在集成开发环境主区域内的新标签页中打开。请注意,标签页显示的是文件名。请注意,每次点击不同的文件名都会在集成开发环境主区域内打开。
要从讲座中复制代码,可以单击每个代码块顶部的 "将代码复制到剪贴板 "按钮(或者选择要复制的代码,然后按Ctrl + C 复制)。
要粘贴代码,请使用集成开发环境打开要添加代码的文件。确保可以书写文本:光标应时隐时现,然后按Ctrl + V 粘贴。
接下来,将下面的代码复制到 robot_control_class.py文件中。
机器人控制类.py
在 [ ] 中:
#!/usr/bin/env python
import rospy
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan
import time
class RobotControl():
def __init__(self, robot_name="cooper"):
rospy.init_node('robot_control_node', anonymous=True)
if robot_name == "summit":
rospy.loginfo("Robot Summit...")
cmd_vel_topic = "/summit_xl_control/cmd_vel"
# We check that sensors are working
self._check_summit_laser_ready()
else:
rospy.loginfo("Robot Cooper...")
cmd_vel_topic='/cooper_1/cmd_vel'
self._check_laser_ready()
# We start the publisher
self.vel_publisher = rospy.Publisher(cmd_vel_topic, Twist, queue_size=1)
self.cmd = Twist()
self.laser_subscriber = rospy.Subscriber(
'/cooper_1/scan', LaserScan, self.laser_callback)
self.summit_laser_subscriber = rospy.Subscriber(
'/hokuyo_base/scan', LaserScan, self.summit_laser_callback)
self.ctrl_c = False
self.rate = rospy.Rate(1)
rospy.on_shutdown(self.shutdownhook)
def _check_summit_laser_ready(self):
self.summit_laser_msg = None
rospy.loginfo("Checking Summit Laser...")
while self.summit_laser_msg is None and not rospy.is_shutdown():
try:
self.summit_laser_msg = rospy.wait_for_message("/hokuyo_base/scan", LaserScan, timeout=1.0)
rospy.logdebug("Current /hokuyo_base/scan READY=>" + str(self.summit_laser_msg))
except:
rospy.logerr("Current /hokuyo_base/scan not ready yet, retrying for getting scan")
rospy.loginfo("Checking Summit Laser...DONE")
return self.summit_laser_msg
def _check_laser_ready(self):
self.laser_msg = None
rospy.loginfo("Checking Laser...")
while self.laser_msg is None and not rospy.is_shutdown():
try:
self.laser_msg = rospy.wait_for_message("/cooper_1/scan", LaserScan, timeout=1.0)
rospy.logdebug("Current /kobuki/laser/scan READY=>" + str(self.laser_msg))
except:
rospy.logerr("Current /cooper_1/scan not ready yet, retrying for getting scan")
rospy.loginfo("Checking Laser...DONE")
return self.laser_msg
def publish_once_in_cmd_vel(self):
"""
This is because publishing in topics sometimes fails the first time you publish.
In continuous publishing systems, this is no big deal, but in systems that publish only
once, it IS very important.
"""
while not self.ctrl_c:
connections = self.vel_publisher.get_num_connections()
if connections > 0:
self.vel_publisher.publish(self.cmd)
#rospy.loginfo("Cmd Published")
break
else:
self.rate.sleep()
def shutdownhook(self):
# works better than the rospy.is_shutdown()
self.ctrl_c = True
def laser_callback(self, msg):
self.laser_msg = msg
def summit_laser_callback(self, msg):
self.summit_laser_msg = msg
def get_laser(self, pos):
time.sleep(1)
return self.laser_msg.ranges[pos]
def get_laser_summit(self, pos):
time.sleep(1)
return self.summit_laser_msg.ranges[pos]
def get_front_laser(self):
time.sleep(1)
return self.laser_msg.ranges[360]
def get_laser_full(self):
time.sleep(1)
return self.laser_msg.ranges
def stop_robot(self):
#rospy.loginfo("shutdown time! Stop the robot")
self.cmd.linear.x = 0.0
self.cmd.angular.z = 0.0
self.publish_once_in_cmd_vel()
def move_straight(self):
# Initilize velocities
self.cmd.linear.x = 0.5
self.cmd.linear.y = 0
self.cmd.linear.z = 0
self.cmd.angular.x = 0
self.cmd.angular.y = 0
self.cmd.angular.z = 0
# Publish the velocity
self.publish_once_in_cmd_vel()
def move_straight_time(self, motion, speed, time):
# Initilize velocities
self.cmd.linear.y = 0
self.cmd.linear.z = 0
self.cmd.angular.x = 0
self.cmd.angular.y = 0
self.cmd.angular.z = 0
if motion == "forward":
self.cmd.linear.x = speed
elif motion == "backward":
self.cmd.linear.x = - speed
i = 0
# loop to publish the velocity estimate, current_distance = velocity * (t1 - t0)
while (i <= time):
# Publish the velocity
self.vel_publisher.publish(self.cmd)
i += 1
self.rate.sleep()
# set velocity to zero to stop the robot
self.stop_robot()
s = "Moved robot " + motion + " for " + str(time) + " seconds at " + str(speed) + " m/s"
return s
def turn(self, clockwise, speed, time):
# Initilize velocities
self.cmd.linear.x = 0
self.cmd.linear.y = 0
self.cmd.linear.z = 0
self.cmd.angular.x = 0
self.cmd.angular.y = 0
if clockwise == "clockwise":
self.cmd.angular.z = -speed
else:
self.cmd.angular.z = speed
i = 0
# loop to publish the velocity estimate, current_distance = velocity * (t1 - t0)
while (i <= time):
# Publish the velocity
self.vel_publisher.publish(self.cmd)
i += 1
self.rate.sleep()
# set velocity to zero to stop the robot
self.stop_robot()
s = "Turned robot " + clockwise + " for " + str(time) + " seconds at " + str(speed) + " radians/second"
return s
if __name__ == '__main__':
robotcontrol_object = RobotControl()
try:
robotcontrol_object.move_straight()
except rospy.ROSInterruptException:
pass
结束机器人控制类文件
然后在 IDE(代码编辑器)中打开 pyscript1.py文件。
现在,将以下内容复制到 pyscript1.py脚本:
pyscript1.py
在 [ ] 中:
from robot_control_class import RobotControl
rc = RobotControl()
a = rc.get_laser(49)
print ("The distance measured is: ", a, " m.")
pyscript1.py
请看一下代码,并试着理解它的作用。
现在,让我们执行脚本。
使用python 或python3 命令是执行 Python 脚本最简单、最直接的方法。该命令必须与脚本的文件路径和文件名一起使用。通常,我们倾向于导航到文件目录,然后只使用文件名运行命令,而不是提供完整的文件路径。在这种情况下,如果你按照之前的指示执行命令,就已经进入了pyscript1.py 文件所在的目录。因此,在这种情况下,你只需在终端中键入以下内容即可运行脚本:
在 Shell #1 中执行
在 [ ] 中:
python pyscript1.py
你应该会得到类似这样的输出结果:
[INFO] [1749723648.374540]: Robot Cooper...
[INFO] [1749723648.377078]: Checking Laser...
[INFO] [1749723648.406689]: Checking Laser...DONE
The distance measured is: inf m.
- 练习 2.1 - 结束
那么......刚才发生了什么?我们来解释一下
您想在 6 个月内从事机器人技术工作吗?机会就在这里。
了解更多信息:
2.1.1 代码解释
我们首先可以在脚本中看到以下一行:
在 [ ] 中:
from robot_control_class import RobotControl
在这里,我们导入了一个名为 RobotControl.这个类是我们机器人点火学院创建的,可以帮助你与 ROS 机器人进行交互,而无需真正使用 ROS。
进口意味着什么?
导入在 Python 中非常有用和常见。通过导入,您可以在程序中包含在其他 Python 模块中创建的代码。这意味着您程序中的 Python 代码可以执行另一个程序文件中定义的 Python 代码(这里是指 RobotControl类)中定义的 Python 代码,而无需重写。
要导入另一个 Python 模块的代码,请指明以下内容:
在 [ ] 中:
from <name_of_the_module> import <method_or_class_to_be_imported>
在我们的例子中,我们导入了一个名为 RobotControl的 Python 类,该类定义在名为 robot_control_class.
如何知道要导入哪些模块和类?
这是一个非常好的问题!您必须事先了解哪些模块可能对您的工作有帮助,以及这些模块提供哪些方法或类可供导入。为此,您必须查看创建这些模块的人员提供的代码文档。
在本例中,我们(机器人点火学院)创建了模块 robot_control_class我们知道,在该模块中,有一个名为RobotControl 的类,它提供了我们与机器人交互所需的一切。
如果您好奇并想了解 robot_control_class及其包含和提供的内容,可以使用 webshell 并导航到以下目录,查看我们为本课程创建的代码:
在 [ ] 中:
/home/simulations/public_sim_ws/src/all/ros_basics_examples/python_course_class
创建变量
我们可以看到下一行:
在 [ ] 中:
rc = RobotControl()
在这里,我们创建一个名为 rc的变量。 RobotControl类型的变量。我们将使用该变量调用该类的方法来获取机器人传感器数据。您将在本课程后面的 Python 类一章中学习这部分内容。现在,只需记住如何创建某个类型的变量。
调用类的方法
下一行代码是
在 [ ] 中:
a = rc.get_laser(49)
这里有三件新鲜事:
我们正在调用*
get_laser()* 方法,该方法由RobotControl类提供。我们为方法提供了一个参数(数字
49)。然后,我们将方法的输出结果存储 到新变量
a中。
这种 get_laser()方法?
方法
get_laser (ray_number)该方法允许您从机器人的激光器中获取数据。调用该方法时,它将返回您作为参数指定的激光射线测得的距离。参数
ray_number:在这里您可以指定一个 0 到 99 之间的数字,该数字表示您希望获得测量距离的激光读数的射线。
现在,这听起来可能有点令人困惑,让我们试着解释一下。在模拟的库珀机器人身上,你可以看到安装了激光器。

现在,您可能已经知道,这台激光器在一个与地面平行的二维平面上投射出许多光束(准确地说是 100 道)。这些射线正在测量与拦截射线的最近障碍物之间的距离。

这些光束从激光器向各个方向投射,覆盖机器人前方大约 180 度的范围。请看下图。您可以进入模拟窗口,点击它(检查您是否可以用鼠标移动摄像头),然后按键盘上的字母R 来切换激光的可视化效果。

此图表示激光器在 180 度范围内投射的激光束。另外,请记住图像中出现的数字,因为这些数字稍后将非常重要。
图中数字的含义如下:
如果我们将数字
0传递给get_laser()方法,我们将获得机器人右侧第一束激光的读数。如果我们将数字
49传递给get_laser()方法,我们就能获得机器人前方激光束的读数。99如果我们向get_laser()方法,我们将获得机器人左侧最后一束激光的读数。所有介于两者之间的数字也是如此。
因此,调用 get_laser()49 方法,该方法将返回机器人正前方的激光读数。这就意味着,我们测量的是距离机器人正前方最近的障碍物的距离。机器人正前方有什么呢?机器人可以移动的自由空间。 那么......你还记得我们执行脚本时的输出结果吗?
[INFO] [1749723648.374540]: Robot Cooper...
[INFO] [1749723648.377078]: Checking Laser...
[INFO] [1749723648.406689]: Checking Laser...DONE
The distance measured is: inf m.
那么,这个输出的意思就是,机器人正前方(49 号位置)的激光束没有探测到任何超出机器人激光测距范围(20.0 米)的东西。这就是inf 的值Infinite 显示的原因。很棒吧?
调用方法是什么意思?
在脚本的最后一行之前,让我们介绍另一个概念:调用方法。我们将在第四单元深入讨论方法,但现在,为了能够与模拟进行交互,我们需要介绍调用方法的概念。要调用一个方法,只需指定该方法的名称,并在名称后面加上括号。然后,在这些括号内指定该方法所需的参数。
在 [ ] 中:
method_name(parameter1, parameter2, ...)
在我们的例子中,只有一个参数、 ray_number,所以我们这样调用我们的方法:
在 [ ] 中:
rc.get_laser(49)
还要注意的是,在方法名称之前,我们把 rc对象。这是因为 get_laser()方法是由这个对象定义的。你将在第 5 单元学到更多关于这些概念的知识,所以现在不用太担心这个问题,只要记住如何调用方法就可以了。我可以向你保证,在课程结束时,你将掌握所有这些概念。
获取方法的输出
调用 get_laser()方法时,该方法会施展魔法,计算您指定的射线检测到的距离。然后将该值返回给调用者。
这意味着调用该方法所得到的结果必须存储在某个地方。这个地方就是变量 a.
但是等等......变量*a* 从何而来?
问得好!
变量 a不知从何而来。它是在我们调用方法的同一行自动创建的。
但是等等......*a* 是哪种变量?
另一个好问题!
变量的类型由 Python 系统自动分配,它与方法返回值的类型相匹配。 get_laser()方法返回值的类型相匹配。这意味着在操作之前,你不需要知道变量的类型。很酷吧?
在屏幕上显示数据
最后,在脚本的最后一行,我们有一个 print()方法。
在 [ ] 中:
print ("The distance measured is: ", a)我们将在本章后面讨论 print()方法,所以现在只需记住,使用该方法是为了在屏幕上打印某些内容。
在这种情况下,我们打印的是 get_laser()方法提供的输出,即射线测得的距离。
正如您所看到的,您执行的脚本非常简单,但它可以让我们介绍几个非常重要的概念,您在所有 Python 脚本中都需要这些概念:数据类型和变量。
2.1.2 变量
变量可以看作是存储数据的容器:可以是数字、文本或更复杂的数据类型。
在程序执行过程中,变量可以被访问,甚至可以被修改,这意味着变量将被赋予一个新值。
在大多数编程语言(如 C++ 或 Java)中,您需要先声明变量才能使用它。但在 Python 中,这要容易得多。在 Python 中不需要声明变量。如果您想使用一个变量,您只需要想一个名字,然后开始给它赋值!您可以从下面的代码片段中看到这一点。
在 [ ] 中:
a = 5 b = 'This is a string' c = ['This', 'is', 'a', 'list', 1, 2, 3]
如果您想尝试一下,那么只需在命令行中输入python3 ,即可进入Python 解释器,在这里您可以输入 Python 代码并立即看到结果。
在 Shell #1 中执行
在 [ ] 中:
python3
你应该得到
Python 3.8.5 (default, Jul 28 2020, 12:59:40)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
当出现 Python 解释器提示>>> 时,就可以开始在命令行中输入或执行 Python 代码了。
注:键入exit() 并按回车键,可终止 Python 解释器并返回正常命令行提示$ 。
如前所述,您也可以在程序运行过程中更改变量的值。例如,我们可以执行以下步骤:
a = 5
a = 6
print (a)
因此,在最后的 print变量的值为 a的值为6 。
您可以在 Python 解释器内执行此 Python 脚本。
执行后,您应该会在单元格下方看到输出结果,就像这样:
>>> a = 5
>>>
>>> a = 6
>>>
>>> print (a)
6
>>>
但这还不是全部。Python 还允许您在运行程序时更改变量的类型。例如,您可以这样做
在 [ ] 中:
a = 5
a = 'This is now a string'
print (a)
在这里,当我们打印变量 a 时,会输出以下文本:现在这是一个字符串。
>>> a = 5
>>>
>>> a = 'This is now a string'
>>>
>>> print (a)
This is now a string
>>>
提示:您可以一直打开 Python 解释器,并使用快捷键Ctrl+L来清除屏幕。
- 练习 2.2 -
a) 在 ~/catkin_ws/src/robot_control文件夹中,创建一个新的 Python 脚本,名为 variables.py.在该脚本中,添加必要的代码,执行以下操作:
首先,您将调用方法
get_laser(),并将其响应存储到一个名为laser1.其次,您将打印这个值,以了解您得到了什么。
然后,您将再次调用
get_laser()方法,并将其响应存储在另一个名为laser2然后,再打印这个值,看看现在得到了什么。
最后,您将调用
get_laser()方法最后一次,使用不同的数字。现在,您将在同一个变量中存储其响应laser2.然后再次打印这个
laser2变量的值,看看现在得到了什么。
您应该会得到类似下面的输出结果:
[INFO] [1749724193.066836]: Robot Cooper...
[INFO] [1749724193.068492]: Checking Laser...
[INFO] [1749724193.156755]: Checking Laser...DONE
The laser1 value received is: 7.243560791015625
The laser2 value received is: inf
The laser3 value received is: 6.581600189208984
- 练习 2.2 - 结束
- 练习 2.2 的解法

请尽量自己做,除非遇到困难或需要灵感。如果你能为每一个练习而奋斗,你会学到更多。
变量.py
在 [ ] 中:
from robot_control_class import RobotControl
robotcontrol = RobotControl()
laser1 = robotcontrol.get_laser(0)
print ("The laser1 value received is: ", laser1)
laser2 = robotcontrol.get_laser(49)
print ("The laser2 value received is: ", laser2)
laser2 = robotcontrol.get_laser(99)
print ("The laser3 value received is: ", laser2)- 习题 2.2 的最终解答 -
因此,正如您所看到的,在 Python 中使用变量非常简单。在本单元中,我们已经多次提到数据类型,现在让我们来看看它们!
2.1.3 数据类型
Python 中的每个值都有一个数据类型。基本上,变量的数据类型表示该变量包含的内容:是数字?是文本?
Python 中有各种各样的数据类型。在本章中,我们将只介绍一些最重要的数据类型。
数字
弦乐
列表
元组
字典
数字
在数字数据类型中,我们可以将数字分为不同的类型。现在,我们只区分整数和浮点数。
在 [ ] 中:
a = 5 # This is an integer
a = 0.5 # This is a float
弦乐
字符串基本上是字符序列。我们可以使用单引号 (' ') 或双引号 (" ") 来表示字符串:
在 [ ] 中:
s1 = 'This is a string'
s2 = "This is also a string"
作为一个字符序列,字符串可以有下标或索引。字符串的第一个字符的索引为 0。因此,举例来说,如果我们有以下代码片段:
在 [ ] 中:
s1 = 'This is a string'
s2 = "This is also a string"
print (s1[0])
print (s2[8])
表达式 s1[0]指的是 s1字符串的第一个字符,而表达式 s2[8]则指字符串的第 9 个字符。 s2字符串的第 9 个字符。如果执行前面的脚本,将得到以下输出结果:
- 预期成果
>>> s1 = 'This is a string'
>>>
>>> s2 = "This is also a string"
>>>
>>> print (s1[0])
T
>>> print (s2[8])
a
>>>
- 结束语 预期成果
最后,您还可以连接不同的字符串。例如,请看下面的脚本:
在 [ ] 中:
s1 = 'This is' s2 = " a string" s3 = s1 + s2 print (s3)
因此,如果执行上述脚本,您将在 s3和 s1和 s2.
- 预期成果
>>> s1 = 'This is'
>>>
>>> s2 = " a string"
>>>
>>> s3 = s1 + s2
>>>
>>> print (s3)
This is a string
>>>
- 结束语 预期成果
列表
Python List 是一个有序的项目序列,列表中的所有项目不需要是同一类型。要声明一个 Python List,只需将所有项目放在括号[ ] 内,并用逗号分隔每个项目。请看下面的脚本:
在 [ ] 中:
l = [1, 2, 3, 'This', 'is', 'a', 'list']
print (l)
与字符串类似,我们也可以访问列表中的每个特定项目,甚至列表中的某个项目范围。请看下面的示例:
在 [ ] 中:
l = [1, 2, 3, 'This', 'is', 'a', 'list']
print (l[2])
print (l[0:3])
print (l[3:])
在第 1 次打印中,我们从列表中获取第 3 个项目(请记住,第 1 个项目是 0 位置)。
在第 2 次打印中,我们将获得第 1 次和第 3 次打印之间的所有项目。
在第 3 次打印中,我们将获得从第 4 次打印到最后一次打印的所有项目。
因此,如果执行脚本,就会得到类似下面的结果:
- 预期成果
>>> l = [1, 2, 3, 'This', 'is', 'a', 'list']
>>>
>>> print (l[2])
3
>>> print (l[0:3])
[1, 2, 3]
>>> print (l[3:])
['This', 'is', 'a', 'list']
>>>
- 结束语 预期成果
最后,还有一点很重要,那就是列表可以更新。请看下面的例子:
在 [ ] 中:
l = [1, 2, 3, 'This', 'is', 'a', 'list']
print (l)
l[2] = 8
print (l)
- 预期成果
>>> l = [1, 2, 3, 'This', 'is', 'a', 'list']
>>> print (l)
[1, 2, 3, 'This', 'is', 'a', 'list']
>>>
>>> l[2] = 8
>>> print (l)
[1, 2, 8, 'This', 'is', 'a', 'list']
>>>
- 结束语 预期成果
元组
元组由一系列用逗号分隔的值组成,这些值被括在括号() 中。元组的特点是不能更新,是只读的。因此,从根本上说,它们与列表相同,唯一的区别是元组内的值不能更新。请看下面的示例:
在 [ ] 中:
t = (1, 2, 3, 'This', 'is', 'a', 'tuple')
print (t)
- 预期成果
t = (1, 2, 3, 'This', 'is', 'a', 'tuple')
>>>
>>> print (t)
(1, 2, 3, 'This', 'is', 'a', 'tuple')
- 结束语 预期成果
字典
字典也类似于列表,因为字典包含一个值列表,并且可以更新。但主要区别在于,字典中的条目是通过键而不是位置来访问的。因此,字典基本上是一个项目列表,每个项目都是由键和值组成的一对。
请看下面的例子:
在 [ ] 中:
dict = {"Jon": 25, "Daenerys": 22, "Cersei": 31, "Night King": 35}
print (dict["Jon"])
print (dict["Night King"])
从上面的代码中可以看出,字典值是通过键来访问的。因此,如果执行上述代码,就会得到如下结果:
- 预期成果
>>> dict = {"Jon": 25, "Daenerys": 22, "Cersei": 31, "Night King": 35}
>>>
>>> print (dict["Jon"])
25
>>> print (dict["Night King"])
35
>>>
- 结束语 预期成果
与列表一样,词典也可以更新。
在 [ ] 中:
dict = {"Jon": 25, "Daenerys": 22, "Cersei": 31, "Night King": 35}
dict["Jon"] = 10
print (dict["Jon"])
- 预期成果
>>> dict = {"Jon": 25, "Daenerys": 22, "Cersei": 31, "Night King": 35}
>>>
>>> dict["Jon"] = 10
>>> print (dict["Jon"])
10
>>>
- 结束语 预期成果
提示:请记住,输入exit() 后回车(或quit() 或CTRL + D ),即可退出 Python 解释器。
太好了!介绍了这些新的数据类型后,让我们来做几个练习,以便将它们付诸实践!在下面的练习中,我们将介绍一种新方法,你可以在你的程序中调用它:
get_laser_full():顾名思义,这种方法可以获取机器人所有激光束的所有数据。正如我之前所说,总共有 720 个不同的读数。因此,调用该方法时,将返回一个包含所有 720 个不同激光束读数的列表。
- 练习 2.3 -
a) 创建一个新的 Python 脚本,命名为 lists.py.在该脚本中,添加必要的代码,执行以下操作:
首先,您将调用
get_laser_full()方法,并将其响应存储在一个 Python 列表中。然后,从完整的读数列表中打印位置 0、360 和 719。
- 练习 2.3 - 结束
- 练习 2.3 的预期结果
[INFO] [1749724277.624480]: Robot Cooper...
[INFO] [1749724277.627020]: Checking Laser...
[INFO] [1749724277.694681]: Checking Laser...DONE
Position 0: 7.243560791015625
Position 49: inf
Position 99: 6.581600189208984
- 结束语 预期成果
- 练习 2.3 的解法

请尽量自己做,除非遇到困难或需要灵感。如果你能为每一个练习而奋斗,你会学到更多。
列表.py
在 [ ] 中:
from robot_control_class import RobotControl
rc = RobotControl()
l = rc.get_laser_full()
print ("Position 0: ", l[0])
print ("Position 49: ", l[49])
print ("Position 99: ", l[99])
- 习题 2.3 的最终解答 -
- 练习 2.4 -
a) 创建一个新的 Python 脚本,命名为 dictionaries.py.在该脚本中,添加必要的代码,执行以下操作:
首先,您将调用
get_laser_full()方法,并将其响应存储在一个 Python 列表中。然后,您将创建一个字典,其中包含列表中的位置及其对应的键值对。请看下面的示例:
位置 1:5
第 52 位:32
位置 231:0
第 644 位:21
您将对列表中的以下位置执行此操作:0, 100, 200, 300, 400, 500, 600, 719.
最后,您将打印出生成的字典。
- 练习 2.4 - 结束
- 练习 2.4 的预期结果
[INFO] [1749724486.350524]: Robot Cooper...
[INFO] [1749724486.352122]: Checking Laser...
[INFO] [1749724486.399797]: Checking Laser...DONE
{'P0': 7.243560791015625, 'P10': 7.62423038482666, 'P20': 4.86594295501709, 'P30': 7.617183208465576, 'P40': 9.165175437927246, 'P50': inf, 'P60': 8.102754592895508, 'P70': 9.51919174194336, 'P80': 7.778250694274902, 'P90': 6.859456539154053, 'P99': 6.581600189208984}
- 结束语 预期成果
- 练习 2.4 的解法

请尽量自己做,除非遇到困难或需要灵感。如果你能为每一个练习而奋斗,你会学到更多。
字典.py
在 [ ] 中:
from robot_control_class import RobotControl
rc = RobotControl()
l = rc.get_laser_full()
dict = {"P0": l[0], "P10": l[10], "P20": l[20], "P30": l[30], "P40": l[40], "P50": l[50], "P60": l[60],"P70": l[70], "P80": l[80],"P90": l[90], "P99": l[99]}
print (dict)
- 习题 2.4 的最终解答 -
2.2 输入/输出方法
2.2.1 印刷
在本章中,我们已经多次使用 print方法很多次了,所以现在你可能已经知道它的用途了。基本上,print 方法用于写入程序的标准输出。这对于与程序交互的用户交流,让他知道发生了什么特别有用;但当我们要调试自己的程序时,它也非常有用。
请看下面的示例,了解打印方法的一些用途。
如果在上一个示例结束时退出了 Python 解释器,则启动它。
在 Shell #1 中执行
在 [ ] 中:
python3
在 Shell #1 中执行
在 [ ] 中:
a = 5
print ("Simple print")
print ("Now we print the variable a = " + str(a))
print ("Now we print the variable a = %d" % a)
print ("This is an example of a \n new line")
正如您所看到的,第 1 版印刷很简单。
第 2 次打印结合了常规打印和变量。请注意,我们正在将变量转换为字符串值。
第 3 次打印也是将常规打印与变量相结合。请注意,在这种情况下,我们不需要将变量转换为字符串值,因为我们使用的是
%格式。第 4 行打印显示了如何使用
/n表达式跳转到新行的示例。
- 预期成果
>>> a = 5
>>>
>>> print ("Simple print")
Simple print
>>> print ("Now we print the variable a = " + str(a))
Now we print the variable a = 5
>>> print ("Now we print the variable a = %d" % a)
Now we print the variable a = 5
>>> print ("This is an example of a \n new line")
This is an example of a
new line
>>>
- 结束语 预期成果
2.2.2 输入
在向执行程序的用户发送信息的同时,你可能还想让用户向你的程序提供一些数据。事实上,所有程序都需要与环境或 "外界"(通常是用户)进行通信。在编程中,这通常被称为 I/O(输入/输出)功能。
正如我们已经看到的,在这种情况下,输出将是 print()方法,而输入将由 input()方法执行。请看下面的示例:
在 [ ] 中:
name = input("What's your name? ")
print("Nice to meet you, " + name)
在 robot_control文件夹中,新建一个 Python 脚本,名为 input.py的 Python 脚本,并将上面显示的代码复制到文件中。现在让我们执行该文件,看看它是如何工作的。
在 Shell #1 中执行
在 [ ] 中:
python input.py
执行文件时,系统会要求您介绍自己的姓名,如下所示:

输入您的姓名,然后按回车键。最后,您应该会得到这样的结果:

每当调用输入法时,程序都会停止运行,直到用户输入并按回车键结束输入。
现在让我们看看另一个例子:
在 [ ] 中:
age = input("What's your age? ")
age2 = age + 1
print("So next year you will be %d years old!" % age2)
与前一个例子没有太大区别,不是吗?那么......你怎么看?它能正常工作吗?让我们一起来看看!
在 robot_control文件夹中,创建另一个 Python 脚本,名为 input2.py的 Python 脚本,并将上面显示的代码复制到文件中。现在让我们执行该文件,看看它是否有效。
在 Shell #1 中执行
在 [ ] 中:
python input2.py
因此,在介绍完您的年龄并按下Return键后,您将得到如下结果:

What's your age? 22
Traceback (most recent call last):
File "input2.py", line 3, in
age2 = age + 1
TypeError: can only concatenate str (not "int") to str
所以实际上是失败了!有趣......但你能猜到原因吗?事实上,代码中存在一些问题。
首先,您需要知道 Python 3 不会评估通过 input方法接收到的数据,而是以字符串的形式原样返回。这意味着 age变量将包含一个字符串。因此,在操作 age + 1中,我们实际上是要将一个字符串和一个整数相加。这种操作是不可能的,所以我们得到了一个错误。那么......我们该怎么办呢?
那么,如果我们要确保 age变量的内容是整数,最简单的方法就是明确地转换它。为此,我们可以使用 int()方法,就像这样
在 [ ] 中:
age = int(input("What's your age? "))该 int()方法将括号内的内容转换为整数。现在,我们确保 age变量将是一个整数,这样我们就可以将它与另一个整数相加。
用以下代码更新 input2.py文件中的代码:
在 [ ] 中:
age = int(input("What's your age? "))
age2 = age + 1
print("So next year you will be %d years old!" % age2)
更新后,尝试再次执行。
在 Shell #1 中执行
在 [ ] 中:
python input2.py
现在您会得到类似这样的结果:
What's your age? 22
So next year you will be 23 years old!
让我们做下面的练习。
- 练习 2.5 -
a) 创建一个新的 Python 脚本,命名为 test_input.py.
b) 在脚本中创建一个代码,执行以下操作:
首先,它要求用户输入一个 0 到 719 之间的数字。
其次,它会调用
get_laser()方法,将输入的数字作为参数。最后,它会将
get_laser()方法的响应。
预期输出:
Select a number between 0 and 99: 50
[INFO] [1749725517.830685]: Robot Cooper...
[INFO] [1749725517.832561]: Checking Laser...
[INFO] [1749725517.925339]: Checking Laser...DONE
The laser value received is: inf
- 练习 2.5 - 结束
- 练习 2.5 的解法

请尽量自己做,除非遇到困难或需要灵感。如果你能为每一个练习而奋斗,你会学到更多。
test_input.py
在 [ ] 中:
from robot_control_class import RobotControl
num = int(input("Select a number between 0 and 99: "))
rc = RobotControl()
a = rc.get_laser(num)
print ("The laser value received is: ", a)
- 习题 2.5 的最终解答 -
2.3 操作员
在 Python 中,运算符用于对变量和值执行操作。我们可以将运算符分为以下几个基本组:
算术运算符
赋值操作符
比较运算符
逻辑运算符
2.3.1 算术运算符
操作员 名称 示例 + 加法 1 + 1 = 2 - 分段 2 - 1 = 1 * 乘法 2 * 2 = 4 / 分部 5 / 2 = 2 % 模数 5 % 2 = 1
在 Python 解释器中输入以下内容:
在 [ ] 中:
a = 5
b = 2
print (a+b)
print (a-b)
print (a*b)
print (a/b)
print (a%b)
- 预期成果
>>> a = 5
>>> b = 2
>>>
>>> print (a+b)
7
>>> print (a-b)
3
>>> print (a*b)
10
>>> print (a/b)
2.5
>>> print (a%b)
1
>>>
- 结束语 预期成果
2.3.2 赋值操作符
操作员 示例 相同 = x = 5 x = 5 += x += 3 x = x + 3 -= x -= 3 x = x - 3 *= x *= 3 x = x * 3 /= x /= 3 x = x / 3 %= x %= 3 x = x % 3
使用 Python 解释器运行以下代码:
在 [ ] 中:
x = 5
x += 1
print (x)
x -= 2
print (x)
x *= 2
print (x)
- 预期成果
>>> x = 5
>>> x += 1
>>> print (x)
6
>>>
>>> x -= 2
>>> print (x)
4
>>>
>>> x *= 2
>>> print (x)
8
>>>
- 结束语 预期成果
2.3.3 比较运算符
操作员 手段 相同 == 平等 5 == 5 != 不平等 4 != 5 > 大于 5 > 4 < 小于 4 < 5 >= 大于或等于 5 >= 4 <= 小于或等于 4 <= 5
将以下内容直接粘贴到 Python 解释器中:
在 [ ] 中:
a = 5
b = 6
if (a == b):
你应该得到
>>> a = 5
>>> b = 6
>>>
>>> if (a == b):
...
请注意,解释器在期待缩进代码行时,会显示三个点... ,而不是标准的 Python 交互提示>>> 。我们必须按两次回车键(基本上是输入空行)来表示您不想再写缩进行。
现在粘贴以下内容,保留前导空格:
在 [ ] 中:
print ("a is equal to b")后添加一个缩进块是很重要的。 :.通过查找冒号来决定何时需要增加缩进。 如果不添加前导空格,就会出现这个错误:
IndentationError: unexpected indent
现在在 Python 解释器中一次一行地输入以下内容。 记住在每个冒号后添加缩进/空格 :以避免出现问题。 还要记得按两次回车键,表示缩进完成。
在 [ ] 中:
a = 5
b = 6
if (a == b):
print ("a is equal to b")
if (a > b):
print ("a is greater than b")
if (a < b):
print ("a is less than b")
if (a >= b):
print ("a is greater than or equal to b")
if (a <= b):
print ("a is less than or equal to b")
注意:复制并粘贴上面的整个代码块是行不通的,您必须逐行输入代码。
- 预期成果
>>> a = 5
>>> b = 6
>>>
>>> if (a == b):
... print ("a is equal to b")
...
>>> if (a > b):
... print ("a is greater than b")
...
>>> if (a < b):
... print ("a is less than b")
...
a is less than b
>>> if (a >= b):
... print ("a is greater than or equal to b")
...
>>> if (a <= b):
... print ("a is less than or equal to b")
...
a is less than or equal to b
>>>
- 结束语 预期成果
注:担心新 if的新表达?别担心,您将在下一章学到它!
2.4 意见
在编程过程中,在代码中添加注释是非常常见的。基本上,注释是代码中永远不会被执行的部分。这些注释对提高代码的可读性和第三方用户的理解能力非常有帮助。
在 Python 中,使用# 符号添加注释:
在 [ ] 中:
# This is a comment
print ("This is a demo to show how to use comments in Python")
2.5 结论
在第二课中,您已经学习了与 Python 有关的一些最基本(但也很重要)的概念,如变量和不同的数据类型。此外,您还学习了一些在大多数 Python 程序中都需要用到的基本语法。现在,有了所有这些概念,您就可以开始创建更复杂的 Python 程序了。那么......您还在等什么呢?
2.6 单元测验
点击页面左下角的右箭头按钮("转到下一单元")后,会出现以下窗口或类似窗口,其中包含一个测验:

如果由于某种原因没有显示,请告诉我们,我们会解决这个问题。

发表评论