-
python实现九九乘法表
"""while循环实现九九乘法表"""
right = 1
while right <= 9:
left = 1
while left <= right:
print(f"{left}x{right}={left * right}", end='\t')
left += 1
print()
right += 1
"""for循环实现九九乘法表"""
for right in range(1,10):
for left in range(1,right+1):
print(f"{left}x{right}={left * right}", end='\t')
print()
-
python实现石头剪刀布
import random
"""石头剪刀布--基础版"""
computer = random.randint(0, 2)
player = int(input("请出拳(0:石头 1:剪刀 2:布):"))
drr = {0: "石头", 1: "剪刀", 2: "布"}
print(f'玩家输入: {drr[player]}, 电脑出拳: {drr[computer]}')
if computer == player:
print("平手!")
elif computer - player in (-1, 2):
print("电脑胜利")
else:
print("玩家胜利")
# 石头剪刀布--优化版
drr = {0: "石头", 1: "剪刀", 2: "布"}
# 轮次
epoch = 1
while True:
# 三局两胜
success_c = 0
success_p = 0
for i in range(1, 4):
computer = random.randint(0, 2)
# 判断用户输入是否是数字 以及是否在字典里
while True:
player = input(f"第{epoch}轮{i}局 请出拳(0:石头 1:剪刀 2:布):")
if player.isdigit() and int(player) in drr:
player = int(player)
break
print("输入错误,请重新输入....")
print(f'玩家输入: {drr[player]}, 电脑出拳: {drr[computer]}')
# 每一局判定胜负
if computer == player:
print(f"第{epoch}轮{i}局平手!\n")
elif computer - player in (-1, 2):
print(f"第{epoch}轮{i}局电脑胜利\n")
success_c += 1
else:
print(f"第{epoch}轮{i}局玩家胜利\n")
success_p += 1
# 如果有一方一开始连胜两局,第三局就不需要玩了
if 2 in (success_c, success_p):
break
# 本场胜负判断
if success_c == success_p:
print(f"第{epoch}轮两局三胜平手\n")
elif success_c > success_p:
print(f"第{epoch}轮两局三胜电脑胜利\n")
else:
print(f"第{epoch}轮两局三胜玩家胜利\n")
# 是否继续
while (isContinue := input("是否继续?Y(是)/N(否)")) not in ('y', 'Y', 'n', 'N'):
print("输入错误,请重新输入....")
# 结束
if isContinue in ('n', 'N'):
print("欢迎下次光临")
break
epoch += 1
-
推导式 二维数组列变行
# 正常处理 将二维数组列变行
lst = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]]
lst_new = []
for x in range(len(lst[0])):
print(x)
item = []
for y in lst:
print(y)
item.append(y[x])
print(item)
lst_new.append(item)
print(lst_new)
# 推导式
lst = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]]
lst_new = [[y[x] for y in lst] for x in range(len(lst[0]))]
print(lst_new)
-
条件运算
条件语句
if 判断条件1:
执行语句1...
elif 判断条件2:
执行语句2...
else:
执行语句4...
if 0 == None (结果为false)
if 0 | [] | 结果为false
小整数池 除了 -5--256 ,还包含 None、True、False
random模块常用函数
random.random() 返回[0.0 - 1.0] 随机浮点数 不包含1.0
random.randint(a,b) 返回[a,b] 随机整数(a>b)
random.uniform(a,b) 返回[a,b]/[b,a] 随机浮点数,自动比较大小
random.choice(seq) 非空序列返回随机元素,seq为空时报错
random.sample(pop,k)pop:总样本序列或集合, k:取几个,以列表方式返回(不放回)
py3.9 集合采样已弃用(集合不属于序列)
random.shuffle(x) 将可变序列(列表、集合、字典) 随机打乱位置,原地操作
random.randrange([start],end,[step]) 左闭又开 [start,end] 随机返回一个元素
random.seed([x]) 固定随机数的作用,x可以时任意数字,可以理解为种子
x为空时解除固定随机数
range([start],end,[step]) [start,stop,step] 左闭右开
返回数据为range(start,end) 切片之后还是range,可以转元组和list
是序列,不可变,是可迭代对象(和元组、字符串)
步长为正数 start-end必须从小到大
步长为负数 start-end 必须从大到小
优势:数据量比较大时,存储在元组或list中会占用较大内存,range 只存start、end、step,不占用内存
循环
while 循环
while 判断条件:
执行语句...
死循环 while true
for循环
(一)for i in (可迭代对象):(获取元素)
执行语句....
(二)for i in (len(可迭代对象)):(获取索引)
执行语句....
# 获取索引和元素
(三)for index, item in enumerate(lst):
执行语句.....
enumerate(可迭代对象,start =0)枚举
返回迭代器,转list之后 [(索引,元素),(索引,元素),(索引,元素)]
for循环....else 不冲突
for后面的标识符没有用到的时候 用"_"代替,里面也是有值的
跳过循环
break 结束所在循环
continue 结束本次循环
pass 空操作,什么都不执行(可临时占位)也可以用...
-
推导式
列表推导式
[表达式 for子句]
[表达式 for子句 更多的for子句或if子句]
lst = [x for x in range(9, 1, -2)]
字典推导式
{k:v for子句}
{k:v for子句 更多的for子句或if子句}
d = {x: x + 1 for x in range(9, 1, -2)}
集合推导式
{表达式 for子句}
{表达式 for子句 更多的for子句或if子句}
s = {x for x in range(9, 1, -2)}
s = {x + y for x in range(5) for y in range(1, 4)}
-
list、dict、set的迭代问题:
字典在迭代期间 不允许个数发生改变,可以修改数据,必须保证size不发生改变
集合在迭代期间 不允许改变size
列表遍历期间 删除清空全部元素时,达不到效果(遍历中元素发生改变 会导致下标发生变化),需要拷备份数据进行遍历
-
函数
自定义函数格式:
def func_name([arg1, arg2...]):
func_body...
--函数在定义时,不会执行函数提
--函数在被调用时,才会执行函数体
--函数只需要被定义一次,可以被多次调用
调用函数格式
func_name([实参1, 实参2...])
函数的好处
--结构性比较清晰
--代码简化,提高可复用性
函数是否有返回值由return决定
return的作用:
-将return后面的对象返回给函数的调用放
-结束return所在的函数
return后面可以跟单个/多个对象/表达式,
不跟就返回None
如果函数被调用,没有执行到return,等价于return None
breake/pass/continue/return
相同:都是关键字,
不同:return结束函数体,break结束循环
文档注释:
func__doc__ 输出文档注释
help([obj]) 输出obj的帮助信息 help()命令行启动帮助界面
__annotations__ 以字典的形式存放在函数属性
数学相关的内置函数
max 取最大值
max(可迭代参数,[key,default])
max(arg1,arg2,*arg,[key]) arg最少为两位
min 取最小值,用法同max
pow(base, exp, [mod])
base的exp次幂,mod存在时对米的结果取模
round(num,[ndg]) 四舍五入
ndg:保留的小数点位数,不存在保留整数位
会保留符号,
-精确到整数位时(0.5 1.5 2.53.5),如果是中间的话(0.5),遵循从偶规则
abs(num) 取绝对值
sum(可迭代参数,/,start=0) 求和
-/ * 都为特殊参数,不接受实参
-start 累计相加的开始的数字
类型标注
变量类型会随着着变量随之改变,python属于弱类型语言
变量: 类型 定义变量的类型 -> 返回类型标注
导入的两种方式
import numbers
from random import randint (random没有导入 可以直接使用randint,导入多个可以用逗号隔开
from random import randint, randrange, shuffle )
参数分类
必需参数
必须参数可以传位置参数也可以传关键字参数
位置参数 和顺序有关
关键字参数 和位置无关
关键字参数必须放在位置参数之后
默认参数 如有实参,优先接受实参,没有实参则使用自己的默认值
默认参数必须放在必需参数的后面
不定长参数
- *arg 接收[0,+∞)个位置参数,贪婪,打包成一个元组,没有实参输出空元组
- **kwargs 接收[0,+∞]个关键字参数,贪婪,打包成一个字典,没有实参输出空字典
特殊参数
/ * 特殊参数不接收实参
限制传参的格式
*的作用 *后面的参数必须为关键字参数
/的作用 限制/前面的实参必须为位置参数
匿名参数
定义:lambda [arg1,arg2...]: 一个表达式
调用匿名函数:
func_name = lambda [arg1,arg2...]: exp
func_name([实参1,实参2...])
(lambda[arg1,arg2])([实参1,实参2...])
匿名函数没有return,参数可以有多个但表达式只有一个
匿名函数可以在需要函数对象的任何地方使用(如:赋值给变量、作
为参数传入其他函数等),因为匿名函数可以作为一个表达式,而不
是一个结构化的代码块
匿名函数没有传参数 直接写 lambda: 表达式
-
封包
将多个值赋值给一个变量时,Python 会自动将这些值封装成元组,这
个特性称之为封包
a = 1,2,3,4 输出a 为元组(1,2,3,4)
多目标赋值 a=b=c=d = 1
-
解包
针对所有的可迭代对象
取值过程中的解包
a,b,c,d = [1,2,3,4] 序列赋值本质上是解包
等号两边不等长时,参数前加*号 相当于*arg,但不贪婪,会将数据打包成list,变量里的*只能存在一个
传实参中的解包
调用函数时,传入可迭代参数时 可以用单个* 函数内会解包
可迭代参数是 字典时,可以用**,函数会按照key获取值
-
递归实现兔子问题
# 兔子问题 兔子过了两个月就会生 第n个月会有多少只兔子
# 规律 前两个月的兔子数量相加等于第三个月的兔子数量
# 递归实现 m:月份
# 递归缺点是会重复大量计算,次数较多时计算会很慢
import sys
store = {}
def get_rabbit(m):
if m < 2:
return 1
# 将重复计算的数据存储在字典中,避免大量重复计算
if m in store:
return store[m]
res = get_rabbit(m - 1) + get_rabbit(m - 2)
store[m] = res
return res
sys.setrecursionlimit(1001) # 放宽递归最大深度
print(sys.getrecursionlimit()) # 查找递归最大深度限制
print(get_rabbit(45))
# print(store)
# 循环实现
def func(m):
m0 = m1 = 1
for _ in range(m - 1):
m0, m1 = m1, m0 + m1 # 序列赋值
return m1
# 循环m次返回m0 循环m-1次返回m1
print(func(6))
-
命名空间
命名空间是 从名称到对象的映射,以字典方式实现
作用: 避免名字冲突(同一命名空间中不能重名,不同命名空间可以重名而没有影响)
内置命名空间
解释器启动时创建,持续到解释器终止
由builtins模块实现
dir([obj])
obj不传 返回当前模块定义的标识符名称构成的str类型的list
传obj-返回obj下面定义好的属性、方法列表
全局命名空间
在模块读入时创建,持续到解释器退出
针对某一个py文件
记录模块的函数、变量、类、其他导入的模块
globals() # 返回当前的全局命名空间--字典类型 名称:对象
局部命名空间
在函数被调用时创建,持续到函数结束
记录函数里的变量和参数 ---针对函数
locals() 返回当前的局部命名空间 --字典
全局的locals等价于globals
命名空间查找顺序
局部--> 全局 --> 内置 --> 没找到报错
将字符串当作python程序执行
eval(exp,[globals,locals])
返回exp的返回值,针对单行
exec(obj,[globals,locals])
无返回值,针对多行字符串
globals 指定全局命名空间 locals指定局部,locals被忽略,取相同的globals
-
作用域
定义: python程序可以直接访问命名空间的正文区域
作用: 决定了那一部分区域可以访问哪个特定的区域
分类:(L - E - G - B 作用域依次增大)
局部作用域(Local) - L
闭包函数外的函数中(Enclosing) - E(闭包函数里的内部函数与外部函数之间的距离)
全局作用域(Global) - G
內建作用域(Built-in) - B
作用域查找规则: (built > globals > enclosing > local)
在当前作用域找不到对应名称,取更大一级作用域去找,最后找不到就会报错(不能往 小了找,enclosing、local可以有多个,global只能有一个)
只有函数、类、模块 会引入作用域,推导式会引入新的作用域
条件语句、循环语句不会引入新的作用域
global 和 nonlocal区别
-- global 变量名 声明当前作用域的变量a全部为全局变量
-- nonlocal 变量名 声明当前作用域的变量a全部为enclosing变量
闭包函数
一般来说,闭包函数需要满足3个条件
--首先需要是嵌套函数
--外部函数的返回值是内部函数的引用
--内部函数用到了外部函数的变量或形参
-
常用高阶函数
定义:参数或返回值为其他函数的函数(闭包函数属于高阶函数)
对返回值进行操作
filter(function,iterable) --过滤,属于内置类型
function 函数,或者None(必需参数)
iterable 可迭代对象
--将iterable 中的每个元素依次作为实参传递给 所指定函数去调用
--返回值进行bool判定,为True的留下,为False的去掉,最后映射到元数据(function传None时,是对可迭代对象中的每个元素直接进行bool判定)
--返回数据为迭代器,可以用list转列表
map(function,*iterable)
func:必需,必须为可接受n个可迭代对象的函数
*iterable:(n)多个可迭代对象(不定长参数)
--拉链操作 将可迭代1..可迭代2..参数相邻进行函数调用(以最短的可迭代对象为准)
--返回值为 迭代器,用list转列表
reduce(func,iterable,[initial])
--需要先导入包 from functools import reduce
--返回值 非迭代器
--func 必须为可接受两个实参的函数 initial:初始值,从初始值开始,再拿一个元素进行func调用
-(无初始值)先拿两个参数进行func调用,用结果和后面一位进行func调用...循环
-初始值+元素数量等于1时,返回该元素,当均无元素时 会报错
-
递归函数(了解)
定义: 程序调用自身的编程技巧成为递归
递归函数要满足2个条件:
递归边界条件(一般到递归边界则终止当前递归)
递归推理(一般是提取重复的子问题,不断向递归边界靠拢或者不断
缩小问题规模)
递归默认的最大深度限制是 1000
先import sys
sys.setrecursionlimit(1001) # 放宽递归最大深度
sys.getrecursionlimit() # 查找递归最大深度限制
-
面向过程编程
更加注重算法,注重任务完成的过程,符合人的思维逻辑
特点: 可读性比较好、易于阅读、思维比较简单
缺点: 结构不够明显、不宜于修改
比较符合任务量较小 代表语言:C语言
-
面向对象编程
重数据轻逻辑,实现程序解耦
特点: 高内聚 低耦合
类是抽象的
程序 = 算法 + 数据结构
类
类, 类对象(大驼峰命名)
实例化: 类对象()
输出实例化后的对象会输出__main__
__main__ 指的是当前这个模块
间接执行py02(其他文件引入py02 ) 输出类对象时,会输出模块名.student
方法: 类里面的函数称之为方法
魔术方法: (特殊方法) 官方定义好的以两个_开头和结尾命名的方法
特点:一般不需要主动调用,在特定情况下会自动调用
__new__(cls, *args, **kwargs): 构造方法, 实例化时自动调用(先)
__init__(self): 初始化方法, 实例化自动调用(后) 无返回值
实例化过程: 每一次实例化时,会自动调用__new__方法,将实例化操作的类对象(即student) 作为实参传递给形参cls
实例化操作传入的其他实参传给形参 *args, **kwargs,然后__new__会根据cls构造出一个实力对象并返回
接着,又自动调用__init__方法,把__new__构造的实例对象(即stu1)作为实参传递给形参self, 实例化操作传入的其他实参传给形参,
然后__init__就可以对该实例对象进行属性定制操作(原地操作 inplace)
实例对象是由构造方法__new__创建并返回的,初始化方法__init__只是做属性定制,所以 __init__不能用返回值(return None)
所有类都默认继承object
实例对象属性定制的变量 叫实例属性(实例变量) 独有的
类属性(类变量): 将变量绑定给类对象 叫做类属性 共有的
属性的增删改查:
调用
实例属性
--实例对象.属性名称(只能用实例对象调用)
类属性:
--既可以类对象调用(推荐),也可以用实例对象调用
--注意:如果调用的实例属性和类对象同名,则实例对象优先调用实例属性
--实例属性不存在时,会用type调用实例对象调用类属性
修改
实例属性
--只能用实例对象修改
--stu1.name = '新名称'
类属性:
--只能用类对象修改
--注意:不能用实例对象修改类属性 会给该实例动态定义实例属性
动态定义实例属性:
用实例对象定义不存在的实例属性时, 会动态增加 实例属性
动态定义类属性:
用类对象定义不存在的类属性时, 会动态增加类属性
删除
del
属性操作相关内置函数
delattr(obj,name)
删除object的name属性, name指定为str
object可以为实例对象,也可以为类对象
getattr(obj,name,[default])
获取object的name属性
hasattr(obj,name)
判断obj里的name是否存在,存在返回True,不存在返回False
setattr(obj,name,value)
将obj里的name属性设置为value 原地操作无返回值
存在就修改,不存在就动态增加
功能
对象方法
第一个参数位隐式接收了实例对象。第一个参数是self
既可以用实例对象调用(推荐),也可以用类对象调用
注意:如果用类对象调用,self不会自动实例化类对象,需要主动传递实参
类方法
与对象方法不同,方法前面加装饰器 @classmethod # 内置的类方法装饰器
调用类方法,类方法默认第一个参数为cls
既可以用类对象调用(推荐),也可以用实例对象调用
注意:如果用实例对象调用类方法,本质上是在用实例对象的type(即Student)在调用 类方法
静态方法
@staticmethod 内置的静态方法装饰器
既可以用类对象调用(推荐),也可以用实例对象调用
选择方法:
不同的self不同的效果 使用对象方法 独特性
共性的可以使用类方法或者静态方法
面向对象的三大特性
封装
将属性前面添加 '__',将属性封装为 私有属性(只能在类内访问)
在方法面前添加'__',将方法封装为 私有方法
可以简介访问: 通过非私有化方法简介访问 私有方法或私有属性
python运行时,将__school 改为_Student__school,在类外调用不到
就算是继承关系,子类也无法直接访问父类的私有属性和私有方法(可间接访问)
继承
所有类默认继承object父类, 一般不写出来
继承分为 单继承(A->B->C A->C A->B) A(基类、父类、超类)
多继承(A、B -> C) 多继承从左往右找
继承顺序 先找自己->找父类(多继承从左往右 找到底object)
对象的继承查找顺序: 类对象.__mro__
优点及意义:对于子类而言,继承可以简化代码,对于父类而言,子类是父类功能的扩充
子类重写父类的方法后,需要再次调用父类的方法可以用super表示父类超类(前提 存在继承关系)
super(要调用哪个类的父类, 用哪个对象调用).method()
super(要调用哪个类的父类, 用哪个对象调用).属性attr
类内的方法进行调用父类方法时,可以用super().方法() (不推荐)
继承相关的内置函数
isinstance(obj,classinfo)
判断obj是否是classinfo 的实例对象或者子类的实例对象(考虑继承) 相当于type(obj) == A 但type不会考虑继承关系
classinfo 可以为元组,一个满足就满足
返回bool值
issubclass(class,classinfo)
判断class是否是classinfo的子类
classinfo可以为元组,满足一个就成立
类是自身的子类,
多态
具有不同内容的方法可以使用相同的方法名,则可以用一个方法名调用不同内容的方法
type(obj) 返回obj
type(name,bases,dict) 创建一个新类型
python里一切皆对象
所有类都默认继承object
object是所有类的父类,type、object 也是是object的子类
所有的类都是type类的实例对象,所以type、object也是type的实例对象