黑马python入门(3):python基础(变量 字符串 if 循环 函数)
教程地址: https://www.bilibili.com/video/BV1ex411x7Em
注意 这教程是专门给零基础的观看 里面很多东西都很初级 有基础的可以考虑选择2倍速或者1.5倍速观看即可
有基础的可以直接廖雪峰 https://www.liaoxuefeng.com/wiki/1016959663602400
和教程的顺序不一样 是按照自己的习惯整理出来的 有些特别初级的东西压根就没写上
pycharm的版本选择
免费: pycharm个人版 pycharm社区版 推荐社区版 社区版和专业版的差别是 没有框架支持 无远程开发支持 无数据库支持
收费: pycharm专业版 自然是推荐这个的 但是收费 网上有神秘的破解版
pycharm的运行代码
和其他ide差不多 需要设置一个入口文件 或者主文件(main) 然后才能继续执行
要执行的文件->>右键->>run XXX.py 只需要这里运行一次 就设置该文件为main文件了 下次就从右上执行该文件了
pycharm的调试代码
要调试
1.设置断点
3.到达断点停下来 点击f7或者f8来一步一步执行 f7可以精确到函数 模块 包内单步执行 f8只是专注于当前文件的代码单步执行
4 左下还会出现bug窗口 显示单步执行过程中的各种变量的情况 包含函数 模块 包里面的 都可以选择
pycharm判断处于哪个代码块
光标处于哪个代码块 下面出现提示 或者是上面
------------------------------------------------------------
注释
1.# 单行注释内容 注意看#后面还有个空格 符合pep8规范
2.
“””
多行注释内容
“””
3.a = 11 # 这里本行末尾的注释 #前后都要有空格 前面2个空格 后面1个空格符合规范
4,# TODO 展示TODO注释的用法
TODO注释是一种特殊的注释 本质上还是注释 但是这个注释 可以在左下的TODO栏里面能找到
能够点击这TODO注释快速在TODO注释之前切换 很方便
总结下注释的常见用法
前三种注释随便用 能简单表达清晰就可以了 而第四种 我们常常用来实现项目的结构布局
随便拿个项目来进行需求分析 比如老师后面要讲到的和电脑猜拳的项目
一大眼 需求是 用户和电脑猜拳 两个名字 用户和 电脑 动词 猜拳
具体流程一开始应该是
用户出拳->>电脑出拳->>判断猜拳结果
直接根据分析在代码中写入
# TODO 用户猜拳 wait # TODO 电脑猜拳 wait # TODO 判断结果 wait
进一步分析后 继续细化 我们觉得 应该是
# TODO 初始化 wait # TODO 用户猜拳 wait # TODO 等待用户输入 wait # TODO 电脑猜拳 wait # TODO 电脑随机生成拳 wait # TODO 判断结果 wait # TODO 反馈给用户 等待用户的进一步命令 wait
这样整体细化的结构就出来了
我们可以按照这个结构依次的把各个功能模块完成 完成一个就把wait去掉 表示该模块已经写完 TODO注释可以很方便的在模块之间切换
还有个函数自动生成注释
在def xxxx(): 下面一行加3个引号回车 就可以自动创建出该函数对应的注释
PEP8 Python 编码规范整理 (用来规范我们的日常书写 养成良好习惯)
https://www.jianshu.com/p/2ae8544cda83
pep8的变量命名规范
模块 全小写可下划线
包 全小写 不要下划线
类 TestCordIsName 这样的大坨峰法 模块内部的类 使用_大坨峰法即可
类属性 全小写 可下划线
异常 大坨峰_Error 加后缀
函数 全小写 可下划线
常量 全大写可下划线
全局变量
算术运算符
+-*/ 加减乘除
// 求商
%求余
**求幂
变量
1.常见数据类型
数字型
(1)int 整数型 10
(2)float 浮点型 123.4
(3)bool 布尔型 True False
(4)complex 复数型
非数字型
(1)str “123ssf”
(2)tuple 元组 就是无法修改的数字索引数组(1, 2, 3,4)
(3)list 列表 就是常见的数字索引数组 [1, 2, 3, 4, 5]
(4)dict 字典 就是lua的table{“name”:”123”,”age”:18} 注意不能{1,2,3} 字典就是纯粹的非数字索引数组 {1,2,3} 不是字典而是集合set
(5)set 集合 不重复的序列 {17, 18}
2.对常见类型的理解
int str float等等 这些其实都是类 每个类型数值都是对应类的实例
print(int)->>结果为<class 'int'>
下面是int类的类属性和类方法
而我们创建一个数值变量 该变量也附带了这些属性方法
3.数据类型判断
isinstance(变量名, 类名)
注意:常见的type()无法实现直接判断类型 因为返回值是一个对象类型 就算是用str()转换为字符串 得到的也是类似 “<class 'int'>”
使用isinstance函数来实现输出变量类型的函数
def get_type(var): """ :param var: 要检测类型的变量 :return: 返回类型字符串 :function:用来实现别的语言的type的功能 返回参数对应的变量类型字符串 """ if isinstance(var, int): # 第一个参数是变量名 第二个是类型常量 temp1 = "int" elif isinstance(var, float): temp1 = "float" elif isinstance(var, bool): temp1 = "bool" elif isinstance(var, complex): temp1 = "int" elif isinstance(var, str): temp1 = "str" elif isinstance(var, tuple): temp1 = "tuple" elif isinstance(var, list): temp1 = "list" elif isinstance(var, dict): temp1 = "dict" elif isinstance(var, set): temp1 = "set" else: temp1 = str(type(var)) print(temp1) return temp1
4.容器和序列的理解(不一定对)
序列就是 str tuple list
也叫序列 序列还有一些公共的方法和属性如切片 相加 相乘 in判断某个元素是否在序列里 len() list() str() sorted() sum() max() min(
容器就是 序列+ dict+set
5.不同类型变量的转换和运算
运算
数字型之间可以相互运算 当作正常四则运算都可以 True就是1 False就是0
常见的类型转换
int->str 基本什么转化str都能转换
int->float 自动在末位加.0
float->int 会抹去小数点
floar->str 基本什么转化str都能转换
bool->int-> 0 1
bool->float –>0.0 1.0
bool->str –>”True” “False”
str->int 如果 print(int("11.0")) 一样会报错 因为字符串格式不符合整数标准 它不会自动识别浮点数格式并转化为整数 切记
str->float 如果 print(float("11")) 一样会报错 因为字符串格式不符合标准 无法转化
str->bool 除了“” 其他都是True
str->tuple 有两种形式 tuple(“2345”)->(2,3,4,5) tuple(eval(“(23,45)”))->(23,45)
str->list 有两种形式 list(“2345”)->[2,3,4,5] list(eval(“(23,45)”))->[23,45]
str->dict dict(eval("{'name':'ljq', 'age':24}"))->{'name': 'ljq', 'age': 24}
tuple->str str((2,3,4,5))->”(2,3,4,5)”
tuple->list list((1,2,3,4))->[1,2,3,4]
tuple->dict XXXX很明显字典是非数字索引数组 元组无法转化成这个形式
tuple->set set((1,2,3,4))->{1,2,3,4}
list->str str([2,3,4,5])->”[2,3,4,5]”
list->tuple tuple([1,2,3,4])->(1,2,3,4)
list->dict XXXX很明显字典是非数字索引数组 无法转化
list->set set([1,2,3,4])->{1,2,3,4}
dict->str str({"name": "zjl","age": 18,"test":(1,2,3,4)}) -> “{'name': 'zjl', 'age': 18, 'test': (1, 2, 3, 4)}” 留心 双引号变单引号了
dict->tuple tuple({"name": "zjl","age": 18,"test":(1,2,3,4)})->('name', 'age', 'test') 只是把key转换了 基本没意义
dict->list list({"name": "zjl","age": 18,"test":(1,2,3,4)})->['name', 'age', 'test'] 只是把key转换了 基本没意义
dict->set set({"name": "zjl","age": 18,"test":(1,2,3,4)})->{'name', 'age', 'test'} 只是把key转换了 基本没意义
Python类型隐式转换不存在
print(1+ "12")->>
Traceback (most recent call last):
File "E:/python/test1.py", line 19, in <module>
print(1+ "12")
TypeError: unsupported operand type(s) for +: 'int' and 'str'
6.Python的所有的False
print(False) #False print(bool(0)) #False print(bool("")) #False print(bool(())) #False print(bool([])) #False print(bool({})) #False print(bool(None)) #False
7.None的理解
None是一个常量 类型是<class 'NoneType'>
NoneTyoe类的唯一值就是None 其他语言里面相当于null
很多函数没有返回值 其实返回的是None
8 关键字和变量命名
变量命名没什么可说的 按照pep8的标准即可 数字字母下划线构成
关键字(主要是命名的时候不要和系统已经存在的关键字冲突 这个才是关键字的问题)如下
import keyword print(keyword.kwlist) # ['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
9 变量格式化输出print()
格式化字符
(1)%d 整数
(2)%f 浮点数
(3)%s 字符串
(4)%% 代表% 只是在pirnt第一个参数里面 才不能直接输出% 需要用%%形式来代表
常见的几种用法
aaa = 11 bbb = "bbbbb" ccc = 1231.23 # 只输出一个的写法 print("aaa:%d" % aaa) # 输出多个变量 并且变量还在输出过程中运算过 print("aaa:%d,bbb:%s,ccc:%f" % (aaa+1, bbb+"ccc", ccc)) # %06d表示这整数要求6位 不足的补零 %.03f表示这个浮点数小数点3位 不足的补零 print("aaa:%06d,bbb:%s,ccc:%.03f" % (aaa, bbb+"ccc", ccc))
结果
aaa:11
aaa:12,bbb:bbbbbccc,ccc:1231.230000
aaa:000011,bbb:bbbbbccc,ccc:1231.230
小知识:
print(“123”,end=”-”)
print(“456”
结果 123-456 正常而言 print函数输出了指定内容后会加一个回车换行 但是后面加的这个东西可以调整 print(“123”,end=”-”)来调整最后接的东西
小知识:
print(“%d:%s” % (a,b)) 这里的(a,b)其实是一个元组 % 后面接一个参数 可以是单个变量也可以是元组 这个要理解下
python3的print总结 https://www.runoob.com/w3cnote/python3-print-func-b.html
10 变量可变类型和不可变类型
常见的结构 变量名 = 值
实际上 变量名只是一个类似指针的东西 他只是指向赋值的值的存储地址而已 值本身的类型不同 它存储的机制就会不同
存储地址固定不变的类型
1、int 2 str 3 tuple
不可变的类型重新赋值原理 实际上是另外开辟了一个内存地址来存放新值 并且变量名改变了自己的旧指向 指向了这个新开辟的内存地址 不是在原来值得地址上修改下存储内容的理解
i = 0 j = 0 k = 0 # 虽然是3个不同变量名 但是他们的值0 都指向同一个地址 print(id(i)) # 0这个值对应的内存地址为:140723744577152 print(id(j)) # 0这个值对应的内存地址为:140723744577152 print(id(k)) # 0这个值对应的内存地址为:140723744577152 i = 1 print(id(i)) # 0这个值对应的内存地址为:140723744577184 print(id(j)) # 0这个值对应的内存地址为:140723744577152 print(id(k)) # 0这个值对应的内存地址为:140723744577152
存储地址可变的类型
1.list 2.dict
aaaa = [1, 2, "sdf23", (1, 2, 3)] print(id(aaaa)) # 2363575725632 print(id(aaaa[2])) # 2363574904368 aaaa[2] = "234234" # 改变了其中一个元素的值后 元素对应的内存地址发生了变动 但是变量本身没变化 print(id(aaaa)) # 2363575725632 print(id(aaaa[2])) # 2363574904432
这玩意实际上意义不大 只有在函数参数是传址 还是传参上有用 可以简单记忆
不可变类型就是传参 可变类型就是传址 在函数内部对可变类型操作 会直接影响到外界
11 变量作用域
全局变量 :不在类 函数 模块内声明的都是全局变量
局部变量:在类 函数 模块内声明的都是局部变量
闭包作用域 在闭包里面 或者说 在一个函数内部里面嵌套了另外1个函数 这种形式叫闭包 闭包这种形式下 嵌套的函数可以调用外部函数的局部变量
内置变量 内置函数 或者第三方库里面的 变量 方法 类都属于
def test(): aaaaa = 1 print("test函数的局部变量aaaaa的值:[%d]" % aaaaa) def test_1(): # 这个函数在另外函数内部 这个函数内部可以自由的调用外部函数的局部变量 print("test_1函数的局部变量aaaaa的值:[%d]" % aaaaa) #内部嵌套函数并没有aaaaa这个变量 所以他按照顺序查找 找到外层函数有个同名局部变量 test_1() test() # 调用函数 print("全局变量aaaaa的值:[%d]" % aaaaa)
结果:
test函数的局部变量aaaaa的值:[1]
test_1函数的局部变量aaaaa的值:[1]
全局变量aaaaa的值:[11111]
变量范围查找顺序:
如果在变量自己的范围内找不到对应名字的变量 可以按照一定顺序查找
局部作用域>闭包作用域>全局作用域>内置作用域
比如上面的test_1函数内的aaaaa变量 先找test_1函数本身范围 没有这个名字的局部变量 然后又向外找 找闭包范围的变量 test()函数里面有一个同名变量 找到了自然就用了 找不到则下一步就是找全局变量是否有aaaaa的变量 还找不到就找内置函数 第三方库的同名变量
小知识:局部范围想使用全局变量 或者闭包变量
def test(): aaaaa = 1 print("test函数的局部变量aaaaa的值:[%d]" % aaaaa) def test_1(): # 这个函数在另外函数内部 这个函数内部可以自由的调用外部函数的局部变量 global aaaaa # 这代码一写就表示这里的aaaaa是强制使用全局变量的aaaaa print("test_1函数的局部变量aaaaa的值:[%d]" % aaaaa) #内部嵌套函数并没有aaaaa这个变量 所以他按照顺序查找 找到外层函数有个同名局部变量 aaaaa = 100 test_1()
结果:
test函数的局部变量aaaaa的值:[1]
test_1函数的局部变量aaaaa的值:[11111]
全局变量aaaaa的值:[100]
nonlocal 和 gloabal差不多 后者是强制使用全局变量 前者是强制使用闭包变量
小知识:globals()函数的用法
作用:返回当前的所有全局变量的一个字典
注意 globals()的返回值字典无法用for in直接遍历 提示是字典处于变动中无法实时显示内容 只能把返回值字典复制给一个普通字典变量 一个快照 然后对这个普通字典变量进行遍历输出才可以
字符串
1.常用字符串函数
(1)字符串的拼接
“123123”+”34234234” ->> “12312334234234” # 但是 这种方式效率低下 如果是连续的拼接不要使用这个方式 用join()
aa = "hello " bb = "world" cc = "." print("".join((aa, bb, cc))) # 注意参数是元组 开头的"" 是表示用什么连接这些字符串 # 结果 hello world.
join的用法和常见的不一样
连接符.join((字符串1, 字符串2, 字符串3, 字符串4))
--1.开头是连接符 如果不用连接符就“”空字符串即可
--2 join的参数是一个元 组 元组的元素才是要拼接的各个字符串
(2)字符串的重复
“abc” * 3 –>> “abcabcabc”
(3)字符串截取(切片 属于容器的公共方法 用于字符串 列表 元组 )
注意:切片是左闭右开 小心
常见用法 str[起点下标:终点下标:步长] 步长不写默认为1
aa = "abcdefghijklmn" print(aa[2:5]) # cde 截取从第2位到第五位的str 但是不包含第五位 print(aa[2:]) # cdefghijklmn 截取从第2位到末尾的str print(aa[0:5]) # abcde 截取从开始到第五位的str 但是不包含第五位 print(aa[:5]) # abcde 截取从开始到第五位的str 但是不包含第五位 print(aa[0:]) # abcdefghijklmn 截取整个字符串 print(aa[:]) # abcdefghijklmn 截取整个字符串 print(aa[0::2]) # acegikm 截取从第2位到末位 步长为2 间隔2个截取一个 print(aa[-2:-5:-1]) # mlk 反向截取 注意反向截取步长为负数
(4)字符串切割split()
被切割的字符串.split(分隔符,切割次数) ->返回值是列表
aa = "abc-defg-hi-jk-lmn" bb = aa.split("-") # 单纯切割 print(bb) # ['abc', 'defg', 'hi', 'jk', 'lmn'] bb = aa.split("-", 2) # 规定了切割次数为2 切割完第二次就不切了 print(bb) # ['abc', 'defg', 'hi-jk-lmn'] aa = "abcdefghijkmn" bb = aa.split("-", 2) # 如果被切割字符串内没有分隔符会如何 print(bb) # ['abcdefghijkmn']
(5)空白字符的清理
strip()====trim()
或者直接正则替换掉就好
(6)字符串的遍历 单个元素的使用
其实非数字类型都可以遍历的 属于非数字类型的公共方法
aa = "abcdefghijkmn" for v in aa: print(v, end="--") # a--b--c--d--e--f--g--h--i--j--k--m--n-- print("===============") print(aa[0]) # a print(aa[1]) # b
(7)字符串的查找find()
拒绝index() 函数竟然找不到会报错 真是令人惊讶
连我自己写的 index_tuple_list_set都不如
被查找的字符串.find(查找的字符串,起点下标,终点下标) 起点下标默认为0 终点下标默认自然是末位了
aa = "abcdefghijkmn" print(aa.find("e")) # 4 print(aa.find("e", 2, 4)) # -1 找不到 print(aa.find("e", 2, 5)) # 4 设置了起点和终点 就能找到了
(8)字符串替换 replace()
被替换的字符串.replace(被替换字符串,新字符串,替换次数) 替换次数可以省略
很简单的用法 后面学了正则 这些完全可以自己写
练手 写个批量替换
def replaceX(r_list, n_list, s_str): """ :param r_list:strlist 要被替换的字符串构成的list :param n_list:strlist 和r_list一一对应的新字符串列表 :param s_str:str 被替换的原始字符串 :return: str 返回批量替换后的字符串s_str funtion: 批量替换 """ i = 0 while i < len(r_list): s_str = s_str.replace(r_list[i], n_list[i]) i += 1 return s_str aa = "abc{title}de{span}xy{b}zfghi{b}xyzj{span}kxyz{title}mn" print(aa) # abc{title}de{span}xy{b}zfghi{b}xyzj{span}kxyz{title}mn r_list = ["{title}", "{span}", "{b}"] n_list = [" <title> ", " <span> ", " <b> "] print(replaceX(r_list, n_list, aa)) # abc <title> de <span> xy <b> zfghi <b> xyzj <span> kxyz <title> mn
(9)转大小写
upper() lower() 没什么可说的
(10)判断是否 系列
isnumeric 字符串是否是纯数字组成 里面每一个字符都必须是数字 和常见的验证数值不太一样 不太合要求
isalnum 判断字符串是不是阿拉伯字符或数字 [a-zA-Z0-9]+ 意义不大print("111".isnumeric()) # True print("111.1".isnumeric()) # False 里面多个字符.不是纯数字 print("11e3".isnumeric()) # False 里面多个字符e不是纯数字 print("0.111".isnumeric()) # False 里面多个字符.不是纯数字
isalpha 判断字符串是不是纯英文字符[a-zA-Z] 意义不大
isdecimal 判断字符串是不是十进制的数
isdigit 判断字符串是不是一个正整数
isidentifier 判断字符串是不是一个合法的标识符,也就是 是不是一个合法的变量名
isspace
本质上都可以用正则来实现
判断是不是纯数字(数字包含 正负整数 正负浮点数 正负科学记数法)
def isnumeric_plus(isnum_str, num_mode = 1): """ :param isnum_str: str验证是否是数值的字符串 数值包含 正负整数 正负浮点数 正负科学记数法 :num_mode: 是判断正负整数 还是浮点数 :return: bool True Falae function:验证是否是数值的字符串 1:数值包含 正负整数 正负浮点数 正负科学记数法 2:正负整数 3:正负浮点数 其他:都是1 base: 需要re库支持 """ if num_mode == 1: pattern = re.compile(r'^[+-]?[\d]+([.][\d]+)?([Ee][+-]?[\d]+)?$') # 匹配正负整数 正负浮点数 正负科学记数法 elif num_mode == 2: pattern = re.compile(r'^[+-]?\d+$') # 匹配正负整数 elif num_mode == 3: pattern = re.compile(r'^[+-]?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$') # 正负浮点数 else: pattern = re.compile(r'^[+-]?[\d]+([.][\d]+)?([Ee][+-]?[\d]+)?$') # 匹配正负整数 正负浮点数 正负科学记数法 # print(pattern.search(str)) if pattern.search(isnum_str): temp1 = True else: temp1 = False return temp1
(11)format
常用的没多复杂
print("这是我的{0},年龄{1},地址是{2}".format("zjl", 16, "shandong")) # 这是我的zjl,年龄16,地址是shandong print("这是我的{name},年龄{age},地址是{address}".format(name="zjl", age=16, address="shandong")) # 这是我的zjl,年龄16,地址是shandong print("这是我的{name},年龄{age},地址是{address}".format(**{"name": "zjl", "age": "16", "address": "shandong"})) # 配合dict使用 加** # 这是我的zjl,年龄16,地址是shandong print("这是我的{0[0]},年龄{0[1]},地址是{0[2]}".format(["zjl", 18, "shandong"])) # 配合list 调用的方式特别 {0[0]} {0[1]} # 这是我的zjl,年龄16,地址是shandong
2.转义字符和回车换行问题
回车换行问题
在linux下 回车换行 其实是\n 但是window下 回车换行是\r\n 这会导致 我们linux 或者安卓下的文件 比如文本文件 拿到window下 发现 都是写在第一行的 没有分行
常见的转义字符
\”
\’
\\
\r
\n
\t
\b
\u编码 比如\u4e2d\u56fd = 中国 二个汉字
3.保持原始格式的字符串
字符串用“”“ ”“”包裹起来 是维持原来的结构
bb = """ <html> <title>测试标题</title> <body> <span>hello world</span> </body> </html>" """ print(bb)
但是注意 如果里面 存在转义字符 依然起效 比如里面有\r\n 依然在显示的时候还是呈现回车换行的效果
3.正则(这里用来判断)
正则基础 https://www.runoob.com/regexp/regexp-tutorial.html
正则函数 https://www.runoob.com/python3/python3-reg-expressions.html
正则在线测试和常见正则表达式 http://c.runoob.com/front-end/854
正则的作用
1.判断字符串是否匹配
2.替换字符串
3.提取符合要求的字符串
if语句
1.比较运算符
== !=(2.7下是<>) <= < > >= 没什么值得说的
2.逻辑运算符
and or not
3 赋值运算符
= += -= *= /=
4 完整的if语句结构
math_score = 87 chinese_score = 64 # 注意缩进 python很多代码块没有诸如 }, end if等等结束标识符 用严格的缩进来代替结束标识符来限制代码块的范围 if (math_score >= 60) and (chinese_score >= 60): # 后面别忘记加: pass elif (math_score >= 60) and (chinese_score < 60): # 是elif 不是elseif 并且后面别忘记加: pass elif (math_score < 60) and (chinese_score >= 60): pass else: # 后面别忘记加: pass
如果条件过于复杂 一行写不下 可以用这种格式来分行写条件 更加的优雅美观
if (math_score >= 60) and (chinese_score >= 60) and (english_score >= 60):
↓↓↓↓↓↓↓↓↓↓↓↓↓↓先在所有条件上加括号 然后分行即可↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
if ((math_score >= 60)
and (chinese_score >= 60)
and (english_score >= 60)):
注意:python里面没有诸如 }, end if end 之类的结束符来标识代码块的范围 用了严格的缩进来代替这些结束符 所以python的缩进至关重要 不能搓和其他语言不一样
5 python中不存在switch语句 只能用if…elif…结构来实现
循环
1.完整的while循环
count = 0 ceiling = 35 while count < ceiling: count = count + 1 if count > 40: print("[%d] < %d 循环break代码" % (count, ceiling)) break elif count == 30: """ # 注意 循环里面存在continue 千万注意他的位置和计数代码的位置关系 如果count += 1写在末尾 那么一旦 # 执行到 continue 后 会自动跳转到下个循环 但是本次循环没有执行count += 1 i的值没有变化 下一次循环 i的值依然是30 就会陷入一种死循环中无法解脱 """ print("[%d] < %d 循环continue代码" % (count, ceiling)) continue else: print("[%d] < %d" % (count, ceiling)) else: # 这里是循环没有执行break 则循环结束肯定会到这里执行下 print("[%d] >= %d 循环结束 循环的else代码" % (count, ceiling))
留心while循环中存在continue的时候的位置
无限循环:while True:就可以 但是不大推荐 使用无限循环要小心
2.for循环
(1)结构:
for iterating_var in 序列: statements(s)
序列包含 字符串 元组 列表 字典
(2)完整的for循环
aa_test_list = (1, 2, 3, 4, "5", 6, ["a", "b"], 8, 9) aa_test_list = (1, 2, 3, 4, "5", 6, 7, 8, 9) for v in aa_test_list: if isinstance(v,int): print(v) elif isinstance(v,str): print("是字符串 跳过") continue else: print("不是字符串和数字 停止循环") break else: print("for循环正常的循环完毕")
(3)常见用法
aa_str = "123456789" aa_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9) aa_list = [1, 2, 3, 4, 5, 6, 7, 8, 9] aa_dict = {"name": "zjl", "age": 16, "address": "shandong"} print("===========重复10次===========") for i in range(10): # 重复10次循环 是0-9 print("%d" % (i)) print("==========for(i=0;i<10;i++)步长为2============") for i in range(0, 10, 2): # 其他语言常见的for(i=0;i<10;i++)结构的实现 print("%d" % (i)) print("=========for(i=0;i<10;i++)形式遍历元组列表=============") for i in range(0, len(aa_tuple)): # for(i=0;i<10;i++)形式遍历元组列表 print("%d :%s" % (i, aa_tuple[i])) print("=========遍历字符串=============") for v in aa_str: # 遍历字符串 print("%s" % (v)) print("=========# 遍历元组=============") for v in aa_tuple: # 遍历元组 print("%s" % (v)) print("========遍历列表==============") for v in aa_list: # 遍历列表 print("%s" % (v)) print("=========遍历字典=============") for k, v in aa_dict.items(): # 遍历字典 print("%s : %s" % (k, v))
小知识:range()返回一个左闭右开的数字列表
for i in range(10)
print(i)
结果输出的是0-9
小知识:字典方法items()的理解
返回的是键值元组为元素的列表
aa_dict = {"name": "zjl", "age": 16, "address": "shandong"} print(aa_dict.items())
结果
dict_items([('name', 'zjl'), ('age', 16), ('address', 'shandong')]) # 本质上是个列表 但是列表的每个元素都是元组 元组的元素是键值 这样在用字典的items方法遍历字典就很好理解了
函数
1.传址还是传参
没什么说的 序列参数就是传址 数值 字符串 元组就是传值 就是之前说的可变类型和不可变类型
简单说 传址进函数 在函数内对参数的操作都会作用到外面的变量 传值则不会 在函数内部对参数的任何操作都不会影响到外部变量
2.参数 可变参数 默认值参数
默认值参数是在下面
test_config=1, ip="", test_mode="w"
这样就是设置参数默认值 注意 默认值靠后写 不能再固定参数前面
def test(test_a, test_b, test_config=1, ip="", test_mode="w"): # 可变参数都靠后放 固定参数靠前放 print( "test_a:{0},test_b:{1},test_config:{2},ip:{3},test_mode:{4}".format(test_a, test_b, test_config, ip, test_mode)) test(1, 2) # 只传递了2个必备的参数 test(1, 2, ip="192.168.1.100") # 指定传递了其中一个可选参数 其他可选参数就是用默认值 test(1, 2, ip="192.168.1.255", test_config=2) # 指定传递了其中一个可选参数 其他可选参数就是用默认值
给这些可变参数传值 可以直接可变参数名=XX即可
test(1, 2, ip="192.168.1.100")
ip就是其中一个可变参数
特殊的函数参数的传递和使用
test(test_a, test_b, *args, **kwargs)
def test(test_a, test_b, *args, **kwargs): # 可变参数都靠后放 固定参数靠前放 print( "test_a:{0},test_b:{1},args:{2},ip:{3}".format(test_a, test_b, args, kwargs)) test(1, 2, *(1, 2, 3, 4, 5), **{"name": "zjl", "age": 18})
结果
test_a:1,test_b:2,args:(1, 2, 3, 4, 5),ip:{'name': 'zjl', 'age': 18}
注意 *args对应的是一个元组 而且这个元组传值的时候也要前面加* **kwargs是对应一个字典 传递字典时候也要前面加**
也可以换另外的形式来传参
test(1, 2, 1, 2, 3, 4, 5, name="zjl", age=18) 效果和上面一样
3.函数返回值
return后面什么不加表示返回None 如果函数连return都没 也返回None
return (10, 20) –>如何接收 –> a, b=test() ->这样a=10 b=20 接收完毕 也可以去掉括号 return 10, 20 效果一样
4.递归
没什么说的 注意python下递归是有上限的 无法无限递归 上限好像是999
石头剪刀布游戏
1.Python随机数
python提供了完善的随机方法 并不需要我们手动的一点点造轮子 random.randint 就提供了整数范围内的随机数功能
import random # 导入random库 random.seed() # 设置随机数种子 i = 0 while i < 10: print(random.randint(1, 10)) i += 1 """ 结果: 10 9 9 1 5 5 7 8 6 4 """
如果不嫌麻烦可以自己尝试从random.random()来造轮子
def get_random_int(r_min, r_max): """ :param r_min:int 随机整数最小范围 :param r_max:int 随机整数最大范围 :return:int 指定范围的随机整数 :function:返回指定范围的随机整数 :base:需要random库的支持 """ if r_max >= r_min: temp1 = int((r_max - r_min + 1) * random.random() + r_min) else: temp1 = int((r_min - r_max + 1) * random.random() + r_max) return temp1
2.需求分析
用户和电脑猜拳 二名词 一个动词 主体是用户 和电脑 操作的猜拳
0.初始化
1.用户出拳
(1)接收用户输入验证合法性
(2)存储用户数据
2.电脑出拳
(1)随机生成电脑出拳
3.判断反馈结果
(1)根据用户和电脑出拳情况判断出结果并反馈
(2)继续等待下一局或者用户退出命令
和老师不太一样 按照自己思路写的
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # author:zjl albert time:2020/8/31 # 一.初始化 # (1) init import random import datetime random.seed() finger_guess_list = ["s", "j", "b"] # 存储石头剪刀布标识的列表 finger_guess_chinese_list = ["石头", "剪刀", "布"] # 存储石头剪刀布汉字的列表 # (2) 猜拳规则信息发布 i = 0 temp1_str = "[游戏规则]:\r\n" while i < len(finger_guess_list): temp1_str = "".join([temp1_str, "按[", str(finger_guess_list[i]), "]:", str(finger_guess_chinese_list[i]), "\r\n"]) i += 1 temp1_str = "".join([temp1_str, "按[q]:退出"]) print(temp1_str) while True: # 二.用户出拳 # (1) 接收用户输出并验证合法性 user_content = input("请出拳:") user_content = user_content.strip() # 清首尾空 user_content = user_content.lower() # 全转小写 if user_content in finger_guess_list: # 验证合法 自然继续执行 temp2_user_pos = -1 i = 0 while i < len(finger_guess_list): # 因为列表是程序员自己写的 不可能存在其他类型 都是str 所以不用检测了list了 if user_content == finger_guess_list[i]: temp2_user_pos = i break i += 1 # 三.电脑出拳 temp3_computer_pos = random.randint(0, len(finger_guess_list) - 1) computer_content = finger_guess_list[temp3_computer_pos] # 四.判断反馈结果 if ((user_content == "s" and computer_content == "s") # 打平 or (user_content == "j" and computer_content == "j") or (user_content == "b" and computer_content == "b")): print("=平=,用户出[%s:%s],电脑出[%s:%s] --%s" % (finger_guess_list[temp2_user_pos], # 本行太长不符合pep8标准 分成多行 finger_guess_chinese_list[temp2_user_pos], finger_guess_list[temp3_computer_pos], finger_guess_chinese_list[temp3_computer_pos], datetime.datetime.now().strftime("%H:%M:%S")) ) elif ((user_content == "s" and computer_content == "j") # 用户赢 or (user_content == "j" and computer_content == "b") or (user_content == "b" and computer_content == "s")): print("[赢],用户出[%s:%s],电脑出[%s:%s] --%s" % ((finger_guess_list[temp2_user_pos], finger_guess_chinese_list[temp2_user_pos], finger_guess_list[temp3_computer_pos], finger_guess_chinese_list[temp3_computer_pos], datetime.datetime.now().strftime("%H:%M:%S"))) ) else: print("<输>,用户出[%s:%s],电脑出[%s:%s] --%s" % ((finger_guess_list[temp2_user_pos], finger_guess_chinese_list[temp2_user_pos], finger_guess_list[temp3_computer_pos], finger_guess_chinese_list[temp3_computer_pos], datetime.datetime.now().strftime("%H:%M:%S"))) ) elif user_content == "q": print("====欢迎再来====") break else: # 用户输入非法 提示 并不向下执行了 print("您输入的是:[%s] 不合要求 请重新输入 --%s" % (user_content, datetime.datetime.now().strftime("%H:%M:%S")))
结果
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现