面向孩子们的-Python-入门指南-全-
面向孩子们的 Python 入门指南(全)
一、你知道吗?
我为父母写了这一章的第一部分,其余部分是为孩子们写的。我希望在本章中让你相信编程和 Python 作为你孩子的第一门编程语言的重要性。如果你的孩子比你大(10 岁以上),他们可以自己阅读这些主题。在这一章的后半部分,我将向孩子们简要介绍他们可以用 Python 做的所有有趣的事情,他们将从我的书中学到什么,以及如何充分利用我的书。
那么,让我们开始吧。
什么是编程?
你有你的小工具——你的笔记本电脑、个人电脑、平板电脑、手机等等——只要你让它做什么,在合理的范围内,它就会做什么。怎么做?嗯,这是因为每次你给你的小工具分配任务时,它的预编程指令就会在后台启动。那些指令集被称为代码。
您会发现,您的小工具需要一套完整的指令来执行最简单的任务,如打开应用或执行计算。他们毕竟只是机器,只是一切的基础上的 1 和 0。他们不能独立思考,所以我们用代码让他们思考。
换句话说,编程是你的计算机说的语言,不同的编程语言是它理解/说的不同语言。你可能懂英语、法语和普通话,但你可能不懂意大利语或日语。类似地,从字面上看,有数百种编程语言(Python、JavaScript、C、C++、C#、Ruby 等。),你的电脑可能会说几个,或者只说一个,其他的听不懂。
为什么你的孩子应该学习编码?
既然你知道了什么是编程,以及它是如何运行数字世界的,我不应该给你很多理由来说服你教你的孩子编程,对吗?
但是,你可能仍然想知道为什么你的孩子需要学习编程,为什么他们现在要学习 ??。毕竟,在我们这个时代,人们在大学里学习编程,并且只有当他们决定成为一名程序员时。
嗯,我想我有几个理由可以让你相信,为什么在这个时代,不管未来的职业抱负如何,孩子们都应该学习编程,为什么他们现在开始学习是明智的。
编程就像数学
三十年前,没有人敢做出这样的声明,但是现在,时代变了,是的,编程确实像数学一样。它无处不在,就像数学一样。
至少在我们 18 岁之前,数学是我们教育要求的一部分,但今天并不是我们每个人都是数学家。那为什么数学被强迫灌输给我们?因为数学决定一切。我们在日常生活中需要基础数学,当然在大多数职业生涯中也需要。所以,我们学了从微积分到代数再到几何的所有东西,非常清楚长大后我们可能不会用到 90%的知识。
这正是今天编程的情况。一切都数字化了。从送餐到股市预测,应有尽有。计算机已经进入各个领域,包括建筑和制造等传统领域。现在大多数建筑设备都是数字化的,是什么驱动了它们?程序和数千行代码。
甚至艺术也被数字化了。因此,无论你的孩子进入哪个领域,他们的编程知识都将助他们一臂之力。
但除此之外,编码还通过培养逻辑思维和解决问题的能力来提高孩子的数学能力。
编码提高逻辑思维和创造力
一个矛盾的说法,但在这种情况下是正确的。您的孩子创建的每个代码块都将被逻辑驱动。
逻辑决定编程,一旦他们开始自己编码,他们将学会将一个问题分解成小部分,应用逻辑解决每个部分,然后最终将所有部分组合成一个连贯的解决方案。
这就是现实世界中解决问题的方式,不管是在哪个领域,他们将在孩提时代学习这种无价的技能。
但老实说,你的孩子会厌倦逻辑。这就是创造力的来源。这个世界是靠创造力和逻辑运行的,编程也是如此。
编程没有正确的答案。如果他们正在解决问题,他们如何解决并不重要。当然,有最佳实践,但是如果你让两个程序员解决同一个问题,很可能他们的代码块看起来完全不同。
因此,当他们在编程过程中提出一个解决方案,以及针对多个问题的多个解决方案时,他们也会培养创造力。
两全其美,你说呢?
编码是未来
让我们在这里非常诚实。我们正以惊人的速度走向一个完全数字化的社会。一切都数字化了。应用无处不在。人工智能每天都在世界上掀起新的浪潮。在我们知道之前,我们将拥有人工智能驱动的技术来清洁我们的房子和驾驶我们的汽车。
难怪编程在当今世界已经成为一项无价的技能,对程序员的需求每年都在增加。
因此,编码确实是未来,通过在年轻时学习编码,你的孩子将比他们的竞争对手有优势。听起来不错,但是如果你的孩子想成为一名机械工程师,为什么他们需要编程呢?还是金融分析师?
这使我回到我最初的论点。一切都被数字化了,编码无处不在,在每一个领域。所以,如果你的孩子有编程基础,那么他们不会脱颖而出吗?
例如,一个具有编程知识的金融分析师可以自己编写一个股票预测应用,从而为公司节省大量资源,或者他们至少可以流利地使用技术术语,从而更好地指导程序员,并为他们的老板节省数百个生产时间。
所以,不管你的孩子将来要学什么,编程都会帮助他们,在不久的将来,他们会有一项可以赚钱的技能,可以用来赚外快。
在他们十几岁的时候,他们不必以卖汉堡包的最低工资作为副业。他们可以作为一名软件开发人员从事自由职业,用一半的时间工作至少可以多赚三到四倍的钱。
或者更好的是,你的孩子可以决定成为一名企业家。正如你所知道的,几乎每个创业公司都以某种方式与编程和软件有关,所以作为一名程序员,你的孩子可以自己编写应用,轻松节省数万元的程序员费用。
我相信这些都是非常有说服力的论据,可以解释为什么你的孩子需要现在就开始学习编程。
为什么是 Python?
好了,现在你已经确信了你的孩子学习编码的好处,但是为什么是 Python 呢?在数十种流行的编程语言中,为什么要从 Python 开始呢?
我坚信 Python 应该是孩子现实世界编程的首选,让我来告诉你为什么。
Python 很简单
嗯,差不多就是这样。孩子们想玩得开心,如果我们想让他们学习编程,那就需要有趣和简单。Python 都是。
不像其他古老的语言,在创建第一个程序之前需要学习大量的语法和理论,Python 非常简单。语法简单易懂,逻辑性强。“打印”只是在屏幕上打印一些东西。很好记,对吧?没有很多记忆要做,你的孩子可以从一开始就开始编码和创作。
对于没有编程知识的初学者来说,它是完美的编程语言,对孩子来说更好,因为它也很有趣。
Python 有许多内置的儿童友好模块和库,可以帮助他们只用几行代码就能绘制图形、创建游戏和有趣的应用。
它可以做很多事情
现在,不要低估 Python,因为它很容易学。它可以用于从 web 开发到桌面应用开发到人工智能的几乎所有领域。
这种语言非常强大,它附带的库和模块甚至更强大。你什么都有附件。
你可以用 Turtle 创建图形,用 Tkinter 创建漂亮的桌面应用(就像你非常喜欢在笔记本电脑上使用的计算器应用),用 Pygame 创建专业游戏,用 Django 或 Flask 开发成熟的网站和网络应用,用大量简单易学的库应用机器学习(人工智能)算法。Python 有无限的可能性。
通过用 Python 开始他们的编程之旅,您的孩子不仅仅是步入了编码的世界,他们还用这个时代最受欢迎的(也是最受欢迎的)编程语言之一来武装自己。
还有什么?随着 Python 的受欢迎程度以及它在人工智能等快速发展领域的采用率不断增长,Python 显然会继续存在,因此您孩子的技能在未来不太可能过时。
从现在开始,我将向孩子们致辞。
Python 好玩!
你好。所以,你是来学 Python 的。它不仅易于上手,还附带了许多附加功能,让编程变得有趣。你想知道你能用 Python 创造的所有酷的东西吗?
游戏!
谁不爱游戏,我说的对吗?但是如果你能创造出自己的游戏,然后和你的朋友一起玩呢?如果你能做到这一点,你将成为班上最受欢迎的孩子。
还有什么?你可以随心所欲地改变游戏的功能。想要五条命而不是三条?太好了,再加两个。不够水平,你已经厌倦了?在你的游戏中编码更多的关卡!让这些水平变得格外困难,给自己一个挑战。你可以自由地做任何你想做的游戏,你甚至可以从你的朋友那里得到建议并应用到你的游戏中。
只需一点点编码,你就能修改你一直不满意的游戏,或者创造一个全新的你可以和朋友一起玩的游戏。
所以,你会在编码和编码之后(玩游戏的时候)玩得很开心。
图形和动画
对我来说,图形和动画是仅次于游戏的最好的东西。你呢?
想象一下,运行一个程序来实时绘制您创建的设计。一部动画怎么样?如果您可以创建设计和动画,并在您一直想创建和玩的游戏中使用它们,会怎么样?
就像我常说的,可能性是无限的,它们只受你的创造力和想象力的限制。和 Python 一起狂奔!
网站
你使用互联网吗?那你现在肯定已经访问了至少 100 个网站了。他们看起来很棒,不是吗?如果你能创建一个和你最喜欢的网站一样的网站会怎么样?
如果你学习 Python,你当然可以。
我说的不是简单的网站。我说的是有很多很酷的功能的大型成熟网站和网络应用。经过足够的练习,你甚至可以创建像脸书和 Instagram 这样的网站和应用。
应用
Python 自带了很多工具,就像你在游戏中使用的工具一样。这些工具在 Python 中被称为库和包。在这些库的帮助下,你几乎可以创建任何东西,包括应用。
你用笔记本电脑还是平板电脑?它有很多很酷的应用,对吗?有计算器应用、秒表/计时器应用、绘画应用等等。
如果你能创建那些精确的应用会怎么样?嗯,有了 Python,你当然可以。事实上,你将在本书中学习创建一些应用。你兴奋吗?
不仅如此,有了像 Kivy 和 PyQt 这样的包,你甚至可以开始用 Python 创建移动应用。我们不会在这本书里讨论这些包,但是正如你所看到的,你有很多使用 Python 的可能性。
咻!这确实是一个很大的列表。使用 Python,世界就是你的了,快来玩吧!
充分利用这本书
这一章(也是最后一章)将是仅有的两章包含大量文本。在剩下的章节里,我已经尽力让事情保持有趣和实用。
你会遇到很多例子来说明我们所涉及的每一个主题。将会有很多编码,所以我推荐你和我一起编码例子。尽量不要复制粘贴。把所有东西都打出来,这样你就可以熟悉编码了。
每一章都有很多活动、谜题和迷你项目,还有详细的、一步一步的解决方案。我建议遵循前几章的解决方案,但是一旦你足够自信,尝试自己解决难题/活动,然后用给定的解决方案进行交叉验证。
记住,编程没有错解!如果你得到了想要的结果,你就可以开始了。
这本书包括四个顶点项目(大项目)来巩固你的 Python 知识。我建议创建项目,但不要就此止步。尝试在每个项目中改变一些东西,让它成为你自己的。当然,不要忘记向你的家人、朋友和老师展示你的项目!
差不多就是这样。这是一本简单易懂的书,所以不要被它的篇幅所淹没。只要开始动手,开始编码。
摘要
在这一章中,我简要解释了什么是编程,以及为什么你的孩子需要在这么小的年龄就学习编程,而不管他们未来的愿望如何,这一章是写给父母(前半部分)和孩子(后半部分)的。我也给出了令人信服的论据,说明为什么 Python 应该是孩子首选的真实世界编程语言,以及孩子可以用 Python 做什么。我们在本章结尾简要概述了你将从本书中学到的一切,以及充分利用本书的最佳方式。
在下一章,我们将学习如何安装 Python 并创建和执行我们的第一个 Python 程序。
二、我们来装 Python 吧!
在这一章中,我们将深入了解什么是编程,以及如何用它来控制各种小工具。我们还将考虑在我们的系统中安装 Python。让我们开始吧!
说计算机的语言
语言是用于两个或更多人之间的交流,我说的对吗?但是如果有人用你不懂的语言跟你说话,你能听懂吗?当然不是。我也不会!
同样,你的电脑也不能理解它不会说的语言。所以,如果你只是看着你的电脑,用简单的英语命令它打开画图程序,它是听不懂你的。另一方面,如果你用它能理解的语言和它交谈,你肯定会得到回应。
编程语言是计算机理解的语言。Python 就是其中之一。如果你想让你的电脑或手机或 GPS 或平板电脑做些什么,你需要给它们指令。
当您点按画图应用的图标时,您的设备如何知道您实际上已经点按了它?它怎么能打开那个应用而不是别的呢?这是因为一个程序员可能写了一串代码,说当有人点击画图图标时,画图应用应该打开。如果他们修改了代码,写下点击那个图标应该打开谷歌 Chrome 浏览器,那么就会发生这种情况。
所以,一个程序员的工作极其重要。他们让设备工作。他们创造了设备的大脑,使行动成为可能。没有他们的代码,你每天使用的设备将只是一堆塑料、芯片和电线,除此之外别无其他。
所以,如果你学会了说计算机语言,你也可以给你的计算机,或者任何小工具,像这样的指令。一旦你擅长编程,你就可以创建像画图这样的应用或者像《我的世界》这样的游戏。
开始-安装 Python
现在你知道什么是编程了。它只是你给一个小工具/设备的一组指令,让它做你想让它做的事情。
那我们开始编程好吗?Python 是最简单的编程语言之一,所以这正是我们将在本书中学习的内容。
不过,在编写 Python 程序之前,您需要将它安装在您的笔记本电脑或计算机上。还记得我说过你的电脑需要说这种语言来理解你在说什么吗?
现在,您的计算机可能不会说 Python 语言。那是因为 Python 没有安装在里面。一旦你安装了它,你的电脑将在几秒钟内学会这种语言(是的,就是这么快!),然后当你用 Python 给它指令的时候,它会理解你并做出相应的反应。这是魔法!
我会给你一步一步的在你的系统上安装和运行 Python 的指导,所以跟着我做,好吗?我将对 Windows 和 Mac 分别给出说明,所以请直接跳到您设备上的说明。
在 Windows 计算机上安装 Python
让我们先看看如何在 Windows 设备上下载和安装 Python。这些步骤适用于 Windows 及更高版本。
下载 Python
- 在你的浏览器上打开以下链接:
www.python.org/downloads/
。
图 2-1
Python Windows 下载页面
- 点击下载按钮(看图 2-1 中的箭头)下载 Python 安装程序。记得我告诉过你编码是神奇的吗?你会看到现在的行动。当你打开页面时,它知道你使用的是 Windows 电脑,无需你告诉它。
在写这本书的时候,我已经下载了 Python 3.8.5 ,但是你可能正在下载一个更新的版本。不要担心那个。继续下载最新版本。
安装 Python
它知道你有一台 Windows 电脑,所以你现在必须安装Python 的 Windows 版本。让我们这样做:
-
Open the .exe file you just downloaded. You will see a popup like Figure 2-2.
图 2-2
Python 安装设置
-
Do not forget to click the checkbox that says “Add Python 3.8 to PATH” (Figure 2-3).
图 2-3
将 Python 添加到路径
-
Once you have ticked the box, click install now. The installation will start, and it will look something like Figure 2-4.
图 2-4
Python 安装进度
-
Wait until the green bar reaches the end, and you will see a message that says “Setup was successful” (Figure 2-5).
图 2-5
Python 设置成功消息
-
按下关闭按钮,你就完成了在电脑上安装 Python。万岁!
在 Mac 设备上安装 Python
接下来让我们看看如何在 Mac 设备上下载和安装 Python。如果您有一台 Windows 计算机,并且已经按照上一节中的步骤安装了 Python,则可以跳过这一节。
Python 通常预装在任何 Mac 设备中,但您的系统中可能有旧版本的 Python。拥有任何软件的最新版本都没有坏处,所以让我们更新我们的 Python,好吗?
下载 Python
图 2-6
Python Mac OS 下载页面
- 在你的浏览器中打开以下链接:
www.python.org/downloads/
(图 2-6 )。
- 点击黄色下载按钮下载 Python 安装程序。记得我告诉过你编码是神奇的吗?你会看到现在的行动。
你有没有注意到,当你从你的 Mac 设备访问下载页面时,它会自动显示“为 Mac OS X 下载最新版本”?那是因为 Python 网站的代码读取的是哪个操作系统(Windows,Mac 等。)您正在使用,并给了您自动下载的正确版本。很酷,对吧?
您的包将如图 2-7 所示下载。
图 2-7
Python 3.8.5 包已下载
在写这本书的时候,我已经下载了 Python 3.8.5,但是你可能正在下载一个更新的版本。不要担心那个。继续下载最新版本。
安装 Python
-
Open the installer and you will see a screen like Figure 2-8.
图 2-8
Python Mac 安装–简介
-
Click Continue, and you will get the following page (Figure 2-9).
图 2-9
Python Mac 安装–阅读我
-
Click Continue again, and you will get the following page (Figure 2-10).
图 2-10
Python Mac 安装–许可
-
Click Continue again (Figure 2-11).
图 2-11
Python Mac 安装–许可协议
-
While you are at the license page, you might get a popup like the preceding one. Click Agree, and you will get the Installation Type page (Figure 2-12).
图 2-12
Python Mac 安装–安装类型
-
We are almost there! Click the Install button, and your installation should start immediately. In certain cases, you might see a popup that asks for your username and password like the following one (Figure 2-13).
图 2-13
Python Mac 安装–认证
-
输入您的 Mac 用户名和密码,您就可以开始了。如果你正在使用你父母的系统,打电话给他们来帮助你完成这一步。
一旦完成这一步,您应该会看到安装开始(图 2-14 )。
图 2-14
Python Mac 安装–安装
图 2-15
Python 包
- 等到蓝条跑到最后。应该不会超过几分钟。一旦完成,你的 Python 包应该会打开(图 2-15 )。
恭喜你!你已经下载了 Python!没你想的那么难,是吗?让我们在下一节中尽情享受吧。
摘要
在本章中,我们学习了如何在 Mac 和 Windows 中下载和安装 Python。在下一章,让我们看看如何用 Python 创建我们的第一个程序。
三、你的第一个 Python 程序
在这一章中,让我们看看用 Python 创建和运行程序,并创建我们的第一个 Python 程序。
用 Python 创建和运行程序
好了,现在我们已经安装了 Python,让我们开始创建我们的第一个程序。我们不能只在 MS word 或记事本中编写 Python 程序。事情不是这样的。我们需要一个特定的应用,可以理解你写的 Python 代码。这个应用将处理你的代码并给出你想要的结果。
其中一个默认的 Python 应用叫做 IDLE 。它是集成开发和学习环境,由 Python 软件基金会开发。安装 Python 时会自动安装(图 3-1 ):
图 3-1
Python 在 Windows 上空闲
-
转到您的应用(在 Windows 或 Mac 中)并输入 IDLE(图 3-1 )。
-
When you open the application, the Python Shell will open. This is where we will type our Python programs and get our outputs (results) (Figure 3-2).
图 3-2
Python Shell
-
You can change the way the text looks in this application. You can increase the font, make the text bold, and change the font style. In order to do that, go to Options and click Configure IDLE (Figure 3-3).
图 3-3
配置空闲
-
When you click it, the following window will pop up (Figure 3-4).
图 3-4
Python 空闲配置窗口
-
让我们将字体大小更改为 29(查看突出显示的方块),并选中“粗体”复选框(如果尚未选中的话)。
这就是我们现在要改变的,但是正如你所看到的,你有更多的选择。您可以随意使用它们来格式化 Python Shell 的文本。
Python 交互模式(Python Shell)
使用 IDLE 运行 Python 程序有两种方式。默认的方法是直接在 Python Shell 中输入代码(图 3-5 )。
图 3-5
Python Shell 提示符
你看到箭头所指的兵种了吗?这被称为 Python Shell 提示符。它要求你在提示符后输入你的 Python 代码,这样它就可以运行代码并给出你期望的结果。
每次在 Shell 中键入 Python 代码,按回车键;它将运行该行代码并执行它。这非常方便,因为你可以立即得到结果。
你的外壳可以做数学
没错。您可以在 Python Shell 中进行数学运算。让我们试着做一些基本的操作,好吗?
我想向你证明,Python 不是你第一次学的外星语言。您可以进行极其复杂的数学计算,也可以得到 Shell 中的结果。想看看这是怎么回事吗?
好吧,让我们从简单的开始。在提示符下键入以下内容:
3 + 6
按回车键,你应该会看到下面的结果(图 3-6 )。
图 3-6
一个简单的数学问题
你的 Python 应用只是做数学吗?多酷啊。让我们试试更复杂的东西。
(235 * 542) / (564 + 123)
运行前面的数学表达式,您应该会看到以下结果(图 3-7 )。
图 3-7
能有多复杂?
你可以用计算器交叉验证结果。这是正确的。你可以让方程变得任意复杂,你的 Shell 不到一秒钟就会吐出结果。多试几个看看!
但你能做的就这些吗?数学问题?差远了!你甚至可以在屏幕上打印东西,这就是我们接下来要看的。但话说回来,它也不止于此。你可以用 Python 做很多事情。我不想一开始就给你太多压力,所以我们要慢慢来,好吗?
使用 Python 打印
Python 是一门非常易学的语言。证明?如果你想在屏幕上打印东西,只需使用“打印”命令。Python 或任何编程语言中预定义的代码/命令称为语法。
因此,将消息打印到屏幕上的语法如下:
print('Hello there!')
你需要在“print”后面加上左括号和右括号,并在引号内输入你的信息。它可以是单引号(“消息”)或双引号(“消息”)。
当您运行前面的代码行时,这就是您将得到的结果(图 3-8 )。
图 3-8
打印消息
但是在这里要小心。“print”中的“p”应该是小写的 p,如果使用大写的 p,会得到如图 3-9 所示的错误信息。
图 3-9
“打印”而不是“打印”
错误信息显示“打印”未定义。这是因为就 Python 而言,“print”不同于“Print ”,将内容打印到屏幕上的命令使用小写的 p。换句话说,Python 是区分大小写的。所以一定要使用“命令”或“语法”。
空闲脚本模式
还记得我说过用你的空闲写程序有两种方法吗?到目前为止,我们已经研究了第一种方法。乍看起来很容易,但你注意到它有问题吗?
使用 Shell 时,您可以获得每一行代码的输出,只要您编写非常简单的代码行,这就可以了。但是,一旦你开始编写实际的程序,你会想要一个应用,处理多行代码在一起,并给你最后的结果。您需要脚本模式来实现这一点。
让我们看看这是如何工作的。让我们印上同样的“你好!”语句,但现在处于脚本模式。
转到档 ➤ 新档(图 3-10 )。
图 3-10
打开一个新文件
一个无标题的文档将像下面这样打开(图 3-11 )。
图 3-11
无标题文档
进入文件 ➤ 另存为(图 3-12 ),用保存文件。py 扩展。。py 表示一个特定的文件包含 Python 代码,并且需要这样执行。
图 3-12
保存您的。py 文件
我们将文件命名为 print.py 。点击保存,你应该会看到你的文件名从无标题变成了 print.py,现在,你可以随意命名你的文件,但是只要确保保存类型是“Python files”或者你给出一个扩展名。或者两者都有,好吗?
现在,让我们再次键入我们的代码行(图 3-13 ):
图 3-13
编写您的代码行
print('Hello there!')
这就对了。你已经编写了你的第一个 Python 程序。呼呼!
让我们运行它,好吗?
转到运行➤运行模块(图 3-14 )。
图 3-14
运行程序
它会要求你再次保存代码。单击确定。您的 IDLE 应该再次打开 Shell 窗口,在最后一个提示中,您应该看到结果(“Hello there!”)打印出来,如图 3-15 所示。
图 3-15
输出(结果)
现在你已经运行了你的第一个 Python 程序,并且得到了你的第一个结果!又来了!
Python 活动:打印您的姓名(以及其他一些内容)
现在我们来到了我们的第一个 Python 活动。你要打印你的名字。实际上,我们为什么不做个小介绍呢?你要介绍你自己,并把介绍打印在屏幕上。
不要担心。这并不难做到。我会教你怎么做。让我们创造一个虚构的人物,给她取名苏珊·史密斯。让我们假设她 9 岁,她喜欢小狗。现在让我们向世界介绍她吧!
打开一个新文件,保存为 introduction.py,你知道怎么做吧?
现在,跟我来。在文件中键入以下内容:
print('Hello there!')
print('My name is Susan Smith.')
print('I am 9 years old.')
print('I love puppies! :)')
我们需要在屏幕上打印出多行,所以我们创建了多个打印语句。让我们保存刚刚创建的代码并运行它。进入运行 ➤ 运行模块。
图 3-16
打印到屏幕上的简介
我们的介绍在屏幕上(图 3-16 )!
现在,我希望你在介绍时也这样做。你叫什么名字?你几岁了?你喜欢什么?打印屏幕上的所有内容。去吧。这很容易做到。
恭喜你,你现在是一名初露头角的 Python 开发者了。
摘要
在这一章,我们看了 IDLE 和它的交互式编程环境。我们在 Python Shell 中尝试了一些数学问题,然后创建了我们的第一个 print 语句。然后我们学习了脚本模式以及一次编写和运行多行代码。我们以一个活动结束了这一章,在这个活动中,我们介绍了自己,并在屏幕上打印了多行代码。
在下一章中,我们将会看到在 Python 代码中使用数字,操作数字,等等。
四、Python 喜欢数字
在前一章中,我们学习了如何开始使用 Python。我们看了看为 Windows、Mac 和 Linux 下载最新版本的 Python,然后看了看使用 IDLE 创建我们的第一个 Python 程序。
让我们在这一章看看如何玩数字。我们将看看如何在变量中存储数字,以及在 Python 中可以使用的不同类型的数字。
Python 中的数字
数字在任何事情中都扮演着非常重要的角色,所以难怪它们在编程中也很重要。你想在未来成为一名顶尖的游戏程序员吗?那么你需要知道你的数字。你想让球去哪里?你的太空枪应该向你的外星人射出多少子弹?子弹应该有多快?你的角色应该跑多快,或者走多快,或者做任何事情多快?你需要数字来确定所有这些以及更多。
此外,一旦你开始编程和创建不同类型的项目,你会发现数字在几乎每一种编程中都扮演着重要的角色,而不仅仅是游戏。
所以,事不宜迟,让我们看看如何在 Python 中创建数字,如何存储它们,如何使用它们,等等。
存储您的号码
我们已经看过 Python 中的数字了,还记得吗?在空闲 Shell 中键入以下内容:
3 + 5
按 Enter 键,您将获得以下输出:
8
在 Python 中玩数字就是这么简单。但是你发现问题了吗?你对结果和数字真的无能为力。编程就是自动化,我说的对吗?但是现在还没有太多的自动化。
我们能做什么?那么,如果我们可以把这些数字存储在某个地方,这样我们就可以多次使用它们,会怎么样呢?如果我们把结果存储在别的地方,这样我们就可以用它来做进一步的计算,会怎么样呢?你明白我在说什么吗?
除非你开始储存你的价值观,不管是数字、字母还是单词,否则你在编程方面做不了什么。
好吧,这很好,但是你怎么储存它们呢?Python 中有没有一个秘密容器,把你想要的所有值都存储在里面,等你需要的时候拿出来玩?不完全是,但是你可以制造这样的容器。甚至更好,不是吗?您可以创建称为变量的信息容器,在其中存储您想要的值。你可以创建无限数量的容器!😮
那么,如何创建这些变量呢?
看看你的橱柜。你必须看到一个容器,里面装着你父母用来烹饪的每一种调味品,甚至是盐、胡椒和糖等常见的烹饪原料。你妈妈可能给它们贴了这样的标签,我说的对吗?
标有盐的容器里有盐,或者她可能有一个她理解的暗号。
类似地,你也要标记你的变量。有一定的规则来标记它们,但除此之外,你可以自由支配以任何方式标记你的变量,所以尽情享受吧。只要确保你以后阅读标签时能理解它们就行了。你需要知道你的容器里有什么,不是吗?
创建变量就是这么简单。决定一个标签/名称,并将其输入到您的 Shell 或脚本中,您就创建了您的变量。
但是如果变量中没有存储信息,它就没有用,你可以用“=”号来实现。我们在数学中用等号表示答案,不是吗?同样,在 Python 中,我们用它给变量赋值。变量在“=”的左边,值在右边。
让我给你看一些例子,让你更好地理解。
为什么我们不把上次计算中的数字存储在两个独立的变量中,这样我们就可以根据需要重用它们了?
让我们打开一个新的脚本文件(你知道怎么做),并将其保存为 numbers.py。我们将使用该文件来测试本章中的示例。
num1 = 3
num2 = 5
我将它们命名为 num1 和 num2,作为 number1 和 number2 的简写形式,所以当我回顾代码时,我记得它们指的是什么。
让我们测试一下 num1 和 num2 中是否真的存储了数字。我们为什么不把它们打印出来看看?
print(num1)
print(num2)
当我们运行前面的四行代码时,我们将得到如下结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
3
5
如您所见,变量确实存储了数字。所以,你的程序现在已经创建了两个容器,标记为 num1 和 num2,就像你妈妈标记盐和糖的容器一样。“num1”中包含值 3,“num2”中包含值 5。
让我们更进一步。我们为什么不创建另一个变量,叫做 sum,把两个数的和存储在里面呢?
sum = num1 + num2
print(sum)
当我们现在运行 numbers.py 时,我们将得到以下结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
3
5
8
太好了。“sum”保存现在“num1”和“num2”的总和。你看到这有多方便了吗?我们不必就此止步。我们实际上可以改变这些变量的值!我们试试换 num1。我将清除脚本文件,这是留给我的内容:
num1 = 3
print(num1)
num1 = 6
print(num1)
正如您在前面的代码中看到的,我们首先将 3 赋给 num1,然后将 num1 中存储的值更改为 6。让我们看看这是否可行:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
3
6
是的,它是!“num1”最初有 3 个,但现在它有 6 个存储在里面,如果你打印 num2,你会注意到值不变为 5。所以,我们实际上可以改变变量中存储的值。我们现在手里握着一个真正项目的雏形!
但是不要太兴奋。创建变量时有一些规则要遵循。不过不要担心,规则是相当温和的。确保在创建变量时遵循这些规则,否则会出现错误。
我将列出它们,以便您以后参考:
-
变量应该以字母或下划线(_)开头,不能有其他字符(不能有数字或特殊字符,如!、#、$、%等。).
-
变量只能包含字母、数字和下划线(_)。
-
变量区分大小写。“num1”与“Num1”不同。
很简单,你不觉得吗?但是我们都不喜欢理论,所以让我们来测试一下这些规则,看看它们是否正确。回到您的 Shell 提示符。我们先创建一个遵循规则的变量,然后我们打破规则,看看会发生什么。
_var5 = 1
当我运行前面的代码时,什么也没有发生。看起来前面的变量被接受了。它以下划线开头,里面只有字母和数字。
如果我违反了第一条规则呢?
1var_ = 1
糟糕,我收到一个错误,内容如下:
SyntaxError: invalid syntax
如果我的变量开始是正确的,但是没有遵循第二条规则怎么办?
var$s = 5
再次出错:
SyntaxError: invalid syntax
让我们看看规则 3 是否也是正确的。让我们回到我们的数字。这一个的 py。让我们删除文件中的所有其他内容,并键入以下内容:
num1 = 3
Num1 = 7
print(num1)
print(Num1)
当您运行前面的代码行时,您应该会看到:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
3
7
看那个!Num1 和 num1 中可能有相同的字母和数字,但是大小写(N 和 N)完全不同。因此,Python 变量确实是区分大小写的。
我们已经成功验证了所有规则。咻!
评论
“评论”在英语中是什么意思?你有什么评论吗?描述一下?类似的东西,对吗?
类似地,您可以在 Python 代码上编写注释来描述它们。你可以把它们写在你的代码行之前或之后。这些注释仅供参考,Python 既不会读取也不会执行。
每当您在键入任何内容之前添加“#”(散列符号)时,该特定行就成为客户端。然而,当你开始一个新行的时候,你又回到了你的常规编码。因此,您的“#”正好创建一行注释。
#This is a comment
您可以使用注释来描述代码行,这样当您稍后阅读您的脚本时,您就会明白发生了什么。你也可以和你的朋友分享你的代码,你的评论会帮助他们理解它。
当您使用“#”符号时,您会创建单行注释。如果你想让你的评论跨越多行呢?
这也有一个语法:
'''
This
is
a
multi-line
comment
'''
(or)
"""
This
is
a
multi-line
comment
"""
用三个单引号/双引号(不加空格)写下你的评论,这样你就有了一个多行的评论。
你的数字有不同的形式
现在我们知道了变量是如何工作的,以及如何使用它们来存储我们的数字。在我们继续玩之前,我想给你看样东西。您知道 Python 中有不同类型的数字吗?
是的,就像数学中有整数和带小数点的数字一样,Python 中也有整数和浮点数。您甚至可以让 Python 检查代码中使用的数字类型,或者将一种数字类型转换成另一种。现在让我们看看所有这些。
整数
整数称为整数,简称 int。
让我们再次清除 numbers.py,从下面的代码行开始:
num1 = 3
“num1”存储一个整数 3。任何不带小数点的数字都是整数。
你实际上可以检查一个数字是否属于特定的类型。Python 有这些叫做内置函数的东西,可以用来做很多很酷的事情。因为它们是内置的,因为它们已经内置到 Python 中了,所以你不需要知道它们在后台是如何工作的。你可以用它们来得到你想要的结果。
例如,有一个名为“type”的内置函数,带有一个小“t”,可用于查找数字的类型。让我们找出“num1”中存储的是什么样的数,好吗?
print(type(num1))
在前面的代码行中,我让 Python 查找 num1 的类型。同样,变量或数字应该在左括号和右括号内,就像我们处理 print()语句一样。然后,我将整个内容放在一个 print 语句中,因为我想打印结果。否则,我就看不到类型检查的结果。
让我们运行前面的代码行,看看我们会得到什么:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
<class 'int'>
给你。上面写着‘int’,意思是整数。
这也适用于负数。
num1 = -3
print(type(num1))
结果仍然是这样的:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
<class 'int'>
所以,正负整数都叫整数。
现在让我们为其余的类型做同样的事情,好吗?
浮点数
浮点数有小数点。即使只有一个小数点,也会被归类为浮点。
num2 = 5.5
print(type(num2))
如果您运行前面的代码行,您将得到以下输出:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
<class 'int'>
<class 'float'>
看那个。最后创建的变量中存储了一个浮点数。
同样,正负小数点数字在 Python 中都称为浮点数。让我们检查一下!
num2 = -5.5
print(type(num2))
结果将是这样的:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
<class 'float'>
是的,它是一个浮点数。
复数
现在,让我们看看复数。你在学校学过复数吗?这些数字有实部和虚部,对吗?如果你还没有在学校学过,但是你很好奇,我建议你自己去读一读。你可以请你的父母帮助你做这项研究。一个简单的谷歌搜索应该可以消除你的疑虑。这是一个非常有趣的数学概念。另一方面,你可以跳过下一部分。这个决定完全取决于你。我们不会在任何程序中大量使用复数,所以不用担心它们。
num3 = 2 + 3j
print(type(num3))
因此,2 + 3j 是复数,其中 2 是实数,3 是虚数。如果我们运行前面的代码行,最终输出将是这样的:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
<class 'int'>
<class 'float'>
<class 'complex'>
这就对了。最后一个数字是一个复数。我们实际上可以分别提取实部和虚部。你想看看是怎么回事吗?
如果您想从一个复数中提取实数,请键入该数字(或包含该数字的变量),然后在其后跟一个句点(。),然后在后面加上关键字“真实”。关键字类似于 Python 中预定义的工具/方法。它们在后台做我们不知道的事情,但是在前台给我们想要的输出。在我们的例子中,我们将能够成功地提取实数。
print(num3.real)
同样,对于提取虚数,键入“imag”而不是“real”。
print(num3.imag)
当您运行前面的代码行时,您将获得以下输出:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
<class 'int'>
<class 'float'>
<class 'complex'>
2.0
3.0
查看前面输出中的最后两行。2.0 是实数,3.0 是虚数。它们将被提取为浮点数。
我之前说过,你可以直接给出数字。但是在这之前你需要处理一些事情。
print(3 + 4j.imag)
如果您尝试运行前面的代码行,您的代码将会出错,就像这样:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
<class 'int'>
<class 'float'>
<class 'complex'>
2.0
3.0
7.0
Python 认为你的虚数是 7.0 而不是 4.0。为什么呢?嗯,那是因为 Python 把 3 和 4 相加,得到的结果是 7,再把 j 加进去。所以根据它,你的复数现在是 7j 而不是 3 + 4j。在本章的下一节,我会告诉你所有关于“执行顺序”的内容,但是现在,我想让你知道在处理表达式时括号的重要性。
如果我们将复数包装在()中,让我们看看会发生什么。
print((3 + 4j).imag)
运行前面的代码行,得到如下结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
<class 'int'>
<class 'float'>
<class 'complex'>
2.0
3.0
4.0
太好了。我们得到了想要的结果。因此,圆括号保持了表达式的原样。
数字之间的类型转换
您可以将一种数字类型转换成另一种。我们将使用更多的预定义函数(方法)来完成这项工作。
若要将浮点数或复数转换为整数,请使用 int()方法。让我们清空 numbers.py 文件,重新开始。或者,您可以在我们重新开始时创建并命名一个新的脚本文件,特别是如果您希望保存每个示例的话。
num1 = 3.0
print(num1)
print(int(num1))
在前面的例子中,我在变量“num1”中存储了一个浮点数 3.0。我先打印了准确的数字。然后,我使用 int()函数将“num1”转换为整数,并打印出来。让我们看看结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
3.0
3
看那个。小数点现在没了。但是如果我们有小数点后的数字呢?接下来会发生什么?
让我们将 num1 的值编辑为 3.45,然后再次测试。
num1 = 3.45
print(num1)
#convert the number to an integer
print(int(num1))
运行前面的代码行,您将得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
3.45
3
有意思。我们仍然得到 3,即使算上小数,这个数字接近 3.5。为什么会这样?那是因为 Python 正在做一个叫做舍入的东西。不管小数点是什么,当你进行整数转换时,它只是去掉小数点,保留整数。让我们试试 3.9,看看这是不是真的:
num1 = 3.9
print(num1)
print(int(num1))
运行上面几行代码,得到:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
3.9
3
我们还是没有拿到 4。☹:当你进行整数转换时,它只是去掉小数点,不管它们有多大。别担心。当我们查看 Python 中更多的内置数学函数时,您将了解如何基于小数点进行适当的舍入。
现在,让我们把一个复数转换成 int。
num1 = 3+4j
print(num1)
print(int(num1))
当我们运行前面的代码行时,我们得到如下结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
(3+4j)
Traceback (most recent call last):
File "C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py", line 3, in <module>
print(int(num1))
TypeError: can't convert complex to int
天啊,我们出错了!为什么会这样?理论上,把一个复数转换成整数是不可能的,因为,你会提取哪一部分呢?
但是,如果要提取实部或虚部,可以将转换成整数。让我们试试那个。
我先把提取的实数保存在另一个变量“r”里。
num1 = 3+4j
#Find the real part of the number
r = num1.real
print(r)
print(int(r))
在前面几行代码中,我提取了实数,将其赋给变量“r”,然后将其转换为整数。当我们运行前面的代码行时,我们将得到以下结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
3.0
3
接下来让我们将整数转换成浮点数。我们需要使用 float()内置方法。
num1 = 3
print(num1)
print(float(num1))
当您运行前面的代码行时,您将得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
3
3.0
成功转换!
这适用于复数吗?你怎么想呢?不,他们不会。我们将不得不再次提取实数或虚数,但是提取已经产生了浮点数,所以为什么要转换它们呢?
现在让我们把整数和浮点数都转换成复数。您必须使用 complex()函数来实现这一点。
num1 = 3
print(num1)
print(complex(num1))
运行前面的代码行,您将得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
3
(3+0j)
看那个!它把整数作为复数的实部,虚部是 0。
现在让我们用浮点数试试。
num1 = 3.5
print(num1)
print(complex(num1))
运行前面的代码行,您将得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/numbers.py
3.5
(3.5+0j)
它将整个浮点数作为复数的实部,虚部仍为 0。有意思!
迷你项目-你理解数字吗?
这不仅仅是一个小项目,这将是一个测试你对手头主题理解的活动。你懂 Python 中的数字吗?让我们看看!
我先描述一下问题陈述。我希望你在看我的解释之前先试一试。我们仍在一步一步地走,所以我已经确保这个活动不会太难。
问题陈述:创建三个变量(num1、num2 和 num3)并分别在其中存储数字 3、5.5 和 3 + 5j。然后,将 num1 转换为浮点数,将 num2 转换为整数。提取 num3 的虚数,替换 num3 中的虚数,并将其转换为整数。在屏幕上显示三个转换后的数字。用注释描述重要的代码行。
解决方案:
这是一个非常简单的问题,不是吗?不要担心,一旦我们涉及到更多的话题,你会看到更复杂、更有趣的内容。
以下是整个程序:
#Created num1, num2 and num3 and stored the respective values
num1 = 3
num2 = 5.5
num3 = 3 + 5j
#convert num1 into a floating point number
num1 = float(num1)
#convert num2 into an integer
num2 = int(num2)
#Extract the imaginary part of num3 and place it back in num3
num3 = num3.imag
#Convert the imaginary number (floating) into an integer
num3 = int(num3)
#Print everything
print(num1)
print(num2)
print(num3)
我已经在评论里描述了我所做的一切,就像问题所问的那样。代码和注释是不言而喻的,所以我相信您理解它们。为什么不尝试不同的组合和转换来更好的理解题目呢?
摘要
在这一章中,我向你介绍了数字以及如何在 Python 中使用它们。我们研究了使用变量存储数字,以及 Python 允许您创建和操作的不同类型的数字。
五、让我们一起玩转数字吧!
在前一章中,我简要介绍了在 Python 中使用数字、创建和存储数字以及可以使用的不同类型的数字。
让我们在这一章中通过看看如何使用你的数字来做计算,以及如何在 Python 的预定义数字方法中获得真正的乐趣,来看看如何使用这些数字。
拿出你的号码来玩吧
我们已经学习了在 Python 中创建和存储数字以及不同类型的数字。但是我们还没有对他们做任何事情,不是吗?
你想最终玩你的数字吗?没错。
你也可以用 Python 做几乎所有你在数学上做的事情。你可以把两个或两个以上的数相加,数乘,数除,数减,还不止于此!你可以比通常的计算多做一点。如果你一直在做同样的计算,编程还有什么乐趣呢?
你有能找到除法余数的运算符。是的,你没看错。你再也不用通过漫长的过程来寻找剩余的东西了。我打赌你的计算器不会这么做!
你也可以做指数运算。想求 5 * 5 * 5 的结果?那是 5 的 3 次方。Python 有一个单一的操作符可以用来做这件事。还有什么?想让数字和功率有多大就有多大,你还是会立刻得到你的结果。
基本数学运算
事不宜迟,让我们看看在 Python 中可以使用的所有操作。我将通过例子解释操作符是如何工作的。清除 numbers.py 文件或创建新的脚本文件。
先来看加法。需要使用“ + ”符号将两个数相加。如果要将三个数字相加,请使用“ + ”两次。就像你在数学课上做加法一样。
num1 = 5
num2 = 7
add = num1 + num2
print(add)
当您运行前面的代码行时,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
12
答案是正确的!让我们把事情变得更复杂,好吗?
num1 = 55.876
num2 = 100.54
#Add num1 and num2
add = num1 + num2
num3 = 1235.583
#Add the value in num3 to the current value in add
add = add + num3
print(add)
我们创建了两个数字“num1”和“num2”,将它们相加,并将结果存储在变量“add”中。然后,我们创建了另一个变量“num3 ”,并在其中存储了另一个数字。我们将“add”的当前值与“num3”相加,并将其存储回“add”中,然后打印“add”的最终值。让我们看看我们得到了什么:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
1391.999
用你的计算器交叉验证。我确信那是正确的答案。如您所见,您可以添加多个数字。你也可以改变你的变量的值,通过计算它的当前值,并把它重新存储(在编程中叫做重新赋值)回那个变量。
我们在 Python 里学过加法。同样的规则也适用于减法、乘法和除法。让我们快速地看一下它们。
你需要用“–”符号做减法,“ / ”做除法,“ *** ”做乘法。与数学不同,在编程语言中使用“ x 或“ X 进行乘法运算是行不通的。
num1 = 20
num2 = 10
#Addition
add = num1 + num2
print(add)
#Subtraction
sub = num1 - num2
print(sub)
#Multiplication
mul = num1 * num2
print(mul)
#Division
div = num1 / num2
print(div)
当您运行前面的代码行时,您会得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
30
10
200
2.0
你注意到什么了吗?每隔一次运算(加法、减法和乘法)都会产生一个整数作为输出,但是除法的结果是一个浮点数。记下这一点。在 Python 中除法总是产生十进制数。如果没有小数点,它只会以“ .0 ”结束结果,但它仍然是一个十进制(浮点)数。
Python 中的特殊数学运算
我们已经看了常见的操作符。现在来看看特别的。
你需要使用乘法运算符两次来做取幂运算。“**”是你要找的接线员。
因此,不要键入 2 * 2 * 2 * 2 ,这意味着 2 的 4 次方(2 乘以自身四次),您可以只键入 2 ** 4 ,您会得到相同的结果。如果你必须将 2 乘以 20 次,只需输入 2 ** 20 。有了这个操作员,您可以节省大量的时间和空间。
让我们看一些例子。
exp = 2 ** 4
print(exp)
exp = 2 ** 20
print(exp)
exp = 5.5 ** 3
print(exp)
exp = 5.5 ** 3.5
print(exp)
正如您在前面的代码中看到的,求幂运算也适用于浮点数。数字和指数(幂)都可以是浮点数。让我们看看结果,看看它是否有效,好吗?
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
16
1048576
16.5
19.25
是的,有效!
现在,让我们找到我们的余数。用模运算符“ % ”代替除法运算符“ / ”,就可以得到运算的余数。还记得一个数除以另一个数会发生什么吗?你得到一个商和一个余数,对吗?你的模数操作符也会做同样的事情,但是它只会返回余数而不是商。如果想求同一个运算的商,就用同一个数的除法运算符。
#Division
div = 5 / 2
print(div)
#Remainder
r = 5 % 2
print(r)
当您运行前面的代码时,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
2.5
1
你看到发生了什么吗?您得到除法的浮点值作为第一个结果,得到 5 / 2 的余数作为第二个结果。
但是如果你只需要商,而不需要带小数点的完整结果呢?你也可以选择!
它被称为楼层除法运算符。用两个正斜杠写,像这样:“ // ”。
它会将你的数字相除,只返回整数,忽略小数点。让我们用简单和复杂的例子做同样的尝试。
floor = 5 // 2
print(floor)
当您运行前面的代码时,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
2
看那个。我们只得到 2,而不是 2.5。2 是运算 5 / 2 的商。所以,如果你想分别得到商和余数,可以用除法运算得到商,用模运算得到余数。
让我们看一个更复杂的例子来测试这是否真的有效:
#Division
div = 100 / 15
print(div)
#Quotient
q = 100 // 15
print(q)
#Remainder
r = 100 % 15
print(r)
当您运行前面的代码时,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
6.666666666666667
6
10
当你把 15 乘以 6 时,你会得到 90。所以,100 / 15 的商是 6,余数是 10。我们得到了正确的答案。有效!
赋值操作
Python 有一种叫做赋值操作的东西,可以让我们变得简单。我们已经看过其中一个了。还记得等于,“ = ”的运算符吗?您可以使用该运算符为变量赋值。
让我们快速看一下剩下的部分。它们很容易理解。
还有就是 += 运算符。
a += 5 基本意思是 a = a + 5 。所以,如果你想给一个变量加一个值,然后把它重新赋给同一个变量,就用这个操作符。
同样,你有 -= 、 *= 、 /= 、 = 、 %= 、/=。
现在让我们看看所有这些例子。阅读以下代码行中的注释,了解每行代码的作用:
num = 5
#Add and re-assign 5
num += 5
#Ans -> 10
print(num)
#Subtract 5 from num
num -= 5
#Ans -> 5
print(num)
#Multiply the current value of num with 2
num *= 2
#Ans -> 10
print(num)
#Divide the value of num by 2
num /= 2
#Ans –> 5.0
print(num)
#Calculate num to the power 2 and re-assign it
num **= 2
#Ans –> 25.0
print(num)
#Find the quotient of num / 3
num //= 3
#Ans –> 8.0
print(num)
#Find the remainder of num / 3
num %= 3
#Ans –> 2.0
print(num)
当您运行前面的代码行时,您将得到以下结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
10
5
10
5.0
25.0
8.0
2.0
你在之前的行动中有没有发现什么奇怪的事情?我们从整数开始,但是当我们执行除法运算时,不管运算如何,其余的结果仍然是浮点型的。我们知道为什么我们在除法运算中得到一个浮点。除法总是产生一个浮点数。但是,为什么在其余的行动中仍然如此呢?
这是因为对浮点数执行运算总是会得到一个浮点数,即使另一个数字是整数。
什么先来?
Python,实际上任何编程,在执行数学运算的顺序上,都有一种叫做优先级的东西。你一定在数学课上也学过这个。
还记得 BODMAS 规则吗?它基本上是说,括号内的任何东西首先执行,然后是除法,然后是乘法,然后是加法,最后是减法。
Python 没有确切的规则,但它有一些类似的东西。
Python 中的优先级规则如下:
-
执行顺序从左到右。
-
括号具有最高的优先级。
-
然后是取幂运算符**。
-
然后是乘法(*)、除法(/)、地板除法(//)和模数(%)运算符。它们具有相同的优先级别。
-
最后,还有加法(+)和减法(-)运算符,它们也具有相同的优先级。
为什么我们不测试一下这些规则呢?
就拿下面这个表达式来说吧:2 + 3 * 5。
让我们在 Python Shell 中运行前面的表达式,看看会得到什么:
>>> 2 + 3 * 5
17
为什么是 17?既然执行顺序是从左到右发生的,那么 2 + 3 不是应该先执行得到 5 吗,结果(5)不是应该已经乘以 5 得到 25 而不是 17 吗?
这就是优先权的来源。尽管执行的顺序是从左到右,但是具有较高优先级的操作(在本例中是乘法)将首先执行,然后和的结果将被加到第一个数字上(在本例中)。
但是如果有括号会怎么样呢?
>>> (2 + 3) * 5
25
现在我们得到一个 25,因为即使加法的优先级比乘法低,括号的优先级最高,所以它们首先被执行。
如果有两个括号呢?
>>> (2 + 3) * 5 * (1 + 2)
75
前面的表达式是这样做的:(5) * 5 * (1 + 2) = 5 * 5 * 3 = 75。
当两个操作具有相同的优先级时,遵循从左到右的规则。既然你知道了数字中的优先级是如何工作的,为什么不写下不同的表达式,并猜测它们在 Python 中是如何执行的呢?然后您可以执行它们来验证您的结果。
有数字的酷东西
Python 是一口不断付出的井。你可以对数字做任何你想做的事情,以任何你想的方式操纵它们。怎么做?有一个很酷的小工具叫做数学模块。你还记得我告诉过你 Python 插件可以让你做很酷的东西吗?这是其中之一。
有了这个模块,你几乎可以用 Python 做任何你想做的事情。你可以找到一个数字的力量,它的平方根,地板,天花板,等等。让我们来看看这一部分中最重要的一些。如果你想知道更多,快速的谷歌搜索会给你一个你能用数学模块做的所有操作的列表。你有一堆预定义的方法/函数来帮助你完成这些事情。
我们开始吧!
可以找到十进制数的底数和上限数。那是什么?您可以将小数四舍五入为整数。但是如果你使用 floor 函数,它会把数字四舍五入到最小的整数。
打开一个新的脚本文件或清除您正在使用的脚本文件。
在使用 Math 模块中的任何预定义方法之前,需要先将其导入到脚本文件中。您需要使用“import”关键字来实现这一点。
import math
前面的代码行告诉我们的程序,我们正在将数学模块导入到我们的文件中。你注意到我们是如何用一个小“m”写“数学”的吗?务必做到这一点。如果你把它写成“数学”,你会得到一个错误,因为 Python 是区分大小写的。这适用于您在 Python 中使用的任何预定义函数或关键字。您需要在不改变拼写或大小写的情况下使用它们。
数字的下限和上限
好了,现在我们已经导入了数学模块,让我们开始操作吧。寻找一个数的底数的语法是math.floor(num)
,其中“num”或者是保存浮点数的变量,或者是数本身。这同样适用于 ceil。
import math
print(math.floor(5.6))
print(math.floor(5.3))
print(math.floor(5))
print(math.ceil(5.6))
print(math.ceil(5.3))
print(math.ceil(5))
当您运行前面的代码行时,您将得到以下结果:
RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
5
5
5
6
6
5
看那个!不管小数点是多少,floor 运算总是产生最小的整数,在本例中是 5,ceil 运算总是产生最大的整数,是 6。对整数的 Floor 或 ceil 运算对数字没有影响,您将得到与结果相同的数字。
幂和平方根
接下来,我们来看看超能力。还记得我们如何使用“**”运算符来计算一个数的幂吗?我们也有类似的数学运算。
它的语法是math.pow(num,power)
。
所以,如果你想找出 5 的 3 次方(5 * 5 * 5),你可以这样做:
import math
print(math.pow(5,3))
当您运行前面的代码时,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
125.0
结果是一个浮点数。试着用小数点工作,看看你会得到什么。
同样,您可以用 sqrt 方法求出数字的平方根。如果 5 * 5 是 25,那么 25 的平方根就是 5。我们来测试一下!
import math
print(math.sqrt(25))
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
5.0
结果又是浮点数。
数字的阶乘
你知道如何求一个数的阶乘吗?
3 的阶乘是3 * 2 * 1
,是 6。
5 的阶乘是5 * 4 * 3 * 2 * 1
,是 120。
你看到这里的模式了吗?不过,你不必再费力地计算阶乘了。Python 通过阶乘方法为您做到了这一点!
import math
print(math.factorial(5))
运行前面的代码,您将得到以下结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
120
是的,有效!
罪恶,cos,谭,等等
如果你知道 sin、cos、tan 和 log 是如何工作的,那么你会发现下一部分很有趣。如果你不知道这些概念,不用担心。一旦你在数学课上学会了这些概念,你可以回到这一节。
您可以通过相关的预定义方法找到数字的正弦、余弦、正切和对数。在我们开始之前,我想澄清一些事情。在任何预定义的方法中,我们在括号()内给出的值/变量被称为 参数 ,我也这样称呼它们。
import math
print(math.sin(2))
print(math.cos(5))
print(math.tan(2))
print(math.log(10,2)) #The first argument is the number and the second is the base
运行前面的代码,您将得到以下结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
0.9092974268256817
0.28366218546322625
-2.185039863261519
3.3219280948873626
你可以用你的科学计算器验证结果,你会发现结果是一样的。
这些只是你可以用数学模块做的一些操作。至少还有十几个。
在官方的 Python 文档中查看它们,如果你愿意,可以用它们来玩: https://docs.python.org/3/library/math.html
.
更多数值运算
你对数学的兴趣不仅仅局限于数学模块。有很多独立的功能也很酷。您不必导入数学模块来完成这些操作,但它们同样强大。
您想在一系列数字中找出最小的数字吗?然后使用“min”方法,给出每个你想要比较的数字作为该方法的参数,用逗号分隔。“max”也是一样。
import math
print(min(-100,100,40,25.64,200.3452,-253))
print(max(-100,100,40,25.64,200.3452,-253))
我给了 min 和 max 相同的数字列表。让我们看看结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
-253
200.3452
有效!–253 是最小值,200.3452 是最大值。
如果要在运算中把负数转换成正数,那么就用“abs”方法。
print(abs(-100))
上述代码将导致以下结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
100
使用随机数
如果你不想在计算中使用一个数字呢?如果你想让你的电脑为你选择号码呢?Python 为您提供了保护。
Python 还有另一个模块叫做“随机”模块,它带有一堆很酷的函数,可以帮助你的计算机在每次运行时选择一个随机数。
现在让我们来看看。您需要首先导入随机模块。是带小“r”的“随机”。
如果希望返回给定范围内的随机数,请使用 randrange()函数。
import random
print(random.randrange(1,11))
“random”是模块的名称,“randrange”是函数的名称。我在第二个参数中给了 11,因为 random 模块忽略了范围中的最后一个数字。所以,如果我给 10,那么我只会得到从 1 到 9 的随机数。因为我想包含 10,所以我给出 11 作为我的第二个参数。
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
10
当我再次运行时,我得到了这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
2
下一次:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
7
当您多次运行相同的代码行时,您会得到与我不同的结果。你为什么不自己试试看呢?
我们只是触及了随机模块的表面。从那来的还有更多。例如,你可以让你的程序用“choice”方法从你指定的单词或短语中选择一个字母。
import random
print(random.choice("Hello there!"))
打印前面的代码,您会注意到每次运行程序时都会得到一个字母(包括感叹号和空格)。
您也可以从一系列数字中进行选择。我们将在后面的章节中详细讨论列表,但是现在,只要理解列表包含一个数据列表,在我们的例子中,是一个数字列表,你应该把数字写在方括号中,用逗号分隔,就像这样:
import random
l = [1,3,5,7,9]
现在让我们的程序从这个列表中随机选择:
print(random.choice(l))
运行前面的代码;第一次,我得到了这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
3
后续运行会给我随机选择。试试看!
“random”模块的“random”方法返回一个介于 0 和 1 之间的随机浮点数。
import random
print(random.random())
当我运行前面的代码时,我得到了这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
0.6386828169729072
由于 randrange 只返回一个范围内的整数,所以我可以使用 uniform 返回一个范围内的浮点数。这里唯一的区别是该函数在其结果中考虑了范围内的两个数字。
import random
print(random.uniform(1,10))
当我运行前面的代码时,我得到了这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
3.7563014275306283
迷你项目-数字的倍数
在这个迷你项目中,我将教你如何用一个数的方法找到一个数的倍数。例如,如果我想显示 3 到 100 的所有倍数,我会这样做:
Python 中还有另一种预定义的方法,称为“范围”方法。我们通常只在学习循环时才知道这个方法(在后面的章节中),但是我想在这里介绍一下,因为从技术上讲,它是一个数字方法。
范围函数,顾名思义,产生一个范围。您需要将它写成 range(num),其中所有内容都用小写字母表示:
- 让我们在 Python Shell 中打印以下代码行:
>>> print(range(5))
运行前面的代码,您将得到这样的结果:
- 或者,您也可以给出一个范围内的开始和结束数字,如下所示:
range(0, 5)
>>> print(range(1,10))
运行前面的代码,您将得到这样的结果:
- 此外,您可以使用“*”运算符打印整个范围。不,不要把它和乘法运算符混淆。当某物(在我们的例子中,范围)有多个对象(在我们的例子中,多个数字)时,这个操作符用于打印。
range(1, 10)
让我们打开脚本并执行以下操作:
r = range(1,10)
现在,变量“r”包含范围。要打印“r”内的所有内容,即从 1 到 10 的数字列表,请使用“*”,如下所示:
- 在变量前指定“*”,这样 Python 就知道您正试图打印下一个变量中的所有内容。或者,您也可以像这样编写相同的打印语句:
print(*r)
print(*range(1,10))
运行这些语句中的任意一条,您将得到以下结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
1 2 3 4 5 6 7 8 9
是的,它工作了!
- 如果我运行这个:
print(*range(10))
我会得到这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
0 1 2 3 4 5 6 7 8 9
如您所见,如果您没有给出起始范围,那么它会打印从 0 到结束范围之前的数字。
- 您也可以使用第三个参数跳过范围之间的数字。如果您给 2 作为第三个参数,您的程序将打印该范围内的第二个数字。3 表示第三个参数将打印第三个数字,4 表示第四个数字,依此类推。
print(*range(0,10,2))
当您运行前面的代码时,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
0 2 4 6 8
你只打印出了 0 到 10 之间的偶数。多棒啊。您可以使用第三个参数跳过任何数字。
现在我们知道了所有这些,你能猜到我们如何应用这些来解决我们的问题吗?因此,我们需要找到给定范围内给定数字的倍数,我们知道我们将使用 range()函数来完成这一任务。
- 假设我们想找出从 1 到 100 的 3 的倍数,并把它们全部打印出来。所以,那是 3,6,9 直到 99,对吗?您可以在一行代码中做到这一点。在检查解决方案之前,您想亲自尝试一下吗?
试过?好了,现在来看解决方案!
print(*range(3,101,3))
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75 78 81 84 87 90 93 96 99
哇哦!很简单,不是吗?
我们只是把倍数作为第一个参数,因为它无论如何都会是第一个结果-3 * 1 = 3。然后我们指定 101 作为第二个参数,所以如果 100 是一个倍数,它将被包含在内。最后,我们再次将 3 作为第三个参数,因为我们每次都需要跳过三个数字。而且成功了!
现在,你为什么不尝试不同的倍数和范围,看看它如何为你工作?
摘要
在这一章中,我们继续看数字。我们研究了如何使用 Python 中不同的操作符来处理数字。我们还研究了如何使用“数学”模块和预定义函数来进一步处理我们的数字。我们最后看了“随机”模块,我们像往常一样用一个迷你项目完成了这一章。
在下一章,我们来看看 Python 中一个非常有趣的概念。我们将会看到使用 Turtle 模块来绘制图形。
六、使用turtle
画酷酷的东西
在前几章中,我们学习了如何在 Python 中处理数字。我们看了 Python 中不同类型的数字,可以做的各种操作,以及使用各种模块和预定义的方法来享受 Python 的乐趣!
在这一章中,我们将会看到 Python 中的另一个模块, Turtle 模块。我们将学习关于turtle
的所有知识,用它来绘制图形、形状、设计、文本等等。我们还会以一些很酷的迷你项目来结束这一章。
我们开始吧
你开始厌烦了吗?让我们从理论上休息一下,好吗?我答应给你快乐,现在是我兑现承诺的时候了。让我们用 Python 来画吧!你想知道怎么做吗?
好吧,我来给你介绍一下那个神奇的世界,那就是“乌龟”。 Turtle 是一个 Python 模块,它附带了大量工具(预定义的方法),你可以用它们在屏幕上绘图。天空是你用turtle
所能做的极限。
在这一章中,让我们从turtle
的基础开始,随着我们深入到这本书,我将向你展示你可以用turtle
和 Python 做的更高级的技巧。
不再有无聊的项目!从这一章开始,我们的迷你项目将会变得丰富多彩。你兴奋吗?我知道我是!
好吧,我们开始吧。
你为什么不创建一个新文件,随便你怎么命名?你可以用它来写这一章。不过要小心命名!不要将您的文件命名为 turtle.py,因为您的 Python 安装中已经有一个 turtle.py,使用相同的名称命名您的文件会导致运行时出错。除此之外,你可以给它起任何你想要的名字。我将我的文件命名为 drawTurtle.py。
在我们开始之前,我们需要将乌龟导入到我们的 Python 脚本文件中。turtle
只是一个附加品,记得吗?因此,除非您导入它,否则它不会出现在您的文件中。这个过程实际上非常简单。只需输入“进口”,然后输入带小“t”的“海龟”。
import turtle
好极了。我们已经将 Turtle 导入到脚本文件中。接下来让我们创建我们的屏幕。 Turtle 创建图形,如果你注意到了,你的 Python Shell 并没有正确显示图像或绘图。因此,我们将创建我们自己的屏幕,在那里我们的绘图将出现。
让我们创建一个变量“s”(你可以随意命名)。我们将使用 turtle 的 getscreen()预定义函数从 turtle 获取我们的屏幕,并将其分配给 s ,如下所示:
s = turtle.getscreen()
现在,变量“s”包含了我们的龟屏(图 6-1 )。让我们运行前面的代码行,看看我们会得到什么。
图 6-1
蟒蛇龟屏
您是否看到了一个类似于上图的弹出窗口,中间有一个黑色标记?那是我们的乌龟。
现在我们有了屏幕,让我们创建我们的turtle
!迷茫?不要这样。在 turtle 中,一只乌龟会画出你在屏幕上命令的任何东西。字面意思。会很酷的,你会看到的。海龟包里还有另一个预定义的函数 Turtle()(海龟太多了,我知道:D)。它有你需要在屏幕上画画的所有工具,像画线、画圆、给它们上色等等。让我们得到这个函数,并把它赋给一个变量 t,这样我们可以在以后绘图时使用它。
t = turtle.Turtle()
记住 Turtle()函数中的“T”是大写的。
当您现在运行代码时,您不会看到任何变化。它仍然是相同的空白屏幕,但我们现在已经设置好了一切。前三行代码(import、getscreen 和 turtle())在每个涉及 Turtle 图形的程序中都是常量,所以总是从这些代码开始,我假设您已经在我未来的示例中包含了这些代码行。
接下来我们画画吧!
让你的 turtle
动起来
现在我们已经准备好了一切,让我们让我们的乌龟按照我们想要的方向移动,并在它移动的时候画画。我们的乌龟要画直线,我们要给它这些线的距离和方向。听起来不错?让我们看看它是如何工作的。
向前和向后移动
先从基础的开始测试,前进后退。
要向前移动,需要使用 Turtle()函数的 forward()预定义方法,在括号内,需要给出距离。所以,如果你想让你的海龟向前移动(并画出)100 点,你要在括号内给 100 点,就像这样:
t.forward(100)
我们在前面的例子中给出了t.forward()
,因为 forward()函数也在变量 t 的内部,因为我们把 Turtle()内部的所有东西都赋给了它。
让我们保存并运行我们的脚本,我们将得到这个(图 6-2 )。
图 6-2
前进 100 分
太好了!我们得到了一条向前的直线,它停在 100 点,正如我们所希望的。
你如何让它向后移动?是的,你猜对了!通过使用 backward()函数。但是有一个条件!如果你现在让你的海龟后退,它只会越过当前的线,你什么也看不见。让我们测试一下。
t.backward(100)
运行前面的代码,你会得到这个(图 6-3 )。
图 6-3
落后 100 分
是的,一点都没变。看我画的指向turtle
起点的箭头。我们的乌龟只是回到了那个起点,却没有画出什么新的东西。
有一种方法可以解决这个问题。还有一个函数叫做 home(),它会让你的海龟回到家(起始位置)。所以,在我们给出 backward 命令之前,为什么不用 home()让 turtle 回到位置呢?
整个代码片段将如下所示:
import turtle
s = turtle.getscreen()
t = turtle.Turtle()
t.forward(100)
t.home()
t.backward(100)
当我们运行前面的代码时,我们会得到这个(图 6-4 )。
图 6-4
前进、回家和后退
耶!我们的乌龟从出发位置出发,向右(向前)画了一条 100 点的直线,然后回到出发位置(它确实是边走边画的,但是因为它画过了原来的线所以你没看到),再向左(向后)画了一条 100 点的直线。它完美地工作。
或者,您可以只给t.backward(200)
来获得相同的结果。
运行代码时,您注意到什么了吗?海龟(Turtle)实时为你画出这些线条。是不是很牛逼?
让你的乌龟改变方向
不能一直向前向后画。你需要改变方向来画出合适的形状。这就是天使出现的地方。你在学校学过角度了吗?如果没有,也不用担心。我来快速解释一下概念。这很容易。
看图 6-5 。
图 6-5
在 Turtle 中使用角度来改变方向
在 Python 的海龟模块中,角度基本上就是方向。所以,如果你想让你的海龟从现在的位置(家)一直往前走,那就直接说往前(100)。如果你想让它直接向上,那么首先通过向左(45°)或向左(45°)改变方向。现在,如果你给 forward(100)或类似的东西,你会得到一条向上的线,就像我在前面的图中画的一样。类似地,向下,再次使用 90 度,但这次是向右(90 度)。对于其余部分,您可以参考前面的图像,并决定您需要使用哪一行代码来改变方向。
如你所见,如果我们想让我们的turtle
转完整个圈,也就是向下画而不是向右画,那么我们需要给 90 度作为我们的角度。现在让我们来测试一下。我假设你已经输入了三行强制性的海龟代码。然后,键入以下内容:
t.forward(100)
t.right(90)
t.forward(100)
我们首先让海龟向前移动 100 点。然后我们让它右转 90 度,这是一个急转弯(对画正方形和长方形有用)。现在,我们的海龟面朝下,我们让它再向前移动 100 点。
当我们运行前面的代码行时,我们会得到这个(图 6-6 )。
图 6-6
右(90)
现在让我们向左移动 90 度,看看我们会得到什么。
t.left(90)
t.forward(100)
当你运行这个脚本时,你会得到这个(图 6-7 )。
图 6-7
左(90 度)
看,它向左急转弯了。
恭喜你!你现在有四个最强大的工具供你使用,你可以用它们来画很多东西。你想从几个很酷的造型开始吗?
让我们从简单的开始,好吗?正方形怎么样?
迷你项目-画一个正方形
不要马上看解决方案。编程中同一个问题有很多解法,尽量自己找,然后再看我的。
好吧,我会让我的解决方案非常简单。我要用向前和向右。我的正方形的长度和高度都是 100 点。
这些是我要用来画正方形的步骤:
-
我先让乌龟向前移动 100 点,然后右转 90 度。
-
然后再向前移动 100 点,画出正方形的第二条边,再右转。
-
再次向前画第三条边,再次右转。
-
再次向前画第四条边,也是最后一条边。
让我们将前面的说明转换成代码:
import turtle
s = turtle.getscreen()
t = turtle.Turtle()
t.forward(100)
t.right(90)
t.forward(100)
t.right(90)
t.forward(100)
t.right(90)
t.forward(100)
让我们运行前面的代码行。你会看到 turtle 用我们的命令实时绘制(图 6-8 )。
图 6-8
画一个正方形
耶!我们得到了我们的广场!
你可以只输入t.home()
而不是最后的t.forward(100)
,你会得到同样的结果。你为什么不试试看?
迷你项目-画一个六边形
对于我的六边形,我将遵循与我的正方形相同的规则。唯一的不同是我每次都要让我的乌龟转 60 度,因为这是六边形的边所在的角度(图 6-9 )。
图 6-9
六边形的角
此外,我将使用六次 forward 函数,而不是四次,因为我需要它来绘制六条边。
看看下面的代码。很容易理解。
import turtle
s = turtle.getscreen()
t = turtle.Turtle()
t.forward(100)
t.right(60)
t.forward(100)
t.right(60)
t.forward(100)
t.right(60)
t.forward(100)
t.right(60)
t.forward(100)
t.right(60)
t.forward(100)
为一个形状键入所有这些代码行有点乏味,你不觉得吗?别担心。当我们看自动化时,我将教你如何用几行代码画出你想要的任何形状,任何次数。我保证等待是值得的。
当你运行前面的代码时,你会得到这个(图 6-10 )。
图 6-10
画一个六角形
又来了!
快捷指令
每次向前、向后、向右和向左打字有点乏味,你不觉得吗?为什么我们不缩短每件事,让事情变得简单些呢?可以写成 fd 、 bk 、 rt 、 lt 来代替。
让我们用我们的正方形试试我们的捷径。
import turtle
s = turtle.getscreen()
t = turtle.Turtle()
t.fd(100)
t.rt(90)
t.fd(100)
t.rt(90)
t.fd(100)
t.rt(90)
t.fd(100)
运行前面的代码,你会得到这个(图 6-11 )。
图 6-11
快捷方式 fd、bk、lt 和 rt
我们成功了,耶!
现在我要你让你的想象力自由驰骋。想画什么就画什么。只需输入你的代码,运行它,查看结果,并进行修改。创建尽可能多的形状。尽情享受吧!
转到屏幕上的随机点
到现在为止,你可能已经是让 turtle 在屏幕上画直线并操纵它们得到不同形状的专家了。但这难道不是一个繁琐的过程吗?您实际上是编写两行代码来绘制每一条直线——向前或向后绘制,然后向右或向左改变方向。
如果你可以命令你的turtle
去一个特定的位置,当它去的时候画一条直线,它就这样做了,会怎么样?没有角度,没有前进,什么都没有。类似这样的事情会节省你的时间和空间,不是吗?
你当然可以用预定义的函数 goto 做类似的事情。但是,不要像你做向前和向后那样,仅仅指定你想让你的乌龟移动的点数,你需要指定你想让乌龟移动到的确切坐标。
什么是坐标?你在学校学过它们吗,也许是在你学图形的时候?如果没有,也不用担心。我现在解释一下。
图 6-12
海龟坐标
看前面的图片(图 6-12 )。turtle
平时(家)出发的点就是标有(0,0)的大红点。第一个 0 是 x 值,第二个 0 是 y 值。你注意到这些线被标记为 X,–X,Y 和–Y 了吗?这些被称为轴。不用太担心轴和坐标。如果你还不知道他们,你只需要知道足够多,知道把你的海龟送到哪里。
x 值向右正增加,向左负增加。Y 值向上正增加,向下负增加。现在你知道了,你也知道(x,y)是坐标的写法,再看一下图像。你看到坐标现在是怎么写的了吗?
(200,200)是它所在的位置,因为 x 在正 200,y 也在正 200。所以,如果你给 goto(200,200),那么你将从(0,0)画一条直线,这是 turtle 的默认起点,到(200,200),这将是一条对角线(图 6-13 )。
图 6-13
(0,0)到(200,200)
用 goto 画一个正方形
好了,现在你知道坐标是如何工作的了,让我们用它来画点东西。正方形怎么样?
我将从默认值(0,0)开始。我不必提及这一点,因为默认情况下 Turtle 会这么做。然后,我将向上移动到(0,100),然后向右移动到(100,100),向下移动到(100,0),最后回到(0,0)。你为什么不参考坐标图像来看看这些点在哪里?
现在让我们编写代码:
import turtle
s = turtle.getscreen()
t = turtle.Turtle()
t.goto(0,100)
t.goto(100,100)
t.goto(100,0)
t.home()
t.home()会让海龟回到(0,0)的位置。
当你运行前面的代码时,你会得到这个(图 6-14 )。
图 6-14
带 goto 的正方形
看看,你只用了四行代码而不是七行代码就画出了同样的东西。你为什么不摆弄坐标,画更多的正方形或其他形状呢?
迷你项目-画一个曼荼罗(只有直线)
在这个迷你项目中,我们将把你的绘画提升到一个新的高度。我们要画一个曼荼罗,但是只用直线。好吧,我承认。只有线的曼荼罗不是真正的曼荼罗,但是,嘿,它仍然是曼荼罗,所以让我们跟随它。我们将在未来的课程中学习绘制更复杂的曼荼罗,所以请耐心等待!
我们开始吧,好吗?首先,我们要在底部画一个正方形,并从正方形的每一边画四个倾斜的正方形:
-
让我们先从基础做起。
#Mandala with lines import turtle s = turtle.getscreen() t = turtle.Turtle()
-
Now, we’re going to create our base, our square. It’s going to be a square of 100 points on each side, starting from the point (0,0), moving upward to (0,100) for the first side, then right toward (100,100) for the second side, then down to (100,0) for the third side, and going back to home (0,0) for the last side.
#Create the square base first t.goto(0,100) t.goto(100,100) t.goto(100,0) t.home()
When we run what we have so far, this is what we’ll get (Figure 6-15).
图 6-15
第一步——画出正方形的底部
-
接下来我们画第一个倾斜的正方形。
现在,我们的笔在(0,0)。我们将要求它画一条对角线到点(50,50)(正方形的中间),然后在点(0,100)会合,这将在正方形内给出一个圆锥形。
#First tilted square
t.goto(50,50)
t.goto(0,100)
当我们运行前面的代码时,我们会得到这个(图 6-16 )。
图 6-16
第 2 步–第一个倾斜的正方形,第一部分
-
Now let’s draw the same shape outside of the square to complete our first tilted square. Let us have our Turtle go to the exact opposite of the point 50,50 which is –50,50 and then again back home.
t.goto(-50,50) t.home()
When we’re done, we’ll get something like this (Figure 6-17).
图 6-17
步骤 3-完成第一个倾斜的正方形
-
我们有了第一个倾斜的正方形!耶!现在来看下一个。
第二个很简单,真的。我们只是从 0,0 到点 50,-50(在方块下面),然后在 100,0 处会合。然后我们要去方块的对面到 0,100,准备画下一个方块。
#2nd tilted square
t.goto(50,-50)
t.goto(100,0)
t.goto(0,100) #Getting ready to draw the next tilted square
当我们运行前面的代码时,我们将得到这个(图 6-18 )。
图 6-18
步骤 4–第二个倾斜的正方形
-
From the point 0,100, let’s draw the next tilted side to 50,150. Then let’s go back to 100,100 from there, we’ll get a conical shape again. Then, when we go to the center of the square to 50,50, we’ll have our third tilted square (Figure 6-19).
#3rd tilted square t.goto(50,150) t.goto(100,100) t.goto(50,50)
图 6-19
第五步–第三个倾斜的正方形
-
从中心 50,50,到 100,0,这样我们可以准备完成第四个倾斜的正方形。转到 150,50 开始圆锥形,转到 100,100 结束圆锥形。
#4th tilted square t.goto(100,0) t.goto(150,50) t.goto(100,100)
当我们运行整个脚本时,我们将得到这个(图 6-20 )。
图 6-20
第六步–第四个倾斜的正方形
哇哦!是的,我们有一个基本的曼荼罗形状,但是当我们完成学习剩余的好东西乌龟的时候,你可以定制这个形状到你想要的任何形状!
摘要
在这一章中,我们看了 Python 的图形模块 Turtle ,如何使用它通过使用向前、向后、向右和向左来绘制线条,同时也使我们的乌龟走向各自的坐标点。我们还学习了用 Python 绘制正方形、矩形、六边形等形状,并以两个迷你项目结束了这一章。
下一章,让我们更深入地研究turtle
;学习如何画圆、点、半圆和圆弧;让事情变得丰富多彩;并编写更多有趣的迷你项目!
七、深入turtle
在前一章中,我们介绍了 Python 中的 Turtle 库。我们看着用turtle
画线条和形状,我们甚至学会了如何画一个完全由线条组成的曼荼罗图案。
在这一章中,我们将更深入地了解一下turtle
。您将学习如何为您的设计绘制颜色,以及绘制各种形状、大小和角度的圆形和弧形。您还将学习如何在屏幕上绘制文本。在这一章的最后,你将学会如何改变你绘画的角度,并最终画出笑脸或任何类型的图画。
自定义您的屏幕
没有颜色的图形和图像有什么用?现在,你的屏幕看起来很无聊。它有一个白色的背景,你的屏幕标题永远是“蟒蛇龟图形”。但是你可以改变这一切。
首先,你可以用 title 方法改变你的屏幕标题,但是要记住一些事情。这个函数不是 t (turtle)的一部分。乌龟)。你需要以 turtle 开头,实际的包,就像这样:
turtle.title('Hello Turtle!')
你的背景颜色也是一样。您需要使用 bgcolor 方法来更改您的背景颜色,并在单引号(')或双引号(")内指定您的颜色。
我将把我的屏幕背景色改为红色。
turtle.bgcolor('red')
你想看看我们做的改动吗?看黄色箭头(我在图 7-1 中画的)。我们的标题现在写着“你好海龟!”我们的屏幕是红色的。完美!
图 7-1
背景颜色设置为红色
尝试将您的屏幕更改为不同的颜色或标题。
你也不局限于基本的颜色。跟着这个链接: https://en.wikipedia.org/wiki/Web_colors
。
你会在上面找到上百种颜色的名字。让你的想象力自由驰骋!
定制您的图形
你知道如何改变屏幕的背景颜色。太好了。但是图像颜色呢?彩色笔和用颜色填充的图像是任何一幅好画的主食,不是吗?
因此,您可以更改笔的颜色(图形的轮廓)和图形的颜色(填充颜色)。如果你觉得龟(笔)的速度太慢,你也可以为你的线条设置一个尺寸,并改变它的速度。
要更改笔的颜色,请使用 pencolor 函数(按原样用所有小写字母编写函数),并给出颜色的名称作为参数(括号内的内容)。我将使用上一节中我给你链接的颜色表中的一种颜色。
同样,要更改填充颜色,请使用 fill color 函数。您可以使用 pensize 函数增加笔的大小(线条的粗细),并给出一个数字作为参数。指定一个大于 2 的数字才能真正看出差异,因为 1 是默认的钢笔大小。此外,您可以使用速度功能来提高笔的速度。默认的速度值是 1,所以给出比这个值更大的值,你会看到一个变化。
让我们应用所有这些,看看结果。
import turtle
s = turtle.getscreen()
t = turtle.Turtle()
turtle.title('Hello Turtle!')
turtle.bgcolor('DarkOrchid')
t.pencolor('Salmon')
t.fillcolor('Chartreuse')
t.pensize(5)
t.speed(7)
t.goto(0,100)
t.goto(100,100)
t.goto(100,0)
t.home()
好吧。我已经指定了背景颜色为“暗兰”,钢笔颜色为“鲑鱼”,填充颜色为“黄绿色”,钢笔大小为 5,速度为 7。我还用 goto 画了一个正方形。来看看有没有效果(图 7-2 )。
图 7-2
设置速度、大小、笔色和背景色
这在一定程度上起了作用。我的笔画得太快了,这次没看到它画(真扫兴)。线条粗,笔色确实是三文鱼色,但是填充色在哪里?
那是因为 Turtle 希望你指明你希望填充开始和结束的时间,这样它就不会不小心填充了不该填充的东西(就像只是两条线连接在一个点上)。
当希望填充开始时,需要使用 begin_fill()方法,当希望填充结束时,需要使用 end_fill()方法。
因此,在我输入了更改颜色、大小和速度所需的代码行之后,这就是我在绘制形状时要做的事情:
t.begin_fill()
t.goto(0,100)
t.goto(100,100)
t.goto(100,0)
t.home()
t.end_fill()
现在,当我运行我的程序时,我会得到这个(图 7-3 )。
图 7-3
设置矩形的填充颜色
是的,有效!
此外,您可以使用快捷方式进行格式化。您可以不使用两行代码来指定钢笔和填充颜色,而是使用一行代码,如下所示:
t.color('Salmon','Chartreuse')
第一个值用于 pencolor,第二个值用于 fillcolor。
或者,更好的是,您可以对所有四个格式选项使用一行,如下所示:
t.pen(pencolor='Salmon', fillcolor="Chartreuse", pensize=5, speed=7)
请注意,您不必将数字放在报价中。当您在脚本中使用前面的代码行时,您会注意到结果根本没有改变。
您可以根据自己的需要省略这些参数中的任何一个(pencolor='Salmon '是一个参数)。
在我们结束这一部分之前,我想让你尝试一下。我希望您将速度的值指定为 0。你认为会发生什么?海龟会以一只真正的海龟的速度开始画我们的正方形吗?还是会惊喜?试试看!
没有线条的形状
到目前为止我们一直在看画线,但是如果你想画圆呢?这也有一个预定义的函数。它叫做“圆”,你必须给出半径,作为括号内的自变量。半径基本上就是圆的大小。
让我们试一个,好吗?
环
s = turtle.getscreen()
t = turtle.Turtle()
t.circle(100)
我一直保持简单。运行前面的代码,你会得到这个(图 7-4 )。
图 7-4
画一个圆-逆时针方向
正如你所看到的,turtle 从默认的 0,0 位置开始逆时针方向(向左)画圆,所以圆被画在 0,0 位置的上方。
如果我给半径一个负值,它会顺时针方向画,也就是在 0,0 位置的下面。让我们试试。
t.circle(-100)
运行上面几行代码,你会得到这个(图 7-5 )。
图 7-5
画一个圆-顺时针方向
你可以使用你在你的圆的直线上使用的相同的颜色和尺寸选项。
作为一个小活动,我想让你用不同的颜色画出不同颜色的圆圈,看看你得到了什么。
点
你可以用“点”功能画一个点。它只是一个使用钢笔颜色填充自身的填充圆,或者您可以在第二个参数中给出一个首选颜色。
t.dot(100, 'Salmon')
运行前面的代码,你会得到这个(图 7-6 )。
图 7-6
画彩色圆点
你注意到什么了吗?我们的圆比我们的点大得多。这是因为我们在点函数中给出的值实际上是直径,而不是半径。所以,你的圆,有相同的值,将会是你的点的两倍大。
弧
现在,让我们画一个弧线!弧线是圆的一部分,不是吗?所以,我们还是要用 circle 函数,但是我们要添加更多的参数,让 turtle 知道它应该只画圆(弧)的一部分。
你知道天使是怎么工作的,不是吗?(图 7-7
图 7-7
圆中的角
360 度构成一个圆,所以如果你想要一个半圆,你只需要 180 度。要做四分之一圆(弧),需要 90 度。我们现在要做一个半圆。
t.circle(100,180)
运行前面的代码,你会得到这个(图 7-8 )。
图 7-8
画一个半彩色
当你给定的值为-100,180 时,你会得到相同的弧线,但是在下面。给定 100°、–180°,您将看到第一个弧的镜像,给定–100°、–180°,您将看到相同的镜像,但在 0,0°位置下方。自己试试看吧!
如果你给的角度是 90 度,你会画出四分之一圆。你为什么不试着改变角度来得到不同大小的弧线呢?不要只停留在 90 或者 180。你有 0 到 360 度的角度可以选择。玩得开心!
更多选择!
对于海龟 ??,我们有更多的选择,但是因为我们在这一章中只讨论了基础知识,所以在我们继续讨论项目之前,我只讨论几个。有时,您可能想要在屏幕上绘制多个形状或图形,并且它们可能位于不同的位置。因此,您需要一种方法来将笔移动到新位置,而不在移动中绘制任何内容。移动后,您的笔应该会再次开始绘图。penup 和 pendown 方法(都是小写字母)可以帮助您做到这一点。
当你给你的海龟下“笔”命令时,你是在让它把笔从屏幕上拿开。它将不再绘制,但它将根据您的前进、后退或转到命令移动位置。命令“pendown”的作用正好相反。如果你想让你的笔再画一次,给它 pendown 命令。仅当 penup 命令有效时,此命令才起作用。
此外,您可以在程序完成图形绘制后使用 hideturtle 函数来隐藏屏幕上的乌龟。我相信你知道这个方法后会很欣慰。我知道我是。那些海龟在我的照片上看起来不太好!
我知道我刚刚向你扔了一堆随机的方法,你可能会感到困惑。那么,我们为什么不把刚刚学到的东西拿来测试一下呢?让我们先画一个正方形,然后画一个圆形,在屏幕的不同边上,把乌龟藏在最后,好吗?
-
我将在启动程序时使用“penup”(在我像往常一样设置 turtle 之后),然后将笔发送到位置(–200,200)。一旦我的笔移动了,我就要指定 pendown,因为接下来我要画我的正方形。
import turtle s = turtle.getscreen() t = turtle.Turtle() t.penup() t.goto(-200,200) t.pendown()
-
然后,我将我的正方形的填充颜色设置为蓝色。
-
接下来,我将使用常见的代码行来绘制我的正方形。
#Draw the square t.begin_fill() t.goto(-100,200) t.goto(-100,100) t.goto(-200,100) t.goto(-200,200) t.end_fill()
-
一旦画出,我需要再次改变位置来画出我的圆。因此,再次暂停,转到(200,–200),它在屏幕的另一侧,然后暂停。
#Change positions again t.penup() t.goto(200,-200) t.pendown()
-
我将我的圆的填充颜色设置为红色。
t.fillcolor('blue')
-
Then, I’m going to draw a 50-point radius circle.
#Draw the circle t.begin_fill() t.circle(50) t.end_fill()
就这样!我们在屏幕的相对两侧有两个形状!
-
最后,我将使用 hideturtle()函数来隐藏乌龟(否则它仍会显示在圆圈上)。
t.fillcolor('red')
t.hideturtle()
当你运行程序时,你会得到这个(图 7-9 )。
图 7-9
隐藏“t”形海龟
- 这就是你会发现事情有点不同的地方。如果我只是用 t.hideturtle(),那么我就只隐藏其中一只乌龟(你为什么不画出来看看?).但是你一定注意到有两只乌龟。有一个在原始位置(0,0),它属于 turtle 包本身,还有一个(预定义函数 Turtle()的 t)进行绘制。
所以,我们需要 hideturtle()重复两次。我们已经为“t”编写了 hideturtle()。让我们为完整的“海龟”包再写一个。
turtle.hideturtle()
一旦我添加了前面的代码行,让我们再次运行脚本(图 7-10 )。
图 7-10
隐藏“海龟”海龟
看那个!屏幕中央的乌龟也消失了。是啊!
在屏幕上绘制文本
到目前为止,我们已经绘制了各种各样的图形,但是没有一幅图像是完整的,没有一点文字,是吗?这也很简单。你想看看吗?
要编写一个简单的文本,只需使用turtle
的 write 方法,指定想要显示的文本,就像这样:
import turtle
s = turtle.getscreen()
t = turtle.Turtle()
t.write('Hello there!')
运行它,你会得到这个(图 7-11 )。
图 7-11
在屏幕上绘制文本
那看起来像鸡肉涂鸦。嗷!我们能以任何方式操纵这段文字吗?没错。
让我们先把文本放在某个地方。
t.penup()
t.goto(200,200)
t.pendown()
现在,让我们再画一次,但有一点小小的变化:
t.write('Hello there!', move=True)
默认情况下,move 参数为 False。如果你使它为真,你会看到正在绘制的文本下面的箭头,就像这样(图 7-12 )。
图 7-12
在不同的位置绘制文本
你现在可能看不出太大的区别,因为文本太小太短了。
还是太小了!让我们增加一些风格,好吗?你知道你可以在你的文本上使用不同的字体风格,不是吗?有 Arial、Calibri、Times New Roman 等一大堆类似的款式。简单的谷歌搜索会给你一个列表。
我要做我的乔治亚。但这还没有结束。我也可以增加或减少字体大小和改变字体类型。让我们一起玩吧!
让我们再次改变位置,为我们将要创建的“大”文本腾出空间:
t.penup()
t.goto(-200,200)
t.pendown()
x 位置现在是–200,而不是 200。
现在,让我们画课文。
t.write('Hello there!', move=True, font=('Georgia',40,'normal'))
你注意到上面代码中的一些东西了吗?我已经提到了“字体”下的所有样式,它们都在组合括号内。另外,字体样式(' Georgia ')和类型(' normal ')在引号内(可以是单引号或双引号)。让我们运行上面的代码,我们会得到这个(图 7-13 )。
图 7-13
格式化文本
您可以使用 pencolor 工具更改文本的颜色。
t.pencolor('Red')
您还可以将文本加粗、斜体和下划线(或这三种中的任意一种),方法是将它们作为值与其余字体值一起包含,如下所示:
t.write('Hello there!', move=True, font=('Georgia',40,'normal','bold','italic','underline'))
运行前面的代码,你会得到这个(图 7-14 )。
图 7-14
更改文本的颜色
看起来不错!
迷你项目-正方形内的圆圈
这将是一个简单的项目。在这个项目中,我们将在一个正方形内画一个圆:
-
我们先设置一下 turtle。我没有在这个程序中设置速度,但是你可以这样做。
import turtle s = turtle.getscreen() t = turtle.Turtle()
-
接下来,我将正方形的填充颜色设置为“红色”,钢笔大小设置为 5。我要先画正方形,然后画里面的圆。
#Set the color and pen size for the square t.fillcolor('Red') t.pensize(5)
-
让我们现在画正方形。我将首先转到-100,-100 的位置,这样我可以围绕屏幕中心(0,0)画圆。这样,我可以围绕同一个中心点画圆。
#Draw the square t.penup() t.goto(-100,-100) t.pendown() t.begin_fill() t.goto(-100,100) t.goto(100,100) t.goto(100,-100) t.goto(-100,-100) t.end_fill()
-
现在,为了将圆的中心设置为 0,0,我要求我的笔移动到位置 0,-100,所以当我从这个点逆时针方向画一个 100 点的半径时,中心将是 0,0。我已经将圆形的填充颜色设置为“蓝色”。
#Set position so the circle's center is 0,0 t.penup() t.goto(0,-100) t.pendown() #Draw the circle #Color and size t.fillcolor('Blue') #Circle t.begin_fill() t.circle(100) t.end_fill()
-
最后,让我们把乌龟藏起来。
t.hideturtle() turtle.hideturtle()
现在,让我们运行整个代码,看看我们是否得到了我们想要的(图 7-15 )。
图 7-15
在正方形内画圈
哇哦!:d
更改绘图方向
到目前为止,改变方向的唯一方法是使用 right()和 left()方法。但是,在创建圆弧时,您可能需要其他东西来改变笔的角度,以便您可以将圆弧放置在您想要的任何位置。想画眉毛怎么办?还是侧身一笑?
Turtle 为你提供了 setheading()方法来做到这一点。我们先来看看什么是标题。heading()方法给出了笔在特定时间的角度。
import turtle
s = turtle.getscreen()
t = turtle.Turtle()
print(t.heading())
当我运行前面的代码时,我得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\drawTurtle.py
0.0
现在,笔处于 0°的角度,这意味着它将在水平方向上绘制。但是用 setheading(),我可以改变角度。
也许,让我们把它做成 90 度。只要提到括号内的角度,就可以了。
t.setheading(90)
现在让我们检查航向。
print(t.heading())
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\drawTurtle.py
90.0
很好,航向是 90 度。这对我们意味着什么?我们划一条线检查一下好吗?
t.pensize(5)
t.forward(100)
当我们运行前面的代码行时,我们会得到这个(图 7-16 )。
图 7-16
将航向设置为 90 度
看那个!它向上画了一条线,所以当航向为 90 度时,笔指向上方。你已经知道了每个角度的位置,所以你可以用 setheading()来猜测你的笔将会指向哪个角度,但是让我们用一个小程序来演示一下,好吗?我们正在重新开始,因此请打开一个新脚本或清除您当前使用的脚本。
-
让我从设置海龟开始。我要打印当前的航向(程序开始运行时为 0 度,指向右边)。我还增加了笔的大小为 5,速度为 5。
import turtle s = turtle.getscreen() t = turtle.Turtle() print(t.heading()) t.pensize(5) t.speed(5)
-
现在,我要让笔在当前度数上向前画 100 点。一旦画好,我将使用 heading()方法让笔写出当前的度数。然后让我们提起笔,回到(0,0)重新开始。
#0 degrees t.forward(100) t.write(t.heading()) t.penup() t.home() t.pendown()
-
现在,让我们改变方向为 90 度(向上),向前画,重复前面的动作。
#90 degrees t.setheading(90) t.forward(100) t.write(t.heading()) t.penup() t.home() t.pendown()
-
现在,180 度(指向左边)。
#180 degrees t.setheading(180) t.forward(100) t.write(t.heading()) t.penup() t.home() t.pendown()
-
最后 270 度(指向下方)。
#270 degrees t.setheading(270) t.forward(100) t.write(t.heading()) Finally, let’s hide all the turtles. t.hideturtle() turtle.hideturtle()
运行前面的代码,你会得到这个(图 7-17 )。
图 7-17
设定航向的角度图
你明白使用 setheading()的意义了吗?你可以把你的角度调到任何你想要的角度。现在,我们刚刚把它设置成画垂直线或水平线。不如换个角度看看有什么收获?
迷你项目–笑脸
在这个项目中,让我们更进一步,好吗?让我们画一个笑脸!
-
我已经设置好了
turtle
套装。如果你喜欢,你可以改变速度。import turtle s = turtle.getscreen() t = turtle.Turtle()
-
接下来,我让笔移动到 0–100 的位置,这样我就可以画一个圆,这是我们的脸,圆心在 0,0。这将让我更好地计算眼睛、鼻子和嘴巴。
#Let's draw a smiley #Go to the position t.penup() t.goto(0,-100) t.pendown()
-
现在,让我们画这张脸。填充颜色将是黄色,钢笔大小将是 5,圆的半径将是 100 点。
#Draw the face #Color and size t.fillcolor('yellow') t.pensize(5) #Circle t.begin_fill() t.circle(100) t.end_fill()
-
接下来,我要画眼睛。我在反复试验的基础上设定了位置。你可以在你的程序中使用相同的或者改变位置来看看你得到了什么并且创建你自己的(我推荐这样做)。
我要让我的笔去位置–40,30 画左眼,画一个直径 30 的黑点。
-
然后,到位置 40,30(同一水平线,X 值相反)画右眼,同样是直径 30 的点。
#Second eye t.penup() t.goto(40,30) t.pendown() t.dot(30)
-
接下来,我们来画鼻子。这就是圆心在 0,0 的地方,因为我们的笑脸的鼻子将从 0,0 开始。让我们画一条从 0,0 到 0,–30 的直线。
#Draw the nose t.penup() t.goto(0,0) t.pendown() t.goto(0,-30)
-
最后,棘手的部分。让我们画出微笑。我们要让乌龟走到第一只眼睛的 x 位置,也就是–40,但是 y 位置也是–40。同样,我是在反复试验后找到这个值的,最终得到了一个我想要的结果。自己试试!
#Draw the smile #Go to the x position of the first eye but a different y position t.penup() t.goto(-40,-40) t.pendown()
-
微笑是一个半圆,不是吗?但是,如果你尝试像现在这样画一个半圆,你会得到一个倾斜的微笑,而不是我们在笑脸上看到的唯一微笑。这就是 setheading 的用武之地。我们需要改变笔的角度,这样我们就可以按照我们想要的角度画出半圆。让我们将角度更改为–60。不要迷茫!这与将角度设置为 120°是一样的(两者都可以使用)。
Next, let’s draw a semi-circle with the angle 120, so it’s not exactly a semi-circle, but not a quarter circle either – something in between.
#Change the direction of the pen (turtle) t.setheading(-60) t.circle(40,120)
-
最后,让我们藏起我们的乌龟!
#Finally, hide the turtle t.hideturtle() turtle.hideturtle()
#Draw the eyes
#First eye
t.penup()
t.goto(-40,30)
t.pendown()
t.dot(30)
咻!太久了。现在我们要运行代码并检查我们的努力是否有成果吗?(图 7-18 )
图 7-18
笑脸
耶!那是一个可爱的小笑脸!为什么不试着创造不同的表情符号呢?或许是一个悲伤的笑脸?皱眉头,还是大笑?你有你需要的工具(goto,setheading 等。)到现在创造任何形象,不仅仅是脸!
摘要
在这一章中,我们深入探讨了 Python Turtle 模块。我们学会了如何使用颜色,画弧线、圆圈和圆点,并控制它们的方向和大小,最后,我们学会了如何在屏幕上绘制文本。
在下一章,让我们深入研究字符串,如何创建和使用它们,以及 Python 为您配备的各种预定义的字符串方法,最后,让我们用它们来制造一些魔法吧!
八、玩转字母和单词
在前几章中,我们暂时停止了 Python 基础知识的学习,我们学习了所有关于 Turtle 的知识,并使用它来绘制直线、由直线、圆、曲线甚至文本组成的形状。我们用一堆酷炫多彩的迷你项目完成了这一章。
在本章中,我们将回顾 Python 的基础知识,了解字符串、它们是什么、如何创建它们、如何使用 Python 中各种可用的预定义函数来操作它们,以及从程序用户那里获得直接输入以使您的项目更加动态。像往常一样,我们将以一些迷你项目来结束这一章,但是我们现在将使用 Turtle 来使我们的项目变得丰富多彩。
什么是字符串?
弦…弦…弦。这么简单的东西用这么成熟的词。字符串就是字母和数字,串在一起。句子、短语和单词——它们都是字符串。单个字母也可以是字符串。
你还记得打印声明吗?当我们第一次开始使用 print()函数时,我们在括号内的引号中写了一些东西。是“你好!”?确实是的。
那是一根绳子。Print 语句中通常包含字符串。但这还没有结束。您也可以将字符串存储在变量中,就像处理数字一样。
现在你知道了什么是字符串,接下来让我们学习如何创建它们!这将是一个比一般章节更长的章节,所以系好安全带!我保证所有的练习和有趣的项目会弥补长度。
让我们创建一些字符串
我将创建一个名为 strings.py 的新脚本文件,并将其用于本章。
a = 'This is a string'
变量“a”现在有了字符串“这是一个字符串”。您也可以将字符串放在双引号内。
a = "This is a string"
现在让我们试着打印这个字符串,好吗?很简单。再次使用 print 语句,但不是在括号内键入带引号的字符串,而是键入包含该字符串的变量的名称,不带引号,如下所示:
print(a)
现在,如果您运行前面的代码,您将得到这样的结果:
RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/strings.py
This is a string
我们成功地打印了我们的字符串。耶!
你的字符串也可以有数字,它们仍然被认为是一个字符串。引号内的任何内容都是字符串。让我将一个数字放在引号中,并使用 type()方法检查它的类型。
a = "1234"
print(type(a))
当您运行前面的代码时,您将得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/strings.py
<class 'str'>
看那个!即使“a”有一个数字 1234,因为它被放在引号内,Python 自动认为它是一个字符串。
我想要一条又一条的线!
只要您坚持创建单行字符串,那么字符串就很好。如果我们需要多条线呢?我们不能一直为每个新的字符串行创建单独的打印语句。这就是我们在第一个迷你项目中所做的,我们打印了苏珊·史密斯的介绍,记得吗?那太不方便了!
为什么我们不试着在字符串格式中创建多行,看看会发生什么?
a = "This is the first line.
This is the second line.
This is the last line."
在前面的例子中,“a”有三行字符串,用双引号括起来。让我们运行它,看看会发生什么(图 8-1 )。
图 8-1
带双引号的多行字符串–错误
哦哦。我甚至不能运行代码。我立即得到一个弹出窗口,显示前面的错误。我们之前写的根本不是可接受的代码。那么,如何才能创建多行字符串呢?还记得第三章的多行注释吗?我们使用了三个单引号,注释前不带空格,注释后也是一样,这样就创建了一个多行注释。
我要坦白一件事。该语法实际上是多行字符串的语法。我们只是借用它来创建一个多行注释,因为一个没有存储在变量中的多行字符串会被 Python 忽略,所以它在技术上充当了一个注释(尽管它不是)。
好了,聊够了。现在让我们创建一个多行字符串。我将复制 Susan Smith 的介绍,但是我将使用多行字符串来创建和打印它。
intro ='''Hello there!
My name is Susan Smith.
I am 9 years old.
I love puppies!'''
print(intro)
当我运行前面的代码时,我得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/strings.py
Hello there!
My name is Susan Smith.
I am 9 years old.
I love puppies!
简单利落,你说呢?是的!
我的字符串有引号!O:
天哪,我们的字符串有引号,我们得到一个错误!
intro =""Hello!", said Susan"
我得到了这个(图 8-2 )。
图 8-2
同一个字符串中的单引号和双引号–错误
邦默
我可以改变绳子周围的引号。
intro ='"Hello!", said Susan'
print(intro)
有用吗?
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/strings.py
"Hello!", said Susan
没错。
但是如果我的字符串既有单引号又有双引号呢?可能是如下所示的字符串:
“那是我的泰迪熊”,苏珊说。
我不能把前面字符串中的双引号替换成单引号。我需要一种方法告诉 Python“That ' s”中的单引号实际上是字符串的一部分,而不是代码的一部分。我们在 Python 中有一个叫做 的转义字符 ,它只是一个反斜杠,“”。您可以在作为字符串一部分的引号(单引号或双引号)前使用它,Python 会在运行代码时忽略它。
让我们试试。
intro = '"That\'s my Teddy", said Susan.'
print(intro)
运行前面的代码,我们会得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/strings.py
"That's my Teddy", said Susan.
是的,有效!
让我们把两根或更多的绳子连接起来
当我们将“+”符号用于两个或多个数字时,它们被加在一起。你想看看如果你对绳子做同样的事情会发生什么吗?好吧!
我已经创建了两个变量 str1 和 str2 来保存字符串“Hello”和“there!”。我已经创建了第三个变量“string ”,并为它分配了 str1 和 str2。
str1 = 'Hello'
str2 = 'there!'
string = str1 + str2
print(string)
让我们打印字符串,看看会得到什么:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/strings.py
Hellothere!
哦,看那个。它只是把 str1 中的字符串放在 str2 中的字符串之后。真有意思。即使我们使用了加法运算符,加法也没有发生。
事实上,这种字符串操作有一个名称。叫做 字符串串联 。当你在两个或多个字符串上使用“+”时,你把它们加在一起,是的,但不是传统意义上的。你只要把它们合并在一起,按照它们被加入的顺序。
不过,我的成绩让我有些困扰。“Hellothere!”不是我想要的。我想在这些词之间留一个空格。那是那个短语的正确用法。所以,我为什么不加进去呢?
str1 = 'Hello'
str2 = 'there!'
string = str1 + " " + str2
print(string)
那很简单!我们刚刚创建了另一个只有一个空格的字符串,并将其添加到 str2 之前。让我们运行前面的代码,我们将得到这个:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/strings.py
Hello there!
现在,这看起来是正确的。因此,正如你所看到的,你可以连接两个以上的字符串,它们可以在变量中,也可以在引号中。如果放在引号内,即使是空格也是字符串。
印刷中的串联()
您也可以在 print()中应用字符串连接。
a = 'Hi!'
print('Susan says, "' + a + '"')
看起来是不是有点复杂?别担心。“我已经用逗号、空格和双引号将字符串的第一部分括起来了,”Susan 说。字符串的下一部分是变量“a”中的内容,所以我将这两个字符串连接起来。字符串的最后一部分是右双引号,它也包含在单引号中。或者,我可以只使用双引号,并使用转义字符来区分字符串的双引号。
如果我运行前面的代码,我会得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/strings.py
Susan says, "Hi!"
做得好!
空字符串
所有这些字符串操作让我想起了一些事情!有一种叫做 的空字符串 ,在这里你不需要在引号之间输入任何东西,甚至连一个空格都不要输入。
a = ''
在前面的例子中,变量“a”存储一个空字符串。如果你把它打印出来,你将在输出中得不到任何东西(甚至没有一个空格)。试试看!
访问字符串中的字符
我要在《弦》里给大家介绍一个令人瞠目结舌的话题!您实际上可以访问、检索甚至修改字符串中的特定字符(字母)。这有多酷?您可以使用此功能在字符级别对字符串进行更改。
a = 'Hello there!'
看下面的字符串索引图。字符串中的每个字符都有一个索引。事实上,它们有两个指数,一个正指数和一个等价的负指数。您可以通过使用这些索引来访问这些字符。
图 8-3
字符串索引图表
如图 8-3 所示,正指数从 0 开始,数值向左增加。负指数从–1 的最后一个位置开始。空格有索引,感叹号也有。这不仅仅是为了字母/数字。
好吧,这很好,但是我们如何访问这些索引呢?简单!键入字符串的名称,打开和关闭方括号,并在括号内键入相关的索引,就可以开始了。
如你所见,索引从 0 开始,最后一个是字符串长度减 1。字符串中的空格也会占用索引。
所以,如果我想检索字符串的第一个字符“H”,我会这样做:
print(a[0])
当您运行前面的代码时,您会看到:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/strings.py
H
完美!
现在,如果我要检索字符串的最后一个字符,我会首先计算字符串的长度。在这种情况下,长度为 12,包括空格。现在让我们减去 1,如下所示:
print(a[12-1])
当您运行程序时,您的解释器(空闲)将自动计算得出 11 的索引。结果是这样的:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/strings.py
!
是的,没错。
负指数
正如您在前面的图像中看到的,字符串中的相同字符有正索引和负索引。让我们尝试访问“o”,它位于正索引 4(字符串中的第五个位置)和负索引位置–8。
print(a[-8])
运行前面的代码,您将得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/strings.py
O
效果非常好!
因此,第一个字符将位于[–12],最后一个字符将位于[–1]。
切割字符串的一部分
你可以提取字符串的一部分,而不仅仅是一个字符。那就叫 切片 。
切片遵循与字符提取相同的模式,但唯一的区别是您必须在方括号内给出一个范围。如果我想提取一个字符串中的前四个字符,我会给定范围为 0:4,因为第一个字符的索引是 0,第四个字符的索引是 3。在切片中,范围的结尾(在我们的例子中是 4)将被省略。因此,是 0:4 而不是 0:3。让我们试试看能得到什么!
a = 'Hello there!'
print(a[0:4])
运行前面的代码,您将得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/strings.py
Hell
是的,我们拿到了!
如果我们想要最后四个字符呢?你可以用两种方法来做这件事。最后一个字符的正索引是 11,倒数第四个字符的正索引是 8,所以我们可以这样做:
print(a[8:12])
运行前面的代码,我们会得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/strings.py
ere!
太好了。目前为止一切顺利。但是负指数呢?最后一个字符的负索引是–1,倒数第四个字符的负索引是–4,因此我们可以改为执行以下操作:
print(a[-4:-1])
注意,我们首先给出了–4(倒数第四个字符),它将被包含在内。但是–1 不包括在内,对吗?这就是语法的工作原理,这是最后一个索引。
好了,让我们运行前面的代码,看看它是否有效:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/strings.py
Ere
啊好吧,它不工作。我们少了一个“!”。☹
我们能做什么?嗯,在这种情况下,从一个点开始,需要字符串的其余部分(字符串末尾的倒数第四个位置),您可以将范围内的最后一个数字留空,就像这样:
print(a[-4:])
运行前面的代码,您将得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/strings.py
ere!
完美!
字符串方法——字符串的魔力!
就像处理数字一样(第五章第五章),你有很多预定义的方法来帮助你处理数字。有些看起来很神奇!你会明白的。
在 Python 官方文档中有一个完整的 Python 字符串方法列表,并解释了它们的作用。下面是链接: https://docs.python.org/2.5/lib/string-methods.html
。
以后可以参考前面的文档。我将试着涵盖大多数重要的方法,虽然我不能涵盖每一个方法,因为那样会使这一章太长。不过不要担心。一旦你学会了一些,你就能破译其余的是如何工作的。
好吧,让我们开始吧!
为什么我们不从简单的开始呢?len()方法用于查找字符串的长度。
该方法的语法如下:len(string)
a = 'Hello there!'
print(len(a))
当您运行前面的代码时,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
12
计算字符串中的字符数(包括空格),您会注意到它的长度确实是 12。
大写和小写
好的,现在让我们看看其他的方法。“capitalize()”方法将字符串中的第一个单词大写。它不会改变原来的字符串。它只是创建了一个副本,你可以把它赋给一个新的变量或者打印出来。
语法是这样的:string.capitalize()。
“字符串”可以是引号内的确切字符串,也可以是存储该字符串的变量。
a = 'i am here'
print(a.capitalize())
print(a)
当您运行前面的代码时,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
I am here
i am here
看,大写并不影响原来的字符串。
同样,可以使用 upper()方法将字符串中的所有字符(字母)大写。这也创建了一个副本。所有的字符串方法都创建副本。他们很少对原始字符串进行更改。
a = 'i am here'
print(a.upper())
当您运行前面的代码时,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
I AM HERE
同样,您可以使用 lower()方法将字符串中所有大写字母更改为小写字母。
a = 'I AM here'
print(a.lower())
当您运行前面的代码时,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
i am here
你注意到有些字母已经很小了吗?这种方法不会改变这些。
不像在 capital 中那样只将整个字符串的第一个字母大写,实际上可以使用 title()方法将字符串中每个单词的第一个字母都大写。
a = 'i love chimpanzies!'
print(a.title())
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
I Love Chimpanzies!
杂项方法
使用 count 方法,可以返回单词、字母或短语在字符串中出现的次数。
语法是string.count('word')
。
这个方法是区分大小写的,就像 Python 中的其他方法一样,所以如果你想要“word”,不要把它打成“Word”。
为了测试这个方法,我创建了一个多行字符串,就像我教你的那样:
a = '''Susan is a lovely girl.
Barky is Susan's best friend.
Barky plays with Susan'''
让我们数一数在前一串中“Susan”和“Barky”被提到了多少次,好吗?
print(a.count('Susan'))
print(a.count('Barky'))
结果是这样的:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
3
2
哇哦!
可以用 strip()方法修剪字符串中多余的空格。
a = ' Hello there! '
print(a.strip())
当您运行前面的代码时,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
Hello there!
完全没有空格!
同样的方法有左侧和驾驶侧版本。rstrip()方法只去除字符串右侧的空白。lstrip()方法对字符串的左边做同样的事情。你为什么不试试它们,看看它们是否有效?
还记得我们刚刚用过的那根大绳子吗?如果我们弄错了呢?如果我们要谈论罗尼而不是苏珊呢?我们需要交换他们的名字,对吗?您可以使用 replace 方法来实现这一点。语法是string.replace('original','replaced')
。
a = '''Susan is a lovely girl.
Barky is Susan's best friend.
Barky plays with Susan'''
print(a.replace('Susan','Ronny'))
让我们运行前面的代码,我们将得到这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
Ronny is a lovely girl.
Barky is Ronny's best friend.
Barky plays with Ronny
看,现在是罗尼了!
我们还可以找到某个单词、字母或短语在字符串中的起始位置。记住,字符串位置从 0 开始,所以你总是落后一个计数。
a = "I love coding. I have fun with coding"
print(a.find('coding'))
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
7
计算字符数,包括空格,您会注意到第一次出现的“编码”从位置 8 开始(因此对于 Python 字符串是 7)。
如果找不到这个短语呢?
print(a.find('Coding'))
你知道“编码”不同于 Python 中的“编码”,所以它不会出现在字符串中。
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
-1
哎呀,结果是 a–1。
index()方法与 find()方法完全一样。唯一的区别是,如果没有找到短语,它将返回一个错误,而不是–1。为什么不尝试用 index()做同样的事情呢?
使用 split 方法,您可以将一个字符串拆分成一个列表。我们将在以后的课程中讨论什么是列表。现在,只需要知道列表中包含多个值,用逗号分隔。
为了使用 split 方法,您需要给出一个分隔符。比如说我想把字符串按单词拆开。然后我会给出一个空格作为分隔符。
a = "I love coding."
print(a.split(' '))
当您运行前面的代码时,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
['I', 'love', 'coding.']
这是一个列表,它包含我们的字符串,用单词分隔。
真的吗?假的?
在我进一步讨论这些方法之前,我想教你们 Python 或任何编程语言中真和假的概念。很简单。如果某事为真,那么你的程序将返回“真”。如果一个条件为假,那么你将得到“假”。就这样。
例如,假设我想看看我的字符串中是否有单词“best friend”。我很想知道巴克利是不是罗尼最好的朋友。
我必须使用“in”关键字。关键字是在 Python 中做一些事情的特殊单词。“in”关键字检查我们想要查找的单词或短语是否在我们的字符串中。
string = "Barky is Ronny's best friend."
print('best friend' in string)
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
True
但是如你所知,Python 是区分大小写的。所以,“闺蜜”和“闺蜜”或其他任何版本都不一样。所以照原样用词,好吗?
让我们看另一个例子,好吗?
print('Python' in 'Python is fun')
当您运行前面的代码时,您将得到 True。
但是如果你要求这个:
print('Coding' in 'Python is fun')
你将得到 False,因为“编码”不在字符串“Python 是有趣的”中。
同样,你可以在你的字符串中测试很多其他的字符串。
你想看看你的字符串是否既有字母又有数字吗?使用 isalnum()方法。只有当字符串中的每个单词都包含字母和数字时,它才返回 true,如下所示:
a = 'number123 number253'
print(a.isalnum())
前面的代码将返回 True,而下面的代码:
a = 'This is a number: 123'
print(a.isalnum())
将返回 False,因为大多数单词只有字母而没有字母和数字。
如果字符串中的每个字符都是字母(没有数字或特殊字符),isalpha()方法返回 true。如果字符串中的每个字符都是数字(没有字母或特殊字符),isnumeric()方法返回 true。
如果所有字符都很小,Islower()返回 true。如果每个字符都大写,Isupper()返回 true。
我希望你在使用这些方法的同时给出不同的可能性,并探索它们是如何真正发挥作用的。成交?
你可以参考我在“字符串方法——字符串的魔力”中给出的链接部分获得其余的方法,并在您的实验中使用它们。玩得开心!😛
嘿,我知道你在想什么。
“天哪,方法真多。我怎么会记得他们所有人?”
你为什么要这么做?我会告诉你一个更大的秘密…嘘
程序员不会一开始就试图去记忆语法。这就是谷歌的作用。他们只是创造了很多。他们解决了很多难题,创造了有趣的项目,并在遇到困难时搜索语法。随着时间的推移,这些语法会被牢牢记住,因为他们用得太多了。
所以,忘掉记忆吧。用这本书作为参考。解开谜题,用你的技巧创建迷你项目,并将大项目带到下一个级别,当你完成所有这些时,你将成为 Python 的大师。开心就好。
字符串格式
打印声明是枯燥和有限的。☹:你不能用你想要的方式格式化它,如果你尝试,你会淹没在一堆引号中。但是更重要的是,你不能用字符串打印数字(即使它们在变量中)!O:
让我证明给你看。
a = 4
b = 5
sum = a + b
所以现在,我想打印下面的语句:4 + 5 = 9,我想使用变量名而不是实际值来打印它,以保持动态。我也许可以改变一个变量的值,我的打印语句也会自动改变。
我们应该可以用之前学过的连接来实现,对吗?让我们试试。
print('The answer is: ' + a + ' + ' + b + ' = ' + sum)
理想情况下,前面的代码应该会产生以下结果:
答案是:4 + 5 = 9
但这是我们得到的:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
Traceback (most recent call last):
File "C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py", line 4, in <module>
print('The answer is: ' + a + ' + ' + b + ' = ' + sum)
TypeError: can only concatenate str (not "int") to str
从本质上讲,这个错误说的是你只能把一个字符串(引号内的任何东西)和一个字符串连接起来,而包含数字(不带引号)的变量不是字符串。
这句话对我来说不仅很难写,而且令人困惑,它根本不起作用。
这就是格式化的由来。您可以设置打印报表的格式。只需将{}(没有空格)放在变量出现的地方,稍后可以使用 format 方法填充它们。
先说简单的。
a = 'apple'
假设我想打印'这是一个苹果',其中值'苹果'来自变量 a。
我会键入整个字符串,但将{}放在“apple”的位置,如下所示:
'This is an {}'
接下来,我将标记 format 方法并将变量“a”放在括号内。Python 会自动用变量中的值替换{}。
a = 'apple'
print('This is an {}'.format(a))
当您运行前面的代码时,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
This is an apple
很简单,不是吗?你再也不用摆弄空格和引号了,呼呼!
我们现在来看一个更复杂的例子,好吗?
a = 'Apples'
b = 'Bananas'
如果我想印“苹果和香蕉有益健康”,我会这样做:
print('{} and {} are good for your health'.format(a,b))
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
Apples and Bananas are good for your health
你注意到我是如何在格式中用逗号分隔变量的吗?
您可以将字符串的第一部分放在一个变量中使用,就像这样:
a = 'Apples'
b = 'Bananas'
s = '{} and {} are good for your health'
print(s.format(a,b))
或者,如果我想先打印香蕉,然后打印苹果,但我不想改变它们的排列顺序,我可以在要打印的字符串中标记它们,就像这样:
s = '{1} and {0} are good for your health'
print(s.format(a,b))
Python 中的索引是从 0 开始的,还记得吗?
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
Bananas and Apples are good for your health
好吧。既然我们是使用 format()设计印刷品的专家,为什么不回到我们最初的问题呢?
a = 4
b = 5
sum = a + b
让我们格式化我们的字符串!
print('The answer is: {} + {} = {}'.format(a,b,sum))
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
The answer is: 4 + 5 = 9
是的!简单整洁,就应该这样。
从用户那里获得输入(开始自动化)
到目前为止,我们只是固定了变量的值。那太无聊了!我想要自动化。编程就是这样的,不是吗?
我希望每次运行加法程序时给出一个不同的数字,每次打印消息时给出一个不同的字符串。这就是输入。用户或运行程序的人给出可在程序中使用的值以获得结果。这些值被称为输入。
在 Python 中,可以使用 input()方法获取输入。很简单,不是吗?
当你运行一个程序时,它会问你要值,然后等你给它值。这就是所谓的提示。
我打算从简单的开始。我会收到一条可以立即打印的消息。在请求输入时包含一条信息总是好的,这样用户就知道他们期望给出什么值。您可以将消息包含在输入的括号内的引号中。
message = input('Enter your message: ')
print('Here is your message: ' + message)
我提示用户输入一条消息,我在变量“message”中收到了同样的消息。然后我把它打印出来了。很简单。
当我运行前面的代码时,我首先得到的是:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
Enter your message:
程序在这个阶段停止了,因为它在等我的消息。
现在让我输入:
Enter your message: I love Python!
当我按下回车键,我会得到这个:
Here is your message: I love Python!
效果非常好!我的信息以我想要的格式打印出来了。
字符串到整型或浮点型的转换
我们研究了输入,以及如何动态获取值并在程序中使用它们。计算难道不是使用动态值的最好方法之一吗?每次执行加法运算时,我都希望得到不同的数字。
让我用 input 来做同样的事情,看看它是否有效。
a = input('First number: ')
b = input('Second number: ')
sum = a + b
print('{} + {} = {}'.format(a,b,sum))
在前面的代码片段中,一切看起来都很好。应该管用吧?错了。
当我运行它时,我得到的是:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
First number: 5
Second number: 2
5 + 2 = 5 2
我的程序提示我输入这两个数字,我输入了它们。一直到现在都很好。但是后来,事情变得不稳定了。
为什么呢?
你根本没有输入数字。当你给一个输入赋值时,你的程序认为它是一个字符串,而不是一个数字。所以,这里发生的是字符串连接,而不是加法。
我们如何让 Python 把我们的输入看成数字?当然,您需要转换它们!还记得我们如何转换不同类型的数字吗?同样,可以使用 int()方法将字符串转换为整数,或者使用 float()方法将字符串转换为浮点数。
让我们修改我们的代码:
a = input('First number: ')
#Convert 'a' into an integer and store it back in 'a'
a = int(a)
b = input('Second number: ')
#Convert 'b' into an integer and store it back in 'b'
b = int(b)
sum = a + b
print('{} + {} = {}'.format(a,b,sum))
我在代码中唯一改变的是获得每个输入后的整数转换。我已经将转换后的值存储回同一个变量中。让我们运行这段代码,看看它是否有效:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
First number: 5
Second number: 2
5 + 2 = 7
唷!现在可以用了。
迷你项目——将 乌龟 文字带到下一个层次!
这将是一个简单的项目。我们将实时输入您的用户名,并在我们的turtle
屏幕上用彩色大字体打印出来:
-
先来设置一下我们的
turtle
:import turtle s = turtle.getscreen() t = turtle.Turtle()
-
接下来,让我们创建一个变量名,将用户名作为输入:
-
我们不需要以任何方式转换这个字符串,因为我们只是将它与另一个字符串连接起来。现在,让我们在
turtle
上创建我们定制的问候。在此之前,让我们创建想要打印的确切字符串,并将其赋给变量“greeting”。
name = input("What's your name? ")
-
现在,让我们设置笔的颜色,也许,暗紫色?让我们也将笔移动到位置–250,0,这样它就可以在屏幕的中心绘制。
t.pencolor('DarkViolet') t.penup() t.goto(-250,0) t.pendown()
-
Finally, let’s create our text.
t.write(greeting,font=('Georgia',45,'normal','bold','italic'))
我已经将变量“greeting”与我们需要的文本放在一起,代替了实际的文本,我还将字体样式设置为“Georgia ”,大小设置为 45,并将文本设置为粗体和斜体。我省略了 move 属性,所以它默认为“false”(文本下面没有箭头)。
-
最后,让我们藏起我们的乌龟:
t.hideturtle() turtle.hideturtle()
greeting = 'Hi {}!'.format(name)
让我们现在运行这个程序:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
What's your name? Susan Smith
它问名字。我报出了“苏珊·史密斯”这个名字,按下回车键,瞧!(图 8-4 )。
图 8-4
多彩的问候
我们有我们的问候,它看起来也很漂亮!
迷你项目-对着屏幕大喊大叫
我们要按照题目说的去做。让我们对着屏幕喊,好吗?哦,等等…或者屏幕会对我们大喊大叫?不管怎样,让我们大声喊叫吧!喔!
概念很简单。我们将从用户那里得到一个字符串输入。信息将是“用不到 3 个字说出你的想法”。少于三个单词,所以我们的文本可以在一行中以足够大的字体显示。在后面的章节中,您将学习获得尽可能多的输入单词所需的工具,并确保通过腾出空间来打印它们,所以现在不要担心这个。
然后,我们将结果大写,在末尾添加两个或更多感叹号,并打印出turtle
中的所有内容。简单吧?开始吧!
-
首先,让我们设置一下
turtle
包:import turtle s = turtle.getscreen() t = turtle.Turtle()
-
然后,让我们得到输入:
message = input("Enter what's on your mind in 3 words or less: ")
-
最后,我们来格式化一下我们要喊的消息吧!我们的“信息”可能是小写字母。我们如何将邮件中的每个字母都转换成大写?没错。upper()方法。让我们利用这一点,并在结尾加上三个感叹号,使我们的信息更具戏剧性!
-
现在,我要将笔移动到–250,0,并将笔的颜色改为红色,因为没有什么比红色更能说明大喊大叫了。
t.pencolor('Red') t.penup() t.goto(-250,0) t.pendown()
-
现在,进入节目的主要部分。让我们创建我们的
turtle
文本。我将使用“Arial Black”字体。字体的大小将会是 45,但是我将会停止将文本加粗。这次不用斜体。
shout = '{}!!!'.format(message.upper())
-
最后,让我们把乌龟藏起来。
t.hideturtle() turtle.hideturtle()
t.write(shout,font=('Arial Black',45,'normal','bold'))
让我们运行一切。我的信息是“这是什么?”。让我们看看我们得到了什么:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
用三个字或更少的话说出你的想法:这是什么?
当我按下回车键并查看我的turtle
屏幕时,我得到了这个(图 8-5 )。
图 8-5
对着屏幕大喊
没错。成功!
迷你项目-扭转你的名字
我要在解决这个项目的同时教你一些有趣的东西。到目前为止,我们已经看到了各种操纵琴弦的方法。在我们结束这一章之前,我们为什么不多看一个?
你知道你可以扭转你的弦吗?对,没错!完全颠倒,只有一行小小的代码。你想尝尝吗?
让我们创建一个程序,它获取用户的名字作为输入,颠倒他们的名字,并将其显示在 Turtle 屏幕上:
-
让我们像往常一样设置
turtle
。import turtle s = turtle.getscreen() t = turtle.Turtle()
-
并获取用户名,将其放入变量“name”中。
-
现在有趣的部分来了!我们将格式化我们想要照常显示的字符串。我们创建了一个变量“reverse”来存储字符串。但是我们如何逆转呢?还记得我们过去如何使用方括号来访问单独的字符、提取字符串的一部分等等吗?还有,你还记得负指数吗?这就对了。
如果使用以下语法,可以反转字符串:string[::–1]。这是一个双冒号,后面跟一个–1。就这么简单!
name = input("What's your name?")
-
最后,让我们将钢笔的颜色改为“金色”,将位置改为–250,0,并在屏幕上绘制反向的字符串。
t.pencolor('Gold') t.penup() t.goto(-250,0) t.pendown() t.write(reverse,font=('Georgia',45,'normal','bold')) t.hideturtle() turtle.hideturtle()
reverse = '{}'.format(name[::-1])
让我们运行程序:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py
What's your name? Susan Smith
现在,点击输入,你会得到这个(图 8-6 )。
图 8-6
颠倒你的名字
呵呵,她的名字被颠倒了,好吧。😛
迷你项目——丰富多彩的动态数学
在数字一章中,我们不得不求助于用预定义的数字和没有颜色进行无聊的计算!☹
所以,我想在我们进入下一章之前,我们可以从数字中获得一些真正的乐趣。我们走吧。
在这个项目中,我们将对两个给定的数字进行加法、乘法、减法和除法运算。无聊,我知道!但是这一次,我们将从用户那里获得两个数字作为动态输入,并在 Turtle 中以彩色显示结果。有趣吗?我知道!
-
让我们先设置一下乌龟。
import turtle s = turtle.getscreen() t = turtle.Turtle()
-
然后,让我们得到我们将在操作中使用的第一个和第二个数字的输入。但是有一个问题!我们不能照原样使用它们。它们是字符串格式的,记得吗?所以,让我们把它们转换成整数,然后赋回给相同的变量。
num1 = input("Enter the first number: ") num1 = int(num1) num2 = input("Enter the second number: ") num2 = int(num2)
-
现在,让我们做加法。我们将创建一个名为 display 的变量,它将保存四个操作的所有格式化字符串。
#Addition add = num1 + num2 display = "{} + {} = {}".format(num1,num2,add)
-
格式化后,让我们将笔放在–150,150 的位置,这样我们的绘图就与屏幕中间对齐了。然后,我们把笔的颜色改成“红色”,画出文字。
t.penup() t.goto(-150,150) t.pendown() t.pencolor("Red") t.write(display,font=("Georgia",40,"normal","bold"))
-
现在做同样的减法,除了现在位置是–150,50,颜色是“蓝色”。
#Subtraction sub = num1 - num2 display = "{} - {} = {}".format(num1,num2,add) t.penup() t.goto(-150,50) t.pendown() t.pencolor("Blue") t.write(display,font=("Georgia",40,"normal","bold"))
-
对于乘法运算,位置将为–150 和–50,颜色将为“绿色”。
#Multiplication mul = num1 * num2 display = "{} * {} = {}".format(num1,num2,add) t.penup() t.goto(-150,-50) t.pendown() t.pencolor("Green") t.write(display,font=("Georgia",40,"normal","bold"))
-
对于除法运算,位置为–150 和–150,颜色为“紫色”。
#Division div = num1 / num2 display = "{} / {} = {}".format(num1,num2,add) t.penup() t.goto(-150,-150) t.pendown() t.pencolor("Violet") t.write(display,font=("Georgia",40,"normal","bold"))
-
最后,让我们把乌龟藏起来。
t.hideturtle() turtle.hideturtle()
-
现在,让我们运行程序。它首先要求输入。我们的输入是 10 和 5。
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\strings.py Enter the first number: 10 Enter the second number: 5
当我们点击回车,这就是我们得到的结果(图 8-7 )。
图 8-7
丰富多彩的动态数学
太美了!
摘要
在这一章中,我们学习了字符串,它们是什么,创建单行、多行和空字符串,创建带引号的字符串,连接两个或多个字符串,访问字符串中的字符,提取字符串的一部分,字符串切片,如何以不同的方式操作字符串,以及从用户那里获取输入并在我们的程序中使用它们。
在下一章,让我们看看如何命令我们的程序做我们想做的事情。我们将研究“if”语句,用“if else”和“if elif else”语句创建多个选项,等等。会很好玩的!
九、听从我的命令!
在前一章中,我们学习了所有关于字符串的知识,以及如何使用它们来创建字母和数字的字符串,如何以我们想要的任何方式操作字符串,如何从用户那里获得输入并将其转换成我们想要的数据类型,以及如何根据我们的喜好格式化输出(尤其是在打印语句中)。
在这一章中,让我们看看如何用“if 和 else”语句来命令我们的计算机。
真或假
在编程中,真或假决定了你的程序走向。如果“某事”是真的,就做“某事”。如果是假的,就做“别的”。你可以用前面的“条件”创建许多程序。
所以,要给你的系统下命令,你需要三样东西(图 9-1 )。
图 9-1
条件及其结果
-
将由 Python 评估的条件
-
真或假的结果
-
根据结果决定下一步发生什么的语法,即根据结果指向两种结果之一的语法
先看结果真假。“真”和“假”也是 Python 中的值。它们被称为布尔值。就像我们有我们的字符串和数字一样,我们可以将布尔值赋给变量,将它们转换成另一种值类型,找到它的类型(布尔值),等等。你想看看怎么做吗?
让我们为本章创建一个新的脚本文件。我创建了一个名为 condition.py 的文件。我将在本章中使用和重用这个文件。真和假需要用大写的 T 和 F 来写,否则你会得到一个错误,所以请记住这一点。
让我们创建变量“a”和“b”并给它们赋值“真”和“假”。
a = True
b = False
print('a is {} & b is {}'.format(a,b))
当您运行前面的代码时,您将得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/condition.py
a is True & b is False
好了,现在我们知道如何使用布尔值了。但是它们到底是什么呢?您知道布尔实际上只是 1 和 0 吗?O:
哦,是的,你的真被你的计算机读为 1,假被你的计算机读为 0。你的电脑是一个非常简单的生物。它将你发送给它的所有复杂、怪异的代码和脚本转换成非常简单的基于 1 和 0 的值。真值和假值都转换为它们的基数-1 和 0。
我们何不验证一下这是不是真的?如果我把布尔值转换成整数,我应该得到 1 或 0。
a = True
a = int(a)
b = False
b= int(b)
print('a is {} & b is {}'.format(a,b))
我修改了前面的代码,并插入了整数转换。让我们看看我们得到了什么:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/condition.py
a is 1 & b is 0
看那个!True 转换为 1,False 转换为 0!
同样,您可以使用 bool()方法将数字和字符串转换为布尔值。任何不是空字符串或数字 0 的值都将返回 True。是的,即使是负数也会返回 True!我们为什么不测试一下呢?
我将在我的 Shell 中直接测试相同的内容。
1 转换为 True。
>>> bool(1)
True
0 转换为 False。
>>> bool(0)
False
一个包含某些内容的字符串会转换为 True。对于内部只有一个空格的字符串也是如此。
>>> bool('hi there!')
True
空字符串转换为 False。
>>> bool('')
False
Python 中有一个值“None”。它基本上意味着里面什么都没有。如果将“None”赋给一个变量,该变量中的值将被替换为空值。自然,“无”会转换为 False。
>>> bool(None)
False
在后面的章节中,我们将会看到更多的叫做列表、元组和集合的值。当我们这样做时,您会注意到,包含某些内容的列表、元组和集合会转换为 True,而空列表、元组和集合会转换为 false。
比较并决定
好了,我们已经看过结果了。但是我们如何得到它们呢?我们需要返回这些结果的条件,不是吗?Python 有很多条件你可以用!你想看看吗?我要再次提醒你这里的数学课。
还记得大于号(>)和小于号(
是的,你可以用那些符号作为你的条件!为什么我们不在我们的壳里测试它们呢?
3 大于 5 吗?
>>> 3 > 5
False
没有。
>>> 3 < 5
True
但是 3 比 5 小吗?哦,是的!
快看,成功了!你甚至可以测试是否相等。两个数相等吗?只要用两个等号代替一个,就可以了!
>>> 3 == 3
True
太好了。
您还可以使用不等于运算符来查看两个值是否不相等!=,像这样:
>>> 2 != 2
False
2 不等于 2 吗?不,它们是相等的,所以你得到一个假的。
你也可以用字符串来做这个,不仅仅是数字。
>>> 'hello' == 'Hello'
False
我们有一个错误。你能猜到原因吗?没错。Python 是区分大小写的,所以“H”不等于“H”。
您可以使用< =符号检查某个值是否小于或等于另一个值,从而简化计算。
>>> 2 <= 2
True
前面的代码为真,因为即使 2 不小于 2,它也肯定等于 2,并且由于其中一个条件为真,因此结果为真。
同样,您可以使用> =符号检查某个值是否大于或等于另一个值。
>>> 3 >= 5
False
3 既不大于也不等于 5,因此结果为假。
如果发生这种情况,请执行以下操作(命令!)
我们现在知道所有关于“真”、“假”和条件的事情。下一步是什么?当然是命令!
Python 中有一个漂亮的小工具可以用来发出命令。这就是所谓的“如果”陈述。你能猜出它是做什么的吗?给你个提示:跟“如果”有关。😛
到目前为止,您已经知道了如何创建条件以及如何解释它们的结果(真或假),现在让我们将所有这些放在一起给出一个命令。
事实上这很简单。简单地说,这就是“if”语句的作用:它检查一个条件,如果该条件为真,那么它执行一条或多条语句。如果这不是真的,那么这些语句将不会被执行,你的程序将会进入下一行代码。
让我快速演示一下“if”语句是如何工作的,以便你更好地理解它(图 9-2 )。
图 9-2
“如果”语句
“if”语句的语法如下:
if comparison:
lines of code
“if”有一个小“I”,if 语句内的语句要写缩进,基本就是空格/制表符。比较后的冒号“:”也是必需的。如果您不缩进“内部”代码行,那么 Python 不会知道这些代码行属于“If”语句,并且只应在条件为真时执行。所以,记得缩进,好吗?
好了,现在我们知道了 if 语句是如何工作的,让我们来测试一下。如果某人的年龄小于 5 岁,我想印“你是个小孩”。就这样。
我们如何做到这一点?嗯……条件可能是age < 5
或类似的东西。如果我想把 5 岁包括在这个列表中,那么我可以把它列为age <= 5
。我可以在我的声明中包含一个打印声明,基本上就是说“你是一个小孩子”。应该可以了,对吧?我们来测试一下!
age = input("What's your age? ")
age = int(age)
if age <= 5:
print("You're a little kid :)")
我创建了一个变量 age,从用户那里获得输入,并将默认字符串转换成整数,这样就可以与数字进行比较。
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\condition.py
What's your age? 5
You're a little kid :)
耶,成功了!您已经在 Python 中执行了第一个条件命令。庆祝的时间到了。
现在,我要你给出任何一个大于 5 的数字,看看你会得到什么。
你试过吗?你什么也得不到,对吗?嗯,那不理想。让我们在下一节解决这个问题吧!
不然呢?
我们看到,如果条件为真,我们可以执行“if”语句的内部语句。但如果不是真的,什么都不会发生。但是如果我想发生什么呢?如果孩子大于 5 岁,那么我希望打印出“你是一个大孩子”。我该怎么做?
“if”语句伴随着“else”语句。如果“if”语句为假,它们就会被执行。让我来说明这是如何工作的(图 9-3 )。
图 9-3
“if else”语句
else 语句的语法非常简单:
else:
inner lines of code
您应该在“else”后面加上一个冒号,因为这次我们不需要检查条件。同样,就像你的“if”语句一样,把你的内部代码行放在缩进、制表符或空格之后。
现在让我们来测试一下这是如何工作的!
age = input("What's your age? ")
age = int(age)
if age <= 5:
print("You're a little kid! :)")
else:
print("You're a big kid! :)")
现在让我们假设年龄为 8 岁,看看我们的程序会做什么:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\condition.py
What's your age? 8
You're a big kid! :)
哇哦!
不止一个条件!O:
你知道,有时候,事情不只是黑与白,对吗?如果有人超过 5 岁,他们不一定还是孩子。如果他们超过 12 岁,他们就是青少年了。如果他们超过 18 岁,他们就是成年人了。但是我们的项目没有考虑所有这些。嗯…不完整,你不觉得吗?让我们解决这个问题。
有一种叫做“elif”的语句可以插入到“if”和“else”语句之间。你能猜出 elif 是做什么的吗?名字里就有,不是吗?如果某个值为假,那么我们将检查第二个条件,看看和是否为真。在用 else 语句结束之前,可以像这样一个接一个地堆叠任意数量的 elif 语句。让我来说明这是如何工作的。
elif 语句的语法(在 if 之后,else 之前)如下(图 9-4 ):
图 9-4
“if elif else”语句
elif condition:
Inner lines of code
让我们现在测试一下我们的 elifs,好吗?我将创建一个主要的“if”条件来测试 if age <= 5
(小孩)。如果这不是真的,我们将包括另一个测试是否age <= 12
(大孩子)的条件。我们将包含第三个条件来测试age <= 19
(青少年),最后包含第四个条件来测试age >= 20
(成人)。
好的,听起来不错,但是 else 语句是用来做什么的呢?else 语句将捕捉所有其他内容。例如,如果您的用户错误地输入了一个字符串或任何其他非数字值,那么您的 else 语句将“捕捉”到这一点,并要求他们重新运行程序。够清楚了吗?我们要不要用代码写这个,看看是否可行?好吧。
age = input("What's your age? ")
age = int(age)
if age <= 5:
print("You're a little kid! :)")
elif age <= 12:
print("You're a big kid! :)")
elif age <= 19:
print("You're a teenager! :)")
elif age >= 20:
print("Wow, you're an adult already!")
else:
print("Looks like you've not entered a number. Please re-run the program")
我将运行年龄为 13 岁的前面几行代码。
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\condition.py
What's your age? 13
You're a teenager! :)
现在,我要你每次用不同的年龄值(数字或其他)运行这个程序,看看你得到了什么。你为什么不试着也给一根绳子呢?玩得开心!
迷你项目-猜数字游戏
这将是一个简单的小游戏。我们不会在这里使用“ Turtle ”,但是你可以随意在游戏的任何部分使用它。
所以,游戏是这样工作的:当游戏开始时,程序会生成一个 1 到 10 之间的数字(包括 1 和 10)。然后,用户有三次猜对数字的机会。如果他们猜对了任何一个数字,他们就赢了。否则,他们就输了。简单吧?我们试试吧!
-
我们先导入“随机”模块。我们需要这个模块,因为我们将在游戏开始时生成一个 1 到 10 之间的数字,用户需要猜这个数字。
-
让我们从打印一条介绍游戏的消息开始。然后,让我们生成我们的随机数。我们将使用“随机”模块的 randrange()方法。你还记得这个方法吗?它从该范围内生成一个随机数,不包括该范围内的最后一个数。我们需要一个介于 1 和 10 之间的数字,所以范围是 1,11。
print('Guess a number and win!') number = random.randrange(1,11)
-
然后,让我们从用户那里得到第一个猜测。输入通常是字符串,所以我们先把它们转换成整数。
guess1 = input('Guess a number between 1 and 10 - Your first try: ') guess1 = int(guess1)
-
现在,我们将开始我们的比较。如果第一次猜测与数字相等,则打印一条成功消息。如果没有,开始一个“else”语句。在 else 语句中,重新开始。得到第二个猜测,在“else”中,开始一个内部“if”语句,检查第二个猜测是否与要猜测的数字相同。
if(guess1 == number): print('You guessed it right! :)') else: guess2 = input('Guess again - Your second try: ') guess2 = int(guess2) if(guess2 == number): print('You guessed it right! :)')
-
我们将在第三次尝试中做同样的事情。
else: guess3 = input('Guess again - Your final try: ') guess3 = int(guess3) if(guess3 == number): print('You guessed it right! :)')
-
最后,最后一个“else”语句。如果他们在三次尝试后仍然没有猜中,那么程序将运行最后的“else”语句并打印一条悲伤的消息。☹,为什么我们不告诉他们号码是多少?他们可能想知道,对吗?
-
而且,就是这样!一个简单的小程序。
else: print('Sorry! You used up all your tries! :(') print('The number was {}'.format(number))
import random
不如我们来看看这个游戏行不行?让我们运行上面的代码,我们将得到这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\condition.py
Guess a number and win!
Guess a number between 1 and 10 - Your first try: 5
Guess again - Your second try: 7
You guessed it right! :)
第二次试就猜到了!哇哦!
让我们再试一次:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\condition.py
Guess a number and win!
Guess a number between 1 and 10 - Your first try: 10
Guess again - Your second try: 6
Guess again - Your final try: 3
Sorry! You used up all your tries! :(
The number was 2
哎呀,这次我错过了。数字是 2。☹
情况越积越多!
有时,您可能希望同时检查多个条件。或者你可能希望你的情况与它的实际情况相反。
Python 为您提供了两个选项来实现这一点。这些被称为逻辑操作符,你可以用它们来组合条件语句(比较)并得出最终的真或假结果。迷茫?不要这样。我会解释的。
第一个是 和 运算符。如果在两个或更多比较上使用“与”运算符,那么条件将返回 true 只有如果 所有 比较都为 true。
语法如下:
(comparison1) and (comparison2)
您也可以编写不带括号的比较,执行仍然会正常进行(比较优先于逻辑操作符),但是包含它们以使执行顺序更清晰总是一个好的做法。
让我解释一下“and”操作符是如何工作的。英语中“and”是什么意思?包容一切,围绕“和”,对吗?所以,当你在两个或更多的条件周围使用这个语句时,只有当它周围的所有条件都为真时,最后的结果才为真。如果其中一个条件为假,那么即使另一个条件为真,你也会得到一个假的结果。我为什么不用一个例子来解释这个呢?(图 9-5 )
图 9-5
“与”语句及其结果
你现在明白“和”是怎么运作的了吧?
接下来,您有了 或 运算符。这是怎么回事?很简单,真的。在英语中,“或”是“非此即彼”的意思,我说的对吗?因此,如果“或”运算符周围的任一条件为真,则整个语句为真。
如果在两个或更多比较上使用“或”运算符,那么如果这些比较中的任何一个为真,则条件将返回真。
**语法如下:
(comparison1) or (comparison2)
让我来说明“或”语句是如何工作的(图 9-6 )。
图 9-6
“或”语句及其结果
最后,还有 而不是 运算符。这里没什么好猜的。很简单,不是吗?“not”运算符只是颠倒了结果。如果比较的结果为真,那么在比较语句中使用“not”运算符将返回假,反之亦然。
语法如下:
not(comparison)
您也可以在其他逻辑语句中使用“not”运算符:
not((comparison1) and (comparison2))
在编程中,你需要确保你总是关闭括号。在前面的语法中,我们用两组括号将每个比较括起来,中间是“and”运算符,另一组括号将所有比较括起来。
让我们通过在 Python Shell 中测试这些语句来结束本章:
>>> (5 > 3) and (4 < 3)
False
5 大于 3,但 4 不小于 3。如果我们使用“或”操作符,
>>> (5 > 3) or (4 < 3)
True
我们得到一个真值,因为其中一个比较为真。
现在就来结合逻辑语句吧!我们为什么不用数学运算来做比较,让事情变得复杂一点呢?
>>> ((5 > 3) or (4 < 3)) and ((3 + 2) == 5)
True
花一分钟仔细阅读前面的陈述。先看看括号的位置。我用括号将每个操作(大于、小于和加法)括起来,一个括号包含“或”语句,另一个括号包含等于操作。如果我漏掉了其中的一个括号,我要么会得到一个错误,要么运算的顺序会被打乱,我的答案会是错误的。
现在让我们测试“not”运算符。
>>> not(5 > 3)
False
5 > 3 是真的,但是因为我在比较中使用了“not”操作符,所以得到了一个假的。
>>> not((5 > 3) or (4 < 3))
False
“或”运算的结果为真,因为其中一个语句为真,但由于我对所有语句都使用了“非”,所以最终结果为假。
>>> (5 > 3) and (not(4 < 3))
True
原来,前面的操作返回 false 是因为 4 < 3 is not true. But I used “not” on 4 < 3, which made the final result of the comparison True. So 为真,而 True 为真。
我要在这里停止测试,但我要你全力以赴!为什么不把所有你知道的数学运算符与比较运算符和逻辑运算符结合起来呢?尝试不同的组合,看看你会得到什么。编程就是要实验。实验去吧!
摘要
在这一章中,我们学习了如何命令我们的电脑做我们想做的事情。我们学习了布尔值和条件以及它们的结果。然后,我们继续学习“if”、“else”和“elif”语句,以及如何使用它们来命令我们的计算机。最后,我们看了“and”、“or”和“not”以及它们的用法。像往常一样,我们也做了一些小项目。
在下一章,让我们看看用循环来自动化我们的程序。你会发现在用海龟创建图形时,这是一种受欢迎的解脱。**
十、自动化一点
在前一章中,我们学习了所有关于条件、if、else 和 elif 语句的知识,以及如何组合多个条件来创建复杂的命令。
在这一章中,让我们看看循环的自动化,如何使用 for 和 while 循环来自动化图形的创建,如何用 break 语句提前结束循环,等等。在这一章中,我们将会看到许多丰富多彩和有趣的迷你项目。
魔法圈!
Python 的神奇和奇妙是永无止境的,循环是其中的佼佼者!还记得我们为了在 turtle 中绘制一个简单的小图形而编写的大量代码吗?你想要更简单的方法来做同样的事情吗?如果您可以用四到五行代码一个接一个地画出数百个方块,那会怎么样?那只是一个例子。如果你想在海龟身上打印出 1 到 100 的数字,又是 4 到 5 行代码,该怎么办呢?这是 100 条打印语句,但我们只用了四行代码就完成了。怎么会?这就是循环的力量。
使用循环,你可以让你的程序重复相同的动作任意次。您想打印 1 到 100 之间的内容吗?可以创建一个自动化代码,从 1 开始,打印 1,然后 1 加 1,就是 2;打印出来,并再次递增;等等。
看图 10-1 。我们有一堆代码行。存在一个范围,只要该范围为真,我们就运行相同的代码行。该范围从一个数字开始,每次循环重复时递增 1。一旦达到设定的数量,我们就停止运行“循环”。每次运行这些相同的代码行,就称为一次迭代。在我们的例子中,我们将有 100 次这样的迭代来打印 1 到 100。
图 10-1
循环——插图
Python 中有两种类型的循环,我们将同时研究这两种循环。我还将通过许多迷你项目来展示这些循环的威力。你对开始感到兴奋吗?我知道我是!循环是真正的交易。你已经成功一半了!
对于循环
For 循环是最常用的循环。他们不只是迭代给定的次数。是的,他们确实是这样做的,但是你可以使用“for 循环”来迭代字符串、列表和许多类似的复杂数据。
在这一章中,我们将只研究在给定的数字范围内使用 for 循环,或者用一个字符串作为范围。一旦我们将来看到复杂的数据类型,比如列表和字典,让我们重温一下 for 循环,以及如何在这些数据类型中使用它们,好吗?
好吧,那我们开始吧!
让我们继续前面的例子。我想打印从 1 到 100 的数字。你已经看过插图了。你知道需要什么。让我们先看看如何在一个范围内写一个 for 循环,然后让我们试着解决我们的问题,好吗?
语法非常简单。您必须以“for”关键字开始语法,并在整个语法中使用小写字母。然后,您需要创建一个临时变量。它可以是一个“x”(随机的,未知的数字)或一个“I”(表示迭代),或者它可以是你想要的任何变量名。该变量将在每次迭代的范围内存储您的当前数字。
所以,如果你的范围是从 1 到 5,假设我们把临时变量命名为“x”。
Iteration 1 : x is 1
Iteration 2 : x is 2
Iteration 3 : x is 3
Iteration 4 : x is 4
Iteration 5 : x is 5
当 x 达到 5 时,我们的循环停止执行。你知道这是怎么回事吗?
此外,你的数值范围可以是任何东西,真的,只要它有连续性。如果您给定的范围是 range(1,6),那么这意味着您希望每次迭代的 x 值从 1 到 5。忽略范围内的最后一个数字。
别忘了你的结肠!就像在你的“if”语句中一样,你的“for”语句以一个冒号结尾,并且它里面的代码行应该放在一个缩进后面。
所以,语法应该是这样的:
for x in range(1,6):
lines of code
我知道,我知道。都有点混乱,太理论化了。我们来看一堆例子,好吗?
我的问题陈述是什么来着?我想打印从 1 到 100 的数字,对吗?范围应该是 range(1,101 ),因为我希望包含 100,并且我只需要在循环中包含一个 print 语句。
代码应该是这样的:
for x in range(1,101):
print(x)
运行前面的代码,您会得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
1
2
3
.
.
.
97
98
99
100
我的代码打印了全部内容,但是我不认为我们在这一章中有足够的空间来打印所有内容,所以这里是它的“剪切”版本。你有没有运行代码看看?很神奇,对吧?你只用了两行代码就完成了所有这些。仅此而已。 即 是循环往复的力量。
只有当我想打印范围内的所有内容时,这才有效。如果我只想打印偶数,该怎么办?我可以给出一个我力所能及的条件来实现它。
假设我的范围是这样的:range(2,101,2)
我基本上要求我的代码从 2 到 100 打印,但是对于每一次迭代,我希望“x”的当前值增加 2 而不是 1。
因此,x 在第一次迭代中是 2,在第二次迭代中是 4,依此类推。我们要测试这个吗?
for x in range(2,101,2):
print(x)
当我运行前面的代码时,我会得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
2
4
6
8
10
.
.
.
94
96
98
100
如果你希望每次的增量都是 3,那么把 3 作为第三个参数,以此类推。
for 循环中的 If 语句
或者,我可以使用我们在第五章学到的模数运算符来过滤掉我不想要的数字。所以,如果我只想打印 off 数,那么我可以做一个 x % 2 运算,每当我得到 1 的结果时,我就可以确认当前数是奇数并打印出来。
1 % 2
是1
2 % 2
是0
3 %
2 又是 1
你看到模式了吗?让我们试试这个!
for x in range(1,101):
if (x % 2) == 1:
print(x)
现在你知道如何在 for 循环中使用 if 语句了。同样,也可以在 if 循环中使用 for 语句。
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
1
3
5
7
.
.
.
93
95
97
99
嵌套 for 循环
您也可以在 for 循环中创建 for 循环。这些被称为嵌套 for 循环。为了演示嵌套循环是如何工作的,我将在本节末尾创建一个为每次迭代打印星号的模式,作为一个迷你项目。
但在我们开始之前,我想介绍一个印刷概念。你有没有注意到每个新的打印语句是如何写在新的一行中的?这是默认的。但是如果我们不想那样呢?如果我们希望下一条 print 语句与前一条语句在同一行,该怎么办?您可以使用" end = "语法来实现这一点。
print('Hello', end = " ")
print('there!')
如果您运行前面的代码行,您将得到以下结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
Hello there!
end = " "告诉您的 print 语句用一个空格结束 print 语句,并指示 IDLE 在空格后立即打印下一个 print 语句,而不是在新的一行中。
现在你知道了如何操作 print 语句,让我们回到嵌套循环。
实际上,语法非常简单。假设我想连续打印 123 个数字,一个接一个,重复十次。因此,外部循环的范围为(1,11),内部 for 循环的范围为(1,4),print 语句只出现在内部 for 循环中,因为我们只需要打印出 1、2 和 3。我们来测试一下,好吗?
for x in range(1,11):
for i in range(1,4):
print(i, end = "")
在前面的代码行中,我没有在 end =后面加空格,因为我希望 1、2 和 3 一个接一个地打印出来。另一方面,如果我给出这样的结果:end = ",那么我会在每一行得到 1,2,3 这样的结果。你可以随心所欲地设计这个。尝试使用其他特殊字符来操纵结果。
当我运行前面的代码时,我得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
123123123123123123123123123123
哎呀,出问题了!那是什么?好吧,我们从来没有打破界限,不是吗?我们需要在每一行都写完之后这样做,这样我们就可以在下一行重复同样的事情,我说的对吗?让我来。
Python 中有一段代码可以让您创建一个新行。它叫做\n,它类似于我们在想把单引号和双引号排除在代码之外时使用的反斜杠,还记得吗?所以我只需要在内部 for 循环结束后添加另一行代码。
for x in range(1,6):
for i in range(1,4):
print(i, end = "")
print("\n")
你看到凹痕了吗?第一个打印语句在内部 for 循环中,第二个打印语句在外部 for 循环中。缩进会影响 Python 代码的成败,所以要非常小心,好吗?如果我在第一行的同一行写第二个 print 语句,那么 Python 会认为我想要在每个数字都被打印出来之后,而不是在每一行都被打印出来之后再写一行。那就完全不同了,不是吗?
当我运行前面的代码时,我得到了这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
123
123
123
123
123
或者,您可以用一个空的 print()结束外部的 for 循环,您将得到一个新行,因为默认情况下 print 语句会生成新行。
迭代字符串
与“while”循环相比,for 循环的优点在于它们迭代的是事物,而不仅仅是数字范围。例如,您可以迭代字符串中的每个字母。你想尝尝吗?
让我创建一个变量“a ”,并在其中放置一个字符串“Hello there”。然后,我将使用相同的语法,但这一次,我将只提到“a”,它包含字符串,而不是范围。
a = 'Hello there!'
for x in a:
print(x)
让我们看看我们得到了什么:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
H
e
l
l
o
t
h
e
r
e
!
看那个!每一行都印上了每个字符。很整洁,是吧?想想像这样强大的东西的所有可能性!
While 循环
既然您已经彻底探索了“for”循环,而“循环是小菜一碟,相信我。与 for 循环不同,while 循环会一直执行循环中的语句,只要条件为真。还记得你的“如果”声明吗?与此类似,但这里有一个额外的迭代元素。
语法非常简单:
initialize
while condition:
lines of code
increment
语法有点混乱,不是吗?我举个例子解释一下。实际上,它类似于 for 循环,只是稍微长一点。在 for 循环中,我们给出一个范围。假设我们的范围从 1 开始,那么在我们的“while”循环中,我们需要用范围的开始来初始化我们的临时变量,如下所示:
x = 1
然后,我们需要条件。假设我们希望范围在 11 处结束,这意味着它需要从 1 迭代到 10,因此我们可以给出这样的条件:
while x < 11:
或者,你也可以让你的条件 x <= 10。你可以自由地用你的“while”循环来做这件事。
最后,你需要你的代码行。它可以是任何东西,真的,它可以是任何数量的语句行。但是就像你的“for”循环一样,内部代码行需要在缩进之后。
这是我们目前掌握的情况:
x = 1
while x < 11:
print(x)
但是如果我们在这里结束循环,我们会创建一个永无止境的循环。“x”将始终为 1,并且将始终小于 11,因此条件将始终为真,循环将永远不会停止执行。那很危险。所以我们需要循环在某一点停止,对吗?这就是增量的来源。用你想要的任何数字增加 x,所以在某一点,循环结束。
这是我们最后的代码:
x = 1
while x < 11:
print(x)
x += 1
让我们运行前面的代码:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
1
2
3
4
5
6
7
8
9
10
完美!
中止任务!中断并继续
打破,然后继续。不难猜到这些是做什么的,是吗?“break”语句中断循环,不管您的范围或条件是否为真。
for x in range(1,11):
if(x == 5):
break
print(x)
print('Loop broke :(')
在前面的代码行中,我在中间劫持了我的 for 循环。当 x 为 5 时,我要求循环中断,执行行将立即跳转到循环后的行,这是打印“循环中断了☹".”的打印语句让我们测试一下这是否可行。
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
1
2
3
4
Loop broke :(
看那个。我甚至没有得到 5 分,因为我的 break 语句在我的 print 语句之上。☹:这就是“休息”的方式。
但是,另一方面,“continue”语句只是跳过特定的迭代,仍然执行其余的迭代。这次我们为什么不用 while 循环来测试呢?让我们用同样的例子,但是这一次,当 x 为 5 时,我想要一个 continue。
x = 1
while x < 11:
if x == 5:
x += 1
continue
print(x)
x += 1
print('5 was skipped!')
仔细阅读前面的代码行。你注意到什么了吗?我在 continue 语句之前包含了另一个 increment 语句。为什么?还记得我告诉过你我们需要小心 while 循环中的无限循环吗?如果我继续循环,那么 x 会一直停留在 5,因为在每次迭代中,我的程序会检查 x 是否为 5,它会一直为真,因为增量不会发生。所以虽然循环可能很棘手。小心点。
让我们运行我们的代码:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\numbers.py
1
2
3
4
6
7
8
9
10
5 was skipped!
是的,的确如此。5 被跳过!
你现在是循环专家了。恭喜你自己!
迷你项目-猜数字游戏版本 2
我们将再次尝试上一章的“猜数字”游戏,但这一次,我们将引入自动化的魔力。
像往常一样,用户可以试三次,但每次失败时,他们都会得到一个提示,告诉他们自己的猜测是高于还是低于要猜测的数字:
-
让我们先导入 random 模块,因为我们将从中生成要猜测的数字。
-
让我们打印出一条消息,然后在 1 到 10 的范围内生成一个随机整数(整数)。范围中的最后一个数字是 11,因为 randrange()不考虑这一点。
print('Welcome to Guess a Number Game!') number = random.randrange(1,11)
-
接下来,让我们创建一个运行三次迭代的 for 循环(范围为 1,4,从 1 到 3)。对于每次迭代,要求用户输入一个 1 到 10 之间的数字。获取输入,并将其转换为整数。
for i in range(1,4): guess = input('Enter a number between 1 and 10: ') guess = int(guess)
-
一旦进入,我们将开始我们的比较。首先,我需要检查最后一次迭代,因为如果我们已经到了最后一次尝试,他们仍然没有猜对,我们需要停止游戏。那么,让我们检查一下“I”的值是否为 3,猜测是否仍然不对。打印一条“对不起”的信息,告诉他们号码是多少。
if(i == 3 and number != guess): print('Sorry! You used up all your tries! :(') print('The number was {}'.format(number))
-
但是,如果他们在最后一次尝试中猜对了,那么打印成功消息。
elif(i == 3 and number == guess): print('You guessed it right! :)')
-
现在我们已经完成了检查,让我们创建一个“else”语句来包含前两次尝试的代码。
import random
对于前两次尝试,检查当前猜测是否是错误的。如果是,那么在检查“猜测”是小于还是大于要猜测的数字之后,打印一条消息。如果他们在任何一次尝试中都猜对了,那么打印一条成功消息并中断 for 循环,因为我们不需要更多的迭代。
如果在第三次迭代中,你不需要“break”语句,因为这将是循环的最后一次迭代。
else:
if(number != guess):
if(guess < number):
print('You guessed a lesser number. Try higher.')
else:
print('You guessed a higher number. Try lower.')
else:
print('You guessed it right! :)')
break
就这样!很简单,不是吗?让我们看看它现在是否工作。
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\condition.py
Welcome to Guess a Number Game!
Enter a number between 1 and 10: 10
You guessed a higher number. Try lower.
Enter a number between 1 and 10: 5
You guessed a higher number. Try lower.
Enter a number between 1 and 10: 3
You guessed it right! :)
我最后一次猜对了。咻!
有趣的小游戏,你不觉得吗?和朋友一起试试吧!根据需要增加或减少尝试次数或范围。为此疯狂吧!?IndexRangeEnd ID="ITerm14 "?>
迷你项目-自动化您的广场
这将是一个简单的项目。我们将在 Turtle 中自动化我们的 square。
我要创建一个 for 循环。我将范围设为 1:5,这样它会迭代四次来绘制正方形的四条边。我将在整个循环中重复向前 100 点和向右 90 度。
import turtle
s = turtle.getscreen()
t = turtle.Turtle()
t.pensize(5)
t.color('Red','Green')
t.begin_fill()
for x in range(1,5):
t.forward(100)
t.right(90)
t.end_fill()
t.hideturtle()
turtle.hideturtle()
让我们运行前面的代码。看那个!我们有我们的正方形(图 10-2 ),我们只写了之前写的几行的一小部分。
图 10-2
自动化广场
迷你项目-自动化任何基本形状
在这个项目中,我们将自动化我们给程序的任何形状。所以,你只要输入边数和边的角度,你的程序就会为你画出相关的形状。很酷,对吧?我们开始吧!
图 10-3
四边和 90 度角-正方形
-
我们先设置一下 turtle。
import turtle s = turtle.getscreen() t = turtle.Turtle()
-
我打算把笔的尺寸设为 5,这样我们的形状看起来会更好。我们的钢笔的颜色将是蓝色,形状的填充颜色将是橙色。
t.pensize(5) t.color('Blue','Orange')
-
接下来,让我获取边数和角度作为输入,并将其转换为整数。
sides = input("How many sides does your shape have?") sides = int(sides) angle = input("What's the angle between the sides?") angle = int(angle)
-
现在,让我们开始画画。从 begin_fill 开始,然后打开一个从 0 到 sides–1 的 for 循环(给 0,sides 作为范围)。这意味着,如果 sides 的值为 5,循环将运行五次,并将为循环的每次迭代绘制一条边。
t.begin_fill() for x in range(0,sides):
-
在 for 循环中,让我们创建一个“if”语句来检查我们是否到达了最后一面。如果有,那么我们将把笔带回家(0,0)并打破循环。
if(x == sides-1): t.home() break
-
在余下的迭代中,我们将把笔向前推 100 点,并以给定的角度将笔的方向改为正确的方向。
t.forward(100) t.right(angle)
-
“for”循环到此结束。让我们通过结束填充和隐藏海龟来结束这个程序。
t.end_fill() t.hideturtle() turtle.hideturtle()
-
Let’s give our inputs as 4 and 90:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\drawTurtle.py How many sides does your shape have? 4 What's the angle between the sides? 90
输入输出后,单击 Enter。查看
turtle
屏幕,您将看到如图 10-3 所示的图像。
那是一个正方形!
-
现在,3 和 60(图 10-4 ):
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\drawTurtle.py
你的形状有几条边?3
两边之间的角度是多少?60
图 10-4
边 3 和角 60——三角形
一个等边三角形!
- 现在,6 和 60(图 10-5 ):
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\drawTurtle.py
你的形状有几条边?6
两边之间的角度是多少?60
图 10-5
六边形和 60 度角-六边形
六边形,不错!
尝试用 5 和 60 得到五边形,用 8 和 45 得到八边形,用不同的值做实验,看看你得到了什么。玩得开心!
迷你项目-自动绘制曼荼罗设计
在这个项目中,我们将自动绘制一个合适的曼荼罗设计。很简单,你会明白的!
-
我们先设置一下 turtle。
import turtle s = turtle.getscreen() t = turtle.Turtle()
-
我要把笔的速度设为 0,这样它就能画得很快。笔的大小是 5,笔的颜色是红色。
t.speed(0) t.pensize(5) t.pencolor('Red')
-
接下来,让我们打开一个 for 循环,我准备让它循环 7 次(范围 0,7)。现在,我已经通过反复试验得出了这个 for 循环中的所有值。你可以随心所欲地改变它们,看看你会得到什么,好吗?
-
在 for 循环的每次迭代中,我都要画一个 100 点的圆,然后左转 50 度。
t.circle(100) t.left(50)
-
就这样!如果你现在运行这个程序,你会看到你的曼荼罗设计。但是我们为什么不更进一步,在设计里面画一个圆呢?将钢笔大小更改为 7,转到位置–10,–50(通过试错找到),将钢笔颜色更改为蓝色,绘制半径为 50 的圆。最后,把乌龟藏起来。
t.pensize(7) t.penup() t.goto(-10,-50) t.pendown() t.pencolor('Blue') t.circle(50) t.hideturtle() turtle.hideturtle()
for i in range(0,7):
运行前面的代码,你会得到这个(图 10-6 )。
图 10-6
简单的循环曼荼罗设计
那看起来很漂亮!尝试改变值和颜色,看看你会得到什么。
迷你项目-弧形螺旋
在这个项目中,我们将演示 Python 中的 setheading()方法。我们要画圆弧螺线!你会明白的。
-
让我们先设置一下
turtle
。import turtle s = turtle.getscreen() t = turtle.Turtle()
-
首先,我将把当前的标题(方向)打印到 Shell。当我们开始的时候你会看到它是 0。让我们也改变笔的大小为 5 和速度为 5,所以它画得有点快。
print(t.heading()) t.pensize(5) t.speed(5)
-
我要把起始角度设为 0。
-
然后,我将打开一个运行 12 次的 for 循环,因为我想展示圆弧中一个圆的 12 个角。
angle = 0
图 10-8
四分之一圆螺旋
-
每次循环运行,我都会画一个半径为 100 的半圆。在半圆的末端,我会写下当前的方向。然后我会把我的笔移回到起点,这样它就为下一个弧做好了准备。
t.circle(100,180) t.write(t.heading()) t.penup() t.home() t.pendown()
-
最后,我将在循环的每次迭代中增加 30°的角度,并将航向设置为那个特定的角度。
angle += 30 t.setheading(angle)
-
Run the preceding code, and you’ll get this (Figure 10-7).
图 10-7
半圆螺旋
-
将圆的角度改为 90 度画四分之一圆(圆弧),就得到这个(图 10-8 )。
for i in range(12):
如果你愿意,你可以删除文字,在所有的东西上画一个圈,并且使它也成为一个新的曼荼罗设计!
摘要
在这一章中,我们学习了如何通过使用循环在你的程序中实现入门级的自动化。我们学习了 for 循环、while 循环和 ranges,以及如何用 break 和 continue 语句操作循环。我们也用本章学到的概念创建了许多迷你项目。
在下一章,让我们看看如何用 Python 的内置数据结构在一个变量中存储多个值和不同种类的值。
十一、很多很多的信息!
在前一章中,我们学习了所有关于用 for 和 while 循环自动化代码的知识。我们还查看了 break 和 continue 语句,并创建了许多丰富多彩的迷你项目。
在这一理论密集的章节中,让我们看看 Python 提供的各种内置数据结构。让我们看看如何使用这些数据结构在单个变量中一次存储多个值,并看看在现实世界的程序中使用这些数据结构的实际例子。
存储多个值
到目前为止,我们只是一次存储一个值。当然,我们可以改变值,但是我们不能在同一个地方存储两个值。那不是有点不方便吗?假设我想存储六个不同的颜色值,这样我就可以在我的代码中一个接一个地使用它们。
我该怎么做?我可能会这样做:
color1 = 'Red'
color2 = 'Orange'
color3 = 'Blue'
color4 = 'Yellow'
color5 = 'Green'
color6 = 'Violet'
然后,每当我想在代码中使用这些值时,我就必须记住并引用它们。哇…这是一个漫长的过程。
如果我能把所有六种颜色存储在同一个地方,同一个变量里,会怎么样?它看起来有点像图 11-1 。
图 11-1
同一变量中有多个值
这在 Python 中叫做 数据结构 。看看数据是如何构造(组织)和存储的?因此得名。有四种这样的预制数据结构可用于在同一位置存储多个值。您节省了许多代码行和时间,并且您的代码也更加高效。您也可以存储不同类型的数据。同一个数据结构可以存储字符串、数字和布尔值。
访问这些数据也很容易。在访问字符串中的单个字符时,你只需要遵循和我们使用的格式相似的格式。我一会儿会谈到这一点。
让我先向您展示四种数据结构:
-
列表 : Python 确实是一门简单易学的语言,不是吗?这种语言使用的关键字非常容易记忆。名单就是这样。这是一个信息列表,不过是 点了 。列表中的单个值可以被 改变 ,并且列表中的 允许其中有重复值 。
-
元组:元组类似于列表。唯一的区别是 的值一旦固定 就不能更改。这意味着您也不能添加或删除值。
-
集合:集合不同于元组的列表,是 无序的 ,没有索引可以从中访问特定的值。它 也不允许重复的值 ,因为这些值是无序的。
-
字典:顾名思义,字典将值以 字:描述 格式存储。字典也是无序的,但是它们可以改变,在 Python 中被称为“键”的“单词”充当索引,通过它可以访问值(描述)。
你现在可能正眯着眼睛看这本书。完全不用担心。乍一看,这些数据结构令人生畏。他们绝对不是。我将在下一节用有趣且容易理解的例子来解释它们,你很快就会明白所有的事情。
列表
让我们先来看看列表。创建它们非常容易。用逗号分隔要存储在列表中的多个值,并用方括号([])将所有内容括起来,这样就有了一个列表。你想尝尝吗?
让我们把前面例子中写的六行代码转换成一个列表,好吗?
colors = ['Red', 'Orange', 'Blue', 'Yellow', 'Green', 'Violet']
前面的例子中只有字符串(因此有引号),但是您可以创建一个只有数字的列表,或者只有布尔值,或者两个或更多的组合。根据你的需要创造你想要的东西。
你现在可能正眯着眼睛看这本书。一点也不担心。乍一看,这些数据结构令人生畏。他们绝对不是。我会轻松有趣地解释它们:
a = [1, 'Hello', True, False, 34.5, '*']
前面的代码是异类值(不同数据类型)的列表。
访问列表中的值
好,我们有一个值列表。我们如何访问它们?你想猜猜吗?你已经知道了。
是的,有索引,就像我们对琴弦做的那样。列表中第一个值的索引为 0,第二个值的索引为 1,依此类推。
假设我想在列表“a”中访问并打印第三个值。它在索引 2 处。
print(a[2])
运行前面的代码,您将得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/dataStructures.py
True
成功访问!
你可以做负索引,就像你对字符串做的那样。因此,要访问列表中的最后一个元素(值),我只需给出-1。
print(a[-1])
运行前面的代码,您将得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/dataStructures.py
*
有效!耶!
切一个单子!
如果负索引和访问有效,就像字符串一样,那么使用范围提取列表的一部分也应该有效,对吗?我们来测试一下。
假设我想提取第二个到第五个值,索引为 1 到 4。我的范围应该是 1:5,因为范围中的最后一个数字不包括在内。
print(a[1:5])
['Hello', True, False, 34.5]
哦,是的,它起作用了!那么通过负指数提取应该也可以,对吗?假设我想要从负的第三个索引中提取所有内容。
print(a[-6:-3])
你已经知道负指数是如何工作的了,对吗?如果我运行前面的代码,我会得到这样的结果:
[1, 'Hello', True]
您也可以更改值。假设我想将第二个值(字符串)改为一个数字。然后,我必须访问第二个值(第一个索引),并给它赋值。
a[1] = 100
print(a)
让我们打印整个列表,看看现在发生了什么变化:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/dataStructures.py
[1, 100, True, False, 34.5, '*']
列表操作着火了!
您有许多预定义的方法,可以用来以多种方式操作您的列表。还记得我们在你的琴弦上看到的方法吗?你会发现其中一些在这里也重复了。你准备好玩你的列表了吗?没错。
像往常一样,您可以使用 len()方法找到字符串的长度:
a = [1, 'Hello', True, False, 34.5, '*']
print(len(a))
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
6
没错。我们的列表长度是 6。有效。
对于我们将在本章中学习的每一种数据结构,你都有一个完整的方法列表。因此,我将把你链接到 Python 文档中的页面,那里列出了所有这些方法及其解释。
就是这里: https://docs.python.org/3/tutorial/datastructures.html
。
也就是说,让我们看看本章中一些最重要的方法,好吗?
复制并追加
append()方法在列表末尾追加或添加一个元素:
a.append('new')
print(a)
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
[1, 'Hello', True, False, 34.5, '*', 'new']
copy 方法创建列表的副本,该副本可以赋给任何变量以创建复制的列表:
b = a.copy()
print("List b contains: {}".format(b))
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
List b contains: [1, 'Hello', True, False, 34.5, '*', 'new']
清点并清除
列表可以有重复的值,对吗?假设我们有一个数字列表,其中的数字是重复的,我想检查一个特定的数字在列表中出现了多少次。我可以使用“计数”方法来实现这一点。
l = [1,2,1,1,4,5,3,5,3,2]
print(l.count(1))
我以列表名“l”开始语法,然后是方法名“count”,然后我提到了我想要计数的值(1)。如果它是一个字符串,我会用引号引起来。让我们运行前面的代码,我们将得到这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
3
我们得到了正确的答案!数字 1 在列表中出现了三次。
您可以使用“清除”方法清除整个列表。
l.clear()
print(l)
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
[]
我们现在有一个空名单了!
串联
您可以使用“extend”方法来连接或联接两个列表。
list1 = [1,2,3,4,5]
list2 = [6,7,8,9]
list1.extend(list2)
print(list1)
正如您在前面的代码中看到的,您希望首先列出的列表元素排在最前面,然后是句点("."),然后是“extend”方法,然后在括号内,您可以提到您想要加入第一个列表的列表的名称。
让我们运行前面的代码,我们将得到这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
[1, 2, 3, 4, 5, 6, 7, 8, 9]
看那个!完美地结合在一起,并且按照我们想要的顺序。
在您的列表中搜索
“index”方法返回您正在搜索的值的第一个实例的索引。例如,如果您想在一个列表中查找数字 3,但是它重复了两次,那么只返回第一次出现的数字 3 的索引。让我举个例子:
list1 = [1,2,3,2,3,1,3]
print(list1.index(3))
当您运行前面的代码时,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
2
看那个!3 在列表中出现了三次,但我们只得到前 3 个的索引。太好了。
但是如果你愿意,你可以缩小搜索范围。如果我想在列表的后半部分找到 3,也许从第三个索引开始呢?您也可以将搜索的开始和结束指定为参数。让我告诉你怎么做:
print(list1.index(3,3,6))
我让我的程序从索引 3 到 5 中搜索 3。你知道这些东西是怎么运作的吧?该范围中的最后一个值将不包括在内。所以,如果最后一个值是 5,那么你的程序只会搜索到第五个索引。
当我运行前面的代码时,我会得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
4
看那个!我们得到了列表中 3 的第二个实例的索引。很好!
添加和删除元素
您知道如何使用方括号将元素添加到列表中,也可以使用相同的方法更改元素。但是,如果我想在列表中间插入元素,以便其他值仍然存在,但只是进一步移动,该怎么办呢?
您可以使用 insert 方法来实现这一点。方法中的第一个参数是您想要值的位置,第二个参数是您想要添加的值。
colors = ['Red', 'Orange', 'Blue']
colors.insert(1,'Green')
print(colors)
我在第一个索引中添加了值“Green”。现在‘桔子’应该再推一步。让我们检查一下,好吗?
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
['Red', 'Green', 'Orange', 'Blue']
是的,成功了!
默认情况下,pop()方法删除列表中的最后一个元素。如果你给了一个位置(索引),它会移除那个位置的元素。
让我们尝试删除前面列表中的第二个元素,也就是我们刚刚插入的元素,好吗?
colors.pop(1)
print(colors)
当我们运行整个代码时,我们会得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
['Red', 'Green', 'Orange', 'Blue']
['Red', 'Orange', 'Blue']
看那个!列表最初有四个元素,我们使用 pop()方法成功地删除了第二个元素。
或者,您也可以使用 remove()方法。唯一的区别是您可以指定想要删除的确切元素。
我们的列表目前有['红色','橙色','蓝色']。我不想要蓝色了。为什么我们不试着移除它?
colors.remove('Blue')
print(colors)
让我们看看它是否有效:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
['Red', 'Orange']
耶!成功了。
有点太长了,不是吗?别担心!我们快完成了。那就用一个有趣的小项目来分散我们的注意力,好吗?
反转和排序
还有一种方法叫做 reverse()方法。你能猜出它是做什么的吗?没错。它反转列表中的元素。我们试试吧!
li = [1,2,3,4,5]
li.reverse()
print(li)
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
[5, 4, 3, 2, 1]
成功!
最后(是的,最后),还有另一个方法叫做 sort()方法,它按照字母顺序对元素进行排序。
默认情况下,排序按升序进行。
colors = ['Red', 'Orange', 'Blue', 'Yellow', 'Green', 'Violet']
colors.sort()
print(colors)
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
['Blue', 'Green', 'Orange', 'Red', 'Violet', 'Yellow']
就像魔法一样!O:
这适用于数字吗?
li = [1,4,3,6,2,8,7,9,5]
li.sort()
print(li)
当您运行上面的代码时,您会得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
[1, 2, 3, 4, 5, 6, 7, 8, 9]
呵呵,管用。
但是如果我想按降序排序呢?在这种情况下,我将修改 sort()函数调用,如下所示:
li.sort(reverse=True)
print(li)
当您给定参数 reverse=True 时,您的程序将按降序对列表进行排序。默认值是 reverse=False,它按升序对列表进行排序。默认某件事发生的时候,不需要作为论据来提。
让我们运行前面的代码,我们将得到这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
[9, 8, 7, 6, 5, 4, 3, 2, 1]
很好…我的列表现在是降序排列。Python 让我们几乎可以做任何事情,不是吗?
列表更有趣!
您可以使用“in”关键字检查列表中是否存在某些内容:
print('Hello' in a)
在前面的代码行中,我们询问了字符串“Hello”是否是列表的一部分。
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
False
结果是假的。我们将第二个值从“Hello”更改为 100,还记得吗?所以,“你好”不再是列表的一部分。与 Python 中的所有内容一样,这些搜索也是区分大小写的。所以,“你好”不同于“你好”,如果字符串是“你好!”,那么你需要搜索整个东西。部分搜索不起作用。让我展示给你看:
a[1] = 'Hello there!'
print('Hello' in a)
我已经将第二个值更改为“Hello there!”,当我在列表“a”中搜索“Hello”时,让我看看我得到了什么:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
False
看那个。它仍然是假的,因为你没有用正确的词搜索。
现在你知道列表是如何工作的了,我想回到之前的话题。还记得“for”循环吗?记住我的承诺,当我教你关于列表的时候,我会重温 for 循环。我们现在在这里!
您可以使用 for 循环遍历列表。很简单。只需创建您的列表,然后将其替换为一个范围,如下所示:
l = [1,2,3,4,5]
for i in l:
print(i)
结果是这样的:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
1
2
3
4
5
或者,您也可以直接指定列表,如下所示:
for i in [1,2,3,4,5]:
用前面的代码行修改并运行您的代码,您会注意到您会得到相同的结果。
除了“extend”方法之外,您还可以使用“+”运算符连接两个列表,就像您处理字符串一样,如下所示:
list1 = [1,2,3,4,5]
list2 = [6,7,8,9]
list1 += list2
print(list1)
或者,您可以创建一个新变量,并将 list1 + list2 的值赋给它。两个都行。
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
[1, 2, 3, 4, 5, 6, 7, 8, 9]
“clear”方法只是清除列表。但是如果你使用“del”关键字,你可以删除整个列表。你想要检查吗?
让我们删除前面的列表,好吗?
del list1
print(list1)
当我尝试在删除 list1 后打印它时,我会得到一个错误,如下所示:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
Traceback (most recent call last):
File "C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py", line 10, in <module>
print(list1)
NameError: name 'list1' is not defined
看那个!“列表 1”已经完全从我们的程序中删除了。
您也可以对列表中的元素进行同样的操作。
a = [1, 'Hello', True, False, 34.5, '*']
del a[2]
print(a)
我已经让我的程序删除了列表中的第三个元素。让我们打印,我们会得到这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
[1, 'Hello', False, 34.5, '*']
第三个值“True”不再存在于列表“a”中。
迷你项目——多色自动星形
在这个项目中,我要用 Python 画一个星星,但是每一面都要有不同的颜色。这就是我的清单出现的地方。我将创建一个包含五种颜色的列表,并在其中运行一个 for 循环。对于 For 循环的每一次迭代, Turtle 都会用列表中的新颜色画出星星的一边。
让我们看看是怎么做的,好吗?
-
我将从设置 Turtle 的常用代码行开始:
-
我将设置笔的大小为 5,这样我的图像看起来很好。
import turtle
s = turtle.getscreen()
t = turtle.Turtle()
- 接下来,我将创建一个名为“colors”的变量,并为它分配一个由五种颜色组成的列表,“红色”、“棕色”、“绿色”、“蓝色”和“橙色”。我已经给了你一个颜色列表的链接,所以选择你喜欢的颜色。
t.pensize(5)
- 接下来,我将创建一个临时变量 x,它通过 for 循环遍历整个列表:
colors = ['Red', 'Brown', 'Green', 'Blue', 'Orange']
- 对于循环的每一次迭代,我的笔的颜色都会变成临时变量“x”中的当前颜色。我会让我的
turtle
向前移动 200 点,然后右转 144 点,因为一颗星星的外角是 144 度,我需要转那么多才能得到一颗合适的星星。
for x in colors:
- 这结束了我的 for 循环和缩进。最后,我要把我的乌龟藏起来。
t.pencolor(x)
t.forward(200)
t.right(144)
t.hideturtle()
turtle.hideturtle()
当你运行前面的代码时,你会得到这个(图 11-2 )。
图 11-2
多色星
没错。我们拿到了。为什么不试试不同颜色或不同形状的呢?或者,你可以尝试在每次迭代中随机选择颜色?你已经知道怎么做了(我已经教过你了),所以继续尝试吧。
元组
现在我们已经详细地看了列表,你会发现剩下的三个数据结构很容易理解,所以我将快速地浏览它们,好吗?
正如我之前提到的,元组类似于列表。唯一的区别是,它是有序的(就像一个列表,有索引和所有),但不可改变的(不像一个列表)。这对我们意味着什么?这只是意味着你不能添加、删除或改变列表中的元素。
现在这是一个扫兴的人!这是否意味着元组没有列表酷?确切地说,我不会这么说。你知道,你可能需要创建一个列表,你不希望任何人以后操纵,我说的对吗?类似于“只读”列表?在这些情况下,元组是您最好的朋友。否则,100%去做一个列表。
您可以创建带括号的元组,元组项用逗号分隔,如下所示:
t1 = ('Red', True, 2, 5.0)
print(t1)
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
('Red', True, 2, 5.0)
元组中的大多数内容都遵循与列表相同的格式,所以我只列出它们,我希望你们在自己的计算机上尝试一下。这是我们的小活动,好吗?
就像处理列表一样,可以用方括号访问元组中的元素。
t1[1]将返回第二个元素,True。元组就像列表一样被索引,其中第一个索引是 0。
就像列表一样,可以使用负索引来访问元组中的值。因此,t1[–1]将返回列表中的最后一个元素。
您也可以使用索引对元组进行切片。
如果您想要提取第二个到第四个值(最后一个),那么您可以指定 t1[1:4])或者只指定 t1[1:],因为我们无论如何都想要第一个索引中的所有内容。
如果你想用负索引写同样的东西,你可以这样做:t1[–3:]因为你想要从–3 到元组末尾的所有东西。
可以使用 len(t1)方法获得元组的长度,并使用“in”关键字检查元组中是否有内容,就像处理列表一样。你为什么不试试看?
然后是你的“for”循环。您也可以循环遍历元组。过程是一样的。
for x in t1:
print(x)
为什么不运行前面的代码,检查循环是否适用于元组?
到目前为止,元组看起来像写在括号内的列表。他们到底有什么用?还记得我说过元组是不可改变的吗?我们还没有尝试过改变元素或者添加元素到我们的元组中,不是吗?让我们试试。
我将尝试将第二个元素的值从 False 改为 True。
t1[1] = False
让我们运行我们的代码,我们会得到这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
Traceback (most recent call last):
File "C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py", line 4, in <module>
t1[1] = False
TypeError: 'tuple' object does not support item assignment
糟糕,我们出错了!元组不支持项赋值,这意味着它们的元素不能被改变。
尝试向元组添加新元素。访问第四个索引(第五个元素)并添加一些内容。当你这样做的时候,你会发现你遇到了同样的错误。
这是元组最重要的用途。您可以创建不可更改的列表,用于存储不应更改的敏感信息。如果你创建一个程序来存储你同学的身份证号码会怎么样?你不想改变这些,是吗?然后将它们存储在一个元组中。就这么简单!
但是,就像在您的列表中一样,您可以使用“del”关键字删除整个元组,就像这样:
del t1
如果你现在尝试访问 t1,你会得到一个错误。
元组也有方法,但是它们只有很少的方法可以用来访问元素,而且没有方法可以操作元素或元组本身。
“count”方法返回一个值在元组中重复的次数。记住,元组可以有重复的值,就像列表一样。
“index”方法返回元组中值的位置(索引)。
t1 = ('Red', True, 2, 5.0)
print(t1.index(5.0))
当您运行前面的代码时,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
3
没错。5.0 在第三个索引中(第四个位置)。
tuple 到此为止。很简单,不是吗?接下来让我们看看列表中的下一个数据结构。
设置
你还记得我跟你说过的关于布景的事吗?它们是无序的,不能有重复的值。真是祸不单行。但是电视也有其用途。你想看看吗?
太好了。你在花括号里写集合,像这样:
colors = {'Red', 'Orange', 'Blue'}
前面的代码是一组颜色“红色”、“橙色”和“蓝色”。
但是!集合是无序的。那么,这些价值真的会像我们创造的那样出现吗?你想要检查吗?
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
{'Blue', 'Orange', 'Red'}
哇,看那个!顺序变了。你能再运行一次程序并告诉我你得到了什么吗?
顺序又变了,不是吗?这有多酷?
但是我们现在确实有一个问题。集合是无序的。那么,如果我们不知道索引,我们如何访问元素呢?我们如何向集合中添加元素?我们如何在特定的位置插入元素?不幸的是,有些事情你不能用集合来做,任何与秩序相关的事情都属于集合。
所以,你不能用方括号来寻找一个特定位置的元素。但是,您可以使用“in”关键字来检查某个元素是否存在于集合中:
print('Red' in colors)
运行前面的代码,你会得到真。
你也可以遍历集合,就像你处理列表和元组一样。
for i in colors:
print(i)
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
Orange
Blue
Red
但是在不知道索引的情况下,如何向集合中添加元素呢?有一个 add()方法可以用来添加单个元素,尽管您不知道它们最终会出现在哪里。
colors.add('Green')
print(colors)
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
{'Blue', 'Green', 'Orange', 'Red'}
多有趣啊。我们在布景中加入了“绿色”,它最终出现在第二个位置。再次运行程序,你会在别的地方找到它。
如果我想向我的颜色集中添加多种颜色,该怎么办?我可以通过使用“update()”方法来节省空间。
在方括号内创建一个值列表,并将其放在括号内。让我尝试将“绿色”和“黄色”都添加到我的集合中:
colors.update(['Green','Yellow'])
print(colors)
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
{'Red', 'Yellow', 'Blue', 'Orange', 'Green'}
看看绿色和黄色的结局。😄
就像列表一样,您也可以使用 len()方法来查找列表的长度。
现在,让我们看看操纵集合的其他方法,好吗?我将只列出与我们在列表中看到的相似的那些。
在列表中,pop()方法移除一个随机值,而不是最后一个值。您可以使用 remove()方法通过将特定值作为参数来移除它。
或者,也可以使用“discard()”方法删除特定的元素。discard 和 remove 之间的唯一区别是,如果提到的元素不存在,discard 不会引发错误。这在现实编程中很重要。当运行一个程序时,你不希望因为一行代码出错而导致程序停止执行。
clear()方法清除集合,copy()方法复制列表。
您可以使用“del”关键字删除整个集合,但不能使用它来删除特定的元素,因为它们没有您可以访问的固定索引。
最后,我们来看看连接集。您可以使用“union()”或“update()”方法连接两个集合。
colors = {'Red', 'Orange', 'Blue'}
colors1 = {'Green', 'Yellow'}
假设我们有两个集合,colors 和 colors1 有各自的值,我们希望将它们合并到 colors 集合中。
您可以使用 union()方法。它用两个集合中的值创建一个新集合。
colors2 = colors.union(colors1)
print(colors2)
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
{'Yellow', 'Green', 'Red', 'Blue', 'Orange'}
但是 update 只是用两个集合中的值更新语法中的第一个集合。如果打印出语法中的第二组,您会注意到它没有变化。更新只是改变第一组。
colors.update(colors1)
print(colors)
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
{'Orange', 'Yellow', 'Red', 'Blue', 'Green'}
我们也完成了布景。耶!你现在已经成为相当专业的 Python 程序员了。
字典
这个列表中的最后一个数据结构是字典。让我们快速完成它,然后回去做一些更有趣的迷你项目,你同意吗?是啊!
所以,字典是无序的,但是它们是有索引的,并且可以改变。我喜欢字典的一点是,它们可以用来模拟现实世界的东西。你想看吗?
字典也是在花括号内创建的,但是在花括号内,您需要提到 key:value 对中的值。这里的“关键”是索引。
因为我想让我的字典模拟真实世界的对象,所以我将创建一个代表一个人的特征的字典:他们的姓名、年龄、眼睛颜色、头发颜色等等。
我是这样做的:
person1 = {"name":"Susan","age":9,"pet":"Barky","hair":"black","eyes":"blue"}
我已经创建了一本字典“person1”。她的名字叫苏珊,她 9 岁了,她的宠物叫巴克利,她有黑色的头发和蓝色的眼睛。看起来很棒,不是吗?
现在,让我们来操作这本字典。您可以像这样使用“键”来访问值:
print(person1["name"])
或者
print(person1.get("name"))
记住,你必须在任何地方都用引号括起来。
运行这两行代码中的任何一行,您都会得到相同的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
Susan
她的名字!
您也可以更改值。苏珊实际上是 8 岁,不是 9 岁!快,让我们在她伤心之前纠正她的年龄!
person1["age"] = 8
print(person1)
运行这个程序,您将得到以下结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
{'name': 'Susan', 'age': 8, 'pet': 'Barky', 'hair': 'black', 'eyes': 'blue'}
很好!
您也可以用同样的方式添加一个新的键:值对。让我们添加一个键,性别,并使其为女性。
person1["gender"] = 'female'
print(person1)
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
{'name': 'Susan', 'age': 9, 'pet': 'Barky', 'hair': 'black', 'eyes': 'blue', 'gender': 'female'}
这是添加的,耶!
您可以使用“in”关键字检查某个键是否存在。
print('pet' in person1)
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
True
是的,“宠物”是字典的关键词之一。
就像往常一样,你可以使用“len”方法找到字典的长度。
以下将删除字典:
del person1
person1.clear()
将字典清空。
您可以使用 copy()方法来复制字典。
像往常一样,您可以循环遍历字典,但是因为我们的字典有一个键和值,所以我们可以用不同的方式进行循环。
让我们先创建一个更小的字典:
person1 = {"name":"Susan","age":8}
让我们先遍历所有的键并打印出来:
for i in person1:
print(i)
这应该会打印出所有的键:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
name
age
没错。
如果你想要这些值,只要改变“我”的位置,就像这样:
for i in person1:
print(person1[i])
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
Susan
8
我们现在只得到值。喔!
或者,可以使用 items()方法循环访问键和值,如下所示:
for i,j in person1.items():
print("{} = {}".format(i,j))
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
name = Susan
age = 8
很好!
在结束之前,我们再看最后一件事。pop()删除给定的 key:value 对,而 popitem()删除字典中的最后一项。
person1.pop("name")
print(person1)
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
{'age': 8}
年龄是唯一剩下的关键!☹
让我们再次重写字典,这一次,尝试 popitem()。
person1.popitem()
print(person1)
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
{'name': 'Susan'}
现在,‘名字’是唯一剩下的关键!
字典到此为止!
迷你项目——永不落幕的色彩
又一个简单的项目!我们将在 1 秒钟后随机改变背景颜色,同时在海龟屏幕上打印当前颜色。
扭曲?我们将使用一个名为“时间”的新包来使海龟屏幕在每次颜色变化之间暂停。准备好了吗?我们走吧!
-
所以,就像我说的,我们需要“时间”和“海龟”模块。两个都导入吧。
import time import turtle
-
接下来,我们像往常一样设置 turtle。
s = turtle.getscreen() t = turtle.Turtle()
-
设置好之后,让我们将刚刚创建的笔移动到我们希望它书写颜色的位置。这就是重点——80,0。
t.penup() t.goto(-80,0) t.pendown()
-
现在,让我们创建一个颜色字典。这次我将创建一个字典而不是一个列表,因为我将使键的值(颜色)大写,这样我就可以把它们写在屏幕上。
colors = {'RED':'Red', 'BROWN':'Brown', 'GREEN':'Green', 'BLUE':'Blue', 'ORANGE':'Orange'}
-
在我们开始画画之前,让我们把乌龟藏起来。当你运行这个程序时,你就会明白为什么了。
t.hideturtle() turtle.hideturtle()
-
现在,有趣的部分来了。我们希望这个项目永无止境,记得吗?所以,很明显我们需要一个循环,但是什么样的循环呢?我们如何创建一个永无止境的循环?还记得我说过如果我们不小心的话,“while”循环可以永远运行下去吗?也就是说,如果条件没有在某一点变为假。
如果我们真的这么做了呢?如果我们让 while 循环的条件为“真”,那会怎么样?然后,如果在 while 循环中没有 break 语句,那么它将永远运行下去。
- 简单!接下来,让我们创建一个 for 循环来遍历“颜色”字典。
#never ending loop
while True:
-
对于每次迭代,让我们将海龟屏幕的背景色改为 For 循环中的下一种颜色(值)。另外,让我们用 Arial 字体,50 磅,粗体字来写键值(x)。
turtle.bgcolor(colors[x]) t.write(x,font=('Arial',50,'bold'))
-
现在,在每次颜色变化之后,在下一次颜色变化(用于循环迭代)发生之前,我们需要 0.5 秒的延迟或间隙。这就是“时间”包的用武之地。它有一个名为 sleep()的内置函数,这个函数会在提到的秒数内暂停循环。在我们的例子中,它是 0.5。
for x in colors:
- 好的,从技术上来说应该是这样,但是如果我们不去管它,那么你会注意到你的海龟在旧文本上写下一个文本,事情会继续变得混乱。你为什么不试试看?
time.sleep(0.5)
你的 turtle 包自带了一个 clear()函数,可以清空屏幕。那么,我们为什么不在改变下一种颜色和绘制下一个文本之前清空屏幕呢?
t.clear()
就这样!让我们现在运行这个,我们会得到这个(图 11-3 )。
图 11-3
永不落幕的颜色
你会注意到程序在“颜色”字典中无限循环。很甜蜜,是吧?
迷你项目-姓氏和名字颠倒
在这个项目中,这是我想要发生的:当我输入一个名字,例如,Susan Smith,我希望我的程序返回它的反转,即,Smith,Susan。
这与其说是一个迷你项目,不如说是一个难题。逻辑很简单:
-
让我们通过获取名称作为输入来启动程序。条件是他们的名和姓需要用一个空格隔开。这很重要。你会明白为什么。
name = input('Please Enter your first and last name, separated by a space: ')
-
正如我所说的,字符串输入的格式对于程序的运行非常重要。所以,我要计算字符串中单个空格的个数。如果没有,或者不止一个,那么程序会停止并显示一条错误消息。
让我们先创建一个变量 count,并将其赋值为 0。
-
接下来,让我们创建一个 for 循环,遍历刚刚得到的字符串。只要有一个空格,我们就加 1 来计数。
for i in name: if i == ' ': count += 1
-
如果计数只有 1,那么我们就可以开始了。让我们使用 split 方法将字符串转换成列表,其中名字和姓氏被分隔成单独的列表项,使用单个空格作为分隔符。
if count == 1: #Convert string to list, where the condition is the space l = name.split(' ')
-
接下来,我们来倒排一下。
#Reverse list l.reverse()
-
最后,让我们在列表的第一个位置插入一个带空格的逗号,这样当我们连接所有内容时,我们就得到我们想要的确切格式。
#Add a comma, with a space, in the first position of the list l.insert(1,', ')
-
现在让我们用一个空字符串作为连接条件将列表连接成一个字符串。这样,所有的东西都粘在一起,唯一分隔姓和名的是“,”。
#Join a list into a string name = ''.join(l)
-
最后,打印所有内容。
count = 0
-
如果计数不是 1,则打印一条错误消息。
else: print('Please Enter your name in the correct format')
print('Your reversed name is: {}'.format(name))
现在,让我们运行程序!
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
Please Enter your first and last name, separated by a space: Susan Smith
Your reversed name is: Smith, Susan
完美!
摘要
在本章中,我们深入探讨了 Python 提供的四种预定义数据结构,即列表、集合、元组和字典。我们研究了如何创建、删除、操作它们,等等。最后,我们看了如何在程序中使用它们,以及为什么它们在真实的编程场景中有用。
在下一章中,让我们暂时放下所有的学习,开始创作吧!我们将创建许多迷你项目。
十二、有趣且丰富的迷你项目!
在前一章中,我们深入探讨了 Python 提供的四种预定义数据结构,即列表、集合、元组和字典。我们研究了如何创建、删除、操作它们,等等。最后,我们看了如何在程序中使用它们,以及为什么它们在真实的编程场景中有用。
在这一章中,让我们暂时放下所有的学习,开始创作吧!我们将创建许多迷你项目。你可以通过创建这些迷你项目来温习到目前为止所学的主题。所以,跟我一起编码吧。玩得开心!
专题 12-1:奇数还是偶数
让我们从简单的事情开始这一章。这是任何编程语言中的经典难题。
我们将分两部分完成这个项目。在第一部分中,我们将检查一个给定的数是偶数还是奇数。在第二部分中,我们将从用户那里获得一个数字范围,并打印该范围内的偶数或奇数。
但是在我们开始之前,让我问你一个问题。我们如何决定一个数是奇数还是偶数?嗯,任何被 2 除尽的数都是偶数,对吗?除以 2 得出 1 的数是奇数。
这个概念很简单。您还记得模数运算符吗?它返回除法运算的余数。
当你把一个偶数除以 2 时,你会得到什么?0
当你把一个奇数除以 2 时,你会得到什么?一
就这样!所以,如果这个数和 2 的模返回 0,我们就得到一个偶数。如果没有,我们得到一个奇数。
现在,我们可以创建我们的程序了吗?
第一部分-你的号码是奇数还是偶数?
-
获取输入并将其转换为整数。
-
然后,检查模量。如果是 0,就是偶数;否则就是奇数。
num = input('Enter a number: ')
num = int(num)
- 让我们运行程序。我的输入是 45。
if((num % 2) == 0):
print('{} is an Even number'.format(num))
else:
print('{} is an Odd number'.format(num))
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
Enter a number: 45
45 is an Odd number
第二部分-打印一个范围内的奇数或偶数
现在,对于第二个程序,让我们从用户那里获得一个范围,以及他们是否希望在该范围内打印偶数或奇数,并打印相同的数字。
-
获取范围并将它们转换为整数。也获得了“选择权”。
start = input('Enter the start of the range: ') end = input('Enter the end of the range: ') start = int(start) end = int(end) choice = input('Even or Odd? Enter e or o: ')
-
在我们循环遍历这个范围之前,让我们检查一下它是否正确。“开始”值应该小于“结束”值。
-
如果是,让我们创建一个遍历整个范围的 for 循环。如果选择为奇数,则仅在模数的结果为 1 时打印。如果选择偶数,则仅当模数的结果为 0 时打印。如果两者都不是,他们给出了一个无效的选择,并打印一条错误消息。
for i in range(start,end+1): if(choice == 'o' or choice == 'O'): if((i % 2) == 1): print(i) elif(choice == 'e' or choice == 'E'): if((i % 2) == 0): print(i) else: print('Enter a valid choice and try again')
-
最后,也为该范围打印一条错误消息。
else: print('Enter a valid range')
-
让我们运行这个程序。我的范围是 1 到 10,我想打印这个范围内的奇数。
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py Enter the start of the range: 1 Enter the end of the range: 10 Even or Odd? Enter e or o: O 1 3 5 7 9
if(start < end):
太好了。
项目 12-2:你妈妈给的小费够吗?
在这个项目中,我们将创建一个小费计算器,输入总账单和他们的妈妈给服务员的小费。计算他们的妈妈给的小费的百分比,如果是 10-15%就说好,如果是 15-20%就说好,如果是 20%以上就说好。如果少于 10%,就说他们的妈妈给的小费不够。
让我们创造它,好吗?
-
获取账单金额和小费,并将它们转换为整数。
bill = input('What was your bill? ') tip = input('How much did you tip? ') bill = int(bill) tip = int(tip)
-
让我们计算一下小费的百分比。为此,将小费乘以 100,然后除以账单金额。这只是你计算百分比的反向操作。让我们将百分比(由于除法运算,它将是一个浮点数)转换为整数。
percent = (tip * 100) / bill percent = int(percent)
-
现在,让我们使用 if elif else 打印出正确的消息。简单!
if((percent >= 10) and (percent <= 15)): print('{}%. You tipped Okay'.format(percent)) elif((percent >= 15) and (percent <= 20)): print('{}%. That was a good tip!'.format(percent)) elif(percent >= 20): print('{}%. Wow, great tip! :)'.format(percent)) else: print("{}%. You didn't tip enough :(".format(percent))
运行这个程序,你会得到这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\dataStructures.py
What was your bill? 400
How much did you tip? 45
11%. You tipped Okay
作品!
项目 12-3:画一棵圣诞树
你知道你可以用基本的 Python 语法画一棵圣诞树吗?没有包或模块,只有 Python。我们试试好吗?
所以基本上,给定树的高度,我想让我的程序画一棵这个高度的树。很简单,对吧?
正如你可能猜到的,我们需要循环来做这件事,树看起来就像图 12-1 。
图 12-1
5 米高的圣诞树
这个程序是如何工作的?
因此,我们需要一个循环遍历树的每一行,另一个循环遍历树的高度。这称为嵌套循环。在这个嵌套循环中,遍历树的高度的循环是外部循环,对于外部循环的每次迭代,我们将使用内部循环来绘制相关的行。
我们开始吧!
每当我们试图画谜题或任何类型的问题时,最好是写一个算法来帮助我们更好地编写程序。在这种情况下,我将使用前面的树来逆向工程我的算法。你想看看怎么样吗?
算法:
-
在图 12-1 中,树的高度为 5。所以,我们需要五排叶子和一个树桩在末端(在树的中间)。
-
第一行有 1 颗星,第二行有 1 + 2 (3)颗星,第三行有 3 + 2 (5)颗星,依此类推,直到最后。
-
如果你在画出第一颗星星(第一行)之前数空格数,是四,也就是树的高度减一。对于第二行,空格数为 3,随后每减少一行。
-
树桩又是四格之后画的,所以和我们第一排一样。我们需要一个单独的 for 循环来绘制树桩,因为它不是树的给定高度的一部分。
好了,现在我们已经有了一个算法,让我们开始吧!
让我们创建我们的程序吧!
-
让我们先获得树的高度,然后将字符串转换为整数。
n = input("What's the height of your tree? ") n = int(n)
-
接下来,让我们分配变量。我将创建一个变量 sp,它将表示空格的数量。它将从 n-1 开始。我可以减少循环内部的值。
同样,我将创建另一个变星,从 1 开始。
-
现在,让我们画我们的树吧!主 for 循环将遍历树的整个高度(0 到 n–1,所以范围是 0,n)
#draw the tree for i in range(0,n):
-
在主外部 for 循环中,我们需要两个内部 for 循环,一个用来画空格,一个用来画星星。
We need to loop from 0 to sp, and for every iteration of the loop, print a single space. But here’s the catch. Print statements end at new lines, so if you want to be on the same line, you need to use an attribute called end and give it an empty string as its value. This will make sure that the next space is drawn right next to the first space.
#draw spaces for j in range(0,sp): #By default, a print function ends with a newline. Use the end='' to make it end with an empty string instead, so we can draw the star next print(' ',end='')
-
现在,让我们画出我们的星星。为此,我们需要遍历范围 0,star–1。再次使用 end= ' '以确保它们绘制在同一条线上。
for k in range(0,star): print('*',end='')
-
我们现在已经完成了内部 for 循环。在开始外部 for 循环的下一次迭代之前(我们的树的下一行),让我们更改变量的值。让我们将 star 增加 2,将 sp 减少 1。让我们将一个空的 print()放在最后,因为我们已经完成了这一行,下一行需要一个新的行。
star += 2 sp -= 1 print() #so there's a new line
-
那棵树就这样了!现在,关于树桩。做你在第一排做的。从 0 到 n–2(范围 0,n–1)运行一个 for 循环,并打印一个 end= ' '的空格。一旦循环完成,打印一个星星,我们就完成了!
#draw the stump for i in range(0,n-1): print(' ',end='') print('*')
sp = n-1
star = 1
喔!这花了一些时间。我们运行这个程序好吗?
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/mini_projects.py
What's the height of your tree? 10
按回车键,你会得到这个(图 12-2 )。
图 12-2
10 米高的圣诞树
耶!有效!
项目 12-4:螺旋!
在这个项目中,我们将制作不同种类的随机彩色螺旋。会很有趣的!
方形螺旋
-
首先,让我们创建一个方形螺旋。因为我们需要随机选择颜色,我们需要导入 turtle 和 random 模块。
#Square spiral import turtle, random
-
让我们先设置乌龟屏幕,并将笔的大小设置为 5,速度设置为 0。
s = turtle.getscreen() t = turtle.Turtle() t.pensize(5) t.speed(0)
-
因为这将是一个方形螺旋,我将长度设为 4。你会明白为什么。
-
让我们也创建一个颜色列表,我们将在我们的循环中随机选择。
colors = ['Red', 'Brown', 'Green', 'Blue', 'Orange', 'Yellow', 'Magenta', 'Violet', 'Pink']
-
现在,让我们创建我们的循环,并使它从 1 到 149(因此范围为 1–150)。经过反复试验,我选择了这个数字。然后,我将使用 random.choice 方法,该方法从列表中随机选择项目,并将选择的项目赋给变量“color”。
for x in range(1,150): color = random.choice(colors)
-
将钢笔颜色更改为该颜色,并使钢笔向前移动“长度”并向右移动 90 度。然后,将长度的当前值加上 4,这样在下一次迭代中,笔将向前移动 4 个点。这不断重复,因此,我们已经创建了一个螺旋,它的大小不断增加(因为长度值的增加,也因为我们在每条线被画出后都旋转了 90 度)。
t.pencolor(color) t.forward(length) t.right(90) length += 4
-
最后,把乌龟藏起来。
t.hideturtle() turtle.hideturtle()
length = 4
运行前面的代码,你会得到这个(图 12-3 )。
图 12-3
方形螺旋
改变范围和长度的初始值(和增量),你会得到不同大小的方形螺旋。试试看!
随机螺旋
既然我们意识到螺旋的形状取决于长度和角度,那么如果我们把角度换成其他角度,比如 80 度,会发生什么呢?当然,我们将创建一个随机形状的螺旋!
这几乎像一个五边形,但不完全像,因为五边形的外角是 72 °,这里我们给了 80°。只是为了表明你可以让你的想象力天马行空,得到令人敬畏的结果!
#Spiral pentagon
import turtle, random
s = turtle.getscreen()
t = turtle.Turtle()
t.pensize(5)
t.speed(0)
length = 4
colors = ['Red', 'Brown', 'Green', 'Blue', 'Orange', 'Yellow', 'Magenta', 'Violet', 'Pink']
for x in range(1,200):
color = random.choice(colors)
t.pencolor(color)
t.forward(length)
t.right(80)
length += 2
t.hideturtle()
turtle.hideturtle()
运行前面的代码,你会得到这个(图 12-4 )。
图 12-4
随机螺旋
三角形螺旋
因为三角形的外角是 120 度,将角度改为 120 度,你就得到一个三角形螺旋!
#Triangular spiral
import turtle, random
s = turtle.getscreen()
t = turtle.Turtle()
t.pensize(5)
t.speed(0)
length = 4
colors = ['Red', 'Brown', 'Green', 'Blue', 'Orange', 'Yellow', 'Magenta', 'Violet', 'Pink']
for x in range(1,120):
color = random.choice(colors)
t.pencolor(color)
t.forward(length)
t.right(-120) #-120 so we get a triangle facing upward
length += 4
t.hideturtle()
turtle.hideturtle()
运行前面的代码,你会得到这个(图 12-5 )。
图 12-5
三角形螺旋
星形螺旋
因为星星的外角是 144 度,给你的角度 144 度,你就得到一个星形螺旋!
#Star spiral
import turtle, random
s = turtle.getscreen()
t = turtle.Turtle()
t.pensize(5)
t.speed(0)
length = 4
colors = ['Red', 'Brown', 'Green', 'Blue', 'Orange', 'Yellow', 'Magenta', 'Violet', 'Pink']
for x in range(1,130):
color = random.choice(colors)
t.pencolor(color)
t.forward(length)
t.right(144)
length += 4
t.hideturtle()
turtle.hideturtle()
运行前面的代码,你会得到这个(图 12-6 )。
图 12-6
星形螺旋
圆形螺旋
圆形螺旋会和其他的有点不同。我们的长度仍然是 4,但是我们一次只向前移动一点,得到一个圆形,在这种情况下我把角度设为 20。您可以改变角度,使您的螺旋紧密结合,并进一步分开。
#Circular spiral
import turtle, random
s = turtle.getscreen()
t = turtle.Turtle()
t.pensize(5)
t.speed(0)
length = 4
colors = ['Red', 'Brown', 'Green', 'Blue']
for x in range(1,100):
color = random.choice(colors)
t.pencolor(color)
t.forward(length)
t.right(20)
length += 1
t.hideturtle()
turtle.hideturtle()
运行前面的代码,你会得到这个(图 12-7 )。
图 12-7
圆形螺旋
项目 12-5:复杂的曼荼罗——完全自动化
在这个项目中,让我们用 for 循环画一个复杂的曼荼罗。这也是随机着色的。看起来会很壮观!
-
先导入随机和海龟模块,设置好海龟屏和笔。接下来,让我们改变笔的大小为 5,速度为 0。
#Mandala import turtle, random s = turtle.getscreen() t = turtle.Turtle() t.pensize(5) t.speed(0)
-
接下来让我们创建一个颜色列表。
-
然后,我们将使我们的循环遍历 1 到 24 (1,25 作为范围)。
colors = ['Red', 'Blue', 'Green']
-
让我们选择我们的随机颜色,并改变笔的颜色。
color = random.choice(colors) t.pencolor(color)
-
现在有趣的部分来了。曼荼罗通常是复杂地画圆,我对吗?所以,让我们为每次迭代画一个 100 点的圆,但是每次稍微移动角度 15 度,所以我们得到一个紧密编织的曼荼罗设计(你会看到)。
t.circle(100) t.right(15) #closely formed mandala
-
最后,把乌龟藏起来。
t.hideturtle() turtle.hideturtle()
for x in range(1,25):
运行前面的代码,你会得到这个(图 12-8 )。
图 12-8
复杂曼陀罗
尝试改变循环的范围,圆的半径,和角度来得到不同类型的曼荼罗。你可以创造数百个这样的设计!
项目 12-6: 乌龟 带圈赛跑
这将是一个有趣的小游戏,展示了 for 循环和 Python 随机包的强大威力。我们还将学习一些我们在turtle
章节中跳过的turtle
方法。兴奋吗?我也是!
所以,概念很简单。我们有三只海龟,我们将在它们之间进行一场比赛。差不多了。当我们完成后,它将看起来像一个实际的,现场比赛发生在我们的屏幕上。我们如何做到这一点?
首先,我们需要我们的玩家,幸运的是, Turtle 让创造“海龟”变得很容易。
-
让我们先导入 turtle 和随机包并设置我们的屏幕。
#Turtles import turtle, random s = turtle.getscreen()
-
现在,对我们的海龟来说,我们不会用通常的方法。我们要用这只乌龟创造三只独立的乌龟。Turtle()命令,命名为红色、蓝色和绿色。乌龟让我们这么做。我们可以随心所欲地创造出任意多的乌龟,并把它们放在我们想要的任何地方,同时让它们画出不同的东西。很酷,你不觉得吗?
-
一旦我们创建了一个玩家(乌龟),我们将改变它的笔的大小为 5,用 color()方法改变“乌龟”的颜色,用 shape()方法改变乌龟的形状为“乌龟”。你马上就会看到这些是如何工作的。
red = turtle.Turtle() red.pensize(5) red.color('Red') red.shape('turtle') blue = turtle.Turtle() blue.pensize(5) blue.color('Blue') blue.shape('turtle') green = turtle.Turtle() green.pensize(5) green.color('Green') green.shape('turtle')
-
最后,让我们隐藏屏幕中央的主海龟。
图 12-9
海龟就位
-
现在,如果你运行这个程序,你不会看到太多。你只能看到绿海龟,因为那是最后画的。要分开看海龟,让我们把它们移到比赛位置。在尝试了很多值之后,我选择了任意值。你可以选择任何你想要的起点。
#Make turtles move to position red.penup() red.goto(-250,150) red.pendown() blue.penup() blue.goto(-250,0) blue.pendown() green.penup() green.goto(-250,-150) green.pendown()
-
现在,让我们运行程序,我们会得到这个(图 12-9 )。
turtle.hideturtle() #hide the main turtle at the center
我们有三个海龟队员,他们已经就位。完美!
-
最后,让我们让他们比赛!创建一个运行 100 次迭代的 for 循环。在每次迭代中,让每只乌龟向前移动一个从 1 到 10 的随机数。这样,我们不知道任何一只海龟会移动多远,这有一种真实世界的比赛感觉。
#Make the turtles move for i in range(100): red.forward(random.randint(1,10)) blue.forward(random.randint(1,10)) green.forward(random.randint(1,10))
差不多就是这样。如果你现在运行程序,你会看到三条不同颜色的线在屏幕上以不同的速度移动,停在不同的点上。这就是了。你的种族(图 12-10 )!
图 12-10
乌龟赛跑
这就是我们的迷你项目!希望你在创造它们的时候很开心。
摘要
在这一章中,我们看了六个不同的有趣的迷你项目。在创建丰富多彩的迷你项目时,我们重温了在前面章节中学到的概念。我们还学习了创建算法来解决编程中的问题和难题。
在下一章,让我们学习如何用函数实现真正的自动化,如何为我们的用户定义函数获取参数,如何用函数节省时间和大量代码行,等等。
十三、功能自动化
在前一章中,我们暂停了所有的学习并创建了更多有趣的迷你项目。现在我们精力充沛了,让我们继续学习几个章节,好吗?
在这一章中,我们将会看到一个非常有趣的概念。我们已经介绍了 Python 中使用循环的自动化,但是在这一章,让我们看看真正的函数自动化。它像魔法一样有效。你会明白的。
真正的自动化
为什么我这么叫它?我们已经看到了循环,它们自己完成了大量的自动化工作。我们只用了几行代码就创建了完整的形状,对吗?那么,我们为什么需要函数呢?
如果你需要重复密码呢?例如,让我们带回我们在循环章节中写的代码。还记得我们如何创建一个程序,它根据我们给它的输入创建一个形状吗?我们不得不多次运行这个程序来绘制不同的形状。如果我想从程序的同一次运行中绘制不同的形状呢?如果我想给出多个输入,那么我的程序一个接一个地绘制每个形状,同时擦除前一个形状,该怎么办?你会怎么做?
你可能需要多次编写相同的代码,用不同的角度和边输入,对吗?所以,如果你想画五个形状,你需要五个循环,一个接一个,每个循环之间有一个 clear()方法。那太长了!如果我们也能缩短它呢?
有了函数,你当然可以!你可以用一个叫做“函数”的东西来创建你的“for 循环”。到目前为止,我们已经使用了很多函数。只是,我们称它们为预定义方法,因为它们已经用 Python 创建了。但是现在,您可以创建自己的函数。多令人兴奋啊。你已经成为一个如此有经验的程序员,你现在可以创建你自己的函数,调用它们,发送参数,自动化,等等。
既然你的“for 循环”在你的函数中,你可以做一些叫做“调用函数”的事情,每次给不同的值,以确保你的 for 循环每次都画出不同的形状。一会儿我会教你怎么做。
但是现在,让我们学习如何编写一个基本函数。
我们的第一个功能
每个函数都有两个部分。有一个函数定义,它有你想要多次执行的代码。然后是函数调用,这是字面上“调用”函数定义的代码行。它可能会发送参数/值作为函数的输入。
但是首先,让我们创建一个没有参数的函数,这样你就能理解它们是如何工作的。
所以,函数是有定义的,不是吗?到目前为止,我们已经注意到 Python 非常直观。它的语法很有意义。“if”是指英文单词 If;而“while”的意思是某事将持续一段时间,因此是一个循环;等等。类似地,“def”意味着你正在创建一个函数定义。
像往常一样,只需提到“def”,即您正在创建的函数的名称,后跟括号和冒号。然后,在下一行中,在缩进后添加代码行。就这么简单!
让我们创建一个打印“Hello there!”的函数当我们称之为。我们命名我们的函数,这样我们可以在以后调用它们。我们已经调用了许多预定义的函数,比如 len()和 join(),对吗?对于您创建的函数,这个概念是相同的:用户定义的函数。我将把我的函数命名为 greet(),因为这就是它要做的,问候调用它的人。
def greet():
print('Hello there!')
太好了。我们有我们的功能。让我们运行它。
蟋蟀…什么也没发生。☹为什么?!
啊对了,我们还没叫呢!我们如何做到这一点?那么,我们如何调用我们的预定义函数呢?格式是一样的。函数名,后跟括号。就这样!
让我们现在正确地做事情。一个函数定义,然后是一个函数调用,就像它应该的那样。
def greet():
print('Hello there!')
greet()
现在运行这个程序,你会得到这个:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/functions.py
Hello there!
啊哈!我们拿到了。
为什么我们需要函数?
但是函数有什么用呢?我很困惑。是吗?它做我们一直在做的事情,而不需要添加额外的代码来创建和调用函数。
嗯…如果我想问候我的用户五次而不是一次呢?也许小组有五个人?在此之前,我会添加五个打印声明。但是现在,我可以添加五个函数调用,就像这样,函数会被调用,然后“你好!”每次都会被打印出来。酷!
greet()
greet()
greet()
greet()
greet()
运行前面的代码,您将得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/functions.py
Hello there!
Hello there!
Hello there!
Hello there!
Hello there!
我们拿到了。或者我们有吗?这也有什么用?我们仍然创建了五行代码。无论如何我们都会这么做的。我们既没有节省时间,也没有节省空间。倒霉!
每次做不同的事情!
当你每次调用函数时都给它发送不同的值,你就会明白函数的真正用途了。让我们修改一下 greet()程序,让它在每次调用时都问候一个人。
现在我想让函数每次都用他们的名字问候这个人,我需要让我的函数知道他们的名字是什么,对吗?我该怎么做?也许我的函数可以在被调用的时候接收到它?没错。创建函数时,可以在括号内包含发送的一个或多个参数的名称(可以发送任意数量的参数)。
好了,暂停!参数?争论?哪个是哪个?别担心。其实都是一样的,但是如果你想具体一点,你从函数调用中发出的值叫做参数,你在函数定义中收到的值就是实参。简单吧?一旦我们看了我们的例子,你会更好地理解。
创建(定义)您的功能
让我们看看它是如何工作的:
def greet(name):
print('Hello {}!'.format(name))
看那个!我在括号中收到了参数“name ”,然后在我的 print 语句中使用了它。本质上,这不是一个变量,但它的行为很像变量。您可以随意命名您的参数。一旦我们完成了这个例子,你为什么不把你的参数的名字从" name "改成" n ",看看它是否还能工作?
现在我们已经创建了我们的定义,让我们创建程序的其余部分。让我们创建一个变量名并获得输入。然后,让我们调用 greet()函数,但是这一次使用括号内的参数名称“name”。
name = input("What's your name?")
greet(name)
很好!不要被同一个“名字”迷惑了。我只是让变量的名字和函数接收的参数的名字相同,这样你就不会混淆了。但是参数名称可以是您想要的任何名称,并且您的程序仍然可以正常工作。
运行前面的代码,您将得到以下结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\functions.py
What's your name? Susan
Hello Susan!
看那个!有效!
你可以重用你的代码!
现在,我将向你展示函数的真正用途。函数的真正用途在于,你不需要一遍又一遍地重复同样的代码行。
因此,让我们创建一个名为“calculation”的函数来计算它接收到的任意两个数的加、减、除和乘。好吗?
因此,它将接收两个数字,n1 和 n2,作为参数。我将进行计算,并将结果打印成四行:
def calculate(n1,n2):
n1 = int(n1)
n2 = int(n2)
add = n1 + n2
sub = n1 - n2
div = n1 / n2
mul = n1 * n2
print('''Addition: {}
Subtraction: {}
Multiplication: {}
Division: {}
'''. format(add,sub,mul,div))
在前面的代码行中,我接收了两个数字作为参数 n1 和 n2。然后我将它们转换成整数,因为我将使用“input()”方法接收数字,默认情况下这些值是字符串。然后,我完成了计算,最后使用多行字符串引号将所有内容打印出来。
现在到了我正在谈论的部分。既然我们已经创建了 calculate 函数,我们可以随时调用它。如果我们想要计算三次呢?在我们发现函数之前,我们会多次编写相同的代码行,因为没有其他方法来接收不同的输入并用不同的值进行相同的计算。
但是现在,我们有办法了!
calculate(input("Enter the first number"),input("Enter the second number"))
calculate(input("Enter the first number"),input("Enter the second number"))
calculate(input("Enter the first number"),input("Enter the second number"))
我已经创建了三个函数调用,其中每个函数调用都有两个参数,它们只不过是输入语句。
让我们运行这些:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\functions.py
Enter the first number 10
Enter the second number 5
Addition: 15
Subtraction: 5
Multiplication: 50
Division: 2.0
Enter the first number 5
Enter the second number 10
Addition: 15
Subtraction: -5
Multiplication: 50
Division: 0.5
Enter the first number 100
Enter the second number 20
Addition: 120
Subtraction: 80
Multiplication: 2000
Division: 5.0
看那个!用同样的几行代码,我能够做三组不同的计算,而不用像我们通常做的那样运行程序三次。
这是函数的真正用法。 真正的自动化!
没有争论?
但是在函数调用中发送参数时要小心。如果您没有发送函数定义所期望的参数数量,那么在运行函数时您将会遇到一个错误。如果您发送的参数数量较少或较多,情况也是如此。
def greet(name):
print('Hello {}!'.format(name))
对于上述功能:
greet()
不带参数的调用将产生以下错误:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\functions.py
Traceback (most recent call last):
File "C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\functions.py", line 3, in <module>
greet()
TypeError: greet() missing 1 required positional argument: 'name'
函数调用缺少一个必需的参数。
另一方面一个叫两个论点:
greet(name1,name2)
您将收到以下错误:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\functions.py
Traceback (most recent call last):
File "C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\functions.py", line 3, in <module>
greet(name1,name2)
NameError: name 'name1' is not defined
参数未定义!因此,一定要确保实参的数量与函数定义中的形参数量相匹配。
给个答案
到目前为止,我们只是把东西打印出来。但是如果我们需要一个答案呢?假设我有一个表达式,我使用 add()和 mul()函数来获得数字的加法和乘法结果。但是然后,我想,比如说,把他们都分了。在不知道手术结果的情况下,我怎么能这么做呢?打印结果并不总是足够的,不是吗?
Python 对此也有一个简单的解决方案!只需返回结果。就这么简单。使用“return”语句,返回您的结果,它将在您的函数调用中被接收。然后,您可以将函数调用赋给一个变量并使用其结果,或者将函数调用本身作为一个值使用。
迷茫?别这样,亲爱的。另一个有趣的活动正在进行中,它会让你理解这个概念。
让我首先创建两个函数,加法()和乘法()。它们分别接收参数 n1 和 n2,并执行这两个数的加法和乘法。
def addition(n1,n2):
add = n1 + n2
def multiply(n1,n2):
mul = n1 * n2
但是我不能用这些值,对吗?所以,让我把它们还回去。
def addition(n1,n2):
add = n1 + n2
return add
def multiply(n1,n2):
mul = n1 * n2
return mul
现在,我已经返回了数字相加和相乘的结果。或者,您可以只在 return 语句中执行操作,如下所示:
def addition(n1,n2):
return n1 + n2
def multiply(n1,n2):
return n1 * n2
如果你这样做的话,你可以节省几行代码。只有当你的整个函数只有一行代码时,这才会起作用。
好了,现在我们已经准备好了函数,让我们使用它们吧!
num1 = input("Enter your first number: ")
num1 = int(num1)
num2 = input("Enter your second number: ")
num2 = int(num2)
mul = multiply(num1,num2)
add = addition(num1,num2)
calc = mul /add
print("{} / {} = {}".format(mul,add,calc))
在前面的代码行中,我接收了两个数字作为输入,并将字符串转换为整数。然后,我创建了一个名为“calc”的变量,它将这些数字相乘的结果除以这些数字相加的结果。
我没有在那里执行操作,而是接收了变量 mul 和 add 中的值。从技术上讲,这就是我们所需要的,因为这些函数中的 return 语句会将操作的结果返回给函数调用,然后它们就可以在“calc”操作中使用了。
我们要不要检查一下这个是否能用?
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\functions.py
Enter your first number: 10
Enter your second number: 5
50 / 15 = 3.3333333333333335
没错。有效!为什么不同的操作不尝试相同的呢?想怎么复杂就怎么复杂,享受数学乐趣!
没有争论?怎么办!
有时,您可能不知道要发送什么参数。也许你只是想测试一下功能?但是当函数需要参数时不发送参数会给我们一个错误!我们能做什么?
救援的默认参数!
在定义函数时,您可以为参数指定“默认值”,这样,即使您在调用函数时忘记发送任何参数,它们也能正常工作。你想测试一下吗?
在下面的例子中,我创建了一个 printName 函数,它只打印给定的名字。我调用了这个函数两次,一次有参数,一次没有。让我们看看会发生什么。
def printName(name='Susan'):
print('My name is {}'.format(name))
printName('John')
printName()
Run, and:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\condition.py
My name is John
My name is Susan
它完全按照我们的预期工作。当我们实际从函数调用中发送参数时,默认参数被忽略。如果我们忘记了,它就被使用了。完美!
争论太多了!
函数还没有停止让您的编程生活变得简单。如果你不知道要发送多少个参数呢?但是你想收到所有的,没有任何错误。
武断的论点会帮助你做到这一点。用*listName 而不是参数名来接收它们,这样就可以像访问列表项一样访问每个参数。让我告诉你怎么做。
假设我想打印我的函数调用发送的数字的总和,但是我不知道我需要增加多少,所以我只是把它们作为一个任意的参数接收。
因为*listName 本质上是一个列表,所以我们可以像在列表中一样循环遍历它。
def addNums(*nums):
sum = 0
for num in nums:
sum += num
return sum
现在让我用我的任意参数调用我的函数。
print(addNums(1,5,3,7,5,8,3))
print(addNums(1,3,5,7,9))
print(addNums(1,2,3,4,5,6,7,8,9))
当我运行这个程序时,我得到了这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\condition.py
32
25
45
哇,这个特性给了我在程序中做任何我想做的事情如此多的自由!
另一方面,你可以发送一个列表作为参数。那也可以。为什么不试着修改前面的程序来发送和接收一列数字呢?
你试过吗?它看起来像这样吗?
def addNums(nums):
sum = 0
for num in nums:
sum += num
return sum
print(addNums([1,5,3,7,5,8,3]))
print(addNums([1,3,5,7,9]))
print(addNums([1,2,3,4,5,6,7,8,9]))
太好了。
全球与本地
到目前为止,我们已经看到,一旦你创建了一个变量,你不能重新定义它。你可以重新给它赋值,是的,例如:
for i in range(1,10):
print(i,end='')
print()
print(i)
看看前面的程序。我创建了一个变量“I ”,它在同一行中打印从 1 到 9 的数字。在 for 循环完成后,我们打印一个新行和“I”的当前值。
让我们运行这个程序,我们会得到这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\condition.py
123456789
9
看那个!它是 9,这不是一个错误,因为一旦创建了" I ",即使它是在 for 循环中创建的,它也可以被整个程序访问。
函数中的变量
但是函数就不是这样了。现在让我们在函数中创建相同的内容:
def printNum():
for i in range(1,10):
print(i,end='')
printNum()
print()
print(i)
Run the above, and:
>>>
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\condition.py
123456789
Traceback (most recent call last):
File "C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\condition.py", line 7, in <module>
print(i)
NameError: name 'i' is not defined
看看前面的输出。当函数仍在执行时,一切都很好。它按照我们想要的顺序打印出我们的号码。但是,当我们试图在函数外部打印“I”的当前值时,我们得到一个“未定义”的错误。这怎么可能呢?变量“I”是在函数的 for 循环中定义的,不是吗?
是的,它是,但是它是本地的那个功能,不能在外面使用。因此,在函数内部创建的任何变量都称为局部变量。
**### 返回局部变量
如果你想在函数之外使用它,你需要返回它,就像这样:
def printNum():
for i in range(1,10):
print(i,end='')
return i
i = printNum()
print()
print(i)
现在,运行这个程序,你会得到这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\condition.py
123456789
9
有效!
全局变量
同样,任何在函数外部创建的变量都被称为 全局 变量,如果你想在函数内部使用它,你需要使用全局关键字,就像这样:
假设我想创建一个全局变量“sum”。每次我发送一个数字列表时,它们都会被添加到 sum 的“当前”值中,所以我们实际上得到的是多个列表的总和。我们如何做到这一点?
我已经创建了一个变量“sum ”,并在程序开始时将其赋值为 0。接下来,让我定义函数。如果我想在函数外部使用相同的“sum”,那么我需要在函数开始时将其称为“全局 sum”(不带引号)。在函数定义的顶部提到全局变量总是一个好习惯。
就这样。程序的其余部分和我们之前写的类似。
sum = 0
def addNums(nums):
global sum
for num in nums:
sum += num
return sum
print(addNums([1,5,3,7,5,8,3]))
print(addNums([1,3,5,7,9]))
print(addNums([1,2,3,4,5,6,7,8,9]))
运行这段代码,您将得到以下结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\condition.py
32
57
102
sum 的旧值被保留下来,并被添加到后续函数调用中发送的新值中。太好了。
Note
创建顺序和用法 在 Python 中非常重要。在你调用一个函数之前,先定义它。所以, 函数定义 应该总是在函数调用之上,否则会出错。同样,在使用变量之前,先创建它。因此,您的 全局变量 应该在您希望使用它们的函数定义之前创建。
希腊字母的第 11 个
λ是一个匿名函数。它没有名字,可以接受任意数量的参数,但只能有一行代码。听起来很简单,不是吗?当我们有自己的荣耀功能时,为什么我们还需要它呢?
在接下来的章节中,我们将讨论事件。这些事件将让您在单击应用上的按钮、按下鼠标按钮、单击键盘按钮等时调用函数。在这些情况下,Lambdas 是非常需要的,所以让我们现在看看它们(即使现在它们对我们没有太大的用处)。
lambda 的语法非常简单:
variable = lambda arguments: line of code
为什么我们要把 lambda 赋给一个变量?所以我们当然可以称之为!
现在让我们看一个例子:
sum = lambda num1,num2: num1 + num2
现在,我们可以通过调用 sum()来调用 lambda,如下所示:
print(sum(3,5))
print(sum(100,240))
运行前面的代码行,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\condition.py
8
340
迷你项目——用 Python 做数学作业
我们会让这个项目变得简单。如果我们使用一个像 Tkinter 这样的包,我们可以使它成为一个合适的应用。但是我们还没有覆盖 Tkinter ,所以我们就在 Shell 中做吧。
我们的计算器将被设计成这样:
-
每种运算都有不同的功能——加、乘、除、减和取模。
-
我们将从用户那里获得信息。我们将从两个数字开始,以及他们选择要进行的手术。
-
然后,我们将打印结果,并询问他们是否想继续使用计算器。
-
如果答案是“Y”或“Y”,那么我们将询问他们是否希望之前的结果作为计算中的一个数字。如果“Y”或“Y”也是,那么我们只需要再输入一个输入,并再次请求他们想要的操作。
-
计算器可以永远这样下去。当用户回答“n”继续时,我们将跳出循环并结束程序。
有趣吗?兴奋地开始了吗?我也是!
-
让我们再次创建执行这些操作的函数。因为函数定义需要在调用之前创建,所以让我们先完成它。
#Addition def add(n1,n2): return n1 + n2 #Subtraction def sub(n1,n2): return n1 - n2 #Multiplication def mul(n1,n2): return n1 * n2 #Division def div(n1,n2): return n1 / n2 #Modulus def mod(n1,n2): return n1 % n2
-
现在,让我们创建一个永不结束的 while 循环,这意味着条件始终为真,直到我们用“break”语句中断循环。
-
在 while 循环中,我们将要求用户输入两个数字作为输入,并像往常一样将字符串转换为整数。
-
然后,我们会要求手术。我们将使用 if…elif…else 语句来调用相关函数并获得结果。
#create a result globally result = 0 #default value repeat = 0 #if the user decided to reuse the result of previous operation, this becomes 1 while(True): #if this is the first/new operation if(repeat == 0): #number1 num1 = input('Your first number: ') num1 = int(num1) #number2 num2 = input('Your second number: ') num2 = int(num2) #If the user asked to use the result of the last operation in this one else: #number2 num2 = input('Your second number: ') num2 = int(num2) #get the operator op = input('''Enter any of the following numbers, that correspond to the given operation: Just the number, not the period. 1\. Addition 2\. Subtraction 3\. Multiplication 4\. Division 5\. Modulus ''') op = int(op) #Call the relevant function if(op == 1): result = add(num1,num2) elif(op == 2): result = sub(num1,num2) elif(op == 3): result = mul(num1,num2) elif(op == 4): result = div(num1,num2) elif(op == 5): result = mod(num1,num2) else: print('You entered an invalid operation. Please run the program again') break #print the result print('Answer: {}'.format(result)) again = input('Do you want to do another operation? Enter Y or N: ') if((again == 'y') or (again == 'Y')): reuse = input('Do you want the result of the current operation to be the first number of the next? Y or N: ') if((reuse == 'y') or (reuse == 'Y')): num1 = result repeat = 1 else: repeat = 0 else: print('Ok bye!') break
迷你项目-自动化形状-下一级
循环是自动化,但是函数应该是真正的自动化,不是吗?为什么我们不看看他们能对我们的自动化形状迷你项目做些什么?
我将创建一个名为 draw_shape()的函数,并将我的代码放入其中。我将在函数中接受两个参数:边数和角度。
如果边数等于 1,我就画一个圆。否则,我要画一个多边形。就这么简单。
对于这个项目,我将使用另一个叫做时间包的包。这样,在绘制下一个形状之前,我可以给出大约 300 毫秒的小延迟,这样用户就可以看到正在发生什么:
-
我们先导入海龟和时间包。
import turtle import time
-
那么让我们建立海龟。我将钢笔颜色设置为红色,填充颜色设置为黄色。
s = turtle.getscreen() t = turtle.Turtle() t.pensize(5) t.color('Red','Yellow')
-
然后,我要定义 draw_shape()函数。在函数开始的时候,我要用时间包的 sleep()方法,基本上让程序停止 0.3 秒(300 毫秒)。然后,我将清除乌龟,这样在我画下一个之前,任何先前的形状都会被删除。
def draw_shape(sides,angle): time.sleep(0.3) t.clear() t.begin_fill() #If sides are greater than 1, then it’s a polygon if sides > 1: for x in range(0,sides): if(x == sides-1): t.home() break t.forward(100) t.right(angle) elif sides == 1: #circle t.circle(100,angle) t.end_fill() t.hideturtle() turtle.hideturtle()
-
我将在不同的函数调用中给出多个值。当您运行这个程序时,您将看到这些形状被连续绘制,中间有 0.3 秒的延迟。
draw_shape(4,90) draw_shape(3,60) draw_shape(5,50) draw_shape(6,60) draw_shape(8,45) draw_shape(1,180) draw_shape(1,360)
您将获得的图像如图 13-1 所示。
图 13-1
自动化形状
整洁!
摘要
在这一章中,我们研究了真正的自动化功能。我们学习了定义函数、调用函数、发送参数使函数动态化、返回值给函数调用、接受任意参数等等。我们也自动化了我们在前面章节中做的一些项目。
在下一章,让我们像专业人士那样进行真实世界的编程!我们将在编程中观察对象并模仿真实世界的场景。**
十四、让我们创造真实世界的对象
在前一章中,我们研究了真正的自动化功能。我们研究了如何使用函数节省时间、空间和代码行,定义函数,调用函数,向函数发送参数,使用默认参数,将值返回到调用语句,以及接受任意参数和列表作为参数。b
在这一章中,让我们看看如何用面向对象编程(OOPs)进行真实世界的编程。我们将会看到类、初始化函数、self、用户定义的属性和方法,以及在我们的类上创建对象。我们还将了解如何访问我们的属性和函数,以及如何更改属性值。
什么是面向对象编程?
Python 中的一切都是对象。它有自己的属性和方法记得吗?现实世界就是这样。就拿我们人类来说吧。我们有属性,比如我们的身高、体重、眼睛颜色、头发颜色等等。同样,我们也有“方法”,比如我们跑步、走路、说话、做事,对吗?
Python 中的一切都反映了我们现实世界中的对象。例如,字符串有长度这样的属性,但是有拆分、大写等方法。人类是一个“群体”,在这个“群体”之下存在着个体的人类,他们有自己的价值观(不同的发色、体重、身高等。).类似地,“字符串”也是一个组,在这个组下,您可以使用自己的属性和方法创建自己的单独字符串。
这就是面向对象编程的核心:真实世界的编程。您可以为项目创建自己的对象,而不是使用预定义的对象及其方法和属性。你看到这里的可能性了吗?现在世界是你的了!
但这是一个庞大的主题,不可能在一章中涵盖所有内容。我也不想让你太困惑。你是来学习 Python 和创建好玩的项目的,我们不用 OOPs(面向对象编程)也能创建本书中的项目。但是我会给你一个 OOPs 的介绍,让你了解它的基本知识。听起来不错?好吧,那我们开始吧!
来证明一下吧!
我刚才说了 Python 里一切都是对象,不是吗?为什么我们不证明一下呢?
让我们从一个整数(一个数)开始,检查它的类型。
num = 10
print(type(num))
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\oops.py
<class 'int'>
有意思。在下一节中,您将看到类是您在 Python 中创建对象的方式,所以本质上,整数是一个类,保存整数的变量是对象。好吧,但是剩下的数据类型呢?
s = 'Hello'
print(type(s))
b = True
print(type(b))
f = 1.0
print(type(f))
def fName():
pass
print(type(fName))
运行整个程序,你会得到这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\oops.py
<class 'int'>
<class 'str'>
<class 'bool'>
<class 'float'>
<class 'function'>
哇哦!都是课!所以在 Python 中一切确实都是对象。
班级
还记得我之前提到的那些团体吗?如果您想要创建自己的对象,则需要创建一个组,您可以在该组下创建这些对象。“人类”是一个群体,每个人都是一个独立的对象。每个人都有一套我们共有的属性和方法,对吗?
类似地,每组对象都有一组通用的属性和方法,所以让我们为该组创建一个蓝图,并使用自己的一组值分别创建每个对象。
迷茫?不要这样。一会儿就清楚了。
你需要 类 来创建这些蓝图。
为了对真实世界建模,让我们创建一个“Human”类,它具有反映我们人类的属性和方法。
class Human:
sample = 'Sample property value'
就这样!你有你的第一堂课。这不是强制性的,但是在命名你的类的时候,第一个字母要大写,这样当你创建你的对象的时候,你可以更好的区分它们。
好吧。我们有一节课,但是下一节是什么?我们的对象在哪里?你需要创造它们。为什么我们不创建一个“人类 1”对象呢?
human1 = Human()
就这么简单。现在,您可以访问类内部的属性值,如下所示:
print(human1.sample)
运行前面的代码,您将得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/oops.py
Sample property value
有效!
有自己价值的对象
到目前为止,我们还没有创建基于我们在其上创建的对象来改变其属性值的动态类。
为此,您需要使用一个名为 init()函数的“class”预定义方法。也就是 init 前两个下划线,init 后两个下划线,后跟()。
使用这种方法,您可以在创建对象时发送对象的单个值,以便将它们分配给类的属性。让我们看看如何:
class Human:
def __init__(self,name,age,hair,eye,pet):
self.name = name
self.age = age
self.hair = hair
self.eye = eye
因此,定义 init 函数并接受创建对象时所需的属性。我们的属性将是姓名、年龄、头发(头发颜色)、眼睛(眼睛颜色)和宠物(他们宠物的名字)。
但这还不是全部。一开始就有这个特殊的属性,“自我”。那是什么?你想猜猜吗?什么是自我?你自己?那么它应该是被创造的对象,不是吗?绝对的!
“自我”是被创建的对象,我们正在为该对象创建属性,并为其分配可接受的值。只要遵循变量命名约定,您可以随意命名它。程序员使用“自我”,所以他们知道它是什么。
好了,现在我们已经创建了一个“适当的”类,让我们创建我们的对象。
human1 = Human('Susan',8,'brunette','blue','Barky')
我们的第一个对象是“human1 ”,它将是“human”类的一个对象,我们已经为它发送了一些属性。确保按照 init()函数期望的顺序发送属性,否则可能会出现错误。
你可以像那样创建任意数量的对象。让我们创建另一个。
human2 = Human('Johny',10,'blond','green','Boxer')
到目前为止,这看起来类似于一个常规的函数调用。那为什么要用类呢?
首先,你不需要返回任何东西来访问这些属性。
print(human1.name)
print(human2.eye)
您的对象的名称,后跟一个句点和属性,您就可以开始了。
让我们运行它,我们将得到以下结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/oops.py
Susan
green
没错。我们得到了我们想要的。
操纵你的对象
与函数不同,我们也可以改变对象的属性值。
human2.eye = 'brown'
print('Eye color: {}'.format(human2.eye))
运行所有程序,你会得到这个:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/oops.py
Susan
green
Eye color: brown
看那个。值已更改。
所以,对象是字典和函数的混合体。它们是两个世界中最好的,甚至更多!
就像在字典中一样,您可以使用“del”关键字删除对象的属性,或者只删除整个对象,如下所示:
del human2.eye
del human1
但是不像你的数据结构(列表、字典等等。),不能循环遍历一个对象。☹
对象做事情
当我开始这一章的时候,记得我说过什么吗?对象有属性(就像我们一样),它们做事情或者事情对它们做(就像我们一样)。那么,我们为什么不添加一堆让我们的对象做事情的“方法”呢?
您将创建常规的旧函数,但这次只在类内部创建。
让我们的对象说话,行走,奔跑,好吗?或者只是模拟一样。
class Human:
def __init__(self,name,age,hair,eye,pet):
self.name = name
self.age = age
self.hair = hair
self.eye = eye
def talk(self):
print('{} talking'.format(self.name))
def green(self):
print('Hello there!')
def walk(self):
print("{} is walking".format(self.name))
human1 = Human('Susan',8,'brunette','blue','Barky')
human2 = Human('Johny',10,'blond','green','Boxer')
你注意到我们如何使用自我了吗?从类中访问对象的名字。“自我”是调用函数的对象。每个函数都需要接受“self”来指示调用它的对象,不管是否在函数中使用它的属性值,否则在运行程序时会出错。
让我们现在调用我们的函数,看看我们得到了什么:
human1.talk()
human1.greet()
human2.walk()
运行前面的代码,您将得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/oops.py
Susan talking
Hello there!
Johny is walking
哇,太好了!
turtle
与对象赛跑
既然我们知道了类是如何工作的,以及如何用它们来创建对象,为什么我们不试着用它们来复制我们的海龟赛跑呢?我相信我们现在可以让代码更简单。
我们将创建一个 turtle 类来创建我们的 Turtle,用一个用户定义的 move()方法随机移动 Turtle(在 1-10 的范围内)。
-
让我们从导入海龟和随机模块以及设置海龟屏幕开始。让我们也把主海龟藏起来。
-
让我们创建一个
turtle
类。初始化函数将接受颜色、x 和 y 来改变海龟的颜色,并将海龟移动到起始位置。
import turtle, random
s = turtle.getscreen()
turtle.hideturtle()
- 那么,我们来定义一下 self.turtle,为什么是 self.turtle 而不是 self?嗯,“self”指的是我们正在创建的对象,所以如果我们想要在该对象上创建一个 turtle,我们需要创建一个包装对象,在我的例子中就是 self.turtle。您可以随意命名它。
class Turtle:
def __init__(self,color,x,y):
这样,原始对象不会被重新分配,我们仍然可以创建一只乌龟。
- 接下来,让我们更改笔的大小、颜色和形状。
self.turtle = turtle.Turtle()
- 最后,让我们把乌龟移动到给定的位置。
self.turtle.pensize(5)
self.turtle.color(color)
self.turtle.shape('turtle')
- 现在我们已经完成了 init()函数,让我们创建一个 move()函数。它只是随机地让乌龟向前移动,就像我们在原程序中做的那样。
self.turtle.penup()
self.turtle.goto(x,y)
self.turtle.pendown()
def move(self):
self.turtle.forward(random.randint(1,10))
我们班到此为止!
-
现在,让我们创建我们的对象。我将创建三个对象,红色、蓝色和绿色,以及它们的相关值。
-
现在,在 0–99(100 次迭代)的范围内,让我们为每一次迭代调用三只乌龟的 move()函数。
red = Turtle('Red',-250,150)
blue = Turtle('Blue',-250,0)
green = Turtle('Green',-250,-150)
for i in range(100):
red.move()
blue.move()
green.move()
就这样!我们的程序工作吗(图 14-1 )?
图 14-1
有阶级的乌龟赛跑
当然了,红队赢了!
摘要
在这一章中,我们看了如何用面向对象编程(OOPs)进行真实世界的编程。我们看了类、初始化函数、self、用户定义的属性和方法,以及在我们的类上创建对象。我们还研究了如何访问我们的属性和函数,以及如何更改属性值。
在下一章中,让我们看看文件,如何创建、打开和修改它们。
十五、Python 和文件
在前一章中,我们学习了如何使用类在 Python 中创建真实世界的对象。我们学习了在 Python 中一切都是对象。然后,我们学习了如何在 Python 中创建类,并使用这些类创建类似的对象,而无需编写太多行代码。
在本章中,我们来看看 Python 中的文件处理。我们将着眼于从 Python 代码内部创建、读取、写入和操作系统中的文件。
为什么是文件?
我能听到你的呻吟。你可能会说,这又是一个无聊的理论话题。别这么快就放弃文件。这是一个很轻松的话题,可以打开太多的可能性去数。
一旦你学会了这一点,现实世界的编程就是你的了。您可以开始将系统中的文件包含在您的程序中,您可以从您的程序中创建它们,读取它们,操作它们,完全删除它们,等等。如果你想在你的笔记本和电脑上创建功能齐全的应用,那么你最好学习文件。
这是一个快速的章节,所以不要太担心,像往常一样,我们将以一个有趣的,这次是简单的迷你项目来结束它。此外,从下一章开始,你将创建所有你想创建的大项目、小项目、应用和游戏,所以更有理由快速完成这一章,你不觉得吗?
打开和读取现有文件
让我们从简单的开始。在对文件做某些事情之前,您需要检索它并将其保存在一个变量中,以便以后可以读取它、写入它等等。
使用“open”方法并在双引号或单引号内指定文件名。您需要指定完整的文件名,包括相关的扩展名,如。py,。txt,等等。
但是,如果文件与脚本存在于同一个文件夹中,那么您可以只提及文件名及其扩展名,就像我在我们的示例中将要做的那样。
我将让我的程序检索 introduction.py 文件,因为它与我为本章创建的 files.py 文件在同一个文件夹中,所以我不需要指定完整的路径。
但是如果我的路径在不同的文件夹中呢?怎么才能拿到?O:
这是一个非常简单的过程。在 Windows 中打开你的文件浏览器,或者在 Mac 中打开它,如图 15-1 所示。
图 15-1
找到您的文件
在我放置箭头的地方单击,也就是在最后一个文件夹名称之后。你会得到路径,像这样(图 15-2 )。
图 15-2
获取您的文件路径
现在,你可以复制路径。但是不能照原样使用。您需要按照以下格式格式化路径和文件名。在前面的示例中,我们试图获取文件“introduction.txt”的路径,该文件位于路径 G:\Python 中。为了在我的程序中使用它,我将把它格式化成这样:
G:\\Python\introduction.txt
然后,我会把整个事情放在引号内,并使用它。就这么简单!
准备好 open()方法后,将其赋给一个变量。为什么呢?一会儿你就知道了!
file = open(' introduction.py')
现在我们已经将文件存储在变量“file”中,我们可以开始操作它了。
你想先做什么?我们要读它吗?打印里面的内容?好吧,就这么办!
你能猜到读取一个文件会怎样吗?也许 Python 有 read()函数我们可以用?是的,你说得对!这正是我们所拥有的。
但是,在使用 read 函数之前,您需要向您的程序指定这正是您要做的事情。因此,当您检索文件时,您需要添加第二个参数,指定您以只读格式检索文件,并且稍后您将读取并可能打印其中的内容。
让我们改变我们的代码行:
file = open(' introduction.py','r')
正如您在前面的代码中看到的,我在引号中包含了第二个参数“r”。这将让我的程序知道,我只是检索文件来读取它,而不是别的。
现在,我们实际上可以读取并打印我们的文件。你想试试吗?
file.read()
让我们运行上面的代码,然后…
蟋蟀…
什么都没发生。😮 为什么?!你让你的程序去读它,它就这样做了。你没让它打印结果吧?你需要对计算机非常清楚。他们需要确切的指示。
因此,让我们打印我们的读取操作:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/file.py
print('Hello there!')
print('My name is Susan Smith.')
print('I am 9 years old.')
print('I love puppies! :)')
看那个!introduction.py 文件中的全部内容(代码)都打印出来了。你注意到什么了吗?尽管该文件包含代码,并且是在 Shell 中打印的,但是这些 print()行并没有被执行。它们就是这样印刷的。
为什么会这样?在这种情况下,您的文件被认为是一个普通的文本文件,代码行是文件中的内容。仅此而已。如果您想要执行前面的代码,您需要以通常的方式进行,而不是通过文件操作打开或读取它。
你可以要求你的程序只打印指定数量的字符,而不是全部。假设我只想打印出前 50 个字符(单个字母、数字、特殊字符和空格),其他什么都不要。然后我要做的就是在括号内指定 50,就像这样:
print(file.read(50))
运行前面的代码,您将得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/file.py
print('Hello there!')
print('My name is Susan Smith.')
计算前面结果中的字符数,您将得到 50 个,包括作为单独字符的空格和新行。
你为什么不尝试不同的数字,看看你会得到什么?
逐行
如果您不想打印整个文件,也不想计算字符数,该怎么办?如果你只想要第一行呢?然后,您可以使用 readline()方法来读取行。让我们用 readline()代替 read()。
print(file.readline())
运行前面的代码,您将得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/file.py
print('Hello there!')
耶!只是第一行。
如果我想打印更多的行呢?我可以像在 read()中那样在括号中指定 2 吗?
print(file.readline(2))
运行前面的代码,您将得到这样的结果:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/file.py
pr
啊,真倒霉。它以为我又要两个字了。我想唯一的办法是指定另一个 readline()。我们试试好吗?
print(file.readline())
print(file.readline())
我们现在有两个 readline()方法。有用吗?
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/file.py
print('Hello there!')
print('My name is Susan Smith.')
没错。我们现在有两条线,它们之间有一个巨大的空间,因为它们是用两种不同的印刷品印刷的。
如果你想读取并打印出整个文件,那么就像遍历一个列表一样遍历它。对于循环的每一次迭代,程序将打印文件中的一行。
file = open('introduction.py','r')
for i in file:
print(i)
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\file.py
print('Hello there!')
print('My name is Susan Smith.')
print('I am 9 years old.')
print('I love puppies! :)')
这是整个文件!
创建新文件
您可以在 open()方法中使用“x”或“w”属性来创建新文件。“w”只是创建一个不存在的文件,但打开一个已存在的文件,而“x”专门用于创建新文件。如果您尝试“创建”一个现有文件,“x”会返回一个错误。
现在让我们创建一个文件 newFile.txt。
file = open('newFile.txt','x')
我们的文件刚刚创建!再次运行程序,你会得到一个错误,因为文件现在已经存在。
操作文件
您可以使用 write 方法向文件中添加。为了做到这一点,你需要打开你想要添加文本的文件,无论是写,“w”,还是附加,“a”,模式。
“写入”模式将覆盖文件中当前的任何文本。追加模式将给定的文本追加到文件的末尾。
我们两个都试试,好吗?
我已经以“写”模式打开了我们在上一节中创建的文件。
file = open('newFile.txt','w')
现在,让我们使用“write”方法向我们的文件添加几行文本,由新行“\n”分隔。
f.write('Hi there!\nThis is a new file.\nWe just added text to it!')
现在,让我们阅读我们的文件,看看我们是否得到同样的结果。
file = open('newFile.txt', 'r')
print(file.read())
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\file.py
Hi there!
This is a new file.
We just added text to it!
哇哦!
让我们现在尝试追加。
file = open('newFile.txt','a')
file.write('\nThis is the last line')
file = open('newFile.txt','r')
print(file.read())
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\file.py
Hi there!
This is a new file.
We just added text to it!
This is the last line
这是一个非常强大的功能,可以使编程桌面应用,或任何应用,对你来说非常容易!
迷你项目-用文件介绍
这将是一个非常简单的项目。我们将在您选择的文件夹中创建一个名为 introduction.txt 的文本文件。我们将通过 Python 代码编写对该文件的介绍,最后,我们将在 Shell 中打印该介绍。简单!
我们可以开始了吗?
- 我将在下面的路径中创建我的文件:
G:\\Python\introduction.txt
我也可以用“x ”,但是我用的是“w ”,这样我就不用再以写模式打开文件了。
- 然后,我要写苏珊对它的介绍:
f = open('G:\\Python\introduction.txt','w')
- 现在,让我们把它打印出来。让我们再次打开我们的文件,但这一次是在读模式下,一边读一边打印它的内容,最后关闭它。
f.write('''Hi, I'm Susan.
I'm 9 years old.
My puppy's name is Barky.
He loves me very very much! :)''')
f = open('G:\\Python\introduction.txt','r')
print(f.read())
f.close()
现在,当我们运行程序时,我们会得到这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\file.py
Hi, I'm Susan.
I'm 9 years old.
My puppy's name is Barky.
He loves me very very much! :)
完美!
摘要
在这一章中,我们学习了所有关于文件的知识,从你的 Python 代码中创建它们,读取它们,将它们存储在变量中,在你的程序中操作文件,等等。
在下一章,让我们学习一下 Tkinter ,一个让你创建桌面应用的 Python 包。
十六、用 Tkinter 创建很酷的应用
在前一章中,我们学习了用 Python 创建、打开和操作计算机文件的所有知识。在这一章中,我们正式回到 Python 的乐趣中。您将了解到 Tkinter ,这是一个可以用 Python 创建桌面应用(GUI——图形用户界面)的包。您将学习如何创建按钮、标签、框等等。
让我们开始吧!
还记得我们和海龟一起工作时做了什么吗?与 Tkinter 合作的一些流程是相同的。你现在是职业程序员了。你已经知道了 Python 的基础知识。你已经完成了迷你项目的整个章节。
所以,在这一章,我希望你穿上你的大男孩/女孩裤子。我不会给出很多实际的解释,因为你已经知道了很多这方面的东西。我们将在这一章中涉及很多内容,在这一章的最后,你将拥有和你在系统中看到的一样漂亮的应用,并且你将拥有创建更多应用的工具。激动吗?我也是!我们开始吧。
就像 turtle 一样,我们需要首先导入 Tkinter 。让我们打开一个新的脚本文件。不要保存为“tkinter.py”。您的 Python 安装中已经有一个类似的文件,它包含您将用来创建应用的所有预定义方法的代码。我将把我的文件保存为 tkPrograms.py。
我们先导入 Tkinter 。
from tkinter import *
我已经要求所有东西都从 Tkinter 包中导入。“*”代表一切。现在,我们需要创建一个包含我们的应用的窗口。我要调用我的 w,需要调用的函数是 Tk():
w = Tk()
让我们运行一下,看看我们会得到什么(图 16-1 )。
图 16-1
tkinter screen(tkinter screen)
看那个!一扇漂亮的小窗。它也有可以用来最小化、最大化和关闭窗口的按钮。你为什么不试试它们?
标题有点奇怪吧?上面只写着 tk。我不喜欢!我希望我的能说“我的第一个应用”。我该如何改变?当然是通过在我们刚刚创建的窗口上调用 title()方法!
w.title('My first Tkinter app')
再次运行,看看您会得到什么(图 16-2 ):
图 16-2
标题变更
看那个!上面写着我现在想要的。我稍微调整了一下窗口大小,这样我就可以看到整个标题。这太美了。我只写了三小段代码,现在我有了一个漂亮的小窗口。你能看出 Tkinter 有多厉害吗?O:
好吧,那么,这是它的设置。接下来,让我们看看如何创建小部件并将它们放在这个窗口上。这就是事情变得有趣的地方!
标签、纽扣和包装
Tkinter 有很多“小部件”,你可以创建它们来让应用变得生动。这些小部件包括按钮、文本框和单选按钮。一旦创建了一个小部件,就需要把它放在窗口上。所以,这个过程通常有两个步骤。现在让我们看看如何创建标签和按钮,好吗?
要创建标签,您需要使用" Label()"方法,并在第一个属性中提及您希望标签放置的窗口,并在" text "属性中提及您希望标签中的文本。我将创建一个变量 label1,并将我的标签放入其中。
label1 = Label(w,text='My Label')
如果我运行这个,我将再次以一个空白窗口结束。为什么呢?记得我之前告诉你的吗?小工具需要放在窗口内才可见。我们如何做到这一点?
最简单的方法之一是使用 pack()方法。它只是将你创建的窗口小部件打包或放入窗口,并根据窗口小部件的大小调整窗口大小。
这就是为什么我把我的标签放在一个变量中,这样我就可以在变量上调用 pack()方法。那样看起来很整洁。
label1.pack()
现在运行所有程序,看看会得到什么(图 16-3 )。
图 16-3
标签
这就对了。一个小小的窗户,上面只有我的标签。
如果你不想要两行代码,你可以这样写,这样就可以了:
Label(w, text='My Label').pack()
我将坚持使用第一种方法,因为一旦我们开始设计标签并向它添加许多属性,它看起来会很整洁。稍后我还可以引用同一个标签来更改它的属性值。它只是在现实世界中更有活力。
但是你注意到什么了吗?每当我运行这个程序时,我的 shell 都会打开我的窗口,但是它会返回到下一个提示符(<<
现在,再次运行,您会注意到我们的 Shell 没有进入下一个提示。很好!
好吧。我们现在能把事情弄得漂亮一点吗?为什么我们不玩我的标签的大小和颜色?
不过,在我们开始之前,让我们先来看看颜色的选择。 Tkinter 认识一吨的颜色名称,你可以在这里找到他们的名单,在他们的官方网站: www.tcl.tk/man/tcl8.5/TkCmd/colors.htm
。
如果你想把颜色形象化,你可以使用这个网站: www.science.smith.edu/dftwiki/index.php/Color_Charts_for_TKinter
.
第二个链接是第三方网站,但仍然有用。
所以,现在我们已经用颜色武装了自己,让我们开始吧!
您可以使用宽度和高度属性来更改标签的大小。它们分别改变标签的宽度和高度。但是,当您使用这些属性时,您会注意到一些不同。假设这两个属性的值都是 10,但是您会注意到标签的高度大于标签的宽度。这是因为这些值不是以像素为单位,而是以字符“0”的大小为单位。它的宽度比它的高度小两倍,不是吗?这就是你看到的。所以,在给出你的价值观的时候考虑一下这个。
此外,您可以使用 bg 属性更改标签的颜色,使用 fg 属性更改标签文本的颜色。让我们把它们结合在一起,设计我们的标签吧!
label1 = Label(w, text='My Label', bg="Salmon4", fg="gold2", width=10, height=5)
label1.pack()
我已经将背景色改为“Salmon4”,文字颜色改为“gold2”,宽度改为 10 个字符单位,高度改为 5 个字符单位。现在让我们运行程序(图 16-4 )!
图 16-4
更改标签的大小和颜色
喔!看看窗口是如何扩展到包含我的新标签的。太完美了。
你还可以使用其他的属性,但是让我们在本章的后面部分来看看。那么,纽扣呢?它遵循相同的程序。使用 Button()方法,属性相同。
button1 = Button(w, text='My Button', bg='steel blue', fg="snow", width=10, height=5)
button1.pack()
运行所有程序,看看会得到什么(图 16-5 )。
图 16-5
纽扣
你会发现你真的可以点击按钮。它是动画,不像标签。
但这还没有结束。当你点击这个按钮时,你可以让你的系统做一些事情。使用 command 属性,我可以在单击按钮时调用函数。
def buttonClick():
print('You just clicked the button! :)')
button1 = Button(w, text='Click Me!', bg='steel blue', fg="snow", width=10, height=5, command=buttonClick)
button1.pack()
如你所知,在 Python 中,函数定义应该总是在函数调用之前,在我们的例子中,是在按钮之前。让我们创建一个打印消息的函数 buttonClick()。就这样。
现在,在我们的按钮中,我们添加了一个新属性“command”,该值是我们函数的名称。就名字,不用加括号。现在,像往常一样,打包按钮并运行程序,您将得到按钮。单击它,回到 Shell,您会看到:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\tkPrograms.py
You just clicked the button! :)
哇哦!有效!
详细包装
到目前为止,事情看起来很糟糕。我们实话实说吧。这不是我们创建应用的方式。但是不要惊慌。pack()方法还有一些技巧。
在我们看这些之前,让我们先来看看所谓的“框架”。这个框架不完全是一扇窗户。我们已经创造了一个。但是有了框架,你可以把你的部件分组,然后按照你想要的方式组织它们。
让我们围绕标签和按钮创建一个框架。我们也可以给出背景颜色(bg)、宽度和高度,但是在这种情况下,宽度和高度是以像素为单位的,所以要使数字更大。
frame1 = Frame(w)
frame1.pack()
label1 = Label(frame1, text='First button')
label1.pack()
button1 = Button(frame1, text="Button1")
button1.pack()
label2 = Label(frame1, text='Second button')
label2.pack()
button2 = Button(frame1, text="Button2")
button2.pack()
正如您在前面的代码中看到的,我创建了一个框架,然后在该框架中创建了两个标签和两个按钮。因此,frame1 的根窗口是“w”,即原始窗口,但其余小部件的根窗口是我们的 frame1。这样,我们可以在同一个窗口中创建任意多的框架。现在,让我们运行它,看看我们会得到什么(图 16-6 )。
图 16-6
包装几何方法
似乎什么都没有改变。☹该收拾()方法来救援了!
pack()方法是一个几何管理器,它将您的小部件打包到它的父窗口(在我们的例子中是 frame1)的行和列中。
首先,让我们看看填充选项。您可以使用此选项让您的小部件填充父小部件。
现在,弹出的窗口看起来好像包含了整个框架(图 16-7 ),但事实并非如此。如果我调整它的大小,它会在框架周围添加填充。
图 16-7
Pack()调整大小问题
但是如果我想让框架充满主窗口,那么我可以使用填充和扩展选项。先说“填”。这里我可以给三个值,X,Y,或者两个都给。
x 在水平方向填充主窗口,Y 在垂直方向填充主窗口,两者都填充了整个窗口小部件。三个都看看吧。
frame1 = Frame(w, bg="black")
frame1.pack(fill=X)
我已经给了框架一个背景色,这样我们就可以单独看到框架了。
接下来,我将填充到 Y:
frame1.pack(fill=Y)
最后我把它改成两个(图 16-8 ):
图 16-8
带填充的框架
frame1.pack(fill=BOTH)
填充在一定程度上起作用,但是当窗口调整大小时,它仍然不会扩展。这是因为 fill 只是让 Python 知道它想要填充给它的整个区域。如果我们两个都给,它将水平和垂直填充整个区域。
但是,如果我们希望它填充整个父对象,也就是说,在父对象扩展时扩展,那么我们需要“expand”选项。让它成真,看看神奇。
frame1 = Frame(w, bg="black")
frame1.pack(fill=BOTH, expand=True)
让我们对 X 和 Y 做同样的尝试:
frame1.pack(fill=X, expand=True)
最后,
frame1.pack(fill=Y, expand=True)
现在,用不同的填充值运行程序,并调整窗口大小,得到这个结果(图 16-9 )。
图 16-9
Tkinter 中的填充选项
很迷人,不是吗?
好了,现在我们知道了如何填充父窗口,但是这对我们的小部件有什么帮助呢?我们有四个,我希望第一个标签和按钮在第一行,第二个标签和按钮在第二行。我该怎么做?这就是“侧面”选项出现的原因。
让我先解释一下侧边选项是如何工作的。让我们创建两个小部件,并尝试用“side”的不同选项打包它们。
label = Label(w, text='My Label')
label.pack(side=TOP)
button = Button(w, text='My Button')
button.pack(side=TOP)
我已经给了边作为顶部开始,这是默认的。您会注意到小部件一个接一个地被打包。
现在,将两者的值都更改为 LEFT。它会把所有东西并排放在一起。当你给 BOTTOM 的时候,它会从底部到顶部打包所有的东西,RIGHT 做的正好和 LEFT 相反。
当我们运行前面代码的四个变体时,我们得到以下四个输出(图 16-10 )。
图 16-10
Tkinter 中的侧面选项
看看在第三个图像中,按钮是如何出现的,然后是标签。这就是 BOTTOM 的作用。它颠倒了顶部。同样,右是左的反义词。
看起来很棒,是的,但这似乎还不完整。这是因为您需要所有三个选项来按照您想要的方式正确对齐您的小部件。
所以现在,让我们结合所有的选项,创造一些看起来一致的东西。我将创建两个框架,每个框架都将被打包在顶部(一个接一个),它们从两侧填充父窗口,expand 为 True。
类似地,我将在第一个框架下创建一个标签和一个按钮,并向左打包(并排),但使它们包含整个父框架(fill 为 both,expand 为 True)。让我们对第二帧重复同样的操作。
现在,让我们看看我们得到了什么:
frame1 = Frame(w, bg="black")
frame1.pack(side=TOP, fill=BOTH, expand=True)
label1 = Label(frame1, text='First button')
label1.pack(side=LEFT, fill=BOTH, expand=True)
button1 = Button(frame1, text="Button1")
button1.pack(side=LEFT, fill=BOTH, expand=True)
frame2 = Frame(w, bg="white")
frame2.pack(side=TOP, fill=BOTH, expand=True)
label2 = Label(frame2, text='Second button')
label2.pack(side=LEFT, fill=BOTH, expand=True)
button2 = Button(frame2, text="Button2")
button2.pack(side=LEFT, fill=BOTH, expand=True)
运行前面的代码,你会得到这个(图 16-11 )。
图 16-11
包装有序的标签和按钮
哇哦!这正是我第一次创建这些小部件时想要的放置方式。搞定了。
现在展开这个窗口,您会注意到小部件也随之展开。由于子部件完全包围了框架,您看不到它们的背景颜色,这意味着我们已经正确地完成了我们的工作!
大量输入
既然您已经知道了如何使用 pack()方法来正确地对齐小部件,那么让我们回到快速查看更多小部件。Tkinter 提供了大量从用户那里获取输入的小工具。
一行文本
通过使用 Entry()方法,可以从用户那里获得单行文本输入。
entry = Entry().pack()
运行前面的代码,你会得到这个(图 16-12 )。
图 16-12
入口小部件
看那个!我现在可以给出单行条目。
此外,除了 fg、bg 和 width 等常见属性之外,您的入口小部件还具有可用于操作入口的方法。
为什么我们不看看怎么做呢?我们可以使用 get()方法来检索我们在条目中键入的内容,并且我们可以按照自己的意愿使用它。
现在,让我们创建一个标签“name”和一个输入框,最后创建一个按钮“Enter”。当用户单击按钮时,它调用 greet()函数,该函数从输入框中“获取”输入并打印出“Hello”消息。够简单吗?我们试试吧!
def greet():
name = entry.get()
print('Hello {}'.format(name))
label = Label(w,text='Your name?')
label.pack(side=LEFT)
entry = tkinter.Entry(w)
entry.pack(side=LEFT)
button = Button(w,text='Enter',command=greet)
button.pack(side=LEFT)
让我们运行一切,我们会得到这个(图 16-13 )。
图 16-13
带有条目的名称框
现在,当我按 Enter 键并查看 Shell 时,我得到了这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\tkPrograms.py
Hello Susan
耶!
另外,delete()方法可以删除文本,insert()方法可以在任意位置插入文本。
我们先来看看 insert。语法非常简单。
entry.insert(pos, ‘text’)
所以,只要给出你想要插入文本的位置。第一个位置是 0,从那里开始增加,就像你的弦一样。第二个参数是要插入的直接文本或包含文本的变量。
你想看看这是怎么工作的吗?让我们修改我们的程序。现在,当用户输入他们的名字时,他们必须点击“插入你好”按钮,当点击时,就会在他们的名字前插入你好和一个空格。
def insert():
entry.insert(0,'Hello ')
label = Label(w,text='Your name?')
label.pack(side=LEFT)
entry = tkinter.Entry(w)
entry.pack(side=LEFT)
button = Button(w,text='Insert Hello',command=insert)
button.pack(side=LEFT)
让我们运行程序(图 16-14 )。
图 16-14
插入到输入框中
当我们点击按钮时,我们得到这个(图 16-15 )。
图 16-15
插入的
哇哦!
同样,你可以删除。如果你只给出一个参数,它会删除那个字符。0 删除第一个字符,1 删除第二个字符,依此类推。
但是,如果你给一个范围,它会删除一个字符范围。
通常,不考虑范围内的最后一个数字。例如,范围 0,4 删除索引 0 到 3 中的字符(不包括 4)。
但是如果你想删除一切,那么就把 END 作为你的最后一个论点,就大功告成了。我们试试好吗?
def insert():
entry.delete(0,END)
label = Label(w,text='Your name?')
label.pack(side=LEFT)
entry = tkinter.Entry(w)
entry.pack(side=LEFT)
button = Button(w,text='Clear',command=insert)
button.pack(side=LEFT)
当我运行程序时,我得到这个(图 16-16 )。
图 16-16
从输入框中删除
我已经输入了 Susan,当我按下清除按钮时,我得到了这个(图 16-17 )。
图 16-17
输入框已清除
一笔勾销!
一行又一行
现在,让我们看看如何输入和操作多行文本!您可以使用 Text()方法来做到这一点。
text_box = Text()
text_box.pack()
运行这个,你会得到一个大的文本框,当你在其中输入几行代码时,它会是这样的(图 16-18 )。
图 16-18
文本框
您可以使用 get()方法从该文本框中检索文本,但是您需要指定行号和范围中的字符数。
“1.0”将只检索第一行的第一个字符。
“1.0”,“1.9”将检索第一行中的第一个字符到第九个字符。
“2.0”、“2.5”将从第二行的第一个字符到第五个字符进行检索,以此类推。
“1.0”,“2.10”会一直检索到第二行的第十个字符,所以可以这样跨多行。
要获得整个文本,只需给出“1.0”,结束。
你现在明白这是怎么回事了吗?让我们尝试检索整段文本。
text_box = Text(w)
text_box.pack()
def get_text():
t = text_box.get(1.0,END)
print(t)
button = Button(w,text="Get data",command=get_text)
button.pack()
让我们再次运行程序,键入相同的文本,看看我们会得到什么(图 16-19 )。
图 16-19
从文本框中获取数据
现在我们有一个大的文本框,在末尾有一个小按钮,因为我们就是这样包装的。让我们点击按钮,我们得到这个:
>>>
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\tkPrograms.py
Hello there! This is the first line of text.
This is the second line of text.
This is the third line of text.
Bye bye!
有效!
同样,您可以在文本框中插入文本。
text_box.insert(1.0,"Welcome! ")
前面的代码将插入“欢迎!”在第一行的开头加一个空格。文本、复选框、条目、单选按钮、菜单按钮、复选按钮、列表框。
要在文本末尾插入内容,请使用 end 作为第一个参数,但是如果您希望文本在新的一行中,请在第二个参数的开头添加\n(换行符),如下所示:
text_box.insert(END,"\nYou're great!")
要删除整段文本,请执行以下操作:
text_box.delete("1.0",END)
您可以使用与 get()相同的格式来删除文本片段。
这是对文本框的快速浏览。现在,进入下一个部件!
Tkinter变量
**但在此之前,我想先谈谈变量。还记得我们如何直接输入文本,而不使用变量吗?那不是很有活力。如果我想根据应用/游戏中发生的事情更改标签文本或按钮文本,该怎么办?我需要一个变量。这就是 Tkinter 可变类的用武之地。它们的工作原理和我们的正常变量非常相似。
您可以创建五种变量:整型、字符串型、布尔型和双精度型(浮点型)。
num = IntVar()
string = StringVar()
b = BooleanVar()
dbl = DoubleVar()
将它们赋给一个实际变量,使该变量成为一个t inter变量。另外,确保语法的大写和小写保持不变。
既然有了变量,就可以使用“set”方法给它们赋值了。如果你给一个变量赋了一个错误的值,你会得到一个错误。所以,只有一个整型变量,以此类推。
要取回变量值,请使用 get()方法。所以,让我们把两者结合起来,看看我们会得到什么。
num.set(100)
string.set("Hello there!")
b.set(True)
dbl.set(150.14)
print(num.get())
print(string.get())
print(b.get())
print(dbl.get())
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\tkPrograms.py
100
Hello there!
True
150.14
但这仍然不是动态的,对吗?我们可以将动态变量设置为我们的t inter变量吗?答案是肯定的!
只需获取一个输入,将其放入一个变量中,并将其设置为您的字符串(或任何类型)。就这样。
i = input('Enter a string: ')
string.set(i)
print(string.get())
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\tkPrograms.py
Enter a string: Hello there!
Hello there!
所以现在,我们可以动态设置标签文本。
i = input('Label text: ')
string = StringVar()
string.set(i)
label = Label(w, text=string.get())
label.pack()
运行前面的代码,您将得到这样的结果:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\tkPrograms.py
Label text: Hello there!
输入完毕后按回车键,你将得到(图 16-20 ):
图 16-20
字符串变量
耶!我们的第一个动态标签!
很多选择!
如果你想给你的用户选择,那么复选框和单选按钮是正确的选择,你不这样认为吗?Tkinter 也有这些小工具!
您可以使用 Checkbutton(小“b”)小部件创建一个复选框。
它的工作方式类似于其他小部件,除了您可以给出 onvalue 和 offvalue 来指定当 check 按钮被单击或不被单击时的“值”。
但是获得复选按钮状态的一个更简单的方法是将一个 Tkinter 整数变量赋给它的“variable”属性,每当复选框被选中时,变量的值就变为 1,当它未被选中时,变量的值就变为 0。
我们将创建两个复选框,所以让我们创建两个整数变量来存储它们的“状态”(无论它们是否被选中)。
c1 = IntVar()
c2 = IntVar()
让我们创建一个标签“杂货清单”并打包。
Label(w,text='Grocery list').pack()
现在是我们的复选框。唯一的区别是我们的“变量”属性被赋予了整型变量。
Label(w,text='Grocery list').pack()
check1 = Checkbutton(w,text="Milk",variable = c1)
check1.pack(side=LEFT)
check2 = Checkbutton(w,text="Flour",variable = c2)
check2.pack(side=LEFT)
现在,我们如何检索这些值呢?我们需要一个按钮,单击它将调用 check()函数来检查哪些框被单击了。
def check():
if(c1.get() == 1):
print('We bought Milk.')
if(c2.get() == 1):
print('We bought flour.')
button = Button(w,text='Check',command=check)
button.pack()
简单!让我们运行程序,我们得到这个(图 16-21 )。
图 16-21
检验盒
按下“检查”按钮,你会得到这个:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\tkPrograms.py
We bought Milk.
We bought flour.
对于单选按钮,我们只需要一个变量,因为我们只是选择其中一个选项。它有一个“value”属性,当设置了一个整数值时,它将把相同的值赋给你赋给“variable”属性的变量。
您也可以在单选按钮中添加一个“命令”。
让我们创建一个程序,询问用户是否喜欢狗,并根据他们的选择打印一条消息!
对于本例,我将直接从单选按钮发出命令,所以让我们先创建“check”函数。
我们将创建一个字符串,用来保存人们点击复选框后需要显示的消息。现在,我们将在我们的单选按钮中设置两个值,1 表示这个人喜欢狗,2 表示这个人不喜欢狗。
一旦我们设置了字符串,创建标签。
def check():
string = StringVar()
if var.get() == 1:
string.set('You love dogs! :)')
else:
string.set("You don't love dogs :(")
label = Label(w,text=string.get())
label.pack()
现在,让我们创建一个整数变量来保存单选按钮的值。接下来是一个询问他们是否爱狗的标签。
var = IntVar()
Label(w,text='Do you love dogs?').pack()
最后,单选按钮包含相关的文本、分配给它们的变量“var”、每个值和一个命令,如果按钮被选中,该命令将调用“check”函数。
radio1 = Radiobutton(w,text="Yes!",variable = var, value=1, command=check)
radio1.pack()
radio2 = Radiobutton(w,text="Nope",variable = var, value=2, command=check)
radio2.pack()
就这样!
运行程序,你会得到这个(图 16-22 )。
图 16-22
单选按钮
选择一个选项(图 16-23 ):
图 16-23
选择了单选按钮
完美!
菜单
使用 Tkinter ,您可以创建像您在应用中看到的菜单!您可以使用 Menu()方法来创建它们。
您可以创建一个主菜单,并将其配置到窗口的顶部,并且可以添加任意数量的子菜单。
让我创建一个主菜单“main”。
from tkinter import *
w = Tk()
main = Menu(w)
让我们在主菜单中添加一个子菜单。我会叫它文件菜单。
fileMenu = Menu(main)
现在,我将使用 add_cascade()方法向我的第一个子菜单添加一个标签,并将其放在 main 中。
main.add_cascade(label='File',menu = fileMenu)
现在,让我们添加项目到我们的主菜单。
fileMenu.add_command(label='New File', command=lambda: print('New File clicked'))
fileMenu.add_command(label='Open', command=lambda: print('Open clicked'))
如您所见,我们可以像处理按钮一样给这些项目附加一个命令。
如果你现在运行这个程序,你将什么也看不见。这是因为一旦您创建了所有的菜单、子菜单和项目,您就需要将主菜单配置到窗口(就像您打包小部件一样)中,以便显示它。
使用 config()方法可以做到这一点。
w.config(menu=main)
现在,运行您的程序,您将能够看到您的菜单(图 16-24 )。
图 16-24
菜单
单击“新建文件”菜单项,您将看到以下内容:
>>> New File clicked
我得到了我期望的消息。完美!
完美的布局——网格
我认为包装几何管理器在功能上有一点点限制。你不也这样认为吗?
这就是为什么 Tkinter 有网格几何管理器,这是联赛除了包管理器。您可以根据行和列完美地对齐您的小部件。
行和列的排列如下图所示(图 16-25 )。小部件将被放置在单元格内,每个单元格都有一个从 0 开始的行号和列号。您可以将单元格扩展到任意数量。
图 16-25
网格中的行和列
你可以提到部件的具体行和列,以及你希望它粘在哪里。
sticky 有多个值:E 代表东,W 代表西,N 代表北,S 代表南,NE 代表东北,NW 代表西北,SE 代表东南,SW 代表西南。
如果你给一个小部件一个“E ”,它将(通常是文本)粘在栏的最右边,以此类推。
如图所示,行和列从 0 开始。您可以使用 padx 和 pady 来填充小部件,这样它们就不会粘在一起。
所以,让我们把所有的放在一起排列一堆标签,好吗?
from tkinter import *
w = Tk()
w.title('My first Tkinter app')
#first row, first column, east sticky
label1 = Label(w,text='Label1')
label1.grid(row=0,column=0,sticky='E',padx=5,pady=5)
#first row, 2nd column, east sticky
label2 = Label(w,text='Label2')
label2.grid(row=0,column=1,sticky='E',padx=5,pady=5)
#first row, 4th column, west sticky
button1 = Button(w,text='Button1')
button1.grid(row=0,column=2,sticky='W',padx=5,pady=5)
#second row, first column, east sticky
label3 = Label(w,text='Label3')
label3.grid(row=1,column=0,sticky='E',padx=5,pady=5)
#first row, 2nd column, east sticky
label4 = Label(w,text='Label4')
label4.grid(row=1,column=1,sticky='E',padx=5,pady=5)
#second row, 4th column, west sticky
button2 = Button(w,text='Button2')
button2.grid(row=1,column=2,sticky='W',padx=5,pady=5)
w.mainloop()
运行程序,你会得到这个(图 16-26 )。
图 16-26
以网格形式排列的小部件
太美了!
迷你项目-小费计算器应用
让我们把到目前为止学到的所有东西放在一起,用 Tkinter 创建一个小费计算器,好吗?
这是我们需要的:
-
两个输入框用于输入账单金额(浮点)和小费金额。
-
接下来,我们需要一个按钮来获取这些值并调用 tip_calculator()函数。
-
这个函数将计算我们的小费,并在屏幕底部的标签中显示结果。
够简单吗?我们开始吧!
-
让我们先设置一下 Tkinter 。
from tkinter import * w = Tk() w.title('My first Tkinter app')
-
然后,让我们看看账单(一个标签和一个条目,在屏幕上正确排列)。
#Get the bill amount bill_label = Label(w,text='What was your bill? ') bill_label.grid(row=0,column=0,sticky="W",padx=5,pady=5) bill = Entry(w) bill.grid(row=0,column=1,sticky="E",padx=5,pady=5) Next, let’s create the label and entry widgets to get the tip. #Get the tip tip_label = Label(w,text='What did you tip? ') tip_label.grid(row=1,column=0,sticky="W",padx=5,pady=5) tip = Entry(w) tip.grid(row=1,column=1,sticky="E",padx=5,pady=5)
-
在创建按钮之前,我们需要定义 tip_calculator 函数。它将从 tip 和 bill 中获取条目值,并将这些值转换为整数(条目通常是字符串)。接下来,我们要计算小费的百分比。
#Tip calculator function def tip_calculator(): t = tip.get() t = int(t) b = bill.get() b = int(b) percent = (t * 100) / b percent = int(percent)
-
让我们根据“percent”的值格式化一个适当的字符串。
if((percent >= 10) and (percent <= 15)): string = '{}%. You tipped Okay!'.format(percent) elif((percent >= 15) and (percent <= 20)): string = '{}%. That was a good tip!'.format(percent) elif(percent >= 20): string = '{}%. Wow, great tip! :)'.format(percent) else: string = "{}%. You didn't tip enough :(".format(percent)
-
最后,让我们创建一个 Tkinter 字符串变量,并在其中设置格式化字符串,然后用该文本创建一个标签,并将其放在屏幕上。
str_var = StringVar() str_var.set(string) label = Label(w, text=str_var.get()) label.grid(row=3,column=0,padx=5,pady=5)
-
最后,让我们创建一个按钮,让它在被点击时调用函数。
#Enter button button = Button(w,text='Enter',command=tip_calculator) button.grid(row=2,column=0,sticky="E",padx=5,pady=5) w.mainloop()
让我们运行程序,我们会得到这个(图 16-27 )。
图 16-27
小费计算器应用
我们的应用运行完美!你可以通过添加颜色和字体来进一步美化它。
摘要
在本章中,我们看了如何使用 Tkinter 包在 Python 中创建桌面应用。我们学习了如何创建不同的小部件,包括按钮、标签、复选框、单选按钮和菜单。我们还学习了框架。然后,我们学习了如何设计小部件的样式,以及当小部件被点击时如何执行命令。最后,我们学习了如何使用 pack()和 grid()几何方法在屏幕上组织小部件。
在下一章,让我们学习当点击、鼠标点击和键盘按下等事件在我们的小部件上发生时执行功能。**
十七、项目:Tkinter 井字棋
在前一章,我们学习了 Tkinter 的基础知识。我们学习了如何用 Tkinter 创建按钮、标签、框架、菜单、复选框、单选按钮等等。我们还学习了如何设计我们的窗口小部件,并让我们的窗口小部件根据事件(点击、鼠标移动、键盘按压等)来做事情。).最后,我们学习了如何用画布画画。
在这一章中,让我们应用我们在上一章中学到的知识,创建我们的第一个大项目:井字棋!我们还将了解事件,并将它们绑定到我们的小部件。
绑定事件–让您的应用充满活力!
在上一章中,我们学习了很多关于 Tkinter 的知识。我敢肯定,你已经厌倦了学习所有的概念,你宁愿现在就创建一个项目。耐心听我说几分钟,好吗?让我们快速了解如何将事件绑定到我们的小部件,并开始玩井字棋。
那么,什么是绑定呢?好吧,让我们说你点击你的按钮(用你的鼠标左键),你想在这种情况下执行一个功能。你会怎么做?你可以使用“命令”,是的,但是如果你想区分鼠标左键和右键点击呢?根据点击了哪个鼠标键或者按了哪个键盘键打开不同的功能?
事件可以帮助您完成所有这些任务,甚至更多。
让我们先来看看按钮点击事件。让我们创建一些绑定,当鼠标左键和右键点击一个按钮部件时,这些绑定执行不同的功能。
from tkinter import *
w = Tk()
def left_clicked(event):
print('Left mouse button clicked')
return
def right_clicked(event):
print('Right mouse button clicked')
return
button = Button(w,text='Click here!')
button.pack()
button.bind('<Button-1>',left_clicked)
button.bind('<Button-3>',right_clicked)
w.mainloop()
请看前面的代码片段。我们创建了按钮,打包它,然后使用 bind()方法创建两个绑定。第一个参数表示我们希望绑定到按钮的事件,第二个参数是事件发生时需要调用的函数。
事件需要在引号中指定,
现在,在函数定义中,我们接受了一个参数 event,尽管我们没有从函数调用中发送任何参数。这怎么可能?好吧,每当一个事件被绑定到一个小部件时,你的程序自动发送一个事件对象到这个函数。这个“事件”会有很多关于刚刚发生的事件的信息。
例如,我们可以使用 event.x 和 event.y 找到鼠标左键单击的 x 和 y 坐标位置。
from tkinter import *
w = Tk()
def click(event):
print("X:{},Y:{}".format(event.x,event.y))
frame = Frame(w,width=200,height=200)
frame.pack()
frame.bind('<Button-1>',click)
w.mainloop()
现在,让我点击框架上的任意位置(图 17-1 )。
图 17-1
鼠标左键单击事件
我点击了中间的某个地方,结果是这样的:
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\tkPrograms.py
X:93,Y:91
那是 93 的 x 和 91 的 y。太好了。
同样,你也可以寻找键盘按键。为此,您需要使用
当您将鼠标光标移动到小部件上时,您可以使用
好了,现在你已经知道了事件是如何发生的,让我们开始玩井字棋吧!
井字棋–解释
到目前为止,我们只是在创建迷你项目。但是在现实世界中,你需要做的不仅仅是画几个形状或者运行一堆循环。在现实世界中,你将创建人们日常生活中使用的游戏和应用。
所以在这一章,我们将创建我们的第一个这样的游戏。让我们创建经典的井字棋。我们的应用看起来会像这样(图 17-2 )。
图 17-2
Tkinter 的井字棋
我们的游戏板有九个盒子,你可以在上面画画。有两个玩家:X 和 O,他们轮流在黑板上画画。如果一个玩家连续抽三张牌(垂直、水平或对角),那么这个玩家赢。如果没有人做到这一点,并且所有九个棋盘都被填满,那么游戏就是平局。
这是一个简单的游戏。我将介绍“messagebox ”,它将帮助您创建您在笔记本电脑程序中看到的消息弹出窗口。
设置Tkinter
像往常一样,让我们从导入 Tkinter 的所有内容开始。但是我们还需要导入 messagebox,因为当您使用*时,您只是导入外部的类和函数,而不是“一切”。
from tkinter import *
from tkinter import messagebox
让我们接下来设置我们的窗口。我将把我的窗口的标题改为“井字棋”。
w = Tk()
w.title('Tic Tac Toe')
创建全局变量
我们在函数一章中看到了全局变量,还记得吗?全局变量可用于跟踪多个函数中发生的变化。在这种情况下,我们需要多个全局变量。
例如,我们需要跟踪“turn”变量发生的总体变化,该变量计算玩家使用的回合数(井字棋总共提供九个回合)。
turn = 0
接下来,我们需要一个列表来记录谁在哪个盒子上玩过。这个列表将有九个预定义的条目,它们当前包含空字符串。我们将根据谁在哪个盒子上玩,用“X”或“O”来代替它们。
state = ['','','','','','','','','']
接下来,我们需要一个二维列表(一个更大的列表中的列表)来保存所有的获胜状态(图 17-3 )。我们将在每个玩家玩游戏后比较这些获胜状态,以检查是否有人赢得了游戏。
图 17-3
井字棋盒(编号)
请看前面的图像。在井字棋中,如果玩家在三个连续的盒子上画出他们的符号,无论是垂直的、水平的还是对角的,他就赢了。1,4,7 是第一个垂直获胜状态。1,2,3 是第一个水平获胜状态。1,5,9 是第一个对角线赢的状态,以此类推。
有三种垂直获胜状态、三种水平获胜状态和两种对角获胜状态。一共赢了八个州。
让我们将它们存储在我们的列表中。但是因为我们在这里使用列表,并且它们的索引从 0 开始,所以让我们将 1,2,3 转换为 0,1,2。对其余的获胜州进行同样的操作,您将得到如下结果:
winner = [[0,1,2], [3,4,5], [6,7,8], [0,3,6], [1,4,7], [2,5,8], [0,4,8], [2,4,6]]
最后,让我们创建一个变量“game”来存储游戏的状态。当我们开始游戏时,这将是真的,如果有人赢了,或者如果游戏以平局结束(所有九个盒子都用完了,但没有人赢),我们将把“游戏”的值改为假,这样就没有人可以在盒子上画画了。
game = True
创建按钮
我们需要九个盒子,玩家可以在上面“画画”,对吗?为什么不把事情简单化,创建按钮呢?我们可以让他们的文本从一个单倍行距的字符串开始,每次玩家玩的时候,我们可以把文本改成“X”或者“O”。那会有用的!
在我们创建按钮之前,让我们定义一个变量“font ”,它将存储按钮文本所需的字体(我们的玩家在按钮上“画”的内容)。“Helvetica”,20 为文本大小,“粗体”字体。
font = ('Helvetica',20,'bold')
接下来,让我们创建九个按钮,每个框一个。我们将文本设为单个空格,高度为 2,宽度为 4。让我们将创建的“font”变量分配给字体。
最后,我们将看到我们在函数一章中学到的“lambda”函数的一些实际应用。到目前为止,每当我们在按钮上使用 command 属性时,我们都不必向被调用的函数发送参数。
但是现在,我们需要发送两个参数:一个是被点击的实际按钮,另一个是被点击的按钮的编号(从 1 开始)。
如果你想在这样的事件中发送参数,你需要用 lambda 封装函数调用,如下所示。lambda 本身不需要任何参数,因为它现在是一个匿名函数。您的一行代码将是对 buttonClick()函数的函数调用,其中发送了参数 b1 和 1。
让我们对其余的按钮重复这个过程。让我们也将按钮平行地放置在网格中。这是正常的网格排列。
#9 buttons
b1 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b1,1))
b1.grid(row=0,column=0)
b2 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b2,2))
b2.grid(row=0,column=1)
b3 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b3,3))
b3.grid(row=0,column=2)
b4 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b4,4))
b4.grid(row=1,column=0)
b5 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b5,5))
b5.grid(row=1,column=1)
b6 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b6,6))
b6.grid(row=1,column=2)
b7 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b7,7))
b7.grid(row=2,column=0)
b8 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b8,8))
b8.grid(row=2,column=1)
b9 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b9,9))
b9.grid(row=2,column=2)
在按钮的顶部创建一个 buttonClick()函数定义,并在它上面放置一个 pass(这样就不会出现函数为空的错误)。我们将在下一部分用相关代码填充函数定义。
让我们运行程序,我们得到这个(图 17-4 )。
图 17-4
九个盒子–已创建
这是我们目前掌握的情况。很好!
当按钮被点击时,在它上面绘图
现在让我们定义 buttonClick()函数。这应该在我们创建按钮的文本块之上(函数调用规则之前的函数定义)。
我们将在这个函数中访问全局变量 turn、state 和 game,所以让我们先加载它们。
#When a button is clicked
def buttonClick(b,n):
global turn,state,game
接下来,在绘制特定的盒子之前,让我们检查一下这个盒子当前是否是空的。如果它被占用了(一个玩家已经在上面画过了),我们就不应该再在上面画了,相反,你的游戏会弹出一个错误信息。
还有,检查一下游戏是否还是真的(没人赢,九试还没用完)。
if b['text'] == ' ' and game == True:
如果条件成立,那么检查谁正在玩。玩家“X”开始游戏,由于我们从 0 开始“回合”,每当轮到 X 时,“回合”的值将是一个偶数。你知道怎么检查偶数,对吧?去吧。
#hasn't been clicked on yet
if turn % 2 == 0:
所以,如果轮到 X,那么将按钮的文本改为“X”,将 turn 的值增加 1,并将 state[n–1]的值改为“X”。为什么是 n–1?列表的索引从 0 开始,按钮的编号从 1 开始,所以在“状态”中使用它之前,我们需要将值减 1。
#player X's turn
b['text'] = 'X'
turn += 1
state[n-1] = 'X'
当你在一个盒子上画图的时候,调用 winner_check()函数并发送“X”作为参数。我们将很快定义 winner_check()函数。如果你和我一起编码,现在,只需要在函数中输入 pass,这样你就不会因为没有定义它,而是调用它而得到错误。另外,在 buttonClick()函数之上创建 winner_check()函数,因为我们是从 buttonClick 调用的。
#winner check
winner_check('X')
好了,现在做完了,我们来检查一下 turn 是不是偶数,也就是说,是不是轮到 O 了。如果是,按照前面的方法做,但是只对“O”做。
elif turn % 2 == 1:
#player O's turn
b['text'] = 'O'
turn += 1
state[n-1] = 'O'
winner_check('O')
让我们运行一下我们目前所拥有的,看看我们是否能在我们的盒子上“画”出来(图 17-5 )。
图 17-5
盒子上的“画”
是的,我们可以!
最后,检查“else”条件。要么游戏已经结束,要么有人已经在盒子上画了,你不想重复。
在 messagebox 中,有一个 showinfo 方法,可以用来打印消息。让我们利用这一点。
如果“游戏”变量为假(游戏结束),打印“游戏结束!开始新游戏。如果盒子已经被画出,打印“这个盒子被占用了!”。
else:
if game == False:
messagebox.showinfo('showinfo','Game over! Start a new game.')
#because even when the game is over, the buttons will be occupied, so check for that first
elif b['text'] != ' ':
messagebox.showinfo('showinfo','This box is occupied!')
让我们检查错误框现在是否工作(图 17-6 )。
图 17-6
箱子被占了
我试着在一个被占用的盒子上画画,弹出了这条消息。太好了。另一个条件现在不相关,因为我们还没有检查赢家,所以游戏还不会“结束”。
看起来这个项目快结束了,对吗?我们已经提取了。我们甚至创建了 winner_check()函数来进行下一步工作。但是我们真的完成了 buttonClick()吗?没有。
我们还需要检查抽签情况!如果 turn 的值大于 8(玩家玩过九次),而“game”的值仍然为真怎么办?如果“game”仍然为真,这意味着还没有人赢,因为当我们调用 winner_check()函数时,如果我们发现有人赢了,我们会立即将“game”更改为 False。
所以,我们没有回合,游戏仍然正确的唯一原因是因为我们打成了平局。让我们打印该消息并结束游戏(将“game”改为 False)。
#game ended on draw
if turn > 8 and game == True:
messagebox.showinfo('showinfo','The match was a Draw')
game = False
buttonClick()到此为止!咻。那很大。
让我们运行程序,并检查“绘制”条件是否有效(图 17-7 )。
图 17-7
这场比赛是平局
是的,它工作了!但是我们需要 winner_check()来使一切正常工作。
接下来我们来看看 winner_check()。
检查每个回合中是否有玩家获胜
每当玩家玩游戏时,我们需要检查该玩家是否在该回合赢得了游戏。这个函数接受玩家(“X”或“O”)作为它的参数。
#Every time a button is clicked, check for win state
def winner_check(p):
我们还要导入全局变量 state、winner 和 game,因为我们需要它们。
global state,winner,game
现在,我们需要循环访问获胜者。因此,对于循环的每次迭代,“I”都有一个“赢”状态列表。
对于每次迭代,让我们检查 state[i[0]]、state[i[0]]、state[i[0]]是否持有相同的 player 值(“X”或“O”)。
例如,第一个内部列表是[0,1,2],所以我们检查 state[0],state[1]和 state[2],如果它们都包含字符串“X”,则 plaly er“X”获胜。如果他们都持有“O”,“O”获胜。就这样!
for i in winner:
if((state[i[0]] == p) and (state[i[1]] == p) and (state[i[2]] == p)):
如果条件成立,那么创建一个字符串,基本上就是“X 赢了!”或者“O won!”并用它创建一条消息。最后,将“game”的值改为 False。
string = '{} won!'.format(p)
messagebox.showinfo('showinfo',string)
game = False
让我们现在运行我们的程序,我们得到这个(图 17-8 )。
图 17-8
x 赢了!
哇哦!有效!
“游戏结束”条件有效吗?让我关闭当前消息框,并尝试通过单击在其中一个空框上绘图(图 17-9 )。
图 17-9
游戏结束!
看那个!我们的“游戏结束!”刚刚弹出的消息。我们的游戏运行完美!
新游戏按钮
我们为什么不在游戏中加入一个“新游戏”按钮呢?现在,我们的游戏结束后就暂停了。我们必须再次运行程序来开始新的游戏。如果我们有一个可以重置一切的按钮,那就太好了,不是吗?
就这么办吧。让我们先创建一个按钮。
new = Button(w,text='New Game',command=new_game)
new.grid(row=3,column=1)
点击此按钮将执行 new_game()函数。
现在,让我们在“新建”按钮上方创建 new_game()函数。
在我们定义函数之前,让我们创建一个所有按钮的列表。我们将需要它来遍历按钮并清除它们(这样我们就可以再次在它们上面绘图)。
#create a list of the buttons so we can change their text
boxes = [b1,b2,b3,b4,b5,b6,b7,b8,b9]
我们的 new_game()函数需要全局变量 state、game、turn 和 box。我们需要导入状态、游戏和回合,这样我们就可以将它们重置回初始值。
#New game
def new_game():
global state,game,turn,boxes
让我们重新设置回合、状态和游戏。
turn = 0
state = ['','','','','','','','','']
game = True
最后,让我们遍历“框”,将每个框的文本值改为一个空格。
for b in boxes:
b['text'] = ' '
我们的节目到此结束!我相信你已经这样做了,但是如果你忘记了,在程序的末尾添加一个 mainloop()。
w.mainloop()
让我们现在运行程序,我们得到这个(图 17-10 )。
图 17-10
新游戏按钮
我们现在有了“新游戏”按钮。试着测试一下。效果非常好!
你觉得创建这个游戏有趣吗?我知道我很乐意创造它,也很乐意教你如何创造它。摆弄游戏。更改字体、颜色等。祝你一切顺利!
整个程序
现在你已经学会了如何在 Tkinter 中创建一个井字棋,下面是整个程序的编写顺序。供你参考。
from tkinter import *
from tkinter import messagebox
w = Tk()
w.title('Tic Tac Toe')
turn = 0
state = ['','','','','','','','','']
winner = [[0,1,2], [3,4,5], [6,7,8], [0,3,6], [1,4,7], [2,5,8], [0,4,8], [2,4,6]];
game = True
#Every time a button is clicked, check for win state
def winner_check(p):
global state,winner,game
for i in winner:
if((state[i[0]] == p) and (state[i[1]] == p) and (state[i[2]] == p)):
string = '{} won!'.format(p)
messagebox.showinfo('showinfo',string)
game = False
#When a button is clicked
def buttonClick(b,n):
global turn,state,game
if b['text'] == ' ' and game == True:
#hasn't been clicked on yet
if turn % 2 == 0:
#player X's turn
b['text'] = 'X'
turn += 1
state[n-1] = 'X'
#winner check
winner_check('X')
elif turn % 2 == 1:
#player O's turn
b['text'] = 'O'
turn += 1
state[n-1] = 'O'
player = 'X'
winner_check('O')
else:
if game == False:
messagebox.showinfo('showinfo','Game over! Start a new game.')
#because even when the game is over, the buttons will be occupied, so check for that first
elif b['text'] != ' ':
messagebox.showinfo('showinfo','This box is occupied!')
#game ended on draw
if turn > 8 and game == True:
messagebox.showinfo('showinfo','The match was a Draw')
game = False
font = ('Helvetica',20,'bold')
#9 buttons
b1 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b1,1))
b1.grid(row=0,column=0)
b2 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b2,2))
b2.grid(row=0,column=1)
b3 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b3,3))
b3.grid(row=0,column=2)
b4 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b4,4))
b4.grid(row=1,column=0)
b5 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b5,5))
b5.grid(row=1,column=1)
b6 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b6,6))
b6.grid(row=1,column=2)
b7 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b7,7))
b7.grid(row=2,column=0)
b8 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b8,8))
b8.grid(row=2,column=1)
b9 = Button(w, text=' ', width=4, height=2, font = font, command = lambda: buttonClick(b9,9))
b9.grid(row=2,column=2)
#create a list of the buttons so we can change their text
boxes = [b1,b2,b3,b4,b5,b6,b7,b8,b9]
#New game
def new_game():
global state,game,turn,boxes
turn = 0
state = ['','','','','','','','','']
game = True
for b in boxes:
b['text'] = ' '
new = Button(w,text='New Game',command=new_game)
new.grid(row=3,column=1)
w.mainloop()
摘要
在本章中,我们从 Python 中的注释以及如何创建单行和多行注释开始。然后我们继续讨论变量,如何创建它们,它们的命名约定,以及可以在其中存储什么。然后我们看了 Python 编程语言中大量可用的数据类型以及如何使用它们。然后我们看了 Python 中的类型检查,最后我们看了如何在 Python 中获取输入并在输出中显示它们。
在下一章,让我们深入研究字符串,如何创建和使用它们,以及 Python 为您提供的各种预定义的字符串方法。
十八、项目:使用 Tkinter 绘制应用
在前一章中,我们学习了如何用 Tkinter 创建井字棋应用。我们还学习了所有关于事件的知识,以及如何使用它们让我们的应用响应外部事件(鼠标点击、键盘按键等)。).
在这一章中,我们将学习所有关于使用“画布”在你的 Tkinter 屏幕上“绘画”的知识,并使用它来制作一个绘画应用。你可以用笔画画,画圆形/椭圆形、直线和正方形/长方形。您还可以更改笔的大小以及形状的轮廓颜色和填充颜色。这是一个简单,但完整的应用!
绘画应用–解释
我们的绘画应用将会非常棒!你将能够徒手画直线、正方形、长方形、椭圆形和圆形。你也可以从数百种不同的颜色中选择。酷吧?
一旦我们完成了,它看起来就像图 18-1 一样。
图 18-1
最终应用
我不是艺术家,所以请原谅我的基本图纸,但你可以看到这个应用是多么强大,对不对?最棒的是,这只是一个起点。您可以扩展此应用,添加更多功能,并将其变成您想要的任何东西。
分享给你的朋友,有绘画比赛,或只是玩得开心!
开始
先从导入 Tkinter 开始。像往常一样,让我们导入所有内容,但是这样做只会导入“外部”类。它不会导入内部的,比如颜色选择器。我们需要颜色选择器来为我们的应用创建调色板。那么,让我们也导入它。
from tkinter import *
from tkinter import colorchooser
现在,让我们创建并初始化我们的变量。要在屏幕上绘图,您需要坐标,即鼠标指针在屏幕上点击位置的 x 和 y 点。让我们创建 x 和 y 变量,并在开始时将它们分别赋值为 0。
我现在用了一种新的分配方式。让事情变得简单,不是吗?
x, y = 0,0
接下来,让我们创建一个变量“color ”,并从一开始就把它设置为 None(没有值)。你也可以让它成为一个空字符串。这个变量将在将来保存我们的形状的填充颜色。我们还需要一种颜色作为我们的“笔”或形状的轮廓,所以让我们创建一个可变的“轮廓”,默认为黑色。我们还需要一支笔的大小。默认情况下会是 1。
color = None
outline = 'black'
sizeVal = 1
设置屏幕
现在,让我们设置我们的屏幕。我们将默认设置屏幕的状态为“缩放”,因此它会扩展到全屏。此外,我们将配置我们的行和列,使第一个单元格(行 0 和列 0)扩展到屏幕的整个宽度和高度。我们可以将画布放在这个单元格中,这样它也可以扩展到全屏。
w = Tk()
w.title('Paint Application')
w.state('zoomed')
w.rowconfigure(0,weight=1)
w.columnconfigure(0,weight=1)
我们将权重设为 1,让程序知道这个特定的行和列应该扩展到它的最大容量。
让我们运行我们的程序,我们得到这个(图 18-2 )。
图 18-2
我们的 Tkinter 屏幕
太好了。
创建画布
现在,让我们创建画布。我们需要使用 Canvas 方法来做到这一点,并将其放置在窗口“w”中。让我们也使我们的画布的背景默认为“白色”。
#create a canvas
canvas = Canvas(w, background="white")
接下来,我将把画布放在第一行和第一列(0),并使它在所有方向(北、南、东、西)都具有粘性,这样它就可以向所有方向扩展并占据整个空间(这是我们目前的整个屏幕)。
canvas.grid(row=0,column=0,sticky="NSEW")
让我们现在运行程序,我们得到这个(图 18-3 )。
图 18-3
帆布
完美!我们现在有了我们的白色画布。
创建您的第一个菜单(形状)
如果你看了完整的应用,你会注意到我们有多个菜单可供选择。第一个是形状菜单。你可以选择用钢笔还是画线、正方形或圆形。让我们现在创建菜单。
你已经知道如何创建菜单。让我们创建一个包含所有菜单的主菜单。我们的“绘图选项”菜单将成为我们“主”菜单的第一个子菜单。让我们添加一个级联,并标记它。
main = Menu(w)
menu1 = Menu(main)
main.add_cascade(label='Draw Options',menu = menu1)
最后,让我们添加四个命令,“钢笔”,“直线”,“正方形”和“圆形”。但是我们需要将选择值发送给“select”函数,该函数将依次调用相关的函数来进行相应的绘制。让我们用λ来实现。我们要给我们的选项编号,钢笔是 1,线条是 2,正方形是 3,圆形是 4。
menu1.add_command(label='Pen', command=lambda: select(1))
menu1.add_command(label='Line', command=lambda: select(2))
menu1.add_command(label='Square', command=lambda: select(3))
menu1.add_command(label='Circle', command=lambda: select(4))
最后,让我们配置窗口的“主”菜单。将来,这一行应该出现在我们创建了所有四个菜单之后。
w.config(menu=main)
如果你现在运行你的程序,并尝试点击菜单项,你会得到一个错误,因为你的“选择”功能还没有定义,但你仍然会看到你的菜单,就像这样(图 18-4 )。
图 18-4
第一个菜单(绘图选项)
哇哦!第一步成功了!
让我们的抽奖选项发挥作用吧!
现在我们有了绘图选项菜单,让我们让它工作。让我们首先创建“选择”函数,它将画布与相关的鼠标点击绑定在一起。在菜单上创建这个函数(函数调用)。我们需要两种绑定。
对于手绘,我们需要一个
然后,我们需要一个
让我们现在做那件事。让我们以“选项”的形式接收我们的号码。如果 options 为 1,则取消绑定
def select(options):
if options == 1:
#selected Pen, create bind
canvas.unbind("<ButtonRelease-1>")
canvas.bind('<B1-Motion>',draw_line)
类似地,对于 2,解除绑定
if options == 2:
#selected line, create bind
canvas.unbind("<B1-Motion>") #so pen is no longer active
canvas.bind('<ButtonRelease-1>',draw_line)
对于 3,调用 draw_square 函数。
elif options == 3:
#selected square, create bind
canvas.unbind("<B1-Motion>")
canvas.bind('<ButtonRelease-1>',draw_square)
对于 4,调用 draw_circle 函数。
elif options == 4:
#selected circle, create bind
canvas.unbind("<B1-Motion>")
canvas.bind('<ButtonRelease-1>',draw_circle)
获取鼠标位置
在创建 draw_line 函数之前,我们需要获取鼠标位置。如您所知,我们可以使用我们的“事件”来实现这一点。因此,让我们在我们的函数之外创建另一个绑定(在菜单的正上方和函数定义的正下方),将任何鼠标左键点击绑定到画布。
所以,每次你的用户点击画布时,我们都要记录下背景中画布的 x 和 y 位置。
我们不会绘制任何东西,直到用户选择了一个绘制选项,但是我们仍然要做好准备,好吗?
canvas.bind('<Button-1>',position)
现在,定义绑定上面的函数。接收函数定义中的“事件”。让我们也加载全局 x 和 y 值,并将 event.x 和 event.y 值(鼠标单击的 x 和 y 坐标位置)赋给 x 和 y 全局变量。
在画布上单击鼠标左键,获取鼠标的当前位置。
def position(event):
global x,y
x,y = event.x,event.y
就这样!你可以打印出 x 和 y,看看这个函数的运行。让这成为我们的小活动,好吗?
让我们画出我们的线
现在,让我们创建一个函数,它将为我们的手绘绘制迷你线和直线。我们需要什么?
canvas 中有一个 create_line 函数,可以用来,是的,你猜对了,画直线!你只需要给出起点和终点的坐标点。您还可以指定“填充”,这实际上是线条的颜色。
我们将使用“轮廓”颜色,因为我们希望线条颜色和形状轮廓颜色一致。您也可以指定线条的宽度。让我们给 sizeVal 作为这个属性的值。
但是你需要小心你提到的坐标值。先提起点的 x,y 坐标,再提终点的 x,y 坐标。更重要的是,要在一个元组中提到所有四个值,否则会出现错误。
def draw_line(event):
让我们加载我们的 x 和 y 值,这是鼠标第一次点击的点,我们使用 position()函数不断计算。让我们也加载 sizeVal,它目前为 1。一旦我们写了让用户手动改变线条宽度的代码行,它就会自动更新。
global x,y,sizeVal
现在,开始的 x 和 y 位置是包含鼠标单击点的 x 和 y 位置(position()函数)。结束 x 和 y 位置是事件的 x 和 y 位置。
在手绘的情况下,每次拖动鼠标(同时仍然按下鼠标左键),我们都会为每一分钟的变化获得一个新的事件,以及新的 x 和 y 位置。
对于绘制直线,终点是释放鼠标按钮的时间。
canvas.create_line((x,y,event.x,event.y),fill=outline, width = sizeVal)
最后,让我们用事件的 x 和 y 值来更新 x 和 y 值。手绘的时候特别需要这个,这样就可以重新开始了。
x,y = event.x,event.y
让我们现在运行我们的程序。
当我们试图像这样在屏幕上画画时,什么也没有发生。为什么呢?我们还没有启动任何选项。但是,如果我选择钢笔或线条(从菜单中),我可以在画布上绘图(图 18-5 )。
图 18-5
徒手和直线
正方形和长方形!
现在让我们画正方形和长方形。过程类似。在 canvas 中有一个 create_rectangle 方法。再次给出元组内的开始和结束坐标。在这种情况下,你可以提到两种颜色,轮廓和填充颜色,最后是形状的宽度。
然后,让我们将当前事件的 x 和 y 值(鼠标释放)赋给第一个 x 和 y 值(鼠标左键单击)。
def draw_square(event):
global x,y,sizeVal
canvas.create_rectangle((x,y,event.x,event.y), outline=outline, fill=color, width = sizeVal)
x,y = event.x,event.y
就这样!让我们现在运行我们的程序。选择“正方形”,按住鼠标按钮,将其拖到您想要的点,然后释放按钮。你会得到一个正方形或长方形。试试看!
我就是这么做的(图 18-6 )。😛
图 18-6
正方形和长方形
漂亮的正方形和长方形!
圆形和椭圆形!
最后,让我们画圆和椭圆。还有一种方法叫做 create_oval。完美的椭圆形是圆形,对吗?你也需要给出这个方法的起点和终点。
您的起点是您按下鼠标按钮的时候,终点是您最后释放鼠标按钮的点的 x 和 y 值(鼠标释放事件)。
def draw_circle(event):
global x,y,sizeVal
canvas.create_oval((x,y,event.x,event.y), outline=outline, fill=color, width= sizeVal)
x,y = event.x,event.y
让我们运行程序,我们得到这个(图 18-7 )。
图 18-7
环
很好!我们已经完成了所有的绘图功能。我们快到了!
选择尺寸!
现在,让我们进入我们节目的第二个菜单。到目前为止,我们的线条和轮廓的宽度都太窄了。如果我们希望它们更厚呢?为此我们也需要选择。让我们创造它们吧!我将创建从 1、5、10 到 30 的尺码。1 是我们设置的默认值。
让我们为尺寸创建一个新的子菜单 menu2。将它放在 menu1 代码之后,但在菜单配置代码行之前。每个选项都将是一个大小,我将为每个选项的点击调用 changeSize 函数。我们将把大小作为参数发送给这个函数。
menu2 = Menu(main)
main.add_cascade(label='Select Size', menu = menu2)
menu2.add_command(label='1', command=lambda: changeSize(1))
menu2.add_command(label='5', command=lambda: changeSize(5))
menu2.add_command(label='10', command=lambda: changeSize(10))
menu2.add_command(label='15', command=lambda: changeSize(15))
menu2.add_command(label='20', command=lambda: changeSize(20))
menu2.add_command(label='25', command=lambda: changeSize(25))
menu2.add_command(label='30', command=lambda: changeSize(30))
现在,定义函数来改变大小。您可以将该函数放在 select()函数之后,或者您想要的任何地方,只要它在 menu2 的代码行(函数调用)之上。
这是一个非常简单的过程。让我们接收我们的大小,加载全局 sizeVal,并将我们的大小赋给 sizeVal。就这样!因为 sizeVal 是全局的,并且被加载到我们所有的绘图函数中,所以一旦我们改变了大小,下一次我们绘图时,新的大小将反映在该绘图中。
def changeSize(size):
global sizeVal
sizeVal = size
让我们检查一下这个是否有效!我准备把大小改成 15 后画一堆线(图 18-8 )。
图 18-8
更改轮廓的宽度
这些线条很粗。😄
很多很多颜色!
现在,让我们创建第三个菜单,让我们改变轮廓和填充颜色的图纸。
让我们创建一个 menu3,它只包含两个选项,一个用于更改线条颜色,另一个用于更改填充颜色,每个选项调用各自的函数。
menu3 = Menu(main)
main.add_cascade(label = 'Choose Color', menu = menu3)
menu3.add_command(label='Line Color', command = set_line_color)
menu3.add_command(label='Fill Color', command = set_fill_color)
现在,让我们定义这些函数。我们将使用我们的颜色选择器来创建我们的调色板。colorchooser 中有一个 askcolor 方法,可以在我们需要时打开调色板(在这种情况下,当单击“线条颜色”选项时)。这将在新窗口中打开。让我们为这个窗口设置一个标题:选择颜色。
def set_line_color():
global outline
getColor = colorchooser.askcolor(title="Choose color")
现在,你不能就这样使用 getColor。当我们选择一种颜色时,比如说红色,这是它在 getColor 中注册的格式:
((255.99609375, 0.0, 0.0), '#ff0000')
元组中的第一个值包含另一个保存 rgb 颜色值的元组(我们颜色的红、绿、蓝阴影)。元组中的第二个值包含我们刚刚选择的颜色的十六进制值。它们是一样的,你可以把它写成“红色”。这些只是你提及颜色的不同形式。你真的不需要了解它们或者记住它们。只要知道每个阴影有十六进制和 rgb 值,你可以使用,你的计算机可以识别。
现在,我们不能使用整个元组。我们只需要它的一个值。让我们检索第二个值并使用它,好吗?
outline = getColor[1]
现在,每次我们改变“线条颜色”,“轮廓”的值也会改变,这将反映在我们的下一个绘图中。
现在,让我们做同样的填充颜色。
def set_fill_color():
global color
getColor = colorchooser.askcolor(title="Choose color")
color = getColor[1]
这就是我们的颜色!让我们检查它是否工作,好吗?让我们点击“线条颜色”,看看调色板是否打开(图 18-9 )。
图 18-9
颜色!
有效!
现在,让我们选择我们的颜色(图 18-10 )。
图 18-10
最终应用,完成!
我们所有的颜色都非常完美!
我已经画完了!
好了,我们有了一个小小的绘画应用。我们已经心满意足了!但是如果我们想重新开始呢?我们需要一个选项来清空画布。让我们来创造吧!
首先,菜单。
menu4 = Menu(main)
main.add_cascade(label = 'Clear', menu = menu4)
menu4.add_command(label = 'Clear', command = clear_screen)
现在,clear_screen()函数。我们只需要一行代码:canvas.delete('all ')。这将删除画布上的所有内容。
def clear_screen():
canvas.delete('all')
这就是选项出现的方式(图 18-11 )。
图 18-11
清楚的
画一些东西,选择清除选项,看到一切都消失了!不过在你做之前先截图吧!
我们已经完成了我们的绘画应用!😮 最后,如果您还没有编写它,请编写主循环代码行,我们就完成了。
w.mainloop()
整个程序
现在,整个程序按照它应该被创建的顺序:
from tkinter import *
from tkinter import colorchooser
x, y = 0,0
color = None
outline = 'black'
sizeVal = 1
w = Tk()
w.title('Paint App')
w.state('zoomed')
w.rowconfigure(0,weight=1)
w.columnconfigure(0,weight=1)
#create a canvas
canvas = Canvas(w, background="white")
canvas.grid(row=0,column=0,sticky="NSEW")
def draw_line(event):
global x,y,sizeVal
canvas.create_line((x,y,event.x,event.y),fill=outline, width = sizeVal)
x,y = event.x,event.y
def draw_square(event):
global x,y,sizeVal
canvas.create_rectangle((x,y,event.x,event.y), outline=outline, fill=color, width = sizeVal)
x,y = event.x,event.y
def draw_circle(event):
global x,y,sizeVal
canvas.create_oval((x,y,event.x,event.y), outline=outline, fill=color, width= sizeVal)
x,y = event.x,event.y
def select(options):
if options == 1:
#selected Pen, create bind
canvas.unbind("<ButtonRelease-1>")
canvas.bind('<B1-Motion>',draw_line)
if options == 2:
#selected line, create bind
canvas.unbind("<B1-Motion>") #so pen is no longer active
canvas.bind('<ButtonRelease-1>',draw_line)
elif options == 3:
#selected square, create bind
canvas.unbind("<B1-Motion>")
canvas.bind('<ButtonRelease-1>',draw_square)
elif options == 4:
#selected circle, create bind
canvas.unbind("<B1-Motion>")
canvas.bind('<ButtonRelease-1>',draw_circle)
def position(event):
global x,y
x,y = event.x,event.y
def changeSize(size):
global sizeVal
sizeVal = size
def set_line_color():
global outline
getColor = colorchooser.askcolor(title="Choose color")
outline = getColor[1]
def set_fill_color():
global color
getColor = colorchooser.askcolor(title="Choose color")
color = getColor[1]
def clear_screen():
canvas.delete('all')
canvas.bind('<Button-1>',position)
#options
main = Menu(w)
menu1 = Menu(main)
main.add_cascade(label='Draw Options',menu = menu1)
menu1.add_command(label='Pen', command=lambda: select(1))
menu1.add_command(label='Line', command=lambda: select(2))
menu1.add_command(label='Square', command=lambda: select(3))
menu1.add_command(label='Circle', command=lambda: select(4))
menu2 = Menu(main)
main.add_cascade(label='Select Size', menu = menu2)
menu2.add_command(label='1', command=lambda: changeSize(1))
menu2.add_command(label='5', command=lambda: changeSize(5))
menu2.add_command(label='10', command=lambda: changeSize(10))
menu2.add_command(label='15', command=lambda: changeSize(15))
menu2.add_command(label='20', command=lambda: changeSize(20))
menu2.add_command(label='25', command=lambda: changeSize(25))
menu2.add_command(label='30', command=lambda: changeSize(30))
menu3 = Menu(main)
main.add_cascade(label = 'Choose Color', menu = menu3)
menu3.add_command(label='Line Color', command = set_line_color)
menu3.add_command(label='Fill Color', command = set_fill_color)
menu4 = Menu(main)
main.add_cascade(label = 'Clear', menu = menu4)
menu4.add_command(label = 'Clear', command = clear_screen)
w.config(menu=main)
w.mainloop()
摘要
在这一章中,我们学习了如何使用“画布”在屏幕上“绘画”,并用它来制作一个绘画应用。我们用钢笔画画,画了圆形/椭圆形、直线和正方形/长方形。我们还改变了你的笔的大小和形状的轮廓颜色和填充颜色。
在下一章,让我们回到我们最初的包,turtle
包。让我们用turtle
、记分牌等等创建一个成熟的蛇应用。这将是一次有趣的旅程。系好安全带。
十九、项目:turtle
贪食蛇游戏
在前几章中,我们深入研究了 Tkinter 。我们学习了如何在 Tkinter 中创建窗口小部件,设计它们的样式,让它们在事件发生时做一些事情,以及在画布上绘图。我们还着眼于创建两个大项目——一个井字棋和一个绘画应用。
本章我们回到turtle
。所有这些章节我们都在研究turtle
,但是我们从来没有创造出一个真实世界的应用。所以,让我们在本章中创建一个贪食蛇游戏。
贪食蛇游戏
这是一个非常简单的游戏。你有你的蛇,它在我们的游戏中被画成一个正方形。我们从它的头部开始,当你按下任何一个箭头键时,头部就会向箭头所指的方向移动。
然后,你有一个红色的,成熟的苹果,正好和你的蛇头一样大。它出现在随机的位置,引诱你的蛇头去吃它。
每当你的蛇接触到苹果时(我们假设它当时吃了苹果),你的苹果就会消失在蛇的胃里。蛇是一部分一部分长的(刚吃过,所以应该是长的吧?).另一个苹果出现在屏幕上的另一个随机位置。
蛇每吃一个苹果,记分牌就加 1。
但是如果蛇头撞上了屏幕的四面墙中的任何一面或者撞上了自己的身体(长这么大!),游戏结束!☹
够简单的游戏,不是吗?你玩过吗?我们的最终游戏看起来会像这样(图 19-1 )。
图 19-1
贪食蛇游戏
我们的蛇当时已经吃了六个苹果,长了六个身体部位(包括头在内有七个)。
那好吧。既然您已经知道了贪食蛇游戏是如何工作的,那么您一定对我们需要编写什么样的代码来实现这一切有一个简单的想法。别担心。我会详细解释一切。
此外,不要混淆你需要写每段代码的顺序。当我解释事情的时候,它可能看起来很混乱,但是我已经在这一章的结尾按照正确的顺序包括了整个代码。自己编游戏的时候可以参考一下。
我们开始吧!这将是一个稍微有点长,但非常有益的旅程!
导入所需的模块
这个游戏需要三个模块。你需要乌龟包来画蛇、得分和苹果。你需要随机包装,使苹果出现在随机的位置,这是游戏的主要方面之一。
最后,你需要“时间”包。我们以前见过这个包,它让一个循环或函数暂停一段指定的时间。我们现在需要它来让我们的蛇以可控的速度移动。如果我们不调整节奏,我们的蛇会在一眨眼的时间里离开屏幕。
import turtle
import time
import random
设置海龟屏幕
我们将设置一个海龟屏幕,步骤和我们通常使用的一样。将标题设为“贪食蛇游戏”,背景色设为“黑色”。
s = turtle.Screen()
s.title('Snake Game')
s.bgcolor('Black')
但是在本例中,我们将使用 setup()函数来设置屏幕的宽度和高度(以像素为单位)。我们需要一个指定的宽度和高度,这样我们就知道屏幕上的所有内容,这样我们就可以指定精确的坐标来移动我们的蛇。
s.setup(width = 500, height = 500)
最后,让我们去掉每当我们在屏幕上画东西时出现的动画。动画是漂亮的,是的,但是我们将会画这么多东西,画得太快了,以至于动画化每一幅画对我们的游戏来说都不是很好。
您可以使用 tracer()方法(在我们的屏幕中)并输入 0 来实现这一点。看那个!你已经在turtle
中学到了一堆新东西。
s.tracer(0) #gets rid of animation
现在,运行程序,你会得到一个像这样的黑屏(图 19-2 )。
图 19-2
游戏屏幕
创建并初始化所需的变量
我们已经在我们的节目中看到了这一点。无论何时你创建一个程序,你都需要一些贯穿整个程序的“全局”变量。我们也有一些。
有一个“蛇”列表,它将包含我们蛇的每一部分的“龟”。每当我们绘制一条蛇的一部分(包括头部)时,我们将创建一只新的乌龟,这样所有的乌龟可以一起工作,同时绘制整条蛇。通过将这些海龟存储在一个列表中,我们可以随时访问它们,并得到它们的位置(你会看到如何操作)。
snake = []
我们要做 20 码的。这是你的方块的宽度和高度(蛇头,蛇的部分,苹果)。我要把这个值设为常数。
size = 20
让我们还创建一个变量“key”来存储按下了哪个键:“u”表示上箭头键,“d”表示下箭头键,“l”表示左箭头键,“r”表示右箭头键。当我们开始游戏时,这个值将是一个空字符串。
key = ''
最后,让我们做一个“score”变量,并在开始游戏时将其值初始化为 0。
score = 0
画头像
现在我们已经初始化了变量,让我们画出我们的头,让它出现在我们的屏幕上。
我们将为此创建一个新的海龟(头)。使其速度为 0,形状为正方形,颜色为绿色。最后,将其移动到位置 0,0(屏幕中心)。
#Draw head
head = turtle.Turtle()
head.speed(0)
head.shape('square')
head.color('Green')
head.penup()
head.goto(0, 0)
让我们也将这个头添加到“蛇”列表中。因为列表是空的,所以它将占据列表的第一个位置。
snake.append(head) #get the first head
运行程序,告诉我你看到了什么。还是黑屏吗?我们的乌龟在哪里?!
好吧,我想我们看不到任何东西,因为有追踪器。我们去掉了动画,记得吗?这次我们需要一个游戏循环来纠正错误。
在 Pygame 中你会学到更多关于游戏循环的知识,但是现在,只要知道每个游戏都需要一个永不结束的循环(通常是 while 循环)在游戏还“开着”的时候运行。
现在让我们创建这样一个循环,并使用(我们屏幕的)update()方法在每次循环执行时更新屏幕。
while True:
s.update()
就这样!现在再次运行程序,你会在你的屏幕中间看到一个可爱的小蛇头(图 19-3 )。
图 19-3
蛇头
画第一个苹果
现在我们已经画了蛇,让我们在它的第一个随机位置画第一个苹果。为此我们需要另一只乌龟,我们打算给它取名为“苹果”。
#Draw first apple
apple = turtle.Turtle()
apple.speed(0)
apple.shape('square')
使它的颜色为红色,让我们把它移动到一个随机的位置。
apple.color('Red')
apple.penup()
阅读下面一行代码。我们正在生成一个介于–11 和 11 之间的随机数,并将其乘以 20。如果你把某个东西乘以 20,你就在创造 20 的倍数,这正是我们想要的,因为我们的蛇头每次移动都会向前移动 20 点。
如果我们的蛇必须获胜,它应该能够完全叠加苹果,因此苹果应该与蛇出现在同一条运动线上。我们需要 20 的倍数才能实现。
为什么是–11,11 的范围?嗯,你可以把它放大一点,也许是-11,12,所以实际范围是-11 到 11,但整个前提是苹果应该出现在屏幕内。
–11 * 20 等于–220。这是我们正方形左上角的 x,y 位置,然后是正方形,大小为 20。所以,我们正方形的右上角将是–240,对吗?
这就是它应该结束的地方。如果我们再向左移动,我们的苹果可能会消失。
aX = random.randint(-11,11)*20
aY = random.randint(-11,11)*20
最后,让我们来看看我们刚刚创建的随机 x 和 y 坐标。
apple.goto(aX,aY)
你有没有注意到我们的笔(头和苹果)总是“向上”?那是因为我们不会和他们一起抽签。这次乌龟(笔)将成为游戏角色,而不是他们的图画。
让我们运行程序,我们得到这个(图 19-4 )。
图 19-4
头和第一个苹果
太好了。我们有一个蛇头,固定在屏幕的中间,一个苹果出现在屏幕内的任意位置。
多次运行这个程序,你会注意到苹果每次都被画在不同的位置。酷吧?
现在,在程序的最后(在这一行之前添加下一行代码),添加以下内容:
s.mainloop()
这是为了确保在我们关闭屏幕之前,屏幕是打开的,所以在我们玩游戏的时候,提示不会出现在 Shell 中。
我的屏幕记录了我的箭头按压吗?
大多数游戏都有移动控制。我们要么使用操纵杆,要么使用键盘按键。我们的游戏很简单,所以我们会坚持使用键盘按键。
当我们按下箭头键时,我们能让我们的蛇动起来吗?向上、向下、向左或向右箭头键。
要让您的屏幕“监听”键盘按键,即知道按键被按下,请使用屏幕的 listen()方法。现在,你的屏幕正在监听。将这几行代码放在你画出第一个苹果和蛇头之后,但是在 while 循环(游戏循环)之前。
#Listen to the events and act
s.listen()
现在,当按键发生时,您可以使用 onkeypress()方法来调用用户定义的函数。这类似于我们在 Tkinter 中的工作方式,唯一的区别是我们的函数调用在我们寻找的“事件”之前。
我们的事件是“上”、“下”、“左”和“右”。这些是 onkeypress()函数所期望的值,所以将它们放在引号内,并且不改变大小写。你的函数可以是任何东西。我把我的设定好了,设定好了,设定好了,设定好了,设定好了。
s.onkeypress(set_up,'Up')
s.onkeypress(set_down,'Down')
s.onkeypress(set_left,'Left')
s.onkeypress(set_right,'Right')
现在我们已经调用了我们的函数,我们需要创建它们(否则我们会得到一个错误)。让我们定义一下 onkeypresses 上面的函数。每个函数将加载全局“key”变量,并将值更改为“up”、“down”、“right”或“left”。
但是我们需要记录一些东西。在贪食蛇游戏中,蛇不能向后移动,否则它们只会撞到自己的身体(从而结束游戏),所以我们需要检查用户是否试图向后移动。
例如,如果 key 的当前值是‘down ’,那么接下来我们不应该将该值更改为‘up’。忽略特定按键等等。
def set_up():
global key #so the global variable key can be used in a local context here
if(key != 'down'):
key = 'up'
def set_down():
global key
if(key != 'up'):
key = 'down'
def set_left():
global key
if(key != 'right'):
key = 'left'
def set_right():
global key
if(key != 'left'):
key = 'right'
好吧,我们已经正式改变方向了。但是如果我们现在运行这个程序,我们看不出有什么不同。按键。发生什么事了吗?没有。我们还没有编写让我们的蛇移动的代码!让我们接下来做那件事。
让我们的蛇头移动
所以,在贪食蛇游戏中,一旦我们设定了一个方向,蛇就会自动向那个方向移动,直到我们再次改变方向。所以基本上,一旦蛇开始移动,它会继续移动,直到撞到什么东西。
为了创建这种自动移动,我们将在游戏循环中调用 moveHead()函数。
while True:
s.update()
moveHead()
但是,我们不会就此止步。我们将在每次迭代时以 0.2 秒的延迟运行 while 循环,这样人眼就可以看到蛇在移动。
循环的每次迭代都在几微秒内执行。Python 和你的电脑就是这么强大,这么快。但是,这是一个游戏。我们需要人眼能看到的东西,所以让我们放慢我们的程序,好吗?每次迭代后让它休眠 0.2 秒。
time.sleep(0.2)
好了,现在我们完成了“while”循环,让我们创建 moveHead()方法来设置头部的 x 和 y 坐标。
我们将为每个函数调用连续改变头部的 x 和 y 坐标 20 点(这发生在 0.2 秒的延迟),因此头部每 0.2 秒向前移动 20 点(图 19-5 )。
图 19-5
游戏屏幕坐标
请看前面的插图。如果你想向左移动你的蛇,减少 X 的值,同时保持 Y 的值不变。若要向右移动,请增加 X 的值。若要向上移动,请增加 Y 的值(X 保持不变)。若要向下移动,请减小 y 的值。
够简单吗?现在让我们把它应用到我们的代码中吧!
#Make it move based on the set direction
我们不需要在这个函数中加载“key ”,因为我们没有改变/重新分配它的值。我们只是在找回它的价值。使用 xcor()和 ycor()方法检索“头”龟(我们游戏中的蛇头)的当前 x 或 y 坐标。现在你知道为什么我们在列表中存储整个海龟了。这是为了让我们可以用它来获得很多关于它的信息(比如它的位置)。
增加或减少 x 或 y 坐标的“大小”(20 像素),因为这是我们的测量。我们的苹果也将出现在这些点上。
def moveHead():
if key == 'up':
head.sety(head.ycor() + size)
if key == 'down':
head.sety(head.ycor() - size)
if key == 'left':
head.setx(head.xcor() - size)
if key == 'right':
head.setx(head.xcor() + size)
现在,运行程序并尝试让蛇移动(图 19-6 )。会的!
图 19-6
移动蛇头
如果你试着向后移动,它不会。你为什么不试着自己看看?
让记分牌开始吧
现在我们的蛇头在动了,我们需要开始得分了。在我们让蛇每次“吃”一个苹果时都成长之前,让我们在屏幕的右上角绘制记分卡,这样我们就可以跟踪代码。将这段代码放在你画第一个苹果的代码下面。不要担心订单。我将把整个代码按照正确的顺序粘贴到本章的末尾。
我将为记分牌创建另一只海龟,因为我想让它在其他海龟工作的时候“画”分数。我将它定位在点 120,120(朝向右上角)。
#Draw the score
sc = turtle.Turtle()
sc.speed(0)
sc.pencolor('White')
sc.penup()
sc.goto(120,220)
首先,让我们用 Arial 字体写“分数:0”,20 分,粗体格式。随着游戏的进展,我们会更新数值。
sc.write('Score:0',font=('Arial',20,'bold'))
让我们最终隐藏这只乌龟,因为我们只需要它画的东西(不像“苹果”和“蛇”龟)。
sc.hideturtle()
运行程序,你得到这个(图 19-7 )。
图 19-7
创建记分板
是的,我们有记分牌了!伙计们,我们快到了!
我们的蛇在吃东西!
现在我们已经完成了我们的记分牌,让我们让我们的蛇吃。现在,如果我们的蛇碰到苹果,什么也不会发生。它会从旁边经过。它不会长大,我们的苹果也不会消失。
将接下来的几行代码(在函数定义之前)放在“while 循环”中,紧接在 s.update()方法之后。
所以,我们要检查我们的蛇的“头”和苹果之间的距离。如果该距离小于或等于 0,也就是说,如果蛇头完全与苹果合并,那么我们希望完成两件事情:
-
在另一个随机位置绘制的新苹果。我们将创建一个 drawApple()函数来完成这项工作。
-
蛇的尾部又多了一个身体部分。我们将创建一个新的“海龟”作为我们头部的身体部分。让我们创建一个 drawSnake()函数来完成这项工作。
Turtle 有一个 distance()方法,它检查一个对象是否在另一个对象的特定距离内。在我们的例子中,我们将检查我们的对象是否与另一个对象没有距离(完全叠加)。
#check for eating
if head.distance(apple) <= 0: #completely superimposed
drawApple()
#Create a new body part
drawSnake() #keep the tail - old head
让我们将 Score 的值增加 1,并调用 changeScore()方法,将 score 的当前值发送给它。此方法将更新记分卡。
score += 1
changeScore(score)
好了,这就是我们的 while 循环(现在)。我们现在需要定义三个函数(在调用“while”循环之上):一个绘制新的苹果,一个更改分数,下一个绘制新的蛇身体部分,因为它必须生长(它刚刚吃了东西,不是吗?).
#Draw apple function
按照和之前画第一个苹果时一样的步骤,得到下一个 x 和 y 坐标,然后把“苹果”龟移动到那个点。就这样!
def drawApple():
aX = random.randint(-11,11)*20
aY = random.randint(-11,11)*20
apple.goto(aX,aY)
现在,让我们画蛇的身体部分。每当我们的蛇头吃一个苹果,我们就要创造一个新的乌龟。所以,每次我们的 drawSnake()函数被调用时,一个新的 turtle“sBody”就会被创建。它将是方形的,颜色是绿色的,就像我们的蛇“头”一样。让我们将新的部分添加到“snake”列表中。
#draw snake
def drawSnake():
sBody = turtle.Turtle()
sBody.speed(0)
sBody.shape('square')
sBody.color('Green')
sBody.penup()
snake.append(sBody) #insert at the end
现在,让我们研究 changeScore 方法。让比分“海龟”sc 回到 120,220 的位置(起始位置)。让我们使用 clear()方法清除当前的内容,用当前的分数创建一个新的字符串,并重写文本。因为速度为 0,所以你不会看到任何实时发生的情况,所以对于我们人类的眼睛来说,它看起来就像记分牌在无缝地更新自己。
def changeScore(score):
sc.goto(120,220)
sc.clear()
string = 'Score: {}'.format(score)
sc.write(string,font=('Arial',20,'bold'))
sc.hideturtle()
让我们运行程序,尝试吃一些苹果(图 19-8 )。
图 19-8
创建新的蛇的部分(蛇吃)
嗯,记分牌似乎在正常更新。苹果确实消失了,并出现在一个新的位置。每次我们的蛇吃东西时,我们似乎都会得到新的“身体部分”,但它们没有连接在一起,也没有一起移动。并且,看起来新的身体部分正在彼此之上出现(在屏幕的中间),所以对我们的眼睛来说,我们只看到一个身体部分,而现在应该有两个(因为分数是 2)。
为什么呢?我们还没有要求他们这么做。你知道,在编程中,你需要对每一件小事进行详细的说明。所以,我们就这么做吧,好吗?
让整条蛇动起来
让我们通过调用 moveBody()来更新 while 循环。这个函数会将蛇的身体部分附加到头部,并使身体部分随之移动。
一旦我们完成了,我们的 while 循环将看起来像这样:
while True:
s.update()
#check for eating
if head.distance(apple) <= 0: #completely superimposed
drawApple()
#Create a new body part
drawSnake() #keep the tail - old head
score += 1
changeScore(score)
moveBody() #RIGHT HERE!
moveHead()
time.sleep(0.2)
确保对 moveBody()函数的调用是在 moveHead()函数之前的,这样它们在新的头部被绘制之前移动,这样看起来就像实际的移动。
现在,让我们定义 moveBody()函数。我们基本上要交换坐标。
因为我们在程序开始时附加了" head "," snake "列表的第 0 个索引将包含我们的" head "海龟,对吗?然后,我们附加了其他身体部分,也在蛇头后添加了乌龟。所以,为了模拟运动,我们需要这些身体部位移动它们的坐标。
现在,只有“Head”移动,因为这是我们编写的唯一代码(moveHead()函数)。所以,每次“头”移动到一个新的坐标,紧挨着它的身体部分(在“蛇”列表中)应该移动到头的旧坐标。现在,第一个身体部位旁边的身体部位应该移动到第一个身体部位的旧位置,以此类推,直到蛇的所有部位都向前移动了 20 个像素。
我们如何才能做到这一点?在编程中,每当你想交换值时,你需要一个临时变量来保存旧值。
因此,我们将创建一个临时列表 temp 来存储蛇身体部位的所有当前 x 和 y 坐标。
为此,我们将创建一个“for”循环来遍历“snake”列表。
def moveBody():
temp = []
#create a list of the current positions
让我们在列表的一个“项目”中只存储每个蛇部分的 x 和 y 坐标。我们将在一个列表中创建字典。
for i in snake:
x = i.xcor()
y = i.ycor()
temp.append({'x': x, 'y': y})
现在我们有了临时名单,让我们交换一下。我们不需要改变第零个索引中的项目的位置(这是我们的头,它自己移动),所以让我们创建一个 for 循环,从 1 开始循环到蛇的长度(1-(len–1)),这只是身体部分。
#Move entire body
for i in range(1,len(snake)):
因为“temp”已经有了整条蛇(包括头部)的“旧的”x 和 y 坐标,我们就使用它。所以,让我们让第 I 个位置的乌龟(从第一个索引开始)去第 I–1 个位置的乌龟的 x 和 y 坐标(这是我们的头,开始)。
就是这样!因为我们使用了一个字典来存储我们在 temp 中的值,所以我们需要像这样访问它们。因此,“temp”中第一项的 x 值将是 temp[0]['x'],依此类推。
snake[i].goto(temp[i-1]['x'],temp[i-1]['y'])
让我们检查一下我们的蛇现在是否移动(图 19-9 )。
图 19-9
让整条蛇动起来
它完美地移动和生长。哇哦!
现在,游戏的最后一部分。碰撞检查!
碰撞检查
在为下一次睡眠移动头部之前,我们需要做碰撞检查,这样下一次移动就不会发生。我们将调用 checkCollision 函数,如果有冲突,它将返回 True,如果函数调用的结果确实为 True,我们将打破游戏循环(while loop)。更新后的 while 循环如下:
while True:
s.update()
#check for eating
if head.distance(apple) <= 0: #completely superimposed
drawApple()
#Create a new body part
drawSnake() #keep the tail - old head
score += 1
changeScore(score)
moveBody()
moveHead()
#Before moving the head for the next round, check for collision
if checkCollision():
break
time.sleep(0.2)
例如,如果我们将碰撞检查放在其他地方,在身体移动之前,我们可能会在游戏中看到不一致。例如,尝试在 moveBody()和 moveHead()之间放置碰撞检查。乍一看,这似乎合乎逻辑,但通过这样做,你正在创建一个身体,移动它,但随后在你移动头部的 之前立即检查碰撞 。这将导致身体碰撞,因为现在你的第一个身体部位和你的头在同一位置。
因此,在检查碰撞之前,让我们完全移动我们的蛇。
现在,让我们定义碰撞检查函数。这个函数将加载全局“key”变量,因为我们要把它改回一个空字符串,所以移动会暂时停止。
我们还将创建一个变量“collision ”,并将其默认值设为 False。
def checkCollision():
global key
collision = False
先检查一下有没有撞墙。很简单,真的。如果头部的 x 或 y 坐标大于 240 或小于–240,则碰撞为真。
#wall collision
if head.xcor() < -240 or head.xcor() > 240 or head.ycor() < -240 or head.ycor() > 240:
collision = True
现在,对于身体碰撞,让我们再次循环 1 到蛇列表的长度(只有身体部分,而不是头部)。如果头部的 x 和 y 坐标与蛇身体任何部分的 x 和 y 坐标相同,那么就发生了身体碰撞,碰撞再次成立。
#body collision
for i in range(1,len(snake)):
if head.xcor() == snake[i].xcor() and head.ycor() == snake[i].ycor():
collision = True
最后,如果碰撞是真的,那么让 key 再次成为空字符串(暂停移动)。游戏基本上结束了。如果 collision 不为真,那么什么都不会发生,下一次“while”循环将继续。
if collision == True:
key = '' #pause the movement
接下来我们需要做三件事:
-
暂停程序 1 秒钟,让用户意识到游戏已经结束。
-
将蛇(及其所有部分)和苹果从屏幕上移开,这样它就基本上“消失”了。
-
画一个“游戏结束”的信息。我们需要一只新的海龟来做这件事。我们将保留记分卡,以便用户知道他们最后的得分。
time.sleep(1) #pause for a bit so user registers what happened
让我们通过“蛇”循环,并将其所有部分移动到 2000,2000(基本上离开屏幕)。让我们也把苹果搬到一个更远的位置。
for s in snake:
s.goto(2000,2000) #make it go off the screen
apple.goto(2500,2500)
We’re going to create an ordinary Turtle, move it to the point -170,0 and draw ‘GAME OVER’ in white.
#game over message
game = turtle.Turtle()
game.penup()
game.goto(-170,0)
game.pencolor('white')
game.write('GAME OVER!',font=('Arial',40,'bold'))
game.hideturtle()
return collision
最后,让我们将碰撞返回到调用函数。就是这样!我们已经完成了我们的游戏!
让我们检查一下碰撞是否有效,好吗?
先检查一下有没有撞墙(图 19-10 )。
图 19-10
壁碰撞
是的,它工作了。
现在进行车身碰撞(图 19-11 )。
图 19-11
身体碰撞
那边有一条盘绕的蛇!
在提到的 1 秒钟延迟后,一切都消失了,我们只剩下记分牌和“游戏结束”的消息。如果用户想再次玩,他们必须再次运行程序(图 19-12 )。
图 19-12
游戏结束消息
咻!时间很长,但绝对值得!我希望你和我一起创作这个游戏时有很多乐趣。我知道我做到了!
整个代码
现在,正如承诺的那样,整个代码:
#import the required modules
import turtle
import time
import random
#setup the screen
s = turtle.Screen()
s.title('Snake Game')
s.bgcolor('Black')
s.setup(width = 500, height = 500)
s.tracer(0) #gets rid of animation
#create and assign the required variables
snake = []
size = 20
key = ''
score = 0
#Draw the head
head = turtle.Turtle()
head.speed(0)
head.shape('square')
head.color('Green')
head.penup()
head.goto(0, 0)
snake.append(head) #get the first head
#Draw the first apple
apple = turtle.Turtle()
apple.speed(0)
apple.shape('square')
apple.color('Red')
apple.penup()
#generate a random integer that's a multiple of 20
#multiples of 20 that doesn't go beyond the screen (250,-250)
aX = random.randint(-11,11)*20
aY = random.randint(-11,11)*20
apple.goto(aX,aY)
#Draw the scoreboard at the beginning
sc = turtle.Turtle()
sc.speed(0)
sc.pencolor('White')
sc.penup()
sc.goto(120,220)
sc.write('Score:0',font=('Arial',20,'bold'))
sc.hideturtle()
#Change the direction of the snake
def set_up():
#so the global variable key can be used in a local context here
global key
if(key != 'down'):
key = 'up'
def set_down():
global key
if(key != 'up'):
key = 'down'
def set_left():
global key
if(key != 'right'):
key = 'left'
def set_right():
global key
if(key != 'left'):
key = 'right'
#Make the snake move based on the set direction
def moveHead():
if key == 'up':
head.sety(head.ycor() + size)
if key == 'down':
head.sety(head.ycor() - size)
if key == 'left':
head.setx(head.xcor() - size)
if key == 'right':
head.setx(head.xcor() + size)
#make the new snake body move (if the snake has grown)
def moveBody():
temp = []
#create a list of the current positions
for i in snake:
x = i.xcor()
y = i.ycor()
temp.append({'x': x, 'y': y})
#Move entire body
for i in range(1,len(snake)):
snake[i].goto(temp[i-1]['x'],temp[i-1]['y'])
#Draw apple function
def drawApple():
#generate a random integer that's a multiple of 20
#multiples of 20 that doesn't go beyond the screen (250,-250)
aX = random.randint(-11,11)*20
aY = random.randint(-11,11)*20
apple.goto(aX,aY)
#Create a new snake part
def drawSnake():
sBody = turtle.Turtle()
sBody.speed(0)
sBody.shape('square')
sBody.color('Green')
sBody.penup()
snake.append(sBody) #insert at the end
#Update the score
def changeScore(score):
sc.goto(120,220)
sc.clear()
string = 'Score: {}'.format(score)
sc.write(string,font=('Arial',20,'bold'))
sc.hideturtle()
#Check for collision – wall & body
def checkCollision():
global key
collision = False
#wall collision
if head.xcor() < -240 or head.xcor() > 240 or head.ycor() < -240 or head.ycor() > 240:
collision = True
#body collision
for i in range(1,len(snake)):
if head.xcor() == snake[i].xcor() and head.ycor() == snake[i].ycor():
collision = True
if collision == True:
key = '' #pause the movement
time.sleep(1) #pause for a bit so user registers what happened
for s in snake:
s.goto(2000,2000) #make it go off the screen
apple.goto(2500,2500)
#game over message
game = turtle.Turtle()
game.penup()
game.goto(-170,0)
game.pencolor('white')
game.write('GAME OVER!',font=('Arial',40,'bold'))
game.hideturtle()
return collision
#Listen to the events and act on the required key presses
s.listen()
s.onkeypress(set_up,'Up')
s.onkeypress(set_down,'Down')
s.onkeypress(set_left,'Left')
s.onkeypress(set_right,'Right')
#The main game loop that keeps the game running
while True:
s.update()
#check for eating
if head.distance(apple) <= 0: #completely superimposed
drawApple()
#Create a new body part
drawSnake() #keep the tail - old head
score += 1
changeScore(score)
#Move the body first, and then the head to the new position
moveBody()
moveHead()
#Before moving the head for the next round, check for collision
#If there's a collision, stop the game loop – no more movement
if checkCollision():
break
#A delay of 0.2 seconds before each movement
time.sleep(0.2)
#Keep the screen open until the user closes it
s.mainloop()
摘要
在这一章中,我们用我们的turtle
包创建了一个贪食蛇游戏。我们学到了很多新东西,比如使用时间模块暂停你的程序一会儿,创建游戏循环,获取你的海龟的位置,移动你的游戏角色,碰撞检查,在 2D 游戏中记分,等等。
在下一章中,让我们来了解一下关于 Pygame 的一切。我们将学习如何在 Pygame 中创建简单的 2D 游戏,这是专门为制作游戏而创建的。
二十、成为 Pygame 的游戏开发者
在前一章中,我们用乌龟创建了一个贪食蛇游戏。
在这一章中,让我们学习一个简介 Pygame ,一个被广泛用于 2D 游戏开发的平台。让我们学习所有关于创建我们的角色,使用图像作为角色,设置和修改你的屏幕,使你的角色移动,碰撞检测,从枪中射出子弹,分数,文本,等等!
什么是Pygame
?
Pygame 是一个跨平台的平台,由多个 Python 模块组成。它是为编写视频游戏而设计的。当你开始时,它可能看起来很简单,但一旦你深入了解它,它就非常强大,你可以用它创建任何东西,从简单的基于文本的游戏到复杂的,复杂的,多玩家的世界游戏。
在这一章中,让我们学习一下 Pygame 的基础知识,因为探索它的全部特性和功能已经超出了本章的范围。
安装并导入Pygame
任何超出标准 Python 代码的东西都需要安装,我说的对吗?这也适用于 Pygame 。
但是问题不像 Tkinter 和 Turtle , Pygame 不会安装在你的标准 Python 安装中。所以,你需要单独安装。
要在你的 Python 安装中安装 Pygame ,进入你的命令提示符和你已经完成 Python 安装的文件夹(图 20-1 )。
图 20-1
打开命令提示符
在命令提示符下,键入以下内容:
pip install pygame
按 Enter 键并等待几秒钟。您应该会得到这样的消息(图 20-2 )。
图 20-2
安装 Python
就这样!Pygame 现已安装在您的系统中。接下来让我们在程序中使用它。打开 Python Shell 并创建一个新脚本。随便你怎么叫,就是别叫 pygame。
不像 Tkinter 和turtle
,你不能只是导入 pygame 就完事大吉。您还需要初始化库。使用 init()方法可以做到这一点。你的程序只有在初始化后才能运行。
import pygame
pygame.init()
就这样!我们已经导入了 Pygame ,并且已经准备好了!
设置您的游戏屏幕!
创作游戏的下一步是什么?到目前为止你已经创造了很多,那你为什么不猜呢?没错。一个屏幕。我们需要一个所有事情都发生的屏幕。
让我们现在做那件事。我将定义一个变量“screen”(您可以随意命名自己的屏幕),并使用 display.set_mode 方法来创建具有我想要的尺寸的屏幕。
不过,您需要在一个元组或列表中给出屏幕的宽度和高度。否则你会得到一个错误。
screen = pygame.display.set_mode((500,500))
现在,让我们运行我们的程序,看看我们得到了什么(图 20-3 )。
图 20-3
python 窗口
我们有我们的屏幕。喔!
但是试着关闭你的屏幕,你会发现你不能。这是因为与其他软件包不同, Pygame 需要特殊指令来关闭屏幕。因此,我们将梳理屏幕上发生的所有事件,选择与鼠标左键单击“x”(关闭)按钮相对应的事件,并要求 Pygame 在单击发生时“退出”。
够简单吗?开始吧。
如你所知,每个游戏都需要一个游戏循环。一个永无止境的循环,只有在游戏结束时才会结束。 Pygame 也不例外。我们将创建一个“while”循环,当单击关闭按钮时,该循环变为 false。
game = True
现在,我们将使用一个“for”循环来梳理屏幕上发生的所有事件。您可以使用 pygame.event.get()方法获取事件列表,并且可以遍历它们。对于每次迭代,检查 event.type 是否为 pygame。退出(我们正在寻找的关闭按钮点击)。如果是,将“game”设为 False,以便 while 循环停止执行。
while game:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game = False
一旦我们退出游戏循环,我们将使用 pygame.quit()方法关闭屏幕。
现在试着关闭屏幕。关门了吗?没错。
让你的屏幕漂亮
现在,让我们使我们的屏幕漂亮!我们为什么不从改变屏幕的标题开始呢?
您需要使用 display.set_caption 方法来实现这一点。将这几行代码放在创建屏幕的那一行下面(游戏循环的上面)。
pygame.display.set_caption('My first game')
运行程序,看看你会得到什么(图 20-4 )。
图 20-4
自定义您的屏幕
我们的标题变了!
我们的屏幕现在是黑色的。我们为什么不换颜色呢?为了设置我们的颜色,我们将使用 RGB 值。
r 代表红色,G 代表绿色,B 代表蓝色。这三种颜色称为原色,这三种颜色的不同深浅和组合构成了你随处可见的其余颜色。
所以,有了这三个值,我们就可以想出几乎任何颜色。这三种颜色的值从 0 到 255,其中 0 表示没有任何颜色,255 表示有颜色。
自然,(0,0,0)是完全没有颜色,会给我们黑色,(255,255,255)是完全有颜色,会给我们白色。
您可以通过以下网站找到您想在程序中使用的任何颜色的 RGB 颜色代码:
有很多其他网站给你同样的信息。在线搜索“颜色选择器”或“rgb 颜色代码”来查找它们。
现在我们已经了解了颜色是如何工作的,让我们用红色填充我们的屏幕。那就是 255,0,0(只有红色的完全存在)。
在“while”循环中,在我们查看事件的 for 循环下面,添加以下代码行:
screen.fill((255,0,0))
但是如果你现在运行这个程序,你不会看到变化。为什么会这样?嗯,屏幕并不是每次迭代都会更新。您需要使用 display.update()方法来更新您的屏幕。
pygame.display.update()
现在,再次运行你的程序,你会得到这个(图 20-5 )。
图 20-5
更改屏幕背景
我们的颜色变了!喔!
在屏幕上创造你的角色
您可以使用 draw 方法绘制线条、矩形(或正方形)、圆形或多边形。这些可以成为你的游戏角色。
划清界限相当容易。语法如下:
pygame.draw.line(screen,color,(x1,y1),(x2,y2),width)
您需要指定线条的绘制位置(屏幕)、颜色(RGB)、线条起点和终点的 x 和 y 坐标(元组中的每一对),最后是线条的粗细。
让我们在程序中尝试一下。将这一行代码放在 display.update()方法的上方,这样这一行代码就会更新到屏幕上:
pygame.draw.line(screen,(255,255,0),(50,50),(100,150),10)
运行程序,你会得到这个(图 20-6 )。
图 20-6
画直线
我们把线放在了我们想要的位置!
接下来,我们来看一个长方形。语法是这样的:
pygame.draw.rect(screen,color,(x,y,width,height),outline)
我们需要指定矩形左上角点的 x 和 y 位置及其宽度和高度。如果你提到相同的宽度和高度值,你会得到一个正方形。最后一个值表示您想要填充还是轮廓。如果您将轮廓设为 0,您将得到一个完全填充的矩形。任何其他值都会得到一个轮廓。让我给你看两者的例子:
pygame.draw.rect(screen,(153,255,102),(100,200,100,100),0)
运行程序,你会得到这个(图 20-7 )。
图 20-7
绘制矩形
现在,我们将轮廓设为 50(填充 50%)(图 20-8 )。
图 20-8
50%填充
现在,让我们画一个圆。语法是这样的:
pygame.draw.circle(screen,color,(x,y),radius,outline)
x 和 y 点是圆心的 x 和 y 坐标。然后,提及半径和轮廓(如果你不需要完整的填充)。
pygame.draw.circle(screen,(0,102,255),(300,200),50,0)
运行程序,你会得到这个(图 20-9 )。
图 20-9
画圆
很好!
最后,你可以画多边形(任意数量的线)。
pygame.draw.polygon(screen,color,((x1,y1),(x2,y2)...(xn,yn)))
我们先画一个三角形。
pygame.draw.polygon(screen,(128,0,0),((150,350),(50,450),(250,450)))
也许是五边形,下一个?
pygame.draw.polygon(screen,(253,0,204),((400,300),(300,300),(350,450),(450,450),(450,350)))
运行程序,你会得到这个(图 20-10 )。
图 20-10
绘制多边形
形状就是这样!现在,让我们看看图像。
让我们从零开始为我们的形象。这是一个非常简单的过程。你需要加载你的图像(一次,在你的游戏循环之外),并在你希望它出现的精确坐标上“blit”它,所以它在屏幕上得到更新。
指定图像所在的确切路径。如果你不想让事情变得复杂,把你的图片和你的 Python 文件放在同一个文件夹里,你只需要提到文件的名字,就可以了。
image = pygame.image.load('ball.png')
然后,使用“blit”将其显示在屏幕上。
while game:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game = False
screen.fill((255,0,0))
screen.blit(image,(200,150))
pygame.display.update()
运行程序,你会得到这个(图 20-11 )。
图 20-11
绘制图像
这就对了。我们的形象在这里。
移动你的角色
移动我们的角色相当容易。你只需要改变角色的 x 和/或 y 坐标,就大功告成了。如果你想要连续的移动,在游戏循环的每一次迭代中不断改变它。
让我们试着移动我们的球,好吗?
我想让它向下移动,直到它的 y 值达到 400(由于我们的图像的高度是 100,当它的 y 达到 400 时,它的底部会接触到屏幕),然后停止,好吗?就这么办吧。
让我们导入 pygame 和时间。这里我们需要时间模块,因为我们要减慢迭代的速度,这样人眼就可以看到球的运动。
import pygame
import time
pygame.init()
screen = pygame.display.set_mode((500,500))
image = pygame.image.load('ball.png')
game = True
我们将创建一个保存第一个值 150 的“y”变量。
y = 150
while game:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game = False
screen.fill((255,0,0))
让我们 blit 图像。
screen.blit(image,(200,y))
只要 y 不是 400,我们就让 y 值在循环的每次迭代中增加 1。
if y != 400:
y += 1
让我们更新屏幕,让程序在每次循环迭代之间休眠 0.005 秒。
pygame.display.update()
time.sleep(0.005)
pygame.quit()
就这样!运行程序(图 20-12 ,你会看到一个平滑的向下运动,直到球碰到屏幕底端。
图 20-12
移动你的角色
键盘按压事件
好了,我们现在可以移动我们的球了。但是,如果我们想根据用户输入来移动它,比如键盘输入事件,该怎么办呢?
假设我想根据用户在键盘上按下的箭头键向四个方向移动我的球。我该怎么做?
还记得我们在寻找退出事件时循环的事件吗?我们也可以对按键事件使用相同的循环。
寻找 KEYDOWN 事件,当用户在游戏屏幕上按下一个键时,它只记录和。当你寻找 KEYDOWN 的时候,你会得到一个事件字典。将它们放入变量中。让我们把我们的命名为“钥匙”。
要注册左箭头键,请搜索键[K_LEFT]。如果该值为真,则向左移动(x 减 1)。
要注册右箭头键,请搜索 keys[K_RIGHT],如果正确,则将 x 增加 1。
要注册向上箭头键,搜索 keys[K_UP],如果为真,则将 y 值减 1。
要注册向下箭头键,请搜索 keys[K_DOWN],如果为真,则将 y 值增加 1。
为了获得连续的运动,引入方向变量,它将根据你设置的方向连续增加或减少你的 x 或 y 值。
让我们为 x 和 y 设置一个初始值,方向变量为 0,因为此时球不动。
x = 200
y = 150
xd = 0
yd = 0
while game:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game = False
现在,让我们寻找我们的事件。如果用户希望将方向设置为向左,那么 xd 应该变为–1,而 yd 保持不变。遵循相同的逻辑,为其余的方向。
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
xd = -1
yd = 0
if event.key == pygame.K_RIGHT:
xd = 1
yd = 0
if event.key == pygame.K_UP:
yd = -1
xd = 0
if event.key == pygame.K_DOWN:
yd = 1
xd = 0
screen.fill((255,0,0))
现在,在 blit 图像和更新屏幕之前,将 xd 和 yd 值添加到当前的 x 和 y 值中。
x += xd
y += yd
screen.blit(image,(x,y))
pygame.display.update()
time.sleep(0.005)
pygame.quit()
现在,当你设定一个方向时,球将继续向那个方向移动,直到你改变它(就像在我们的贪食蛇游戏中一样)。
但是如果我们只想让屏幕随着键盘按键一起移动呢?当我们停止按箭头键时,我们希望球停止移动。
有一个 KEYUP 活动可以帮助你做到这一点。在 for 循环中,检查 KEYUP 事件是否已经发生,并在内部“if”语句中,检查当前事件是 LEFT、RIGHT、DOWN 还是 UP 事件。
如果是这样,停止改变 xd 和 yd 值(使它们为 0),你将停止移动。
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_UP or event.key == pygame.K_DOWN:
xd = 0
yd = 0
就这样!
迷你项目——弹跳球
在这个项目中,我们将创建一个在屏幕上上下跳动的弹力球。当它击中屏幕的顶部或底部时,它应该反转方向并像这样继续。够简单吗?让我们用 pygame 来做这件事。
-
让我们从导入 pygame 和 time 开始。
-
然后,让我们初始化 pygame 并创建我们的屏幕。它的宽度和高度都是 500。
import pygame
import time
- 现在,让我们创建一个变量 y,并把它设为 0。这是因为随着上下弹跳,唯一会改变的值是 y 值。
pygame.init()
screen = pygame.display.set_mode((500,500))
- 我们还需要一个“游戏”变量,该变量当前为真,但当用户关闭屏幕时将变为假。
y = 0
- 让我们也创建一个方向变量“d ”,它默认为 1。我们将球的 y 值增加 1(向上移动)和–1(向下移动)。这个变量会改变球的方向。
game = True
- 现在,让我们创建我们的游戏循环。
d = 1
- 首先,让我们创建退出条件。如果事件类型是 pygame。退出,让游戏变得虚假。
while game:
- 然后,让我们用白色填充我们的屏幕。
for event in pygame.event.get():
if event.type == pygame.QUIT:
game = False
- 然后,我们用 draw.circle 方法在位置 250,y(一开始是,250,0)画一个红球。它的半径是 25,是一个完全填充的圆,所以最后一个属性是 0。
screen.fill((255,255,255))
- 让我们使用 display.update 方法来确保每次循环运行时屏幕都得到更新。
#draw a ball
#circle draw function
#where you want to draw it, color of the circle, position, width
pygame.draw.circle(screen,(0,0,255),(250,y),25,0)
- 如果我们让游戏保持原样,我们的球会移动得太快以至于人眼看不到。所以,让我们放慢循环的迭代速度。每次迭代后会有 0.005 秒的延迟。
pygame.display.update() #update the screen in the output window
- 现在,让我们设置墙壁碰撞条件。当 y 为 488 时(由于我们的球的直径为 25,我们需要球的另一半可见,所以我们将其设置为 488 而不是 500),让我们减小 y 的值,因为我们需要球向上移动。所以 d 将会是-1。
time.sleep(0.005)
- 如果 y 是 12,那么增加 y 的值,“d”将是+1。
if y == 488:
d = -1
- 最后,一旦我们脱离了 if elif 语句,让我们用“y”的当前值加上“d”。
elif y == 12:
d = 1
y += d
pygame.quit()
就这样!运行该程序,你将拥有一个弹跳球(图 20-13 )。
图 20-13
弹跳球
摘要
在这一章中,我们学习了 pygame 的基础知识。我们学习了如何设置我们的游戏屏幕,设置游戏循环,创建我们的角色(形状和图像),让他们移动,检测墙壁碰撞,以及检测键盘事件。
在下一章,让我们应用本章所学的知识,再多一点,来创建一个太空入侵者游戏!
二十一、项目:太空射手与Pygame
在前几章,我们学习了 Pygame 的基础知识。我们学习了创建游戏屏幕、关闭屏幕、美化屏幕、创建角色、移动角色等等。
在这一章中,让我们应用我们到目前为止所学的,甚至更多,来创建一个太空射击游戏。您还将学习如何为游戏创建文本和记分卡。
太空射击游戏
这是一个非常简单的游戏。你有一艘更像枪的宇宙飞船。当你按下左右箭头键时,它可以向左或向右移动。
然后,你有你的敌人。三排敌人,总共 21 个,他们会朝飞船移动。如果他们击中飞船,游戏就结束了!
为了防止这种情况,飞船可以向敌人射击。它一次只能射出一颗子弹。子弹在每次射击后(当它击中敌人或屏幕的上壁时)重新加载,因此飞船可以再次射击。
子弹每击中敌人一次,你得一分,击中的敌人消失。如果你杀死了所有的 21 个敌人,他们会重新加载,你会得到一个新的三排 21 个敌人。重新开始射击,直到你输了!
看那个(图 21-1 )。敌人就在附近,所以我们需要清除那一排来活命。我们已经击中了两个敌人,我们的分数是 2。
图 21-1
决胜比赛
这是一个足够简单的游戏,有很多改进的潜力(更多的关卡,更快的速度,更多的子弹,更多的敌人),所以让我们开始吧!
导入所需的模块
我们需要 pygame 模块来创建游戏本身,还需要 time 模块来减慢角色的速度,使其足以被人眼看到。
import pygame
import time
初始化一切
我们来初始化 Pygame 及其字体包(写记分牌)。
pygame.init()
pygame.font.init() #To use text
接下来,让我们创建我们的游戏屏幕,并将标题设置为“太空射手”。
screen = pygame.display.set_mode((500,500))
pygame.display.set_caption('Space Shooters')
让我们也创建一个“font”变量来存储我们需要使用的字体,即字体类型“Arial”和大小 40。
font = pygame.font.SysFont('Arial',40)
我们需要两个游戏条件:一个在游戏结束(敌人击中飞船)时为真的“over”和一个在用户关闭窗口时为假的“game”。
over = False #Game over
game = True #Closed the game window
就这样!让我们运行程序,我们得到这个(图 21-2 )。
图 21-2
游戏屏幕
我们有屏幕了!
游戏循环
接下来,让我们创建我们的游戏循环。
while game:
让我们首先创建窗口“关闭”条件。你已经知道如何创建它了。
#Close window condition - Quit
for event in pygame.event.get():
if event.type == pygame.QUIT:
game = False
同时,让我们用黑色填充屏幕。当然,这不会有太大的区别,因为 pygame 屏幕的默认颜色是黑色。
screen.fill((0,0,0))
程序退出游戏循环后,关闭窗口:
pygame.quit()
不要担心代码序列。我将把整个代码按照它应该被写的顺序粘贴在这一章的末尾。
现在,再次运行程序并尝试关闭窗口。会有用的!
创造宇宙飞船
现在,让我们创建我们的飞船,并使它出现在屏幕上。
将这几行代码放在游戏循环上面。
#Create the spaceship
我要加载我为这个项目得到的 spaceship.png 图像。这是一艘漂亮的小飞船,指向上方。
spaceship = pygame.image.load('spaceship.png')
现在,让我们设定宇宙飞船的初步位置。水平居中,x 位置 250,y 位置 390(朝向屏幕底部)。让我们也将方向设置为 0 作为默认值。当我们使宇宙飞船移动时,我们可以增加或减少它。
sp_x = 250
sp_y = 390
sp_d = 0
要使飞船出现在屏幕上,在游戏循环中,在 for 循环下,包含以下代码行:
if over == False:
screen.blit(spaceship,(sp_x,sp_y))
如果游戏仍然是真的,那么将图像 blit 到我们设置的 x 和 y 坐标位置。
最后,更新显示:
pygame.display.update()
让我们运行程序,我们得到这个(图 21-3 )。
图 21-3
定位你的宇宙飞船
我们有自己的太空船。耶!
移动飞船
你已经知道如何让角色移动了,对吗?我们需要完成以下工作:
-
根据按下的箭头键,向右或向左移动飞船。
-
当用户停止按箭头键时,停止移动飞船。
在这种情况下,我们需要寻找两个事件:KEYUP 和 KEYDOWN。
在 KEYUP 中,我们需要寻找两个键:K_LEFT 和 K_RIGHT。
让我们回到我们的游戏循环和 for 循环,在这里我们遍历了屏幕上发生的所有事件,并包含了接下来的两个条件。
寻找 KEYDOWN 条件,如果“下”事件中按下的键是左键(左箭头键),那么空间方向减 1,这意味着飞船会向左(水平)移动。
如果按下的键是右箭头键,那么空间方向增加 1,表示飞船会向右(水平)移动。
if event.type == pygame.KEYDOWN:
#Make spaceship move
if event.key == pygame.K_LEFT:
sp_d = -1
if event.key == pygame.K_RIGHT:
sp_d = 1
现在,让我们让飞船停止移动,如果箭头键被释放。让我们寻找一个 KEYUP 事件,并检查释放的键是否是左右箭头键。
#Make spaceship stop if not moving
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
如果是,将飞船方向返回到 0,这样位置没有变化,它只是停在用户离开的地方。
sp_d = 0
但是我们不能就此止步。如果我们希望 sp_d 值在游戏循环的每一次迭代中都移动,我们需要在 for 循环之外将 sp _ d 值加到 sp_x 值上。
#Spaceship move condition
sp_x += sp_d
将前面的代码行放在飞船 blit 上面,并“更新”代码行。
现在,运行代码并尝试移动飞船。哇哦!真快。我真的控制不了我的飞船。为什么会这样?
嗯,我们没有间隔游戏循环迭代,是吗?让我们在每次迭代后暂停程序(游戏)0.005 秒。将这一行代码放在“显示”代码行之上。
time.sleep(0.005)
现在,运行整个程序,试着左右移动你的飞船,你会得到这个(图 21-4 )。
图 21-4
让飞船在箭头压力下移动
有效。没错。
创造和移动敌人
现在让我们转移敌人!我们需要三排七个敌人,总共 21 个。它们将具有相同的属性(图像),但唯一的区别是它们的位置。
让我们创建包含所有值的列表。一个保存图像,这样它可以在游戏循环中 blit,一个保存所有的“x”位置,一个保存所有的“y”位置,最后,一个保存敌人的运动(方向)。
#Create enemy
enemy = []
enemy_x = []
enemy_y = []
enemy_d = []
让我们也记录下活着的敌人的数量。计数器将从 0 开始,每击落一个敌人就加 1。当数字达到 21 时,我们要重置一切,再次画出三排新的敌人,让他们倒下继续游戏。
enemy_count = 0
现在,让我们设定敌人的 x 和 y 位置。为此,我们将创建一个从 0 到 20(范围为 21)的 for 循环。
对于第一行(从迭代 0 到 6),x 位置将从 0 开始,并以 70-0、70、140、210、280 等倍数增加。
y 位置将位于–60(远离屏幕,在顶部),但仍然靠近可见部分,因为这是第一行。
每个敌人的距离值都是 0.5,因为这是他们倒下的速度。
for i in range(21):
#Row 1
if i <= 6:
enemy.append(pygame.image.load('enemy.png'))
enemy_x.append(70 * i)
enemy_y.append(-60)
enemy_d.append(0.5)
看那个!为了创建 70 的倍数,我只是用“I”乘以 70,因为“I”无论如何都会取 0 到 6 之间的值。
现在,第二排有点棘手。我们仍然需要 x 值为 70 的倍数,但是我们不能再使用“I ”,因为,对于第二行,“I”将从 7 到 13。所以,让我们把“I”减去 7,同时乘以 70。
这组敌人的 y 值将会是–120,比第一行稍微靠后一点。
#Row 2
elif i <= 13:
enemy.append(pygame.image.load('enemy.png'))
enemy_x.append(70 * (i-7))
enemy_y.append(-120)
enemy_d.append(0.5)
同样,让我们用 70 乘以 I–14 得到第三行,也就是最后一行的 x 值,并将 y 值设为–180。
#Row 3
else:
enemy.append(pygame.image.load('enemy.png'))
enemy_x.append(70 * (i-14))
enemy_y.append(-180)
enemy_d.append(0.5)
就这样!我们已经确定了敌人的位置。让他们出现,然后倒下。
在游戏循环(while 循环)中,在你“blit”飞船之后,让我们创建另一个“for”循环,运行 21 次(0 到 20)。
就像我们在宇宙飞船上做的一样,如果游戏还没有结束,我们只会吸引敌人。
这里我们需要检查两个条件:
-
如果敌人的“y”位置超过 500(它已经到达屏幕的末端),那么让它回到–60 的“y”位置。够了。为什么?嗯,第一排会先消失,然后第二排,最后第三排。一切都在不断移动,所以如果我们只是将每一行移回–60,前一行的移动将补偿下一行在同一点的出现。
-
如果 y 位置还没到 500,那么我们需要把敌人下移。把敌人 d 的值加到敌人 y 的值上,然后把这个敌人传送到屏幕上。
#Draw enemies and make them move
for i in range(21):
if over == False:
#enemy wall collision
if enemy_y[i] >= 500:
enemy_y[i] = -60
else:
#Draw enemies
enemy_y[i] += enemy_d[i]
screen.blit(enemy[i],(enemy_x[i],enemy_y[i]))
就这样!我们的敌人现在应该行动了。让我们检查一下(图 21-5 )。
图 21-5
创造敌人
没错。我们有三排移动的敌人!
发射子弹
接下来,让我们发射子弹。我们需要做三件事:
-
在游戏循环之外创建子弹,但在用户开火(按空格键)之前不要 blit 它。
-
检查游戏循环中的“空格”按下事件(在遍历所有事件的 for 循环中,以及在我们进行 KEYDOWN 事件检查的“if”语句中),如果发生了,设置子弹的 x 和 y 位置并改变其方向。
-
最后,在 events“for”循环之外,但在游戏循环之内,将子弹 blit 到屏幕上(如果它已经发射)。让我们同时检查一下是否有撞墙的情况,如果子弹碰到了墙,就把它带回到原来的位置。
好吧。现在我们知道我们需要做什么,让我们写同样的代码。
我们将加载“bullet.png”图像,这将是我们的项目符号。首先,我们将子弹的 x 和 y 位置设置为–100,这样它就不在屏幕上了,玩家看不到。让我们也将移动值 bullet_d 设置为 0,这样就没有移动。
#create the bullet
bullet = pygame.image.load('bullet.png')
#place it off the screen to start with
bullet_x = -100
bullet_y = -100
bullet_d = 0
最后,我们将创建一个变量“fire”来保存子弹的状态。如果用户发射了子弹,这个变量的值将从 False(默认值)变为 True。
fire = False
现在,让我们注册“space”按键。转到游戏循环,在遍历所有事件的 for 循环中,查找注册 KEYDOWN 事件的“if”语句。在该语句中,键入以下内容:
注册 K_SPACE 新闻事件。只要“发射”值为假(子弹之前没有发射过),如果用户单击空格键,让子弹移动。
现在把“火”变成真的(因为子弹已经发射了)。将项目符号的 x 和 y 值定位到飞船的当前 x 和 y 值。最后,使 bullet_d 值为–2,这样它就会向上移动。
#Make bullet fire
if event.key == pygame.K_SPACE:
if fire == False:
fire = True
bullet_x = sp_x
bullet_y = sp_y
bullet_d = -2
现在,让我们把子弹上膛。
在 for 循环之外,在我们 blit 飞船的代码之上,但是在我们改变了飞船的 x 值之后(所以新的 x 值被赋给了子弹),如果“fire”为真,“over”为假(游戏仍然有效),blit 子弹。
#Fire bullet
if fire == True and over == False:
我们已经将 x 值设置为 bullet_x+12,这样它就从飞船后面消失了。
screen.blit(bullet,(bullet_x+12, bullet_y))
接下来,让我们将项目符号的 y 值增加 bullet_d 的值(在本例中减少,因为 bullet_d 的值将为–2)。
bullet_y += bullet_d
最后,我们来检查一下是否撞墙。一旦子弹到达屏幕顶部(y 为 0 或更小),如果“fire”值仍然为真(仍然发射),让我们将子弹的 x 和 y 值改回飞船的 x 和 y 值,并使 bullet_d 值为 0,于是它开始移动。让我们也将“fire”的值设为 False,这样子弹就不再“blit”到屏幕上,直到它再次被发射。
#bullet wall collision
if bullet_y <= 0 and fire == True:
bullet_x = sp_x
bullet_y = sp_y
bullet_d = 0
fire = False
运行代码,你会得到这个(图 21-6 )。
图 21-6
射出箭
我们的子弹现在能用了!
创建并显示记分板
现在我们已经有了我们所有的角色,他们正在按照我们想要的方式移动,让我们创建我们的记分牌,这样我们就可以在向敌人射击时显示分数。
让我们先创建我们的记分牌。
#Create scoreboard
“score”的值将从 0 开始。
score = 0
接下来,让我们创建另一个变量 score_text,它存储我们希望在游戏开始时显示的字符串,即 Score: 0。
score_text = 'Score: {}'.format(score)
最后,让我们使用 Pygame 中的“字体”选项来渲染这个 score_text。文本颜色将是(255,255,255),这是白色的。这是 RGB。我们已经谈过了。
score_board = font.render(score_text,False,(255,255,255))
如果我们现在运行程序,我们什么也看不到,因为我们还没有在游戏循环中渲染记分牌。让我们现在做那件事。
screen.blit(score_board,(350,0))
将前面的代码放在 time.sleep 代码行的上方。
让我们运行我们的代码,我们将得到这个(图 21-7 )。
图 21-7
记分板
我们有记分牌了,耶!
杀死敌人
现在,让我们创建当子弹击中敌人时杀死敌人的代码行。对于循环的每一次迭代,我们将不断地寻找子弹和所有 21 个敌人之间的碰撞。
因此,让我们打开一个“for”循环来实现这一点。将这个放在游戏循环中,在你“blit”所有敌人的下方。
for i in range(21):
现在,我们需要碰撞条件。这很简单。如果子弹和敌人之间的距离(最左上角的位置)小于或等于 55,我们就有碰撞。这将覆盖从左上角到敌人其余部分的任何一点的子弹。
为此,让我们从敌人的坐标中减去子弹的坐标(因为它们在屏幕的底部,所以更高)。让我们得到这个减法的绝对值,这样无论两个字符在哪里,我们只得到我们需要的“差”值,没有符号。
if abs(bullet_x+12 - enemy_x[i]) <= 55 and abs(bullet_y - enemy_y[i])
为什么是 bullet_x+12?那是因为我们在那个“x”点“blit”子弹。
如果发生碰撞,我们需要将子弹带回原位,并使子弹运动值 bullet_d 为 0。
#bring bullet back to position
bullet_x = sp_x
bullet_y = sp_y
bullet_d = 0
让我们也把“fire”设为 False,因为我们已经发射完子弹了。它完成了我们派它去做的事情。
fire = False
现在,在同一个“if”语句中,让我们打开更多的 if 和 else 语句,将敌人带回原位(而不是移动)。它会在那个位置等待,直到当前集合中的所有敌人都被杀死,这样三排敌人再次形成。
还记得我们在定位敌人时使用的条件吗?让我们用同样的方法来定位他们,这样一旦 21 个敌人都被杀死,他们就可以出发了。
#bring enemy back to position
if i < 7:
enemy_x[i] = 70 * i
enemy_y[i] = -60
elif i < 14:
enemy_x[i] = 70 * (i-7)
enemy_y[i] = -120
else:
enemy_x[i] = 70 * (i-14)
enemy_y[i] = -180
最后,让敌人的移动值为 0,来停止它的移动(等待其余的加入它),并增加敌人计数 1。
enemy_d[i] = 0
enemy_count += 1
当子弹击中敌人时会发生什么?敌人死亡,回到原来的位置。子弹也会回到原来的位置,但是分数也会增加!
让我们接下来做那件事。让我们增加分数,重新渲染。
#increase score
score += 1
score_text = 'Score: {}'.format(score)
score_board = font.render(score_text,False,(255,255,255))
就这样!我们现在可以杀死敌人了。让我们看看它是否有效,好吗?(图 21-8
图 21-8
杀死敌人
哇哦!我们现在可以杀死我们的敌人,我们的分数也相应增加!
关掉太空船!
最后,让我们为飞船和敌人创造一个碰撞的条件,这样我们就可以结束游戏了。将这几行代码放在您编写敌人-子弹碰撞代码行的代码下面。
过程是一样的。对于我们的游戏循环的每一次迭代,我们将循环通过所有的敌人,并检查他们是否有一个击中了我们的飞船。
#Enemy-spaceship collision
for i in range(21):
碰撞条件将是飞船和敌人的 x 和 y 值之间的差值,如果它们小于或等于 50,游戏结束。
if abs(sp_x - enemy_x[i]) <= 50 and abs(sp_y - enemy_y[i]) <= 50:
#game over
让“过”成真。如果 over 是真的,那么我们就不会把飞船和敌人(更不用说子弹)blit 到屏幕上了,记得吗?这意味着他们将从屏幕上消失,我们将只剩下记分牌。
#make everything disappear
over = True
现在让我们试试(图 21-9 )。
图 21-9
关掉太空船
是的,它工作了!
重新吸引敌人
在碰撞检查之后,我们需要检查用户是否杀死了所有的敌人。如果所有 21 个都从屏幕上消失了,我们需要将敌人计数值重置回 0,并使它们再次从屏幕顶部落下。
#Set enemy move condition
if enemy_count == 21:
for i in range(21):
enemy_d[i] = 0.5
enemy_count = 0
让我们运行程序,并检查这是否可行(图 21-10 )。
图 21-10
重新吸引敌人
看那个!我们有了第二排敌人,现在我们的分数是 23!O:
游戏结束!
最后,让我们在敌人击中飞船时写下“游戏结束”。当“结束”为真时写“游戏结束”,这意味着发生了碰撞。
#Game over
if over == True:
#Draw game over text
让我们创建一个新的游戏字体,字体类型为 Arial,字体大小为 80。让我们在我们想要的文本上呈现该字体。使颜色变白。最后,将它“blit”到屏幕上的位置 50,200(围绕屏幕的中心)。
game_over_font = pygame.font.SysFont('Arial',80)
game_over = game_over_font.render('GAME OVER',False,(255,255,255))
screen.blit(game_over,(50,200))
让我们运行我们的代码,我们得到这个(图 21-11 )。
图 21-11
屏幕上的游戏
哇哦!我们的游戏结束了!
很简单,不是吗?尝试一下,也许试着改进它(更多的级别,更多的难度,等等。).
整个代码
现在,这里是完整的代码,就像承诺的那样:
import pygame
import time
pygame.init()
pygame.font.init() #To use text
screen = pygame.display.set_mode((500,500))
pygame.display.set_caption('Space Invaders')
font = pygame.font.SysFont('Arial',40)
over = False #Game over
game = True #Closed the game window
#Create the spaceship
spaceship = pygame.image.load('spaceship.png')
sp_x = 250
sp_y = 390
sp_d = 0
#Create enemy
enemy = []
enemy_x = []
enemy_y = []
enemy_d = []
enemy_count = 0
#Position enemies - 3 rows of enemies
for i in range(21):
#Row 1
if i <= 6:
enemy.append(pygame.image.load('enemy.png'))
enemy_x.append(70 * i)
enemy_y.append(-60)
enemy_d.append(0.5)
#Row 2
elif i <= 13:
enemy.append(pygame.image.load('enemy.png'))
enemy_x.append(70 * (i-7))
enemy_y.append(-120)
enemy_d.append(0.5)
#Row 3
else:
enemy.append(pygame.image.load('enemy.png'))
enemy_x.append(70 * (i-14))
enemy_y.append(-180)
enemy_d.append(0.5)
#create the bullet
bullet = pygame.image.load('bullet.png')
#place it off the screen to start with
bullet_x = -100
bullet_y = -100
bullet_d = 0
fire = False
#Create scoreboard
score = 0
score_text = 'Score: {}'.format(score)
score_board = font.render(score_text,False,(255,255,255))
while game:
#Close window condition - Quit
for event in pygame.event.get():
if event.type == pygame.QUIT:
game = False
if event.type == pygame.KEYDOWN:
#Make spaceship move
if event.key == pygame.K_LEFT:
sp_d = -1
if event.key == pygame.K_RIGHT:
sp_d = 1
#Make bullet fire
if event.key == pygame.K_SPACE:
if fire == False:
fire = True
bullet_x = sp_x
bullet_y = sp_y
bullet_d = -2
#Make spaceship stop if not moving
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
sp_d = 0
screen.fill((0,0,0))
#Spaceship move condition
sp_x += sp_d
#Fire bullet
if fire == True and over == False:
screen.blit(bullet,(bullet_x+12, bullet_y))
bullet_y += bullet_d
#bullet wall collision
if bullet_y <= 0 and fire == True:
bullet_x = sp_x
bullet_y = sp_y
bullet_d = 0
fire = False
if over == False:
screen.blit(spaceship,(sp_x,sp_y))
#Draw enemies and make them move
for i in range(21):
if over == False:
#enemy wall collision
if enemy_y[i] >= 500:
enemy_y[i] = -60
else:
#Draw enemies
enemy_y[i] += enemy_d[i]
screen.blit(enemy[i],(enemy_x[i],enemy_y[i]))
#Bullet-enemy collision
for i in range(21):
if abs(bullet_x+12 - enemy_x[i]) <= 55 and abs(bullet_y - enemy_y[i]) <= 55:
#bring bullet back to position
bullet_x = sp_x
bullet_y = sp_y
bullet_d = 0
fire = False
#bring enemy back to position
if i < 7:
enemy_x[i] = 70 * i
enemy_y[i] = -60
elif i < 14:
enemy_x[i] = 70 * (i-7)
enemy_y[i] = -120
else:
enemy_x[i] = 70 * (i-14)
enemy_y[i] = -180
enemy_d[i] = 0
enemy_count += 1
#increase score
score += 1
score_text = 'Score: {}'.format(score)
score_board = font.render(score_text,False,(255,255,255))
#Enemy-spaceship collision
for i in range(21):
if abs(sp_x - enemy_x[i]) <= 50 and abs(sp_y - enemy_y[i]) <= 50:
#game over
#make everything disappear
over = True
#Set enemy move condition
if enemy_count == 21:
for i in range(21):
enemy_d[i] = 0.5
enemy_count = 0
screen.blit(score_board,(350,0))
#Game over
if over == True:
#Draw game over text
game_over_font = pygame.font.SysFont('Arial',80)
game_over = game_over_font.render('GAME OVER',False,(255,255,255))
screen.blit(game_over,(50,200))
time.sleep(0.005)
pygame.display.update()
pygame.quit()
摘要
在这一章中,我们用 Pygame 创建了一个太空射击游戏。我们在游戏中应用了前一章所学的知识,我们还学习了所有关于碰撞检测和在游戏屏幕上渲染文本的知识。
在下一章中,让我们来看看用 Python 进行 web 开发的概述。我们将简要介绍用 HTML 创建网页,用 CSS 设计网页,用 JavaScript 使网页动态化,以及在 Python 自己的 Flask 中创建第一个程序。
二十二、将 Python 用于 Web 开发
在前一章中,我们学习了如何用 Pygame 创建一个太空射击游戏。我们学习了射击角色、碰撞检测、在 Pygame 屏幕上渲染文本等等。
在这一章中,我们来看看用 Python 进行 web 开发。让我们简单看看用 HTML、CSS 和 JavaScript 创建网站,以及用 Python 的 Flask 创建你的第一个程序。
Python 和 web 开发
什么是 web 开发?你访问网站吗?脸书、网飞、亚马逊等等?你在网上使用的任何东西都属于网络开发。
它们是用属于 web 开发的一套独特的技术来创建和维护的。这是如何工作的,Python 在这里起了什么作用?
好吧,在我们开始之前,让我们谈一点关于 web 开发的主要技术。有 HTML、CSS 和 JavaScript。
HTML 是网站的组成部分。这是什么意思?你在网上看到的一切都是由 HTML 创建的。图像、文本、按钮,一切都来自 HTML。
现在 CSS 设计了所有的样式。它被称为“级联样式表”,你用 HTML 创建的元素(构建块)可以被设计(颜色、对齐等。)使用 CSS。JavaScript 让一切都变得动态。当你点击网站上的一个按钮时,会发生一些事情,对吗?也许另一个网站打开了,或者你只是得到一个弹出窗口,给你一些信息。JavaScript 允许你在你的站点上做类似的事情。
但是 Python 呢?它在 web 开发中处于什么位置?要理解 Python 在 web 开发中的作用,需要理解前端和后端 web 开发的区别。
前端 web 开发就是我们刚才谈到的:HTML、CSS、JavaScript,所有这些加在一起我们得到了你的网站面向用户的一端;也就是用户看到的。
后端 web 开发正好相反。这是用户看不到的:服务器端开发。大多数应用需要大量的信息传输和检索,我说的对吗?您在某个网站上有一个帐户,当您登录到该网站时,应该会检索到您的帐户详细信息。你在谷歌上搜索一些东西,他们会给你一个与你的搜索相关的网站列表。
所有这些信息检索和传输(你向某人发送聊天消息或电子邮件)都属于后端 web 开发,你需要使用像 Python 这样的后端技术来实现这一点。Python 有一个“文件”特性,还记得吗?这只是开始。在 Python 的帮助下,您可以创建数据库并将它们连接到您的 web 应用等等。
让我们快速看一下这些技术能为我们提供什么。这不是一个全面的章节。Web 开发,尤其是全栈 web 开发,是一个巨大的主题,需要一本自己的书来完整地涵盖。我将给你们举一些例子来说明这些技术是如何工作的,以便让你们有所了解。如果你对这个主题感兴趣,你可以选择在将来阅读它。
构建模块–HTML
正如我之前告诉你的,HTML,即超文本标记语言,是用来创建你的网络应用的构建模块的。你可以在记事本(或 notepad++)中编写你的 HTML 代码,但是当你保存文件时,保存为 filename.txt 或 filename.txt,而不是 filename.txt
一个 HTML 代码有两部分,头部和身体。“头”包含用户不可见的代码,比如标题,而“体”包含页面所有可见的部分,比如段落、图像和按钮。
现在让我们创建一个简单的 HTML 文件。打开一个记事本,也许可以把你的文件命名为 website.html,或者任何你想命名的名字。当您将文件保存为 html 文件时,您会注意到图标从记事本图标变为默认浏览器图标。
<!DOCTYPE html>
<html>
</html>
前面的代码是 html 文件的框架。一个 HTML 代码包含标签,有的是空的,有的是有开始和结束标签的(就是这样写的:)。指定我们在代码中使用 HTML5,HTML 的最新版本。
<html>...</html>
是根标签。它包含了整个代码。
<!DOCTYPE html>
<html>
<head>
</head>
<body>
</body>
</html>
这是你的头和身体标签。现在,让我们在标签中添加一个标题。
<!DOCTYPE html>
<html>
<head>
<title>My first website</title>
</head>
<body>
</body>
</html>
在浏览器中打开该文件,您将看到如图 22-1 所示的屏幕。
图 22-1
基本 HTML 网站
我们有我们的标题。完美!
如果要添加文本或元素,需要使用标签。让我快速列出一些重要的标签,这样我们就可以在我们的网站上使用它们。
<h1> </h1>
用于创建主标题。
<h2> </h2>
用于创建子标题。
您可以创建更多减小尺寸的标题(h3、h4、h5、h6),但常用的是 h1 和 h2。
<p> </p>
用于创建段落。
<button> </button>
用于创建按钮。
<a> </a>
用于创建您在网上看到的超链接(链接到其他网站和页面)。
<img>
用于创建图像。这是一个空标签,但是它需要属性来指定图像的位置。
所以,我想现在就够了。让我们在程序中使用它们。让我们为苏珊创建一个介绍页面。
<body>
<h1>My introduction</h1>
<p>Hello there! I'm Susan. I'm 8 years old. I have a puppy named Barky. I love him so much! :) </p>
<button>Click Me!</button>
<a href='google.com'>Look me up!</a>
<img src='susan.png'>
</body>
我们已经创建了一个标题、一个段落(如果你愿意,你可以创建更多)、一个按钮(还不能用,但已经创建好了)、一个到 Google 的链接(你可以链接到任何你想链接的地方),最后,我们显示了 Susan 的照片。
现在打开我们的网站,我们看到了这个(图 22-2 )。
图 22-2
添加到我们网站的各种元素
我们已经有了制作网页的材料!当然,按钮不起作用(等待 JavaScript),事情还不漂亮(CSS!),但是我们有我们的积木!
漂亮的东西——CSS
如果你想美化事物:添加颜色,对齐事物,等等,你需要 CSS。但是 CSS 是一个庞大的主题,所以我不会在这里面面俱到。让我给你们看一些例子。
要编写 CSS 样式,需要在标签中打开和关闭一个
调用您想要样式化的元素,并提及其中的样式属性和值,比如背景色:蓝色,就像这样。您需要用分号结束每个属性-值对,不像 Python 的代码行,缩进(或下一行)标志着一行代码的结束。
让我们将整个页面的背景颜色改为浅灰色。我们将为此调用 html 元素(整个页面)(图 22-3 )。
图 22-3
添加背景颜色
接下来,让我们将标题颜色更改为深绿色,将段落颜色更改为深红色。您需要使用“颜色”属性来实现这一点。
<head>
<title>My first website</title>
<style>
html {
background-color: lightgray;
}
h1 {
color: darkgreen;
}
p {
color: darkred;
}
</style>
</head>
刷新你的网页,你会看到这个(图 22-4 )。
图 22-4
用 CSS 定制(设计)你的网站
这就是基本的 CSS。正如我所说的,这是一个很大的话题,所以我不能在这里完全涵盖它。
前端动态–JavaScript
让我们试着在这一部分让我们的按钮动态化。JavaScript 是一种脚本语言,就像 Python 一样。唯一的区别是前端用 JavaScript,后端用 Python。
您可以使用<script></script>
标签来编写您的 JavaScript 代码,通常在标签内,这样整个网站在动态特性加载之前就加载了。
<body>
<h1>My introduction</h1>
<p>Hello there! I'm Susan. I'm 8 years old. I have a puppy named Barky. I love him so much! :) </p>
<button>Click Me!</button>
<a href='google.com'>Look me up!</a>
<img src='susan.png'>
<script>
</script>
</body>
JavaScript 包含变量、数字、字符串、布尔值、if else 语句、for 和 while 循环、对象以及我们刚刚在 Python 中介绍过的许多其他概念。但这两种语言之间存在差异,尤其是在语法以及如何编写或使用这些语言方面。我们不会在这里一一列举,但我们只列举几个。
您可以使用关键字“let”创建变量。
let variableName;
就像 CSS 一样,JavaScript 中的每一行代码都需要以分号结束。
您也可以给这些变量赋值。但是让我们不要看世俗的东西。让我们看看 JavaScript 的真正力量,它操纵你的 HTML 元素(改变它们的样式,让它们做事情,等等。)就在您的 JavaScript 代码中。
为此,让我首先为我的元素分配一个惟一的“id ”,如下所示:
<button id="btn">Click Me!</button>
这是唯一的 id,不能分配给任何其他元素。我可以使用这个 id 来设置这个特定元素的样式,或者使用 JavaScript 来检索它,如下所示:
<script>
let button = document.getElementById('btn');
</script>
我已经创建了一个变量“button ”,并从我的文档(HTML 文档)中检索了 id 为“btn”的元素,并将它放入变量中。JavaScript 是区分大小写的,所以大写字母也应该保留。
现在,我可以监听这个元素中的事件。我们要不要听一个“咔嚓”事件?我们要不要在你点击按钮的时候弹出一个警告框(就像t inter里的消息框一样)?
您需要在刚刚检索的元素上添加一个事件侦听器。这个侦听器将侦听“click”事件,并在事件发生时调用 buttonClick()函数。
<script>
let button = document.getElementById('btn');
button.addEventListener('click',buttonClick);
</script>
现在,定义调用上面的函数。在 JavaScript 中,我们不用“def”,我们用“function”来定义一个函数。要创建一个提醒,使用类似这样的东西:alert('你的消息');
<script>
let button = document.getElementById('btn');
function buttonClick() {
alert("Hello there! I'm Susan!");
}
button.addEventListener('click',buttonClick);
</script>
现在,让我们刷新页面,看看我们的按钮是否工作(图 22-5 )。
图 22-5
用 JavaScript 制作网站
看那个!我点击了我的按钮,弹出了一个警告框,信息是“你好!我是苏珊!”。很完美,不是吗?这就是 JavaScript 的力量。
Python 的Flask
要用 Python 创建后端,最好使用框架。我们已经看过 Python 的包和库,比如 Turtle 、 Tkinter 和 Pygame 。我们知道它们有多有用,以及它们在多大程度上增强了原始 Python 代码。这同样适用于 web 框架。
最著名的是 Django 和 Flask 。在结束本章之前,让我们看一个关于烧瓶的简单例子。你不能这样使用烧瓶。你需要安装它。
要安装它,请打开命令提示符,并键入以下内容:
pip install Flask
按回车键并等待一段时间。您应该会得到这样的成功消息(图 22-6 )。
图 22-6
安装闪存
现在,让我们创建一个简单的程序,在屏幕上显示我们的介绍性消息。打开一个脚本并命名。让我们将我们的命名为 hello.py。首先从我们的“Flask”框架导入 Flask 类。
from flask import Flask
然后,让我们在变量“app”中创建该类的一个实例。
app = Flask(__name__)
现在,我们需要创建一条路线。我们希望我们的页面出现在网站的“根”上,你知道当你键入 http://websitename.com
或类似的东西时,所以我的路径将是“/”。你可以做你的'/介绍什么的。
@app.route('/')
现在,创建一个函数,introduction,并返回你想在屏幕上显示的内容。不需要调用这个函数。
def introduction():
return "Hello, there! I'm Susan! I'm 8 years old. I have a puppy named Barky. I love him so much! :)"
最后,让我们为我们的网站设置一个主机和端口。这就是 web 开发人员在将他们的网站部署到网上(有实际网站名称的互联网)之前,如何在本地(没有互联网)测试他们的网站。常用的主机是 0.0.0.0,端口是 5000。
app.run(host='0.0.0.0', port=5000)
我们完了!让我们运行我们的程序。
该文件应保存在命令提示符打开所在的文件夹中。我的是 C:\Users\aarthi,所以我要把 hello.py 保存在那里。
现在,转到您的命令提示符并在 Shell 提示符中键入 python hello.py,然后按 Enter 键,您将得到这个(图 22-7 )。
图 22-7
运行您的烧瓶代码
现在,你可以点击这个链接看到你的网站:http://127.0.0.1:5000/
(图 22-8 )。
图 22-8
你的烧瓶网站
耶!我们的第一个烧瓶程序。
摘要
在这一章中,我们看了用 Python 进行 web 开发。我们简单看了一下用 HTML、CSS 和 JavaScript 创建网站,以及用 Python 的 Flask 创建你的第一个程序。在下一章,让我们用你在本书中学到的 Python 概念创建更多的迷你项目。
二十三、更多迷你项目
在前一章中,我们学习了使用 Python 进行 web 开发。我们简要了解了 HTML、CSS 和 JavaScript,并用 Flask 创建了您的第一个程序。在这一章中,让我们用你在这本书中学到的 Python 概念创建更多的迷你项目。
项目 23-1:带t inter的计算器
在这个项目中,我们将创建一个计算器应用,就像你在电脑和手机上看到的带有 Tkinter 的那个。我们开始吧!
-
让我们先导入 Tkinter 并创建我们的窗口。我将把 resizable 选项设置为 0 和 0,这样窗口就不能调整大小了。我还打算把标题设为‘计算器’。
-
现在,我将创建一个字符串变量( Tkinter 变量)来保存我们的表达式(需要计算)。我还创建了一个空字符串,最初用来存放表达式。我们稍后将使用“字符串”中的值设置 Tkinter 变量。现在,我们让它成为一个字符串,而不是整数或浮点数,因为我们可以使用 Python 中的 eval()方法来计算数学表达式,表达式可以是字符串的形式。
from tkinter import *
w = Tk()
w.resizable(0,0) #cant resize
w.title('Calculator')
- 现在,让我们创建我们的按钮。
e = StringVar()
calc = ''
首先,我将创建一个“进入”按钮。它将保存“e”,我们的 Tkinter 变量,让我们将文本对齐到“右”,并在顶部填充足够的外部填充(padx,pady)和内部填充高度(ipady)。
- 接下来,让我们创建一个框架,“按钮”,这将举行我们所有的按钮。我们也打包吧。
entry = Entry(w,font=('Arial',14,'bold'),textvariable = e, justify= RIGHT)
entry.pack(side=TOP, ipady = 7, padx = 5, pady = 5)
- 现在,让我们开始创建所有的按钮。它们的宽度为 13,高度为 2,我们将为 clear 按钮调用 clear_entry()方法,当单击“答案”或“等于”按钮时调用 get_answer()方法,或者调用 button_click()方法,将数字或运算符添加到表达式中。
buttons = Frame(w)
buttons.pack()
-
Now that we’ve created our buttons, we should have something like Figure 23-1.
图 23-1
计算器应用–布局
-
现在,让我们在函数调用(小部件)上方创建按钮。首先,button_click 方法。让我们加载我们的全局“calc”变量,并将所点击的数字或操作符(记住,我们是以字符串的形式发送的)与“calc”的当前值连接起来。就这样!
clear = Button(buttons,text='c',width=13,height=2,font=('Arial',10,'bold'), command=lambda:clear_entry())
clear.grid(row=0,column=0,padx=5,pady=5,columnspan=2)
answer = Button(buttons,text='=',width=13,height=2,font=('Arial',10,'bold'), command=lambda:get_answer())
answer.grid(row=0,column=2,padx=5,pady=5,columnspan=2)
num7 = Button(buttons,text='7', width=5, height = 2, font=('Arial',10,'bold'), command=lambda:button_click('7'))
num7.grid(row=1,column=0,padx=5,pady=5)
num8 = Button(buttons,text='8', width=5, height = 2, font=('Arial',10,'bold'), command=lambda:button_click('8'))
num8.grid(row=1,column=1,padx=5,pady=5)
num9 = Button(buttons,text='9', width=5, height = 2, font=('Arial',10,'bold'), command=lambda:button_click('9'))
num9.grid(row=1,column=2,padx=5,pady=5)
num_div = Button(buttons,text='/', width=5, height = 2, font=('Arial',10,'bold'), command=lambda:button_click('/'))
num_div.grid(row=1,column=3,padx=5,pady=5)
num4 = Button(buttons,text='4', width=5, height = 2, font=('Arial',10,'bold'), command=lambda:button_click('4'))
num4.grid(row=2,column=0,padx=5,pady=5)
num5 = Button(buttons,text='5', width=5, height = 2, font=('Arial',10,'bold'), command=lambda:button_click('5'))
num5.grid(row=2,column=1,padx=5,pady=5)
num6 = Button(buttons,text='6', width=5, height = 2, font=('Arial',10,'bold'), command=lambda:button_click('6'))
num6.grid(row=2,column=2,padx=5,pady=5)
num_mul = Button(buttons,text='*', width=5, height = 2, font=('Arial',10,'bold'), command=lambda:button_click('*'))
num_mul.grid(row=2,column=3,padx=5,pady=5)
num1 = Button(buttons,text='1', width=5, height = 2, font=('Arial',10,'bold'), command=lambda:button_click('1'))
num1.grid(row=3,column=0,padx=5,pady=5)
num2 = Button(buttons,text='2', width=5, height = 2, font=('Arial',10,'bold'), command=lambda:button_click('2'))
num2.grid(row=3,column=1,padx=5,pady=5)
num3 = Button(buttons,text='3', width=5, height = 2, font=('Arial',10,'bold'), command=lambda:button_click('3'))
num3.grid(row=3,column=2,padx=5,pady=5)
num_sub = Button(buttons,text='-', width=5, height = 2, font=('Arial',10,'bold'), command=lambda:button_click('-'))
num_sub.grid(row=3,column=3,padx=5,pady=5)
num0 = Button(buttons,text='0', width = 13, height = 2, font=('Arial',10,'bold'), command=lambda:button_click('0'))
num0.grid(row=4,column=0,padx=5,pady=5,columnspan=2)
num_dot = Button(buttons,text='.', width=5, height = 2, font=('Arial',10,'bold'), command=lambda:button_click('.'))
num_dot.grid(row=4,column=2,padx=5,pady=5)
num_add = Button(buttons,text='+', width=5, height = 2, font=('Arial',10,'bold'), command=lambda:button_click('+'))
num_add.grid(row=4,column=3,padx=5,pady=5)
- 最后,用 calc 的当前值设置 Tkinter 变量。这将使表达式出现在应用的输入框中。
def button_click(n):
global calc
calc = calc + n
- 接下来,对于 clear_entry 方法,我们将再次使“calc”成为空字符串,并将“e”设置为该字符串。
e.set(calc)
- 对于 get_answer 方法,让我们导入“calc ”,创建一个变量“ans ”,该变量将使用 eval()方法计算“calc”中的表达式,并将答案设置为“e ”,因此表达式将替换为答案。
def clear_entry():
global calc
calc = ''
e.set(calc)
- 最后,让我们将“ans”转换为一个字符串(计算后它将是一个整数或浮点值),并用答案替换“calc”中的表达式,这样我们就可以继续计算。
def get_answer():
global calc
ans = eval(calc)
e.set(ans)
calc = str(ans)
运行程序,你会得到这个(图 23-2 )。
图 23-2
最终计算器应用
就这样!一个非常简单的计算器。事实上,你可以做很多事情来改善这种情况。也许添加一些颜色,解决一些问题,或者添加更多的功能。例如,到现在为止,你可以一个接一个地点击两个操作符,这会给你一个错误。你为什么不创造一个“如果”条件来防止这种情况发生呢?
玩得开心!
项目 23-2:随机故事生成器
在这个项目中,让我们创建一个简单的随机故事生成器。我们将有一堆选项,关于我们的故事“何时”发生,我们的“角色”是谁,我们的“敌人”是谁,我们角色的“属性”是什么,以及代词(他或她或它)。最后,我们要写一个从这些选项中选择的故事,每次我们创建一个新的故事,我们都会得到全新的角色、事件和时间线。够有趣吗?我们开始吧!
-
让我们先导入我们的随机模块。
-
然后,我将创建我的选项。
when_ch = ['Once upon a time,','A long time ago,','Thousands of years ago,','Long long ago,'] character_ch = ['dragon','unicorn','fairy','elf'] pronouns_ch = ['he','she','it'] attributes_ch = ['brave','courageous','strong','smart','intelligent'] enemy_ch = ['witches','warlocks','dark elves'] saved_ch = ['the world', 'the Kingdom', 'everyone', 'the village']
-
最后,让我们定义一个 generate_story()函数,它加载我们在。然后,让我们使用 random 模块中的 choice()方法为这个特定的故事选择我们的选项。
def generate_story(): global when_ch,character_ch,pronouns_ch,attributes_ch,enem_chy,saved_ch when = random.choice(when_ch) character = random.choice(character_ch) pronouns = random.choice(pronouns_ch) attributes = random.choice(attributes_ch) enemy = random.choice(enemy_ch) saved = random.choice(saved_ch)
-
此外,如果我们的角色是一个精灵,我们需要用“an”和“a”来称呼其余的角色。
if character == 'elf': a = 'an' else: a = 'a'
-
最后,让我们用多弦创造我们的故事。
story = '''{} there lived {} {}. {} was very {}. {} fought against the {} and saved {}'. '''.format(when,a,character,pronouns.capitalize(),attributes,pronouns.capitalize(),enemy,saved)
-
现在,让我们把它打印出来。
import random
-
现在,对于函数调用,我将创建一个无限 while 循环,询问用户是否要创建一个新的故事。如果他们输入了“Y”或“Y ”,那么让我们调用 generate_story 函数。否则,让我们停止程序。
while True: create = input('Shall we create a new story? Y or N: ') if create == 'Y' or create == 'y': generate_story() else: break
print(story)
很简单,对吧?为什么我们现在不生成一堆故事呢?
= RESTART: C:\Users\aarthi\AppData\Local\Programs\Python\Python38-32\story_generator.py
Shall we create a new story? Y or N: Y
Thousands of years ago, there lived a unicorn. She was very strong. She fought against the dark elves and saved the world'.
Shall we create a new story? Y or N: Y
Thousands of years ago, there lived a dragon. She was very intelligent. She fought against the witches and saved the world'.
Shall we create a new story? Y or N: Y
Once upon a time, there lived an elf. It was very smart. It fought against the dark elves and saved the Kingdom'.
Shall we create a new story? Y or N: N
很好!虽然很简单。我相信你可以添加更多的选项,让这些故事更大或更随机。玩得开心!
项目 23-3:石头剪刀布游戏
让我们为这个项目创建一个石头剪子布游戏!
-
让我们先导入 Tkinter 和随机包。
#Rock, paper, scissors from tkinter import * import random
-
现在,让我们创建我们的窗口,将其背景颜色配置为白色,并使其不可调整大小。
w = Tk() w.configure(bg='white') w.resizable(0,0)
-
首先,我们需要一个包含标题的标签。
title = Label(w,text='Rock Paper Scissors', fg="red", bg="white",font=('Arial',45,'bold')) title.pack()
-
让我们也创建一个 u_option 变量,它现在是空的,但是以后会保存用户的选项。
-
让我们用这三个选项创建一个列表。
u_option = ''
-
现在,让我们创建其余的小部件。我们需要另一个标签,上面写着“选择一个”。
label = Label(w,text='Choose one', fg="green", bg="white",font=('Arial',25,'bold')) label.pack()
-
在那下面,我们需要一块画布来放置石头、纸和剪刀。让我们这样做,当用户悬停在画布上时,光标变成一只“手”。
canvas = Canvas(w,width=500,height=150,background='white') canvas.pack() canvas.config(cursor='hand2')
-
接下来,让我们使用 PhotoImage 方法加载我们的图像。你可以使用任何你想要的图像。我用了石头、纸和剪刀的插图。
options = ['rock','paper','scissors']
- 接下来,让我们将图像绘制到画布中,在我们想要的 X,Y 坐标位置。
img1 = PhotoImage(file="rock.png")
- 然后,让我们在该图像上创建一个 tag_bind。对于画布项目,我们需要 tag_bind,而不是 bind。我们的将是一个
绑定,用于鼠标左键点击,让我们调用 chose()方法,参数是刚刚被点击的项目。
rock = canvas.create_image(50,20,anchor=NW,image=img1)
我们将在这里使用 lambda,因为绑定需要在它们的函数定义中包含事件,而 lambda 本质上是一个函数定义,所以在这里包含“event”作为 lambda 的属性。
- 就这样!让我们为接下来的两张图片重复这个过程。
canvas.tag_bind(rock,'<Button-1>',lambda event:chose('rock'))
-
现在,让我们创建最初为空的标签,但稍后将保存我们想要的信息,关于用户的选择、计算机的选择和获胜者。
you_chose = Label(w,text='', fg="blue", bg="white",font=('Arial',25,'bold')) you_chose.pack() c_chose = Label(w,text='', fg="blue" , bg="white",font=('Arial',25,'bold')) c_chose.pack() winner = Label(w,text='', fg="brown", bg="white",font=('Arial',45,'bold')) winner.pack()
-
现在,让我们在小部件上创建 chose()函数。让我们导入 u_option 变量。
def chose(option): global u_option
-
如果 u_option 为空,这意味着用户第一次选择一个选项,我们准备好开始游戏了。我们把期权赋给 u_option。
if u_option == '': u_option = option
-
让我们也为我们的计算机选择一个随机选项,并把它放在 c_option 中。
img2 = PhotoImage(file='paper.png')
paper = canvas.create_image(200,20,anchor=NW,image=img2,)
canvas.tag_bind(paper,'<Button-1>',lambda event:chose('paper'))
img3 = PhotoImage(file='scissors.png')
scissors = canvas.create_image(350,20,anchor=NW,image=img3)
canvas.tag_bind(scissors,'<Button-1>',lambda event:chose('scissors'))
-
现在,让我们用我们的选择来配置 you _ chose 和 c _ chose。
you_chose.config(text='You chose {}'.format(u_option)) c_chose.config(text='Computer chose {}'.format(c_option))
-
接下来,我们来看看谁赢了。如果 u_option 和 c_option 的值相同,那就是平局。如果 u_option 是石头,那么 c_option 是剪刀用户赢,c_option 是纸用户输。同样,让我们创建其他条件,并为每个结果配置“winner”。
if u_option == c_option: winner.config(text='Draw!') elif u_option == 'rock': if c_option == 'paper': winner.config(text='You lose :(') elif c_option == 'scissors': winner.config(text='You win!') elif u_option == 'paper': if c_option == 'rock': winner.config(text='You win!') elif c_option == 'scissors': winner.config(text='You lose :(') elif u_option == 'scissors': if c_option == 'paper': winner.config(text='You win!') elif c_option == 'rock': winner.config(text='You lose :(')
-
最后,让我们创建我们的“新游戏”按钮。
new = Button(w,text='New Game',font=('Arial',20,'bold'),command=new_game) new.pack()
-
在按钮上方,定义 new_game()函数。我们先加载 u_option。现在,让我们配置我们的标签,让它们再次变成空的,让我们清空 u_option,让用户可以再次播放。
def new_game(): global u_option you_chose.config(text='') c_chose.config(text='') winner.config(text='') u_option = ''
-
就这样!让我们用一个主循环来结束程序。
c_option = random.choice(options)
w.mainloop()
现在,让我们运行程序(图 23-3 )。
图 23-3
石头剪刀布游戏
当用户点击一个选项时,他们会看到这个(图 23-4 )。
图 23-4
用户选择了一个选项
完美运作!
项目 23-4:用Pygame
弹跳球(从四面墙上)
在这个项目中,我们将创建一个从屏幕的四面墙上随机反弹的弹力球。当它碰到屏幕的四面墙中的任何一面时,它应该反转方向并像那样继续。够简单吗?让我们用 pygame 来做这件事。
-
我们先导入 pygame,random 和 time。
import pygame import random import time
-
然后,让我们初始化 pygame 并创建我们的屏幕。它的宽度和高度都是 500。
pygame.init() screen = pygame.display.set_mode((500,500))
-
现在,让我们创建一个变量 x 并把它设为 250,一个变量 y 并把它设为 0。这是因为我们想从点 250,0 开始反弹。
x = 250 y = 0
-
我们还需要一个“游戏”变量,该变量当前为真,但当用户关闭屏幕时将变为假。
-
让我们也创建 x 和 y 方向变量“xd”和“yd ”,它们默认为 1。我们将在范围(1 到 2)(向上移动)和范围(–1 到–2)(向下移动)内增加球的 x 或 y 值。这个变量会改变球的方向。
xd = 1 yd = 1
-
现在,让我们创建我们的游戏循环。
game = True
-
首先,让我们创建退出条件。如果事件类型是 pygame。退出,让游戏变得虚假。
for event in pygame.event.get(): if event.type == pygame.QUIT: game = False
-
然后,让我们用白色填充我们的屏幕。
while game:
-
然后,我们用 draw.circle 方法在位置 250,y(一开始是,250,0)画一个红球。它的半径是 25,是一个完全填充的圆,所以最后一个属性是 0。
#draw a ball #circle draw function #where you want to draw it, color of the circle, position, width pygame.draw.circle(screen,(0,0,255),(250,y),25,0)
-
让我们使用 display.update 方法来确保每次循环运行时屏幕都得到更新。
pygame.display.update() #update the screen in the output window
-
如果我们让游戏保持原样,我们的球会移动得太快以至于人眼看不到。所以,让我们放慢循环的迭代速度。每次迭代后会有 0.005 秒的延迟。
screen.fill((255,255,255))
-
现在,让我们设置墙壁碰撞条件。当 x 大于或等于 488 时(因为我们的球的直径为 25,我们需要球的另一半可见,所以我们将其设置为 488 而不是 500),让我们将 x 的值减少 1 到 2 之间的随机值,因为我们需要球向左移动(回到屏幕内部)。所以 xd 是-1。
if x >= 488: xd = -(random.randint(1,2))
-
如果 y > = 488,同样,减小 yd 的值。
elif y >= 488: yd = -(random.randint(1,2))
-
如果 x < = 12,则增加 xd,如果 y 小于或等于 12,则增加 yd。
elif x <= 12: xd = (random.randint(1,2)) elif y <= 12: yd = (random.randint(1,2))
-
最后,一旦我们脱离了 if elif 语句,让我们用“y”的当前值加上“d”。
x += xd y += yd pygame.quit()
time.sleep(0.005)
就这样!运行这个程序(图 23-5 ),你会得到一个从屏幕的四面墙上反弹回来的弹力球。耶!
图 23-5
弹跳球(离开四面墙)
项目 23-5:温度转换应用
对于这个项目,让我们创建一个温度转换应用。我们的应用将有两个功能,一个“摄氏到华氏”转换器和一个“华氏到摄氏”转换器。
-
让我们导入 tkinter 并设置我们的屏幕。
from tkinter import * w = Tk()
-
现在,让我们设计我们的应用。这将是一个非常简单的设计。我们将创建两个框架,每个转换器一个。
frame1 = Frame(w) frame1.grid(row=0,column=0,padx=10,pady=10)
-
让我们创建一个标签、一个摄氏温度值的输入框、一个点击时进行转换的按钮和另一个获得结果(华氏温度值)的输入框。
#Celsius to Fahrenheit conversion label1 = Label(frame1,text='Celsius to Fahrenheit conversion',font=('Arial',15,'bold')) label1.grid(row=0,column=0,columnspan=3) entry1 = Entry(frame1) entry1.grid(row=1,column=0) button1 = Button(frame1, text='Convert to Fahrenheit',command=find_fahrenheit) button1.grid(row=1,column=1) entry2 = Entry(frame1) entry2.grid(row=1,column=2)
-
让我们对下一个转换器重复同样的操作。
frame2 = Frame(w) frame2.grid(row=1,column=0,padx=10,pady=10) #Fahrenheit to Celsius conversion label2 = Label(frame2,text='Fahrenheit to Celsius conversion',font=('Arial',15,'bold')) label2.grid(row=0,column=0,columnspan=3) entry3 = Entry(frame2) entry3.grid(row=1,column=0) button2 = Button(frame2, text='Convert to Celsius',command=find_celsius) button2.grid(row=1,column=1) entry4 = Entry(frame2) entry4.grid(row=1,column=2)
-
Run the program, and you’ll get this (Figure 23-6).
图 23-6
温度转换器
-
现在,让我们在小部件上创建我们的函数。find_fahrenheit()函数将摄氏温度转换为华氏温度。
-
有一个公式可以做到这一点,如下所示:
def find_fahrenheit():
- 让我们删除第二个输入框(结果框),以防用户已经进行了转换,并且这是一个新的转换。
#Formula is F = ((9/5)*C)+32
-
现在,让我们获取第一个输入框在“C”中的值,并将其转换为一个整数。
C = entry1.get() C = int(C)
-
现在,让我们计算“F ”,并将其插入第二个输入框。就这样!
F = ((9/5)*C)+32 entry2.insert(0,F)
-
让我们对 find_celsius 函数重复同样的操作。
def find_celsius(): #Formula is C = (5/9)*(F-32) entry4.delete(0,END) F = entry3.get() F = int(F) C = (5/9)*(F-32) entry4.insert(0,C)
entry2.delete(0,END)
让我们运行我们的程序,我们会得到这个(图 23-7 )。
图 23-7
转换
有效!
项目 23-6:用文件和Tkinter
介绍
这将是一个简单的项目。我们将在您选择的文件夹中创建一个名为 introduction.txt 的文本文件。我们将通过 Python 代码编写对该文件的介绍,最后,我们将创建一个简单的文本应用,它接受文件名(完整的文件路径)并在文本框中打印出该文件的内容。
我们可以开始了吗?
-
在我们开始之前,让我们导入 Tkinter 并创建我们的屏幕。
from tkinter import * w = Tk()
-
我将在下面的路径中创建我的文件:
G:\\Python\introduction.txt
-
我也可以用“x ”,但是我用的是“w ”,这样我就不用再以写模式打开文件了。
-
4.然后,我要写苏珊对它的介绍:
f.write('''Hi, I'm Susan. I'm 9 years old. My puppy's name is Barky. He loves me very very much! :)''')
-
现在,我将创建一个全局变量,每当我在输入框中按 Enter 键时,它将存储文件的内容。现在让我们在其中存储一个空字符串。
f = open('G:\\Python\introduction.txt','w')
-
现在,让我们创建我们的小部件。我想要一个在我的输入框左边的标签。因此我把它放在第 0 行第 0 列。
label = Label(w,text='File name',font=('Arial',12,'bold')) label.grid(row=0,column=0,padx = 5, pady=5)
-
我将把我的输入框放在第 0 行第 1 列,让它在四个方向都有粘性,并给所有东西填充。我选择的所有值(宽度、填充等。)都是任意的。你可以测试不同的值,选择你喜欢的。
entry = Entry(w,width=65) entry.grid(row=0,column=1,sticky='nsew', padx = 5, pady=5)
-
最后,让我们为我的条目创建一个绑定。每当我按下键盘上的 Enter 键(Mac 中的命令)时,我都想调用我的 get_file 函数。您需要使用'
'条件来实现这一点。
f_content = ''
-
最后,让我们创建文本小部件。我将为我的文本设置一些默认样式,并将其放在第 1 行第 0 列,使其跨越两列(因此它占据了前两个小部件的整个宽度)。
text = Text(w,font=('Arial',14,'bold')) text.grid(row=1,column=0,columnspan=2)
-
好了,现在我们完成了小部件,让我们定义 get_file 函数。定义在调用函数上面好吗?
entry.bind('<Return>',get_file)
因为我们创建了一个绑定,所以我们的函数需要接收“事件”。将 f_content 加载到函数中。
-
首先,从输入框中获取文件名。然后,以读取模式打开该文件,并将其内容存储在 f_content (f.read())中。
file = entry.get() f = open(file,'r') f_content = f.read()
-
最后,将 f_content 中的内容插入到文本框中。我们使用“end”来插入全部内容。
def get_file(event):
global f_content
text.insert('end',f_content)
就这样!
现在让我们运行我们的程序(图 23-8 )。
图 23-8
Tkinter app 布局
我们的小部件就在我们想要的地方!让我们看看我们的程序现在是否工作(图 23-9 )。
图 23-9
导入文件内容
是的,确实如此。我输入了我的文件路径(确切的路径)并按下 Enter 键,我的文件内容显示在我的文本框中。完美!
摘要
在这一章中,我们使用 Tkinter 或 Pygame 创建了六个应用。我们创建了一个计算器,一个随机故事生成器,一个石头剪刀布游戏,一个文件上传应用,一个温度转换应用和一个弹力球。
在下一章,我们来谈谈你的 Python 之旅的下一步。我会给你一些关于你接下来需要学习的东西的想法,我也会给你一些关于你可以自己工作的更多迷你和顶点项目的想法。
二十四、下一步是什么?
在前一章中,我们用 Python 创建了更多有趣的迷你项目。在这一章中,让我们看看接下来会发生什么。我将为您提供更多的 mini 和 capstone 项目想法供您尝试,并且让我们简单地讨论一下如何从这里继续您的 Python 之旅。
迷你项目的想法你可以试试
Python 是一种非常有趣的编程语言,你可以做任何你想做的事情。
迷你项目和拼图是积累 Python 专业知识的好方法。在这本书里,你已经创建了很多迷你项目。为什么我不给你一些想法来创建你自己的迷你项目呢?
货币兑换应用
你可以用这个项目。尝试为尽可能多的货币创建转换选项。
你可以把它做成一个单行的应用,在文本框旁边有下拉菜单(就像你在谷歌的货币转换应用中看到的那样)。下拉列表将列出所有货币选项。根据两边的选择,进行转换。
简单吧?尽可能自动化,也就是尽可能减少代码行。
参加 Pygame 的比赛
我们在一个迷你项目中创建了一个海龟比赛,记得吗?你为什么不用的 Pygame 做同样的尝试,但是这次要做得更好?用线创建适当的跑道,并将您的有色玩家(可以是矩形)放在跑道的起点。
也许你也可以创建一个开始按钮,点击它,让你的玩家比赛(让他们随机移动),最后,根据谁赢了,创建一个玩家颜色的“游戏结束”屏幕。
很简单,不是吗?试试看!
更多图案在turtle
你记得我们在早期项目中创造的曼荼罗模式吗?你为什么不试着创造更多这样的图案呢?让它们变得更复杂。您已经知道可以使用 for 循环来自动化模式。
您可以创建不同的图案(圆形和方形)并将它们随机组合在一起(使用函数调用)。
顶石项目的想法你可以试试
我们已经看到了如何在turtle
中创建贪食蛇游戏,但是正如你现在看到的, Pygame 更适合任何游戏,那么你为什么不尝试在 Pygame 中创建同样的游戏呢?
Pygame 中的贪食蛇游戏
创建它应该很简单。为蛇头和身体部位(包括苹果)绘制矩形,让它们移动(你已经知道如何移动),当蛇头叠加苹果时创建一个记分牌,同时让蛇增长一个身体部位,最后如果有碰撞(墙壁或身体碰撞)就结束游戏。
躲避子弹
为什么我们不用 Pygame 创建一个反向的太空游戏呢?不是向外星人开枪,而是一群外星人向你开枪。你没有弹药了,你现在唯一能做的就是躲开雨点般的子弹(从每艘外星飞船上随机发射,这样你就不知道哪艘要射向你),而这正是你要做的。
比方说,你有十条命,每次子弹击中你,你就失去一条命。坚持的时间越多,分数越高。很有趣,但很简单,你不觉得吗?让游戏变得如你所愿的简单或困难。
记忆游戏 Pygame
这是一个有趣的小游戏,你可能在街机上玩过。创建偶数编号的框。每个盒子后面都藏着一幅图像,但有一个问题。每个图像有两个,你需要匹配它们。
当用户开始游戏时,在指定的时间限制内(可能是 5-10 秒)显示隐藏在盒子后面的所有图像,这样用户就可以看到它们在哪里。然后,再藏起来,游戏就开始了。现在,用户需要匹配图像。
用户第一次点击其中一个框时,它后面的图像就会显示出来。他们必须在下一次点击有相同图像的盒子。如果他们不这样做,如果下一个被显示的图像是不同的图像,这两个图像将再次被隐藏,他们可以重新开始。
如果他们一个接一个地点击隐藏相同图像的相同方框,那么这些方框将不会再被隐藏,他们就获得一分。
他们需要在给定的时间限制内匹配所有像这样的盒子(通常一组 10 张图像需要 30 秒)。
有趣吗?试试看!
展望未来
好了,我们到了书的末尾。到目前为止,您已经学习了 Python 的基础知识,所有关于 Turtle 、 Tkinter 和 Pygame 的知识,并且您还创建了项目来熟悉这些主题。下一步是什么?你应该如何继续你的旅程?让我给你一些建议。
详细的哎呀
我们确实学习了对象和类,但是我们没有更深入地研究这个主题,一点也没有。如果你想做真正的编程,OOPs 会给你很大的帮助。对于任何编程语言来说,这也是一项宝贵的技能,更不用说 Python 了。
那么,为什么不从在更多的项目中使用类开始,看看它们是如何转换代码的呢?接下来,拿起一本好的 Python 面向对象编程的书,继续你的旅程。
正则表达式
在任何编程语言中,正则表达式都是一个非常有趣的高级话题,尤其是 Python。这基本上是一个扭曲的模式匹配。
您是否想知道程序如何知道您的密码没有指定数量的字母、数字和特殊字符,以及它们如何能够指出其中一个字符是否是大写字母?魔法?不,这是你的正则表达式模式匹配。
课题研究。我肯定你会发现它很有趣。
Web 开发
我已经向您介绍了 web 开发的基本知识,但是您可能已经猜到了,我们仅仅触及了皮毛。还有很多东西要学,还有很多事情要做。
就 web 开发而言,世界是你的。深入研究 HTML、CSS 和 JavaScript,了解更多关于网站设计和开发的知识。然后,使用 Django 或 Flask 作为后端,使用 MongoDB 为程序创建和维护数据库。一旦你学会了这个主题,试着创建项目(也许是一个社交媒体网站或一辆购物车)。这是一个需要几个月才能学会的庞大话题。一步一步来。
详细包装
是的,我们已经在一定程度上看过turtle
、 Tkinter 和 Pygame 。但是还有很多要学的。因此,我建议创建更多的项目(不仅仅是本书中提到的那些),当你遇到更多的问题时,你会寻找更多的解决方案(或语法)来解决它们,你会更深入地研究你正在处理的每个包。
玩得开心!
摘要
在这一章中,我给了你更多关于迷你和顶点项目的想法,你可以尝试自己创造。然后,我给了你接下来可以学习的方向。
就这样!我们已经到了这本书的结尾。我希望你和我一起学习 Python 很开心。不要停止学习和创造,但更重要的是,永远不要停止享受乐趣!