Python
Python的使用
计算机简介
计算机的组成
计算机由两部分组成:硬件和软件
- 硬件 硬件包含:键盘、鼠标、显示器、cpu等
- 软件 软件包含:系统软件(windows、macOS、Linux)和应用软件(office、QQ等)
计算机的使用方式
- 必须通过软件来对计算机完成各种操作,但是注意的是,软件中并不是所有的功能都会对用户开放,用户需要调用软件提供的接口来操作计算机
- 用户界面分为两种:TUI(文本交互界面)和GUI(图形化交互界面)
常用DOS命令
系统命令
- shutdown /s /t 1800 /s表示关机 /t表示设定时间
- shutdown /a 表示取消关机
- cls 表示清空屏幕
- time 显示当前计算机时间
- ping www.baidu.com 检查网络是否可通
- ipconfig 寻找ip地址
目录与文件相关
- cd 切换目录,不能切换盘符,并且只能在当前盘符下进行切换目录 切换盘符(例: D:)
- md test 表示新建目录(只能建目录)
- echo "明天放假">a.txt 表示新建文件
- rd test 删除目录 如果包括目录中的文件也删除,使用rd /s test
- del a.txt 删除文件
- del test 删除目录,如果是选择目录,将会连同文件一块儿删除,跟rd /s test功能类似
- copy test/a.txt b.txt 在test下复制a.txt文件到test下取名为b.txt
- move test/a.txt C:tests 移动文件到C:tests下
环境变量
基本介绍
- 环境变量指的就是操作系统当中的一些变量
- 可以通过修改环境变量,来对计算机进行配置(主要是来配置一些路径的)
- 环境变量分为两个部分,上边是用户环境比那辆,下边是系统环境变量,建议值修改用户的环境变量,不哟啊修改系统的环境变量(个人采用的是只在系统变量进行添加,不进行修改及删除)
path环境变量
- path环境变量中保存的是一个个的路径
- 当我们在命令行中输入一个命令(或访问一个文件时),系统会首先在当前目录下寻找,如果找到了则直接执行或打开,如果没有找到,则会依次去path环境变量的路径中去寻找,直到找到为止,如果path环境变量中的路径都没有找到则报错,可以将一些经常需要访问到的文件添加到path环境变量中,这样就可以在任意的位置访问到这些文件了
- 注意事项
- 如果环境变量中没有path,可以手动添加
- path环境变量不区分带小写
- 修改完环境变量必须重新启动命令行窗口
- 多个路径之间使用分号隔开
文本与字符集
文本
文本分为两种,一种叫做纯文本,还有一种叫做富文本
- 纯文本中只能保存单一的文本内容,无法保存内容无关的东西(字体、颜色、图片)
- 富文本可以保存文本以外的内容(word文档)
在开发时,编写程序使用的全都是纯文本
纯文本在计算机底层也会转换为二进制保存 - 将字符转换为二进制码的过程,称为编码
- 将二进制码转换为字符的过程,称为解码
- 编码和解码所采用的的规则,我们称为字符集
字符集
常见的字符集
- ASCII 美国人编码,使用7位来对没过常用的字符进行编码
- ISO-8859-1 欧洲编码,使用8位
- GB2312和GBK 国标吗,中国编码
- Unicode 万国码,编写程序一般使用Unicode编码
乱码 编写程序时,如果发现程序代码出现乱码的情况,就需要检查字符集是否正确
编译语言和解释型语言
计算机智能识别二进制编码,所以任何的语言在交由计算机执行时,必须先转换为机器码,也就是像print('hello')必须要转换为类似1010101这样的机器码
根据转换时机的不同,语言分成两大类
- 编译型语言 C语言 特点:还行速度快,跨平台性差
- 解释型语言 python、js、java 特点:执行速度比较慢,跨平台性比较好
初识Python
C/S架构跟B/S架构
- C/S结构,即Client/Server(客户机/服务器)结构,是大家熟知的软件系统体系结构,通过将任务合理分配到Client端和Server端,降低了系统的通讯开销,可以充分利用两端硬件环境的优势。早期的软件系统多以此作为首选设计标准。
- B/S结构,即Browser/Server(浏览器/服务器)结构,是随着Internet技术的兴起,对C/S结构的一种变化或者改进的结构。在这种结构下,用户界面完全通过WWW浏览器实现,一部分事务逻辑在前端实现,但是主要事务逻辑在服务器端实现,形成所谓3-tier结构。
Python介绍与安装
- Python语言是一种解释性、面向对象、动态数据类型的高级程序设计语言
- Python语言是数据分析师的首选数据分析语言,也是智能硬件的首选语言
- 安装:python3.7,傻瓜式安装,需要选择Add Python3.7 to PATH
pyCharm的常用快捷键
- Ctrl + Alt + L 代码格式化
- Shift + Enter 另起一行
- Ctrl + Shift + R 全局替换
- Ctrl + Shift + F 全局查找
- Shift + F10 运行
- Shift + F9 调试
pyCharm的常规设置
- 设置颜色跟字体 点击file→setting→appearance&behavior→appearance
- 设置图片背景 点击file→setting→appearance→background image
- 设置python自动创建的模板 点击file→Editor→File and Code Templates
python的基本语法
- 在python中严格区分大小写
- python中的每一行就是一条语句,没跳语句以换行结束
- python中每一行语句不要过长(规范中建议每行不要超过80个字符)
- 一条语句可以分多行编写,语句后边以\结尾
- python是缩进严格的语言,所以在python中不要随便写缩进
- 在python中使用#来表示注释,#后的内容都属于注释,注释的内容将会被解释器所忽略,我们可以通过注释来对程序进行解释说明
Python的输入与输出
name = "吴鹏"
# 普通的输出变量
print(name)
# 输出变量不换行
# print(name, end='')
# 第二种格式化输出变量
a = '吴鹏'
b = 20
print("a:{},b:{}".format(a, b))
# 输入变量
data = input("请输入你的名字:") # 可以作为一个变量然后返回打印输出
print(data)
Python中rbuf的含义
- 在输出前面使用f,就相当于format的用法.
- 在输出前面使用r,就相当于去除转义字符,一般在写路径的情况下我们可以直接复制目录,输出前使用r
- 在输出之前使用b,就可以识别字节类型的,如果不加就会认为是个普通的字符串,比如读取音视频文件的时候一般都是bytes数据
- 在输出之前使用u,后面的字符串就会以Unicode格式进行编码
变量、数据类型和运算符
变量
- 什么是变量? 可能改变的数据叫做变量
- 变量规则
- 变量名必须是大小写英文字母_数字或下划线_的组合,不能用数字开头,并且对大小写敏感.
- 关键字不能用于命名变量(31个),如and、as、assert等
- 注释
- # 表示注释一行内容
- """ """ 表示注释多行内容
- 什么是标识符? 在python中所有可以自主命名的内容都属于标识符,比如:变量名、函数名、类名
- python中遵循两种命名规范
- 下划线命名法
- 帕斯卡命名法(大驼峰命名法)
数据类型
- Python语言常用数据类型包括整型、浮点型、字符串、布尔型和空值
- 数据类型转换可以把一些数据转换成我们需要的类型
- int() 转换成数字
- float() 转换成小数
- str() 转换成字符串
- bool() 转换成布尔值
- 对浮点数进行运算时,可能会得到一个不精准的结果
- 一般使用三重引号来表示一个长字符串,三重引号可以换行,并且会保留字符串中的格式
- 使用type()方法可以对数据类型进行类型检查
字符串
- 字符串之间可以进行加法运行,如果两个字符串进行相加,则会自动将两个字符串拼接为一个
- 在创建字符串时,可以在字符串中指定占位符,%s在字符串中表示任意字符
- %f表示浮点数占位符 一般用于数字
- %d表示整数占位符 一般用于数字
- %.5s字符串的长度限制5个字符
- 格式化字符串
- 如果将字符串和数字相乘,则解释器会将字符串重复指定的次数返回
a = "你是头猪%s" % "顾成龙" + ",是的吧"
print(a)
# 如果传入多个参数,那么%后面加上括号,参数以逗号隔开
b = "你是%s,他是%s" % ("猪", "牛")
print(b)
# 表示保留3位字符
c = "需要几个字母:%.3s" % "牛鼻的人啊"
print(c)
# 表示浮点数长度保留3位,四舍五入
d = "需要几个字母:%.3f" % 123.45678
print(d)
# 表示长度控制在5位,如果是三位整数,会在前面补全为0
e = "需要几个字母:%.5d" % 123.45678
print(e)
# 使用格式化参数
name = "顾成龙"
f = f"你是{name}吗"
print(f)
# 使用format进行格式化输出
g = "你是{}吗?".format("猪")
print(g)
布尔值
布尔值实际上也属于整型,True就相当于1,False就相当于0,是可以跟数字进行运算的
类型转换
所谓的类型转换,将一个类型的对象转换为其他对象
类型转换不是改变对象本身的类型,而是将对象的值转换为新的对象
类型转换的四个函数 int() float() str() bool()
- int()可以将其他的对象转换为整型,该函数不会对原来的变量产生影响,是对象转换为指定的类型并将其作为返回值返回,如果希望修改原来的变量,需要对变量进行重新赋值
- 将布尔值转换 True→1 False→0
- 浮点数转换 直接取整,省略小数点后的内容
- 字符串转换 合法的整数字符串,直接转换为对应的数字,如果不是一个合法的整数字符串,就会报错
- float()和init()基本一致,不同的是它会将对象转换为浮点数
- str()可以将对象转换为字符串
- bool()可以将对象转换为布尔值,任何对象都可以转换为布尔值
日期类型
首先引入datatime
import datetime
# 获取当前时间
time = datetime.datetime.now()
print(time)
# 获取一个指定日期
this_time = datetime.datetime(2019, 10, 1, 12, 3, 30)
print(this_time)
# 日期转字符串
d = time.strftime("%Y-%m-%d %H:%M:%S")
print(d)
# 字符串转日期
s = "2017-10-1 10:30:59"
m = time.strptime(s, "%Y-%m-%d %H:%M:%S")
print(m)
运算符
运算符的种类
- 算数运算符 + - * / // ** //表示a除以b向下圆整,丢弃小数部分 **表示a的b次方
- 关系运算符 == != > < >= <=
- 赋值运算符 = += -= *= /= %= **= //=
- 逻辑运算符 and or not
运算符的优先级
在python运算中有优先级
运算符的优先级可以根据优先级的表格来查询
在表格中为止越靠下的运算符优先级越高,优先级越高的越优先计算,如果优先级一样则自左向右计算
一般在开发中遇到优先级不清楚,基本使用小括号来改变运算顺序(基本上小括号是通用)
特殊的数据类型(容器)
列表
# 可以存放任意的数据类型
a=[1,2,3,"wupeng",[1,2,3]]
获取指定位置的值,如:print(a[3])
如果使用的索引超过了最大的范围,会抛出异常
# 列表的切片
做切片操作时,总会返回一个新的列表,不会影响原来的列表
print(a[0:3]) 包括0,不包括3
print(a[-4:-1]) 包括-4,不包括-1 倒数第四个开始-倒数第一个结束(不包括) 取值:2,3,"wupeng"
# 通用操作
可以将两个列表拼接为一个列表
mylist=[1,2,3]+[4,5,6]
print(mylist)
也可以将列表重复几次
mylist=[1,2,3]*3
print(mylist)
使用in和not in来检查元素是否存在于列表中
len() 获取类表中元素的个数
min() 获取列表中的最小值
max() 获取列表中的最大值
index() 可以获取指定元素在列表中第一次的索引,第一个参数是元素,第二个参数表示查找的起始位置,第三个参数表示查找的结束位置
append() 表示在原有数据上追加
insert(a,b) 向列表的指定位置插入一个元素,第一个参数表示插入的位置,第二个参数表示插入的参数
extend(list) 需要一个类表作为参数,会将该序列中的元素添加到当前列表中
clear() 清空序列
pop() 根据索引删除并返回被删除的元素
remove() 删除指定的元素,如果相同值的元素有多个,只会删除第一个
reverse() 用来反转列表
sort() 用来对列表中的元素进行排序,默认是升序排列,如果需要降序排列,则需要传递一个reverse=True作为参数
# 指定位置添加元素
a.insert(2,4) 在列表的下标为2的位置后面添加4
# 通过索引修改元素
a=[1,2,3,4,5]
a[0]=2
print(a)
# 通过切片来修改列表,在给切片进行赋值时,只能使用序列
mylist[0:2]=[1,2,3] 打印出来的结果会将索引为0,1的数值换掉
# 函数(range)
range()是一个函数,可以用来生成一个自然数的序列
该函数需要三个参数
1. 起始位置
2. 结束位置
3. 步长(可以省略,默认是1(常用也是默认值))
序列
序列是python中最基本的一种数据结构
序列用于保存一组有序的数据,所有的数据在序列当中都有一个唯一的位置(索引),并且序列汇总的数据会按照添加的顺序来分配索引
系列的分类
- 可变序列(序列中的元素可以改变) 列表
- 不可变序列
- 字符串
- 元祖(如果必须修改,那么将数据去除存放于列表中,在转换为元祖)
元祖和字典
- 元祖
- 元素数据结构与列表类似,其中元素可以有不同的类型,但是元祖中的元素时不可变的,即一旦初始化之后,就不能够在做修改(报错:元祖对象不支持赋值),所以在操作元祖时,就把元祖当成跟一个不可变的列表就可以
- 一般我们希望数据不改变时,就是用元祖,其余情况都是用列表,当元祖不是空元祖时,括号可以省略,如果元祖不是空元祖,它里面至少有一个
# 元祖的解包
my_tuple=(1,2,3,4,5)
a,b,c,d,f=my_tuple
a,b=b,a
print(a,b)
# 在对一个元祖进行解包时,变量的数量必须和元祖中的元素数量一致,也可以在变量前边添加一个*,这样变量将会获取元素中所有剩余的资源(剩余的资源会产生在添加*的变量,并且以列表存在)
my_tuple=(1,2,3,4,5)
a,b,c,*d=my_tuple
a,b=b,a
print(a,b,c,d) # d的值为[4,5]
- 字典
- 字典是一种大小可变的键值对集,其中的键和值都是Python对象,字典用在需要高速查找的地方
- 字典属于一种新的数据结构,作用和列表类似,都是用来存储对象的容器
- 列表存储数据的性能很好,但是查询数据的性能很差,在查询元素时,字典的效率是非常快的
- 在字典中可以保存多个对象,每个对象都会有一个唯一的名字,我们称为键,通过key可以快速查询value,这个对象称为值
- 每个字典中都可以有多个键值对,而每个键值对我们称其为一项(item)
- 字典的值可以是任意的不可变对象,字典的键是不能重复的,如果出现重复的后边会替换到前边的
a={"username":"吴鹏","age":18}
print(a["username"]) # 能够得到值:吴鹏
# 使用dict()函数来创建字典
# 每一个参数都是一个键值对,参数名就是键,参数名就是值(这种方式创建的字典,key都是字符串)
d=dict(name="wupeng",age=18)
print(d)
# 也可以将一个包含有双值子序列的序列转换为字典,双值序列,序列中只有两个值,子序列,如果序列中的元素也是序列,那么我们成这个元素为子序列
d = dict([(4, 2), (1, 3)])
print(d) # {4:2,1:3}
# len() 可以获取字典中键值对的个数
# in 检查字典中是否包含指定键
# not in 检查字典中是否不包含指定的键
# get() 通过get获取键值对的值
d=dict(username="吴鹏",age=18)
print(d.get("username"))
# 修改字典
d=dict(username="吴鹏",age=18)
d['username']="吴磊"
print(d.get('username'))
# 字典添加键值对
# 使用setdefault()想字典中添加key-value,如果key已经存在于字典中,则返回key的值,不会对字典做任何操作,如果key已经存在于字典中,则返回key的值,不会对字典做任何操作
d=dict(username="吴鹏",age=18)
d.setdefault('username1','吴娟')
print(d)
# 将其他字典添加到当前字典update方法
d=dict(username="吴鹏",age=18)
d2={'class':123,'huiyi':333}
d.update(d2)
print(d)
集合
# 集合是一种无序集,是一组键的集合,不存储值
# 在集合中,重复的键是补被允许的,集合可以用于去除重复值
# 集合也可以进行数学集合运算
# 应用:把一个列表变成集合,就自动去重了
a={1,2,3,4,5,6}
b={4,5,6,7,8,9}
print(a-b) 表示集合的差集:1,2,3
print(a|b) 表示集合的并集:1,2,3,4,5,6,7,8,9
print(a&b) 表示集合交集:4,5,6
print(a^b) 表示集合的对称差:1,2,3,7,8,9
bytes与字符串的转化
区别与介绍
- decode是解码,encode是编码
- 解码代表bytes类型转成str类型
- 编码代表str类型转成bytes类型
- bytes类型的数据一般在写入文件时需要用到
转换演示
b = b'\xe9\x80\x86\xe7\x81\xab'
string = str(b, 'utf-8')
print(string)
# bytes转字符串方式二
b = b'\xe9\x80\x86\xe7\x81\xab'
string = b.decode() # 第一参数默认utf8,第二参数默认strict
print(string)
# bytes转字符串方式三
b = b'\xe9\x80\x86\xe7\x81haha\xab'
string = b.decode('utf-8', 'ignore') # 忽略非法字符,用strict会抛出异常
print(string)
# bytes转字符串方式四
b = b'\xe9\x80\x86\xe7\x81haha\xab'
string = b.decode('utf-8', 'replace') # 用?取代非法字符
print(string)
# 字符串转bytes方式一
str1 = '逆火'
b = bytes(str1, encoding='utf-8')
print(b)
# 字符串转bytes方式二
b = str1.encode('utf-8')
print(b)
# 输出结果
逆火
逆火
逆haha
逆�haha�
b'\xe9\x80\x86\xe7\x81\xab'
b'\xe9\x80\x86\xe7\x81\xab'
选择结构
if-else语句
if 判断条件:
执行语句
if-elif-else语句
if 判断条件:
执行语句
elif 判断条件:
执行语句
else:
执行语句
嵌套if
如果需要在某一个条件里面做二次判断,那么可以使用if嵌套,也就是if结构里面在包含一个或多个if结构
if 条件1:
if 条件2:
else:
else:
循环结构
for循环
# for循环是可以依次得到序列循环中的每个元素,并依次处理
"""
for 循环指定次数:for i in range(初始值,结束值,步长)
"""
for i in range(0,10,2):
print("打印十次")
# 对列、元祖、集合遍历
# 列
list = [1, 2, 3, 4, 5, 6]
# 元祖
list1 = (1, 2, 3, 4, 5)
# 字典
list2 = {"username": "吴鹏", "age": 18}
# 集合
list3 = {1, 2, 3, 4, "wupeng"}
# 遍历列表
for i in list:
print(i)
# 遍历元祖
for m in list1:
print(m)
# 遍历字典
for n,k in list2.items():
print(n,k)
# 遍历集合
for p in list3:
print(p)
for循环案例
# 求100以内的和
# 求1-100的和
sum = 0
for i in range(0, 101):
sum += i
print(sum)
# 求列表中的最大值
# 求列表中的最大值,思路:先设定下标为0是最大的,循环遍历列表的数,如果下标0<下标1,那么最大值=下标1
a = [1, 2, 234, 456, 678]
maxx = a[0]
for i in range(0, len(a) - 1):
if a[0] < a[i + 1]:
maxx = a[i + 1]
print(maxx)
while循环
while循环和for循环不同的是,它的停止条件是个人自己设定的
while 判断条件:
执行语句
判断条件和if语句是相同的,那么什么时候用while呢,在你确定满足条件而不确定需要的循环次数时,那么while是最好的选择
while的嵌套循环
# 循环操作20年每年的每个月递增20元,统计每年每月的金额数
i = 0
sum = 0
while i <= 20:
print("这是第", i, "年")
j=1
while j<=12:
sum+=20
print("第",i,"年,","第",j,"月,","需要交纳",sum,"元")
j+=1
i+=1
print(sum)
continue和break
- continue是结束当前循环,进行下一次循环
- break是结束整个循环
- 嵌套循环的break对应内外循环,内循环内的break结束内循环,外循环内的break结束外循环
无限循环
如果循环中的循环条件永远为真,且没有break关键字进行终端,那么就形成一个无线循环,无线循环也被成为死循环.一般情况会通过一个条件结束死循环
循环相关练习
# 计算所有的奇数之和(使用while)
num = 0
sum = 0
while num <= 100:
if num % 2 != 0:
print(num)
sum += num
num += 1
print("所有奇数和:{}".format(sum))
# 计算所有的奇数之和(使用for... in ...)
sum = 0
# 与while的区别:num不需要定义变量为0
for num in range(101):
if num % 2 != 0:
print(num)
sum += num
num += 1
print("所有的奇数之和:{}".format(sum))
# 使用for动态打印矩形
# 外层循环控制行,内层循环控制列
num = input("请输入边数:")
num = int(num)
for i in range(num - 1):
for j in range(num):
print("*", end="")
print("")
# 动态打印正三角
num = input("请输入三角的边数:")
num = int(num)
for i in range(num):
for j in range(i + 1):
print("*", end="")
print("")
# 乘法表
# 1*1=1
# 1*2=2 2*2=4
# 1*3=3 2*3=6 3*3=9
num = int(input("请输入乘法表边数(行跟列)"))
for i in range(num + 1):
for j in range(i + 1):
print("{}*{}={}".format(j + 1, i + 1, (j + 1) * (i + 1)), end=" ")
print("")
# 电脑随机一个0 - 100的数, 将用户输入的跟电脑随机的数字对比, 满分是100分, 猜错口扣10分, 分数为0, 停止程序.
import random
score = 100
# randint(0,100) 包含0跟100
a = random.randint(0, 100)
count = 0
while True:
num = int(input("请输入第{}个:".format(count + 1)))
if num > a:
print("猜大了")
elif num < a:
print("猜小了")
else:
print("猜对了")
count += 1
if count == score / 10:
break
print("分已经全没,重启程序")
"""
猜数字游戏, 电脑随机产生一个0 - 100的整数, 用户在控制台输入一个整数, 将用户输入的和电脑产生的进行对比:
如果用户猜大了, 就提示猜大了, 猜小了, 就提示猜小了, 猜对了就恭喜答对了
满分是100分,猜错一次就减10分,
当分数为0的时候,停止程序。
"""
import random
content = random.randint(0, 100)
count = 0
score = 100
while True:
if score == 0:
print("您的分数已经归为0,再见")
break
num = int(input("请输入第{}个数:".format(count + 1)))
if num > content:
print("您猜大了")
score -= 10
print("当前分数为:{}".format(score))
elif num < content:
print("您猜小了")
score -= 10
print("当前分数为:{}".format(score))
else:
print("恭喜你,猜对了,当前分数为:{}".format(score))
break
count += 1
"""
随机加减乘除运算, 一共出10题, 电脑随机产生2个0 - 100的整数, 进行随机加减乘除法计算
然后用户输入计算结果, 判断用户输入的是否正确, 回答正确就加十分, 错误就不加分, 10题全对就是100分
"""
import random
score = 0
test = 0
sum = 0
while True:
if test == 10:
break
num1 = random.randint(0, 100)
num2 = random.randint(0, 100)
t = random.randint(0, 3)
if t == 0:
print("请回答第{}题:{}+{}=?".format((test + 1), num1, num2))
sum = num1 + num2
elif t == 1:
print("请回答第{}题:{}-{}=?".format((test + 1), num1, num2))
sum = num1 - num2
elif t == 2:
print("请回答第{}题:{}*{}=?".format((test + 1), num1, num2))
sum = num1 * num2
else:
print("请回答第{}题:{}//{}=?".format((test + 1), num1, num2))
sum = num1 // num2
user = int(input("请输入结果:"))
if user == sum:
score += 10
print("回答正确加10分,当前分数为:{}".format(score))
else:
print("回答错误减10分,当前分数为:{}".format(score))
print("当前总分为:{}".format(score))
test += 1
# 创建一个10个长度整数列表, 列表中的10个元素, 使用随机数赋值, 范围0 - 100, 然后找出列表中的最大值
import random
list = []
for i in range(10):
list.append(random.randint(0, 100))
for j in range(len(list)):
max = list[0]
if max < list[j]:
max = list[j]
print(list[i], end=" ")
print("最大值为max:{}".format(max))
# 冒泡排序
num = [51, 12, 55, 29, 18, 18, 18, 18, 55, 295, 5, 29]
for i in range(len(num)):
# 选出最大去掉一个
for j in range(len(num) - 1 - i):
if num[j] > num[j + 1]:
t = num[j]
num[j] = num[j + 1]
num[j + 1] = t
print(num)
"""
从26个字母中,随机选出4个不重复的字母并且把4个字母,添加到一个列表中
用户在控制台输入4个字母,将用户输入的也添加到一个列表中
然后将电脑的和用户的进行对比
"""
import random
# 从26个字母中,随机选出4个不重复的字母
def getChar():
c1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z']
c2 = []
for i in range(4):
index = random.randint(0, len(c1) - 1)
c2.append(c1[index])
del c1[index]
print(c2)
return c2
# 检查用户输入是否正确的
def check(charList, user):
# 第一个下标保存猜对了几个,
# 第二个下标保存位置对了几个
result = [0, 0]
for i in range(len(charList)):
if user[i] in charList:
result[0] += 1
if user[i] == charList[i]:
result[1] += 1
print("猜对了{}个,位置对了{}个。".format(result[0], result[1]))
return result
print("猜字母游戏开始了。")
charList = getChar()
while True:
str = input("请输入四个字母,退出输入exit")
if str == "exit":
break
user = []
for s in range(4):
user.append(str[s])
print(user)
res = check(charList, user)
if res[1] == 4:
print("恭喜,全部猜对了")
break
print("游戏结束")
函数和模块
初识函数
# 函数就是可以把我们要执行的代码放到一起,需要执行的时候直接调用就可以.
# 函数的命名规则
def name(x):
s=x*x
return s
def 是个关键字
name 是函数命名
x 输入一个参数
return 返回一个值
参数传递
介绍
- 必传参数:平时最常用,必传确定数量的参数
- 缺省参数:在调用函数时可以传也可以不传,如果不传将使用默认值
- 可变参数:可变长度参数
- 关键字参数:长度可变,但是需要以key-value形式传参
实例演示
# 必填参数和缺省参数的结合
# 必填参数a,缺省参数b
def test1(a, b=3):
print(a, b)
test1(0)
# 0 3
test1(0, 1) # 0 1
注:声明函数时,当同时存在必填参数和缺省参数,形参的顺序必须是(必填参数,缺省参数),不能缺省参数在前
# 可变参数
def test2(num, num2=2, *args):
print(num, num2, args)
test2(1) # 1 2 ()
test2(1, 3) # 1 3 ()
test2(1, 3, 3, 3, 3, 3, 3) # 1 3 (3, 3, 3, 3, 3)
test2(1, *(2, 3, 4, 5)) # 1 2 (3, 4, 5)
test2(1, *[2, 3, 4, 5]) # 1 2 (3, 4, 5)
注:args是一个元祖类型,可变参数可不穿,也可以传很多个值,在元祖or列表前面加一个*,代表将里面的每个元素都独立出来,单独作为一个形参传进去
# 关键字参数
def test3(a, b=2, **kwargs):
print(a, b, kwargs)
test3(1) # 1 2 {}
test3(1, 3) # 1 3 {}
test3(1, **{"key": "value"}) # 1 2 {'key': 'value'}
test3(1, 3, **{"key": "value", "key1": "val", "key2": 'val2'}) # 1 3 {'key': 'value', 'key1': 'val', 'key2': 'val2'}
test3(1, name="yy", key="value") # 1 2 {'name': 'yy', 'key': 'value'}
test3(1, 3, name="yy", key="value") # 1 3 {'name': 'yy', 'key': 'value'}
test3(1, name="yy", key="value",b=222222) # 1 222222 {'name': 'yy', 'key': 'value'}
# test3(1, 22222,name="yy", key="value",b=222222) # 会报错,因为第二个值已经传给缺省参数b了
# 注:
# kwargs是一个字典类型,关键字传参数可传可不传
# 如果传dict需要在前面加上**,表示将这个dict的所有key-value当成独立的关键字参数,(变成key=value)传入到kwargs,而修改kwargs不会影响原来的dict
# 不用dict的话也可以直接 key=value 的写法,如果和缺省参数重名,若前面没有传值的话,会当成缺省参数传值;若有的话会直接报错声明函数时,缺省参数不可以放在可变参数后面
# 四种参数类型都有的函数
def test4(a, b=2, *args, **kwargs):
print(a, b, args, kwargs)
test4(1) # 1 2 () {}
test4(1, 1) # 1 1 () {}
test4(1, *(1, 2, 3, 3, 4,)) # 1 1 (2, 3, 3, 4) {}
test4(1, *(1, 2, 3, 3, 4,), cc=123, c=123) # 1 1 (2, 3, 3, 4) {'cc': 123, 'c': 123}
lists = ["a", "b"]
dicts = {"key": 123}
test4(1, *lists, **dicts) # 1 a ('b',) {'key': 123}
作用域
作用域是指变量生效的区域
变量定义在函数内部,所以作用域就是函数内部,函数外部无法访问
在python中一共有两种作用域
- 全局作用域
- 全局作用域在程序执行时创建,在程序执行结束时销毁
- 所以函数以外的区域都是全局作用域
- 在全局作用域定义的变量都属于全局变量,全局变量可以在程序的任意位置被访问
- 函数作用域
- 函数作用域在函数调用时创建,在调用结束时销毁
- 函数每调用一次就会产生一个新的函数作用域
- 在函数作用域中定义的变量,都是局不变量,它只能在函数背部被访问
变量的查找
当我们使用变量时,会优先在当前作用域中寻找该变量,如果有则使用,如果没有则继续去上一级作用域中寻找,如果有就使用,如果依然没有则继续去上一级作用域中寻找,以此类推,知道找到全局作用域,依然没有找到则会抛出异常.
# 在函数中为变量赋值时,默认都是为局部变量赋值,如果希望在函数内部修改全局变量,则需要使用global关键字来声明变量,然后在进行修改
def fun():
global a
a = 10
print(a)
fun()
print(a) # 上面使用global a,已经将a变成全局,然后a修改为10,所以这里也就打印10
命名空间
- 命名空间指的是变量存储的位置,每一个变量都需要存储到指定的命名空间当中
- 每一个作用域都会有一个它对应的命名空间
- 全局命名空间,用来保存全局变量,函数命名空间用来保存函数中的变量
- 命名空间实际上就是一个字典,是一个专门用来存储变量的字典
- locals()用来获取大年作用域的命名空间
- 如果在全局作用域中调用locals()则获取全局命名空间,如果在函数作用域中调用locals()则获取函数命名空间,返回的是一个字典
- 向scope中添加一个key-value就相当于在全局中创建一个变量
- 在函数内部调用locals()会获取到函数的命名空间
- 可以通过scope来操作函数的命名空间,但是不建议这么做
def un1():
a = 1
scope = locals()
print(scope)
un1()
递归
递归简单理解就是自己去引用自己,递归式函数,在函数中自己调用自己.
递归是解决问题的一种方式,和循环很像,整体思想是将一个大问题分解为一个个的小问题,直到问题无法分解时,在去解决问题
- 基线条件 问题可以被分解为最小问题,当满足基线条件时,递归就不再执行了
- 递归条件 将问题继续分解的条件
def fun(n):
# 基线条件
if n == 1:
return 1
# 递归条件
return n * fun(n - 1)
print(fun(3))
递归练习
# 计算n**i
# 10**5=10*10**4
# ...
# 10**1=10
def power(n, i):
if i == 1:
return n
return n * power(n, (i - 1))
print(power(10, 5))
高阶函数
接收函数作为参数,或者将函数作为返回值的函数是高阶函数
def fun1(i):
if i > 5:
return True
else:
return False
def fun2(i):
if i % 2 == 0:
return True
else:
return False
l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def method(func, lst):
new_list = []
for n in lst:
if func(n):
new_list.append(n)
return new_list
print(method(fun1, l))
匿名函数
# filter()可以从序列中过滤出符合条件的元素,保存到一个新的序列中
参数:
1. 函数,根据该函数来过滤序列(可迭代的结构)
2. 需要过滤的序列(可迭代的结构)
返回值:过滤后的新序列(可迭代的结构)
def fun(i):
return i % 3 == 0
l = [12, 3, 4, 5, 6, 7, 8, 9]
r = filter(fun, l)
print(list(r))
# fun是作为参数传递进filter()函数中,而fun实际上只有一个作用,就是作为filter()参数,filter调用完毕以后,fn4就已经没用
# 匿名函数lambda函数表达式
# lambda函数表达式专门用来创建一些简单的函数,是函数创建的有一种方式
# 语法:lambda 参数列表:返回值
l = [12, 3, 4, 5, 6, 7, 8, 9]
r = filter(lambda i: i % 3 == 0, l)
print(list(r))
# map()函数可以对可迭代对象中的所有元素做指定的操作,然后将其添加到一个新的对象中返回
l = [12, 3, 4, 5, 6, 7, 8, 9]
r = map(lambda i: i * 2, l)
print(tuple(r))
排序函数(sort)
# sort() 该方法用来对列表中的元素进行排序,默认是直接比较列表中的元素大小,在sort可以接收一个关键字参数key,key需要一个函数作为参数,每次都会以列表中的一个元素作为参数来调用函数,并且使用函数的返回值来比较元素的大小
l = ["a", "bbb", "cc", "dddd"]
l.sort(key=len)
print(l)
# sorted() 这个函数和sort()的用法基本一致,但是sorted()可以对任意的序列进行排序,并且使用sorted()排序不会影响原来的对象,而是返回一个新对象
闭包
# 将函数作为返回值返回,也是一种高阶函数,这种高阶函数我们也称为闭包,通过闭包可以创建一些只有当前函数能访问的变量,可以将一些私有的数据藏到闭包中
def fun():
def fun1():
print("你是猪")
return fun1
fun()()
内置函数
数学相关
- abs(a) 求绝对值
- max(list) 求list最大值
- min(list) 求list最小值
- sum(list) 求list元素的和
- sorted(list) 返回排序后的list
- len(list) list长度
- divmod(a,b) 获取商和余数,返回的是元祖,(商,余数)
- pow(a,b) 获取乘方数,与a**b类似
- round(a,b) 获取指定位数的小数 表示保留b位小数
- range(a,b) 生成一个a-b的值,左闭右开
类型转换
- int(str) 转换为int类型
- float(int/str) 将int类型或字符类型转换为浮点型
- str(int) 转换为字符型
- bool(int) 转换为布尔类型
- list(iterable) 转换为list
- dict(iterable) 转换为字典
- enumerate(iterable) 返回一个枚举对象
- tuple(iterable) 转换为元祖
认识模块
- 模块是Python中的最高级别组织单元,将程序代码和数据封装起来以便重用,模块的作用,一个py文件就是一个模块
- 代码重用
- 实现共享服务和数据
- 导入从本质上讲,就是在一个文件中载入另一个文件,并且能够读取那个文件的内容,一个模块内的内容通过这样的方法其属性能够被外界使用,在一个模块中引入外部模块
- import 模块名 模块名,就是python文件的名字,注意不要py
- import 模块名 as 模块别名
- 可以引入同一个模块多次,但是模块的实例只会创建一个
- import可以在程序的任意位置调用,但是一般情况下,import语句都会统一写在程序的开头
- 在每一个模块内部都有一个__name__属性,通过这个属性可以获取到模块的名字
- 也可以只引入模块中的部分内容(语法 from 模块名 import 变量,变量...)
- 也可以为引入的变量使用别名(语法 from 模块名 import 变量 as 别名)
文件读写
# 文件读取
# 读取txt中的数据
file = open('th.txt', 'r')
result = file.read()
print(result)
file.close()
# 读取txt中的第一行数据(需要获取第二行在读取一次)
file = open('th.txt', 'r')
result1 = file.readline()
print(result1)
file.close()
# 循环读取txt中的所有行数据
file = open('th.txt', 'r')
result1 = file.readlines()
for i in result1:
print(i)
file.close()
# 文件写入
# 如果文件存在,就重新写入;如果文件不存在则新建一个文件并写入
file = open('th.txt', 'w')
file.write("你不是很聪明")
print(file)
file.close()
# 文件追加写入
# 如果文件存在,就重新写入;如果文件不存在则新建一个文件并写入
file = open('th.txt', 'a') # a表示append 追加写入
file.write("你不是很聪明")
print(file)
file.close()
# 文件读取二进制文件
# 如果文件存在,就重新写入;如果文件不存在则新建一个文件并写入
file = open('th.txt', 'rb') # a表示append 追加写入
result = file.read()
print(result)
# 将读取文件封装成方法(使用with...as的作用就是打开后,最终自动关闭)
def read_txt(fileName):
filepath = "C:/Users/17327/PycharmProjects/yunhe/data/" + fileName
arr = []
with open(filepath, "r", encoding="utf-8") as file:
datas = file.readlines()
for data in datas:
arr.append(tuple(data.strip().split(",")))
return arr
# seek()可以修改当前读取的位置,需要两个参数
1. 第一个是要切换到的位置
2. 计算位置方式,可选值
1. 0 从头计算,默认值
2. 1 从当前位置计算
3. 2 从最后位置开始计算
# tell()方法用来查看当前读取的位置
# 读取文件的其他方法
# 引入os
os.listdir() 获取指定目录的目录结构,需要一个路径作为参数,会获取到该路径下的目录结构,默认路径为.,当前目录,该方法会返回一个列表,目录中的每一个文件的名字都是列表中的一个元素
os.getcwd() 获取当前所在的目录
os.chdir("c:/") 切换到当前所在目录
os.mkdir("aaa") 在当前目录下创建一个名字为aa的目录
os.rmdir("abc") 删除目录
os.remove("aa.txt") 删除文件
os.rename("旧名字","新名字") 可以对一个文件进行重命名,也可以用来移动一个文件
操作excel读写
创建工作簿
待更新...
待更新...
面向对象
一个类中的基本组成
class Dog(object):
tpyes = "阿拉斯加" # 类变量
# 初始化方法
def __init__(self, name, age, sex):
# 实例化变量(属性)
self.name = name
self.age = age
self.sex = sex
# 定义普通方法
def eat(self):
print("狗仔吃饭")
def run(self):
print("狗仔跑步")
实例化对象、self和初始化方法
class Dog(object):
types = "宠物" # 类变量
# 初始化方法,也就是在对象创建的时候就会调用这个方法
def __init__(self, name, age, sex): # self表示当前对象
# 实例化变量(属性)
self.name = name
self.age = age
self.sex = sex # self.__sex=sex 表示私有化(要想获取,需要在类内部定义一个方法调用self.__sex)
# 定义普通方法
def eat(self, speed):
print(self.name + "狗仔吃饭" + "特别快" + speed)
def run(self):
print("狗仔跑步")
# 实例化对象
dog = Dog('阿拉斯加', '18', '雄')
dog.name = '萨摩耶'
print(dog.name)
dog.eat("3m/s")
类的继承和多态
# 创建一个父类
class Animal(object):
def __init__(self,color):
self.color=color
def eat(self):
print("动物在吃")
def run(self):
print("动物在跑")
# 创建一个子类继承
from animal import Animal
import all
class Cat(Animal):
pass
class Dog(Animal):
def __init__(self, name, age, color):
super().__init__(color) # 调用父类的color,dog同样继承
self.name = name
self.age = age
def eat(self):
print("狗仔吃饭")
def run(self):
print("狗仔跑步")
an1 = Animal("绿色")
cat = Cat("黄色")
cat.eat()
dog = Dog("阿拉斯加", 19, "黄色")
dog.eat()
print(dog.color)
all.feed(an1) # 模拟多态实现动物在吃
all.feed(cat) # 模拟多态实现猫在吃,如果没有eat方法,调用父类方法
all.feed(dog) # 模拟多态实现狗在吃
方法的重写及super()
- 如果在子类中如果有和父类同名的方法,则通过子类实例去调用方法时,会调用子类的方法而不是父类的方法,这个特点我们称之为方法的重写(也可以叫做覆盖)
- 当我们调用一个对象的方法时,会优先去当前对象中寻找是否具有该方法,如果有则直接调用,如果没有则去当前对象的父类中寻找,如果父类中有则直接调用父类中的方法,如果没有则去父类的父类中寻找
- 父类中的所有方法都会被子类继承,包括特殊方法.同样也可以重写特殊方法
- 希望可以调用父类的__init_来初始化父类中定义的属性,super()可以用来获取当前类的父类,并且通过super()返回对象调用父类方法时,不需要传递self
class Animal:
def __init__(self, name, age, nom):
self.name = name
self.age = age
self.nom = nom
def run(self):
print("你确实会跑")
class Dog(Animal):
def __init__(self, name, age, nom, sex):
super().__init__(name, age, nom)
self.sex = sex
def run(self):
print(self.name, self.age, self.nom, self.sex)
d = Dog("wupeng", 12, 23, 45)
d.run()
多重继承
- 在python中支持多重继承,也就是我们可以为一个类同时指定多个父类,可以在类名的()后面添加多个类,来实现多重继承
- 多重继承,会使子类同时拥有多个父类,并且会获取到所有父类中的方法
- 在开发中没有特殊的情况,应该尽量避免使用多重继承,因为多重继承会让我们的代码过于复杂
- 如果多个父类中有同名的方法,则会先在第一个父类中寻找,然后找第二个,然后找第三个,前边父类的方法会覆盖后边父类的方法
属性和方法
- 类属性,直接在类中定义的属性是类属性,类属性可以通过类或类的实例访问到,但是类属性只能通过类对象来修改,无法通过实例对象修改
- 实例属性,通过实例对象添加的属性属于实例属性,实例属性只能通过实例对象来访问和修改,类对象无法访问修改
- 实例方法,在类中定义,以self为第一个参数的方法都是实例方法,实例方法在调用时,python会将调用对象作为self传入,实例方法可以通过实例和类去调用,当通过实例调用时,会自动将当前调用对象作为self传入,当通过类调用时,不会自动传递self,此时我们必须手动传递self a.test()等同于A.test(a)
- 类方法,在类内部使用@classmethod来修饰的方法属于类方法,类方法的第一个参数是cls,也会被自动传递,cls就是当前的类对象,类方法和实例方法的区别,实例方法的第一个参数是self,而类方法的第一个参数是cls类方法可以通过类去调用,也可以通过实例调用,没有区别 A.test()
- 静态方法,在类中使用@staticmethod来修饰的方法属于静态方法,静态方法不需要指定任何的默认参数,静态方法可以通过类和实例去调用,基本上是一个和当前类无关的方法,它只是一个保存到当前类中的函数,一般都是一些工具方法,和当前类无关,并且有个特点,不需要传递self或者cls
股票提醒系统实战
# 需要安装Tushare,Tushare是一个免费、开源的ptyhon财经数据接口包,主要实现对股票等金融数据从数据采集、清洗加工到数据存储的过程,能够为金融分析人员提供快速、整洁和多样的便于分析的数据. pip install tushare
代码实现:
import time
import tushare
import datetime
class GetShare(object):
def __init__(self, code):
self.dateNow = tushare.get_realtime_quotes(code)
datetime.datetime.now()
def getShare(self):
# 股票名
name = self.dateNow.loc[0][0]
# 当前价格
price = float(self.dateNow.loc[0][3])
# 最高价
high = self.dateNow.loc[0][4]
# 最低价
low = self.dateNow.loc[0][5]
# 成交量
volumn = self.dateNow.loc[0][8]
# 成交额
amount = self.dateNow.loc[0][9]
# 开盘价
openToday = self.dateNow.loc[0][1]
# 收盘价
pre_close = self.dateNow.loc[0][2]
# # 时间
# timee = self.dateNow.loc[0][30]
return print("股票名:", name, "\t", "当前价格:", price, "\t", "最高价:", high, "\t", "最低价:", low, "\t", "成交量:", volumn,
"\t", "成交额:",
amount, "\t", "开盘价:", openToday, "\t", "收盘价:", pre_close, "\t", "当前时间:",
datetime.datetime.now(), "\t")
ge = GetShare("300026")
ge1 = GetShare("600577")
ge2 = GetShare("300152")
list1 = [ge, ge1, ge2]
while True:
for i in list1:
i.getShare()
print("")
ge.getShare()
print(
"\n---------------------------------------------------------------------------------------------"
"---------------------------------------------------------------------------------------------")
time.sleep(10)
错误和异常
- 错误一般就是指语法错误,也就是解析错误,通常在IDE已经会提醒有语法错误了.
- 异常一般在ide无法直接检测出来,在我们执行到代码语句时,若有异常则会自动抛出.
常见的具体内置异常
均是Exception的子类
- AssertionError:assert断言失败时引发
- AttributeError:属性引用(如: 实例对象.方法 )失败或赋值失败(如: 对象=值 )
- ImportError:加载模块失败时引发,如: from list import test ,若找不到test则报此异常
- ModuleNotFoundError:当一个模块找不到时引发,如: import testss ,testss不存在则报此异常;是ImportError的子类
- IndexError:取序列索引超出范围
- KeyError:在字典中找不到指定的Key
- TypeError:当一个操作或函数被应用于类型不适当的对象时将被引发,传入参数的类型错误(如:传了string给一个int类型的参数)
- ValueError:当传入的参数类型正确,但值不正确时引发(如:传入要求范围之外的数值)
- UnicodeEncodeError:编码错误
- UnicodeDecodeError:解码错误
- OSError:调用操作系统函数时报错引发该异常,一般是I/O操作
OS异常
以下所有异常都是OSError的子类
- FileExistsError:文件已存在(如:创建一个文件)
- FileNotFoundError:文件找不到(如:open一个文件)
- PermissionError:没有权限操作文件(如:写入内容到一个正在打开的文件)
- IsADirectoryError:对目录进行文件操作(如:os.remove() 传入目录路径)
- NotADirectoryError:对文件进行目录操作(如:os.listdir() 传入文件路径)
异常处理
认识异常
- 异常处理就是在写Python时,经常看到的报错信息
- 异常是一个时间,该事件会在程序执行过程中发生,一般情况下,在Python中无法处理程序时就会发生异常,当Python无法处理程序时就会发生异常,当Python脚本发生异常时,我们需要捕获并处理异常
- 在运行过程中,不可避免的会出现一些错误,这些错误在程序汇总,我们称其为异常,程序运行过程中,一旦出现异常将会导致程序立即终止,异常以后的代码全部都不会执行
a=[1,2,3,0,1,54,3,"a",2,1]
for i in a:
try:
if 3/i==1:
print("有东西")
else:
print("东西没用")
except:
print("此处出现异常")
try-except-else-finally
常见的错误和异常
- NameError 这是比较常见的一个错误,就是没有定义变量就拿来用
- SyntaxError 语法错误,少了冒号,没有空格等
- IO error 在做文件操作的时候常遇到的错误,例如文件操作的饿时候文件不存在
- ZeroDivisionError 在做数据处理和计算的时候会遇到这种错误,就是除数是0
- IndentationError 这是新手常遇到的一种错误,就是缩进问题
# try-except-else的用法
a = [1, 2, 3, 0, 1, 54, 3, "a", 2, 1]
for i in a:
try:
if 3 / i == 1:
print("有东西")
else:
print("东西没用")
except:
print("此处出现异常")
else:
print("异常没有抛出,是正确的") # 在没有走except抛出异常而是走try的时候,会执行else的内容
# try-except-else-finally的用法
a = [1, 2, 3, 0, 1, 54, 3, "a", 2, 1]
for i in a:
try:
if 3 / i == 1:
print("有东西")
else:
print("东西没用")
except:
print("此处出现异常")
else:
print("异常没有抛出,是正确的") # 在没有走except抛出异常而是走try的时候,会执行else的内容
finally:
print("最终结束内容") # 有异常也输出,没有异常也输出
自定义异常
a="123456"
if len(a)<8:
ex=Exception("不能小于8位")
raise ex
else:
print("可以进行操作")
网络编程
网络通信概述
- 互联网→路由器(分支)→主机(分支)
- 协议类似于一种规定
- 不同种类之间的计算式是通过大家任何都遵守的协议来进行数据传递,这个计算机都遵守的网络通信协议就叫做TCP/IP协议
端口
- 端口好比一个房子的进出口,如果一个进程需要收发网络数据,那么就需要这样的端口,在linux中,端口可以有65536个之多,操作系统为了统一管理,所以进行了编号,这就是端口号
- 端口是通过端口号来标记的,端口号只有证书,范围是从0-65535
- 知名端口
- 80 分配给HTTP服务
- 21 分配给FTP服务
- 动态端口
- 动态端口的范围是从1024-65535,它不固定分配某种服务,而是动态分配,动态分配是指当一个系统进程或应用程序进程需要网络通信时,它向主机申请一个端口,主机从可用的端口号中分配一个供它使用.当这个进程关闭时,同时也就释放了所占用的端口号
- 端口号的作用 一台拥有IP地址的主机可以提供许多服务,这些服务完全可以通过1个IP地址来实现,那么为了区分不同的网络服务,所以需要使用IP地址+端口号来区分服务,需要注意的是,端口号并不是一一对应的,比如你的电脑作为客户机访问一台www服务时,www服务器使用80端口与你的电脑通信,但你的电脑则可能使用3457这样的端口
IP地址
- ip地址 用来在网络中标记一台电脑的一串数字,比如192.168.1.1,在本地局域网是唯一的
- 每个IP地址包括两部分:网络地址和主机地址
- ip地址分为五类
- A类保留给政府机构 由1字节的网络地址和3字节主机地址组成,网络地址的最高位必须是0(1.0.0.1)
- B类分配给中等规模的公司 由2个字节的网络地址和2个字节的主机地址组成,网络地址的最高位必须是10(128.1.0.1)
- C类分配给任何需要的人 c类网络可达2097152个,每个网络能容纳254个主机
- D类用于组播 第一个字节以1110开始
- E类用于实验 第一个字节以1111开始
- 私有IP
- 在这么多网络IP中,国际规定有一部分IP地址是用于我们的局域网使用,也就是属于私网IP,不在公网中使用范围是10.0.0.0-10.255.255.255 172.16.0.0-172.31.255.255
- IP地址127.0.0.1~127.255.255.255用于回路测试,可以测试本机中配置的web服务器
TCP
- TCP/IP协议是一个协议族,里面包括很多协议,UDP只是其中的一个,之所以命名为TCP/IP协议,因为TCP、IP协议是两个很重要的协议
- TCP/IP协议包括应用层、传输层、网络层、网络访问层
- TCP的三次握手,四次挥手
- 三次握手,建立TCP连接时,需要客户端和服务器共发送3个包。
- 第一次:客户端发送初始序号x和syn=1请求标志
- 第二次:服务器发送请求标志syn,发送确认标志ACK,发送自己的序号seq=y,发送客户端的确认序号ack=x+1
- 第三次:客户端发送ACK确认号,发送自己的序号seq=x+1,发送对方的确认号ack=y+1
- 四次挥手
- 第一次挥手:客户端发出释放FIN=1,自己序列号seq=u,进入FIN-WAIT-1状态
- 第二次挥手:服务器收到客户端的后,发出ACK=1确认标志和客户端的确认号ack=u+1,自己的序列号seq=v,进入CLOSE-WAIT状态
- 第三次挥手:客户端收到服务器确认结果后,进入FIN-WAIT-2状态。此时服务器发送释放FIN=1信号,确认标志ACK=1,确认序号ack=u+1,自己序号seq=w,服务器进入LAST-ACK(最后确认态)
- 第四次挥手:客户端收到回复后,发送确认ACK=1,ack=w+1,自己的seq=u+1,客户端进入TIME-WAIT(时间等待)。客户端经过2个最长报文段寿命后,客户端CLOSE;服务器收到确认后,立刻进入CLOSE状态。
UDP
- 是一个非连接的协议,传输数据之前源端和终端不建立连接,当它传送时,简单的抓取来自应用程序的额数据,尽可能快的扔到网络上,在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制,在接收端,UDP把每个消息段放在队列总,应用程序每次从队列中读一个消息段.
- 由于传输数据布简历连接,因此也不需要维护连接状态,包括收发状态,因此一台服务机可同时向多个客户机传输相同的消息
- UDP信息包的标题很短,只有8个字节,相对于TCP的20个字节信息包的额外开销很小
- 吞吐量不受拥挤控制算法的调解,只受应用软件生成数据的速率,传输带宽、源端和终端主机性能的限制
- UDP使用尽最大努力交付,既不保证可靠交付,因此主机不需要维持复杂的链接状态表
- 我们经常使用ping命令来测试两台主机之间TCP/IP通信是否正常,其实Ping命令的原理就是向对方主机发送UDP数据包,然后对方主机确认收到数据包,如果数据包是否到达的消息及时反馈回来,那么网络就是通的.
- ping命令时用来探测主机到主机之间是否可通信,如果不能ping到某台主机,表明不能和这台主机建立连接.
电子邮件
电子邮件概述
常见的电子邮件协议有SMTP、POP3、IMAP4,隶属于TCP/IP协议,默认状态下,分别通过TCP协议端口25、110和143连接
- SMTP SMTP已经是事实上的E-Mail传输的标准,使用TCP的25端口
- POP协议 用于电子邮件的接受,使用TCP的110端口
发送邮件的准备
- 邮件发送方(发送方地址,发送方客户端授权密码,SMTP服务器地址 smtp.163.com)
- 邮件内容
- 邮件接收方
- 安装pyemail
邮件的实现
import smtplib
from email.mime.text import MIMEText
msg_from = "17327767735@163.com"
pwd = "123453A" # 授权密码
to = "1059457506@qq.com"
subject = "这是我要发送的邮件"
content = "你家着火了"
# 构造邮件
msg = MIMEText(content) # msg邮件对象
msg["Subject"] = subject
msg["From"] = msg_from
msg["To"] = to
# 发送邮件
ss = smtplib.SMTP_SSL("smtp.163.com", 465)
ss.login(msg_from, pwd)
ss.sendmail(msg_from, to, msg.as_string())
多线程
进程
进程就是一段程序的执行过程,它是一个具有一定独立功能的程序关于某个数据集合的一次运动活动,它是操作系统动态执行的基本单元
进程有3种状态
- 就绪态 获取出cpu外的所有资源,之哟啊处理器分配资源就可以马上执行
- 运行态 获得了处理器分配的资源,程序开始执行
- 阻塞态 当程序条件不够时候,需要等待条件满足时候才能执行,如等待i/o操作时候,此刻的状态就叫阻塞态
进程的实现原理
先创建进程在进行提交,然后就绪,就绪如果等待i/o时,阻塞,条件满足后执行,最终在退出。
线程和多线程
- 线程 通常在一个进程中可以包含若干个线程,当一个进程中至少有一个线程,不然没有存在的意义.线程可以利用进程所拥有的资源,我们把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位
- 多线程 多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率.线程是在同一时间需要完成多项任务的时候实现的(车厢与火车的鲜明对比)
- 简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
Python的标准库提供了两个模块:_thread和threading,_thread是低级模块,threading是高级模块,对_thread进行了封装,绝大多数情况下,我们只需要使用threading这个高级模块,启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行
线程的运用(主线程和子线程)
# 主线程和子线程
import threading
import time
def run(name):
print(name, "线程开始执行了")
time.sleep(5)
# target指向一个目标
# 程序执行时,程序本身就是一个线程,叫主线程,手动创建的线程叫子线程
# 主线程的执行中不会等子线程执行完毕就会直接执行后面的代码
# 创建子线程
t1 = threading.Thread(target=run, args=("t1",))
t2 = threading.Thread(target=run, args=("t2",))
t1.start()
t2.start()
t1.join() # 等待子线程执行完毕之后在执行主线程内容(会等待5s中之后执行print)
t2.join()
print("完毕了")
# 线程锁(作用是为了防止线程在执行过程中出现跳出执行发生错乱)
import threading
import time
lock = threading.Lock() # 创建了线程锁
num = 100
# 这边方法传值,那么threading.Thread()需要传入args=(参数,)
def run():
lock.acquire() # 设置锁
global num
num = num - 1
print("线程", num, "执行了,目前的值为:", num)
lock.release() # 释放锁
for i in range(100):
td = threading.Thread(target=run)
td.start()
访问mysql数据库
python安装mysql模块包 pip install pymysql
数据库建立连接
import pymysql
# 打开数据库连接, 主机地址 端口号3306 用户名root 密码 数据库名
db = pymysql.Connect(host='localhost', port=3306, user='root', passwd='bb961202', db='animal', charset='utf8')
# 创建一个游标对象,用来操作数据库
cursor = db.cursor()
print(db)
python创建数据表
import pymysql
# 打开数据库连接, 主机地址 端口号3306 用户名root 密码 数据库名
db = pymysql.Connect(host='localhost', port=3306, user='root', passwd='bb961202', db='animal', charset='utf8')
# 创建一个游标对象,用来操作数据库
cursor = db.cursor()
# 新建表
sql = 'create table persions(name varchar(20),age int(10))'
cursor.execute(sql)
print(db)
python取消sql语句高亮背景
- 打开Settings,搜索Language Injections 勾选掉SQL select/delete/insert/update/create
- 打开Settings,Editor下找到Inspections 找到SQL勾选掉 no data source configured
python新增数据
# 需要注意的是在做python新增的时候需要commit,并且字符集数据库要跟pymysql.Connect()中的charset='utf8'一致
import pymysql
# 打开数据库连接, 主机地址 端口号3306 用户名root 密码 数据库名
db = pymysql.Connect(host='localhost', port=3306, user='root', passwd='bb961202', db='animal', charset='utf8')
# 创建一个游标对象,用来操作数据库
cursor = db.cursor()
# 新建表
# sql = "create table persions7(name varchar(20),age int(10))"
sql = 'insert into dog(name,age)values("球球",12)'
cursor.execute(sql)
db.commit()
print(db)
python查询数据
import pymysql
# 打开数据库连接, 主机地址 端口号3306 用户名root 密码 数据库名
db = pymysql.Connect(host='localhost', port=3306, user='root', passwd='bb961202', db='animal', charset='utf8')
# 创建一个游标对象,用来操作数据库
cursor = db.cursor()
# 新建表
# sql = "create table persions7(name varchar(20),age int(10))"
sql = 'select * from dog'
cursor.execute(sql)
# data = cursor.fetchone() # 获取单个对象(也就是单条数据)
# print(data)
data1 = cursor.fetchall() # 获取多个对象(也就是多条数据)
list = []
for i in data1:
list.append(i)
print(list) # 或者一个列表内包含元祖的数据
python修改数据和删除
import pymysql
# 打开数据库连接, 主机地址 端口号3306 用户名root 密码 数据库名
db = pymysql.Connect(host='localhost', port=3306, user='root', passwd='bb961202', db='animal', charset='utf8')
# 创建一个游标对象,用来操作数据库
cursor = db.cursor()
# 新建表
# sql = "create table persions7(name varchar(20),age int(10))"
sql = 'update dog set name="憨怂" where name="憨比"'
sq2='delete from dog where name="憨比1"'
cursor.execute(sql)
cursor.execute(sq2)
db.commit() # 做修改时,需要提交
db.close() # 执行任意增删改查最好关闭数据库
事务和异常处理
import pymysql
# 打开数据库连接, 主机地址 端口号3306 用户名root 密码 数据库名
db = pymysql.Connect(host='localhost', port=3306, user='root', passwd='bb961202', db='animal', charset='utf8')
# 创建一个游标对象,用来操作数据库
cursor = db.cursor()
# 新建表
# sql = "create table persions7(name varchar(20),age int(10))"
sql = 'update dog set name="憨怂" where name="憨比"'
sq2 = 'delete from dog where name="憨比1"'
try:
cursor.execute(sql)
cursor.execute(sq2)
db.commit() # 做修改时,需要提交事务,事务中的操作就是要么都提交,要么都不提交
except:
db.rollback() # 回滚所有操作都不提交
print()
db.close() # 执行任意增删改查最好关闭数据库
后续补充...