1 python介绍
1.1 python发展史
python由荷兰人Guido(龟叔)开发,龟叔曾经ABC语言,结果失败了,他认为是语言未开源的原因。于是1989年圣诞节龟叔决心开发一门开源语言python,改善在ABC存在的不足。起python这个名字是因为龟叔很喜欢当时的喜剧《蒙提.派森的飞行马戏团》(Monty Python’s Flying Circus)。
后来人工智能崛起,2017年初FaceBook专门推出pytorch工具,从此奠定python的地位。
1.2 python的版本
python分为2.x版本和3.x版本,二者并行,不兼容。而且2.7版本是2.x的最终版本。
1.3 python的特点
- 优点
(1)即面向过程,也面向对象
(2)解释执行,跨平台
(3)可扩展性强(胶水语言,可以和其他语言合并使用)
(4)有强大语言库支持
(5)语法简洁 - 缺点
(1)速度慢(因为是解释执行,相对来说速度慢一些,但基本可以忽略)
(2)开放,不加密
1.4 应用领域
- web开发
- 网络爬虫
- 游戏编程
- 人工智能
1.5 python的执行
(1)交互式执行
在交互式命令窗口(cmd)调用python解释器
(2)脚本执行
step 1: 创建一个脚本(.py文件)
step 2: 在cmd后台找到脚本路径
step 3: 输入
我在D:\test目录下创建一个hello.py脚本文件
hello.py文件内容:
print("hello python!")
print(3 + 5)
脚本执行:
(3)交互模型和脚本模式的区别
交互模式:一行一行的输入,每输入一行,就执行一次,不需要print
脚本模式:一次性把.py文件中所有源码全部执行,没有机会进行交互(一般代码辣么长,也不需要啦)
2 变量&常量
2.1 变量variable
2.1.1 变量定义
使用指定名称来绑定特定的值,在python中相当于给变量值贴标签
2.1.2 变量赋值
变量名 = 变量值
python支持平行赋值
简单举个栗子:
a, b = 3, 5
print(a, b)
3 5
两值交换也简单了:
以前的方法是增加一个中间变量
a, b = 3, 5
temp = a
a = b
b = temp
print(a, b)
5 3
现在直接平行赋值
a, b = 3, 5
a, b = b, a
print(a, b)
5 3
2.1.3 变量定义的内存结构
(1)当定义变量时,比如a = 3,python解释器做了以下事情:
①创建变量值3的内存
②创建变量名a的内存
③将a绑定到3上
图示:
(2)同时为多个变量赋值
对于不可变类型(数字、字符串、字节)来说,多个变量指向同一个内存时,如果内存中已经存在这个值,就不会再新建变量值的内存,只会新建变量名,再将新变量名绑定到已有变量值。并且变量只会指向变量值,不会指向变量,这种底层设计也称为基于内存的管理。
比如新定义b = c = 3,由于之前已经存在a = 3,所以不会新建3的内存,只会新建b, c的内存,并且b,c不会绑定到a上,而是绑定到3上。
图示:
2.1.4 变量修改
第一次赋值,相当于定义变量;第二次赋值,相等于修改变量指向。
注意:
(1)一个变量只能绑定一个数值
(2)同一个变量可以绑定不同类型的数值
(1)很好理解,前面的内存结构图也清楚表现出来。
(2)的意思是对于变量a,可以是a = 3,也可以是a = “abc”,而变量类型python可以自己识别,因此python变量类型也称为鸭子类型。
鸭子类型的名字来源于由James Whitcomb Riley提出的鸭子测试:
当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。
具体可见:
https://www.jianshu.com/p/a14c32656ca8
引申:python是强类型、动态语言
2.1.5 变量删除
- 等待python自动垃圾回收(属于内部结构)
- 自己手动删除变量
a = 3
del a
注意: 此时删除的只是变量名,变量值仍然存在,等待垃圾回收。一般不需要手动删除变量,因为删除命令本身也会占用内存。
2.2 常量constant
这里主要说一下None
None是python中的内直常亮,表示变量值的缺失。
None
和空串' '
类型不同:None是NoneType,空串是字符串str类型。
3 输入&输出
3.1 输入input
默认字符型!字符型!字符型!
3.2 输出print
返回值为None
可修改分隔字符和结束字符
print("Hello World", "不 Hello", "谁跟你Hello", sep='。', end='*')
Hello World。不 Hello。谁跟你Hello*
4 运算符operator
表达式由运算符和操作数组成,操作数指参与运算的数据,运算符是有特殊计算规则的符号,有n个操作数就是n元运算符。
4.1 算术运算符
(1) +
加
(2)-
减
(3)*
乘
(4)/
除:结果为浮点类型
(5)**
求幂
(6)//
取整:向下取整
注意和int()
区别,int直接舍掉小数位(向零取整)
print(10//-3) #结果为-4
print(int(-10/3)) #结果为-3
(7)取模和取余(特意放到一起说,注意区分)
python中取模和取余是分开的,但步骤都是先求商,再求余数,区别在于商的取法不同。
%
取模:商向下取整,符号和除数相同,输出类型与操作数有关
print(10%3) #输出:1
print(-10%3) #输出:2
print(10%-3) #输出:-2
print(-10%-3) #输出:-1
10%3:商为3.33333…,向下取整得3,那么余数 = 被除数 - 除数 * 商 = 10 - 3 * 3 = 1
-10%3:商为-3.33333…,向下取整得-4,那么余数 = 被除数 - 除数 * 商 = -10 - 3 * (-4) = 2
10%-3:商为-3.33333…,向下取整得-4,那么余数 = 被除数 - 除数 * 商 = 10 - (-3) * (-4) = -2
-10%-3:商为3.33333…,向下取整得3,那么余数 = 被除数 - 除数 * 商 = -10 - (-3) * 3 = -1
math.fmod()
取余:商向零取整,符号和被除数相同,输出浮点类型
import math
print(math.fmod(10, 3)) #输出:1.0
print(math.fmod(-10, 3)) #输出:-1.0
print(math.fmod(10, -3)) #输出:1.0
print(math.fmod(-10, -3)) #输出:-1.0
下面只是介绍计算思路,所以结果简单写成整数(实际上输出为浮点类型,见代码):
math.fmod(10, 3):商为3.33333…,向零取整得3,那么余数 = 被除数 - 除数 * 商 = 10 - 3 * 3 = 1
-10%3:商为-3.33333…,向零取整得-3,那么余数 = 被除数 - 除数 * 商 = -10 - 3 * (-3) = -1
10%-3:商为-3.33333…,向零取整得-3,那么余数 = 被除数 - 除数 * 商 = 10 - (-3) * (-3) = 1
-10%-3:商为3.33333…,向零取整得3,那么余数 = 被除数 - 除数 * 商 = -10 - (-3) * 3 = -1
4.2 比较运算符/关系运算符
<
=
>
<=
==
>=
!=或者<>
比较运算符返回值为布尔类型,python中支持链式比较(a < b < c、1 < x > 2等),链式比较中也支持短路(按从左到右顺序比较,前面为false,就不往下比较了。对于上面举的例子1 < x > 2,如果x = 0,先比较1 < 0,结果为false,直接结束比较返回false)。
注意:==
比较内容是否相等,内存地址(对象)不一定相等
4.3 身份运算符
is
is not
身份运算符返回值为布尔类型,判断内存地址(对象)是否是同一个。
注意区分is
和==
:
(1)is
比较地址,==
比较内容。
a = [1, 2, 3]
b = [1, 2, 3]
print(id(a), id(b))
print(a == b)
print(a is b)
-----------------------------
输出:
2031470334536 2031470335048
True
False
(2)对于数值、字符串、字节这种不可变类型(基于内存的类型:直接写入内存),相同的内容是同一个对象。
(3)is
如果是True,==
一定是True;==
如果是是True,is
不一定是True。
4.4 逻辑运算符/布尔运算符
and
or
not
返回值可能是布尔类型,也可能是计算值。
print(3==3 and 1!=1)
print(True or False)
print(3 and 4)
print(0 or 'abc')
----------------------
输出:
False
True
4
abc
短路现象
当有多个表达式时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值。
and:第一个表达式为False的时候,后面表达式不再执行。
or:第一个表达式为True的时候,后面表达式不再执行。
print("aaa") and print("ddd")
----------------------
输出:
aaa
----------------------
解释:
print函数返回值是None,对应布尔类型是False。
对于and运算,第一个表达式为False,后面表达式不执行(短路现象)
print(False or print("False-aaaa"))
----------------------
输出:
False-aaaa
None
----------------------
解释:
先看括号内False or print("False-aaaa"),根据短路运算规则执行print("False-aaaa"),得到第一个输出。
再看括号外print(),返回False or print("False-aaaa")这个表达式的返回值,由于print函数返回值是None,对应布尔类型是False,所以得到第二个输出None。
如果前面的代码在外面加上print()的话,即print(print("aaa") and print("ddd")),也会增加一个输出None。
引申:python运算符优先级顺序
https://blog.csdn.net/qq_41882322/article/details/80139953
由高到低依次为:
- 幂运算:**
- 正负号:+X,-X
- 算术操作符:*,/,//,+,-
- 比较操作符:<,<=,>,>=,==,!=
- 逻辑运算符:not,and,or(not > and > or)
- 赋值运算符(4.6具体介绍)
4.5 位运算符
4.5.1 基础知识回顾
最初利用计算机计算时,将十进制转换成二进制,但是发现有两个问题:(1)出现两个0;
(2)正负数运算结果错误:比如1+(-1) -> 0001 + 1001 = 1010,结果不是0而是-2。
因此引入反码,对负数的二进制进行处理,解决了(2)的计算问题:1+(-1) -> 0001 + 1110 = 1111,该反码对应-0。但问题(1)仍然没得到解决。
因此又引入补码,完全解决计算问题。
计算机中以补码形式存储数据,用补码进行运算,结果仍是补码,然后变回原码(因此自己计算的时候一定要注意得到负数结果还要计算一次原码)。
- 正数
原码反码补码都是相同 ,都是二进制原码 - 负数
原码:正数的二进制码,最高位取1
反码:除符号位以外,其余取反
补码:反码+1
把补码变回原码:取反码+1 - 求补码的小trick:除符号位,从低位到高位遇到第一个1之前不变(包括1),第一个1之后所有位取反。
比如:
-27原码为10011011
算得补码 11100101
-26原码为10011010
算得补码 11100110
4.5.2 位运算符
&
与|
或^
异或~
非:包含符号位一起取反。<<
左位移:左侧舍弃,右侧填充0,移1位相当于乘2。
print(4<<1)
-----------------
输出:
8 # 100 -> 1000
>>
右位移(涉及符号位):左侧正数填充0,负数填充1,右侧舍弃,移1位相当于除2(向下取整)。
print(15 >> 1)
print(-15 >> 1)
-------------------------
输出:
7 # 0000 1111 -> 0000 0111
-8 # 1000 1111 -> 11110001(-15补码)-> 11111000(补码右移1位)-> 10001000(补码转换成原码)
4.6 赋值运算符
=
+=
自加运算(只调用一次a,运算更快)
a+=1
等同于
a=a+1-=
自减运算*=
自乘运算/=
自除运算%=
自模运算**=
自幂运算
4.7 成员运算符
in
not in
返回值是布尔类型,判断元素是否在序列中
a="abc"
Print("a" in a)
Print("ab" in a)
Print("abc" in a)
--------------------------
输出:
True
True
True