python基础语法.py

"""
数据类型
"""
#
# # int
# num1 = 1
# # float
# num2 =1.1
# print(type(num1))
# print(type(num2))
#
# # str ,字符串,特点:数据都带引号,单引、双引均可
# a = 'hello world'
# print(type(a))
# b=True # boolean
# print(type(b))
#
# # list 列表
# c = [10,20,30]
# print(type(c))
#
# # tuple 元组
# d = (10,20,30)
# print(type(d))
#
# # set 集合
# e = {10,20,30}
# print(type(e))
#
# # dict 字典 键值对
# f = {'name':'Tom','age': 16}
# print((type(f)))


# """
# 1.准备数据
# 2.格式化符号输出数据
# """
# age =18
# name = 'TOM'
# weight = 75.5
# stu_id = 1
#
# print('今年我的年龄是%d岁')
# # 1.今年我的年龄是x岁
# print('今年我的年龄是%d岁' % age)
# # 2.我的名字是x
# print('名字是%s' % name)
# # 3.我的体重是x公斤
# # 75.500000
# print('体重是%f公斤' % weight)
# # 75.50
# print('体重是%.2f公斤' % weight)
# # 4.我的学号是x
# print('我的学号是%d' % stu_id)
# # 4.1 我的学号是001
# # %06d,表示输出的整数显示位数,不⾜以0补全,超出当前位数则原样输出
# print('我的学号是%03d' % stu_id)
# stu_id2 = 1000
# print('我的学号是%03d' % stu_id2)
# # 5.我的名字是x,今年x岁了
# print('名字是%s,今年%d岁了' % (name,age))
# print('名字是%s,今年%d岁了' % (name,age + 1))
# # 6.我的名字是x,今年x岁了,体重是x公斤,学号是x
# print('名字是%s,今年%d岁了,体重是%f公斤,学号是%d' % (name, age,weight, stu_id))
# print('名字是%s,今年%d岁了,体重是%.2f公斤,学号是%06d' % (name, age,weight, stu_id))
#
# '''
# 格式化字符串除了%s,还可以写为 f'{表达式}'
# '''
# # 7.我的名字是x,今年x岁了,体重是x公斤
# print('我的名字是%s,今年%s岁了,体重是%s公斤' %(name,age,weight))
#
# print(f'我的名字是{name},今年{age}岁了,体重是{weight}公斤')
# print(f'我的名字是{name},今年{age+1}岁了,体重是{weight}公斤')
#
# # %s 与f'{}'区别; f代码量少;f更高效;开发多用f; f-格式化是python3.6新增的格式化方法
#


'''
转义字符
\n :换⾏。
\t :制表符,⼀个tab键(4个空格)的距离。
\ 反斜杠
'''
# # 两行
# print('hello')
# print('world')
#
# print('hello\npython')
# # 缩进4空格
# print('\tabcd')

'''
print函数的结束符
想⼀想,为什么两个print会换⾏输出?
在Python中,print(), 默认⾃带 end="\n" 这个换⾏结束符,所以导致每两个 print 直接会换⾏
展示,⽤户可以按需求更改结束符。
'''
# print('hello')
# print('hello')
# print('输出内容', end="\n")
# print('输出内容', end=" ")
# print('hello', end="....\t")
# print('world', end=" ")

'''
1.书写input
    input('提示信息')
2.观察特点
    输⼊的特点
    当程序执⾏到 input ,等待⽤户输⼊,输⼊完成之后才继续向下执⾏。
    在Python中, input 接收⽤户输⼊后,⼀般存储到变量,⽅便使⽤。
    在Python中, input 会把接收到的任意⽤户输⼊的数据都当做字符串处理。
'''
# password  = input('请输入您的密码:')
# print(f'您输入的密码是{password}')
# print(type(password))


'''
转换数据类型
int(x [,base ]) 将x转换为⼀个整数
float(x ) 将x转换为⼀个浮点数
complex(real [,imag ]) 创建⼀个复数,real为实部,imag为虚部
str(x ) 将对象 x 转换为字符串
repr(x ) 将对象 x 转换为表达式字符串
eval(str ) ⽤来计算在字符串中的有效Python表达式,并返回⼀个对象
tuple(s ) 将序列 s 转换为⼀个元组
list(s ) 将序列 s 转换为⼀个列表
'''
# num  = input('请输入数字:')
# print(num,type(num)) # str
# print(type(int(num)))  # <class 'int'>


# 1. float() -- 转换成浮点型
# num1 = 1
# print(float(num1)) # 1.0
# print(type(float(num1)))
# str1 = '10'
# print(float(str1)) #10.0
#
# # 2. str() -- 转换成字符串类型
# num2 = 10
# print(type(str(num2)))
#
# # 3. tuple() -- 将⼀个序列转换成元组
# list1 = [10, 20, 30]
# print(tuple(list1))  # (10, 20, 30)
#
# # 4. list() -- 将⼀个序列转换成列表
# t1 = (100, 200, 300)
# print(list(t1))
#
# # 5. eval() -- 将字符串中的数据转换成Python表达式原本类型
# str1 = '10'
# str0 = '1.1'
# str2 = '[1, 2, 3]'
# str3 = '(1000, 2000, 3000)'
# print(type(eval(str1)))
# print(type(eval(str0)))
# print(type(eval(str2)))
# print(type(eval(str3)))

'''
运算符

运算符的分类:
算数运算符
赋值运算符
复合赋值运算符
⽐较运算符
逻辑运算符

单击pycharm - python console ;打开
'''

'''
PyDev console: starting.
Python 3.7.4 (tags/v3.7.4:e09359112e, Jul  8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)] on win32
1 + 1
2
1 + 1.1
2.1
1 - 1
0
1 - 0.5
0.5
2 * 0.5
1.0
4 / 2
2.0
2.0
9 // 4
2
9 % 4 
1
2 ** 3
8
1 + 2 * 3 
7
(1+2) * 3
9
2 * 3 ** 2
18
(2 * 3) ** 2
36


# # // 整除 9 // 4 输出结果为2
# # % 取余 9 % 4 输出结果为 1
# # ** 指数 2 ** 4 输出结果为 16,即 2 * 2 * 2 * 2
# # () ⼩括号 ⼩括号⽤来提⾼运算优先级,即 (1 + 2) * 3 输出结果为 9
# 混合运算优先级顺序: () ⾼于 ** ⾼于 * / // % ⾼于 + -

tyhon console >>>
# 多个变量赋值
num1, num2, str1 = 1, 1.1, 'abc'
num1
1
# 多变量赋相同值
a = b = 100
a
100
b
100

'''

'''
复合赋值运算符
'''
# c = 10
# # c = 10 + 1 + 2       # 错误
# # c += 3 -- c = c + 3  # 正确 (先算复合赋值运算符右边的表达式,再算复合运算符)
# c += 1 + 2
# print(c)  # 13
#
# d = 10
# d *=  1 + 2
# print(d) # 30

'''
比较运算符
1 == 1
True
'''

'''
逻辑运算符
and  or  not
x and y
x or y
not x
'''
# a = 1
# b = 2
# c = 3
#
# print( (a < b) and ( b < c))
# print((a > b) or (c > b))
# print(not (b < c))

'''
条件语句
if 条件:
    条件成立执行的代码1
    .....
'''
# if True:
# if False:
#     print("条件成立执行的代码")
#     print("条件成立执行的代码")
#
# print('这个代码执行吗?')

# age = int(input('请输入您的年龄:'))
# if age >= 18 :
#     print(f"您已经成年{age}岁,可以上网")

# D:\Learn\HM-21人工智能Ai\21年【年度钻石会员】人工智能AI进阶\阶段1 人工智能Python基础\第三章 判断语句\3-3 if...elif...else格式

'''
if 条件:
    代码
else:
    代码
'''
# age = int(input('请输入您的年龄:'))
# if age > 18:
#     print('已经成年,可以上网')
# else:
#     print('未成年,不可上网')

'''
多重判断
if 条件1:
    代码1
elif 条件2:
    代码2
else:
    以上都不成立时,执行
'''
# age = int(input('请输入年龄:'))
#
# if age < 18:
#     print("为童工,不合法")
# elif age >= 18 and age < 60:
#     print("合法工作年龄")
# else:
#     print('退休了')

'''
if嵌套
'''
"""
1. 如果有钱,则可以上⻋
 2. 上⻋后,如果有空座,可以坐下
 上⻋后,如果没有空座,则站着等空座位
如果没钱,不能上⻋
"""
# money = int(input('查找包里是否有钱:'))
# if money > 1:
#     hasSit = False
#     if hasSit:
#         print('有空座,可坐下')
#     else:
#         print('无座,有钱也站着')
# else:
#     print('没钱,不能坐公交,走路吧!')

'''
猜拳游戏
1. 导出random模块
2. 使⽤random模块中的随机整数功能
语法如下:
1 import 模块名
1 random.randint(开始,结束)  ,包含开始和结束
'''

# import random
#
# player = int(input('0-石头,1-剪刀,2-布:'))
#
# computer = random.randint(0, 2)
# print(computer)
#
# if (player == 0 and computer == 1) or (player == 1 and computer == 2) or (player == 2 and computer == 1):
#     print('玩家胜利')
# elif (player == computer):
#     print('平局')
# else:
#     print('玩家输')

'''
三⽬运算符
条件成⽴执⾏的表达式 if 条件 else 条件不成⽴执⾏的表达式
'''
# a = 1
# b = 2
# c = a if a > b else b
# print(c)
#
# aa = 10
# bb = 6
# cc = (aa - bb) if (aa > bb) else (bb - aa)
# print(cc)

'''
while 条件:
 条件成⽴重复执⾏的代码1
 条件成⽴重复执⾏的代码2
'''
# 循环计数器,一般第一个计数值为从0开始;
# i = 0
# while i < 5:
#     print('媳妇儿,我错了')
#     i += 1

'''
0-100内偶数累加的和
'''

# 程序去计算偶数
# i = 2
# result = 0
# while i <= 100:
#     if (i % 2 == 0):
#         result += i
#     i += 1
# print(result)


# 人为经验判断:偶数+2为偶数
# i = 2
# result = 0
# while i <= 100:
#     result += i
#     i += 2
# print(result)

'''
break和continue是循环中满⾜⼀定条件退出循环的两种不同⽅式
'''

'''
4.1 理解
举例:⼀共吃5个苹果,吃完第⼀个,吃第⼆个…,这⾥"吃苹果"的动作是不是重复执⾏?
情况⼀:如果吃的过程中,吃完第三个吃饱了,则不需要再吃第4个和第五个苹果,即是吃苹果的动作
停⽌,这⾥就是break控制循环流程,即终⽌此循环。
情况⼆:如果吃的过程中,吃到第三个吃出⼀个⼤⾍⼦...,是不是这个苹果就不吃了,开始吃第四个苹
果,这⾥就是continue控制循环流程,即退出当前⼀次循环继⽽执⾏下⼀次循环代码。
'''

# i = 1
# while i <= 5:
#     print(f'吃完第{i}个了')
#     if i == 3:
#         print(f'吃饱了')
#         break
#     i += 1
#
# i = 1
# while i <= 5:
#     if i == 3:
#         print(f'吃到第{i}个,吃出一个大虫子,这个不吃了')
#         i += 1
#     print(f'吃完第{i}个了')
#     i += 1

'''
while循环嵌套
'''
'''
打印*形正方形
'''

# i = 0
# while i < 5:
#     print('', end='\n')
#     j = 0
#     while j < 5:
#         print('*', end='')
#         j += 1
#     i += 1

'''
打印星号(三⻆形)
'''
# i = 0
# while i < 5:
#     print('', end='\n')
#     j = 0
#     while i >= j:
#         print('*', end='')
#         j += 1
#     i += 1

'''
九九乘法表
'''

# i = 1
# while i <= 9:
#     print('', end='\n')
#     j = 1
#     while i >= j:
#         print(f'{i} x {j} = { i * j }', end='\t')
#         j += 1
#     i += 1

'''
for循环
'''
'''
for 临时变量 in 序列:
 重复执⾏的代码1
 重复执⾏的代码2
'''

# str1 = 'itheima'
# for i in str1:
#     print(i)

'''
循环可以和else配合使⽤,else下⽅缩进的代码指的是【当循环正常结束之后要执⾏的代码。】 break退出,则不执行else,continue,会执行else
while、for都可与else配合使用
'''
'''
需求:⼥朋友⽣⽓,要求道歉5遍:媳妇⼉,我错了。道歉到第三遍的时候,媳妇埋怨这⼀遍说的不真
诚,是不是就是要退出循环了?这个退出有两种可能性:
更⽣⽓,不打算原谅,也不需要道歉了,程序如何书写?
只⼀遍不真诚,可以忍受,继续下⼀遍道歉,程序如何书写?
'''

# i = 1
# while i <= 5:
#     if i == 3:
#         print('这一遍不真诚;不打算原谅了;不需要道歉了')
#         break
#     print(f'媳妇儿,我道歉第{i}遍了')
#     i += 1
# else:
#     print('媳妇原谅我了')
#
# i = 1
# while i <= 5:
#     if i == 3:
#         print('这一遍不真诚;继续下一次道歉')
#         i += 1
#         continue
#     print(f'媳妇儿,我道歉第{i}遍了')
#     i += 1
# else:
#     print('媳妇原谅我了')


'''
字符串
'''
# 单引号 代码显示效果换行了,内容以脚本的思想,没有换行
# a = 'hello ' \
#     'world'
# print(a)
# print(type(a))
# b = "TOM"
# print(type(b))
#
# # 三引号  支持内容回车换行原样输出展示
# e = '''i am TOM'''
# print(type(e))
# f = """I AM
# TOM"""
# print(type(f))
# print(f)
#
# # I'm TOM
# c = "I'm TOM"
# print(c)
# print(type(c))
#
# # d = 'I'm TOM'
# d = 'I\'m TOM'
# print(d)

'''
下标
'''
# str1 = 'abcdefg'
# print(str1)
# print(str1[2]) # c
# print(str1[5]) # f

'''
切⽚ 
序列[开始位置下标:结束位置下标:步⻓]  
[ ) 左闭右开 
'''
str1 = '012345678'
# 得到整个字符串
# print(str1)

# print(str1[2:5:1]) # 234
# print(str1[2:5:2]) # 24
# print(str1[2:5]) # 234
# print(str1[:5]) # 01234 不写开始,默认从0开始
# print(str1[2:]) # 2345678 不写结束,表示选取到末尾
# print(str1[:]) #  不写开始结束,表示选取从头到尾
# print(str1[::-1]) # 876543210 # 如果步长为负数,表示倒叙选取
# print(str1[-4:-1]) # 567
# 终极测试
# print(str1[-4:-1:1]) # 567
# print(str1[-4:-1:-1]) # 不能选取出数据 从-4开始到-1结束,选取方向从左到右;但是-1是从右向左选取;方向不一致
# # **** 如果选取方向(下标开始到结束)和步长的方向冲突,则无法选取数据
# print(str1[-1:-4:-1]) # 876

# D:\Learn\HM-21人工智能Ai\21年【年度钻石会员】人工智能AI进阶\阶段1 人工智能Python基础\第五章 字符串\5-4 字符串操作方法

'''
四、常⽤操作⽅法
'''
'''
find():检测某个⼦串是否包含在这个字符串中,如果在返回这个⼦串开始的位置下标,否则则返回-1。
字符串序列.find(⼦串, 开始位置下标, 结束位置下标)
注意:开始和结束位置下标可以省略,表示在整个字符串序列中查找。

index():检测某个⼦串是否包含在这个字符串中,如果在返回这个⼦串开始的位置下标,否则则报异常。
'''

# mystr = "hello world and itcast and itheima and Python"
# 1. find()
# print(mystr.find('and'))  # 12
# print(mystr.find('and', 15, 30))  # 23
# print(mystr.find('ands'))   # 不存在,返回 -1
# 2. index()
# print(mystr.index('and'))
# print(mystr.index('ands')) # 不存在,报错: ValueError: substring not found
# 3. count()
# print(mystr.count('and', 15, 30)) # 1
# print(mystr.count('and')) # 3
'''
rfind(): 和find()功能相同,但查找⽅向为右侧开始。
rindex():和index()功能相同,但查找⽅向为右侧开始。
'''
# print(mystr.rfind('and')) # 35
# print(mystr.rfind('ands')) # -1
# print(mystr.rindex('and')) # 35
# print(mystr.rindex('ands')) #  ValueError: substring not found

'''
修改
'''

'''
replace():替换; 有返回值,返回值是修改后的字符串;原字符串变量没有改变
字符串序列.replace(旧⼦串, 新⼦串, 替换次数)
注意:替换次数如果查出⼦串出现次数,则替换次数为该⼦串出现次数。
'''
# mystr = "hello world and itcast and itheima and Python"
# 数据是否可以改变划分为可变类型和不可变类型
# new_str = mystr.replace('and', 'he')
# print(new_str)
# print(mystr.replace('and', 'he', 2))
# print(mystr.replace('and', 'he', 10))

'''
split():按照指定字符分割字符串。 分割,返回一个列表,丢失分割字符
字符串序列.split(分割字符, num)
num表示的是分割字符出现的次数,即将来返回数据个数为num+1个。
'''
# list1 = mystr.split('and')
# list1 = mystr.split('and', 2)
# print(list1)
'''
join() 合并列表里面的字符串数据为一个大字符串
'''
# mylist = ['aa', 'bb', 'cc']
# # aa..bb..cc
# print('..'.join(mylist))
'''
大小写转换
capitalize():将字符串第⼀个字符转换成⼤写。
capitalize()函数转换后,只字符串第⼀个字符⼤写,其他的字符全都⼩写。

title():将字符串每个单词⾸字⺟转换成⼤写
lower():将字符串中⼤写转⼩写。
upper():将字符串中⼩写转⼤写。
'''
# mystr = "hello world and itcast and itheima and Python"
# # print(mystr.capitalize())  # Hello world and itcast and itheima and python
# # print(mystr.title())  # Hello World And Itcast And Itheima And Python
# print(mystr.upper())  # HELLO WORLD AND ITCAST AND ITHEIMA AND PYTHON
# print(mystr.lower())  # hello world and itcast and itheima and python

'''
lstrip():删除字符串左侧空⽩字符。
rstrip():删除字符串右侧空⽩字符。
strip():删除字符串两侧空⽩字符。
'''

# mystr = "   hello world and itcast and itheima and Python   "
# print(mystr)
# print(mystr.lstrip())
# print(mystr.rstrip())
# print(mystr.strip())

'''
ljust():返回⼀个原字符串左对⻬,并使⽤指定字符(默认空格)填充⾄对应⻓度 的新字符串。
字符串序列.ljust(⻓度, 填充字符)
rjust():返回⼀个原字符串右对⻬,并使⽤指定字符(默认空格)填充⾄对应⻓度 的新字符串,语法和
ljust()相同。
center():返回⼀个原字符串居中对⻬,并使⽤指定字符(默认空格)填充⾄对应⻓度 的新字符串,语
法和ljust()相同。

python console
Python 3.7.4 (tags/v3.7.4:e09359112e, Jul  8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)] on win32
mystr = 'hello'
mystr
'hello'
mystr.ljust(10)
'hello     '
mystr.ljust(10, '.')
'hello.....'
mystr.rjust(10)
'     hello'
mystr.rjust(10, '.')
'.....hello'
mystr.center(10)
'  hello   '
mystr.center(10, '.')
'..hello...'

'''

'''
字符串判断
'''
# mystr = "hello world and itcast and itheima and Python"
# print(mystr.startswith('hello'))
# print(mystr.startswith('world', 6))
# print(mystr.endswith('Python'))

'''
isalpha():如果字符串⾄少有⼀个字符并且所有字符都是字⺟则返回 True, 否则返回 False。
isdigit():如果字符串只包含数字则返回 True 否则返回 False。
isalnum():如果字符串⾄少有⼀个字符并且所有字符都是字⺟或数字则返 回 True,否则返回False。
isspace():如果字符串中只包含空⽩,则返回 True,否则返回 False。
'''
# print('hello'.isalpha())
# print('123'.isdigit())
# print('abc123'.isalnum())
# print("\t\n".isspace())
# print('  '.isspace())  # True


'''
列表
'''
'''
下标
'''
# name_list = ['TOM', 'Lily', 'ROSE']
# print(name_list)
# print(name_list[1])
'''
index():返回指定数据所在位置的下标 。注意:如果查找的数据不存在则报错。
count():统计指定数据在当前列表中出现的次数。
与字符使用方式一样
len():访问列表⻓度,即列表中数据的个数。
判断是否存在
    in:判断指定数据在某个列表序列,如果在返回True,否则返回False
    not in:判断指定数据不在某个列表序列,如果不在返回True,否则返回False

'''
# name_list = ['TOM', 'Lily', 'ROSE']
# print(name_list.index('TOM'))
# print(name_list.index('TOMS'))  # ValueError: 'TOMS' is not in list
# print(name_list.count('Lily'))
# print(name_list.count('Lilys')) # 0
# print(len(name_list))
# print('TOM' in name_list)
# print('TOMS' in name_list)
# print('TOMS' not in name_list)
# print('TOM' not in name_list)

'''
需求:查找⽤户输⼊的名字是否已经存在。
'''
# name_list = ['TOM', 'Lily', 'ROSE']
# name = input('请输入您的名字:')
# if name in name_list:
#     print(f'{name}已存在')
# else:
#     print(f'{name}可用')

'''
增加
append():列表结尾追加数据。
列表序列.append(数据)
'''
# name_list = ['TOM', 'Lily', 'ROSE']
# name_list.append('XiaoMing') ['TOM', 'Lily', 'ROSE','XiaoMing']
# print(name_list)  # 列表是可变类型
# name_list.append([11,22]) # 追加整个序列到列表 ['TOM', 'Lily', 'ROSE', 11, 23]
# print(name_list)
'''
extend():列表结尾追加数据,如果数据是⼀个序列,则将这个序列的数据逐⼀添加到列表。
'''
# name_list.extend('xiaoming')
# print(name_list) # ['TOM', 'Lily', 'ROSE', 'x', 'i', 'a', 'o', 'm', 'i', 'n', 'g']
# name_list.extend([11,23])
# print(name_list) # ['TOM', 'Lily', 'ROSE', 11, 23]

'''
insert():指定位置新增数据。
列表序列.insert(位置下标, 数据)
'''
# name_list.insert(1,'aa')
# print(name_list)  # ['TOM', 'aa', 'Lily', 'ROSE']

'''
删除
del ⽬标
del()
'''
# del name_list
# print(name_list) # NameError: name 'name_list' is not defined
# del name_list[0]
# print(name_list) # ['Lily', 'ROSE']
'''
pop():删除指定下标的数据(默认为最后⼀个),并返回该数据。
列表序列.pop(下标)
'''
# del_name = name_list.pop()
# del_name = name_list.pop(1)
# print(del_name)
# print(name_list)
'''
remove(数据)
'''
# name_list.remove('ROSE')
# print(name_list)
# name_list.clear()
# print(name_list)

'''
修改
'''
# name_list = ['TOM', 'Lily', 'ROSE']
# # 修改指定下标的数据
# name_list[0] = 'aaa'
# print(name_list)
#
# # 逆序 reverse()
# list1 = [1, 3, 2, 5, 4, 6]
# list1.reverse()
# print(list1) # [6, 4, 5, 2, 3, 1]
#
# # sort() 排序:升序(默认)和降序
# # list1.sort()
# # list1.sort(reverse=False)
# list1.sort(reverse=True)
# print(list1)
'''
复制
'''
# name_list = ['TOM', 'Lily', 'ROSE']
# name_li2 = name_list.copy()
# name_li2.reverse()
# print(name_li2)
# print(name_list)

'''
列表的循环遍历
'''
name_list = ['TOM', 'Lily', 'ROSE']
# i = 0
# while i < len(name_list):
#     print(name_list[i])
#     i += 1

# for i in name_list:
#     print(i)
# # TOM
# # Lily
# # ROSE
#
# for idx,val in enumerate(name_list):
#     print(idx,val)

'''
列表嵌套
'''
# name_list = [['TOM','Lily', 'Rose'], ['张三','李四', '王五'], ['小米','小花','小明']]
# print(name_list)
# print(name_list[0])
# print(name_list[0][1])

'''
综合应⽤ -- 随机分配办公室
需求:有三个办公室,8位⽼师,8位⽼师随机分配到3个办公室
步骤
1.准备数据
    8位老师,3个办公室
2.分配老师到办公室 随机分配
3.验证是否分配成功 办公室列表追加老师
'''
# import random
# teachers = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
# offices = [[], [], []]
# for name in teachers:
#     offidx = random.randint(0,2)
#     offices[offidx].append(name)
# i = 1
# for office in offices:
#     print(f'办公室{i}人数为{len(office)}')
#     for name in office:
#         print(name)
#     i += 1

'''
元组
元组的应⽤场景
⼀个元组可以存储多个数据,元组内的数据是不能修改的。
'''
# t1 = (10, 20, 30)
# print(type(t1))
# print(t1)
# t2 = (10,)
# print(type(t2)) # <class 'tuple'>
# t3 = (10)
# print(type(t3)) # <class 'int'>
# t4 = ('aaa')
# print(type(t4)) # <class 'str'>
# t5 = ('aaa',)
# print(type(t5)) # <class 'tuple'>
'''
元组的常⻅操作
元组数据不⽀持修改,只⽀持查找,具体如下:
按下标查找数据
index():查找某个数据,如果数据存在返回对应的下标,否则报错,语法和列表、字符串的index
⽅法相同。
count():统计某个数据在当前元组出现的次数。
len():统计元组中数据的个数。
'''
# t1 = ('aa', 'bb', 'cc', 'dd')
# print(t1[0])
# print(t1.index('aa'))
# print(t1.index('bbb'))
# print(t1.count('aa'))
# print(len(t1))
'''
元组修改 
但是如果元组⾥⾯有列表,修改列表⾥⾯的数据则是⽀持的,故⾃觉很重要。
'''
# t1[0] = 'aaa'  # TypeError: 'tuple' object does not support item assignment
# t2 = ('aa', 'bb', ['cc', 'dd'])
# print(t2[2])
# t2[2][0] = 'TOM'
# print(t2)  # ('aa', 'bb', ['TOM', 'dd'])

'''
字典
字典的应⽤场景
思考1: 如果有多个数据,例如:'Tom', '男', 20,如何快速存储?
字典,字典⾥⾯的数据是以键值对形式出现,字典数据和数据顺序没有关系,即字典不⽀持下标,
后期⽆论数据如何变化,只需要按照对应的键的名字查找数据即可。
 创建字典的语法:
 字典特点:
    符号为⼤括号
    数据为键值对形式出现
    各个键值对之间⽤逗号隔开
'''
# 有数据的字典
dict1 = {'name': 'TOM', 'age': 20, 'gender':''}
# print(dict1)
# print(type(dict1)) # <class 'dict'>
# # 空字典
# dict2 = {}
# dict3 = dict()
# print(type(dict2))
# print(type(dict3))
'''
 字典常⻅操作
'''
# 增   字典序列[key] = 值
# 注意:如果key存在则修改这个key对应的值;如果key不存在则新增此键值对。

# dict1 = {'name': 'TOM', 'age': 20, 'gender':' 男'}
# dict1['id'] = 110
# print(dict1)
# dict1['name'] = 'ROSE'
# print(dict1)

# 删  del() / del:删除字典或删除字典中指定键值对。
# del(dict1)
# print(dict1) # NameError: name 'dict1' is not defined

# del dict1['name']
# del dict1['names'] # KeyError: 'names'
# dict1.clear()  # {}
# print(dict1)

# 改 字典序列[key] = 值
# 注意:如果key存在则修改这个key对应的值 ;如果key不存在则新增此键值对
# dict1['id'] = 110
# print(dict1)

'''
查 
 key值查找 
如果当前查找的key存在,则返回对应的值;否则则报错。
get()
 keys()
 values()
 items()
'''
# print(dict1['name'])
# print(dict1['name1']) #     print(dict1['name1'])

# dict1 = {'name': 'TOM', 'age': 20, 'gender':' 男'}
# print(dict1.get('name')) # TOM
# print(dict1.get('id')) # None
# print(dict1.get('id','Lily')) # Lily
# # 查找字典中所有的key,返回可迭代的对象
# print(dict1.keys())  # dict_keys(['name', 'age', 'gender'])
#
# print(dict1.values()) # dict_values(['TOM', 20, ' 男'])
# # 查找字典中所有的键值对,返回可迭代对象,里面的对象是元组,元组数据1是key,2是value
# print(dict1.items())  # dict_items([('name', 'TOM'), ('age', 20), ('gender', ' 男')])

'''
字典遍历
'''
# dict1 = {'name': 'TOM', 'age': 20, 'gender':' 男'}
# # for key in dict1.keys():
# #     print(key)
# # for v in dict1.values():
# #     print(v)
#
# for item in dict1.items():
#     print(item)   # ('name', 'TOM')
#
# # 遍历字典的键值对,拆包
# for k,v in dict1.items():
#     print(f'{k}={v}')

'''
集合
创建集合使⽤ {} 或 set() , 但是如果要创建空集合只能使⽤ set() ,因为 {} ⽤来创建空字典。
特点:
1. 集合可以去掉重复数据;
2. 集合数据是⽆序的,故不⽀持下标
'''
# s1 = {10, 20, 30, 40, 50}
# print(s1)  # {40, 10, 50, 20, 30}

# s2 = {10, 20, 30, 40, 30, 40, 50}
# print(s2)
# s3 = set('abcdefg')
# print(s3)  # {'d', 'b', 'g', 'f', 'a', 'e', 'c'}
# s4 = set()
# print(type(s4)) # <class 'set'>
# s5 = {}
# print(type(s5)) # <class 'dict'>

'''
集合常⻅操作⽅法
增加数据 
因为集合有去重功能,所以,当向集合内追加的数据是当前集合已有数据的话,则不进⾏任何操作。
add()
update(), 追加的数据是序列。
'''
# 集合是可变类型
# s1 = {10, 20}
# s1.add(100)
# print(s1)
# s1.add(100)
# s1.add([10,20,30])  # TypeError: unhashable type: 'list'

# s1.update([10, 50, 30])
# print(s1)
# s1.update(60)  # TypeError: 'int' object is not iterable

'''
删除数据
remove(),删除集合中的指定数据,如果数据不存在则报错。
discard(),删除集合中的指定数据,如果数据不存在也不会报错。
pop(),随机删除集合中的某个数据,并返回这个数据
'''
# s1 = {10, 20, 30, 40, 50}
# s1.remove(10)
# s1.remove(100) # KeyError: 100
# s1.discard(10)
# s1.discard(10)
# print(s1)
# del_num = s1.pop()
# print(del_num)
# print(s1)

'''
查找数据
in:判断数据在集合序列
not in:判断数据不在集合序列
'''
# s1 = {10, 20, 30, 40, 50}
# print(10 in s1)
# print(10 not in s1)

'''
公共操作
运算符
    运算符 描述  ⽀持的容器类型
     +    合并 字符串、列表、元组
     *    复制 字符串、列表、元组
   in/not in   元素是否存在 字符串、列表、元组、字典
公共⽅法
容器类型转换
'''
# # 1. 字符串
# str1 = 'aa'
# str2 = 'bb'
# str3 = str1 + str2
# print(str3) # aabb
# # 2. 列表
# list1 = [1, 2]
# list2 = [10, 20]
# list3 = list1 + list2
# print(list3) # [1, 2, 10, 20]
# # 3. 元组
# t1 = (1, 2)
# t2 = (10, 20)
# t3 = t1 + t2
# print(t3) # (10, 20, 100, 200)
# dict1 = {'name':'aa'}
# dict2 = {'gender':'bb'}
# dict3 = dict1 + dict2  # TypeError: unsupported operand type(s) for +: 'dict' and 'dict'
# print(dict3)

# #  1. 字符串
# print('-' * 10) # ----------
# # 2. 列表
# list1 = ['hello']
# print(list1 * 4) # ['hello', 'hello', 'hello', 'hello']
# # 3. 元组
# t1 = ('world',)
# print(t1 * 4) # ('world', 'world', 'world', 'world')

# 1. 字符串
# print('a' in 'abcd') # True
# print('a' not in 'abcd') # False
# # 2. 列表
# list1 = ['a', 'b', 'c', 'd']
# print('a' in list1) # True
# print('a' not in list1) # False
# # 3. 元组
# t1 = ('a', 'b', 'c', 'd')
# print('aa' in t1) # False
# print('aa' not in t1) # True

# dict1 = {'name': 'TOM', 'age': 20, 'gender':' 男'}
# print('name' in dict1.keys())
# print('TOM' in dict1.values())

'''
公共⽅法
函数 描述
len() 计算容器中元素个数
del 或 del() 删除
max() 返回容器中元素最⼤值
min() 返回容器中元素最⼩值
range(start,
end, step) ⽣成从start到end的数字,步⻓为 step,供for循环使⽤;range()⽣成的序列不包含end数字。
enumerate() 函数⽤于将⼀个可遍历的数据对象(如列表、元组或字符串)组合为⼀个索引序
列,同时列出数据和数据下标,⼀般⽤在 for 循环当中。
'''
# 1. 字符串
# str1 = 'abcdefg'
# print(len(str1)) # 7
# # 2. 列表
# list1 = [10, 20, 30, 40]
# print(len(list1)) # 4
# # 3. 元组
# t1 = (10, 20, 30, 40, 50)
# print(len(t1)) # 5
# # 4. 集合
# s1 = {10, 20, 30}
# print(len(s1)) # 3
# # 5. 字典
# dict1 = {'name': 'Rose', 'age': 18}
# print(len(dict1)) # 2

# str1 = 'abcdef'
# list1 = [10,20,30]
# t1 = (10,20,30)
# s1 = {10,20,30}
# dict1 = {'name': 'TOM','age':17}
# del str1
# # del list1
# del(list1[0])
# print(list1)
# del dict1['name']
# print(dict1)

# print(max(str1),min(str1))
# print(max(list1),min(list1))

# print(range(1, 10,1))  # range(1, 10) 返回可迭代对象
# # 左闭右开
# for i in range(1, 10, 1):
#     print(i)
# 默认步长是1
# for i in range(1, 10):
#     print(i)
# # 默认从0开始
# for i in range(10):
#     print(i)

'''
enumerate(可遍历对象, start=0)
start参数⽤来设置遍历数据的下标的起始值,默认为0。
'''
# list1 = ['a', 'b', 'c', 'd']
# for i in enumerate(list1):
#     print(i)  # (1, 'b') ... (下标 数据)
# start 修改下标起始值
# for i in enumerate(list1,start=1):
#     print(i)

'''
容器类型转换
tuple()
 list()
 set()

'''

# list1 = [10, 20, 30, 40, 50, 20]
# s1 = {100, 200, 300, 400, 500}
# t1 = ('a', 'b', 'c', 'd', 'e')
#
# print(tuple(list1))
# print(tuple(s1))
#
# print(list(s1))
# print(list(t1))
# print(set(list1))
# print(set(t1))

'''
列表推导式
⽤⼀个表达式创建⼀个有规律的列表或控制⼀个有规律列表。
----
列表推导式
字典推导式
集合推导式
'''

# 需求创建一个0-10的列表
# while实现.....
# list1 = []
# i = 0
# while i < 10:
#     list1.append(i)
#     i += 1
# print(list1)

# for实现.....
# list1 = []
# for i in range(10):
#     list1.append(i)
# print(list1)

# 列表推导式实现
# list1 = [i for i in range(10)]
# print(list1)

#  带if的列表推导式
# 需求:创建0-10的偶数列表
# list1 = [ i for i in range(0,10,2)]
# print(list1)
# list0 = []
# for i in range(10):
#     if i % 2 == 0:
#         list0.append(i)
# print(list0)
# list2 = [i for i in range(10) if i % 2 == 0]
# print(list2)

# 多个for循环实现列表推导式
# 需求:创建列表如下: [(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
# list1 = []
# for i in range(1,3):
#     for j in range(3):
#         list1.append((i,j))
# list2 = [(i, j) for i in range(1, 3) for j in range(3)]
# print(list2)

'''
字典推导式
如何快速合并为⼀个字典?
答:字典推导式
字典推导式作⽤:快速合并列表为字典或提取字典中⽬标数据。
'''
# . 创建⼀个字典:字典key是1-5数字,value是这个数字的2次⽅。
# dict1 = {i: i**2 for i in range(1, 5)}
# print(dict1)
# 将两个列表合并为⼀个字典
# list1 = ['name', 'age','gender']
# list2 = ['Tom', 20, 'man']
# dict2 = { list1[i]: list2[i] for i in range(len(list1))}
# print(dict2)
# # 如果两个列表数据长度不同,len统计列表数据多的个数,会报错;统计少的,不会报错
#
# # 提取字典中⽬标数据
# counts = {'MBP': 268, 'HP': 125, 'DELL': 201, 'Lenovo': 199, 'acer': 99}
# count1 = {k: v for k,v in counts.items() if v > 200}
# print(count1)

'''
集合推导式
'''
# 需求:创建⼀个集合,数据为下⽅列表的2次⽅。
# list1 = [1, 1, 2]
# set1 = {i**2 for i in list1}
# print(set1) # print(set1) #

 

'''
函数
函数就是将⼀段具有独⽴功能的代码块 整合到⼀个整体并命名,在需要的位置调⽤这个名称即可完成对应的需求。
函数在开发过程中,可以更⾼效的实现代码重⽤。

学习目标
    函数的作⽤
    函数的使⽤步骤
    函数的参数作⽤
    函数的返回值作⽤
    函数的说明⽂档
    函数嵌套

函数的使⽤步骤
    定义函数
        def 函数名(参数):
             代码1
             代码2
             ......
    调⽤函数
        函数名(参数)
     不同的需求,参数可有可⽆。
'''


# def sel_fun():
#     print('显示余额')
#     print('存款')
#     print('取款')
#
# print('恭喜你登录成功')
# sel_fun()
# print('您的余额为1000元')
# sel_fun()
# print('您取出了300元')
# sel_fun()


# info_print()
def info_print():
    print('hello world')


# 结论1 函数是先定义,后调用
# 2 如果没有调用函数,函数里面的代码不会执行

# .函数的参数作⽤
'''
完成需求如下:⼀个函数完成两个数1和2的加法运算,如何书写程序?
'''
# 定义函数
# def add_num1():
#     result = 1 + 2
#     print(result)
# # 调⽤函数
# add_num1()
#
# # 函数的返回值作⽤
# def buy():
#     return '烟'
# # 使⽤变量保存函数返回值
# goods = buy()
# print(goods)

'''
思考:定义⼀个函数后,程序员如何书写程序能够快速提示这个函数的作⽤?
函数的说明⽂档;注释
函数的说明⽂档也叫函数的⽂档说明。
语法
    定义函数的说明⽂档
def 函数名(参数):
     """ 说明⽂档的位置 """
     代码
     ......
查看函数的说明⽂档
help(函数名)
'''


# def add_num(a, b):
#     """求和函数"""
#     return a + b
#
#
# print(add_num(10, 20))
#
# help(add_num)

'''
变量作⽤域
'''

# def testA():
#     a = 100
#     print(1)
#
# testA()

'''
局部变量 # 所谓局部变量是定义在函数体内部的变量,即只在函数体内部⽣效。
局部变量的作⽤:在函数体内部,临时保存数据,即当函数调⽤完成后,则销毁局部变量。
'''
# print(a)  # NameError: name 'a' is not defined

# 全局变量
'''
所谓全局变量,指的是在函数体内、外都能⽣效的变量。
'''
# # 定义全局变量a
# a = 100
# def testA():
#     print(a)  # # 访问全局变量a,并打印变量a存储的数据
# testA()
#
# def testB():
#     a = 200   # 在 testB 函数内部的 a = 200 中的变量a是不是在修改全局变量 a
#     print(a)
# testA() # 100
# testB() # 200
# print(f'全局变量a = {a}') # 全局变量a = 100
#
# # 如何在函数体内部修改全局变量
# def testC():
#     global a
#     a = 200
#     print(a)
# testA() # 100
# testC() # 200
# print(f'全局变量a = {a}') # 全局变量a = 100


'''
函数的返回值
'''

'''
如果⼀个函数如些两个return (如下所示),程序如何执⾏?
return a, b 写法,返回多个数据的时候,默认是元组类型。
 return后⾯可以连接列表、元组或字典,以返回多个值。
'''

# def return_num():
#     # return 1, 2  # (1, 2)
#     # return (1, 2)
#     # return [1, 2]
#     return {'name':'TOM' ,'age': 13}
# result = return_num()
# print(result)  # (1, 2)

'''
函数的参数
'''
'''
 位置参数
 位置参数:调⽤函数时根据函数定义的参数位置来传递参数。
 传递和定义参数的顺序及个数必须⼀致。
'''
# def user_info(name, age, gender):
#     print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
#
# user_info('TOM', 20, '男')

'''
关键字参数
函数调⽤,通过“键=值”形式加以指定。可以让函数更加清晰、容易使⽤,同时也清除了参数的顺序需求。
'''


# def user_info(name, age, gender):
#     print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
#
#
# user_info('Rose', age=10, gender='男')
# user_info(age=20, name='TOM', gender='男')
# user_info(age=20, name='TOM')  # TypeError: user_info() missing 1 required positional argument: 'gender'

# :函数调⽤时,如果有位置参数时,位置参数必须在关键字参数的前⾯,但关键字参数之间不存在
# 先后顺序。

'''
 缺省参数
缺省参数也叫默认参数,⽤于定义函数,为参数提供默认值,调⽤函数时可不传该默认参数的值(注
意:所有位置参数必须出现在默认参数前,包括函数定义和调⽤)。
'''

# def user_info(name, age, gender='男'):
#     print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
#
#
# user_info('TOM', 20)
# user_info('Rose', 18, '⼥')

'''
不定⻓参数
不定⻓参数也叫可变参数。⽤于不确定调⽤的时候会传递多少个参数(不传参也可以)的场景。此时,可
⽤包裹(packing)位置参数,或者包裹关键字参数,来进⾏参数传递,会显得⾮常⽅便。

'''
# 包裹位置传递
# def user_info(*args):
#     print(args)
#
# user_info('TOM')
# user_info('TOM', 18)
# 注意:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为⼀个元组(tuple),args是元组类型,这就是包裹位置传递。

# 包裹关键字传递

# def user_info(**kwargs):
#     print(kwargs)
#
# user_info(name='TOM',age=13, id=110)  # {'name': 'TOM', 'age': 13, 'id': 110}

# ⽆论是包裹位置传递还是包裹关键字传递,都是⼀个组包的过程。

'''
 拆包和交换变量值
'''
# 拆包
# 拆包:元组
# def return_num():
#     return 100, 200
#
# num1, num2 = return_num()
# print(num1,num2)
#
# # 拆包:字典
# dict1 = {'name': 'TOM', 'age': 18}
# #  对字典进⾏拆包,取出来的是字典的key
# a, b = dict1
# print(a,b)  # name age
# print(dict1[a],dict1[b])

'''
交换变量值
需求:有变量 a = 10 和 b = 20 ,交换两个变量的值。
⽅法⼀
借助第三变量存储数据。
⽅法⼆
a, b = b, a
'''
# c = 0
# a = 10
# b = 20
# c = 10
# a = b
# b = c
# print(a,b)


# a,b = 10,20
# a, b = b, a
# print(a,b)

'''
引⽤
在python中,值是靠引⽤来传递来的。
我们可以⽤ id() id() 来判断两个变量是否为同⼀个值的引⽤。 我们可以将id值理解为那块内存的地址标
识。
'''
#  1. int类型
# a = 1
# b = a
# print(b)
# print(id(a))
# print(id(b))
# print(id(a) == id(b))  # True

#  2. 列表
# aa = [10, 20]
# bb = aa
# print(id(aa) == id(bb))  # True
# print(id(bb))
# aa.append(30)
# print(id(aa) == id(bb))  # True

# 引⽤当做实参
# def test1(a):
#     print(a)
#     print(id(a))
#     a += a
#     print(a)
#     print(id(a))
#
# b = 100  # 不可变类型,在函数内部数值变化时, a += a 导致函数内局部的a id 变化,新开空间;
# test1(b)
#
# c = [11, 22] # 可变类型,在函数内部数据变化时,  a += a id不会发生变化;
# test1(c)


'''
# 可变和不可变类型
所谓可变类型与不可变类型是指:数据能够直接进⾏修改,如果能直接修改那么就是可变,否则是不可变.
可变类型
    列表
    字典
    集合
不可变类型
    整型
    浮点型
    字符串
    元组
'''


# info = []
#
# def add():
#     dict = {'name':'TOM', 'age': 23}
#     # global info
#     info.append(dict)
#
# print(info)
# add()
# print(info)

'''
 递归
 2.1 递归的应⽤场景
    递归是⼀种编程思想,应⽤场景:
    1. 在我们⽇常开发中,如果要遍历⼀个⽂件夹下⾯所有的⽂件,通常会使⽤递归来实现;
    2. 在后续的算法课程中,很多算法都离不开递归,例如:快速排序。
'''

# def sum_num(num):
#     if num == 1:
#         return 1
#     return num + sum_num(num-1)
#
# print(sum_num(996))  # 有最大递归深度

'''
lambda的应⽤场景
lambda语法
lambda 参数列表 : 表达式
注意
lambda表达式的参数可有可⽆,函数的参数在lambda表达式中完全适⽤。
lambda表达式能接收任何数量的参数但只能返回⼀个表达式的值。
'''

# def fn1():
#     return 200
#
# print(fn1) # <function fn1 at 0x000002B631295EE8>
# print(fn1()) # 200
# # ⽆参数
# fn2 = lambda: 100
# print(fn2)  # <function <lambda> at 0x0000017C60B3DEE8> # lambda的内存地址
# print(fn2()) # 100

# fn1 = lambda a, b: a + b
# print(fn1(10,10))

# 默认参数
# fn1 = lambda a, b, c=100: a + b + c
# print(fn1(10,20))

# .可变参数:*args
# fn1 = lambda *args: args
# print(fn1(10,20,30))  # (10, 20, 30)
# 注意:这⾥的可变参数传⼊到lambda之后,返回值为元组。

#
# fn1 = lambda **kwargs: kwargs
# print(fn1(name='python',age = 20))  # {'name': 'python', 'age': 20}

# 带判断的lambda
# fn1 = lambda a, b: a if a > b else b
# print(fn1(10,20))

# 列表数据按字典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)

'''
. ⾼阶函数
把函数作为参数传⼊,这样的函数称为⾼阶函数,⾼阶函数是函数式编程的体现。函数式编程就是指这
种⾼度抽象的编程范式。
'''
# # 在Python中, abs() 函数可以完成对数字求绝对值计算。
# print(abs(-10)) # 10
# # round() 函数可以完成对数字的四舍五⼊计算
# print(round(1.2))
# print(round(1.9))

# #需求: 任意两个数字,按照指定要求整理数字后再进⾏求和计算。
# def sum_num(a, b):
#     return abs(a) + abs(b)
#
# print(sum_num(-10,-20))

# def sum_num(a, b, f):
#     return f(a) + f(b)
#
# print(sum_num(-10,-20,abs))
# 注意:两种⽅法对⽐之后,发现,⽅法2的代码会更加简洁,函数灵活性更⾼。
# 函数式编程⼤量使⽤函数,减少了代码的重复,因此程序⽐较短,开发速度较快。

'''
内置⾼阶函数
 map()
map(func, lst),将传⼊的函数变量func作⽤到lst变量的每个元素中,并将结果组成新的列表(Python2)/迭代器(Python3)返回。
reduce(func,lst),其中func必须有两个参数。每次func计算的结果继续和序列的下⼀个元素做累积计算。
注意:reduce()传⼊的参数func必须接收2个参数。
filter()
filter(func, lst)函数⽤于过滤序列, 过滤掉不符合条件的元素, 返回⼀个 filter 对象。如果要转换为列表,
可以使⽤ list() 来转换
'''

# # 需求:计算 list1 序列中各个数字的2次⽅。
# list1 = [1, 2, 3, 4, 5]
# def func(x):
#     return  x ** 2
#
# result = map(func, list1)

# print(result) # <map object at 0x000002963DFEBB08>
# print(list(result))
#
# for i in result:
#     print(i)

# 需求:计算 list1 序列中各个数字的累加和。
# import functools
# list1 = [1, 2, 3, 4, 5]
# def func(a, b):
#     return a + b
#
# result = functools.reduce(func,list1)
# print(result)

# list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# def func(num):
#     return num % 2 == 0
#
# result = filter(func,list1)
# print(result)  # <filter object at 0x000002455AC3BA48>
# print(list(result))

'''
⽂件操作
⽂件操作的作⽤
⽂件的基本操作
    打开
    读写
    关闭
⽂件备份
⽂件和⽂件夹的操作
总结:⽂件操作的作⽤就是把⼀些内容(数据)存储存放起来,可以让程序下⼀次执⾏的时候直接使
⽤,⽽不必重新制作⼀份,省时省⼒。
'''

'''
. ⽂件的基本操作
2.1 ⽂件操作步骤
1. 打开⽂件
2. 读写等操作
3. 关闭⽂件
注意:可以只打开和关闭⽂件,不进⾏任何读写操作。

2.1.1 打开
在python,使⽤open函数,可以打开⼀个已经存在的⽂件,或者创建⼀个新⽂件,语法如下:
name:是要打开的⽬标⽂件名的字符串(可以包含⽂件所在的具体路径)。
mode:设置打开⽂件的模式(访问模式):只读、写⼊、追加等。
模
式 描述
r 以只读⽅式打开⽂件。⽂件的指针将会放在⽂件的开头。这是默认模式。
rb 以⼆进制格式打开⼀个⽂件⽤于只读。⽂件指针将会放在⽂件的开头。这是默认模式。
r+ 打开⼀个⽂件⽤于读写。⽂件指针将会放在⽂件的开头。
rb+ 以⼆进制格式打开⼀个⽂件⽤于读写。⽂件指针将会放在⽂件的开头。
w
打开⼀个⽂件只⽤于写⼊。如果该⽂件已存在则打开⽂件,并从开头开始编辑,即原有内
容会被删除。如果该⽂件不存在,创建新⽂件。
wb 以⼆进制格式打开⼀个⽂件只⽤于写⼊。如果该⽂件已存在则打开⽂件,并从开头开始编
辑,即原有内容会被删除。如果该⽂件不存在,创建新⽂件。
w+
打开⼀个⽂件⽤于读写。如果该⽂件已存在则打开⽂件,并从开头开始编辑,即原有内容
会被删除。如果该⽂件不存在,创建新⽂件。
wb+ 以⼆进制格式打开⼀个⽂件⽤于读写。如果该⽂件已存在则打开⽂件,并从开头开始编
辑,即原有内容会被删除。如果该⽂件不存在,创建新⽂件。
a
打开⼀个⽂件⽤于追加。如果该⽂件已存在,⽂件指针将会放在⽂件的结尾。也就是说,
新的内容将会被写⼊到已有内容之后。如果该⽂件不存在,创建新⽂件进⾏写⼊。
ab
以⼆进制格式打开⼀个⽂件⽤于追加。如果该⽂件已存在,⽂件指针将会放在⽂件的结
尾。也就是说,新的内容将会被写⼊到已有内容之后。如果该⽂件不存在,创建新⽂件进
⾏写⼊。
a+
打开⼀个⽂件⽤于读写。如果该⽂件已存在,⽂件指针将会放在⽂件的结尾。⽂件打开时
会是追加模式。如果该⽂件不存在,创建新⽂件⽤于读写。
ab+ 以⼆进制格式打开⼀个⽂件⽤于追加。如果该⽂件已存在,⽂件指针将会放在⽂件的结
尾。如果该⽂件不存在,创建新⽂件⽤于读写。
'''

# f = open('test.txt','w')
# f.write('aaa')
# f.close()

'''
测试主访问模式 r  w  a (追加)
'''

# r 如果文件不存在,报错,不支持写入操作;表示只读
# f = open('test1.txt', 'r')
# f = open('test.txt', 'r')
# # f.write('aa') # UnsupportedOperation: not writable
# f.close()

# w 只写,如果文件不存在,新建文件执行写入,会覆盖原有文件
# f = open('1.txt','w')
# # f.write('aaa')
# f.write('bbb')
# f.close()

# a 追加 如果文件不存爱,新建文件,在原有内容基础上,追加新内容
# f = open('2.txt',  'a')
# # f.write('xyz')
# f.write('abc')
# f.close()

#  访问模式参数可以省略,如果省略表示访问模式为r
# f = open('11.txt')
# f = open('1.txt')
# f.close()

'''
读
read()
num表示要从⽂件中读取的数据的⻓度(单位是字节),如果没有传⼊num,那么就表示读取⽂
件中所有的数据。
readlines()
readlines可以按照⾏的⽅式把整个⽂件中的内容进⾏⼀次性读取,并且返回的是⼀个列表,其中每⼀⾏
的数据为⼀个元素。
readline()
readline()⼀次读取⼀⾏内容。
seek()
作⽤:⽤来移动⽂件指针
⽂件对象.seek(偏移量, 起始位置)起始位置:
0:⽂件开头
1:当前位置
2:⽂件结尾

'''
# f = open('test.txt', 'r')
# print(f.read())
# aaaaaa
# bbbbbb
# cccccc
# print(f.read(10))  # 数据有隐藏的换行符号
# aaaaaa
# bbb
# f.close()

# f = open('test.txt', 'r')
# content = f.readlines()
# print(content)  # ['aaaaaa\n', 'bbbbbb\n', 'cccccc']
# f.close()



# f = open('test.txt', 'r')
# print(f.readline())
# print(f.readline())
# f.close()

'''
 访问模式
 带b是二进制
 带+是可读可写
 文件指针按照主访问模式 r w a 初始设置 
'''

'''
1.测试 r+ w+  a+
    
2.文件指针对数据读取的影响
'''
# r+  没有该文件报错;文件指针在开头,
# f = open('test1.txt', 'r+')
# f = open('test.txt', 'r+')

# w+ 没有改文件会新建文件,文件指针在开头,用新内容覆盖原内容
# f = open('test100.txt', 'w+')


# a+ 没有该文件会新建文件,文件指针在结尾
# f = open('test200.txt', 'a+')
#
# con = f.read()
# print(con)
# f.write("ccc")
# f.close()


'''
⽂件对象.seek(偏移量, 起始位置)
作⽤:⽤来移动⽂件指针。
起始位置:
0:⽂件开头
1:当前位置
2:⽂件结尾
'''

# f = open('test.txt', 'r+')
# # f.seek(5, 0) # 改变读取数据开始位置
# f.seek(0, 2)  # 改为指针位置为结尾,读不出数据
# con = f.read()
# print(con)
#
# f.close()

'''
⽂件备份
需求:⽤户输⼊当前⽬录下任意⽂件名,程序完成对该⽂件的备份功能(备份⽂件名为xx[备份]后缀,例
如:test[备份].txt)。
'''
'''
1. 接收⽤户输⼊的⽂件名
2. 规划备份⽂件名
3. 备份⽂件写⼊数据
'''
# old_name = input('请输入您要被封的文件名:')
#
# index = old_name.rfind('.')
#
# new_name = old_name[:index] + '[备份]' + old_name[index:]
# print(new_name)
#
# f = open(old_name,'rb')
# f_bak = open(new_name,'wb')
#
# while True:
#     con = f.read(1024)
#     if len(con) == 0:
#         break
#     f_bak.write(con)
#
# f.close()
# f_bak.close()


'''
⽂件和⽂件夹的操作
导⼊os模块
使⽤ os 模块相关功能
os.函数名()
'''
import os
# os.rename('1.txt','10.txt')
# os.remove('10.txt')

#  创建⽂件夹
# os.mkdir('aa')

# 删除⽂件夹
# os.rmdir('aa')

# 获取当前文件所在目录路径
# print(os.getcwd())

# 改变目录路径
# os.mkdir('aa')
# os.mkdir('bb')
# os.chdir('aa')
# os.mkdir('bb')

# 获取⽬录列表
# print(os.listdir())

'''
需求1.:批量修改⽂件名,既可添加指定字符串,⼜能删除指定字符串。
1.找到所有文件-- listdir
2.构造名字
3.重命名
需求2. 删除Python_, 重命名:1,删除:2
'''

# import os
#
# os.chdir('aa')
#
# flag = int(input('请输入操作1:重命名,2:删除'))
# print(flag)
# file_list = os.listdir()
#
# for i in file_list:
#     if flag == 1:
#         new_name = 'Python_' + i
#         os.rename(i, new_name)
#     elif flag == 2:
#         num = len('Python_')
#         new_name = i[num:]
#         os.rename(i, new_name)
#
# print(os.listdir())
'''
⾯向对象基础
⽬标
    理解⾯向对象
    类和对象
    添加和获取对象属性
    魔法⽅法

'''

'''
类和对象
类和对象的关系:⽤类去创建⼀个对象。
'''

'''
注意:类名要满⾜标识符命名规则,同时遵循⼤驼峰命名习惯。    
2.2.1 定义类
Python2中类分为:经典类 和 新式类
语法
    注意:类名要满⾜标识符命名规则,同时遵循⼤驼峰命名习惯。
    class 类名():
     代码
     ......
拓展:经典类
不由任意内置类型派⽣出的类,称之为经典类
class 类名:
 代码
 ......
 
 
 创建对象
 对象名 = 类名()

'''

# class Washer():
#     def wash(self):
#         print('能洗衣服')
#         print(self)  # <__main__.Washer object at 0x00000205B8B5F0C8>
#
# haier = Washer()
#
# print(haier)  # 打印出内存地址 <__main__.Washer object at 0x000001C522C08208>
# haier.wash()

'''
self指的是调⽤该函数的对象。
注意:打印对象和self得到的结果是⼀致的,都是当前对象的内存中存储地址。
'''

'''
添加和获取对象属性
'''

'''
类外⾯添加对象属性
对象名.属性名 = 值
'''

# class Washer():
#     def wash(self):
#         print('能洗衣服')
#
# haier1 = Washer()
# haier1.width = 400
#
# '''
# 类外⾯获取对象属性
# '''
# print(haier1.width)

'''
类⾥⾯获取对象属性
self.属性名
'''

# class Washer():
#     def wash(self):
#         print('能洗衣服')
#
#     def print_info(self):
#         print(self.width)
#
# haier1 = Washer()
# haier1.width = 400
#
# haier1.print_info()

'''
魔法⽅法
在Python中, __xx__() 的函数叫做魔法⽅法,指的是具有特殊功能的函数。
'''

'''
体验__init__() __init__()
思考:洗⾐机的宽度⾼度是与⽣俱来的属性,可不可以在⽣产过程中就赋予这些属性呢?
答:理应如此。
__init__() ⽅法的作⽤:初始化对象。

__init__() ⽅法,在创建⼀个对象时默认被调⽤,不需要⼿动调⽤
__init__(self) 中的self参数,不需要开发者传递,python解释器会⾃动把当前的对象引
⽤传递过去。
'''

# class Washer():
#     def __init__(self):
#         self.width = 500
#         self.height = 800
#
#     def print_info(self):
#         print(self.width)
#
# haier = Washer()
# haier.print_info()

'''
带参数的__init__() __init__()
'''
# class Washer():
#     def __init__(self, width, height):
#         self.width = width
#         self.height = height
#
#     def print_info(self):
#         print(self.width)
#
# haier = Washer(10,20)
# haier.print_info()


'''
 __str__() 
 当使⽤print输出对象的时候,默认打印对象的内存地址。如果类定义了 __str__ ⽅法,那么就会打印从
在这个⽅法中 return 的数据。
'''

# class Washer():
#     def __init__(self, width, height):
#          self.width = width
#          self.height = height
#     def __str__(self):
#         return '这是海尔'
#
# h = Washer(10,20)
# print(h)  # 这是海尔

'''
 __del__() 
 当删除对象时,python解释器也会默认调⽤ __del__() ⽅法。
'''

# class Washer():
#     def __init__(self, width, height):
#          self.width = width
#          self.height = height
#     def __del__(self):
#         print(f'{self}对象已经被删除')
#
# h = Washer(10,20)
# del h   # <__main__.Washer object at 0x00000242D5DCF648>对象已经被删除


'''
拓展1:经典类或旧式类
不由任意内置类型派⽣出的类,称之为经典类。
class 类名:
 代码
 ......
拓展2:新式类
 class 类名(object):
  代码
'''

'''
⾯向对象-继承
⽬标
 继承的概念
 单继承
 多继承
 ⼦类重写⽗类的同名属性和⽅法
 ⼦类调⽤⽗类的同名属性和⽅法
 多层继承
 super()
 私有属性和私有⽅法
'''

'''
Python⾯向对象的继承指的是多个类之间的所属关系,即⼦类默认继承⽗类的所有属性和⽅法,
'''

# class A(object):
#     def __init__(self):
#         self.num = 1
#
#     def info_print(self):
#         print(self.num)
#
# class B(A):
#     pass
#
# b = B()
# b.info_print()
# 在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)


'''
多继承
故事推进:daqiu是个爱学习的好孩⼦,想学习更多的煎饼果⼦技术,于是,在百度搜索到⿊⻢程
序员,报班学习煎饼果⼦技术。

所谓多继承意思就是⼀个类同时继承了多个⽗类。
'''

# 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()
# 注意:当⼀个类有多个⽗类的时候,默认使⽤第⼀个⽗类的同名属性和⽅法。


# ⼦类重写⽗类同名⽅法和属性
'''
故事:daqiu掌握了师⽗和培训的技术后,⾃⼰潜⼼钻研出⾃⼰的独⻔配⽅的⼀套全新的煎饼果⼦
技术。
⼦类和⽗类具有同名属性和⽅法,默认使⽤⼦类的同名属性和⽅法。
'''

# 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()
#
# # (<class '__main__.Prentice'>, <class '__main__.School'>, <class '__main__.Master'>, <class 'object'>)
# # 打印一个雷的继承层级关系
# 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()


'''
多层继承
故事:N年后,daqiu⽼了,想要把所有技术传承给⾃⼰的徒弟。
'''

# 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_master_cake()
# xiaoqiu.make_school_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):
#         super(School, self).__init__()
#         super(School, self).make_cake()
#         print(f'运⽤{self.kongfu}制作煎饼果⼦')
#
# class Prentice(School):
#     def __init__(self):
#         self.kongfu = '[独创煎饼果⼦配⽅]'
#     # # 如果是先调⽤了⽗类的属性和⽅法,⽗类属性会覆盖⼦类属性,故在调⽤属性前,先调⽤⾃⼰⼦类的初始化
#     def make_cake(self):
#         self.__init__()
#         print(f'运⽤{self.kongfu}制作煎饼果⼦')
#
#     # 需求 一次性调用父类School Master的方法
#     def make_old_cake(self):
#        # 方法一: 如果定义的类名修改,这里也要修改,麻烦代码庞大,冗余
#        #  Master.__init__(self)
#        #  Master.make_cake(self)
#        #  School.__init__(self)
#        #  School.make_cake(self)
#
#        # 方法2
#        # 2.1 super带参数
#        # super(Prentice,self).__init__()
#        # super(Prentice, self).make_cake()
#
#        # 2.2 super带参数
#        super().__init__()
#        super().make_cake()
#  注意:使⽤super() 可以⾃动查找⽗类。调⽤顺序遵循 __mro__ 类属性的顺序。⽐较适合单继承使⽤。
#
# daqiu = Prentice()
# daqiu.make_old_cake()

'''
私有权限
定义私有属性和⽅法
在Python中,可以为实例属性和⽅法设置私有权限,即设置某个实例属性或实例⽅法不继承给⼦类。
故事:daqiu把技术传承给徒弟的同时,不想把⾃⼰的钱(2000000个亿)继承给徒弟,这个时候就
要为 钱 这个实例属性设置私有权限。
设置私有权限的⽅法:在属性名和⽅法名 前⾯ 加上两个下划线 __。

'''


class School(object):
    def __init__(self):
        self.kongfu = '[⿊⻢煎饼果⼦配⽅]'
        # 定义私有属性
        self.__money = 20000

    def make_cake(self):
        print(f'运⽤{self.kongfu}制作煎饼果⼦')

    def __print_info(self):
        print(f'运⽤{self.kongfu}制作煎饼果⼦')


class Prentice(School):
    pass


p = Prentice()
# print(p.money)    #  # AttributeError: 'Prentice' object has no attribute 'money'
# print(p.__money)    # AttributeError: 'Prentice' object has no attribute '__money'
# p.print_info()
# p.__print_info()

# 注意:私有属性和私有⽅法只能在类⾥⾯访问和修改。

'''
 获取和修改私有属性值
 在Python中,⼀般定义函数名 get_xx ⽤来获取私有属性,定义 set_xx ⽤来修改私有属性值。
'''

# class School(object):
#     def __init__(self):
#         self.kongfu = '[⿊⻢煎饼果⼦配⽅]'
#         # 定义私有属性
#         self.__money = 20000
#
#     # get set 是工作习惯
#     def get_money(self):
#         return self.__money
#
#     def set_money(self, money):
#         self.__money = money
#
#     def make_cake(self):
#         print(f'运⽤{self.kongfu}制作煎饼果⼦')
#
#     def __print_info(self):
#         print(f'运⽤{self.kongfu}制作煎饼果⼦')
#
#
# class Prentice(School):
#     pass
#
#
# p = Prentice()
# print(p.get_money())
# p.set_money(10)
# print(p.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()
#
#
# # print(Dog.tooth) # 10
# # print(wangcai.tooth) # 10
# # print(xiaohei.tooth) # 10
#
# '''
# 修改类属性
# 类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了
# ⼀个实例属性。
# '''
#
# Dog.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()


'''
异常
⽬标
了解异常
捕获异常
异常的else
异常finally
异常的传递
⾃定义异常
'''

'''
了解异常
当检测到⼀个错误时,解释器就⽆法继续执⾏了,反⽽出现了⼀些错误的提示,这就是所谓的"异常"。

异常的写法
语法
try:
 可能发⽣错误的代码
except:
 如果出现异常执⾏的代码
'''
'''
快速体验
需求:尝试以 r 模式打开⽂件,如果⽂件不存在,则以 w ⽅式打开。
'''

# f = open('testa.txt', 'r')

# try:
#     f = open('testa.txt','r')
# except:
#     f = open('testa.txt','w')


'''
捕获指定异常
语法
try:
 可能发⽣错误的代码
except 异常类型:
 如果捕获到该异常类型执⾏的代码
 
 注意:
1. 如果尝试执⾏的代码的异常类型和要捕获的异常类型不⼀致,则⽆法捕获异常。
2. ⼀般try下⽅只放⼀⾏尝试执⾏的代码。
'''

# print(num)  # NameError: name 'num' is not defined
# print(1/0) # ZeroDivisionError: division by zero

# try:
#     print(num)
# except NameError:
#     print('有错误')

'''
捕获多个指定异常
当捕获多个异常时,可以把要捕获的异常类型的名字,放到except 后,并使⽤元组的⽅式进⾏书写。
'''

# try:
#     print(1/0)
# except (NameError, ZeroDivisionError):
#     print('有错误')

# 捕获异常描述信息
# try:
#     print(1/0)
# except (NameError, ZeroDivisionError) as result:
#     print(result)

'''
捕获所有异常
Exception是所有程序异常类的⽗类。
'''

# try:
#     print(num)
# except Exception as result:
#     print(result)


'''
异常的else
else表示的是如果没有异常要执⾏的代码。
'''

# try:
#     print(1)
# except Exception as result:
#     print(result)
# else:
#     print('我是else,是没有异常时候执行的代码')


'''
异常的finally
finally表示的是⽆论是否异常都要执⾏的代码,例如关闭⽂件。
'''
# try:
#     f = open('testa.txt', 'r')
# except Exception as result:
#     f = open('testa.txt', 'w')
# else:
#     print('没有异常,真开⼼')
# finally:
#     f.close()
#
# print(f)  #<_io.TextIOWrapper name='testa.txt' mode='r' encoding='cp936'>


'''
命令提示符下运行python文件
C:\Workspace\python00\pythonbase>python 09.py
hello world
'''

'''
异常的传递

体验异常传递
需求:
1. 尝试只读⽅式打开test.txt⽂件,如果⽂件存在则读取⽂件内容,⽂件不存在则提示⽤户即可。
2. 读取内容要求:尝试循环读取内容,读取过程中如果检测到⽤户意外终⽌程序,则 except 捕获异常
并提示⽤户。
'''

'''
如下代码在命令行下测试最好
'''
# import time
#
# try:
#     f = open('test.txt')  # 默认以只读
#     try:
#         while True:
#             con = f.readline()
#             if len(con) == 0:
#                 break
#             print(con)
#             time.sleep(2)
#     except:
#         # 在命令行下ctrl + c 属于异常终止
#         print('程序意外终止')
#         '''
#         C:\Workspace\python00\pythonbase>python 面向对象和异常.py
#         aaaaa
#         程序以外终止
#         '''
# except:
#     print('文件不存在')


'''
⾃定义异常
在Python中,抛出⾃定义异常的语法为 raise 异常类对象 。

需求:密码⻓度不⾜,则报异常(⽤户输⼊密码,如果输⼊的⻓度不⾜3位,则报错,即抛出⾃定义异
常,并捕获该异常)。
'''
'''
1.自定义异常类
2.抛出异常
3.捕获异常
'''


# ⾃定义异常类,继承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:
        password = input('请输入密码:')
        if len(password) < 3:
            raise  ShortInputError(len(password),3)
    except Exception as result:
        print(result)
    else:
        print('密码已经输入完成')

main()
'''
模块和包
⽬标
    了解模块
    导⼊模块
    制作模块
    __all__
    包的使⽤⽅法

Python 模块(Module),是⼀个 Python ⽂件,以 .py 结尾,包含了 Python 对象定义和Python语句。
模块能定义函数,类和变量,模块⾥也能包含可执⾏的代码。
'''
# import my_module1

'''
导⼊模块
导⼊模块的⽅式
import 模块名
from 模块名 import 功能名
from 模块名 import *
import 模块名 as 别名
from 模块名 import 功能名 as 别名
'''

'''
导⼊⽅式详解
import
# 1. 导⼊模块
import 模块名  推荐一个一个导入
import 模块名1, 模块名2...  不推荐如此导入多个
# 2. 调⽤功能
模块名.功能名()
'''

# math sqrt 开平方

# import math
# print(math.sqrt(9))   # 3.0  python 中类似于除法计算都会以浮点型返回

# from  math import sqrt
# print(sqrt(9))

# from  math import *
# print(sqrt(9))

# as定义别名
# import math as mymath
# print(mymath.sqrt(9))

# from math import sqrt as mysqrt
# print(mysqrt(9))

# #  模块别名
# import time as tt
# tt.sleep(2)
# print('hello')

# # 功能别名
# from time import sleep as sl
# sl(2)
# print('hello')

'''
 制作模块
 在Python中,每个Python⽂件都可以作为⼀个模块,模块的名字就是⽂件的名字。也就是说⾃定义模
块名必须要符合标识符命名规则。
'''

'''
步骤
定义模块
新建⼀个Python⽂件,命名为 my_module1.py ,并定义 testA 函数。
测试模块
在实际开中,当⼀个开发⼈员编写完⼀个模块后,为了让模块能够在项⽬中达到想要的效果,这个开发
⼈员会⾃⾏在py⽂件中添加⼀些测试信息.,例如,在 my_module1.py ⽂件中添加测试代码。
调⽤模块
'''
'''
def testA(a, b):
    print( a + b)

# 测试信息,避免被引入其他模块而运行
if __name__ == '__main__':
    testA(3, 4)

# __name__ 是系统变量
# print(__name__)  # 在当前py文件中运行时,__name__ = __main__;当其他文件调用时 为模块名:my_module1'''

# import my_module1
# my_module1.testA(1, 3)


'''
模块定位顺序s
当导⼊⼀个模块,Python解析器对模块位置的搜索顺序是:
1. 当前⽬录
2. 如果不在当前⽬录,Python则搜索在shell变量PYTHONPATH下的每个⽬录。
3. 如果都找不到,Python会察看默认路径。UNIX下,默认路径⼀般为/usr/local/lib/python/
模块搜索路径存储在system模块的sys.path变量中。变量⾥包含当前⽬录,PYTHONPATH和由安装过
程决定的默认⽬录。
注意
    ⾃⼰的⽂件名不要和已有模块名重复,否则导致模块功能⽆法使⽤
    使⽤from 模块名 import 功能 的时候,如果功能名字重复,调⽤到的是最后定义或导⼊的功能。
'''
'''
编写random.py
'''

# import  random
# num = random.randint(0,10)
# print(num)


# # def sleep():
# #     print('我是自定义的sleep')
#
# from time import  sleep
#
# def sleep():
#     print('我是自定义的sleep')
#
# sleep(2)

# 名字重复的麻烦:
# 问题: import 模块名 是否担心 功能名字重复的问题 -- 不需要担心 模块.方法 区别

# import time
# print(time)
#
# time = 1
# print(time)

# 问题 为什么变量也能覆盖模块 -- 在python语言中,数据是通过引用 传递


'''
 __all__ __all__
如果⼀个模块⽂件中有 __all__ 变量,当使⽤ from xxx import * 导⼊时,只能导⼊这个列表中的元
素。
'''

# from  my_module1 import *
#
# testA(1,4)
# # testB(1,4)  # 因为testB不在all列表中 NameError: name 'testB' is not defined

'''
__all__ = ['testA']

def testA(a, b):
    print( a + b)
    print('testA')

def testB(a, b):
    print( a + b)
    print('testB')

# 测试信息
if __name__ == '__main__':
    testA(3, 4)

# __name__ 是系统变量
# print(__name__)  # 在当前py文件中运行时,__name__ = __main__;当其他文件调用时 为模块名:my_module1
'''

'''
包
包将有联系的模块组织在⼀起,即放到同⼀个⽂件夹下,并且在这个⽂件夹创建⼀个名字
为 __init__.py ⽂件,那么这个⽂件夹就称之为包。
'''

'''
制作包
[New] — [Python Package] — 输⼊包名 — [OK] — 新建功能模块(有联系的模块)。
注意:新建包后,包内部会⾃动创建 __init__.py ⽂件,这个⽂件控制着包的导⼊⾏为。
'''

'''
快速体验
1. 新建包 mypackage
2. 新建包内模块: my_module1 和 my_module2
3. 模块内代码如下
'''

'''
导⼊包
2.2.1 ⽅法⼀
import 包名.模块名
包名.模块名.⽬标
'''

# import mypackage.my_module2
# mypackage.my_module2.info_print()

'''
 ⽅法⼆
注意:必须在 __init__.py ⽂件中添加 __all__ = [] ,控制允许导⼊的模块列表。
from 包名 import *
模块名.⽬标

'''

from mypackage import *
# my_module2.info_print()   # 注释 __init__后 NameError: name 'my_module2' is not defined


'''
__dict__ 收集类对象和实例对象的属性字典
'''
# 1. 定义类
class A(object):
    a = 0

    def __init__(self):
        self.b = 1

# 2. 创建对象
aa = A()

# 3. 调用__dict__
print(A.__dict__)

print(aa.__dict__)

 my_module1.py

__all__ = ['testA']

def testA(a, b):
    print( a + b)
    print('testA')

def testB(a, b):
    print( a + b)
    print('testB')

# 测试信息
if __name__ == '__main__':
    testA(3, 4)

# __name__ 是系统变量
# print(__name__)  # 在当前py文件中运行时,__name__ = __main__;当其他文件调用时 为模块名:my_module1

 

posted @ 2021-10-10 23:41  星回中道  阅读(202)  评论(0编辑  收藏  举报