变量
- 定义变量的语法 
变量名 = 值
- 标识符 - 由数字、字母、下划线组成 
- 不能数字开头 
- 不能使用内置关键字 
- 严格区分大小写 
 
- 数据类型 - 整型:int 
- 浮点型:float 
- 字符串:str 
- 布尔型:bool 
- 元组:tuple 
- 集合:set 
- 字典:dict 
 
输出
- 格式化输出 (格式化符号) - %s:格式化输出字符串 
- %d:格式化输出整数 
- %f:格式化输出浮点数 
 
- f-字符串 
f'{表达式}'
age = 18 
name = 'TOM'
weight = 75.5
student_id = 1
# 我的名字是TOM
print('我的名字是%s' % name)
# 我的学号是0001
print('我的学号是%4d' % student_id)
# 我的体重是75.50公斤
print('我的体重是%.2f公斤' % weight)
# 我的名字是TOM,今年18岁了
print('我的名字是%s,今年%d岁了' % (name, age))
# 我的名字是TOM,明年19岁了
print('我的名字是%s,明年%d岁了' % (name, age + 1))
# 我的名字是TOM,明年19岁了
print(f'我的名字是{name}, 明年{age + 1}岁了')- 转义字符 - \n:换行 
- \t:制表符 
 
- print结束符 
print('内容', end="")
输入
- 输入的语法 
input("提示信息")
password = input('请输入您的密码:')
print(f'您输入的密码是{password}')
# <class 'str'>
print(type(password))转换数据类型
# 1. 接收用户输入
num = input('请输入您的幸运数字:')
# 2. 打印结果
print(f"您的幸运数字是{num}")
# 3. 检测接收到的用户输入的数据类型 -- str类型
print(type(num))
# 4. 转换数据类型为整型 -- int类型
print(type(int(num)))# 1. float() -- 转换成浮点型
num1 = 1
print(float(num1))
print(type(float(num1)))
# 2. str() -- 转换成字符串类型
num2 = 10
print(type(str(num2)))
# 3. tuple() -- 将一个序列转换成元组
list1 = [10, 20, 30]
print(tuple(list1))
print(type(tuple(list1)))
# 4. list() -- 将一个序列转换成列表
t1 = (100, 200, 300)
print(list(t1))
print(type(list(t1)))
# 5. eval() -- 将字符串中的数据转换成Python表达式原本类型
str1 = '10'
str2 = '[1, 2, 3]'
str3 = '(1000, 2000, 3000)'
print(type(eval(str1)))
print(type(eval(str2)))
print(type(eval(str3)))运算符
算数运算符
| 运算符 | 描述 | 实例 | 
|---|---|---|
| + | 加 | 1 + 1 输出结果为 2 | 
| - | 减 | 1-1 输出结果为 0 | 
| * | 乘 | 2 * 2 输出结果为 4 | 
| / | 除 | 10 / 2 输出结果为 5 | 
| // | 整除 | 9 // 4 输出结果为2 | 
| % | 取余 | 9 % 4 输出结果为 1 | 
| ** | 指数 | 2 ** 4 输出结果为 16,即 2 * 2 * 2 * 2 | 
| () | 小括号 | 小括号用来提高运算优先级,即 (1 + 2) * 3 输出结果为 9 | 
- 混合运算优先级顺序 - ()高于- **高于- *- /- //- %高于- +- -
赋值运算符
=
复合赋值运算符
| 运算符 | 描述 | 实例 | 
|---|---|---|
| += | 加法赋值运算符 | c += a 等价于 c = c + a | 
| -= | 减法赋值运算符 | c -= a 等价于 c = c- a | 
| *= | 乘法赋值运算符 | c *= a 等价于 c = c * a | 
| /= | 除法赋值运算符 | c /= a 等价于 c = c / a | 
| //= | 整除赋值运算符 | c //= a 等价于 c = c // a | 
| %= | 取余赋值运算符 | c %= a 等价于 c = c % a | 
| **= | 幂赋值运算符 | c ** = a 等价于 c = c ** a | 
比较运算符
| 运算符 | 描述 | 实例 | 
|---|---|---|
| == | 判断相等。如果两个操作数的结果相等,则条件结果为真(True),否则条件结果为假(False) | 如a=3,b=3,则(a == b) 为 True | 
| != | 不等于 。如果两个操作数的结果不相等,则条件为真(True),否则条件结果为假(False) | 如a=3,b=3,则(a == b) 为 True如a=1,b=3,则(a != b) 为 True | 
| > | 运算符左侧操作数结果是否大于右侧操作数结果,如果大于,则条件为真,否则为假 | 如a=7,b=3,则(a > b) 为 True | 
| < | 运算符左侧操作数结果是否小于右侧操作数结果,如果小于,则条件为真,否则为假 | 如a=7,b=3,则(a < b) 为 False | 
| >= | 运算符左侧操作数结果是否大于等于右侧操作数结果,如果大于,则条件为真,否则为假 | 如a=7,b=3,则(a < b) 为 False如a=3,b=3,则(a >= b) 为 True | 
| <= | 运算符左侧操作数结果是否小于等于右侧操作数结果,如果小于,则条件为真,否则为假 | 如a=3,b=3,则(a <= b) 为 True | 
逻辑运算符
| 运算符 | 逻辑表达式 | 描述 | 实例 | 
|---|---|---|---|
| and | x and y | 布尔"与":如果 x 为 False,x and y 返回 False,否则它返回 y 的值。 | True and False, 返回 False。 | 
| or | x or y | 布尔"或":如果 x 是 True,它返回 True,否则它返回 y 的值。 | False or True, 返回 True。 | 
| not | not x | 布尔"非":如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。 | not True 返回 False, not False 返回 True | 
流程控制
条件语句
if语句
if True:
    print('条件成立执行的代码1')
    print('条件成立执行的代码2')
# 下方的代码没有缩进到if语句块,所以和if条件无关
print('我是无论条件是否成立都要执行的代码')if...else...语句
age = int(input('请输入您的年龄:'))
if age >= 18:
    print(f'您的年龄是{age},已经成年,可以上网')
else:
    print(f'您的年龄是{age},未成年,请自行回家写作业')
print('系统关闭')多重判断
age = int(input('请输入您的年龄:'))
if age < 18:
    print(f'您的年龄是{age},童工一枚')
elif (age >= 18) and (age <= 60):
    print(f'您的年龄是{age},合法工龄')
elif age > 60:
    print(f'您的年龄是{age},可以退休')if嵌套
1. 如果有钱,则可以上车
    2. 上车后,如果有空座,可以坐下
    上车后,如果没有空座,则站着等空座位
如果没钱,不能上车
"""
# 假设用 money = 1 表示有钱, money = 0表示没有钱; seat = 1 表示有空座,seat = 0 表示没有空座
money = 1
seat = 0
if money == 1:
    print('土豪,不差钱,顺利上车')
    if seat == 1:
        print('有空座,可以坐下')
    else:
        print('没有空座,站等')
else:
    print('没钱,不能上车,追着公交车跑')三目运算符
值1 if 条件 else 值2
a = 1
b = 2
c = a if a > b else b
print(c)循环语句
while语句
#计算1-100偶数累加和
# 方法一:条件判断和2取余数为0则累加计算
i = 1
result = 0
while i <= 100:
    if i % 2 == 0:
        result += i
    i += 1
# 输出2550
print(result)
# 方法二:计数器控制增量为2
i = 0
result = 0
while i <= 100:
    result += i
    i += 2
# 输出2550
print(result)break和continue
- break(即终止此循环)和continue(退出当前⼀次循环继而执行下⼀次循环代码)是循环中满⾜⼀定条件退出循环的两种不同方式。 
i = 1
while i <= 5:
 if i == 4:
 print(f'吃饱了了不不吃了了')
 break
 print(f'吃了了第{i}个苹果')
 i += 1i = 1
while i <= 5:
 if i == 3:
 print(f'大虫子,第{i}个不不吃了了')
 # 在continue之前一定要修改计数器器,否则会陷入死循环
 i += 1
 continue
 print(f'吃了第{i}个苹果')
 i += 1while循环嵌套
# 重复打印5行星星
# j表示行号
j = 0
while j <= 4:
 # 一行星星的打印
 i = 0
 # i表示每行里面星星的个数,这个数字要和行号相等所以i要和j联动
 while i <= j:
 print('*', end='')
 i += 1
 print()
 j += 1#九九乘法表
j = 1
while j <= 9:
 # 打印一行里面的表达式 a * b = a*b
 i = 1
 while i <= j:
 print(f'{i}*{j}={j*i}', end='\t')
 i += 1
 print()
 j += 1for循环
for 临时变量 in 序列:
    重复执行的代码1
    重复执行的代码2else
while...else
- 循环可以和else配合使用,else下⽅缩进的代码指的是当循环正常结束之后要执行的代码 
while 条件:
 条件成立重复执行的代码
else:
 循环正常结束之后要执行的代码- 所谓else指的是循环正常结束之后要执行的代码,即如果是break终止循环的情况,else下方缩进的代码将不执行 
- continue是退出当前一次循环,继续下一次循环,所以该循环在continue控制下是可以正常结束的,当循环结束后,则执行了else缩进的代码 
for...else
for 临时变量量 in 序列列:
 重复执⾏行行的代码
 ...
else:
 循环正常结束之后要执⾏行行的代码数据序列
字符串
字符串输入输出
下标
- 计算机为数据序列列中每个元素分配的从0开始的编号 
切片
- 切片是指对操作的对象截取其中一部分的操作。字符串、列表、元组都支持切片操作 
序列[开始位置下标:结束位置下标:步长]常用操作方法
查找
所谓字符串查找方法即是查找子串在字符串中的位置或出现的次数
- find():检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则则返回-1。 
字符串序列.find(子串, 开始位置下标, 结束位置下标)开始和结束位置下标可以省略,表示在整个字符串序列中查找开始和结束位置下标可以省略,表示在整个字符串序列中查找
- index():检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则则报异常。 
字符串序列.index(子串, 开始位置下标, 结束位置下标)rfind(): 和find()功能相同,但查找方向为右侧开始。
rindex():和index()功能相同,但查找方向为右侧开始。
- count():返回某个⼦串在字符串中出现的次数 
字符串串序列列.count(子串, 开始位置下标, 结束位置下标)修改
所谓修改字符串,指的就是通过函数的形式修改字符串中的数据。
- replace():替换 
字符串序列.replace(旧子串, 新子串, 替换次数)注意:替换次数如果查出子串出现次数,则替换次数为该子串出现次数
- split():按照指定字符分割字符串 
字符串序列.split(分割字符, num)注意:num表示的是分割字符出现的次数,即将来返回数据个数为num+1个
mystr = "hello world and itcast and itheima and Python"
print(mystr.split('and'))
# 结果:['hello world ', ' itcast ', ' itheima ', ' Python']
print(mystr.split('and', 2))
# 结果:['hello world ', ' itcast ', ' itheima and Python']
print(mystr.split(' '))
# 结果:['hello', 'world', 'and', 'itcast', 'and', 'itheima', 'and', 'Python']
print(mystr.split(' ', 2))
# 结果:['hello', 'world', 'and itcast and itheima and Python']如果分割字符是原有字符串中的子串,分割后则丢失该子串
- join():用一个字符或子串合并字符串,即是将多个字符串合并为一个新的字符串 
字符或子串.join(多字符串组成的序列)list1 = ['chuan', 'zhi', 'bo', 'ke']
t1 = ('aa', 'b', 'cc', 'ddd')
# 结果:chuan_zhi_bo_ke
print('_'.join(list1))
# 结果:aa...b...cc...ddd
print('...'.join(t1))list1 = ['chuan', 'zhi', 'bo', 'ke']
t1 = ('aa', 'b', 'cc', 'ddd')
# 结果:chuan_zhi_bo_ke
print('_'.join(list1))
# 结果:aa...b...cc...ddd
print('...'.join(t1))- capitalize():将字符串第一个字符转换成大写 
- title():将字符串每个单词首字母转换成大写 
- lower():将字符串中大写转小写 
- upper():将字符串中小写转大写 
- lstrip():删除字符串左侧空白字符 
- rstrip():删除字符串右侧空白字符 
- strip():删除字符串两侧空白字符 
- ljust():返回一个原字符串左对齐,并使用指定字符(默认空格)填充至对应长的新字符串 
字符串序列.ljust(长度, 填充字符)- rjust():返回一个原字符串右对齐,并使用指定字符(默认空格)填充至对应长度 的新字符串,语法和ljust()相同 
- center():返回一个原字符串居中对齐,并使用指定字符(默认空格)填充至对应长度 的新字符串,语法和ljust()相同 
- startswith():检查字符串是否是以指定子串开头,是则返回 True,否则返回 False 
字符串序列.startswith(子串, 开始位置下标, 结束位置下标)- endswith()::检查字符串是否是以指定子串结尾,是则返回 True,否则返回 False 
- isalpha():如果字符串至少有一个字符并且所有字符都是字母则返回 True, 否则返回 False 
- isdigit():如果字符串只包含数字则返回 True 否则返回 False 
- isalnum():如果字符串至少有一个字符并且所有字符都是字母或数字则返 回 True,否则返回 False 
- isspace():如果字符串中只包含空白,则返回 True,否则返回 False 
列表
- 列表的格式 
[数据1, 数据2, 数据3, 数据4......]列表的常用操作
查找
- 下标 
- index():返回指定数据所在位置的下标 
- count():统计指定数据在当前列表中出现的次数 
- len():访问列表长度,即列表中数据的个数 
- in:判断指定数据在某个列表序列,如果在返回True,否则返回False 
- not in:判断指定数据不在某个列表序列,如果不在返回True,否则返回False 
增加
- append():列表结尾追加数据 
如果append()追加的数据是一个序列,则追加整个序列到列表
name_list = ['Tom', 'Lily', 'Rose']
name_list.append(['xiaoming', 'xiaohong'])
# 结果:['Tom', 'Lily', 'Rose', ['xiaoming', 'xiaohong']]
print(name_list)- extend():列表结尾追加数据,如果数据是一个序列,则将这个序列的数据逐一添加到列表 
- insert():指定位置新增数据 
列表序列.insert(位置下标, 数据)删除
- del 
name_list = ['Tom', 'Lily', 'Rose']
# 结果:报错提示:name 'name_list' is not defined
del name_list
print(name_list)name_list = ['Tom', 'Lily', 'Rose']
del name_list[0]
# 结果:['Lily', 'Rose']
print(name_list)- pop():删除指定下标的数据(默认为最后一个),并返回该数据 
列表序列.pop(下标)- remove():移除列表中某个数据的第一个匹配项 
列表序列.remove(数据)- clear():清空列表 
修改
- 修改指定下标数据 
- 逆置:reverse() 
- sort() 
列表序列.sort( key=None, reverse=False)reverse表示排序规则,**reverse = True** 降序, reverse = False 升序(默认)
复制
- copy() 
列表的循环遍历
- while 
name_list = ['Tom', 'Lily', 'Rose']
i = 0
while i < len(name_list):
    print(name_list[i])
    i += 1- for 
name_list = ['Tom', 'Lily', 'Rose']
for i in name_list:
    print(i)列表嵌套
所谓列表嵌套指的就是一个列表里面包含了其他的子列表
# 第一步:按下标查找到李四所在的列表
print(name_list[2])
# 第二步:从李四所在的列表里面,再按下标找到数据李四
print(name_list[2][1])元组
一个元组可以存储多个数据,元组内的数据是不能修改的
定义元组
- 元组特点:定义元组使用小括号,且逗号隔开各个数据,数据可以是不同的数据类型 
- 如果定义的元组只有一个数据,那么这个数据后面也好添加逗号,否则数据类型为唯一的这个数据的数据类型 
# 多个数据元组
t1 = (10, 20, 30)
# 单个数据元组
t2 = (10,)元组的常见操作
- 按下标查找数据 
tuple1 = ('aa', 'bb', 'cc', 'bb')
print(tuple1[0])  # aa- index():查找某个数据,如果数据存在返回对应的下标,否则报错,语法和列表、字符串的index方法相同 
- count():统计某个数据在当前元组出现的次数 
- len():统计元组中数据的个数 
但是如果元组里面有列表,修改列表里面的数据则是支持的
字典
- 字典里面的数据是以键值对形式出现,字典数据和数据顺序没有关系,即字典不支持下标 
创建字典
# 有数据字典
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
# 空字典
dict2 = {}
dict3 = dict()字典常见操作
增
- 字典序列[key] = 值 
删
- del() / del:删除字典或删除字典中指定键值对 
- clear():清空字典 
改
- 字典序列[key] = 值 
如果key存在则修改这个key对应的值 ;如果key不存在则新增此键值对
查
key值查找
- 如果当前查找的key存在,则返回对应的值;否则则报错 
get()
字典序列.get(key, 默认值)如果当前查找的key不存在则返回第二个参数(默认值),如果省略第二个参数,则返回None
keys()
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
print(dict1.keys())  # dict_keys(['name', 'age', 'gender'])values()
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
print(dict1.values())  # dict_values(['Tom', 20, '男'])items()
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
print(dict1.items())  # dict_items([('name', 'Tom'), ('age', 20), ('gender', '男')])字典的循环遍历
遍历字典的key
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
for key in dict1.keys():
    print(key)遍历字典的value
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
for value in dict1.values():
    print(value)遍历字典的元素
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
for item in dict1.items():
    print(item)遍历字典的键值对
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
for key, value in dict1.items():
    print(f'{key} = {value}')集合
创建集合
- 创建集合使用 - {}或set(), 但是如果要创建空集合只能使用- set(),因为- {}用来创建空字典
- 集合可以去掉重复数据 
- 集合数据是无序的,故不支持下标 
s1 = {10, 20, 30, 40, 50}
print(s1)
s2 = {10, 30, 20, 10, 30, 40, 30, 50}
print(s2)
s3 = set('abcdefg')
print(s3)
s4 = set()
print(type(s4))  # set
s5 = {}
print(type(s5))  # dict集合常见操作方法
增加数据
- add() 
- update(), 追加的数据是序列 
s1 = {10, 20}
# s1.update(100)  # 报错
s1.update([100, 200])
s1.update('abc')
print(s1)删除数据
- remove(),删除集合中的指定数据,如果数据不存在则报错 
- discard(),删除集合中的指定数据,如果数据不存在也不会报错 
- pop(),随机删除集合中的某个数据,并返回这个数据 
查找数据
- in:判断数据在集合序列 
- not in:判断数据不在集合序列 
公共操作
运算符
| 运算符 | 描述 | 支持的容器类型 | 
|---|---|---|
| + | 合并 | 字符串、列表、元组 | 
| * | 复制 | 字符串、列表、元组 | 
| in | 元素是否存在 | 字符串、列表、元组、字典 | 
| not in | 元素是否不存在 | 字符串、列表、元组、字典 | 
# 1. 字符串
print('-' * 10)  # ----------
# 2. 列表
list1 = ['hello']
print(list1 * 4)  # ['hello', 'hello', 'hello', 'hello']
# 3. 元组
t1 = ('world',)
print(t1 * 4)  # ('world', 'world', 'world', 'world')公共方法
| 函数 | 描述 | 
|---|---|
| len() | 计算容器中元素个数 | 
| del 或 del() | 删除 | 
| max() | 返回容器中元素最大值 | 
| min() | 返回容器中元素最小值 | 
| range(start, end, step) | 生成从start到end的数字,步长为 step,供for循环使用 | 
| enumerate() | 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。 | 
enumerate(可遍历对象, start=0)
list1 = ['a', 'b', 'c', 'd', 'e']
for i in enumerate(list1):
    print(i)
for index, char in enumerate(list1, start=1):
    print(f'下标是{index}, 对应的字符是{char}')容器类型转换
- tuple():将某个序列转换成元组 
- list():将某个序列转换成列表 
- set():将某个序列转换成集合 
集合可以快速完成列表去重
推导式
列表推导式
- 用一个表达式创建一个有规律的列表或控制一个有规律列表 
list1 = [i for i in range(10)]
print(list1)
list1 = [i for i in range(0, 10, 2)]
print(list1)
list1 = [i for i in range(10) if i % 2 == 0]
print(list1)
list1 = [(i, j) for i in range(1, 3) for j in range(3)]
print(list1)
#结果:[(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]字典推导式
dict1 = {i: i**2 for i in range(1, 5)}
print(dict1)  # {1: 1, 2: 4, 3: 9, 4: 16}
#将两个列表合并为一个字典
list1 = ['name', 'age', 'gender']
list2 = ['Tom', 20, 'man']
dict1 = {list1[i]: list2[i] for i in range(len(list1))}
print(dict1)
#提取字典中目标数据
counts = {'MBP': 268, 'HP': 125, 'DELL': 201, 'Lenovo': 199, 'acer': 99}
# 需求:提取上述电脑数量大于等于200的字典数据
count1 = {key: value for key, value in counts.items() if value >= 200}
print(count1)  # {'MBP': 268, 'DELL': 201}集合推导式
#创建一个集合,数据为下方列表的2次方
list1 = [1, 1, 2]
set1 = {i ** 2 for i in list1}
print(set1)  # {1, 4}函数
函数的作用
函数就是将一段具有独立功能的代码块整合到一个整体并命名,在需要的位置调用这个名称即可完成对应的需求
def 函数名(参数):
    代码1
    代码2
#调用
函数名(参数)变量的作用域
- 变量作用域指的是变量生效的范围,主要分为两类:局部变量和全局变量 
#函数体内部修改全局变量
a = 100
def testA():
    print(a)
def testB():
    # global 关键字声明a是全局变量
    global a
    a = 200
    print(a)
testA()  # 100
testB()  # 200
print(f'全局变量a = {a}')  # 全局变量a = 200函数的参数
位置参数
- 调用函数时根据函数定义的参数位置来传递参数 
关键字参数
- 函数调用,通过“键=值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求 
函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序
缺省参数
- 缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用) 
不定长参数
- 不定长参数也叫可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递 
#包裹位置参数
def user_info(*args):
    print(args)
# ('TOM',)
user_info('TOM')
# ('TOM', 18)
user_info('TOM', 18)
#包裹关键字参数
def user_info(**kwargs):
    print(kwargs)
# {'name': 'TOM', 'age': 18, 'id': 110}
user_info(name='TOM', age=18, id=110)传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包裹位置传递
无论是包裹位置传递还是包裹关键字传递,都是一个组包的过程
函数的说明文档
函数嵌套调用
拆包
#拆包:元组
def return_num():
    return 100, 200
num1, num2 = return_num()
print(num1)  # 100
print(num2)  # 200
#拆包:字典
dict1 = {'name': 'TOM', 'age': 18}
a, b = dict1
# 对字典进行拆包,取出来的是字典的key
print(a)  # name
print(b)  # age
print(dict1[a])  # TOM
print(dict1[b])  # 18引用
- 靠引用来传递值 
- 我们可以 - id()来判断两个变量是否为同一个值的引用。 我们可以将id值理解为那块内存的地址标识
# 1. int类型
a = 1
b = a
print(b)  # 1
print(id(a))  # 140708464157520
print(id(b))  # 140708464157520
a = 2
print(b)  # 1,说明int类型为不可变类型 
print(id(a))  # 140708464157552,此时得到是的数据2的内存地址
print(id(b))  # 140708464157520
# 2. 列表
aa = [10, 20]
bb = aa
print(id(aa))  # 2325297783432
print(id(bb))  # 2325297783432
aa.append(30)
print(bb)  # [10, 20, 30], 列表为可变类型
print(id(aa))  # 2325297783432
print(id(bb))  # 2325297783432引用当作实参
def test1(a):
    print(a)
    print(id(a))
    a += a
    print(a)
    print(id(a))
# int:计算前后id值不同
b = 100
test1(b)
# 列表:计算前后id值相同
c = [11, 22]
test1(c)可变和不可变类型
- 所谓可变类型与不可变类型是指:数据能够直接进行修改,如果能直接修改那么就是可变,否则是不可变. - 可变类型- 列表
- 字典
- 集合
 
- 不可变类型- 整型
- 浮点型
- 字符串
- 元组
 
 
- 可变类型
函数加强
递归
- 递归是一种编程思想,特点: - 函数内部自己调用自己 
- 必须有出口 
 
# 3 + 2 + 1
def sum_numbers(num):
    # 1.如果是1,直接返回1 -- 出口
    if num == 1:
        return 1
    # 2.如果不是1,重复执行累加并返回结果
    return num + sum_numbers(num-1)
sum_result = sum_numbers(3)
# 输出结果为6
print(sum_result)
lambda表达式
- 如果一个函数有一个返回值,并且只有一句代码,可以使用 lambda简化 
lambda语法
lambda 参数列表 : 表达式- lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适用 
- lambda表达式能接收任何数量的参数但只能返回一个表达式的值 
lambda的参数形式
无参数
fn1 = lambda: 100
print(fn1())一个参数
fn1 = lambda a: a
print(fn1('hello world'))默认参数
fn1 = lambda a, b, c=100: a + b + c
print(fn1(10, 20))可变参数:*args
fn1 = lambda *args: args
print(fn1(10, 20, 30))可变参数:**kwargs
fn1 = lambda **kwargs: kwargs
print(fn1(name='python', age=20))lambda的应用
带判断的lambda
fn1 = lambda a, b: a if a > b else b
print(fn1(1000, 500))列表数据按字典key的值排序
students = [
    {'name': 'TOM', 'age': 20},
    {'name': 'ROSE', 'age': 19},
    {'name': 'Jack', 'age': 22}
]
# 按name值升序排列
students.sort(key=lambda x: x['name'])
print(students)
# 按name值降序排列
students.sort(key=lambda x: x['name'], reverse=True)
print(students)
# 按age值升序排列
students.sort(key=lambda x: x['age'])
print(students)高阶函数
- 把函数作为参数传入,这样的函数称为高阶函数,高阶函数是函数式编程的体现。函数式编程就是指这种高度抽象的编程范式。 
- abs() 
def sum_num(a, b, f):
    return f(a) + f(b)
result = sum_num(-1, 2, abs)
print(result)  # 3- round():四舍五入 
- map(func, lst):将传入的函数变量func作用到lst变量的每个元素中,并将结果组成新的列表(Python2)/迭代器(Python3)返回。 
list1 = [1, 2, 3, 4, 5]
def func(x):
    return x ** 2
result = map(func, list1)
print(result)  # <map object at 0x0000013769653198>
print(list(result))  # [1, 4, 9, 16, 25]- reduce(func,lst):其中func必须有两个参数。每次func计算的结果继续和序列的下一个元素做累积计算。 
import functools
list1 = [1, 2, 3, 4, 5]
def func(a, b):
    return a + b
result = functools.reduce(func, list1)
print(result)  # 15- filter(func, lst)函数:过滤序列, 过滤掉不符合条件的元素, 返回一个 filter 对象,如果要转换为列表, 可以使用 list() 来转换。 
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def func(x):
    return x % 2 == 0
result = filter(func, list1)
print(result)  # <filter object at 0x0000017AF9DC3198>
print(list(result))  # [2, 4, 6, 8, 10]文件操作
基本操作
打开文件
open(name, mode)name:要打开的目标文件名的字符串(可以包含文件所在的具体路径)
mode:设置打开文件的模式(访问模式):只读、写入、追加等
| 模式 | 描述 | 
|---|---|
| r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 | 
| rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。 | 
| r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 | 
| rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。 | 
| w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 | 
| wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 | 
| w+ | 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 | 
| wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 | 
| a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 | 
| ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 | 
| a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 | 
| ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 | 
文件对象方法
写
文件对象.write('内容')读
read()
文件对象.read(num)- num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据 
readlines()
- readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素。 
f = open('test.txt')
content = f.readlines()
# ['hello world\n', 'abcdefg\n', 'aaa\n', 'bbb\n', 'ccc']
print(content)
# 关闭文件
f.close()sreadline():一次读取一行内容
f = open('test.txt')
content = f.readline()
print(f'第一行:{content}')
content = f.readline()
print(f'第二行:{content}')
# 关闭文件
f.close()seek():移动文件指针
文件对象.seek(偏移量, 起始位置)起始位置:
- 0:文件开头
- 1:当前位置
- 2:文件结尾
关闭
文件对象.close()文件备份
- 用户输入当前目录下任意文件名,程序完成对该文件的备份功能(备份文件名为xx[备份]后缀,例如:test[备份].txt)。 
- 步骤 
- 接收用户输入的文件名 
- 规划备份文件名 
- 备份文件写入数据 
# 1 接收用户输入目标文件名
old_name = input('请输入您要备份的文件名:')
# 2.1 提取文件后缀点的下标
index = old_name.rfind('.')
# print(index)  # 后缀中.的下标
# print(old_name[:index])  # 源文件名(无后缀)
# 2.2 组织新文件名 旧文件名 + [备份] + 后缀
new_name = old_name[:index] + '[备份]' + old_name[index:]
# 打印新文件名(带后缀)
# print(new_name)
# 3.1 打开文件
old_f = open(old_name, 'rb')
new_f = open(new_name, 'wb')
while True:
    con = old_f.read(1024)
    if len(con) == 0:
        break
    new_f.write(con)
   
# 3.3 关闭文件
old_f.close()
new_f.close()  文件和文件夹的操作
在Python中文件和文件夹的操作要借助os模块里面的相关功能,具体步骤如下:
- 导入os模块 
- 使用os模块相关功能 
import os
os.函数名()文件重命名
os.rename(目标文件名, 新文件名)删除文件
os.remove(目标文件名)创建文件夹
os.mkdir(文件夹名字)删除文件夹
os.rmdir(文件夹名字)获取当前目录
os.getcwd()改变默认目录
os.chdir(目录)获取目录列表
os.listdir(目录)面向对象
类和对象
- 类和对象的关系:用类创建一个对象 
类
类是对一系列具有相同特征和行为的事物的统称,是一个抽象的概念,不是真实存在的事物。
- 特征即是属性 
- 行为即是方法 
对象
对象是类创建出来的真实存在的事物
面向对象实现方法
定义类
class 类名():
    代码
    ......- 注意:类名要满足标识符命名规则,同时遵循大驼峰命名习惯。 
创建对象
对象名 = 类名()- 创建对象的过程也叫实例化对象 
self
- self指的是调用该函数的对象 
# 1. 定义类
class Washer():
    def wash(self):
        print('我会洗衣服')
        # <__main__.Washer object at 0x0000024BA2B34240>
        print(self)
# 2. 创建对象
haier1 = Washer()
# <__main__.Washer object at 0x0000018B7B224240>
print(haier1)
# haier1对象调用实例方法
haier1.wash()
haier2 = Washer()
# <__main__.Washer object at 0x0000022005857EF0>
print(haier2)- 打印对象和self得到的结果是一致的,都是当前对象的内存中存储地址 
添加和获取对象属性
类外面添加对象属性
对象名.属性名 = 值对象名.属性名类里面获取对象属性
self.属性名# 定义类
class Washer():
    def print_info(self):
        # 类里面获取实例属性
        print(f'haier1洗衣机的宽度是{self.width}')
        print(f'haier1洗衣机的高度是{self.height}')
# 创建对象
haier1 = Washer()
# 添加实例属性
haier1.width = 500
haier1.height = 800
haier1.print_info()魔法方法
- 在Python中 - __xx__()的函数叫做魔法方法,指的是具有特殊功能的函数。
__init__()
- 初始化对象 
class Washer():
    def __init__(self, width, height):
        self.width = width
        self.height = height
    def print_info(self):
        print(f'洗衣机的宽度是{self.width}')
        print(f'洗衣机的高度是{self.height}')
haier1 = Washer(10, 20)
haier1.print_info()
haier2 = Washer(30, 40)
haier2.print_info()__str__()
- 当使用print输出对象的时候,默认打印对象的内存地址。如果类定义 - __str__方法,那么就会打印从在这个方法中 return 的数据
class Washer():
    def __init__(self, width, height):
        self.width = width
        self.height = height
    def __str__(self):
        return '这是海尔洗衣机的说明书'
haier1 = Washer(10, 20)
# 这是海尔洗衣机的说明书
print(haier1)__del__()
- 删除对象 
class Washer():
    def __init__(self, width, height):
        self.width = width
        self.height = height
    def __del__(self):
        print(f'{self}对象已经被删除')
haier1 = Washer(10, 20)
# <__main__.Washer object at 0x0000026118223278>对象已经被删除
del haier1继承
- Python面向对象的继承指的是多个类之间的所属关系,即子类默认继承父类的所有属性和方法 
# 父类A
class A(object):
    def __init__(self):
        self.num = 1
    def info_print(self):
        print(self.num)
# 子类B
class B(A):
    pass
result = B()
result.info_print()  # 1- 在Python中,所有类默认继承object类,object类是顶级类或基类;其他子类叫做派生类 
单继承
# 1. 师父类
class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')
        
# 2. 徒弟类
class Prentice(Master):
    pass
# 3. 创建对象daqiu
daqiu = Prentice()
# 4. 对象访问实例属性
print(daqiu.kongfu)
# 5. 对象调用实例方法
daqiu.make_cake()多继承
class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')
# 创建学校类
class School(object):
    def __init__(self):
        self.kongfu = '[黑马煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')
class Prentice(School, Master):
    pass
daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()- 当一个类有多个父类的时候,默认使用第一个父类的同名属性和方法 
子类重写父类同名方法和属性
class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')
class School(object):
    def __init__(self):
        self.kongfu = '[黑马煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')
# 独创配方
class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[独创煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')
daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()
print(Prentice.__mro__)- 子类和父类具有同名属性和方法,默认使用子类的同名属性和方法 
子类调用父类的同名方法和属性
class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')
class School(object):
    def __init__(self):
        self.kongfu = '[黑马煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')
class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[独创煎饼果子配方]'
    def make_cake(self):
        # 如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用属性前,先调用自己子类的初始化
        self.__init__()
        print(f'运用{self.kongfu}制作煎饼果子')
    # 调用父类方法,但是为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)
    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)
daqiu = Prentice()
daqiu.make_cake()
daqiu.make_master_cake()
daqiu.make_school_cake()
daqiu.make_cake()多层继承
class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')
class School(object):
    def __init__(self):
        self.kongfu = '[黑马煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')
class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[独创煎饼果子配方]'
    def make_cake(self):
        self.__init__()
        print(f'运用{self.kongfu}制作煎饼果子')
    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)
    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)
# 徒孙类
class Tusun(Prentice):
    pass
xiaoqiu = Tusun()
xiaoqiu.make_cake()
xiaoqiu.make_school_cake()
xiaoqiu.make_master_cake()super()调用父类方法
class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')
class School(Master):
    def __init__(self):
        self.kongfu = '[黑马煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')
        # 方法2.1
        # super(School, self).__init__()
        # super(School, self).make_cake()
        # 方法2.2
        super().__init__()
        super().make_cake()
class Prentice(School):
    def __init__(self):
        self.kongfu = '[独创煎饼果子技术]'
    def make_cake(self):
        self.__init__()
        print(f'运用{self.kongfu}制作煎饼果子')
    # 子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装
    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)
    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)
    # 一次性调用父类的同名属性和方法
    def make_old_cake(self):
        # 方法一:代码冗余;父类类名如果变化,这里代码需要频繁修改
        # Master.__init__(self)
        # Master.make_cake(self)
        # School.__init__(self)
        # School.make_cake(self)
        # 方法二: super()
        # 方法2.1 super(当前类名, self).函数()
        # super(Prentice, self).__init__()
        # super(Prentice, self).make_cake()
        # 方法2.2 super().函数()
        super().__init__()
        super().make_cake()
daqiu = Prentice()
daqiu.make_old_cake()- 使用super() 可以自动查找父类。调用顺序遵循 - __mro__类属性的顺序。比较适合单继承使用
私有权限
定义私有属性和方法
- Python中,可以为实例属性和方法设置私有权限,即设置某个实例属性或实例方法不继承给子类 
- 设置私有权限的方法:在属性名和方法名 前面 加上两个下划线 __ 
  class 类名():
    # 私有属性
    __属性名 = 值
  
    # 私有方法
    def __函数名(self):
      代码获取和修改私有属性值
- 一般定义函数 - get_xx用来获取私有属性,定义- set_xx用来修改私有属性值。
class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')
class School(object):
    def __init__(self):
        self.kongfu = '[黑马煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')
class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[独创煎饼果子配方]'
        self.__money = 2000000
    # 获取私有属性
    def get_money(self):
        return self.__money
    # 修改私有属性
    def set_money(self):
        self.__money = 500
    def __info_print(self):
        print(self.kongfu)
        print(self.__money)
    def make_cake(self):
        self.__init__()
        print(f'运用{self.kongfu}制作煎饼果子')
    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)
    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)
# 徒孙类
class Tusun(Prentice):
    pass
daqiu = Prentice()
xiaoqiu = Tusun()
# 调用get_money函数获取私有属性money的值
print(xiaoqiu.get_money())
# 调用set_money函数修改私有属性money的值
xiaoqiu.set_money()
print(xiaoqiu.get_money())面向对象三大特性
- 封装- 将属性和方法书写到类的里面的操作即为封装
- 封装可以为属性和方法添加私有权限
 
- 继承- 子类默认继承父类的所有属性和方法
- 子类可以重写父类属性和方法
 
- 多态- 传入不同的对象,产生不同的结果
 
多态
多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)。
- 定义:多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果
- 好处:调用灵活,有了多态,更容易编写出通用的代码,做出通用的编程,以适应需求的不断变化!
- 实现步骤:- 定义父类,并提供公共方法
- 定义子类,并重写父类方法
- 传递子类对象给调用者,可以看到不同子类执行效果不同
 
class Dog(object):
    def work(self):  # 父类提供统一的方法,哪怕是空方法
        print('指哪打哪...')
class ArmyDog(Dog):  # 继承Dog类
    def work(self):  # 子类重写父类同名方法
        print('追击敌人...')
class DrugDog(Dog):
    def work(self):
        print('追查毒品...')
class Person(object):
    def work_with_dog(self, dog):  # 传入不同的对象,执行不同的代码,即不同的work函数
        dog.work()
ad = ArmyDog()
dd = DrugDog()
daqiu = Person()
daqiu.work_with_dog(ad)
daqiu.work_with_dog(dd)类属性和实例属性
类属性
设置和访问类属性
- 类属性就是 类对象 所拥有的属性,它被 该类的所有实例对象 所共有。 
- 类属性可以使用 类对象 或 实例对象 访问。 - 类属性的优点 - 记录的某项数据 始终保持一致时,则定义类属性。
- 实例属性 要求 每个对象 为其 单独开辟一份内存空间 来记录数据,而 类属性 为全类所共有 ,仅占用一份内存,更加节省内存空间。
 
修改类属性
- 类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了一个实例属性。 
class Dog(object):
    tooth = 10
wangcai = Dog()
xiaohei = Dog()
# 修改类属性
Dog.tooth = 12
print(Dog.tooth)  # 12
print(wangcai.tooth)  # 12
print(xiaohei.tooth)  # 12
# 不能通过对象修改属性,如果这样操作,实则是创建了一个实例属性
wangcai.tooth = 20
print(Dog.tooth)  # 12
print(wangcai.tooth)  # 20
print(xiaohei.tooth)  # 12实例属性
class Dog(object):
    def __init__(self):
        self.age = 5
    def info_print(self):
        print(self.age)
wangcai = Dog()
print(wangcai.age)  # 5
# print(Dog.age)  # 报错:实例属性不能通过类访问
wangcai.info_print()  # 5类方法和静态方法
类方法
特点
- 第⼀个形参是类对象的方法 
- 需要用装饰 - @classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般- cls作为第一个参数。
类方法使用场景
- 当方法中 需要使用类对象 (如访问私有类属性等)时,定义类方法 
- 类方法一般和类属性配合使用 
class Dog(object):
    __tooth = 10
    @classmethod
    def get_tooth(cls):
        return cls.__tooth
wangcai = Dog()
result = wangcai.get_tooth()
print(result)  # 10静态方法
特点
- 需要通过装饰 - @staticmethod来进行修饰,静态方法既不需要传递类对象也不需要传递实例对象(形参没有self/cls)
- 静态方法 也能够通过 实例对象 和 类对象 去访问。 
静态方法使用场景
- 当方法中 既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象 (如类属性、类方法、创建实例等)时,定义静态方法
- 取消不需要的参数传递,有利于 减少不必要的内存占用和性能消耗
class Dog(object):
    @staticmethod
    def info_print():
        print('这是一个狗类,用于创建狗实例....')
wangcai = Dog()
# 静态方法既可以使用对象访问又可以使用类访问
wangcai.info_print()
Dog.info_print()异常
捕获异常
捕获指定异常
try:
    可能发生错误的代码
except 异常类型:
    如果捕获到该异常类型执行的代码捕获多个指定异常
- 捕获多个异常时,可以把要捕获的异常类型的名字,放到except 后,并使用元组的方式进行书写 
try:
    print(1/0)
except (NameError, ZeroDivisionError):
    print('有错误')捕获异常描述信息
try:
    print(num)
except (NameError, ZeroDivisionError) as result:
    print(result)异常的else
try:
    print(1)
except Exception as result:
    print(result)
else:
    print('我是else,是没有异常的时候执行的代码')异常的finally
try:
    f = open('test.txt', 'r')
except Exception as result:
    f = open('test.txt', 'w')
else:
    print('没有异常,真开心')
finally:
    f.close()异常的传递
import time
try:
    f = open('test.txt')
    try:
        while True:
            content = f.readline()
            if len(content) == 0:
                break
            time.sleep(2)
            print(content)
    except:
        # 如果在读取文件的过程中,产生了异常,那么就会捕获到
        # 比如 按下了 ctrl+c
        print('意外终止了读取数据')
    finally:
        f.close()
        print('关闭文件')
except:
    print("没有这个文件")自定义异常
- 在Python中,抛出自定义异常的语法 - raise 异常类对象。
class 异常类类名(Exception):
  	代码
    
    # 设置抛出异常的描述信息
    def __str__(self):
      return ...
# 2. 抛出异常
raise 异常类名()
# 捕获异常
except Exception...# 自定义异常类,继承Exception
class ShortInputError(Exception):
    def __init__(self, length, min_len):
        self.length = length
        self.min_len = min_len
    # 设置抛出异常的描述信息
    def __str__(self):
        return f'你输入的长度是{self.length}, 不能少于{self.min_len}个字符'
def main():
    try:
        con = input('请输入密码:')
        if len(con) < 3:
            raise ShortInputError(len(con), 3)
    except Exception as result:
        print(result)
    else:
        print('密码已经输入完成')
main()模块和包
模块
- Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句 
- 模块能定义函数,类和变量,模块里也能包含可执行的代码。 
导入模块
- import 模块名
- from 模块名 import 功能名
- from 模块名 import *
- import 模块名 as 别名
- from 模块名 import 功能名 as 别名
制作模块
- 在Python中,每个Python文件都可以作为一个模块,模块的名字就是文件的名字。也就是说自定义模块名必须要符合标识符命名规则 
def testA(a, b):
    print(a + b)
# 只在当前文件中调用该函数,其他导入的文件内不符合该条件,则不执行testA函数调用
if __name__ == '__main__':
    testA(1, 1)模块定义顺序
当导入一个模块,Python解析器对模块位置的搜索顺序是:
- 当前目录
- 如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录。
- 如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/
模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。
- 注意- 自己的文件名不要和已有模块名重复,否则导致模块功能无法使用
- 使用from 模块名 import 功能的时候,如果功能名字重复,调用到的是最后定义或导入的功能。
 
“__all__"
- 如果一个模块文件中 - __all__变量,当使- from xxx import *导入时,只能导入这个列表中的元素。
- my_module1模块代码 
__all__ = ['testA']
def testA():
    print('testA')
def testB():
    print('testB')- 导入模块的文件代码 
from my_module1 import *
testA()
testB()包
- 包将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字 - __init__.py文件,那么这个文件夹就称之为包
制作包
- [New] — [Python Package] — 输入包名 — [OK] — 新建功能模块(有联系的模块)。 - 注意:新建包后,包内部会自动创 - __init__.py文件,这个文件控制着包的导入行为。
import 包名.模块名
from 包名 import *- __all__ = [] :允许导入的模块或功能列表
 
        
        
        
       
         
          
          
          
           
          
          
          
          