python 基础230310
-
变量的命名规则:字母数字下划线/不能以数字开头/不能使用关键字/不能使用中文,要具有描述性,不能过长
python关键字:import keyword ,显示所有关键字:keyword.kwlist -
驼峰体: AgeOfOld 下划线: age_of_old_boy is_person has_error
注意事项:
1.在接受范围内,变量名所描述的内容越精准越好。
2.一个好的变量名,长度应该控制在两到三个单词左右。
3.同一个变量名指代的变量类型,也需要保持一致性。(在一个函数中,一个变量名叫做 photo, 那么在其他地方就不要改成image。)
4.让变量定义尽量靠近使用。
5.某一函数过长时,或者包含太多变量时,请及时把它拆分成多个小函数。
6.在一个函数中,如果某一个定义的变量没有被用到,请及时删除它。 -
变量指向: 变量在内存中是唯一的, 指向一个数据,不是其他变量
例1: v1 = '好嗨哟' v2 = [1, 2, 3, 4, v1] # 列表中的指向的是一个具体的值. v1 = "人生已经到达了巅峰" print(v2) # [1, 2, 3, 4, '好嗨哟'] 例2: age1 = 12 age2 = age1 age3 = age2 age2 = 18 print(age3) # 12 例3: info = [1,] userinfo = {'account': info, 'num': info, 'money': info} info.append(9) print(userinfo) # {'account': [1, 9], 'num': [1, 9], 'money': [1, 9]} info = "题怎么这么多" print(userinfo) # {'account': [1, 9], 'num': [1, 9], 'money': [1, 9]} info = [1, 2, 3] userinfo = [info, info,] info[0] = '嗨' print(info, userinfo) # ['嗨', 2, 3] [['嗨', 2, 3], ['嗨', 2, 3]] ------------------------- 因为Python中对于可变对象和不可变对象的赋值方式不同。 可变数据发生变化时, 引用发生变化 / 不可变变量发生变化时, 引用不发生变化 可变转为不可变, 或者不可变转为可变, 原引用值的指向不会发生变化 .
-
常量:python没有规定的常量CONSTANT, 把变量全部大写,就是约定俗成的常量
派/ 身份证号码 / 历史日期 BIRTH_OF_CHINA
变量是唯一的,但数据不是唯一的: age1 = 33, age2 = 33 -
注释:单行注释 Alt + / # 多行块注释'''''' 注释会读,但不会执行. 难于理解的函数/类要加注释,增加可读性.
-
基础数据类型:int str float bool(True False) 机器是很傻的
int: 1, 3, 5, 11 # 整数
float: 1.1, 3.14, 5.678 # 小数
str: 'name','cock' "中国" # 用引号引起来的描述性的文字或者数据 单引号或者双引号 三引号
bool: True, False # 真 假 -
字符串可以拼接 相加 可以计算, 可以是一大块文字/换行的诗
msg = '''
床前明月光
疑似地上霜'''
print(msg)
msg1 = 'abc'
msg2 = 'def'
msg3 = msg1 + msg2 字符串可以相加
msg4 = msg1 * 8 -
bool 只有2个值 True False # bool值不带引号 # print(2>1) True
True是布尔值 "True"是字符串 -
格式化输出: print(f"我叫{name}, 今年{age}岁, 性别:{gender}")
msg = '我叫' + name + ', 今年' + age + '岁, 性别:' + gender
print(msg) -
用户交互: name = input("请输入用户名:) # 让用户输入内容, 进行下一步操作.比如输入 用户名密码.
-
流程控制:
if / # 只有一个条件
if else # 如果这样, 否则那样
if elif elif else # 猜色子点数, 划分学生成绩等级, 根据合同金额确定审批流程, 多分支
if 嵌套if # 树形分支, 最难 -
while 循环结构: 简单记: 输入不对,重新输, 还不对,再输, 一直输入,就用while循环.
- 结构
while 条件: //while True /1/ 每次都判断这个条件,条件可以写活
循环体 # 循环体运行完后,才能再次判断条件是否再成立..重要 - 循环如何终止? : 改变条件 标志位 或break中断
flag = True while flag: # flag 或者 a<100 print('111') # 不是只打印这一行 flag = False # 写在哪个位置都行,都起一样的作用 print('114') # 打印111 114 共2行后,判断条件不符再退出.
a = b = 1 while 1: a = a + 1 b = b + a if a == 100: break # break阿里可以终止一个无限循环.... print(b)
a = 0 while a < 5: a = a + 1 if a == 3: break # break是终止,..跳出循环 print(a) # 运行结果是打印1 2 --- a = 0 # 打印 1 2 4 5 while a < 5: a = a + 1 if a == 3: continue # continue 是越过这一次循环 进入下一次循环 print(a) # 运行结果是打印1 2 4 5
- while else 组合
count = 1 while count < 5: print(count) count = count + 1 else: # 如果没有被break中断,就打印 print(666) # 执行完while循环后, 再打印666
- while循环实现账号登录3次尝试
count = 1 while count <= 3: username = input("请输入用户名:") password = input("请输入密码:") code = 'qwer' your_code = input("验证码:") if your_code == code: if username == 'abc' and password == '123': print('登录成功!!') break else: print('用户名或者密码错误!') else: print('验证码错误!') print(f'剩余尝试次数3-count}') count = count + 1
- 结构
-
格式化输出: 就是针对字符串的输出, 让某些位置可变 ,动态
print(f"hobbies : {3 - hobbies}") print(f'====== end ======') print(" end ".center(20, "="))
-
运算符
算术运算符: + - * / % ** // 比较运算符: == != > < >= <= 赋值运算符: = += -= *= /= %= **= //= 逻辑运算符: not and or # 优先级 not > and > or 成员运算符: in not in 身份运算符: is is not
-
编码初始: ASCII - GBK - unicode - utf-8
所谓编码, 就是二进制与文字的对应关系 ASCII # 共256个字符 包含了所有英文字母/数字/字符, 1个字符一个字节, A-65 a-97 GBK # 只包含ASCII 和中文, 1个字符1个字节, 一个汉字2个字节 unicode # 万国码,1个字符2个字节, 一个中文4个字节 浪费空间和资源 utf-8: 是unicode的升级, 1个字符一个字节, 欧洲文字2个字节, 中文3个字节 中国12he GBK编码是8个字节 中国12he utf-8编码是10个字节 8bit = 1byte 1024byte = 1 KB 1024KB = 1 MB 1024MB = 1 GB 1024GB = 1 TB 1024TB = 1 PB 7.6MB * 1024 * 1024 * 8 = 63753420.8 bit , 比特流
-
pycharm快捷键: ctrl + 函数名或者方法 = 进源码说明
ctrl + alt + L 快速格式化代码
ctrl + F ctrl + shift + F 查找
ctrl + R ctrl + shift + r 替换
ctrl + shift 上下 移动一行
ctrl + d 复制一行 -
基础数据类型总览: int float bool str list tuple dict set
-
二进制与十进制之间的转换
print(int(0b11010)) # 二进制转10进制 print(int(5).bit_length()) # 有效的二进制长度
-
str bool int转换
# bool 转 int print(int(True)) # 1 print(int(False)) # 0 # int 转 bool -- 非零即True print(bool(123)) # True print(bool(0)) # false # 字符串 <--> 数字 print(int('123'), type(int('123'))) # 123 <class 'int'> print(str(123), type(str(123))) # 123 <class 'str'> # 字符串 <--> 布尔值 print(bool(''), type(bool(''))) # False <class 'bool'> 空字符串, 转为空 print((str(True)), type(str(True))) # True <class 'str'> # 判断一个变量有无内容, 即字符串也可以进行判断 s = input("输入内容") if s: print("有内容") else: print("无内容")
-
str具体操作方法: 索引切片步长 常用操作方法
upper lower startswith endswith capitalize swapcase title strip rstrip lstrip split replace isalnum isalpha isnumber isdigit isdecimal islower isupper join count len() center find index
方法简介
# 索引 切片 步长 s1 = 'python全栈22期' s2 = s1[0] # p 对字符串进行的索引切片, 结果都是字符串 s3 = s1[-1] # 期 s5 = s1[0:6] # python 顾头不顾尾 s6 = s1[6:] # 全栈22期 s7 = s1[0:6:2] # pto 步长, 隔一个取一个 s8 = s1[-1:-6:-1] # 期22栈全 部分翻转取值 s9 = s1[:] # python全栈22期 s10 = s1[::-1] # 期22栈全nohtyp # 字符串的方法 对字符串的操作不会影响原字符串 s = "taibai" s1 = s.upper() # TAIBAI 大写 upper() lower()这两个方法经常用在验证码不区分大小写 print(s1.lower()) # taibai 变成小写 print(s.count('i')) # 统计字符出现个数 print(s.center(30, '=')) # ============taibai============ print(s.capitalize()) # Taibai 首字母大写 print(s.startswith('t')) # 判断开头, 是否以t开头 结果为True print(s[2::2].startswith('i')) # 判断切片后开头, 是否以i开头 结果为True print(s.startswith('i', 3, 5)) # 判断切片后开头, 是否以i开头 结果为True print(s.endswith('d')) # 判断结尾, 是否以d开头 结果为false # replace 替换 msg = 'alex 很nb, alex是老男孩创始人, alex很帅' msg1 = msg.replace('alex', '太白', 2) # 形成一个新字符串 print(msg1) # 太白 很nb, 太白是老男孩创始人, alex很帅 # strip 空白 空格 \t \n 前后两边都去除 s4 = ' \n太白\t' s11 = s4.strip() print(s11) # 太白 去除两边为空的项 s10 = 'ab李a勇efeee' print(s10.strip('abef')) # 李a勇 去除两边的ab ef 不分顺序单项去除 s12 = ' 李勇.. ' print(s12.lstrip()) # 李勇.. 去除左边的空格 s13 = 'aabbcc' print(s13.lstrip('a')) # bbcc 去除左边的aa print(s13.rstrip('c')) # aabb 去除右边的cc # split 分割 ********非常非常非常重要 s14 = '太白 女神 吴超' s15 = s14.split() # ['太白', '女神', '吴超'] 默认以空格分割, 实际是str->list s16 = '太白/女神/吴超' s17 = s16.split('/') print(s17, '111') # ['太白', '女神', '吴超'] 111 现在是以'/'分割 s18 = '/a/b/c' # 前面有个分割符 print(s18.split('/')) # ['', 'a', 'b', 'c'] 第1项为空, 这是个坑 print(s18.split('/', 2)) # ['', 'a', 'b/c'] 只分割前2项 maxsplit是分割次数参数 # join 连接 合并 非常好用经常能使用到的方法 s19 = ['太白', '女神', '吴超'] s20 = ':'.join(s19) # 只有列表的全部元素都是字符串,才能连接成功,否则报错. print(s20) # 太白:女神:吴超 join的一个参数是iterable, 只要是可迭代的,就能拼接合并 s21 = 'abcde' print(":".join(s21)) # a:b:c:d:e # count 统计某个字符出现的次数 s22 = 'asdfasdfasfdsdfsadf' print(s22.count('a')) # 4 a出现了4次 print(s22.count('a', 0, 6)) # 2 索引0-6, a出现了2次 # format 格式化输出 msg = 'abcde' name = 'ly' f = f'我叫{name}, 今天学习内容是{msg}' # is系列 name1 = 'taibai123' print(name1.isalnum()) # True 是否全部由字母数字组成 print(name1.isalpha()) # False 是否全部由字母或者数字组成 print(name1.isdecimal()) # False 是否只由十进制组成 只判断数字用decimal不要用digit print(name1.isdigit()) # False 是否全部由数字组成 还包含罗马数字 大写数字
-
for 循环
# 逐个打印一个字符串 # 用while循环实现 s1 = '老男孩最好的讲师:太白' i = 0 while i < 11: print(s1[i]) i += 1 # 用for循环实现 for i in s1: print(i) # 打印1-100内的3的倍数 for i in range(1, 101): if i % 3 == 0: print(i) # 获取一个字符串的长度 msg = 'abcde' print(len(msg)) # 5 # for循环的格式 # for "变量" in iterable: # for 循环是有限循环 # for 循环中断 for i in range(1, 101): if i % 3 == 0: print(i) if i == 77: break
模仿 重复 练习 / 改动 变通 /创新
当一个初级的程序员,练习代码量大于10万行
-
列表的索引 和 切片
和str的索引切片一致s1 = 'abcdefg' print(s1[1:-2]) # bcde
-
列表的增删改查
- 创建列表, 有3种方式
l1 = [1, 2, 'Alex']
l2 = list() / list(""iterable")
l3 = [i for i in iterable] - 列表的增删改查方法
- 列表的增: append insert extend
l1 = list() while 1: name = input("请输入新员工姓名:") if name in ['Q', 'q']: break l1.append(name) # append ,在最后位置追加 print(l1)
l1 = [1,2,3,4,5] while 1: name = input("请输入新员工姓名:") if name in ['Q', 'q']: break l1.insert(2,name) # insert插入, 先标位置再插入内容 print(l1)
l1 = [1,2,3,4,5] l1.extend('abcde') # extend 把可迭代内容一个一个的追加进去 print(l1)
- 列表的删除 pop()按索引 remove()按值 clear() del
# list.pop() 动作, 按索引删 l1 = [1, 2, 3, 4, 5] l1.pop(-2) # 这是个动作, 但是打印这个动作有值 删除4 print(l1.pop(-2)) # 第2个动作 删除3 /无索引默认删最后一个,有返回值. print(l1) # 1 2 5 # list.remove() 按值删 如有重名,从左开始删 pop用的多 l1 = [1, 2, 3, 4,5] l1.remove(1) print(l1) # 2 3 4 5 # list.clear() 清空成空表 l1 = [1,2,3,4,5] l1.clear() print(l1) # [] # del 按索引删 l1 = [1,2,3,4,5] del l1[1] # 按索引删 print(l1) # [1, 3, 4, 5] l1 = [1,2,3,4,5] del l1[::2] # 按切片删 print(l1) # [2, 4]
- 列表的改
按索引 \ 切片 改值
l1 = [1,2,3,4,5] l1[0] = '太白' # 按索引改值 print(l1) # ['太白', 2, 3, 4, 5] l1 = [1,2,3,4,5] l1[::2] = 'lyy' # 加步长, 数量要一一对应 print(l1) # ['l', 2, 'y', 4, 'y'] l1 = [1,2,3,4,5] l1[:2] = 'lyyyyy' # 加步长, 没有步长可以不用管数量 print(l1) # ['l', 'y', 'y', 'y', 'y', 'y', 3, 4, 5]
6.列表的查
按索引\切片(步长)查
for循环查询l1 = [1,2,3,4,5] for i in l1: print(i) # 显示列表的逐个内容
- 创建列表, 有3种方式
-
列表的嵌套 [1,2,[3,4,5]]
list1 = [1,2,[3,4,5]] list1[2][-1] = 'alex' print(list1) # [1, 2, [3, 4, 'alex']]
-
元组: 2个方法, count, index //不能增删改, 只能查
tuple1 = (1,2,3,4,5) for i in tuple1: print(i) print(len(tuple1)) # 长度 print(tuple1.count(3)) #统计3出现次数 print(tuple1.index(2)) # 查2的索引 print(tuple1.index(2, 0, 2)) # value start, stop # 如果元组里面有列表,则列表可改 tuple2 = (1,2,3,[5,6,7]) tuple2[3][0] = 55 print(tuple2) # (1, 2, 3, [55, 6, 7]) # 应用: 重要数据 用户名, 密码, 个人信息, 不想让别人动的一些数据, 存在元组中 # 元组的拆包 a, b = (1, 2) print(a, b) # 1, 2, 拆包必须一一对应
-
range 类似于列表的, 自定义范围的数字列表
# 普通range r = range(10) # 0,1,2,3,4,5,6,7,8,9 从0开始 for i in r: print(i) # 0,1,2,3,4,5,6,7,8,9 print(r[1]) # 1 range有索引 # # 可以设置start end step r1 = range(1, 10, 2) print(r1) # range(1, 10, 2) for i in range(1, 10, 2): # 可以设置start , end, step print(i) # 1,3,5,7,9 # 可以降序, step为负值 for i in range(10, 1, -1): print(i) # 10, 9,8,7,6,5,4,3,2 # 小例子 l1 = [1,2,3,'alex', '太白'] # 利用for循环, 利用range将l1列表的所有索引打印出来 for i in range(len(l1)): print(i) # 0,1,2,3,4 for i in range(5): pass print(i) # 4
-
列表嵌套的打印 判断一个item是不是列表元组 isinstance(i, list/class/tuple)
# li = [1, 3, 4, "alex", [3, 7, 8, "TaiBai"], 5, "RiTiAn"] # 循环打印列表中的每个元素,遇到列表则再循环打印出它里面的元素。 li = [1, 3, 4, "alex", [3, 7, 8,[666,777,], "TaiBai"], 5, "RiTiAn"] for item in li: if isinstance(item, list): for subitem in item: if isinstance(subitem, list): for sub_subitem in subitem: print(sub_subitem) else: print(subitem) else: print(item)
-
编程实现一个fabonacci数列
# 生成一个数字之内的fabonacci数列 li = [1,1] max_num = int(input("请输入生成多少数字之内的fabonacci:")) if max_num <= 2: print(li) else: while 1: next_num = li[-1] + li[-2] if next_num <= max_num: li.append(next_num) else:break print(li) # 生成多少长度的fabonacci数列 li = [1,1] max_num = int(input("请输入多少个的fabonacci数列:")) if max_num <= 2: print(li) else: while 1: next_num = li[-1] + li[-2] if len(li) < max_num: li.append(next_num) else:break print(li)
-
字典
- 数据类型分类(可变不可变)
可变-不可哈希 : list, dict, set
不可变-可哈希 : int float bool str tuple - 键值对组成字典, 键一般为int str, 值为任意类型
- 3.6之后, 字典是有序的, 按初建顺序
- 字典缺点: 以空间换时间, 字典查询快,但是浪费空间.
- 创建字典的方式
# 创建字典的方式 # 1 方式一: 利用元组或列表的拆包 dic = dict((('one', 1), ('two', 2), ('three', 3))) print(dic) # {'one': 1, 'two': 2, 'three': 3} dic = dict([['张三', 18], ['李四', 19], ['麻子',49]]) print(dic) # {'张三': 18, '李四': 19, '麻子': 49} # 2 方式二: 赋值创建 dic = dict(one = 1, two = 2, three = 3) print(dic) # {'one': 1, 'two': 2, 'three': 3} # 方式3: 正规官方创建方法 dic = dict({'one': 1, 'two': 2, 'three': 3}) print(dic) # {'one': 1, 'two': 2, 'three': 3} # 方式5: 拉链函数 dic = dict(zip(['one', 'two', 'three'],[1, 2, 3])) print(dic) # 方式6: 字典推导式 dic = { k: v for k,v in [('one', 1),('two', 2),('three', 3)]} print(dic) # 方式7:利用fromkey dic = dict.fromkeys('abcd','太白') print(dic) # {'a': '太白', 'b': '太白', 'c': '太白', 'd': '太白'}
- 字典的增删改查
# 字典的增 ------------- # 通过键值对直接增加 dic = {'name': '太白', 'age': 18} dic['weight'] = 75 # 没有weight这个键,就增加键值对 print(dic) # {'name': '太白', 'age': 18, 'weight': 75} dic['name'] = 'barry' # 有name这个键,就成了字典的改值 print(dic) # {'name': 'barry', 'age': 18, 'weight': 75} # setdefault dic = {'name': '太白', 'age': 18} dic.setdefault('height',175) # 没有height此键,则添加 print(dic) # {'name': '太白', 'age': 18, 'height': 175} dic.setdefault('name','barry') # 有此键则不变 print(dic) # {'name': '太白', 'age': 18, 'height': 175} #它有返回值 dic = {'name': '太白', 'age': 18} ret = dic.setdefault('name') print(ret) # 太白 # 字典的删 ------------ # pop 通过key删除字典的键值对,有返回值,可设置返回值。 dic = {'name': '太白', 'age': 18} # ret = dic.pop('name') # print(ret,dic) # 太白 {'age': 18} ret1 = dic.pop('n',None) print(ret1,dic) # None {'name': '太白', 'age': 18} #popitem 3.5版本之前,popitem为随机删除,3.6之后为删除最后一个,有返回值 dic = {'name': '太白', 'age': 18} ret = dic.popitem() print(ret,dic) # ('age', 18) {'name': '太白'} #clear 清空字典 dic = {'name': '太白', 'age': 18} dic.clear() print(dic) # {} # del # 通过键删除键值对 dic = {'name': '太白', 'age': 18} del dic['name'] print(dic) # {'age': 18} #删除整个字典 del dic # 字典的改 ---------------- # 通过键值对直接改 dic = {'name': '太白', 'age': 18} dic['name'] = 'barry' print(dic) # {'name': 'barry', 'age': 18} # update dic = {'name': '太白', 'age': 18} dic.update(sex='男', height=175) print(dic) # {'name': '太白', 'age': 18, 'sex': '男', 'height': 175} dic = {'name': '太白', 'age': 18} dic.update([(1, 'a'),(2, 'b'),(3, 'c'),(4, 'd')]) print(dic) # {'name': '太白', 'age': 18, 1: 'a', 2: 'b', 3: 'c', 4: 'd'} dic1 = {"name":"jin","age":18,"sex":"male"} dic2 = {"name":"alex","weight":75} dic1.update(dic2) print(dic1) # {'name': 'alex', 'age': 18, 'sex': 'male', 'weight': 75} print(dic2) # {'name': 'alex', 'weight': 75} # 字典的查 ------------ # 通过键查询 # 直接dic[key](没有此键会报错) dic = {'name': '太白', 'age': 18} print(dic['name']) # 太白 # get dic = {'name': '太白', 'age': 18} v = dic.get('name') print(v) # '太白' v = dic.get('name1') print(v) # None v = dic.get('name2','没有此键') print(v) # 没有此键 keys() dic = {'name': '太白', 'age': 18} print(dic.keys()) # dict_keys(['name', 'age']) values() dic = {'name': '太白', 'age': 18} print(dic.values()) # dict_values(['太白', 18]) items() dic = {'name': '太白', 'age': 18} print(dic.items()) # dict_items([('name', '太白'), ('age', 18)])
- 字典的嵌套
dic1 = { 'name':['alex',2,3,5], 'job':'teacher', 'oldboy':{'alex':['python1','python2',100]} } 1,将name对应的列表追加⼀个元素’wusir’。 2,将name对应的列表中的alex⾸字⺟⼤写。 3,oldboy对应的字典加⼀个键值对’⽼男孩’,’linux’。 4,将oldboy对应的字典中的alex对应的列表中的python2删除
# 汪峰一家的字典 dic = { 'name':'汪峰', 'age':48, 'wife':[{'name':'国际章','age':38}], 'children':{'girl_first':'小苹果','girl_second':'小怡','girl_three':'顶顶'} } # # 1. 获取汪峰的名字。 name = dic.get('name') print(name) # 2.获取这个字典:{'name':'国际章','age':38}。 dic1 = dic['wife'][0] print(dic1) # 3. 获取汪峰妻子的名字。 wife_name = dic['wife'][0]['name'] print(wife_name) # 4. 获取汪峰的第三个孩子名字。 three_children = dic['children']['girl_three'] print(three_children)
显示商品列表, 选择一种商品进行确认, 异常排除
goods = [ {'name':'电脑', 'price':1999}, {"name":'鼠标', 'price':10}, {"name":'游艇大功率', 'price':20}, {'name':'美女', 'price':998}, ] print('商品名称列表:') print("序号 商品名称 价格") for i, item in enumerate(goods): print(f'{i+1} {item["name"]} {item["price"]}') while True: choice = input("请输入您选择的商品编号:") if choice in ("Q",'q'): print("谢谢使用,再见!") break else: try: choice = int(choice) if 0 < choice <= len(goods): print(f"您选择的商品: {goods[choice-1]['name']}, 价格: {goods[choice-1]['price']}") break # 显示商品名称价格后, ---直接退出, 可根据要求改变break else: print('你选择的商品编号有误,请重新选择!') except ValueError: print('选择有误, 请重新输入您 选择的商品编号!')
- 数据类型分类(可变不可变)
-
字典keys() valus() 方法转换
dic = {'name':'taibai', 'age':18} key_list = dic.keys() print(key_list) # dict_keys(['name', 'age']) 叫高仿列表 key_list = list(key_list) print(key_list) # ['name', 'age'] 可用list转成正常列表 # dic.values() 也可以这样操作
-
拆包 / 循环取值
# a, b = ('name', 'taibai') # a, b = ['你好', '大飞哥'] # a,b = {"汪峰":'北京北京', '王菲': '天后'} dic = {'nage':'taibai', 'age':18} for k,v in dic.items(): print('这是键:', k) print('这是值:', v) 下面这个例子具有很强的数据意义: 创建位置不一样, 生成结果不一样.循环嵌套 data_list = [] data = {} # 这个字典在循环内与在循环外, 生成的结果不一样, key不能重复 for i in range(10): data['user'] = i data_list.append(data) print(data_list) # [{'user': 9}, {'user': 9}, {'user': 9}, {'user': 9}, {'user': 9}, {'user': 9}, {'user': 9}, {'user': 9}, {'user': 9}, {'user': 9}] print(data) # {'user': 9}
-
is id == 的用法
id 是身份证, 内存的唯一值
id相同, 值一定相同 / 值相同, id不一定相同
== 是比较的两边的数值是否相等,而 is 是比较的两边的内存地址是否相等。i = 1 print(id(i)) # 140735527383848 -5 -- 256 这个区间的值, 在内存中ID不变, 小数据池 l1 = [1,2,3] l2 = [1,2,3] print(l1 == l2) # True 判断值是否相等 print(l1 is l2) # False # 不同的内存空间 s1 = 'alex' s2 = 'alex' print(s1 is s2) # 小数据池内的值, 内存中是唯一的 s1 = 'oldboy' * 500 s2 = 'oldboy' * 500 print(s1 is s2) # True s1 = 'oldboy' * 5000 s2 = 'oldboy' * 5000 print(s1 is s2) # False
-
什么是代码块?
Python程序是由代码块构造的。块是一个python程序的文本,他是作为一个单元执行的。
代码块:一个模块,一个函数,一个类,一个文件等都是一个代码块。 -
同一代码块下的缓存机制
>前提条件:在同一个代码块内。 >机制内容:Python在执行同一个代码块的初始化对象的命令时,会检查是否其值是否已经存在,如果存在, 会将其重用。换句话说:执行同一个代码块时,遇到初始化对象的命令时,他会将初始化的这个变量与值存 储在一个字典中,在遇到新的变量时,会先在字典中查询记录,如果有同样的记录那么它会重复使用这个 字典中的之前的这个值。所以在你给出的例子中,文件执行时(同一个代码块)会把i1、i2两个变量指 向同一个对象,满足缓存机制则他们在内存中只存在一个,即:id相同。 适用对象: int(float),str,bool。 >对象的具体细则:(了解) int(float):任何数字在同一代码块下都会复用。 bool:True和False在字典中会以1,0方式存在,并且复用。 str:几乎所有的字符串都会符合缓存机制 ------------ >无论是缓存还是字符串驻留池,都是python做的一个优化,就是将~5-256的整数,和一定规则的字符串, 放在一个‘池’(容器,或者字典)中,无论程序中那些变量指向这些范围内的整数或者字符串,那么他直接 在这个‘池’中引用,言外之意,就是内存中之创建一个。 优点: 提升性能, 节省空间
-
不同代码块下的缓存机制, 也叫小数据池
小数据池,不同代码块的缓存机制,也称为小整数缓存机制,或者称为驻留机制等等 前提条件:在不同一个代码块内。 机制内容:官方对于整数,字符串的小数据池是这么说的: Python自动将-5~256的整数进行了缓存,当你将这些整数赋值给变量时,并不会重新创建对象, 而是使用已经创建好的缓存对象。 python会将一定规则的字符串在字符串驻留池中,创建一份,当你将这些字符串赋值给变量时, 并不会重新创建对象, 而是使用在字符串驻留池中创建好的对象。 适用对象: int(float),str,bool 不同代码块之间, -5-256 在内存中指向同一地址
缓存机制小结
同一代码块下适用一套缓存机制, 不同代码块下适用另一套缓存机制(小数据池)' 小数据池 -5 - 256 优点:提升性能, 节省空间
-
集合set
集合是容器型数据, 要求里面的元素不可变, 即可哈希, 但是集合本身是可变的. 集合是无序的. 集合的作用: 1.列表的去重, 去除重复元素 2.关系测试 即交集 并集 # 集合的创建 set1 = set() # 创建空集合 set1 = {1,2,'adf', 'name', 66} # 集合的增 set1.add('abc') set1.update("太白") # 迭代增加, 增加2个值, 太 白 集合的改: 可以变相实现, 先删除, 再增加 # 集合的删 set1.remove('太') # 按值删, 集合没有按索引删除,因为集合无序, 没有索引 set1.pop() # 随机删除一个 set1.clear() # 清空 del set1 # 删除集合整体 # 交集 & set1 = {1,2,3,4} set2 = {2,4,6,8} print(set1 & set2) # {2, 4} # 并集或合集 | set1 = {1,2,3,4} set2 = {2,4,6,8} print(set1 | set2) # {1, 2, 3, 4, 6, 8} # 差集 - set1 = {1,2,3,4} set2 = {2,4,6,8} print(set1 - set2) # {1, 3} # 反交集 ^ set1 = {1,2,3,4} set2 = {2,4,6,8} print(set1 ^ set2) # {1, 3, 6, 8} # 子集 与 超集 set1 = {1,2,3} set2 = {1,2,3,4,5} print(set1 < set2) # True 说明set1是set2子集 print(set2 > set1) # True 说明set2是set1超集 set3 = frozenset(set1) print(set3) # frozenset 冻结集合,变成不可变类型 # 集合的去重 set1 = [1,1,1,2,2,3,4,5,5,5,65,6,7,7,7,] set1 = list(set(set1)) print(set1) # [1, 2, 3, 4, 5, 65, 6, 7]
-
深浅copy
浅copy: 只是拷了一层皮, 里面的可变不可变数据都是旧的 l1 = [1,'taibai',[22,33]] l2 = l1.copy() l1[0] = 2 l2[-1].append(66) print(l1) # [2, 'taibai', [22, 33, 66]] print(l2) # [1, 'taibai', [22, 33, 66]] 深copy: 全部新建,不可变数据公用, 可变数据是新的 l1 = [1,'taibai',[22,33]] l2 = copy.deepcopy(l1) l1[0] = 2 l2[-1].append(66) print(l1) # [2, 'taibai', [22, 33]] print(l2) # [1, 'taibai', [22, 33, 66]] 对于浅copy来说,只是在内存中重新创建了开辟了一个空间存放一个新列表,但是新列表中的元素与原列表中的元素 是公用的。 对于深copy来说,列表是在内存中重新创建的,列表中可变的数据类型是重新创建的,列表中的不可变的数据类型 是公用的。
# 练习题: 1.使用循环打印出一下效果: * ** *** **** ***** **** *** ** * * *** ***** ******* ********* ---------------------------------- # 2, 敲7游戏 while 1: msg = input("敲7游戏, 请输入一个数字(Q/q退出):") if msg.upper() == 'Q': print("谢谢使用,再见!") break else: try: msg = int(msg) if msg < 7: print("数字太小,不能玩, 请重新输入!") else: result = [str(i) if i % 7 else '咣' for i in range(1, msg+1)] # 经典的列表推导 print(result) # 在这个位置打印列表, 也很美丽,,,打印输出不一定是在代码最后. except ValueError: print("输入的数字内容不合规,请重新输入!")
-
基础数据类型补充
- 字符串 capitylize swapcase title center find index
# 字符串 --capitylize swapcase title center find index # capitylize swapcase title name = 'taibai' print(name.capitalize()) # Taibai 首字母大写 print(name.swapcase()) # TAIBAI 大小写反转 msg = 'taibai say hi' print(msg.title()) # Taibai Say Hi 每个单词的首字母大写 # center print(name.center(20, "=")) # =======taibai======= # find index 查找字符串中的元素是否存在 print(name.find('i',3,3)) #2 返回是第1个找到的元素的索引, 'i'是文本,没有就返回-1 print(name.index("i", 1, 3)) #2 返回是第1个找到的元素的索引, 'i'是文本,没有就返回-1
2.元组 --index count
# 元组 --index count # 元组中如果只含有一个元素且没有逗号,则该元组不是元组,与改元素数据类型一致,如果有逗号,那么它是元组。 tu1 = (1) tu2 = (1,) print(type(tu1), type(tu2)) # <class 'int'> <class 'tuple'> # index:通过元素找索引(可切片),找到第一个元素就返回,找不到该元素即报错。 tu = ('太白', [1, 2, 3, ], 'WuSir', '女神') print(tu.index("太白")) # 0 # count: 获取某元素在列表中出现的次数 tu = ('太白', '太白', 'WuSir', '吴超') print(tu.count('太白')) # 2
3.列表 --count index sort reverse 相加 相乘
# 列表 --count index sort reverse 相加 相乘 # count(数)(方法统计某个元素在列表中出现的次数)。 a = ["q","w","q","r","t","y"] print(a.count('q')) # 2 # index(方法用于从列表中找出某个值第一个匹配项的索引位置) a = ["q","w","r","t","y"] print(a.index('r')) # 2 # sort (方法用于在原位置对列表进行排序)。 # reverse (方法将列表中的元素反向存放)。 a = ["q","w","r","t","y"] a.sort() print(a) # ['q', 'r', 't', 'w', 'y'] a.reverse() print(a) # ['y', 'w', 't', 'r', 'q'] # 列表也可以相加与整数相乘 l1 = [1,2,3,4] l2 = [5,6,7,8] print(l1+l2) # [1, 2, 3, 4, 5, 6, 7, 8] print(l1*2) # [1, 2, 3, 4, 1, 2, 3, 4]
练习题:
# 练习题: # 用3种方法实现, 把一个列表中的索引为奇数对应的元素删 # 第1种方法 l1 = [1,2,3,4,5,6,7,8,9] del l1[1::2] print(l1) # [1, 3, 5, 7, 9] # 第2种方法 现实中经常用这个方法, 倒序法更新列表 l1 = [1,2,3,4,5,6,7,8,9] for i in range(len(l1)-1, -1, -1): if i % 2 != 0: l1.pop(i) print(l1) # [1, 3, 5, 7, 9] # 第3种方法 思维转换 l1 = [1,2,3,4,5,6,7,8,9] l2 = [] for i in range(len(l1)): if i % 2 == 0: l2.append(l1[i]) l1 = l2 print(l1) # [1, 3, 5, 7, 9]
- 字典的增删改查的几个补充方法
#popitem 3.5版本之前,popitem为随机删除,3.6之后为删除最后一个,有返回值 dic = {'name': '太白', 'age': 18} ret = dic.popitem() print(ret,dic) # ('age', 18) {'name': '太白'} # update dic = {'name': '太白', 'age': 18} dic.update(sex='男', height=175) print(dic) # {'name': '太白', 'age': 18, 'sex': '男', 'height': 175} dic = {'name': '太白', 'age': 18} dic.update([(1, 'a'),(2, 'b'),(3, 'c'),(4, 'd')]) print(dic) # {'name': '太白', 'age': 18, 1: 'a', 2: 'b', 3: 'c', 4: 'd'} dic1 = {"name":"jin","age":18,"sex":"male"} dic2 = {"name":"alex","weight":75} dic1.update(dic2) print(dic1) # {'name': 'alex', 'age': 18, 'sex': 'male', 'weight': 75} print(dic2) # {'name': 'alex', 'weight': 75}
# fromkeys:创建一个字典:字典的所有键来自一个可迭代对象,字典的值使用同一个值。 dic = dict.fromkeys('abcd','太白') print(dic) # {'a': '太白', 'b': '太白', 'c': '太白', 'd': '太白'} # dic = dict.fromkeys([1, 2, 3],'太白') print(dic) # {1: '太白', 2: '太白', 3: '太白'} # 这里有一个坑,就是如果通过fromkeys得到的字典的值为可变的数据类型,那么你要小心了。 dic = dict.fromkeys([1, 2, 3], []) dic[1].append(666) print(id(dic[1]),id(dic[2]),id(dic[3])) # {1: [666], 2: [666], 3: [666]} print(dic) # {1: [666], 2: [666], 3: [666]}
循环字典,改变字典大小的问题
练习题: dic = {'k1':'太白','k2':'barry','k3': '白白', 'age': 18} 请将字典中所有键带k元素的键值对删除。 # 错误 dic = {'k1':'太白','k2':'barry','k3': '白白', 'age': 18} for key in dic: if "k" in key: dic.pop(key) # RuntimeError: dictionary changed size during iteration # 错误 dic = {'k1':'太白','k2':'barry','k3': '白白', 'age': 18} for key in dic.keys(): if "k" in key: dic.pop(key) # RuntimeError: dictionary changed size during iteration # 正确 dic = {'k1':'太白','k2':'barry','k3': '白白', 'age': 18} for key in list(dic.keys()): # 把键转成列表 if "k" in key: dic.pop(key) print(dic) #{'age': 18}
-
数据类型之间的转换
int bool str 三者转换
# int ---> bool i = 100 print(bool(i)) # True # 非零即True i1 = 0 print(bool(i1)) # False 零即False # bool ---> int t = True print(int(t)) # 1 True --> 1 t = False print(int(t)) # 0 False --> 0 # int ---> str i1 = 100 print(str(i1)) # '100' # str ---> int # 全部由数字组成的字符串才可以转化成数字 s1 = '90' print(int(s1)) # 90 # str ---> bool s1 = '太白' s2 = '' print(bool(s1)) # True 非空即True print(bool(s2)) # False # bool ---> str t1 = True print(str(True)) # 'True'
str list 两者转换
# str ---> list s1 = 'alex 太白 武大' print(s1.split()) # ['alex', '太白', '武大'] # list ---> str # 前提 list 里面所有的元素必须是字符串类型才可以 l1 = ['alex', '太白', '武大'] print(' '.join(l1)) # 'alex 太白 武大'
list set 两者转换
# list ---> set s1 = [1, 2, 3] print(set(s1)) # set ---> list set1 = {1, 2, 3, 3,} print(list(set1)) # [1, 2, 3]
str bytes 两者转换
# str ---> bytes s1 = '太白' print(s1.encode('utf-8')) # b'\xe5\xa4\xaa\xe7\x99\xbd' # bytes ---> str b = b'\xe5\xa4\xaa\xe7\x99\xbd' print(b.decode('utf-8')) # '太白'
所有数据都可以转化成bool值
转化成bool值为False的数据类型有: '', 0, (), {}, [], set(), None
-
编码的进阶 -- 基础数据类型分类划分
按存储空间占用--从低到高 数字 字符串 集合 : 无序 即无索引 元组 : 有序,有索引, 不可变 列表 : 有序,有索引, 可变, 需要处理数据的增删改 字典 : 有序,需要key和value的相关信息, 可变,需要处理数据的增删改 按存值个数区分 标量类型: 数字 字符串 容器类型: 列表 元组 字典 按可变不可变划分 可变: 列表 字典 不可变: 数字 字符串 元组 布尔值 按访问顺序划分 直接访问: 数字 顺序访问: 字符串 列表 元组 key值访问: 字典
-
数据的编码与解码 encode decode
数据在内存中都是以Unicode编码的, 但是在网络传输或者存储时,必须是utf-8 / GBK等形式. 内存中除了Unicode类型, 只有一个其他的数据类型,就是bytes类型 name = b'taibai' print(type(name)) # <class 'bytes'> 字符串有的方法, bytes几乎都有 数据只有转成bytes, 才能传输出去 # encode称作编码:将 str 转化成 bytes类型 s1 = '中国' b1 = s1.encode('utf-8') # 转化成utf-8的bytes类型 print(s1) # 中国 print(b1) # b'\xe4\xb8\xad\xe5\x9b\xbd' #### str ----> bytes s1 = '中国' b1 = s1.encode('gbk') # 转化成gbk的bytes类型 print(s1) # 中国 print(b1) # b'\xd6\xd0\xb9\xfa' #### bytes ---> str # decode称作解码, 将 bytes 转化成 str类型 b1 = b'\xe4\xb8\xad\xe5\x9b\xbd' s1 = b1.decode('utf-8') print(s1) # 中国 b1 = b'\xe4\xb8\xad\xe5\x9b\xbd' # 这是utf-8编码bytes类型的中国 b2 = b'\xd6\xd0\xb9\xfa' # 这是gbk编码bytes类型的中国 gbk ---> utf-8转换 b2 = b'\xd6\xd0\xb9\xfa' b3 = b2.decode("gbk").encode("utf-8") print(b3) # b'\xe4\xb8\xad\xe5\x9b\xbd'
练习题
2. l1 = [['_']*3]*3 # [['_','_','_'],['_','_','_'],['_','_','_']] 3.看代码写结果,并解释每一步的流程。 v1 = [1,2,3,4,5,6,7,8,9] v2 = {} for item in v1: if item < 6: continue if 'k1' in v2: v2['k1'].append(item) else: v2['k1'] = [item ] #没有键值对,就创建一个 print(v2) # 10.看代码写结果 v1 = [1,2,3,{"name":'太白',"numbers":[7,77,88]},4,5] v2 = copy.deepcopy(v1) print(v1 is v2) print(v1[0] is v2[0]) print(v1[3] is v2[3]) print(v1[3]['name'] is v2[3]['name']) print(v1[3]['numbers'] is v2[3]['numbers']) print(v1[3]['numbers'][1] is v2[3]['numbers'][1]) # 18.完成下列需求: s1 = '太白金星' 将s1转换成utf-8的bytes类型。 将s1转化成gbk的bytes类型。 b = b'\xe5\xae\x9d\xe5\x85\x83\xe6\x9c\x80\xe5\xb8\x85' # b为utf-8的bytes类型,请转换成gbk的bytes类型。 19.用户输入一个数字,判断一个数是否是水仙花数。 20.# 把列表中所有姓周的⼈的信息删掉(此题有坑, 请慎重): # lst = ['周⽼⼆', '周星星', '麻花藤', '周扒⽪'] # 结果: lst = ['麻花藤'] lst = [ i for i in lst if '周' not in i]----有点绝... 21.车牌区域划分, 现给出以下车牌. 根据车牌的信息, 分析出各省的车牌持有量. (选做题) cars = ['鲁A32444','鲁B12333','京B8989M','⿊C49678','⿊C46555','沪 B25041'] locals = {'沪':'上海', '⿊':'⿊⻰江', '鲁':'⼭东', '鄂':'湖北', '湘':'湖南'} # 结果: {'⿊⻰江':2, '⼭东': 2, '上海': 1} count = {} for car in cars: if car[0] in locals: i = locals[car[0]] if i in count: count[i] += 1 else: count[i] = 1 print(count)
-
文件操作 r w a rb wb r+ / read() readlines() write() tell() seek() flush() 改文件
Bytes类型的文本,只供计算机使用,只用于网络传输和存储
str是人类文本,供人类使用.- 文件操作: 读 模式:r rb / read() read(n) readline() readlines()
文件读写的2个通常错误: 1. 路径没找到: 绝对路径 / 相对路径 路径如果被转义, 最好在前面加"r"禁止转义 2. 编码错误: 打开的编码与写入的编码要一致. # read() with open(r'E:\software\pythonProject\practice\创建了一个文本.txt', encoding='utf-8', mode='r') as f1: print(f1.read()) # 全部读出并打印 # read(n) with open(r'E:\software\pythonProject\practice\创建了一个文本.txt', encoding='utf-8', mode='r') as f1: print(f1.read(4)) # 这是什么 只读前4个字符 # readline() with open(r'E:\software\pythonProject\practice\创建了一个文本.txt', encoding='utf-8', mode='r') as f1: print(f1.readline()) # 读第1行 print(f1.readline()) # 读第2行打印 # readlines() with open(r'E:\software\pythonProject\practice\创建了一个文本.txt', encoding='utf-8', mode='r') as f1: content = f1.readlines() print(content) # 是列表 ['这是什么内容\n', '\n', '每个国家都有每个国家的国歌\n', 'news.sohu.com\n', 'www.baidu.com\n', '\n', '123'] for i in content: #循环列表 print(i) # 循环列表打印输出 # rb模式 读视频 图片 with open("采购小帮手.jpg", mode='rb') as f1: content = f1.read() # 读取图片内容, 输出的是Bytes内容 print(content) # b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x00`
- 文件操作: 写 w wb
with open("文件的写.txt", encoding='utf-8', mode='w') as f1: f1.write('随便写一点') # 没有文件,先创建文件 with open("文件的写.txt", encoding='utf-8', mode='w') as f1: f1.write('taibai is best!') #先清空, 后写入 with open("采购小帮手.jpg", mode='rb') as f1: content = f1.read() # 以rb模式读一个图片视频文件, 读取 with open("caigou.jpg", mode='wb') as f2: f2.write(content) # 以wb模式创建一个文件, 再写入, 就完成了复制
- 文件操作: 追加 a(append)
# 文件的追加a with open("文件的写.txt", encoding='utf-8', mode='a') as f1: f1.write('\n') #如果没有文件,就创建文件再追加内容 f1.write('太白最帅!!') # 追加一行6个字符 with open("文件的写.txt", encoding='utf-8', mode='r') as f1: content = f1.read() print(content)
- 文件操作其他 r+ 先读后追加, 让光标到最后/ 一定要先读到最后才能加,要不出错。
with open("文件的写.txt", encoding='utf-8', mode='r+') as f1: content = f1.read() print(content) f1.write('\n人的一切痛苦,本质都是对自己无能的愤怒。')
- 文件操作的其他功能: tell() seek() flush()
# tell() 获取光标的位置, 单位是字节 , 不是字符 with open("文件的写.txt", encoding='utf-8', mode='r') as f1: print("光标位置:", f1.tell()) # 0 content = f1.read() print(content) print("光标位置:", f1.tell()) # 667 # seek() 调整光标位置, 从光标位置开始读写, 是字节 with open("文件的写.txt", encoding='utf-8', mode='r') as f1: print(f1.seek(7)) # 先调整光标位置, 从8开始读 content = f1.read() print(content) # flush 强制刷新 with open("文件的写.txt", encoding='utf-8', mode='w') as f1: f1.seek(667) # 从667开始写 f1.write('中华人民共和国是个伟大的国家!!!!') f1.flush() # 强制刷新保存
- with open 打开多个文件同时操作,文件复制、 反斜杠回车换行
# 文件的复制 with open("文件的写.txt", encoding='utf-8', mode='r') as f1, \ open("文件的写2.txt", encoding='utf-8', mode='w') as f2: content = f1.readlines() for i in content: f2.write(i) 修改文件的步骤 1. 以读的模式打开 2. 以写的模式创建一个新文件 3. 将原文件读出来写入新文件 4. 将原文件删除 5. 将新文件改成原文件 #### 修改一个文件的代码: # low版 import os with open("文件的写.txt", encoding='utf-8', mode='r') as f1, \ open("中国.txt", encoding='utf-8', mode='w') as f2: old_content = f1.read() new_content = old_content.replace('国家','USA') f2.write(new_content) os.remove('文件的写.txt') os.renames('中国.txt','文件的写.txt') # 高级版 import os with open("文件的写.txt", encoding='utf-8', mode='r') as f1, \ open("中国.txt", encoding='utf-8', mode='w') as f2: for line in f1.readlines(): new_line = line.replace('中国', 'USA') f2.write(new_line) os.remove('文件的写.txt') os.renames('中国.txt','文件的写.txt')
练习题
1. 文件a.txt内容:每一行内容分别为商品名字,价钱,个数。 apple 10 3 tesla 100000 1 mac 3000 2 lenovo 30000 3 chicken 10 3 通过代码,将其构建成这种数据类型:[{'name':'apple','price':10,'amount':3},{'name':'tesla','price':1000000,'amount':1}......] 并计算出总价钱。 2,有如下文件: ------- alex是老男孩python发起人,创建人。 alex其实是人妖。 谁说alex是sb? 你们真逗,alex再牛逼,也掩饰不住资深屌丝的气质。 将文件中所有的alex都替换成大写的SB。 # 6.文件a1.txt内容(选做题) # 序号 部门 人数 平均年龄 备注 # 1 python 30 26 单身狗 # 2 Linux 26 30 没对象 # 3 运营部 20 24 女生多 # ....... # 通过代码,将其构建成这种数据类型: # [{'序号':'1','部门':Python,'人数':30,'平均年龄':26,'备注':'单身狗'}, # ......]
-
函数 以功能为导向, 减少代码重复, 使代码可读性更好.
- 函数结构:
def 函数名():
函数体 # 函数名 加 () ,就执行. - 函数的返回值: 一个函数就是封装一个功能,这个功能一般都会有一个最终结果
. 遇到return,函数结束,return下面的(函数内)的代码不会执行。
. return 会给函数的执行者返回值。
如果return后面什么都不写,或者函数中没有return,则返回的结果是None
如果return后面写了一个值,返回给调用者这个值
如果return后面写了多个结果,,返回给调用者一个tuple(元组),拆包。 - 函数的参数:
形参: 定义函数时写的参数 叫形参 (位置参数/默认参数)
实参: 函数调用时给函数传递的参数,叫实参 (位置参数/关键字参数/混合参数)
传参: 就是将实参交给形参的过程 - 实参角度 - 位置参数: 从左至右,一一对应.
def compare(int1, int2): return int1 if int1 > int2 else int2 # 三元表达式 res = compare(1,2) # 1, 2就是实参, 返回值2给了compare(1,2)整体,可赋值给变量或打印 print(res) # 2
5.实参角度 - 关键字参数: 如果参数过多,只需记住参数名字=实参. 关键字参数不用一一对应.
def compare(int1, int2): return int1 if int1 > int2 else int2 compare(int1 = 123, int2 = 124) # 形参名 = 实参名, 这就叫关键字参数
- 实参角度 - 混合传参: 既有位置参数,又有关键字参数
位置参数 一定 要在关键字参数的前面. - 形参角度 - 默认值参数, 在形参里设置默认值, 比如open函数默认值为r, 默认形参必须放在函数定义最后.
def meet(sex,skill, age = 18): # age就是默认函数 pass res = meet('女', skill = 'python') # 默认参数可以不传 print(res)
练习题
1. 定义一个函数,传四个参数name, sex, age, edu写入一个文件. # 连续输入 def func(name, sex, age, edu): with open("student_msg", encoding='utf-8', mode='a') as f1: f1.write(f"{name} | {sex} | {age} | {edu}\n") while 1: name = input("输入姓名(Q/q):") if name.upper() == 'Q': break sex = input("请输入性别:") if sex == "": sex = '女' age = input("请输入年龄:") edu = input("请输入学历:") func(name, sex, age, edu) 2. return 右函数里可以终止while / return可以结束函数,况且while def func(): count = 1 while 1: count += 1 print(count) return func() # 2 3. 定义一个函数, 可以修改文件的内容 import os def file(path, old_content, new_content): with open(path, encoding='utf-8', mode='r') as f1,\ open(path+'.bak', encoding='utf-8', mode='w') as f2: for line in f1: line = line.replace(old_content, new_content) f2.write(line) os.remove(path) os.renames(path+'.bak', path) file('tt.bak', 'USA', 'SIGAPOR')
- 形参角度: 万能参数
万能参数: args, 一种形参,能接收所有的实参. 牛B的是, 聚合成一个元组.
**kwargs, 关键字参数, 聚合到一个字典
*的魔性用法: 定义的时候是聚合 ,执行的时候是打散 *****重要
def func(*args, **kwargs): print(args) print(kwargs) func(1,2,3,4,name='laddyboy') # (1, 2, 3, 4) / {'name': 'laddyboy'} # #前后位置关系,如果想让*args得到值, 那args需要被覆盖. def func(a, b, *args, sex='boy'): print(a, b) # 1 2 print(args) # (3, 4, 5) print(sex) # girl func(1,2,3,4,5,sex='girl') #这样写是可以的. def func(a, b, *args,name='boy', **kwargs):
仅限关键字参数
def func(a, b, *args,sex='boy',c, **kwargs): # c是仅限关键字参数,必须要在实参中传值. print(a, b) print(args) print(sex) print(c) print(kwargs) func(1,2,3,4,5,sex='girl', c='laddyboy',age=18,height=100) ==> 1 2 ==> (3, 4, 5) ==> girl ==>laddyboy ==> {'age': 18, 'height': 100}
形参的最终顺序
形参角度最终顺序(重要必记): 位置参数, *args, 默认参数, 仅限关键字参数, **kwargs
在函数的调用时, *代表打散
def func(*args): return args flag = func(*[1,2,3],*[4,5,6]) # 执行函数的时候,可以在[] () {}前边加上*, 打散后再传后,即可得到打散后的值 # 加上*之后,相当于把列表元组字典两边的束缚拆开了. 特殊时候很有用. print(flag) # (1, 2, 3, 4, 5, 6) # 被打散了 也可以 func(*"str") func(*dict) 例子: 定义一个函数, 体会* **的打散 def func(*args, **kwargs): print(args) print(kwargs) str = 'abc' name = {'name':'张三',} age = {'age':18,} func(*str,**name, **age) ==> ('a', 'b', 'c') ==> {'name': '张三', 'age': 18}
- 名称空间 与作用域
全局名称空间, 局部名称空间, 内置名称空间 python分这3个空间
\1. 内置命名空间--> 存放python解释器为我们提供的名字, list, tuple, str, int这些都是内置命名空间 \2. 全局命名空间--> 我们直接在py文件中, 函数外声明的变量都属于全局命名空间 \3. 局部命名空间--> 在函数中声明的变量会放在局部命名空间 函数执行完后消失,临时空间能用全局与内置的变量
加载顺序 取值顺序
加载: 内置名称空间 --> 全局名称空间 --> 局部名称空间 取值: 局部名称空间 --> 全局名称空间 --> 内置名称空间 单向 不可逆 名称空间取值, 遵守就近原则 例: def func(): # input ='alex' print(input) func() # <built-in function input>
作用域
只有两个作用域: 全局作用域: 内置名称空间 和 全局名称空间 局部作用域: 局部名称空间 局部作用域可以引用全部作用域的变量, 不能修改全局变量. referncee befor assignment LEGB原则, 就近原则, local - eclose - global - built in
- 函数的嵌套 (高阶函数), 就是函数套函数
def func2(): print(2) def func3(): print(6) print(4) func3() print(8) print(3) func2() print(5) # 执行结果 3 /2 /4 /6 /8 /5
- 内置函数: globals() locals()
这2个内置函数很简单 print(globals()) 返回的是字典, 字典里的键值对: 全局作用域的全部内容 print(locals()) 返回的是字典, 字典里的键值对: 当前作用域的全部内容 这个用途很广泛, ,,,多多实践练习尝试
- 关键字: nonlocal global
- 函数结构: