{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 实践2 Python基本语法 \n", "\n", "## 学习目标 \n", "\n", "1. 值具有类型,了解值的类型很重要; \n", "2. 理解变量是值的抽象,可以帮助我们处理用户输入的任何值; \n", "3. 掌握赋值语句,赋值语句是值与变量、变量与变量之间的桥梁。 \n", "4. 掌握基本运算,操作符是对数据进行操作的一些符号,最常用的有算术运算、大小比较、赋值、逻辑运算等; \n", "5. 了解代码注释的语法和意义; \n", "6. 了解浮点表示误差和规避方法; \n", "7. 了解 Python 中字符串的表示方法以及转义符;\n", "8. 了解如何使用 f-string;\n", "9. 掌握输入输出语句,输入输出语句提供了程序与用户的交互渠道,程序可以根据用户的输入,输出对应的结果。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1.关键字\n", "在Python中,具有特殊功能的标识符称为关键字。Python的关键字随版本不同有一些差异,可以在Python 交互方式中按如下所示的方法查阅。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import keyword\n", "keyword.kwlist" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "You are now leaving help and returning to the Python interpreter.\n", "If you want to ask for help on a particular object directly from the\n", "interpreter, you can type \"help(object)\". Executing \"help('string')\"\n", "has the same effect as typing a particular string at the help> prompt.\n" ] } ], "source": [ "help()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. 常量和变量 \n", "数据是计算机处理的对象,在计算机中存储和处理数据,是区分数据类型的,不同的数据类型的表示方式和运算机制都是不同的。 \n", "数据在程序里的存在有两种形式,一种是“值(value)”,一种是“变量(variable)”。按接近人的习惯设计并加以不同数据类型的区别,称为数据的“值(value)”,是数据的“书写形式”。这些数据是不会改变的,也称为常量。 \n", "\n", "下面是一些值的例子: \n", "\n", "```python\n", "42\n", "3.14\n", "'a'\n", "'abracadabra'\n", "True\n", "False\n", "```\n", "\n", "值是有类型的,Python 提供了一个函数叫做 `type()`,可以告诉我们某个值是什么类型,我们可以试一下: " ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "type(1)" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": [ "type(1.0)" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [], "source": [ "type(2+5j)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type(True)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type(\"Python\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type([1,2,3,4,5])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type((1,2,3,4,5))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type({1,2,2,3,4})" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type({\"a\":94,\"c\":96,\"A\":65,\"C\":67})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "有了值,我们就可以做计算,但是写不出真正的程序,为什么呢?因为程序写出来是希望能被很多人反复使用的——这些人叫做用户(user)——这样才比较划算,每次使用,用户输入一些数据,程序进行处理,然后给出用户想要的结果,每次的输入可能是同一类型,但具体的值是多少在我们写程序时是不知道的,所以我们需要一种东西能够来代替值写在程序中,而在程序运行时这些东西才根据用户的输入变成实际的“值”,这些“东西”就是变量。 \n", "\n", "变量使得我们可以编写一个程序来处理一类值,而不管具体值是多少。我们学习代数的时候用 a + b = b + a 就表达了“加法交换律”这样高度抽象的普适规律,而不管 a 和 b 到底是多少,程序里的变量也一样,让我们能够进行“数据的抽象”,这个概念很重要,后面我们还会不断深化它。 \n", "\n", "所有编程语言都支持值和变量,也支持把特定的值赋予某个变量,这样的操作叫做“赋值(assignment)”,下面是一些例子: " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = 12\n", "b = 30\n", "f = 3.14\n", "s = 'abracadabra'\n", "l = [1, 2, 3]\n", "t = True\n", "f = False" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "赋值之后变量就具有了相应的值,**同时也具有了该值对应的类型和对象ID**,所以变量一经赋值就有了类型和对象ID: " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "id(s)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type(s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "如果我们想消灭一个变量不再使用,可以用 del 命令:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "del s\n", "s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3.可变对象和不可变对象\n", "Python3的对象可以分为不可变对象(immutable)和可变对象(mutable)。不可变对象,一旦创建其值就不能被改变,可变对象的值可以被修改。\n", "Python大部分对象都是不可变对象,例如int、float、str、tuple等。变量是指向某个对象的引用,多个变量可以指向同一个对象,给变量重新赋值,并不改变原始对象的值,只是创建一个新对象,该变量指向新的对象。\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s=\"Python\"\n", "s[0]='p'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s=\"python\"\n", "s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "对象本身的值可以改变的对象称为可变对象,例如list、dict、set等。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "l" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "l[0]=10\n", "l" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4.运算符与表达式\n", "Python语言提供了丰富的运算符,例如算术运算符、关系运算符、逻辑运算符等。 \n", "表达式是数据对象和运算符按照一定的规则写出的式子,描述计算过程。与上述运算符对应的表达式可以分为算术表达式、关系表达式、逻辑表达式等。 \n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### (1)算术操作符\n", "算术操作符就是加减乘除之类的,专门针对整数和小数。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "相同类型运算" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = 6\n", "b = 30\n", "f = 3.14\n", "g = 0.7" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a + b" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a - b" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a * b" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#除法,int/int=>float\n", "b / a" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#整除,int//int=>int\n", "b // a" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#幂运算\n", "a**2" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#求余数\n", "a%4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "混合运算" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# int*float =>float\n", "a * g" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#幂可以是小数,下例相当于求根号2\n", "a ** 0.5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "输入以下表达式并查看结果。 \n", "①23+3 ②23>3 ③'23'+'3' ④23/3 ⑤ 23//3⑥23%3⑦23**3 \n", "问题: \n", "表达式结果为整数类型有哪些? \n", "表达式结果为浮点数类型有哪些? \n", "表达式结果为字符串类型有哪些? \n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### (2)关系运算符 \n", "比较大小的一组操作符,`> < >= <= == !=` 分别是大于、小于、大于或等于、小于或等于、等于和不等于关系。这几个操作符比较它左右的数据的大小关系,如果符合操作符的含义就返回布尔值真(`True`),否则返回布尔值(`False`)。在 Python 里这些操作符不仅可以比较数字,还可以比较其他很多类型的数据,下面有一些简单的例子。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a < b" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a >= a" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a <= f" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a + b == 36" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a + b != 36" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "'aaa' < 'aab'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a * g == 4.2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上面的比较有没有什么问题?前面都没啥,但是注意最后一个,a 的值是 6,而 g 的值是 0.7,他们乘起来就是 4.2 啊,为啥最后一个比较返回是 `False` 呢?我们来看看计算机算出来的 `a * g` 是多少:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a * g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "这是什么鬼啊?不要惊慌,这叫浮点误差,下面来简单解释下" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 插播:浮点误差" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "目前我们用的计算机叫“电子计算机”,用电平的高低表示数,电平高的是 1,低的是 0,只有这两种状态,也就是说计算机只认识 0 和 1。要用 0 和 1 表示我们要用到的各种数字,就要采用[二进制](https://zh.wikipedia.org/zh-cn/%E4%BA%8C%E8%BF%9B%E5%88%B6)计数法。\n", "\n", "二进制计数法对于整数来说没啥问题,每一个十进制整数都对应唯一的二进制表示,但对于小数来说问题就来了,**绝大部分十进制小数是没法用有限位数表示为二进制小数的**,如果想知道为什么,可以看看[这篇文章](https://www.taowong.com/blog/2018/07/10/principle-of-computer-float-num.html),如果看不明白也没关系,反正记住这个结论就行了。这个结论决定了在计算机里小数是以一种“近似值”的方式表示的,0.7 在计算机里是个近似等于 0.7 的二进制小数,这个小数乘上 6 之后的结果也是有微小的误差的,转换回十进制小数给我们看结果时就会出现上面那样的奇怪现象。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "那么我们怎么解决这个问题呢?分两种情况:\n", "1. 如果需要绝对精确的结果,那么不要用小数,只用整数进行运算,然后自己计算小数点的位置,绝大部分计算器就是这么做的;\n", "2. 如果不需要绝对精确,那么只要结果的误差足够小就可以了,这时候可以用浮点数进行运算,但比较时不要直接比较结果是不是相等(`==`),而用误差范围来比较:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s = 4.2 # 这是预期结果\n", "r = 0.001 # 这是可容忍误差\n", "\n", "abs(a * g - s) < r # 如果 (a * g - s) 的绝对值比 r 小,就算结果合格\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`abs` 函数的值等于后面括号里的值的绝对值。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### (3)逻辑运算操作符 \n", "逻辑运算操作符是布尔值之间的运算,结果也是布尔值。我们知道布尔值是逻辑上的真和假,而逻辑运算操作符就对应了逻辑代数(也叫布尔代数)里的各种运算。\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "基本的逻辑运算就三个:`and`、`or`、`not`,即 **与**、**或**、**否**。\n", "* 两个布尔值如果都是“真”,他们的 **与** 运算结果也为“真”,其他情况下结果都是“假”;\n", "* 两个布尔值中只要有一个是“真”,他们的 **或** 运算结果就为“真”,如果两个都是“假”,那么 **或** 运算结果为“假”;\n", "* 布尔值“真”的 **否** 运算结果为“假”,布尔值“假”的 **否** 运算结果为“真”。\n", "\n", "通过这三个操作符我们可以组合复杂的逻辑运算:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "t = True\n", "f = False" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "t and f" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "t or f" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "not t" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "t and (not f)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "(not t) or f" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5.赋值语句\n", "Python的赋值语句通过赋值符“=”实现,用赋值符将右边数据对象与左边的变量名建立了引用关系,其一般使用方法如下,尖括号的内容表示具体使用时需要替代:\n", " ` <变量> =<表达式>`\n", "Python还支持连续赋值、同步赋值和复合赋值。\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### (1)连续赋值" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a=b=c=0\n", "a,b,c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### (2)同步赋值" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#输入x,y\n", "x,y=int(input(\"x=\")),int(input(\"y=\"))\n", "x,y" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#交换x,y\n", "x,y=y,x\n", "x,y" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### (3)复合赋值 \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "i=1\n", "i=i+1\n", "i" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "i+=1\n", "i" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "类似的还有 -= *= /= %= **= //= 这一组赋值操作符的变体,与 += 同理。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 练习" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1.执行完下面数值表达式语句后,变量a~k的值分别是多少?\n", "```python \n", "a=5\n", "b=2\n", "a*=b\n", "b+=a\n", "a,b=b,a\n", "c=6\n", "d= c%2+(c+1)%2\n", "e =2.5\n", "f=3.5\n", "g=(a+b)%3+int(f)//int(e)\n", "h=float(a+b)%3+int(f)//int(e)\n", "i=(a+b)/3+f%e\n", "j=a