Python基础

python基础

python注释

1.注释的分类

(1) 单行注释

# print 是一个打印函数 python2x  print "hello world"
# print 是一个打印函数 python3x  print("hello world")

(2) 多行注释 (三个单引号 或者 三个双引号)

'''
print("一表人才")
print("相貌堂堂")
print("鼻如悬胆")
print("疯牛踢躺")
print("婀娜多姿")
print("一脸猥琐")
'''

"""
print("一表人才")
print("相貌堂堂")
print("鼻如悬胆")
print("疯牛踢躺")
print("婀娜多姿")
print("一脸猥琐")
"""

2.注释的注意点: (注释的嵌套)

注意:注释嵌套的时候,外面是三个双引号,里面用三个单引号,外面是三个单引号,里面用三个双引号

'''
print("一表人才")
print("相貌堂堂")
print("鼻如悬胆")
"""
print("疯牛踢躺")
"""
print("婀娜多姿")
print("一脸猥琐")
'''

"""
print("陈全鸡,一表人才")
print("张旭,相貌堂堂")
print("谢诗科,鼻如悬胆")
print("王博,疯牛踢躺")
'''
print("陈梦洁,婀娜多姿")
'''
print("柯虎,一脸猥琐")
"""

3.注释的排错性 (注释一部分代码,执行另外一部分代码进行测试,以此类推)

print("还等什么?")
# print(hello world)
print("hello world")

print("python")

python 变量

变量:可以改变的量,具体指的石内存的一段空间

(1)变量的含义

ruojia = "opesn"
ruojia = "hello world"
print(ruojia)

(2)变量的声明

#(1)
a = 1
b = 2
print(a,b)

#(2)
a,b = 3,4
print(a,b)

#(3)
a = b = 33
print(a,b)

(3)变量的命名

'''
		变量的命名
字母数字下划线, 首字符不能为数字
严格区分大小写, 且不能使用关键字
变量命名有意义, 且不能使用中文哦
'''

rujia305 = "a"
print(rujia305)
_abde = 'c'
a333444 = 1
# 3344_qqqq =2
abc = 1
abC = 2
print(abc)
print(abC)


## 以为下关键字不能声明为变量名
import keyword
res = keyword.kwlist
print(res)
'''
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
'''


中文 = 12434
print(中文)
'''
UTF-8 国际标准编码(可变长的unicode编码集) 万国码   一个中文代表3个字节 一个英文或者符号代表一个字节
gbk   国标编码  一个中文代表2个字节. 一个英文或者符号代表一个字节
'''

'''
中文命名变量,在语法上允许,但严禁使用
'''

(4)变量的交换

a = 10
b = 11
a,b = b,a
print(a,b)

# 变量的交换通用写法
a = 33
b = 55
tmp = a
a = b
b = tmp
print(a,b)


# 身份证号是一个典型的常量
MYID = "210201199810106666"

python 六大数据类型

(1)Number   数字类型(int  float  bool  complex)
(2)String	字符串类型
(3)List		列表类型
(4)Tuple	元组类型
(5)Set		集合类型
(6)Dict		字典类型

->(1)Number 	数字类型分类
int :    		整数类型    (正整数[各种进制] 负整数 0)
float:   		浮点数类型  (1普通小数 2科学计数法表示的小数 例:a = 3e-5  #3e-05 )
bool:    		布尔值类型  (真True和假False)
complex: 		复数类型    (声明复数的2种方法) (复数用作于科学计算中,表示高精度的数据,科学家会使用)	

Number 数字类型

int 整数类型

# ###Number (int)
# 整型 :(正整数 0 负整数)

# 二进制用0b表示
intvar = 0b1010
print(intvar)
print(type(intvar))
print(id(intvar))
# type 可以获取到变量的类型
# id   可以获取该变量所指向的那个值得地址

# 八进制用0o来表示
intvar = 0o127
print(intvar)
print(type(intvar))
print(id(intvar))

# 十六进制用0x来表示
intvar = 0xff
print(intvar)
print(type(intvar))
print(id(intvar))

intvar = 0
print(intvar,type(intvar),id(intvar))

intvar = -99
print(intvar,type(intvar),id(intvar))

float 浮点数类型

# ###Number (float)
# float 浮点型(小数类型)

# 表示方法一
floatvar = 3.14
print(floatvar,type(floatvar),id(floatvar))
# 表示方法二 (科学计数法)
floatvar = 5.88e-2
print(floatvar,type(floatvar),id(floatvar))

floatvar = 4.11e3
print(floatvar,type(floatvar),id(floatvar))

bool 布尔值类型

# bool 布尔类型 (True False)
boolvar = True
print(boolvar,type(boolvar),id(boolvar))
boolvar = False
print(boolvar,type(boolvar),id(boolvar))

complex 复数类型

'''
复数: 实数 + 虚数 组成的
j : 如果有一个数,他的平方等于-1,那么这个数就是j
科学家认为有。属于高精度的类型
'''

# 表示方法一
complexvar = 4+3j
print(complexvar,type(complexvar),id(complexvar))
complexvar = 4j
print(complexvar,type(complexvar),id(complexvar))

# 表示方法二
# complex(实数,虚数)
complexvar = complex(8,-3)
print(complexvar,type(complexvar),id(complexvar))

String 字符串类型

# 用引号引起来的就是字符串 '' "" '''
'''
转义字符:
(1)将有意义的字符变得无意义
(2)将无意义的字符变得有意义

语法: \ + 某个字符

\n,\r\n: 代表换行
\t: 代表一个缩进 水平制表符
\r: 将\r后面的字符串拉倒当前行首
'''

# ###字符串的特性:可获取,不可修改,有序
strvar = "人生苦短,我用python"
res = strvar[-1]
print(res)
# 字符串不能够修改
'''
strvar[-1] = 's'
print(strvar)
'''

(1)单引号引起来的字符串

strvar = "今天天气有雾霾"
print(strvar,type(strvar),id(strvar))

(2)双引号引起来的字符串

strvar = "小楼昨夜又东风"
strvar = "小楼昨'夜'又东风" # 外面是双引号,里面需要单引号,与注释的嵌套注意点相同
strvar = "故国不堪回首\n月明中"
strvar = "故国不堪回首\r\n月明中"
strvar = "故国不堪回首\t月明中"
strvar = "故国不堪\n回首\r月明中"
strvar = "故国不堪回\"首\"月明中"  # 将有意义的双引号变得无意义
print(strvar,type(strvar),id(strvar))

(3)三引号引起来的字符串 (三引号字符串,支持跨行操作)

strvar = """
本来无一'物',
何处惹尘"埃"。
"""
print(strvar)

strvar = '''
床前明月光,
地上鞋两双
'''
print(strvar)

(4)元字符串 r + "字符串" (让字符串里面的转义字符失效)

strvar = r"今天拉肚\r子\t了\n么?"
print(strvar)

(5)字符串的格式化

"""
%d : 整型占位符  
%f :浮点型占位符
%s :字符串占位符

语法: 字符串  %  (值1,值2,。。。。。)  
"""

# %d 
strvar = "昨天买了%d 个娃娃" %(5)
print(strvar)
# %2d 站两个位置,默认居右
strvar = "昨天买了%2d个娃娃" %(5)
print(strvar)
# %-4d 站两个位置,默认居左
strvar = "昨天买了%-4d个娃娃" %(5)
print(strvar)

# %f 小数点后默认精度保留6位
strvar = "华为出了一款折叠手机,价格为%f" %(9.99)
print(strvar)
# %f 精确位数的时候,存在四舍五入
strvar = "华为出了一款折叠手机,价格为%.2f" %(9.99)
print(strvar)

# %s
strvar = "python"
strvar = "%s" %(strvar)
print(strvar)

# 综合案例
strvar = "开工资了,一共%.2f,看好了一辆车,价格%d元,心情在%s" % (9.99,10,"崩溃的边缘")
print(strvar)

List 列表类型

# ###列表的特性:可获取,可修改,有序

# 声明一个空列表
listvar = []
print(listvar,type(listvar))

# (1)列表的获取
#          0   1    2     3     4      5
listvar = [5,False,2-4j,5.16,"python","Go"]
#         -6  -5   -4    -3    -2     -1
res = listvar[4]
res = listvar[-1]
print(res)


# len 计算容器类型的长度 (元素的个数)
lengthvar = len(listvar)
print(lengthvar)
res = listvar[lengthvar-1] #listvar[5]
print(res)

# (2)列表的修改
listvar = [5,False,2-4j,5.16,"python","Go"]
listvar[-2] = "java"
print(listvar)
listvar[1] = True
print(listvar)

Tuple 元组类型

# ###元组的特性:可获取,不可修改,有序
# 区分是否是元组的标志性符号是逗号,声明一个空元组可以用()
tuplevar = ()
print(tuplevar,type(tuplevar))
tuplevar = (1,)
print(tuplevar,type(tuplevar))
tuplevar = 1,2,3
print(tuplevar,type(tuplevar))

# 元组的获取
tuplevar = ("python","shell","java","Go","vue")
res = tuplevar[1]
print(res)

# error 元组不能够修改
'''
tuplevar[-1] = 123
print(tuplevar)
'''

Set 集合类型

# ###集合特征: 自动去重,无序
# 集合的用途,用于做交集,差集,并集,补给(做交叉并补的)

# 1.集合无序
setvar = {"pthon","java","Go","shell"}
print(setvar)

# (1) 无法通过索引获取值
# print(setvar[0])
# (2) 无法通过索引修改值
# setvar[1] = "123"

# 2.集合自动去重
setvar = {"pthon","java","Go","shell","shell"}
print(setvar)

3.定义一个空集合
setvar = {}
print(setvar,type(setvar))  # 空字典,不是空集合
setvar = set()
print(setvar,type(setvar))

# setvar = {[1,2,3]}
# setvar = {{"a":1}}
# setvar = {{1,2,3}}
# setvar = {(1,2,3),"333",(4,5,6)}
setvar = {(1,2,(4,5,6)),"333",(4,5,6)}
print(setvar)

Dict 字典类型

# ###字典特征:键值对存储的数据,有序
'''键和值之间用冒号隔开,键值对之间用逗号隔开'''

'''
哈希算法
把不可变的任意长度值计算成固定长度的唯一值
这个值可正可负,可大可小,通过算出的数,可以获取到对应的值,形成一种映射关系
把这个算法叫做哈希算法,把这个值叫做哈希值

对于字典来讲,里面的键底层就是通过哈希算法计算出来的,
哈希算法不能保证插入内存的数据和字典的字面顺序一致,所以本质上,字典是无序的
3.6版本,把字典的字面顺序记录下来,在从内存拿去数据的时候,根据字面顺序重新排序,所以看起来像有序
3.6版本之前都是无序的,3.6版本经过算法优化变成有序,但本质上无序



可哈希的数据  (不可变的数据):Number(int float bool complex) str tuple
不可哈希的数据 (可变的数据): list set dict

'''

# 语法: dictvar = {"a":1,"b":2,"c":3}
dictvar = {"top":"程咬金","middle":"安其拉","bottom":"鲁班七号",'jungle':"达摩","support":"蔡文姬"}
print(dictvar)

# 获取字典当中的值
res = dictvar['bottom']
res = dictvar['jungle']
print(res)

# 修改字典当中的值
dictvar['support'] = "庄周"
print(dictvar)

# 字典键必须可哈希
'''在命名字典键的时候,推荐使用字符串,按照变量命名的方式来做'''
dictvar = {1:1,(1,2,3):3,False:4,3.14:999,4-2j:888,"opesn":"hello"}
print(dictvar)

变量的缓存机制

同一文件,变量的缓存机制

# ###同一文件,变量的缓存机制
'''
-->Number 部分
1.对于整型而言,-5~正无穷范围内的相同值 id一致
2.对于浮点数而言,非负数范围内的相同值 id一致
3.布尔值而言,值相同情况下,id一致
4.复数的id标识都不相同(在 实数+虚数 这样的结构中)
'''

# int -5 ~ 正无穷
var1 = 666
var2 = 666
var1 = -6
var2 = -6
print(id(var1))
print(id(var2))

# float  非负数范围
var1 = 3.14
var2 = 3.14
var1 = -3.14
var2 = -3.14
print(id(var1))
print(id(var2))


# bool True False
var1 = True
var2 = False
var1 = True
var2 = True
print(id(var1))
print(id(var2))

# complex  在实数+虚数 情况下都不相同
var1 = 5+3j
var2 = 5+3j
print(id(var1),id(var2))
# 只有虚数例外
var1 = 5j
var2 = 5j
print(id(var1),id(var2))


'''
-->容器类型部分
5.字符串而言,字符串值相同情况下,id一致
6.列表,元组,字典,集合无论什么情况 id标识都不同(但空元组的id标识一样)
'''
var1 = "你"
var2 = "你"
print(id(var1),id(var2))

var1 = ()
var2 = ()
print(id(var1),id(var2))

var1 = [1,2]
var2 = [1,2]
var1 = {1,2,"你好"}
var2 = {1,2,"你好"}
print(id(var1),id(var2))

自动类型转换

# ### 自动类型转换 Number(int bool float complex) 数据类型中
'''
Number 精度从低到高 依次是 bool  ->  int  ->  float  ->  complex
最后的值向更高精度转换
'''

# bool + int 
var1 = True
var2 = 5
res = var1 + var2
print(res)

# bool + float
var1 = True
var2 = 5.66
res = var1 + var2
print(res)

# bool + complex
var1 = False
var2 = 4-2j
res = var1 + var2
print(res)

# int + float
var1 = 6
var2 = 20.55
print(var1+var2)

# int + complex
var1 = 12
var2 = 4+9j
print(var1+var2)


# float + complex
var1 = 5.888
var2 = 5-1j
print(var1+var2)

Number 数据类型的强制转换

var1 = 45
var2 = 6.78
var3 = "12345676"
var4 = "nihao223"
var5 = 88-2j
var6 = True
var7 = False

# int 强制类型转换整型  True 强转int是1  False 强转int 是0
res = int(var2)
res = int(var6)
res = int(var7)
res = int(var3)
# res = int(var4) error
# res = int(var5) error 
print(res)

# float 强制转换成浮点型
res = float(var1)
res = float(var3)
res = float(var6)
res = float(var7)
print(res)

# complex 强制转换成复数
res = complex(var1)
res = complex(var2)
res = complex(var3)
res = complex(var6)
res = complex(var7)
print(res)

# bool 强制转换成布尔类型
res = bool(var1)
res = bool(var4)
res = bool(var5)
res = bool({1,2,3})
res = bool(None)
print("<===>")
print(res)

# 通过bool强制转换为假的10个数据
'''
0 , 0.0 , 0j ,False , [] ,() , "" ,set() ,{} , None
None 是一个关键字 本身代表空的 什么也没有
'''
age = None
sex = None

'''
int() float() bool() complex() 默认声明一个当前类型的数据
'''
a = int()
b = float()
c = bool()
d = complex()
print(a,b,c,d)

容器类型的强制转换

# ###容器类型的强制转换 ( str list tuple set dict)
var1 = "人生苦短,我用python"
var2 = ["Vue","html"]
var3 = ("python","shell","Go")
var4 = {"红色的帽子","蓝色的帽子","绿色的帽子"}
var5 = {"cjx":"昨天请假了","lyf":"世界上最美的不过是回眸一笑","chp":"每次看你,都都出了猥琐的小眼神"}
var6 = 5488

# str ( 容器类型数据  /  Number类型数据 都可以 )
'''基于原来的数据类型两边套上引号'''
res = str(var2)
res = str(var3)
res = str(var4)
res = str(var5)
res = str(var6)
print(res,type(res))
print(repr(res)) #原型化输出字符串

# list 强转
'''
如果是列表强转字符串 ,把字符串中的每一个字符都当成新的元素放入列表当中
如果是其他容器类型数据,仅仅在套一个[],作为列表标识  字典单独记 只要键 不要值
'''
res = list(var1)
res = list(var3)
res = list(var4)
res = list(var5) # 强转字典时,只保留键,舍弃值
print(res)

# tuple
'''
如果是元组强转字符串 ,把字符串中的每一个字符都当成新的元素放入元组当中
如果是其他容器类型数据,仅仅在套一个(),作为元组标识  字典单独记 只要键 不要值
'''
res = tuple(var1)
res = tuple(var2)
res = tuple(var4)
res = tuple(var5)
print(res)

# set
'''
如果是集合强转字符串 ,把字符串中的每一个字符都当成新的元素放入集合当中,但是注意集合无序 , 自动去重
如果是其他容器类型数据,仅仅在套一个{},作为集合标识  字典单独记 只要键 不要值 注意集合无序 , 自动去重
'''
res = set(var1)
res = set(var2)
res = set(var3)
res = set(var5)
res = set()
print(res)

# 对列表进行去重
listvar = ["python","Go","shell","java","java","java"]
setvar = set(listvar)
listvar2 = list(setvar)
print(listvar2)

字典强转等长二级容器

# ###二级容器: 自己本身是一个容器,里面的元素还是一个容器类型数据 (list tuple set dict)

# 二级列表:
listvar = [1,2,3,4,[5,6,7,8]]
res = listvar[-1][-1]
print(res)

# 二级元组:
tuplevar = (11,222,33,44,(1,2,3),55)
res = tuplevar[4][1]
print(res)

# 二级集合:
setvar = {1,2,3,4,(5,6,7,8)} # 集合里面放的数据需要可哈希(不可变的)的数据
print(setvar)

# 二级字典
dictvar = {"a":{"c":444},"b":{"d":5555}}
res = dictvar["b"]
print(res)
res = dictvar["b"]['d']
print(res)

# 四级容器
listvar = [1,2,3,4,[5,56,7,89,(99,101,103,1555,{"a":1,"b":2})]]
res = listvar[-1][-1][-1]['a']
print(res)

# 等长的二级容器  : 里面都是容器类型数据,每个容器里面元素个数都一样
listvar = [(1,2,3),(4,5,6)]
listvar2 = ([1,2],[4,5],[11,99])

# ### 强转字典 必须是等长的二级容器,并且里面元素的个数是2个
# (1) 外面是列表 ,  里面是列表或元组或字符串 (不推荐字符串,有局限性)
listvar = [("a",1),("b",2)]
listvar = [["c",3],("d",4)]
listvar = ["e1","f2"]
listvar = [('a1',1),['b2',2],"c3"]
res = dict(listvar)
print(res)

# (2) 外面是元组 , 里面是列表或元组或字符串 (不推荐字符串,有局限性)
tuplevar = (["ccc",111],('aaaa',2222))
res = dict(tuplevar)
print(res)

# (3) 外面是集合,里面是元组或字符串
setvar = {('a',11),('b',22),"c3"}
dictvar = dict(setvar)
print(dictvar)

# 不推荐使用集合,因为集合无序,达不到想要的效果
'''
listvar = [{"a",1},{"b",2}]
tuplevar = ({"a",1},{"b",2})
dictvar = dict(listvar)
dictvar = dict(tuplevar)
print(dictvar)
'''

'''
str() list() tuple() set() dict() 都可以强转成对应的类型
'''
print("<==1=-=>")
res = str()
print(repr(res))
res2 = list()
print(res2)
res3 = tuple()
res3 = set()
res3 = dict()
print(res3)

python 运算符

算数运算符

# 1. 算数运算符:  + - * / // (地板除) % **(幂运算)

var1 = 7
var2 = 4

# +
res = var1 + var2
print(res)

# -
res = var1 -var2
print(res)

# *
res = var1 * var2
print(res)

# / (结果是一个小数)
res = var1 / var2
res = 8 / 8
print(res)

# // (取整数) 两个数在进行地板除的时候,有一个数是小数,就在最后的结果上加.0
res = var1 // var2
res = 8 // 8
res = 28.7 // 5
print("<===>")
res = 28 // 5.3
print(res)

# %
res = var1 % var2
res = 99 % 7
# -1 + 7 = 6 (余数)
res = -99 % 7 
# 1 + (-7) = -6 (余数)
res = 99 % -7
print(res)

# **   var1 * var1 * var1  7*7*7  **是所有运算符 优先级最高的一个
res = var1 ** 3
print(res)

比较运算符

# ###(2)比较运算符:  > < >= <= == != 
'''比较运算符只会产生2个结果  要么True 要么False'''

# > 
var1 = 15
var2 = 18
res = var1 > var2
print(res)

# <
res = var1 < var2
print(res)

# >=  只要满足一个条件即为真
res = var1 >= 15
print(res)

# <=
res = var1 <= 15
print(res)

# == 
res = var1 == var2
print(res)

# != 
res = var1 != var2
print(res)

赋值运算符

# ### 3.赋值运算符  = += -= *= /= //= %= **=

# = 所有运算符当中 等号的优先级最低
var1 = 9
var2 = 5
res = var1
print(res)

# +=
var1 += var2
'''var1 = var1 + var2'''
print(var1)

# -=
var1 -= var2
'''var1 = var1 - var2'''
print(var1)

# *=
var1 *= var2
'''var1 = var1 * var2'''
print(var1)

# /=
var1 /= var2
'''var1 = var1 / var2'''
print(var1)

# //=
var1 //= var2
'''var1 = var1 // var2'''
print(var1)

# %=
var1 %= var2
'''var1 = var1 % var2'''
print(var1)

# **=
var1 **= var2
'''var1 = var1 ** var2'''
print(var1)

成员运算符

# ###4.成员运算符  in    not in 针对于容器类型数据

# str  字符串需要是一个连续的片段
strvar = "人生苦短,我用python"
res = "人" in strvar
res = "生" not in strvar
res = "python" in strvar
print(res)

# list tuple set
listvar = ["python","java","shell"]
res = "python" in listvar
print(res)

tuplevar = "python","java","GO","shell"
res = "GO" not in tuplevar
print(res)

setvar = {'python','shell'}
res =  "shell" in  setvar
print(res)

# dict  注意 : 判断的是键 不是值
dictvar = {"zdx":"python","gss":"shell","mlh":"java"}

身份运算符

# ### 身份运算符  is  is not
"""
var1 = 56
var2 = 56
res = var1 == var2  (判断两个值是否相等)
res = var1 is var2  (判断两个值得地址是否相等)
"""

# Number
# int -5 ~ 正无穷
var1 = 56
var2 = 56
res = var1 is var2
print(res)

# float 非负数
var1 = -99
var2 = -99
print(var1 is not var2)

# bool 
var1 = True
var2 = False
print(var1 is var2)

# complex
var1 = 5+6j
var2 = 5+6j
print(var1 is not var2)

# 容器类型数据  () 、字符串相同 剩下所有的容器类型数据地址都不一样
var1 = ()
var2 = ()
print(var1 is  var2)
var1 = "机"
var2 = "机"
print(var1 is not var2)

逻辑运算符

# ### 6. 逻辑运算符 (and or not)
# (1)and 逻辑与
'''全真则真,一假则假'''
res = True and True 
res = False and True
res = False and False
res = True and 

# (2)or 逻辑或
'''全假则假,一真则真'''
res = True or True
res = True or False
res = False or True
res = False or False
print(res)

# (3)not 逻辑非  相当于取反
res = not True
res = not False
print(res)


# (4)逻辑短路
'''
False and 布尔 在and左边如果时False 逻辑短路 右侧不执行
True or 布尔   在or左边如果是True  逻辑短路 右侧不执行
在开发当中 ,当成"开关"使用
# res = False and False
'''
False and  print(123) #逻辑短路
True or print(456)  #逻辑短路
True and print(789)
# res = print(456)
# print(res)

# 逻辑运算符的优先级 
''' () > not > and > or '''
# res = 6 and 7
# res = True and  True
# print(res)
# res = 5 or 6 and 7
# res = 5 or True
# res = 5 or True
# (1)
res = 5 or 6 and 7
print(res)
# (2)
res = (5 or 6) and 7
print(res)
# (3) 
res = not(5 or 6) and 7
print(res) # False
'''
5 or 6 => 5
not 5 and 7
False and 7
'''
# (4)
res = 3>1 or 4<5 and 6>9 or 8==10
# True or True and False or False
# True or False or False 
# True or False 
print(res)

# 数据类型的判断 isinstance
'''
isinstance(要判断的值,(数据类型1,数据类型2,数据类型3,.....))
最终的返回值要么是True 要么是False
int float bool complex str list set tuple dict
'''
var1 = 6
res = isinstance(var1,int)
print(res)
var2 = "你好"
# 只要类型元组里面含有这个数据类型,即为真
res = isinstance(var2,(set,list,tuple))
print(res)

位运算符

# ### 7.位运算符 (& |  ^ << >> ~)
var1 = 19
var2 = 15

# 按位与 &
res = var1 & var2
print(res)
"""
	000000010011
	000000001111
	000000000011
"""

# 按位或 |
res = var1 | var2
print(res)
'''
	000000010011
	000000001111
	000000011111
'''

# 按位异或 ^ "如果两者不相同,返回真,两者相同返回假
res = var1 ^ var2
print(res)
'''
	000000010011
	000000001111  
    000000011100
'''

# <<  相当于 5 乘以 2的2次幂
res = 5 << 2
res = 4 << 3
print(res) # 20 
"""
000000101
000010100
"""

# >>  相当于 5 除以 2的1次幂
res = 5 >> 1
print(res)
"""
0000101
0000010
"""

# ~ 按位非 (针对于补码来进行操作 ,连符号位都要改变) 公式 -(n+1)
res = ~19
print(res)
"""
000000000010011 (补码)
111111111101100 (按位非)

111111111101100  (给补码求原码)
100000000010011  (反码)
100000000010100  (原码)  => -20
"""

res = ~(-19)
print(res)
'''
100000000010011  (原码)
111111111101100  (反码)
111111111101101  (补码)

按位非操作的是补码
111111111101101  (补码)
000000000010010  (按位非得值)

000000000010010  (原码 == 反码 == 补码)
'''

运算符的优先级

"""
所有运算符的优先级:
(1) 小括号的优先级最高 ()     => (3+3)*5
(2) 
一元运算符:同一时间操作一个数的 ( ~ , - ) -6
二元运算符: 同一时间操作二个数的 

** 符号优先级最高
=  符号优先级最低

整体来说,一元运算符优先级大于二元运算符 , ** 除外
乘,除 > 加减
() > not > and > or 
(<< >> ) > & > ^ > |


除此之外剩下的运算符参考以下:
算术运算符 > 位运算符 > 比较运算符 > 身份运算符 > 成员运算符 > 逻辑运算符
赋值运算符单独拿出来 , 用来把最后的结果进行赋值的
"""

"""
res = 5+5 << 6 // 3 is 40 and True 
res = 5+5 << 2 is 40 and True
res = 10 << 2 is 40 and True
res = 40 is 40 and True 
res = True and True 
res = True
print(res)
"""

python 代码块

# ### 代码块:  以冒号作为开始,用缩进来划分作用域,代表一个整体,是一个代码块。一个文件(模块)也可以称为一个代码块
# ### 作用域:作用的范围
print(11)
print(22)
print(33)


if True:
	print(1)
	print(2)
	print(3)
	
if False :
	print(4)
	print(5)
print(6)

# 代码块的注意点;
'''
	一个tab缩进 和 4个空格 看起来距离一样,但不是同一个缩进,要么全都是用tab,要么全都是用4个空格
'''
if True:
	print(7)
	print(8)
	
	
# php js java ...
if(True){
print(9)
																																								print(10)

}

python 流程控制if

# ### 流程控制 : 
'''
流程: 代码执行的过程
流程控制:对代码执行过程的管控


顺序结构:代码默认从上到下依次执行
分支结构:4个
循环结构:while  for .. in ..

分支结构:
	(1) 单项分支
	(2) 双项分支
	(3) 多项分支
	(4) 巢状分支
	
	
	
if 条件表达式 :
	code1 ...
	code2 ...
如果条件表达式为真 ,则执行代码块里面的内容从上到下
'''

# 单项分支
chen_mengjie =  "小仙女"
if chen_mengjie == "小仙女":
	print("我就给他买好吃的")
	print("我就给他买好喝的")
	print("我就给他买好玩的")
	print("我就给他买包,因为包治百病")
    
    
# 双项分支
'''
if 条件表达式:
	code1..
	code2 ...
	...
else:
	code3
	code4
	
如果条件表达式成立,则执行if这个区间的代码块
如果条件表达式不成立,则执行else这个区间的代码块
if这个区间的代码块叫做真区间
else这个区间的代码块叫做假区间	
'''

# 双项分支 (二选一)
chen_mengjie = "少妇"
if chen_mengjie == "绿巨人":  # if False 
	print("不可描述。。。")
else:
	print("给她买布加迪威龙")
	print("给他买雅诗兰黛")
	print("给他买倩碧")
	print("给他买兰蔻")
	print("给他买香奈儿")

    
# input 等待用户输入一个值,注意得到的值是一个字符串类型的
# res = input("请输入你的姓名:")  # res = '3119'
# print(res,type(res))	

'''
	提示用户输入用户名和密码:
	如果用户名是admin , 并且密码是000 , 
	提示用户恭喜你,登陆成功
	否则提示用户名或密码错误
'''
username = input("请输入用户名:")
password = input("请输入密码:")
print(username,password)
if username == "admin"  and  password == "000" :
	print("恭喜你,登陆成功!")
else:
	print("用户名或密码错误!")
   

# ###多项分支
"""
if 条件表达式1:
	code1
	code2
elif 条件表达式2:
	code1 
	code2 
elif 条件表达式3:
	code3
else:
	code4
	
判断 条件表达式1 是否成立 ,如果成立执行代码块1,如果不成立向下执行
判断 条件表达式2 是否成立 ,如果成立执行代码块2,如果不成立向下执行
判断 条件表达式3 是否成立 ,如果成立执行代码块3,如果不成立向下执行
依次类推..  直到最后 一个条件都不满足
执行最后的else 区间

是一个典型的多选一的结构:必须选一个,剩下的条件分支就不执行了
 **elif 可以写多个或不写
 **else 只能写一个或不写
"""
youqian = False
youfang = True
youche = True
youyanzhi = True
youtili = True

if youqian == True:
	print('hello world 1')
elif youfang == True:
	print('hello world 2')
elif youche == True:
	print('hello world 3')
elif youyanzhi == True:
	print("hello world 4")
elif youtili == True:
	print('hello world 5')
else:
	print('脑弟快走吧,一会好赶不上二路汽车了6')
    

# 巢状分支 (单项分支 双向分支 多项分支 互相的嵌套)
print("<=-=-=>")
youqian = True
youfang = True
youche = False
youyanzhi = True
youtili = False

# 注意数前面的缩进 来判断是否是同一代码块
if youqian == True:
	if youfang == True:
		if youche == True:
			if youyanzhi == True:
				if youtili == True:
					print("恭喜你~ 牵手成功~")
				else:
					print("恭喜你~ 成为我的1号备胎")
			else:
				print("老弟你等等,我们相约98,大约在冬季")
else:
	print("老弟,快走不送")
    

#女生找对象
	# 男生在1米~1.5米之间 小强 你在哪里?
	# 男生在1.5~1.7米之间 没有安全感~
	# 男生 1.7~ 1.8米之间 帅哥 留个电话
	# 男生 1.8~2米之间 帅哥 你建议多一个女朋友吗

height = float(input("请输入您的身高:~"))
# print(height,type(height))

"""
# 这个写法只适用于python
if  1 <= height <=1.5:
	print("小强 你在哪里?")
elif 1.5 < height <= 1.7:
	print("没有安全感~")
elif 1.7 < height <= 1.8:
	print("帅哥 留个电话")
elif 1.8 < height <=2:
	print("帅哥 你建议多一个女朋友吗")
else:
	print("身高刚到你的腰,我们并不合适")
"""

# 通用写法
if  height >= 1  and  height <= 1.5:
	print("小强 你在哪里?")
elif height > 1.5 and height <= 1.7:
	print("没有安全感~")
elif height > 1.7 and  height <= 1.8:
	print("帅哥 留个电话")
elif height>1.8 and height<=2:
	print("帅哥 你建议多一个女朋友吗")
else:
	print("身高刚到你的腰,我们并不合适")

python 循环结构while

# ### 循环结构 : while  for .. in 

'''
循环结构的特点:减少代码的冗余,提高代码的效率
语法形式:
while 条件表达式:
	code1 
	code2
'''

# 打印1~100
# 定义一个初始化的变量
i = 1
# 写一个循环的条件
while i<=100 :
	#代码体,写逻辑
	print(i)
# 写自增自减的条件  (防止死循环)
	i+=1  # i = i+1
"""
16: 1 <= 100 返回True 条件成立执行循环体
18:打印当前i
21:i = i+1  i=2 因为是循环 回到第16行继续判断

16:2<= 100 返回True 条件成立执行循环体
18: 打印当前i
21:i = i+1  i=3 因为是循环 回到第16行继续判断

16: 3<=100 返回True 条件成立执行循环体
18: 打印当前i
21:i = i+1  i=4 因为是循环 回到第16行继续判断

。。。依次类推

什么时候结束?
当i = 100的时候进来
打印100
i = 100 + 1 = 101 因为是循环 回到第16行继续判断
101 <= 100 ? 返回False 不执行 跳出循环 到此结束
"""

# 计算1~100的累加和 ?
i=1
total = 0

while i<=100:
	# print(i)
	# total = total + i #<==>  total += i
	total += i
	i+=1
print(total)
"""
51: i = 1   1 <= 100   返回True
53:total = 0+1  total = 1
54: i+=1  i=2 因为是循环 回到51行进行判断


51:i = 2  2 <= 100 返回True
53:total = 0+1+2 total = 3
54: i+=1  i=3 因为是循环 回到51行进行判断

51:i = 3  3 <= 100 返回True
53:total = 0+1+2 + 3 total = 6
54: i+=1  i=4 因为是循环 回到51行进行判断

...
...
...

算到最后:
total = 0+1 +2 +3+4+5+.... 100  =>5050
i = 101  101 <= 100 返回False 循环条件不满足,循环终止

"""


# 方法二 
i = 1
total = 0
flag = True

# 修改flag的标识
while flag:
	total += i
	i+=1
	# 当i位101的时候,为了避免在回到循环判断中,直接在此处终止
	if i  == 101:
		flag = False
	
print(total)

# 死循环
# while True:
	# print(1)

循环判断练习

# 打印一行十个小星星
help(print)

# end = "" 打印的字符末尾加上一个空,而不是加上\n
# print(1,end="")
# print(2,end="")


i= 0
while i<10:
	print("*",end="")
	i+=1
print(i)

# 用一个变量打印出一行十个小星星 (十个小星星塞在一个变量中,最后达因变量)
res = "*" * 10
print(res)


i = 0
strvar = ''
while i<10:
	# 写代码 写逻辑
	strvar += "*"

	i+=1
print(strvar)
# strvar = "*" + "*" + "*" + "*" ... 10次星星 "**********"

# 打印一行十个小星星 奇数个打印★ 偶数个打印☆
"""
对于任意数n
0 % 2  0
1 % 2  1
2 % 2  0
3 % 2  1
4 % 2  0
余数是0和1

0 % 3 0
1 % 3 1
2 % 3 2
3 % 3 0
4 % 3 1
5 % 3 2
6 % 3 0
余数是0 1 2 


0 % 5 0
1 % 5 1
2 % 5 2
3 % 5 3
4 % 5 4
5 % 5 0
...
...
余数是0 1 2 3 4 
 ***** 任意数 % n 取余  值得范围是多少?   0 ~ (n-1) *****
"""

# 方法一
i = 0
while i < 10:
	if i % 2 == 0:
		print("★",end="")
	else:
		print("☆",end="")

	i+=1
	
# 方法二
print()
i = 0
strvar = ''
while i < 10:
	if i % 2 == 0:
		strvar += "☆"
	else:
		strvar += "★"

	i+=1

print(strvar)

# 用 一个循环 打印十行十列小星星
'''
**********
**********
**********
**********
**********
**********
**********
**********
**********
**********
'''

i = 0
while i < 100:
	# 打印星星
	print("*",end="")
	# 打印换行
	if i % 10 == 9:
		print()
	
	i+=1

 
# 一个循环 打印十行十列隔列变色小星星
i = 0
while i<100:
	# 控制打印 各列变色
	if i % 2 == 0:
		print("☆",end="")
	else:
		print("★",end="")
		
	
	# 控制换行
	if i % 10 == 9:
		print()
	i+=1


# 一个循环 打印十行十列隔行变色小星星
"""
★★★★★★★★★★
☆☆☆☆☆☆☆☆☆☆
★★★★★★★★★★
☆☆☆☆☆☆☆☆☆☆
★★★★★★★★★★
☆☆☆☆☆☆☆☆☆☆
★★★★★★★★★★
☆☆☆☆☆☆☆☆☆☆
★★★★★★★★★★
☆☆☆☆☆☆☆☆☆☆
"""
"""
n // 2 
0 // 2 0
1 // 2 0

2 // 2 1
3 // 2 1

4 // 2 2
5 // 2 2

0 // 4 0
1 // 4 0
2 // 4 0
3 // 4 0
4 // 4 1
...
...
4个1 4个2 4个3

 ***** 任意数和 n 进行地板除 产生n个相同的数 *****
任意数 // 10 产生10个相同的数
任意数 // 25 产生25个相同的数

"""

print("<=-==>")
i = 0
while i<100:
	# 打印星星的部分
	if  i // 10 % 2  == 0:
		print("★",end="")
	else:
		print("☆",end="")
		
	# 换行部分
	if i % 10 == 9:
		print()		
	i+=1

"""
i = 0 1 2 3 4 5 6 7 8 9 
i // 10 =>0

i = 10 11 12 13 14 15 16 17 18 19
i // 10 =>1

i = 20 21 22 23 24 25 26 27 28 29
i // 10 =>2

...
...

i = 90 91 92 93 94 95 96 97 98 99
i // 10 =>9

i // 10 得到最后的数范围是0 ~ 9 
0~9 % 2  0或者1 正好做黑白星星这样的两种花色
"""

# 打印十行十列小星星 (用两个循环)

#(1) 打印一行十个小星星
# print("*" * 10)

i = 0
while i<10:
	print("*",end="")
	i+=1
	
#(2) 把一行十个小星星循环10遍
print("<======>")
j = 0
# 打印10遍
while j<10:

	# 打印一行十个小星星
	i = 0
	while i<10:
		print("*",end="")
		i+=1

	print()
	j+=1
	
# 打印十行十列隔列换色小星星
print("<===>")
i = 0
while i < 10:

	j = 0
	while j<10:
		# 控制打印星星的代码
		# print("*",end="")
		# *@*@*@
		if j % 2 == 0:
			print("*",end="")
		else:
			print("@",end="")
			
		
		j+=1
		
	print()

	i+=1



# 打印十行十列隔行换色小星星
print("<===>")

# 外面循环动的慢,里面循环动的快
# i 所对的外循环 控制这个行 
i = 0
while i < 10:

	# j 所对的内循环 控制这个列
	j = 0
	while j<10:
		# 控制打印星星的代码
		# print("*",end="")
		# *@*@*@
		if i % 2 == 0:
			print("*",end="")
		else:
			print("@",end="")
			
		
		j+=1
		
	print()

	i+=1
	
	
# 99乘法表
# 方向一
# 外面循环用来控制每一行 i
i = 1
while i<=9:

	# 这个循环用来控制每一列 j
	j = 1
	while j<=i:
		
		# 格式化一个字符串
		# strvar = "%d*%d=%2d" % (i,j,i*j)
		# print(strvar,end=" ")	
		# 输出乘法表 i 代表行 j 代表列 i*j是最后的乘积
		print("%d*%d=%2d" % (i,j,i*j), end = " ")
		j+=1

	# 打印换行
	print()
	i+=1
# strvar = "%d * %d = %d" % ()
"""
1 => 1
2 => 2
3 => 3
4 => 4 
...
...
9 => 9
* i 是几 就循环几遍
"""

# 方向二
i = 1
while i<=9:
	# (1)打印空白	
	k = 9 - i  # 8 7 6 5 4 3 2 1 0
	while k>0:
		print("       ",end="")
		k-=1 # k = k - 1
	
	# (2)打印乘法表
	j = 1
	while j<=i:
		print("%d*%d=%2d " % (i,j,i*j),end="")
		j+=1
		
	# (3)打印换行
	print()
	i+=1



# 方向三
print("<==>")
i = 9
while i>0:


	j = 1
	while j<=i:
		print("%d*%d=%2d" % (i,j,i*j), end = " ")
		j+=1

	print()
	i-=1


# 方向四
i = 9
while i>0:
	# (1)打印空白	    
	k = 9 - i  # 8 7 6 5 4 3 2 1 0
	while k>0:
		print("       ",end="")
		k-=1 # k = k - 1
	
	# (2)打印乘法表
	j = 1
	while j<=i:
		print("%d*%d=%2d " % (i,j,i*j),end="")
		j+=1
		
	# (3)打印换行
	print()
	i-=1


# 100~ 999 找吉利数字  111 222 333 ... 999  123 321  456 654 ..678 876 打印出来
'''
通过地板除可以得到一个数的高位
通过取余可以得到一个数的低位
567
百位:567 // 100 = 5
十位:567 // 10 % 10 = 6
个位:567 % 10  = 7
'''

# 方法一
i = 100
while i<=999:

	gewei = i % 10
	shiwei = i // 10 % 10
	baiwei = i // 100
	
	# 111 222 333 ... 
	if  shiwei == gewei and shiwei == baiwei :
		print(i)
	
	# 123 345 678
	if  (shiwei == gewei - 1) and (shiwei == baiwei +1):
		print(i)
	
	# 321 987 543
	if  (shiwei == gewei + 1) and (shiwei == baiwei -1):
		print(i)
	
	i+=1

# 方法二
print("<====>")
"""
	strvar = "789"
	strvar[-1]
	shivar[1]
	strvar[0]  
"""
i = 100
while i<=999:

	strvar = str(i)
	#个位
	gewei = int(strvar[-1])
	shiwei = int(strvar[1])
	baiwei = int(strvar[0])
	
	# 111 222 333 ... 
	if  shiwei == gewei and shiwei == baiwei :
		print(i)
	
	# 123 345 678
	if  (shiwei == gewei - 1) and (shiwei == baiwei +1):
		print(i)
	
	# 321 987 543
	if  (shiwei == gewei + 1) and (shiwei == baiwei -1):
		print(i)
	
	i+=1





# ###百钱买百鸡  公鸡1块钱一只  母鸡 3块钱一只  小鸡5毛钱一只 100块钱 买 100只鸡 有多少种买法

"""
穷举法:一个一个拿出来试
公鸡 = 1,2
母鸡 = 3,4
小鸡 = 5,6
公鸡 + 母鸡 + 小鸡 = 10

1 + 3 + 5
1 + 3 + 6

1 + 4 + 5
1 + 4 + 6


2+3+5
2+3+6

2+4+5
2+4+6

x = 公鸡 y = 母鸡 z = 小鸡
"""

x = 0
while x <= 100:
	
	y = 0
	while y <= 33:
	
		z = 0 
		while z <= 100:
			# 三款鸡加一起是100只 三款鸡价格加一起是100块 两个条件同时满足
			if (x+y+z == 100) and (x +3*y+ 0.5*z == 100):
				print(x,y,z)
			z+=1
		y+=1
	x+=1
    
# 菱形小星星
'''
     *
    ***
   *****
  *******
 *********
***********

***********
 *********
  *******
   *****
    ***
     *
'''	

"""
(1)对于任意个星星,总行数?
11 => 6
9 => 5
7 => 4
..
..
结论: hang = n // 2 + 1


(2)对于当前行i , 空格数?
1 => 5
2 => 4
3 => 3
4 => 2
5 => 1
结论: kongge = 总行数 - i


(3)对于当前行i , 星星数?
1 => 1
2 => 3
3 => 5

结论:xingxing = 2 * i - 1
"""

# 三角形的上半部分
# 第一种
n = 11
hang = n // 2 + 1

i = 1
while i<=hang:
	# 打印空格
	print(" " * (hang-i),end="")	
	# 打印星星
	print("*" * (2*i-1),end="")	
	# 打印换行
	print()	
	i+=1

# 三角形的下半部分
i = hang
while i>0:
	# 打印空格
	print(" " * (hang-i),end="")	
	# 打印星星
	print("*" * (2*i-1),end="")	
	# 打印换行
	print()	
	i-=1

print("<====>")
# 第二种

# 上半部分
n = 11
hang = n // 2 + 1

i = 1
while i<=hang:
	# 打印空格
	# print(" " * (hang-i),end="")	
	k = hang-i
	while k>0:
		print(" ",end="")
		k-=1
	
	
	# 打印星星
	# print("*" * (2*i-1),end="")	
	j = 1
	xingxing = 2*i-1
	while j<=xingxing:
		print("*",end="")
		j+=1
		
		
	# 打印换行
	print()	
	i+=1

# 下半部分
i = hang
while i>0:
	# 打印空格
	# print(" " * (hang-i),end="")	
	k = hang-i
	while k>0:
		print(" ",end="")
		k-=1
	
	
	# 打印星星
	# print("*" * (2*i-1),end="")	
	j = 1
	xingxing = 2*i-1
	while j<=xingxing:
		print("*",end="")
		j+=1		
	# 打印换行
	print()	
	i-=1

关键字pass break continue

# ### pass  break continue

# pass   过 
if True :
	# 不允许代码块里面的内容为空,用pass占位
	pass


i = 0
while i<10:
	pass 
	
	i+=1



# break (只能用在循环当中 终止当前循环)
# 打印1~10 如果遇到 5 终止循环
# 单循环 
i = 1
while i<=10:
	
	if i == 5:
		break
	print(i)
	
	
	i+=1
	
	
# 多循环   (break 终止当前循环)
i =1
while i<=3:
	j = 1
	while j <= 3:
	
		if j == 2:
			print(i,j)
			break
	
		j+=1
	i+=1
	
	
# continue (跳过当前循环,从下一次循环开始)
# 打印1 ~ 10 跳过5
i  = 1 
while i<=10:
	if i == 5:
		# continue 跳过当前循环 即下面的代码不走了 直接回到循环条件的判断里了
		i += 1
		continue
		
	print(i)
	i+=1

'''
代码块里面如果只有一句代码 可以如下写法
if 5 == 5:continue
'''

# 1~100 打印所有不含有4的数字
# 第一种
'''
// 取一个数的高位
%  取一个数的低位

任意数 // n  => 能产生n个相同的整数
任意数 %  n  => 能产生值得范围在0~(n-1)
'''
print("<===>")
i = 1
while i<=100:
	# 个位含有4的 或者 十位含有4的都不要 都跳过
	if i % 10 == 4  or   i // 10 == 4:
		i+=1   # 注意 不加i+=1 会死循环
		continue 
		
	print(i)
	i+=1
	
	
# 第二种
print("<==11==>")
i = 1
while i<=100:
	res = str(i)
	if '4' in res:
		i+=1
		continue
		
	print(i)
		
	i+=1

python for循环的遍历

# ### 循环 for .. in 
listvar = [1,2,3,4,5]
# len(listvar) = 5 算出列表里面所有元素的个数
# listvar[100]

# 把容器里数据拿出来的这个过程 可以叫遍历  迭代  循环
i=0
while i<=len(listvar)-1:
	print(listvar[i])
	i+=1

# 无序容器类型数据没法通过索引来进行遍历 while遍历有局限性 , for .. in 应用而生
'''
for 变量 in  可迭代性数据:
	code1
	code2..	
'''

# 遍历集合
container = {"java","python","Go"}
# 遍历列表
container = ["js","vue","shell","js","html","css"]
# 遍历元组
container = ("k8s","docker","kvm","nginx","mysql","tomcat")
# 遍历字符串
container = "好看的皮囊千篇一律,有趣的灵魂200多斤"
# 遍历字典  (遍历字典的时候 默认遍历的是键)
container = {"top":"亚瑟","middle":"摩根","bottom":"约翰"}
for f in container:
	print(f)

# 遍历等长二级列表
# 变量的解包
a,b = (1,2)
a,b = [3,4]
a,b = (6,7)
# a,b = "ab"  a,b = "abcd"    # 有局限性
# a,b = {"小苍蝇","小蟑螂"}  # 不推荐使用 因为集合无序 存在不确定性
print(a,b)

listvar = [["python","Go","shell"],["java","js","vue"],["k8s","docker","kvm"]]
# a,b,c = ["python","Go","shell"]
for a,b,c in listvar:
    print(a,b,c)

# 遍历不等长的二级列表
print("<===>")
listvar = [["python","Go","shell"],["java","js"],["k8s"]]
for i in listvar:
	for j in i:
		print(j)

        
# range 可迭代的对象
res = list(range(0,9))
print(res)

'''
range(start ,[end , step])
	start 开始值
	end   结束值 (end本身这个值取不到,取到end之前的那个值)
	step  步长
	返回一个可迭代对象
'''

# range 括号里面只有一个值(参数)
# 默认从0开始遍历 到9结束 共10个数
for i in range(10):
	print(i)
print("<====>")
# range括号里面有两个值
for i in range(1,10):
	print(i)
# range括号里面有三个值
print("<====>")
for i in range(1,10,3):
	print(i)
# 打印9~1
print("<====>")
for i in range(9,0,-1):
	print(i)


# 1.改写99乘法表 用for 
for i in range(1,10):
	for j in range(1,i+1):
		print("%d*%d=%2d" % (i,j,i*j), end = " ")

	print()

字符串的相关操作

# (1)字符串的拼接 ( + )
strvar1 = "我爱啃"
strvar2 = "大猪蹄子"
res = strvar1 + strvar2
print(res)
strvar1 += strvar2 # strvar1 = strvar1 + strvar2
print(strvar1)

# (2)字符串的重复 ( * )
strvar = "Go"
res = strvar * 3
print(res)
strvar = "\t"
res = strvar * 3
print(res)

# (3)字符串跨行拼接 ( \ )
strvar = "klasdjflkjsadklfjaskldjfklasjdklfjaskldfjklasdjfklsdjflkajs;dlkfjal;ksdjflkasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfdfl"\
"kl09q2384092830482309riowsrfiej"
print(strvar)

# (4)字符串的索引
#         0 1 2  3 4 5
strvar = "python"
#         -6-5-4-3-2-1
print(strvar[2])
print(strvar[-4])

'''
(5)字符串的切片: 所谓的切片就是截图 
语法 => 字符串[::]  完整格式:[开始索引:结束索引:间隔值]
	(1)[开始索引:]  从开始索引截取到字符串的最后
	(2)[:结束索引]  从开头截取到结束索引之前(结束索引-1)
	(3)[开始索引:结束索引]  从开始索引截取到结束索引之前(结束索引-1)
	(4)[开始索引:结束索引:间隔值]  从开始索引截取到结束索引之前按照指定的间隔截取字符
	(5)[:]或[::]  截取所有字符串
'''
# (1)[开始索引:]  从开始索引截取到字符串的最后
res = strvar[2:]
res = strvar[-3:]
print(res)

# (2)[:结束索引]  从开头截取到结束索引之前(结束索引-1)
# 高位取不到
res = strvar[:8]  # 最大值到7
print(res)

# (3)[开始索引:结束索引]  从开始索引截取到结束索引之前(结束索引-1)
res = strvar[9:12] # 从索引9截取到索引11 高位取不到
print(res)

# (4)[开始索引:结束索引:间隔值]  从开始索引截取到结束索引之前按照指定的间隔截取字符
"""
# 正向截取
把所有的索引算出来,然后依次比对拿值
0   2   4  6  8 10
人  苦   , 用  y  h
"""
res = strvar[0:12:2]
print(res)

"""
# 反向截图
-1 -2 -3 -4  ...
 n  h  y  用

-1 -3 -5 -7 -9 ....
"""
res = strvar[::-2]
print(res)

#(5)[:]或[::]  截取所有字符串
res = strvar[:]
res2 = strvar[::]
print(res)
print(res2)

# 注意的地方:目的是要截图到值
print("<==>")
strvar = "12345"
res = strvar[-5:0] # 取不到值
print(res)

# -5 => 1 
# 0  => 1

字符串相关函数

# 字符串相关函数(方法)
# 使用字符串当中的某一个方法 格式: "字符串".方法()
# *capitalize 字符串首字母大写
strvar = "this is my boy"
res = strvar.capitalize()
print(res)

# *title 每个单词的首字母大写 (非字母隔开的单词)
strvar = "this is999my***girl"
res = strvar.title()
print(res)

# *upper 将所有字母变成大写
strvar = "aa bbb CCC"
res = strvar.upper()
print(res)

# *lower 将所有字母变成小写 
strvar = "HAPPY NEW YEAr"
res = strvar.lower()
print(res)

# *swapcase 大小写互换 
strvar = "aa bbb CCC"
res = strvar.swapcase()
print(res)

# *count 统计字符串中某个元素的数量
strvar = "hello worldddd"
res = strvar.count("d")
print(res)

# *find 查找某个字符串第一次出现的索引位置 (如果找不到返回-1)
'''find("字符串",start,end) 可以划定范围查找'''
strvar = "Oh Father this is mY Favorite Boy"
res = strvar.find("Father")
res = strvar.find("F",4)
res = strvar.find("t",6,11) #正向索引
res = strvar.find("B",-4,-1)#反向索引
print(res)

# *index 与 find 功能相同 find找不到返回-1,index找不到数据直接报错
# res = strvar.index("abc") error 找不到

# *startswith 判断是否以某个字符或字符串为开头 
'''startswith("字符串",start,end)'''
res = strvar.startswith("O")
res = strvar.startswith("Father",4)
print(res)

# *endswith 判断是否以某个字符或字符串结尾 
res = strvar.endswith("y",-3)
res = strvar.endswith("Bo",-5,-2)
print(res)

# *split 按某字符将字符串分割成列表(默认字符是空格)
# split 可以选择第二个参数,用来控制分割几次
strvar = "you can you up no can no bb"
res = strvar.split()
print(res)

strvar = "you-can-you-up-no-can-no-bb"
# split 方向从左向右
res = strvar.split("-",1)
print(res)

# split 方向从右向左 r => right
res = strvar.rsplit("-",2)
print(res)

# *join  按某字符将列表拼接成字符串(容器类型都可)
listvar = ['you', 'can', 'you', 'up', 'no', 'can', 'no', 'bb']
res = "^".join(listvar)
print(res)

# *replace 替换字符串(可选择替换的次数)
'''字符串.replace(就字符串,新字符串,[替换的次数])'''
strvar = "可爱的小狼狗喜欢吃肉,有没有,有没有,还有没有"
res = strvar.replace("有没有","真没有")
print(res)
res = strvar.replace("有没有","真没有",1)
print(res)

# is 开头的函数 都是返回True 或者 False
# *isalnum 判断字符串是否是由数字、字母、汉字组成 
print(111)
strvar = "陈梦洁大美女666888ismysupergirlさしす"
print(strvar.isalnum())

# *isdigit 检测字符串是数字组成 接受二进制字节流 
"""
# 二进制的字节流 bytes  => b" "  Byte是字节
字节流用来做网络传输或存储用的
b开头修饰的字符串必须是ascii编码中的字符
例如: b"12345" 
b"陈元吉大帅锅"错误  中文如果想要转化成字节流需要使用encode和decode
"""
strvar = b"123456"
res = strvar.isdigit()
print(res)

# *isdecimal 检测字符串是否以数字组成  必须是纯数字
strvar = "7890"
res = strvar.isdecimal()
print(res)

# *center 填充字符串,原字符居中 (默认填充空格)
'''
center(要填充的数字,字符)
要填充的数字 是总长度 = 要填冲的字符 + 要填充的符号
'''
strvar = "好"
res = strvar.center(6,"*")
print(res)
# 方法一
strvar = " "
res = strvar.center(7," ")
print(res,99)
# 方法二
strvar = "%7s" % (' ')
print(strvar,99)

# *strip  默认去掉首尾两边的空白符 ( \n \t 空格)
strvar = "        周杰伦     "
res =strvar.strip()
print(res)

# 指定去除收尾两边的字符@
strvar = "@ss"
res = strvar.strip("@")
print(res)

format字符串的格式化

# ### 字符串的格式化 format
"""
(1)顺序传参
(2)索引传参
(3)关键字传参
(4)容器类型数据(列表或元祖)传参
"""

#(1)顺序传参  {}是占位符
strvar = "{}向{}来了一个大大的拥抱"
res = strvar.format("亚瑟","约翰")
print(res)

#(2)索引传参
strvar = "{1}向{0}开了一枪,饮蛋儿亡"
res = strvar.format("亚瑟","达奇")
print(res)

#(3)关键字传参
strvar = "{who2}向{who1}扫射,令人闻风丧胆"
res = strvar.format(who1="迈卡",who2="约翰")
print(res)

#(4) 容器类型数据
strvar = "{1[1]}向{0[0]}泡了一个眉眼,让人魂不守舍,鼻血直冒三千多尺"
res = strvar.format(["亚瑟","摩根"],("达奇","约翰"))
print(res)

# (2) 在format字符串格式化结构中 如果此容器类型数据是字典 通过键取值的时候不要加引号
strvar = "{group1[1]}向{group2[yh]}泡了一个眉眼,让人魂不守舍,鼻血直冒三千多尺"
res = strvar.format(group1 = ["亚瑟","摩根"],group2 = {"dq":"达奇","yh":"约翰"})
print(res)

format特殊符号的使用

### (5) format 的填充符号的使用( ^ > < )
"""
^ 原字符串居中
> 原字符串居右
< 原字符串居左

{who:*>10}
who : 关键字参数
*   : 要填充的字符
>   : 原字符串填充的方向
10  : 总长度10 = 原字符串长度 + 填充字符的长度
"""
strvar = "{who:*^10}在医院扎{something:>>10},感觉{feel:!<10}"
res = strvar.format(who="亚瑟",something="一打疫苗",feel="爽歪歪")
print(res)

# (6)进制转换等特殊符号的使用( :d :f :s :, )
# :d 整型占位符
strvar = "亚瑟买了{:d}个跑车,布加迪威龙玩具车"
res = strvar.format(9)
print(res)
# 可以通过 < > ^ 改变方向
strvar = "亚瑟买了{:^3d}个跑车,布加迪威龙玩具车"
res = strvar.format(9)
print(res)

# :f 浮点型占位符  :.2f 代表保留两位小数 可以四舍五入
strvar = "零花钱{:.2f}"
res = strvar.format(1.248)
print(res)

# :s 字符串占位符
strvar = "{:s}"
res = strvar.format("人生苦短,我用python")
print(res)

# :, 金钱占位符
strvar = "{:,}"
res = strvar.format(1234567)
print(res)

# 综合例子
strvar = "{:s}开工资了,发了{:.2f}钱,买了{:<3d}个降噪耳机"
res = strvar.format("亚瑟",999.919,19)
print(res)

列表的相关操作

# (1)列表的拼接   (同元组)
listvar = [1,2]
listvar2 = [4,5]
res = listvar + listvar2
print(res)

# (2)列表的重复   (同元组)
listvar = [1,2,3]
res = listvar * 3
print(res)

# (3)列表的切片   (同元组)
"""
语法 => 列表[::]  完整格式:[开始索引:结束索引:间隔值]
	(1)[开始索引:]  从开始索引截取到列表的最后
	(2)[:结束索引]  从开头截取到结束索引之前(结束索引-1)
	(3)[开始索引:结束索引]  从开始索引截取到结束索引之前(结束索引-1)
	(4)[开始索引:结束索引:间隔值]  从开始索引截取到结束索引之前按照指定的间隔截取列表元素值
	(5)[:]或[::]  截取所有列表
"""

listvar = ["python","Go","shell","java","js","html","vue","c","c++"]
# (1)[开始索引:]  从开始索引截取到列表的最后
res = listvar[1:]
print(res)

# (2)[:结束索引]  从开头截取到结束索引之前(结束索引-1)
res = listvar[:-1]
print(res)

# (3)[开始索引:结束索引]  从开始索引截取到结束索引之前(结束索引-1)
listvar = ["python","Go","shell","java","js","html","vue","c","c++"]
res = listvar[4:5]
print(res)

# (4)[开始索引:结束索引:间隔值] 
res = listvar[3::2]	#['java', 'html', 'c']
res = listvar[:5:2] 
res = listvar[-6:-9:-1]
res = listvar[-6:-9:-100]
res = listvar[::3]
print(res)

# (5)[:] [::] 获取到所有的列表
res = listvar[::]
print(res)

# (4)列表的获取   (同元组)
#            0       1      2       3     4     5
listvar = ["python","Go","shell","java","js","html"]
#           -6       -5    -4      -3    -2    -1
print(listvar[2])
print(listvar[-4])

# (5)列表的修改   ( 可切片 )
listvar[1] = "C#"
print(listvar)
# 2) 切片  删除2个 重新插入4个  (把指定的几个元素干掉,把新的可迭代行数据插入)
listvar[:2] = "abcd"
print(listvar)
# 3) 切片并且指定间隔值 (指定几个元素,就必须填充几个,否则不匹配)
listvar = ["python","Go","shell","java","js","html"]
listvar[::2] = ["vue","html","c"]
print(listvar)
"""
	iterable  可迭代性数据 (容器类型数据 range对象 迭代器)
	通过切片对列表进行修改需要可迭代性数据
"""
listvar[1:2] = range(0,3)
print(listvar)

#可以用切片的方式来删除
listvar = ["python","Go","shell","java","js","html"]
# del listvar[0::2]
# print(listvar)
"""
error:切记不要这样删除 这样删除的是变量res 不是列表
res = listvar[0::2]
del res
print(listvar)
"""

#关于元组 不能直接修改元组当中的儿子,但是可以修改元组当中的孙子
tup = (1,2,3,4,[5,6,7,(9,10,1,[99,88])],(91,92))
tup[-2][-1][-1][-1] = 101
print(tup)

列表相关函数

# 一 增
# append 功能:向列表的末尾添加新的元素
listvar = [1,2,3]
listvar.append(4)
print(listvar)

# insert  功能:在指定索引之前插入元素
listvar = [1,2,3]
listvar.insert(1,"4")
print(listvar)

# extend 功能:迭代追加所有元素
listvar = [11,22,33]
listvar.extend("abc")
print(listvar)
listvar.extend(["python","Go","shell"])
print(listvar)

# 二 删除
# pop  功能:通过指定索引删除元素,若没有索引移除最后那个
listvar = ["python","Go","shell","java"]
res = listvar.pop()
print(res)
print(listvar)
res = listvar.pop(0)
print(res)
print(listvar)

# remove  功能:通过给予的值来删除,如果多个相同元素,默认删除第一个
listvar = ["python","Go","shell","java"]
listvar.remove("shell")
print(listvar)

# clear  功能:清空列表
listvar = ["python","Go","shell","java"]
listvar.clear()
print(listvar)

# 列表的修改的查找 请看列表相关操作

# 其他列表函数
# index功能:获取某个值在列表中的索引
listvar = ["python","Go","shell","java"]
res = listvar.index("Go")
print(res)

# count  功能:计算某个元素出现的次数
listvar = ["python","Go","shell","java","java","java"]
res = listvar.count("java")
print(res)

# sort  列表排序(默认小到大排序)
listvar = [1,99,-9,23,199]
listvar.sort()
print(listvar)
# reverse=True 选择倒叙 True (从大到小)
listvar.sort(reverse=True)
print(listvar)

# reverse  功能:列表反转操作
listvar = [91 ,-88 ,123 ,66]
listvar.reverse()
print(listvar)

listvar = ["oneal","kobi","james","andoni","kuli"]
listvar.sort()
print(listvar)
# 如果是字母 按照ascii吗进行排序 一位一位的比较
# ['andoni', 'james', 'kobi', 'kohi', 'oneal']

深拷贝浅拷贝

#copy模块中有 浅拷贝 和 深拷贝 两种方法
(1)浅拷贝:  浅拷贝只拷贝外层列表  内层列表跟随原列表进行改变
	# 浅拷贝copy.copy(listvar) 或者 listvar.copy()
(2)深拷贝:  拷贝整个列表  内外列表都不跟随原列表进行改变
	# 深拷贝copy.deepcopy(listvar)
注意:copy模块的copy方法 和 python内置的函数copy一样 都是浅拷贝
### 深拷贝 与 浅拷贝 
"""
a  = 10
b = a
a = 7
print(b)

# 不同的两个变量指向了同一个列表
listvar = [1 , 2 ,3 , 4 ]
listvar2 = listvar
listvar.append(5)
print(listvar2)

"""

# 浅拷贝
# 方法一
listvar = [1,2,3,4]
listvar2 = listvar.copy()
listvar.append(5)
print(listvar)
print(listvar2)

# copy模块 copy方法
# 方法二
import copy
listvar = [1,2,3,4]
listvar2 = copy.copy(listvar)
listvar.append(6)
print(listvar)
print(listvar2)

# 深拷贝  copy 模块下的 deepcopy方法
import copy
listvar = [1,2,3,4,[5,6,7]]
listvar2 = copy.deepcopy(listvar)
listvar[-1].append(19)
print(listvar)
print(listvar2)

# 二级容器
import copy
container = {"a":[1,2,3,4],"b":{"c":1,"d":2}}
container2 = copy.deepcopy(container)
container["b"]["ee"] = "大风车"
print(container)
print(container2)

字典的相关函数

# 一 增
dictvar = {}
dictvar["a"] = 1
dictvar["b"] = 2
print(dictvar)

#fromkeys()  使用一组键和默认值创建字典 ( 不常用 了解)
listvar = ["a","b"]
dictvar = {}
dictvar2 = dictvar.fromkeys(listvar,None)
print(dictvar2)

# 二 删
#pop()       通过键去删除键值对 (若没有该键可设置默认值,预防报错)
dictvar = {"top":"鲁班七号","middle":"甄姬","bottom":"盘古"}
res = dictvar.pop("top")
print(dictvar)
print(res)

res = dictvar.pop("top1","该top1键不存在")
print(res)

#popitem()   删除最后一个键值对 
dictvar = {"top":"鲁班七号","middle":"甄姬","bottom":"盘古"}
res = dictvar.popitem()
print(res)
print(dictvar)

#clear()  清空字典
dictvar = {"top":"鲁班七号","middle":"甄姬","bottom":"盘古"}
dictvar.clear()
print(dictvar)

# 三 改
#update() 批量更新(有该键就更新,没该键就添加)
'''
update 如果存在此键,则更改该值,如果不存在此键,则添加该键值对
'''
dictvar = {"top":"鲁班七号","middle":"甄姬","bottom":"盘古"}
dictvar2 = {"jungle":"韩信","support":"蔡文姬"}
dictvar2 = {"jungle":"韩信","support":"蔡文姬","bottom":"孙策"}
dictvar.update(dictvar2)
print(dictvar)

# 四 查
#get()    通过键获取值(若没有该键可设置默认值,预防报错)
'''
存在这个键则拿取这个值,如果不存在这个键,
则使用默认值,如果不设置默认值,默认返回None
'''
dictvar = {"top":"鲁班七号","middle":"甄姬","bottom":"盘古"}
res = dictvar.get("middle")
res = dictvar.get("middle123","不存在改键")
print(res)

# 其他操作
dictvar = {"top":"鲁班七号","middle":"甄姬","bottom":"盘古"}
#keys()   将字典的键组成新的可迭代对象
print(dictvar.keys())

print("<==>")
for i in dictvar:
	print(i)

for i in dictvar.keys():
	print(i)
    
#values() 将字典中的值组成新的可迭代对象
print(dictvar.values())
for i in dictvar.values():
	print(i)
    
#items()  将字典的键值对凑成一个个元组,组成新的可迭代对象 
#items()  将字典的键值对凑成一个个元组,组成新的可迭代对象 
print(dictvar.items())
for k,v in dictvar.items():
	print(k,"=>",v)

集合的操作

# ### 集合的交叉并补

set1 = {"周杰伦","李宇春","王宝强","斯嘉丽"}
set2 = {"周润发","刘德华","王文","斯嘉丽","李宇春"}
#intersection() 交集 
# print(set1 & set2)
# print(set1.intersection(set2))

#difference()   差集 
# print(set1 - set2)
# print(set1.difference(set2))
  
#union()  并集 
# print(set1 | set2)
# print(set1.union(set2))

#symmetric_difference() 对称差集 (补集情况涵盖在其中) 
# print(set1 ^ set2)
# print(set1.symmetric_difference(set2))

#issubset()   判断是否是子集
set1 = {"李逵","张飞","关羽","贾宝玉"}
set2 = {"张飞","关羽"}
# print(set2 < set1 )
# print(set2.issubset(set1))


#issuperset()  判断是否是父集
# print(set1 > set2)
# print(set1.issuperset(set2))

#isdisjoint() 检测两集合是否不相交  不相交 True  相交False
print(set1.isdisjoint(set2))


# ### 集合的相关函数
setvar = {"李逵","张飞","关羽","贾宝玉"}
# 一 增
#add()    向集合中添加数据
setvar.add("李四")
print(setvar)

#update() 迭代着增加
setvar = {"李逵","张飞","关羽","贾宝玉"}
setvar.update("abc")
print(setvar)

# 二 删
#clear()  清空集合
setvar.clear()
print(setvar)

#pop()     随机删除集合中的一个数据
setvar = {"李逵","张飞","关羽","贾宝玉"}
res = setvar.pop()
print(res)
print(setvar)


#remove()  删除集合中指定的值(不存在则报错)
setvar = {"李逵","张飞","关羽","贾宝玉"}
# setvar.remove("关羽")
# setvar.remove("关羽123")  # 不存在的error情况
print(setvar)


#discard() 删除集合中指定的值(不存在的不删除 推荐使用)
setvar.discard("关羽")
setvar.discard("关羽456")
print(setvar)

# ### 集合不能够修改和查询

# 冰冻集合:
"""
#frozenset 可强转容器类型数据变为冰冻集合
冰冻集合一旦创建,不能在进行任何修改,只能做交叉并补操作
"""

# 定义一个空的冰冻集合
fz = frozenset()
print(fz,type(fz))

fz1 = frozenset(["你好","世界","地球"])
fz2 = frozenset({"世界","球"})
print(fz1,type(fz1))
print(fz2,type(fz2))

# 冰冻集合仅仅只能做交叉并补,不能做添加或删除的相关操作
print(fz1 & fz2)

# fz1.add("足球") error

文件的操作

# ### 文件的操作
'''
#  open("文件名称","打开的模式","文件的编码")
open的返回值: 文件的io对象 (简称文件句柄)
i => input  输入
o => output 输出
'''

# (1)文件的写入操作
# 打开文件
fp = open("123-opesn.txt",mode = "w",encoding="utf-8") #打开冰箱
# 写入文件
fp.write("把大象塞进去") #把大象塞进去
# 关闭文件
fp.close() 				  #把冰箱门关上

# 文件的读取操作
# 打开文件
fp = open("123-opesn.txt",mode="r",encoding="utf-8")
# 读取文件
res = fp.read()
# 关闭文件
fp.close()
print(res)

# (2)wb rb 模式的使用
# 将字符串和字节流(Bytes流)类型进行转换 (参数写成转化的字符编码格式)
    #encode() 编码  将字符串转化为字节流(Bytes流)
    #decode() 解码  将Bytes流转化为字符串
strvar = "大象在屋没".encode("utf-8")
print(strvar)
res = strvar.decode("utf-8")
print(res)

# 在b模式,不要指定encoding 有语法错误
# 把二进制字节流写入到文件当中
strvar = "大象在屋没"
fp = open("1234-opesn.txt",mode="wb")
str1 = strvar.encode("utf-8")
fp.write(str1)
fp.close()

# 把二进制字节流读取出来
fp = open("1234-opesn.txt",mode="rb")
res = fp.read()
fp.close()
print(res)
str2 = res.decode("utf-8")
print(str2)


# (3) 复制图片  (二进制的字节流b模式)  如果是图片用字节流模式
# 读取图片操作
fp = open("图片.png",mode="rb")
res = fp.read()
fp.close()
# print(res)

# 写入图片操作
fp = open("图片2.jpg",mode="wb")
fp.write(res)
fp.close()

文件操作模式

# ### 文件操作模式 r+ w+ a+
# (utf-8编码格式下 默认一个中文三个字节 一个英文或符号 占用一个字节)
    #read()		功能: 读取字符的个数(里面的参数代表字符个数)
    #seek()		功能: 调整指针的位置(里面的参数代表字节个数)
    #tell()		功能: 当前光标左侧所有的字节数(返回字节数)
    
# r+ 可读可写 (一般先读后写)
fp = open(r"123-opesn.txt",mode="r+",encoding="utf-8")
res = fp.read()
print(res)
fp.write("123")
fp.seek(0)
res = fp.read()
print(res)
fp.close()

# r+ 先写后读
fp = open(r"123-opesn.txt",mode="r+",encoding="utf-8")
fp.seek(0,2)
fp.write("456")
fp.seek(0)
res = fp.read()
print(res)
fp.close()

# w+ 可读可写 (默认光标位置文件首) 
fp = open(r"123-opesn.txt",mode="w+",encoding="utf-8")
fp.write("123")
fp.seek(0)
res = fp.read()
print(res)
fp.close()

# a+  可读可写 (默认光标在文件末尾)    [再写入时,光标位置一个强制在后]
fp = open(r"123-opesn.txt",mode="a+",encoding="utf-8")
fp.seek(0)
fp.write("789")
fp.seek(0)
res = fp.read()
print(res)
fp.close()

# tell read
# seek移动的是字节 tell返回的也是字节:当前光标左侧所有的字节数
fp = open(r"123-opesn.txt",mode="a+",encoding="utf-8")
res = fp.tell()
print(res)

fp.seek(0)
res = fp.tell()
print(res)

fp.read(4)
res = fp.tell()
print(res)
fp.close()

"""
注意点 seek在移动的时候有可能中文读一半
"""
fp = open(r"123-opesn.txt",mode="a+",encoding="utf-8")
fp.seek(4)
res = fp.tell()
print(res)
res = fp.read()
print(res)
fp.close()

with open("123-opesn.txt",mode="w+",encoding="utf-8") as fp:
    fp.write("123")
    #  fp.close() 会通过with语法自动完成 不需要在写了

文件相关函数

# 刷新缓冲区 flush
	# 当文件关闭的时候自动刷新缓冲区
	# 当整个程序运行结束的时候自动刷新缓冲区
	# 当缓冲区写满了  会自动刷新缓冲区
	# 手动刷新缓冲区
fp = open("123-opesn.txt",mode="w+",encoding="utf-8")
fp.write("90909090")
fp.flush()
while True:
    pass
fp.close()

fp = open("0321-444.txt",mode="r",encoding="utf-8") 
# 检测文件对象是否可读
res = fp.readable()
print(res)
# 检测文件对象是否可写
res = fp.writable()
print(res)
# 文件对象可以遍历 一次从文件当中拿一行的数据
for line in fp:
	print(line)
fp.close()

#readline()     功能: 读取一行文件内容
'''
	如果当前参数值大于实际字符个数,取当前行
	如果当前参数值小于实际字符个数,取参数值这么多的字符
'''
with open("123-opesn.txt",mode="r+",encoding="utf-8") as fp:
    res = fp.readline()
    print(res)
    
# 读出所有文件的内容
with open("123-opesn.txt",mode="r+",encoding="utf-8") as fp:
    res = fp.readline()
    while res:
        print(res)
        res = fp.readline()
        
#readlines()    功能:将文件中的内容按照换行读取到列表当中
listvar = []
with open("123-opesn.txt",mode="r+",encoding="utf-8") as fp:
    list1 = fp.readlines()
    for i in list1:
        res = i.strip()
        listvar.append(res)
    print(listvar)

#writelines()   功能:将内容是字符串的可迭代性数据写入文件中 参数:内容为字符串类型的可迭代数据
#(1) 需要是可迭代性的数据 (2) 里面的元素是字符串
with open("123-opesn.txt",mode="w+",encoding="utf-8") as fp:
    strvar = "人生苦短,我用python\n"
    fp.writelines(strvar)
    strvar = ["今天", "天气", "完美"]
    fp.writelines(strvar)
    
#truncate()     功能: 把要截取的字符串提取出来,然后清空内容将提取的字符串重新写入文件中 (字节)
with open("123-opesn.txt",mode="a+",encoding="utf-8") as fp:
	fp.truncate(8)
    
"""
read()      参数是字符
readline()  参数是字符
seek()      参数是字节
truncate()  参数是字节
"""

python 函数

# 函数 : 功能  把代码包裹起来 实现某个功能 达成某个目的
# 函数的特点: 可以反复调用 提高代码效率 便于维护管理

# 函数的基本格式
'''
# 函数的定义
def 函数名():
	pass

# 函数的调用
函数名()
'''
def func1():
    print("hell world")
func1()

# 函数的命名
"""
字母数字下划线 首字符不能为数字
严格区分大小写 且不能使用关键字
函数命名有意义 且不能使用中文哦


驼峰命名法: 让命名更加的规范清晰
(1)大驼峰命名法 : MyWorkIsGood (一般应用在类名上面)
(2)小驼峰命名法 :  myWorkIsGood  (一般在函数名字上面)
my_work_is_good 开发中 一般用_来分割不同的单词 目的:表达清晰
"""

# 函数的定义
def ChengFaBiao():
    for i in range(1,10):
        for j in range(1,i+1):
            print("%d*%d=%2d" %(i,j,i*j),end=" ")
        print()
# 函数的调用
ChengFaBiao()
# ChengFaBiao()
# ChengFaBiao()

函数的参数

# ### 函数的参数 :
"""
参数:形参 + 实参
形参:形式参数
(普通形参,默认形参,普通收集参数,命名关键字参数,关键字收集参数)
实参:实际参数
(普通实参,关键字实参)

普通参数 也叫 位置参数

形参和实参要一一对应
"""


# 带有参数的函数
# 函数的定义处  普通形参 hang , lie 
def star(hang,lie):  # 形式参数(形参)在函数的定义处
	i= 0
	while i<hang:
		j = 0
		while j<lie:
			print("*",end="")
			j+=1
		print()
		i+=1
# 函数的调用处   普通实参 10 , 10
star(10,10)         #  实际参数(实参)在函数的调用处
star(5,20)


# 默认形参 hang = 10,lie = 10 (在函数的定义处) 在初始化时给与默认值
"""
如果给与实际参数,按照实际参数调用
如果没给实际参数,按照默认参数调用
"""
def star(hang = 10,lie = 10):
    i = 0
    while i < hang:
        j = 0
        while j < lie:
            print("*",end="")
            j+=1
        print()
        i+=1
star()
star(3,4)


# 普通形参 + 默认形参
"""
两者同时存在时,有顺序 普通形参 放在 默认形参 的前面
"""
def star(hang,lie = 10):
    i = 0
    while i < hang:
        j = 0
        while j < lie:
            print("*",end="")
            j += 1
        print()
        i += 1
star(5)
star(3,4)

# 实参 : 关键字实参 (可以指定参数的名字来进行调用)
"""
(1)关键字实参在调用时,顺序可以颠倒随意
(2)如果是普通形参,调用时用了关键字实参,那么该参数后面所有参数都要使用关键字实参
"""
def star(hang,lie):
    i = 0
    while i < hang:
        j = 0
        while j < lie:
            print("*",end="")
            j += 1
        print()
        i += 1
#关键字实参 :  hang=3 , lie=4 
star(lie=4,hang=3)


# ### 默认形参 关键字实参
'''
这两个参数从写法上来看一样,默认形参在函数的定义处,关键字实参在函数的调用处
''' 
# top middle bottom jungle support 默认形参
def gameteam(top="python",middle="java",bottom="shell",jungle="Go",support="opesn"):
	print("上单选手{who}".format(who = top))
	print("中单选手{who}".format(who = middle))
	print("下路选手{who}".format(who=bottom))
	print("打野选手{who}".format(who=jungle))
	print("辅助明星选手{who}".format(who=support))

gameteam()
# jungle="bengi" ...  这些是关键字实参
gameteam(jungle="bengi",bottom="html",top="css",middle="大魔王faker")


# ### 收集参数
"""
普通收集参数
关键字收集参数
"""

"""
# 普通收集参数
def func(*参数):
	pass
把参数前面加  一颗星星*   叫做普通收集参数

普通收集参数:专门用来收集多余的,没人要的普通的实参,都打包到一个元组当中

def func1(a,b,c,*d):
	print(a,b,c)
	print(d)
	
func1(1,2,3,4,5,6,7)
"""


# ### 收集参数
"""
普通收集参数
关键字收集参数
"""

"""
# 普通收集参数
def func(*参数):
	pass
把参数前面加  一颗星星*   叫做普通收集参数

普通收集参数:专门用来收集多余的,没人要的普通的实参,都打包到一个元组当中

def func1(a,b,c,*d):
	print(a,b,c)
	print(d)
	
func1(1,2,3,4,5,6,7)
"""

# 计算任意个数的累加和
def mysum(*args):
	# print(args)
	total = 0
	for i in args:
		total += i
	print(total)
mysum(1,2,3,99,1001,32323423423423)


"""
#关键字收集参数
def func1(a,b,c,**kwargs):
	pass
把参数前面加  二颗星星**   叫做关键字收集参数

关键字收集参数:专门用来收集多余的,没人要的关键字实参,都打包到一个字典当中
def func1(a,b,c,**d):
	print(a,b,c)
	print(d)
	
func1(1,2,3,f=11,e=12,zz=14)


keyword arguments => kwargs
"""
# 任意字符串的拼接
def myfunc(**kwargs):
    #{monitor = "张三",class_flower = "李四",kehu = "客户",wwu="王五"}
    dictvar = {"monitor":"班长","class_flower":"班花"}
    strvar1 = ''
    strvar2 = ''
    # k 指代的是键 monitor  v 指代的是指 张三
    for k,v in kwargs.items():
        # in 在字典中 判断的是键是否存在
        if k in dictvar:
            # 班长 + : + 张三
            strvar1 += dictvar[k] + ":" + v + "\n"
        else:
            # 客户 + ' ' + '王五'
            strvar2 += v + " "
    #字符串的格式化
    strvar = "{}情深深,雨蒙蒙,{}看了之后猛顶了两口狗粮".format(strvar1,strvar2)
    print(strvar)

myfunc(monitor = "张三",class_flower = "李四",kehu = "客户",wwu="王五")


# ###命名关键字参数
"""
def func(参数1,参数2,*,参数3)
在指定星号"*"后面的参数是命名关键字参数
或者在普通收集和关键字收集之间的参数
如果是命名关键字,在函数调用的时候,必须使用关键字实参
"""
# 命名关键字写法一
# def func(a,b,c,*,d):
	# print(a,b,c,d)
# func(1,2,3,d=4)

# def func(a,b,c,*,d=4):
	# print(a,b,c,d)
# func(1,2,3)

# 命名关键字写法二
# def func(*args,abc,**kwargs):
	# print(args)
	# print(abc)
	# print(kwargs)
# func(1,2,3,4,a =10,abc = 90,b=11)


"""
(4)*和**的魔术用法:打包和解包 
    *和**,在函数的定义处,负责打包(把实参都收集过来,放在元组或字典中)
    *和**,在函数的调用处,负责解包(把容器类型的数据,一个一个拿出来,进行传递)
"""
def func(a,b,c,*,d):
	print(a,b,c)
	print(d)
listvar = [1,2,3]
# func(1,2,3,d=90)
func(*listvar,d=90)


def func(a,b,c,*,d,e,f):
	print(a,b,c)
	print(d,e,f)
dictvar = {"d":88,"e":12,"f":34}
func(1,2,3,**dictvar)  # d = 88  e = 12  f=34


"""
# 所有形参的位置顺序:
普通形参 -> 默认形参 -> 普通收集形参 -> 命名关键字形参 => 关键字收集形参
"""
def f1(a, b, c=0, *args, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)

def f2(a, b, c=0, *, d, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)

# 以上两个函数 打印结果
"""
#(一)
f1(1, 2) #a=1 b=2 c=0 args=()  kw={}
f1(1, 2, c=3)  # a=1 b=2 c=3 args=() kw={}
f1(1, 2, 3, 'a', 'b') #a=1 b=3 c=3 args=("a","b") kw={}
f1(1, 2, 3, 'a', 'b', x=99) #a = 1 b = 2 c = 3 args=() kw={"x":99}
f2(1, 2, d=99, ext=None) # a=1,b = 2,c=0,d=99,kw={"ext":None}
"""
"""
#(二)
args = (1, 2, 3, 4)
kw = {'d': 99, 'x': '#'}
f1(*args, **kw)   #a = 1,b=2,c=3,args=(4,),kw={'d':99,"x":'#'}
"""

"""
#(三)
myargs = (1, 2, 3)
mykw = {'d': 88, 'x': '#'}
f2(*myargs, **mykw) # a=1,b=2,c=3,d=88,kw={'x':"#"}
f2(1,2,3,d=88,x="#")
"""
#(四)
def f1(a, b, c=0, *args,d,**kw):
    print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
    print(d)

f1(1,2,3, 'a', 'b',d=67, x=99,y=77) # a=1,b=2,c=3,args=('a','b') kw={"x":99,"y":77}  d = 67


return 函数的返回值

""" 
return : 自定义返回值  返回到函数的调用处
(1) return 后面除了可以接6大标准数据类型之外 还有函数和类对象,如果不写return ,默认返回None
(2) return 一旦执行return之后,函数立即终止,后面的代码不执行
"""

# (1) 返回6大标准数据类型
# 函数的定义处
def myfunc():
	# return 15
	# return 3.15
	# return True
	# return 4-3j
	# return [1,2,3]
	return {"a":1,"b":2}
# 函数的调用处
res = myfunc()   # => res = 15 print(res)
print(res)


# (2)一旦执行return之后,函数立即终止,后面的代码不执行
def myfunc():
	print("44行走没走")
	return 999
	print("46行走没走")
	print("47行走没走")
	
res = myfunc()
print(res)


# 模拟一个计算器的操作
def calc(sign,num1,num2):
	print(sign,num1,num2)
	if sign == "+":
		res = num1 + num2
	elif sign == "-":
		res = num1 - num2 
	elif sign == "*":
		res = num1 * num2
	elif sign == '/':
		if num2 == 0:
			return "二货,除数不能为0"
		res = num1 / num2
	else:
		return "傻蛋,这个老子不会算~"
	return res
# 符号 数字1 数字2
print(calc("&",2,3))

函数名的使用

# ### 函数名的使用
# python中的函数可以像变量一样,动态创建,销毁,当参数传递,作为值返回,叫第一类对象.其他语言功能有限

# 1.函数名是个特殊的变量,可以当做变量赋值
def myfunc():
	print(123)
print(myfunc)
# func2 = 4+4j
# (1)可以赋值函数
func2 = myfunc
func2()

# (2)可以销毁函数
del func2
# func2()


# 2.函数名可以作为容器类型数据的元素
def fun1():
	print(11)	
def fun2():
	print(22)	
def fun3():
	print(33)
listvar = [fun1,fun2,fun3]
# listvar[1]()
for i in listvar:
	i()
    

# 3.函数名可以作为函数的参数
def myfunc(func):
	res = func() # res = 17
	print(res)
def myfunc2():
	return 17 
myfunc(myfunc2)


# 4.函数名可作为函数的返回值
def myfunc3(func):
	return func	
def myfunc4():
	return 199 
func2 = myfunc3(myfunc4) # func2 = myfunc4
print(func2)
print(func2())


# ### __doc__ 魔术属性 获取函数的文档
# help(print)
res = print.__doc__
print(res)


# 定义一个函数的文档 吃大肠方法
def eat_big_chang(something):
	"""
	功能:吃大肠的过程
	参数:something器皿
	返回值:gameover	
	"""
	print("成{something}大肠".format(something=something))
	print("找肠子头")
	print("把场子头放嘴里,使劲嘬")
	print("把肠子头放下,满意的擦擦嘴")
	return "gameover"	
myfunc = eat_big_chang("一盘")
print(myfunc)
res = eat_big_chang.__doc__
print(res)

局部变量 和 全局变量

# ### 局部变量 和 全局变量
"""
局部变量: 在函数内部的变量 (局部命名空间)
全局变量: 在函数外部或者在函数内部使用global关键字修饰的变量 (全局命名空间)
作用域:作用区域
	局部变量的作用域限定在函数的内部
	全局变量的作用域横跨整个文件
"""
# 局部变量的获取和修改
b = 6
def func():
	a = 5
	print(a) # 获取变量a	
	a = 6    # 修改变量a
	print(a)
	print(b)
func()
# print(a)

# 全局变量
a = 90
print(a)   # 获取变量a
a = 91     # 修改变量a
print(a)

# 在函数里面修改全局变量 借助关键字global
def func2():
	global a
	a = 88
func2()
print(a)

# 在函数里面定义一个全局变量 借助关键字global
def func3():
	global abcd
	abcd = 97
func3()
print(abcd)
"""
如果外面定义了一个全局变量,通过global可以直接在函数内部进行修改
如果外面没有定义该全局变量,通过global可以直接在函数内部定义全局变量
global关键字修饰的时候,写在代码块的开头
"""

函数的嵌套

# ### 函数的嵌套
"""
python当中,函数和函数之间可以互相嵌套,
嵌套在外层的叫做外部函数
嵌套在内存的叫做内部函数
"""

'''
def outer():
	
	def inner():
		print("我是inner")
		
	inner()

outer()
# inner()
'''
"""
(1)内部函数可以直接在函数外部调用么?   不行!
(2)调用外部函数后,内部函数可以在函数外部调用吗  不行!
(3)内部函数可以在函数内部调用吗   可以
(4)内部函数在函数内部调用时,是否有先后顺序 有先后顺序
"""

# 有三个嵌套函数 外层是outer 中间层是inner 最小层是smaller 调用smaller
def outer():
	def inner():
		id = 99
		def smaller():
			print(id)
			print("我是smaller")
		smaller()			
	inner()
outer()	


#LEGB原则(即就近原则找变量)

'''
#找寻变量的调用顺序采用LEGB原则(即就近原则)
B —— Builtin(Python);Python内置模块的命名空间      (内建作用域) (内置命名空间)
G —— Global(module); 函数外部所在的命名空间        (全局作用域) (全局命名空间)
E —— Enclosing function locals;外部嵌套函数的作用域(嵌套作用域) (局部命名空间)
L —— Local(function);当前函数内的作用域            (局部作用域) (局部命名空间)
依据就近原则,从下往上 从里向外 依次寻找
'''
# LEGB 原则找局部作用域当中的a,因为被删除,直接报错;
'''
a = 10
def abc():
	a = 80
	del a
	print(a)
abc()
'''

'''
a = "abc"
def func():
	global a
	a = a.replace("b","d")
	print(a)
	# global a
	# a += "bcdd"
	# print(a)
func()
'''


nonlocal 修饰局部变量

# ### nonlocal 修饰局部变量
"""
nonlocal 符合LEGB原则
(1) 用来修改当前作用域上一级的[局部变量]
(2) 如果上一级没有,继续向上寻找
(3) 如果再也找不到了,直接报错
"""

# (1)用来修改当前作用域上一级的[局部变量]
def outer():
    a = 5
    def inner():
        nonlocal a
        a+= 13
        print(a)
    inner()
    print(a)
outer()

#(2) 如果上一级没有,继续向上寻找
def outer():
    a = 3
    def inner():
        def smaller():
            nonlocal a
            a -= 1
            print(a)
        smaller()
        print(a)
    inner()
    print(a)
outer()


# (3) 如果再也找不到了,直接报错
''' error  只能修饰局部变量
a = 3
def outer():
    def inner():
        def smaller():
            nonlocal a
            a-=1
            print(a)
        smaller()
        print(a)
    inner()
    print(a)
outer()	
'''

# 不通过 nonlocal 来修改变量
def outer():
    # 使用列表
    listvar = [40,41,42]
    def inner():
        listvar[1] += 10
    inner()
    print(listvar)
outer()

闭包函数

# ### 闭包
"""
闭包:
	内函数使用了外函数的局部变量,
	并且外函数将内函数返回出来的方法过程叫做闭包
	里面的这个内函数叫做闭包函数.
"""

# 函数的定义处
def cgj_family():
    f = "opesn"
    def cgj_hobby():
        print("hello world %s" %(f))
    return cgj_hobby
# 函数的调用处
func = cgj_family()  # func = cgj_hobby
print(func,type(func))
func()

print("<==>")
# __closure__ 获取闭包函数使用过的外部变量
# cell_contents 是 单元cell的一个属性,通过他可以获取其中的内容
print(func.__closure__)
print(func.__closure__[0].cell_contents)


"""
闭包的特点:
    内函数使用了外函数的局部变量,外函数的局部变量与内函数发生绑定,延长该变量的生命周期
    (实际内存给它存储了这个值,暂时不释放)
"""
def dulei_family():
    a = "A"
    b = "B"
    # 两个函数共用同一个局部变量money
    money = 1000
    def a_hobby():
        # nonlocal 用来修改局部变量money
        nonlocal money
        money -= 700
        print("爱花钱,爱名牌,爱包包,爱名车手表,家里的钱还剩下%d" % (money))
    def b_hobby():
        nonlocal money
        money -= 200
        print("家里的钱还剩下%d" % (money))
    def big_guanjia():
        return a_hobby,b_hobby
    # 返回大管家
    return big_guanjia
func = dulei_family()
print(func)
# 调用大管家函数
tuplevar = func()
# a和b两个函数都存在元组当中
print(tuplevar)
# 获取a函数
a = tuplevar[0]
# 获取b函数
b = tuplevar[1]
a()
b()


"""
def abc():
    def bbb():
        pass
    return bbb
# 语法 =>  测试的闭包函数.__closure__
# 用__closure__ 魔术属性 来获取闭包函数用过的局部变量,如果是None不是闭包
print(abc.__closure__) # 返回None 不是闭包
"""

locals 和 globals

# ###  locals 和 globals

"""
# ###locals 获取当前作用域的所有内容

如果在函数里:获取locals()调用之前的,当前作用域所有内容
如果在函数外:获取locals()返回值的 打印前,当前作用域所有内容
"""
aaa = 111
def func():
    a = 5
    b = 6
    c = 99
    res = locals()
    print(res)
func()
res = locals()
bbb = 222
print(res)


"""
# ###globals  获取全局作用域的所有内容
如果在函数里: 获取globals()所在函数 调用之前的,全局作用域所有内容
如果在函数外: 获取globals()返回值的 打印前的,全局作用域所有内容
"""
aa1 = 5
bb1 = 9
res = globals()
print(res)

def func():
    a111 = 1
    b222 = 2
    res = globals()
    print(res)
func()
res = globals()
print(res)


# ###利用globals 动态创建全局变量
'''
globals() 
返回全局命名空间所有键值对(系统的字典) , 
键是变量名 值:变量所指向的那个指
'''
dictvar = globals()
print(dictvar)
# 声明一个全局变量opesn  他的值是hello world
dictvar["opesn"] = "hello world"
print(opesn)

# ###利用globals可以实现批量创建全局变量
# 动态创建5个变量p1~p5 
def vars():
    for i in range(1,6):
        dictvar = globals()
        dictvar["p%d" %(i)] = i
vars()
print(p1)
print(p2)
print(p3)
print(p4)
print(p5)

闭包特点意义

# 闭包的特点:
'''
内函数使用了外函数的局部变量,外函数的局部变量与内函数发生绑定,延长该变量的生命周期
(实际内存给它存储了这个值,暂时不释放)
'''
def outer(num):
	def inner(val):
		return num + val
	return inner
func = outer(5)  # func = inner
res = func(10)   # inner(10)  return 5 + 10 => 15
print(res)
'''
inner 是一个闭包,
func = outer(5) num接收到了5,因为num在内函数inner有所使用,
num与inner 发生绑定,帮你存在内存里,暂时不释放,延长num变量的生命周期

res = func(10)
相当于inner(10) val接收到了参数10  return num + val  ==>5 + 10 =>15
return 5 + 10 => 15
res = 15
'''


# 闭包的意义:
'''
闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用.外部无法访问.
'''
# 模拟鼠标点击操作
click_num = 0
# 鼠标点击方法
def func():
	global click_num
	click_num += 1
	return click_num
res = func()
res = func()
res = func()
print(res)
# click_num 被暴露在不安全的位置,随时都可能被任意修改
click_num = 100
res = func()
res = func()
print(res)


# 使用闭包进行改写
def func():
    click_num = 0
    def func2():
        nonlocal click_num
        click_num += 1
        return click_num
    return func2
func = func()	# 返回的是func2  相当于func = func2
res = func()
res = func()
res = func()
res = func()
print(res)
# click_num 放到函数当中,被隐藏起来,外界无法对click_num进行干扰,形成了封装保护的作用。
click_num = 100
res = func()
res = func()
print(res)

递归函数

# ### 递归函数 
'''
递归函数:自己调用自己的函数
递:去
归:回
一去一回是递归
'''
def digui(n):
    print(n,"<==1==>") #n = 1
    if n > 0:
        digui(n-1)#digui(0)
    print(n,"<==2==>")
digui(5)

"""
# 伪代码
def digui(n)
	print(5)
		print(4)
			print(3)
				print(2)
					print(1)
						print(0)
						print(0)
					print(1)
				print(2)
			print(3)
		print(4)
	print(5)
"""

"""
# 去的过程
n = 5 print(5,"<==1==>") 5>0 digui(5-1) => digui(4)  暂停代码在第12行 相当于加了阻塞
n = 4 print(4,"<==1==>") 4>0 digui(4-1) => digui(3)	 暂停代码在第12行 相当于加了阻塞
n = 3 print(3,"<==1==>") 3>0 digui(3-1) => digui(2)  暂停代码在第12行 相当于加了阻塞
n = 2 print(2,"<==1==>") 2>0 digui(2-1) => digui(1)  暂停代码在第12行 相当于加了阻塞
n = 1 print(1,"<==1==>") 1>0 digui(1-1) => digui(0)  暂停代码在第12行 相当于加了阻塞


n = 0 print(0,"<==1==>") 0不大于0 条件不成立 
执行第13行
print(0,,"<==2==>")

触底反弹,执行回的过程, 回到上一层调用的位置
# 回的过程
n = 1  从12行往下执行 走13行 打印print(1,"<==2==>") 
n = 2  从12行往下执行 走13行 打印print(2,"<==2==>") 
n = 3  从12行往下执行 走13行 打印print(3,"<==2==>") 
n = 4  从12行往下执行 走13行 打印print(4,"<==2==>") 
n = 5  从12行往下执行 走13行 打印print(5,"<==2==>") 
"""

# 栈桢空间 : 栈桢空间是用来运行函数的,调用函数就是开辟栈桢空间的过程,调用结束之后,会自动释放栈桢空间。

"""
(1) 去的过程: 每调用一次函数,就开辟一个栈桢空间,每结束一个函数,就释放一层栈桢空间,而递归本质上就是开辟和释放栈桢空间的过程
(2) 回的过程: 当最后一层调用结束之后(触底反弹),要回到上一层调用处,从上一层栈桢空间继续向下执行未完成的代码,直到结束,不停的找上一层,以此类推。
(3) 切记给递归添加一个跳出的条件,防止内存溢出,如果递归的层数过多,不推荐使用  					
"""


# ### 递归函数:
'''
递归回的时候,需要触底反弹
(1) 当前这层栈桢空间里面的代码全部执行完毕,会自动的回到上一层栈桢空间(上一层函数)
(2) 当前函数遇到返回值return , 回到上一层栈桢空间
'''

# 5的阶乘
def func(n):
    total = 1
    for i in range(1,n+1):
        total *= i
    print(total)
func(5)

# 求任意数n的阶乘  5! = 5*4*3*2*1  99! = 99*98*97*96... * 1    3!=3*2*1  0! = 1
def jiecheng(n):
    if n <= 1:
        return 1
    #返回一个 谁*谁
    return n * jiecheng(n-1)
res = jiecheng(5)
print(res)
"""
先计算return 后面的表达式,计算完毕之后再返回 先计算再返回
# 代码解析:
# 去的过程
n = 5  5 * jiecheng(5-1) => 5 * jiecheng(4)
n = 4  4 * jiecheng(4-1) => 4 * jiecheng(3)
n = 3  3 * jiecheng(3-1) => 3 * jiecheng(2)
n = 2  2 * jiecheng(2-1) => 2 * jiecheng(1)
n = 1  return 1

# 因为有返回值 触底反弹 开始执行回的过程
# 回得过程
n = 2  2 * jiecheng(2-1) => 2 * jiecheng(1) => return 2 * 1
n = 3  3 * jiecheng(3-1) => 3 * jiecheng(2) => return 3 * 2 * 1
n = 4  4 * jiecheng(4-1) => 4 * jiecheng(3) => return 4 * 3 * 2 * 1
n = 5  5 * jiecheng(5-1) => 5 * jiecheng(4) => return 5 * 4 * 3 * 2 * 1

最终把return 5*4*3*2*1 返回出来 赋值给res 函数调用完毕;
"""


# 返回时 只返回递归函数自己 完成阶乘 是否可以实现?
# ### 尾递归:只返回函数自己本身,而非表达式(不带有运算的)
'''
尾递归:在内存里只开辟一个栈桢空间,节省内存,受解释器的限制(cpython不支持,大型服务器可以)
尾递归是利用参数来进行运算的
'''
def jiecheng2(n,endval):
    if n <= 1:
        return endval
    return jiecheng2(n-1,n*endval)	#4*5*1
res = jiecheng2(5,1)
print(res)
'''
#代码解析:
# 去的过程
n = 5 return jiecheng2(5-1,5*1)      => return jiecheng2(4,5*1)
n = 4 return jiecheng2(4-1,4*5*1)    => return jiecheng2(3,4*5*1)
n = 3 return jiecheng2(3-1,3*4*5*1)  => return jiecheng2(2,3*4*5*1)
n = 2 return jiecheng2(2-1,2*3*4*5*1)=> return jiecheng2(1,2*3*4*5*1)
n = 1 return endval

# 回的过程
n = 5 return jiecheng2(5-1,5*1)      => return endval
n = 4 return jiecheng2(4-1,4*5*1)    => return endval
n = 3 return jiecheng2(3-1,3*4*5*1)  => return endval
n = 2 return jiecheng2(2-1,2*3*4*5*1)=> return endval
n = 1 return endval
'''

# ###优化版
# 定义一个只有一个参数的尾递归函数
def jiecheng2(n,endval):
    if n <= 1:
        return endval
    return jiecheng2(n-1,n*endval)
# 外层套了一个壳
def jiecheng3(n):
    # 里面真正计算的jiecheng2
    return jiecheng2(n,1)	# return 120
res = jiecheng3(5)	# res  = 120
print(res)


# ###斐波那契数列
'''
给参数第几个,返回对应值
1,1,2,3,5,8,13,21,..... n?
'''
# 找第五个值5
# 第四个值 + 第三个值
def fib(n):
    if n == 1 or n == 2:
        return 1
    # 参数是第几个  return 上一个  +  上上个
    return fib(n-1) + fib(n-2)
res = fib(5)
print(res)
'''
n  = 5
fib(4) + fib(3) =>  3 + 2 => 5

# ###fib(4)   => 3
fib(3)                     +                fib(2)
fib(2)+fib(1) => 1+1 => 2  +  1  => 3

# ###fib(3)
fib(2) + fib(1) => 1+1=>2
'''

匿名函数

# ###匿名函数 (lambda 表达式)
"""
只用一句话来表达只有返回值的函数,简洁方便
lambda 参数 : 返回值
"""

# (1)不带参数的lambda表达式
def func():
	return "开挂的人生需要解释么?不需要解释么?"
	
res = func()
print(res)


# lambda 改写
func = lambda  :  "开挂的人生需要解释么?不需要解释么?"
res = func()
print(res)


# (2)带参数的lambda表达式
def func(n):
	return type(n)
res = func(15)
print(res)

#用lambda 改写
func = lambda n : type(n)
res = func(27)
print(res)

def func(n):
	print(n)

#用lambda 改写
func = lambda n : print(n)
res = func(13)
print(res)


# (3)带有条件分支的lambda表达式
def func(n):
    if n % 2 == 0:
        return "偶数"
    else:
        return "奇数"
res = func(11)
print(res)

# 用lambda 改写
func = lambda n : "偶数" if n % 2 == 0 else "奇数"
res = func(13)
print(res)

#给2个参数,返回较大值
def mymax(x,y):
    if x > y:
        return x
    else:
        return y
func = lambda x,y : x if x > y else y
res = func(12,-19)
print(res)

'''
# 三元运算符
真区间值 if  条件表达式  else 假区间值
'''
res = "真" if 19 % 2 == 1 else "假"
print(res)

n = 801
res = "偶数" if n % 2 == 0 else "奇数"
print(res)

迭代器

# ### 迭代器 : 能够被next调用,并不断返回下一个值得对象是迭代器(迭代器是对象)
"""迭代器会生成一个惰性序列,不是一股脑把所有数据放到内存里面,
而是通过算法,一次只获取一个数据,一个数据只占用一个空间
迭代器可以遍历无限量的数据
"""

"""
特点
	1.惰性序列,节省内存空间
	2.遍历获取值得时候使用next,方向不可逆
	3.迭代器可以遍历无限量大的数据
"""

# 1.可迭代对象
'''
1.判断该类型可迭代 __iter__
'''
setvar = {"a",2,"c","b"}
for i in setvar:
    print(i)
# dir获取对象所有内置方法
listvar = dir(setvar)
print(listvar)
print("__iter__" in listvar)

# 2.迭代器
'''
for循环数据的时候,系统默认会把要循环的可迭代对象变成迭代器,通过next方法进行调用 (next单向不可逆)
把可迭代对象变成一个迭代器 iter(对象)  对象.__iter__()
进行调用时候 可以使用next(迭代器) 或者 迭代器.__next__()
# try .. except .. 捕获异常 抑制错误
判断迭代器类型 需要两个条件 __iter__ __next__ 两个方法同时存在,证明是一个迭代器

可迭代对象 -> 迭代器  从不可被调用 -> 可被调用的过程
'''
# it1 = iter(setvar)   #方法一
it1 = setvar.__iter__()#方法二
print(it1)
res = next(it1)
print(res)
res = next(it1)
print(res)
res = next(it1)
print(res)
res = it1.__next__()
# res = next(it1)
print(res)
#通过next调用,要避免越界
# res = next(it1)
# print(res)
listvar = dir(it1)
print(listvar)
print('__iter__' in listvar and '__next__' in listvar)


# 3.可以通过 Iterable 和 Iterator 两个类型 判断是否是可迭代对象或迭代器
# from 从哪里 collections模块 import引入 Iterable类型(可迭代性) Iterator类型(迭代器)
setvar = {'a',2,'c','b'}
from collections import Iterable,Iterator

# 判断setvar的迭代属性
res = isinstance(setvar,Iterable)
print(res)  # True
res = isinstance(setvar,Iterator)
print(res)  # False
print("<===>")

# 判断range的迭代属性
res = isinstance(range(5),Iterable)
print(res)
res = isinstance(range(5),Iterator)
print(res)

# 把range对象变成迭代器
it2 = iter(range(10))
res = isinstance(it2,Iterable)
print(res)
res = isinstance(it2,Iterator)
print(res)

# 4.遍历迭代器
for i in it2:
    print(i)
# next 获取值得时候,只能是单一方向,不会回头,不可逆 ,如果迭代器到最后没有值了还调用就越界报错
# next(it2)

# 重置迭代器
it2 = iter(range(7))
for i in range(3):
    res = next(it2)
    print(res)

高阶函数 map

# ### 高阶函数 能够把函数当成参数进行传递的就是高阶函数(map reduce sorted filter)
"""
map(func,iterable)
功能:把iterable里面的数据一个一个的那到func函数当中进行处理,最终返回到迭代器中
参数:
	func 自定义函数 或者  内置函数
	iterable :可迭代性数据(常用:容器类型数据 range对象 迭代器)
返回值:迭代器
"""
# ###(1)["1","2","3","4"]  => [1,2,3,4]
listvar = ["1","2","3","4"]
print(listvar)
list2 = []
for i in listvar:
    res = int(i)
    list2.append(res)
print(list2)
'''
首先把“1”拿到int当中进行强转=> 1 ,把1扔到迭代器中
在吧“2”拿到int当中进行强转=> 2,把2扔到迭代器中
在吧“3”拿到int当中进行强转=> 3,把3扔到迭代器中
在吧“4”拿到int当中进行强转=> 4,把4扔到迭代器中
'''
listvar = ["1","2","3","4"]
it1 = map(int,listvar)
print(it1)
from collections import Iterable,Iterator
print(isinstance(it1,Iterable))
print(isinstance(it1,Iterator))

# (1)使用for拿出迭代器里面所有数据
for i in it1:
    print(i,type(i))
    
# (2)使用next拿出迭代器里面所有数据
it1 = map(int,listvar)
res = next(it1)
res = next(it1)
res = next(it1)
res = next(it1)
print(res)

# (3)使用list强转迭代器 (把迭代器里面的数据瞬间强转成列表)
it1 = map(int,listvar)
res = list(it1)
print(res)


# ###(2) [1,2,3,4] => [1,4,9,16]
listvar = [1,2,3,4]
listvar2 = []
for i in listvar:
    res = i ** 2
    listvar2.append(res)
print(listvar2)

'''
把列表中的元素一个一个的放到func自定义函数中,
n接受参数,return返回到迭代器当中
最后把迭代器统一返回
'''
def func(n):
    #在自定义函数当中,务必使用return将值返回,返回到迭代器里面
    return n ** 2
listvar = [1,2,3,4]
it2 = map(func,listvar)
# 使用list强转 瞬间得到所有数据
print(list(it2))


# ###(3) dictvar = {97:"a",98:"b",99:'c',100:'d',101:'e'} ["a","c","b"]  => [97,99,98]
# map
dictvar = {97:"a",98:"b",99:"c",100:"d",101:"e"}
listvar = ["a","c","b"]
listvar2 = []
dictvar2 = {}
for k,v in dictvar.items():
    dictvar2[v] = k
print(dictvar2)

for i in listvar:
    listvar2.append(dictvar2[i])
print(listvar2)

print("<==>")

listvar = ["a","b","c"]

def func(n):
    dictvar = {97:"a",98:"b",99:'c',100:'d',101:'e'}
    dictvar2 = {}
    for k,v in dictvar.items():
        dictvar2[v] = k
    #{"a":97,"b":98,'c':99,'d':100}
    return dictvar2[n]
it2 = map(func,listvar)
print(list(it2))

高阶函数 reduce

# ### reduce
'''
reduce(func,iterable)
功能:计算
	   一次性从iterable里拿出2个值,扔到func函数当中做运算,把运算的结果和iterable当中的下一个数据(第三个),在扔到func函数当中做运算,以此类推
	   直到iterable当中的数据全部拿完为止
参数:func 自定义的函数 或者 内置函数
	  iterable 可迭代性数据(常用:容器类型数据  range对象 迭代器)
返回值:
	   计算最后的结果
'''

# (1)[5,4,8,8]   =>   整型5488
listvar = [5,4,8,8]

# 第一种
listvar = [5,4,8,8]
strvar = ""
for i in listvar:
    strvar += str(i)
print(strvar,type(strvar))
intvar = int(strvar)
print(intvar,type(intvar))

# 第二种
"""
5*10+4 = 54
54*10+8 = 548
548*10+8=5488

谁 * 10 + 谁
x*10 + y
"""


"""
首先第一次拿出列表中的5和4
放到func当中运算,得出return 5*10+4 = 54
那54和列表当中的第三个值8 扔func当中运算 return 54 * 10 + 8 = 548
拿548和最后一个元素8扔func当中运算 return 548 * 10 + 8 = 5488 
拿完所有数据之后 ,直接返回。
"""
def func(x,y):
    return x*10 + y
listvar = [5,4,8,8]
# from 从哪里   functools 模块名 import 引入 reduce
from functools import reduce
res = reduce(func,listvar)
print(res,type(res))

# (2)在不用int强转的情况下 如何实现 "789" => 789
# "789" => [7,8,9] => 789
listvar = [7,8,9]
def func(x,y):
    # 将值进行计算 第一次拿两个参数,依次拿取迭代器中的值,如果没有了,返回该数据
    return x * 10 + y

def func2(n):
    # 字典,定义字符串和整形实际的对应关系,依据字典挨个返回
    dictvar = {"0":0,"1":1,"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9}
    # 返回到迭代器中
    return dictvar[n]
it1 = map(func2,"789") # "789" => 迭代器中已经放入 7 , 8 , 9 
res = reduce(func,it1)  # it1 是迭代器
print(res,type(res))

高阶函数 sorted

# ### sorted
"""
sorted(iterable,reverse=False,key=函数)
功能:排序
参数:iterable:可迭代性数据
	   reverse:是否倒序  reverse=True (倒序,降序) reverse = False(正序,升序)
	   key:后面指定函数 自定义的函数 或 内置函数
返回值:
	   排序后的数据
"""
listvar = [-1,99,78,-33]
listvar = (3.14,56,-9,1)
strvar = "abppuiq"
# (1)从小到大排序  默认升序 reverse = False
res = sorted(listvar)
print(res)

# (2)从大到小排序 reverse=True 倒序
res = sorted(strvar,reverse=True)
print(res)

# (3)使用内置函数进行排序
# abs 绝对值函数
# res = abs(1)
# print(res)
listvar = [-1,22,78,-33]
res = sorted(listvar,key=abs)
print(res)
"""
# abs(-1) => 1
# abs(-33) => 33
# abs(78) =>78
# abs(22) => 22
"""

# (4)使用自定函数进行排序
listvar = [91,29,28,45,73]
# 按照余数排序
def func(n):
    return n % 10
res = sorted(listvar,key=func)
print(res)
"""
91 => 1
73 => 3
45 => 5
28 => 8
29 => 9
"""

"""
sorted 和 列表中的方法sort 从用法上来说是一样的,不一样在于
一个是产生一个新的列表
一个是基于原有列表修改
如此而已其他一样
listvar = [-1,99,78,-33]
listvar.sort(key=func)
print(listvar)
"""

高阶函数 filter

# ###filter
"""
filter(func,iterable)
功能:过滤数据  
	   
参数:
	func : 自定义函数(如果返回True 要这个数据 如果返回False 代表舍弃这个数据)
	iterable:可迭代性数据(常用:容器类型数据 range对象 迭代器)
返回值:迭代器
"""
listvar = [1,2,3,4,5,6,7,8,9]
# 过滤所有的奇数 要偶数

'''
把列表当中的每一个值一一放进func函数当中进行判断
如果该值返回True 则保留此值,扔到迭代器中
如果该值返回False 则舍弃此值,再去拿下一个直到结束
'''
def func(n):
    if n % 2 == 0:
        return True
    else:
        return False
it = filter(func,listvar)
from collections import Iterable,Iterator
print(isinstance(it,Iterator))
#使用list强转 瞬间得到所有数据
print(list(it))

# 优化版
it2 = filter(lambda n : True if n % 2 == 0 else False,listvar)
print(list(it2))

推导式

通过一行循环判断,遍历出一系列数据的方式是推导式
语法: val for val in Iterable (把想要的值写在 for的左侧)
里面是一行循环判断!根据套在推导式外层的符号判断具体是什么类型的推导式

推导式种类三种:
    [val for val in Iterable]  列表推导式
    {val for val in Iterable}  集合推导式
    {a:b for a,b in iterable}  字典推导式

列表推导式,集合推导式,字典推导式的相关写法
(1)普通推导式
(2)带有判断条件的推到式
(3)多循环推到式
(4)带有判断条件的多循环推到式

列表推导式

# ### 推导式  通过一行循环判断,遍历出一系列数据的方式
"""
推导式 语法: i for i in iterable  把循环想要的数据扔到for的左侧
"""

# 1.普通推导式:
# [1,2,3,4] => [2,8,24,64]
listvar = [1,2,3,4]
"""
1 * 2的一次方
2 * 2的二次方
3 * 2的三次方
4 * 2的四次方
"""
"""
listvar = [1,2,3,4]
lst = []
for i in listvar:
    res = i << i
    lst.append(res)
print(lst)
"""
# 基本语法
listvar = [1,2,3,4]
res = [i for i in range(1,5)]
print(res)
lst = [i << i for i in listvar ]
print(lst)

# 2.带有判断条件推导式  最终值 + 推导式 + 单向分支
# [1,2,3,4,5,6,7,8,9,10,11] => [2,4,6,8,10]
listvar = [1,2,3,4,5,6,7,8,9,10,11]
"""
lst = []
for i in listvar:
    if i % 2 == 0:
        lst.append(i)
print(lst)
"""
lst = [i for i in listvar if i % 2 == 0]
print(lst)


# 3.多循环推导式 "谁" * "谁"
list1 = ["a","b","c","d","e"]
list2 = ["aa","bb","cc","dd","ee"]
"""
listvar = []
for i in list1:
    for j in list2:
        strvar = i + "*" + j
        listvar.append(strvar)
print(listvar)
"""
lst = [i + '*' + j for i in list1 for j in list2]
print(lst)


# 4.带有判断条件的多循环推导式
list1 = ["a","b","c","d","e"]
list2 = ["aa","bb","cc","dd","ee"]
"""
lst = []
for i in list1:
    for j in list2:
        if list1.index(i) == list2.index(j):
            strvar = i + "*" + j
            lst.append(strvar)
print(lst)
"""
lst = [i + "*" + j for i in list1 for j in list2 if list1.index(i) == list2.index(j)]
print(lst)




# ###1.{'x': 'A', 'y': 'B', 'z': 'C' } 把字典写成x=A,y=B,z=C的列表推导式
dictvar = {'x': 'A', 'y': 'B', 'z': 'C' }
listvar = [k+"="+v for k,v in dictvar.items()]
print(listvar)

# ###(2).把列表中所有字符变成小写  ["ADDD","dddDD","DDaa","sss"]
listvar = ["ADDD","dddDD","DDaa","sss"]
res = [i.lower() for i in listvar]
print(res)

# ###(3) x是0-5之间的偶数,y是0-5之间的奇数 把x,y组成一起变成元组,放到列表当中
listvar = []
'''
# 方法一
for x in range(0,6):
	if x % 2 == 0:
		for y in range(6):
			if y %2 == 1:
				res = x,y
				listvar.append(res)
print(listvar)
'''
lst = [ (x,y) for x in range(6) if x % 2 == 0 for y in range(6) if y % 2 == 1]
print(lst)
'''
# 方法二
listvar = []
for x in range(6):
	for y in range(6):
		if x % 2 == 0 and y % 2 == 1:
			res = x,y
			listvar.append(res)
print(listvar)
'''
lst = [(x,y) for x in range(6) for y in range(6) if x%2== 0 and y %2 ==1]
print(lst)

# ###(4).使用列表推导式 制作所有99乘法表中的运算
"""
for i in range(1,10):
	for j in range(1,i+1):
		print("{:d}*{:d}={:2d} ".format(i,j,i*j),end="")
	print()
"""
list2 = ["{:d}*{:d}={:2d} ".format(i,j,i*j) for i in range(1,10) for j in range(1,i+1)]
print(list2)
"""
for i in range(9,0,-1):
	for j in range(1,i+1):
		print("{:d}*{:d}={:2d} ".format(i,j,i*j),end="")
	print()
"""
list3 = ["{:d}*{:d}={:2d} ".format(i,j,i*j) for i in range(9,0,-1) for j in range(1,i+1)]
print(list3)


###(5)#求M,N中矩阵和元素的乘积
# M = [ [1,2,3], 
#       [4,5,6], 
#       [7,8,9]  ] 

# N = [ [2,2,2], 
#       [3,3,3], 
#       [4,4,4]  ] 
# =>实现效果1   [2, 4, 6, 12, 15, 18, 28, 32, 36]
# =>实现效果2   [[2, 4, 6], [12, 15, 18], [28, 32, 36]]

M = [[1,2,3],[4,5,6],[7,8,9]]
N = [[2,2,2],[3,3,3],[4,4,4]]
"""
M[0][0] * N[0][0] = 2
M[0][1] * N[0][1] = 4
M[0][2] * N[0][2] = 6

M[1][0] * N[1][0] = 12
M[1][1] * N[1][1] = 15
M[1][2] * N[1][2] = 18

M[2][0] * N[2][0] = 12
M[2][1] * N[2][1] = 15
M[2][2] * N[2][2] = 18
"""
# 效果1
lst = [M[i][j] * N[i][j] for i in range(3) for j in range(3)]
print(lst)

# 原型
# lst = [ [] , [] , [] ]
# print(lst)

# 效果2
lst = [ [M[i][j] * N[i][j] for j in range(3)] for i in range(3) ]
print(lst)


# next 单向不可逆
'''
it1 = iter(range(3))
it2 = iter(range(3))
listvar = [(i,j) for i in it1 for j in it2]
print(listvar)
# 0,0 0,1 0,2
'''

集合推导式

# ### 集合推导式
"""
案例:
	满足年龄在18到21,存款大于等于5000 小于等于5500的人,
	开卡格式为:尊贵VIP卡老x(姓氏),否则开卡格式为:抠脚大汉卡老x(姓氏)	
	把开卡的种类统计出来
"""
listvar = [
    {"name":"张三","age":18,"money":10000},
    {"name":"张四","age":19,"money":5100},
    {"name":"李四","age":20,"money":4800},
    {"name":"李五","age":21,"money":2000},
    {"name":"王五","age":180,"money":20}
]
# 三目运算符 + 推导式   推导式把相应的值扔左边,至于集合里面塞什么值取决于三目运算符
setvar = {"尊贵VIP卡老" + i["name"][0] if 5000 <= i["money"] <= 5500 and 10 <= i["age"] <= 21 else "抠脚大汉卡老" + i["name"][0] for i in listvar}
print(setvar)

字典推导式

# ###字典推导式
'''
### (1)enumerate
enumerate(iterable,[start=0])
功能:枚举 ; 将索引号和iterable中的值,一个一个拿出来配对组成元组放入迭代器中
参数:
    iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range) 
    start:  可以选择开始的索引号(默认从0开始索引)
返回值:迭代器
'''
# (1)enumerate形成字典
listvar = ["python","shell","java","Go","js","vue","html"]
it1 = enumerate(listvar)
print(it1)
from collections import Iterator,Iterable
print(isinstance(it1,Iterator))
# 遍历迭代器
for i in it1:
    print(i)
    
print("<===>")
# 通过for 和 next 进行遍历
it1 = enumerate(listvar,start=5)
for i in range(3):
    res = next(it1)
    print(res)

# 转化成字典推导式
it1 = enumerate(listvar,start=5)
"""
dictvar = {k:v for k,v in it1}
print(dictvar)
"""
# 通过dict强转迭代器
print(dict(it1))


'''
### (2)zip
zip(iterable, ... ...)
    功能: 将多个iterable中的值,一个一个拿出来配对组成元组放入迭代器中
    iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range) 
返回: 迭代器
'''
list1 = ["python","Go","shell","java"]
list2 = ["html","js","vue","css"]
# (1) 用zip形成字典
from collections import Iterator,Iterable
it2 = zip(list1,list2)
print(isinstance(it2,Iterator))

# 遍历迭代器
for i in it2:
    print(i)
    
# 通过zip字典推导式
dictvar = {k:v for k,v in zip(list1,list2)}
print(dictvar)
# 通过dict强转迭代器
print(dict(zip(list1,list2)))


#(2) 把字典1中的键和字典2中的值组装成新字典
dict1 = {"a":"111","b":"222","c":"333"}
dict2 = {0:"张三",1:"李四",2:"王五"}
"""
keys = dict1.keys()
print(keys)
values = dict2.values()
print(values)
print(isinstance(values,Iterable))
print(isinstance(values,Iterator))
"""

# 用字典推导式实现
dictvar = {k:v for k,v in zip(dict1.keys(),dict2.values())}
print(dictvar)

# 用dict强转迭代器
dictvar = dict(zip(dict1.keys(),dict2.values()))
print(dictvar)

生成器表达式

# ### 生成器表达式
'''
#元组推导式的返回值是一个生成器对象,简称生成器,生成器本质就是迭代器.

#迭代器和生成器区别:
	迭代器本身是系统内置的.重写不了.而生成器是用户自定义的,可以重写迭代逻辑

#生成器可以用两种方式创建:
    (1)生成器表达式  (里面是推导式,外面用圆括号)
    (2)生成器函数    (用def定义,里面含有yield)
'''
from collections import Iterator
# 4 8 12 16
gen = (i << 2 for i in range(1,5))
print(gen)
print(isinstance(gen,Iterator))

#(1)使用next方法进行调用
res = next(gen)
res = next(gen)
res = next(gen)
res = next(gen)
# res = next(gen)
print(res)

#(2)使用for循环
gen = (i << 2 for i in range(1,5))
for i in gen:
	print(i)

#(3)next 和 for 搭配使用
gen = (i << 2 for i in range(1,5))
for i in range(2):
	res = next(gen)
	print(res)

#(4)使用list瞬间强转成列表
gen = (i << 2 for i in range(1,5))
print(list(gen))

生成器函数

# ###生成器函数
'''
# yield 类似于 return
共同点在于:执行到这句话都会把值返回出去
不同点在于:yield每次返回时,会记住上次离开时执行的位置 , 下次在调用生成器 , 会从上次执行的位置往下走
		   而return直接终止函数,每次重头调用.
yield 6 和 yield(6) 2种写法都可以 yield 6 更像 return 6 的写法 推荐使用
'''
from collections import Iterator
# (1)生成器函数
def mygen():
    print("one")
    yield 1
    print("two")
    yield 2
    print("three")
    yield 3
gen = mygen()
print(gen)
# 判断类型
print(isinstance(gen,Iterator))
res = next(gen)
res = next(gen)
res = next(gen)
print(res)
"""
首先初始化生成器函数 返回一个生成器对象 简称生成器
使用next进行调用
第一次 直接print(one) yield 1 记录当前的执行状态,将1返回,暂停等待下一次调用
第二次 直接print(two) yield 2 记录当前的执行状态,将2返回,暂停等待下一次调用
第三次 直接print(three)yield 3 记录当前的执行状态,将3返回,此时已经没有更多值,在调用会报错,生成器结束
"""


# (2)优化生成器
def func():
    for i in range(1,101):
        # print("我球衣的号码是%d" % (i))
        yield "我球衣的号码是%d" %(i)
# 初始化生成器函数 =>  产生一个生成器对象 简称生成器
gen = func()
for i in range(50):
    res = next(gen)
    print(res)

for i in range(30):
    res = next(gen)
    print(res)
    
    
# (3)用生成器写斐波那契数列?
def mygen(maxlength):
    a = 0
    b = 1
    i = 0
    while i < maxlength:
        yield b
        a,b = b,a+b
        i += 1
# 初始化生成器函数
gen = mygen(10)
print(list(gen))
'''
# 代码解析:
a = 0 , b = 1
yield 1  记录当前执行状态,返回1 ,等待下一次调用

a,b = b,a+b
a = 1 , b = 1
yield 1  记录当前执行状态,返回1 ,等待下一次调用

a,b = b,a+b
a = 1 , b = 2
yield 2  记录当前执行状态,返回2 ,等待下一次调用

a,b = b,a+b
a = 2 , b = 1+2 = 3
yield 3  记录当前执行状态,返回3 ,等待下一次调用

...
...
...

'''
# 使用for 循环直接遍历生成器
# for i in gen:
#     print(i)

for i in range(3):
    res = next(gen)
    print(res)
    
    
# (4)生成器 send :把值返回到上一个yield
'''
### send
# next和send区别:
	next 只能取值
	send 不但能取值,还能发送值
# send注意点:
	第一个 send 不能给 yield 传值 默认只能写None
	最后一个yield 接受不到send的发送值
'''
print('<===>')
def mygen():
    print("start")
    res = yield 1
    print(res)

    res = yield 2
    print(res)

    res = yield 3
    print(res)
# 初始化生成器函数 返回生成器
gen = mygen()
# 生成器中有send方法,负责发送值给上一个yield ,但是第一次使用send时是没有的。只能在send的参数中加None
val = gen.send(None)
val = gen.send("111")
val = gen.send("222")
# val = gen.send("3333")  # error 越界报错
print(val)
"""
send 先发送 在返回
res = gen.send(None) 执行到106行,记录当前状态,返回yield 1,暂停等待下一次调用
通过send "1111" 给上一个116行的yield 进行接收 往下执行打印1111 ,执行res = yield 2 ,记录当前执行状态 返回2 ,暂停等待下一次调用
通过send “2222” 给上一个119行的yield 进行接收 往下执行打印2222, 执行res = yield 3 ,记录当前执行状态 返回3 ,暂停等待下一次调用
通过send “3333” 给上一个122行的yield 进行接收 往下执行打印3333, 但是没有yield在继续返回了,所以越界报错
"""

### yield from : 将一个可迭代对象变成一个迭代器返回	
def mygen():
    listvar = ["python","shell","Go","java"]
    yield from listvar
# 初始化生成器函数 返回 生成器
gen = mygen()
print(gen)

for i in gen:
    print(i)

python 常用内置函数

# ###常用内置函数
# 1.abs    绝对值函数
res = abs(-444)
print(res)

# 2.round  四舍五入 (n.5 n为偶数则舍去 n.5 n为奇数,则进一!)
"""n.5的情况 奇进偶不进"""
print(round(4.5))
print(round(11.5))
print(round(44.55))
print(round(44.6))
print(round(47.78))
print(round(44.5000000000000000000000000000000000000000000000000000000001))

# 3.sum    计算一个序列得和
listvar = [13,15,99,11]
res = sum(listvar)
print(res)

# 4.min    获取一个序列里边的最小值
listvar = [i for i in range(1,16,2)]
res = min(listvar)
print(res)
listvar = [-19,28,99,-100]
listvar.sort()
print(listvar)
# 取出最小值
res = listvar[0]
print(res)
# 取出最大值
res = listvar[-1]
print(res)

# 5.max    获取一个序列里边的最大值 用key=函数的形式自定义获取最大值
listvar = [("a",10),("b",1),("c",2)]
def func(n):  # n => (a,10)
	return n[-1]
# 默认按照元组当中的第一个元素进行排序获取最大值 c => 99 所以获取(c,2)
res = max(listvar)  
print(res)
# 如果指定自定义函数 获取最大值 用key = func
res = max(listvar,key = func)  
print(res)
# 字典情况下:
def func(n):
	# 自定义绝对值得大小 来决定取字典的某个键
	return abs(dictvar[n])
# 88这个值最大,就获取这个值所应对的键
dictvar = {"a":10,"b":-89,"c":88}
# key = func 是自定义函数 来获取最大值
res = max(dictvar,key=func)
print(res)
# 不指定函数,默认按照字典的键排序,取键的最大值 ,若是字符串按照ascii吗排序
res = max(dictvar)
print(res,"<===>")

# 6.pow    计算某个数值的x次方
res = pow(2,3)  #=>计算2的3次幂
print(res)
res = pow(2,3,3) #=>计算2的3次幂然后和3取余
print(res)

# 7.range  产生指定范围数据的可迭代对象
# 1 3 5 7
for i in range(1,8,2):  # 正序  
	print(i)

# 7 5 3 1
for i in range(7,0,-2): # 倒序
	print(i)

# 8.bin    将10进制数据转化为二进制
res = bin(255)
print(res)

# 9.oct    将10进制数据转化为八进制
res = oct(8)
print(res)

# 10.hex    将10进制数据转化为16进制
res = hex(255)
print(res)

# ###A a 大小写ascii吗相差32
# 11.chr    将ASCII编码转换为字符
res = chr(97)
print(res)

# 12.ord    将字符转换为ASCII编码
res = ord("A")
print(res)

# 13.eval   将字符串当作python代码执行
res = "print(\"hello world\")"
res2 = eval(res)
print(res2)

# 14.exec  将字符串当Python代码执行(更好用也要更慎用)
strvar = "a=5"
exec(strvar)
print(a)
print("<==>")
strvar = """
for i in range(5):
    print(i)
"""
exec(strvar)

# 15.repr   不转义字符 原型化输出字符串
strvar = str([1,2,3,4])
print(strvar,type(strvar))
res = repr(strvar)
res = repr("sfsd\nfssfs")
print(res)
strvar = r"D:\day013"
print(strvar)

# 16.input  接受输入字符串
res = input("先森,贵姓?:")
print(res)


# 16.hash函数 生成哈希值
"""
此hash函数是根据当前值和实际存储在内存的地址关联计算的
相同的值无论哈希多少次,都会产生具有固定长度的唯一值
"""
strvar = "人生苦短,我用python"
res1 = hash(strvar)
res2 = hash(strvar)
print(res1,len(str(res1)),res2,len(str(res2)))
# 如果hash函数能返回哈希值,意味着参数 是不可变数据(可哈希)
# 可哈希 Number(int bool float complex) str ()
# 不可哈希 list set dict
# res = hash([1,2,3])  # 列表不可哈希

python 数学模块

# ### math 数学模块 
import math

#ceil()  向上取整操作 (对比内置round)
res = math.ceil(4.5)
res = math.ceil(3.09)
# res = round(4.51)
print(res)


#floor() 向下取整操作 (对比内置round)
res = math.floor(5.9999999999999)
print(res)


#pow()  计算一个数值的N次方(结果为浮点数) (对比内置pow)
res = math.pow(2,3)
# res = math.pow(2,3,3) # 只有2个参数 区别于内置函数pow
print(res,type(res))
# print(pow(4,3,2))

#sqrt() 开平方运算(结果浮点数)
res = math.sqrt(9)
print(res)


#fabs() 计算一个数值的绝对值 (结果浮点数) (对比内置abs)
res = math.fabs(-6)
print(res)

#modf() 将一个数值拆分为整数和小数两部分组成元组
res = math.modf(13.56)
print(res)
res1 = res[1]
print(res1)  # 取出小数的整数部分,有小数点

#copysign()  将参数第二个数值的正负号拷贝给第一个 (返回一个浮点数)
# 第一个数字的符号完全取决于第二个参数的正负号
res = math.copysign(-9,-3)
print(res)

#fsum() 将一个容器数据中的数据进行求和运算 (结果浮点数)(对比内置sum)
listvar = [1,2,3,4,54]
res = math.fsum(listvar)
print(res)

#圆周率常数 pi
res = math.pi
print(res)

python 随机模块

# ### random 随机模块
import random
#random() 获取随机0-1之间的小数(左闭右开) 0 <= x < 1
res = random.random()
print(res)

#randrange() 随机获取指定范围内的整数(包含开始值,不包含结束值,间隔值) (推荐)
res = random.randrange(2)  #通range的取值范围一样
print(res)
res = random.randrange(1,4)
print(res)
res = random.randrange(1,10,3) # 1 4  7 
print(res)

#randint()   随机产生指定范围内的随机整数 (了解)
res = random.randint(1,3)  # (特殊) randint 高位可以取得到 
print(res)
# error
# res = random.randint(1,10,3) # 不能传递第三个参数
# print(res)



print('<===>')
#uniform() 获取指定范围内的随机小数(左闭右开)   1 <= x < 3
res = random.uniform(1,3)
print(res)
res = random.uniform(5,-2)
print(res)
# a = 5 b = -2
# return a + (b-a) * self.random()
# 5+ -7 * 0~1   -2 < x <= 5 


#choice()  随机获取序列中的值(多选一)
listvar = [1,2,3,4,5,6]
res = random.choice(listvar)
print(res)

'''
# 自定义choice
listvar = [1,2,3,"a","b"]
def mychoice(listvar): 
	# len(listvar) 8 
	num = random.randrange(len(listvar))
	return listvar[num]
res = mychoice(listvar)
print(res)
'''

#sample()  随机获取序列中的值(多选多) [返回列表]
'''sample(iterable,选几个)'''
listvar = ["python","java","shell","Go"]
res = random.sample(listvar,2)
print(res)


#shuffle() 随机打乱序列中的值(直接打乱原序列)
listvar = ["python","java","shell","Go"]
random.shuffle(listvar)
print(listvar)


# 验证码程序 来5个随机值
'''
找出小写a~z  ascii 97~122
找出大写A~Z  ascii 65~90
数字范围:   0~9

res = chr(97)
print(res)
'''


def yanzhengma():
	strvar = ''
	for i in range(5):
		# 随机a~z
		schar = chr(random.randrange(97,123))
		# 随机A~Z
		bchar = chr(random.randrange(65,91))
		# 随机0~9
		num = str(random.randrange(10))
		# 把元素都放在列表中
		listvar = [schar,bchar,num]
		# 5次随出的字符串进行拼接
		strvar += random.choice(listvar)
	# 返回字符串
	return strvar

res = yanzhengma()
print(res)

python 序列化模块

# ### pickle 序列化模块
"""
序列化:把不能够直接存储的数据变成可存储,这个过程叫序列化
反序列化:把存储的数据转化成原本的数据类型,这个过程叫做反序列化

php:
serialize   序列化
unserialize 反序列化
"""
# 非字符串数据不能够直接存储在文件当中,不能够持久化保存
# error 
"""
with open("0401.txt",mode="w",encoding="utf-8") as fp:
	fp.write([1,2,3,4,5])

encode decode 只能针对于字符串进行字节流的转化
res = listvar.encode("utf-8")
print(res)
"""
# 如果是非字符串需要通过序列化的形式转化成字节流在存储在文件中,进行存储
import pickle
# (1)dumps 把任意对象序列化成一个bytes
listvar = [1,2,3,4,5]
res = pickle.dumps(listvar)
print(res,type(res))

# (2)loads 把任意bytes反序列化成原来数据
# 把字节流变成人能看懂的语言 loads
res = pickle.loads(res)
print(res,type(res))

# 序列化函数
def func():
	print(122345)
res = pickle.dumps(func)
print(res)
func = pickle.loads(res)
func()

# 序列化迭代器
from collections import Iterator,Iterable
it = iter(range(9))
print(isinstance(it,Iterator))  # True 迭代器

res = pickle.dumps(it)
print(res)

res = pickle.loads(res)
for i in range(5):
	r = next(res)
	print(r)
    

#dump  把对象序列化后写入到file-like Object(即文件对象)
# 如果是字节流模式 不要制定编码集 dump 把数据写入
# listvar = [1,2,3,4]
def listvar():
	print(123)
	
with open("0401.txt",mode="wb") as fp:
	# dump ( 要序列化的数据 , 文件对象 )
	pickle.dump(listvar,fp)

#load  把file-like Object(即文件对象)中的内容拿出来,反序列化成原来数据
# load读取数据
with open("0401.txt",mode="rb") as fp:
	res = pickle.load(fp)
print(res,type(res))
# 函数的调用
res()

python 时间模块

# ### time 时间模块
import time
# time()      获取本地时间戳
# 返回一个时间戳 单位:秒
res = time.time()  
print(res)
"""
(
	tm_year = 年,
	tm_month = 月,
	tm_day = 日,
	tm _hour = 时, 
	tm_min = 分, 
	tm _sec = 秒, 
	tm _wday = 周几, 
	tm _yday = 一年中的第几天,
	tm_isdst = 是否是夏令时时间
)
"""

#mktime()        通过[时间元组]获取[时间戳] (参数是时间元组)
ttp = (2018,3,2,11,29,0,0,0,0)
res = time.mktime(ttp)
print(res)

#localtime()     通过[时间戳]获取[时间元组] (默认当前时间)
tup = time.localtime()
# 指定时间戳
tup = time.localtime(res)
print(tup)

#ctime()         通过[时间戳]获取[时间字符串] (默认当前时间)
strvar = time.ctime()
# 指定时间戳
strvar = time.ctime(res)
print(strvar)

#asctime()       通过[时间元组]获取[时间字符串](参数是时间元组)
ttp = (2020,4,10,11,28,0,1,0,0)
strvar = time.asctime(ttp)
print(strvar)

# asctime 不能够自动识别周几,需要手动调节
# 取代asctime的优化版本
"""
ttp = (2020,4,11,11,28,0,1,0,0)
res = time.mktime(ttp)
timestr = time.ctime(res)
print(timestr)
"""

#strftime()      通过[时间元组]格式化[时间字符串]  (格式化字符串,[可选时间元组参数])
print("<==>")
res = time.strftime("%Y-%m-%d %H:%M:%S")
print(res)
ttp = (2019,4,10,11,28,0,0,0,0)
fs = "%Y-%m-%d %H:%M:%S hello world"
res = time.strftime(fs,ttp)
print(res)
# windows 不支持带有中文字符的strftime

#strptime()      通过[时间字符串]提取出[时间元组]  (时间字符串,格式化字符串)
'''
strptime 两个字符串不要随意更改,要严丝合缝的进行相关占位符的替换。
'''
strvar = "某年1929,某月-2月某日-6号 某时12点某分20分:某秒30秒 hello world"
strvar2 = "某年%Y,某月-%m月某日-%d号 某时%H点某分%M分:某秒%S秒 hello world"
tup = time.strptime(strvar,strvar2)
print(tup)

#sleep()         程序睡眠等待
time.sleep(1)
print("hello world")

#perf_counter()  用于计算程序运行的时间
'''time.time() 两个时间戳相减同理;'''
startime = time.perf_counter()  # 从此刻开始计数
print(startime,type(startime))
for i in range(100000000):
	pass
endtime = time.perf_counter()
time2 = endtime - startime
print(time2)

python os模块

#  ### os 模块
import os
# (1)system()  在python中执行系统命令
os.system("ifconfig")
os.system("rm -rf 111222.txt")
os.system("touch 123.txt")

# (2)执行系统命令返回对象,通过read读取字符串 [默认转成utf-8编码集]
res = os.popen("ifconfig").read()
print(res)

# (3)listdir() 获取指定文件夹中所有内容的名称列表
listvar = os.listdir(".")
listvar = os.listdir("/home/opesn")
print(listvar)

# (4)getcwd()  获取当前文件所在的默认路径
res = os.getcwd()
print(res)

# (5)chdir()   修改当前文件工作的默认路径
# /pythonfile
os.chdir("/pythonfile")
os.system("rm -rf 222.txt")
os.system("touch ccc.txt")

# (6)environ   获取或修改环境变量 (了解)	
res = os.environ
print(res)
'''
先在家目录当中创建一个文件 opesn
里面写点内容:比如ifconfig
chmod 777 opesn 修改权限
sudo ./opesn 确保脚本可以运行成功

如果使用python执行opesn,发现无法执行
因为系统变量path当中没有该路径,找不到
于是乎,在environ['PATH']当中 追加该路径,系统就可以找到
os.environ 返回的是环境变量和值之间的字典
所以操作如下:
'''
# 获取系统的所有环境变量
print(os.environ['PATH'])
# os.environ['PATH'] = os.environ['PATH'] +   ":/home/opesn/myself"
os.environ['PATH'] += ":/home/opesn/myself"
os.system("opesn")

# ###os 模块属性
# (1)name 获取系统标识   linux,mac ->posix      windows -> nt
print(os.name)
# (2)sep 获取路径分割符号  linux,mac -> /       window-> \
print(os.sep)
# windows => C:\data  linux =>/usr/local/games:
res = os.sep+"sdfsd"+os.sep+"aaaa"
print(res)

# (3)linesep 获取系统的换行符号  linux,mac -> \n    window->\r\n 或 \n
print(repr(os.linesep))

python os.path 路径模块

# ### os.path 路径模块
import os
#abspath()  将相对路径转化为绝对路径
res = os.path.abspath(".")  #/mnt/hgfs/mywork/day015
print(res)

#basename() 返回文件名部分
strvar = "/mnt/hgfs/abc/ccc/23.txt"
res = os.path.basename(strvar)
print(res)

#dirname()  返回路径部分
strvar = "/mnt/hgfs/abc/ccc/23.txt"
res = os.path.dirname(strvar)
print(res)

#*** split() 将路径拆分成单独的文件部分和路径部分 组合成一个元组
res = os.path.split(strvar)
print(res)

#*** join()  将多个路径和文件组成新的路径 可以自动通过不同的系统加不同的斜杠  linux / windows\
path1 = "home"
path2 = "opesn"
path3 = "myself"
res = os.path.join(path1,path2,path3)
print(res)

#splitext() 将路径分割为后缀和其他部分
strvar = "/mnt/hgfs/abc/ccc/23.txt"
res = os.path.splitext(strvar)
print(res)

#*** getsize()  获取文件的大小
res = os.path.getsize("abc.sh")
print(res)

#*** isdir()    检测路径是否是一个文件夹
res = os.path.isdir("123.txt")
print(res)

#*** isfile()   检测路径是否是一个文件
res = os.path.isfile("99.txt")
print(res)

#islink()   检测路径数否是一个链接
res = os.path.islink("./ceshi200/ceshi100")
print(res)

#getctime() [windows]文件的创建时间,[linux]权限的改动时间(返回时间戳)
strvar = "77.txt"
res = os.path.getctime(strvar)
print(res)

import time 
timestr = time.ctime(res)
print(timestr)	# Mon Jun 15 19:23:57 2020

#getmtime() 获取文件最后一次修改时间(返回时间戳)
res = os.path.getmtime(strvar)
print(res)

import time 
timestr = time.ctime(res)
print(timestr)  # Mon Jun 15 19:23:57 2020

#getatime() 获取文件最后一次访问时间(返回时间戳)
res = os.path.getatime(strvar)
import time 
timestr = time.ctime(res)
print(timestr)  # Mon Jun 15 19:23:57 2020

#*** exists()   检测指定的路径是否存在
pathvar = "/pythonfile/1.html"
res = os.path.exists(pathvar)
print(res)

#isabs()    检测一个路径是否是绝对路径 (了解)
var = "."
res = os.path.isabs(var)
print(res)



# 计算一个文件夹当中所有文件的大小是多少?
import os
pathvar = "/mnt/hgfs/mywork/day015/ceshi100"
mysize = 0
listvar = os.listdir(pathvar)
print(listvar)

for i in listvar:
	# 拼接一个绝对路径
	pathvar2 = os.path.join(pathvar,i)
	# 判断该路径是否为文件夹
	if os.path.isdir(pathvar2):
		print("当前"+i+"是一个[目录]")
	# 判断该路径是否为文件
	elif os.path.isfile(pathvar2):
		print("当前"+i+"是一个[文件]")
		mysize += os.path.getsize(pathvar2)
print(mysize)

print("<==>")
def getallsize(pathvar):
	mysize = 0
	listvar = os.listdir(pathvar)

	for i in listvar:
		# 拼接一个绝对路径
		pathvar2 = os.path.join(pathvar,i)
		# 判断该路径是否为文件夹
		if os.path.isdir(pathvar2):
			mysize += getallsize(pathvar2)
			# 外层计算好的文件大小 += 里层计算好的文件大小
			# mysize += mysize
		# 判断该路径是否为文件
		elif os.path.isfile(pathvar2):
			print("当前"+i+"是一个[文件]")
			mysize += os.path.getsize(pathvar2)

	return mysize

res = getallsize(pathvar)
print(res)

"""
解题思路:
	计算a1 大小为1
	计算a1 大小为2
	mysize  = 1 + 2

	getallsize("/mnt/hgfs/mywork/day015/ceshi100/ceshi200")

	计算c1 大小3
	计算d1 大小4
	计算d2 大小5
	mysize = 3+4+5

	算好里面的文件大小之后,return mysize 返回到函数的调用处

	返回之后
	外层的文件夹的size大小 + 里层文件夹的size大小 总和是总size
	return mysize即可
"""

python shutil模块

# ### os 和 shutil
"""
对于文件操作来讲的:
	os =>     创建和删除
	shutil => 复制和剪切
"""
import os
os.chdir("/pythonfile")
#os.mknod   创建文件
os.mknod("abc")

#os.remove  删除文件
os.remove("abc")

#os.mkdir   创建目录(文件夹)
os.mkdir("ceshi1115")

#os.rmdir   删除目录(文件夹)
os.rmdir("ceshi1115")

#os.rename  对文件,目录重命名
os.rename("ccc.txt","aaa.php")
os.rename("ceshi111","bbb.js")

# 相对于当前目录创建
os.makedirs("./a/b/c/d/e")
# 相对于当前目录删除
os.removedirs("./a/b/c/d/e")
os.makedirs("/a/b")  # 直接从根目录创建 会有权限拒绝访问的问题;


# ### shutil
import shutil

# -- shutil模块 复制/移动/
#copyfileobj(fsrc, fdst[, length=16*1024])  复制文件 (length的单位是字符(表达一次读多少字符))
fp1 = open("2.php",mode="r",encoding="utf-8")
fp2 = open("1.html",mode="w",encoding="utf-8")
shutil.copyfileobj(fp1,fp2)

#copyfile(src,dst)   #单纯的仅复制文件内容 , 底层调用了 copyfileobj
shutil.copyfile("1.html","2.html")

# 复制权限时,前提要先有这个文件才行
# *** copymode(src,dst)   #单纯的仅复制文件权限 , 不包括内容  (虚拟机共享目录都是默认777)
shutil.copymode("1.html","2.html")

#copystat(src,dst)   #复制所有状态信息,包括权限,组,用户,修改时间等,不包括内容
shutil.copystat("1.html","2.html")

# *** copy(src,dst)       #复制文件权限和内容
shutil.copy("1.html","3.html")

# *** copy2(src,dst)      #复制文件权限和内容,还包括权限,组,用户,时间等
shutil.copy2("1.html","4.html")

# *** copytree(src,dst)   #拷贝文件夹里所有内容(递归拷贝)
shutil.copytree("ceshi","ceshi02")

# *** rmtree(path)        #删除当前文件夹及其中所有内容(递归删除)
shutil.rmtree("ceshi02")

# *** move(path1,paht2)   #移动文件或者文件夹
shutil.move("index.html","ceshi/")

python zipfile 压缩模块

# ### zipfile 压缩模块
#zipfile.ZipFile(file[, mode[, compression[, allowZip64]]])
#ZipFile(路径包名,模式,压缩or打包,可选allowZip64)
#功能:创建一个ZipFile对象,表示一个zip文件.
#参数:
    -参数file表示文件的路径或类文件对象(file-like object)
    -参数mode指示打开zip文件的模式,默认值为r
        r    表示读取已经存在的zip文件
        w    表示新建一个zip文档或覆盖一个已经存在的zip文档
        a    表示将数据追加到一个现存的zip文档中。
    -参数compression表示在写zip文档时使用的压缩方法
        zipfile.ZIP_STORED      只是存储模式,不会对文件进行压缩,这个是默认值
        zipfile.ZIP_DEFLATED    对文件进行压缩 
    -如果要操作的zip文件大小超过2G,应该将allowZip64设置为True。


import zipfile 

# (1) 压缩文件  
zf = zipfile.ZipFile("/mywork/ceshi0403_1.zip","w",zipfile.ZIP_DEFLATED)
# 把文件写在压缩包中
# 路径名  ,   包中别名
zf.write("/bin/bash","bash")
zf.write("/bin/bzcat","bzcat")
# 路径名 , 用文件存储
zf.write("/bin/grep","/temp/grep")
zf.close()

# (2) 解压文件
zf = zipfile.ZipFile("/mywork/ceshi0403_1.zip","r")
# 参数是一个路径
zf.extractall("/mywork/ceshi0403_1")
# 解压单个 路径,文件夹
zf.extract("bash","/mywork/bash")
# 关闭压缩包
zf.close()

# (3) 追加文件 支持with操作
with zipfile.ZipFile("/mywork/ceshi0403_1.zip","a",zipfile.ZIP_DEFLATED) as zf:
	zf.write("/bin/ip","ip")
    
# (4) 查看包内文件
with zipfile.ZipFile("/mywork/ceshi0403_1.zip","r") as zf:
	listvar = zf.namelist()
print(listvar)

python tarfile 模块

# ### tarfile 模块
import tarfile 

# w	单纯的套一个后缀 打包
tf = tarfile.open("/mywork/ceshi0403_2.tar","w")
# (路径,别名)
tf.add("/bin/cat","cat")
tf.add("/bin/chacl","chacl")
tf.add("/bin/chgrp","/tmp/chgrp")
tf.close()

# bz2	采用bz2算法 压缩  
tf = tarfile.open("/mnt/hgfs/mywork/day016/ceshi0403_3.tar.bz2","w:bz2")
tf.add("/bin/cat","cat")
tf.add("/bin/chacl","chacl")
tf.add("/bin/chgrp","/tmp/chgrp")
tf.close()

# gz	采用gz算法 压缩
tf = tarfile.open("/mnt/hgfs/mywork/day016/ceshi0403_4.tar.gz","w:gz")
tf.add("/bin/cat","cat")
tf.add("/bin/chacl","chacl")
tf.add("/bin/chgrp","/tmp/chgrp")
tf.close()
"""
[理论上!!!] bz2压缩之后的包,占用体积上小,gz稍大
"""

# (2) 解压文件
tf = tarfile.open("/mywork/ceshi0403_3.tar.bz2","r")
# 解压到某一个路径(所有)
tf.extractall("//mywork/ceshi0403_3")
# 解压单个文件
tf.extract("cat","/mywork/cat")
tf.close()

# (3) 他只能对w模式创建的包进行追加[先前没有压缩] 支持with
with tarfile.open("/mywork/ceshi0403_2.tar","a") as tf:
	tf.add("/bin/mv","mv")

# (4) 查看包中所有内容
with tarfile.open("/mywork/ceshi0403_2.tar","r") as tf:
	listvar = tf.getnames()
print(listvar)


# ### 解决tarfile 追加不压缩的问题
"""
(1)先把包里面所有东西解压出来
(2)重新往包里追加文件
(3)重新过滤,重新打包
"""
import os
path = os.getcwd() #/mywork/
#/mywork/ceshi0403_2.tar
path1 = os.path.join(path,"ceshi0403_2.tar")
#/mywork/ceshi0403_2
path2 = os.path.join(path,"ceshi0403_2")
path3 = os.path.join(path,"ceshi_new.tar.bz2")

# (1)解压文件
with tarfile.open(path1,"r") as tf:
	tf.extractall(path2)

# (2)追加文件
os.system("cp -a /home/opesn/abc.sh  " +path2)

# (3)重新过滤,重新打包
listvar = os.listdir(path2)
# print(res)

# 创建一个新的bz2模式的压缩包
with tarfile.open(path3,"w:bz2") as tf:
	# 循环遍历文件夹当中的所有内容
	for i in listvar:
		# 拼接路径变成如下
		# #/mywork/ceshi0403_2/mv
		pathnew = os.path.join(path2,i)
		# 实现过滤操作
		if i != "cat":
			# add (路径,别名)
			tf.add(pathnew,i)

python json模块

# ### json 模块
# json 支持的数据类型如下:int float bool str list tuple dict None

# 第一对 dumps 和 loads 序列化或者反序列化字符串的
import json
'''
ensure_ascii 默认值为True 如果想要显示中文 ensure_ascii = False
sort_keys 按照字典的键排序(从小到大)
'''
dictvar = {"name":"opesn","age":18,"sex":"未知"}
res = json.dumps(dictvar,ensure_ascii=False,sort_keys=True)
print(res,type(res))

dic = json.loads(res)
print(dic,type(dic))


# 第二对 dump 和 load 应用在数据的文件存储
dictvar = {"name":"opesn","age":18,"sex":"未知"}
with open("123-opesn.json",mode="w",encoding="utf-8") as fp:
    json.dump(dictvar,fp,ensure_ascii=False)

with open("123-opesn.json",mode="r",encoding="utf-8") as fp:
    res = json.load(fp)
print(res,type(res))


# ### json 和 pickle 的区别
# (1) json
"""
json 模块连续dump数据之后,不能够通过load还原数据.需要使用loads解决
"""
dic1 = {"a":1,"b":2}
dic2 = {"a":3,"b":4}
with open("124-opesn.json",mode="w",encoding="utf-8") as fp:
    json.dump(dic1,fp)
    fp.write("\n")
    json.dump(dic2,fp)
    fp.write("\n")
    
with open("124-opesn.json",mode="r",encoding="utf-8") as fp:
    # res = json.load(fp)
    # 解决load一次性加载不识别数据的弊端用loads
    for i in fp:
        res = json.loads(i)
        print(res)
        
# (2) pickle
dic1 = {"a":1,"b":2}
dic2 = {"a":3,"b":4}
import pickle
with open("125-opesn.pk1",mode="wb") as fp:
    pickle.dump(dic1,fp)
    pickle.dump(dic2,fp)
    pickle.dump(dic2,fp)
    pickle.dump(dic2,fp)
print("<====>")
with open("125-opesn.pk1",mode="rb") as fp:
    """
    res = pickle.load(fp)
    print(res)
    res = pickle.load(fp)
    print(res)
    """
    """
    for i in fp:
        res = pickle.loads(i)
        print(res)
    """
    try:
        while True:
            res = pickle.load(fp)
            print(res)
    except:
        pass
"""
try:
	写可能有问题的代码
except:
	异常处理的逻辑
一旦try代码块中的代码报错,直接执行except中的代码块
会抑制报错信息,为了不终止程序,继续执行.
"""

"""
# json 和 pickle 两个模块的区别:
(1)json序列化之后的数据类型是str,所有编程语言都识别,
   但是仅限于(int float bool)(str list tuple dict None)
   json不能连续load,只能一次性拿出所有数据
(2)pickle序列化之后的数据类型是bytes,
   所有数据类型都可转化,但仅限于python之间的存储传输.
   pickle可以连续load,多套数据放到同一个文件中
...
"""

"""
json 注意点 
但凡是用来传输数据,字典的键一定得是按照变量命名的字符串.
"""
"""
dic = {1:11,2:333}
res = json.dumps(dic)
print(res)  #{"1": 11, "2": 333}
dic2 = json.loads(res)
print(dic2) #{'1': 11, '2': 333}
"""

python 面向对象

#用几大特征表达一类事物称为一个类,类更像是一张图纸,表达的是一个抽象概念
#对象是类的具体实现,更像是由这图纸产出的具体物品,类只有一个,但对象可以通过这个类实例化出多个
#对象是类的实例,类是对象的模板
#*类中的成员只有方法和属性,不要裸露的把判断和循环直接写在类中,而是用方法包起来

# (1)类的定义:
#(1)
class MyClass:
	pass
#(2) 推荐第二个
class MyClass():
	pass
#(3)
class MyClass(object):
	pass


# (2)类的实例化
class MyClass():
	a = 5
# 实例化对象 或者叫类的实例化
obj = MyClass()

# (3)类的基本结构
"""
在类当中只能有属性和方法,两样东西,其他的通通不要写
"""
class Car():
	# 成员属性
	color = "屎黄色的"
	# 成员方法
	def run(self):
		print("我的车会跑啊")

"""
# 只是语法上不报错,但是一定不要这样写
class Ceshi():
	if 5 == 5:
		print("答对了")
# 改写如下
class Ceshi():
	def func():
		if 5 == 5:
			print("答对了")
中文 = 5
"""

# (4)类的命名
# 使用大驼峰命名法
"""
MyClass 
ShoppingCar
LiuDeHua
每个单词的首字符需要大写(推荐)
"""
# class ceshi():
	# pass

类的封装性

# ### 类的封装性
# 对象相关的操作
"""
私有的: private
	在本类内部可以访问,类的外部不可以访问.(python中 属性或者方法前面加上两个下划线__)
公有的: public
	在本类的内部和外部都可以访问.
	
对象.属性
对象.方法()
"""

class MyCar():
	# 公有成员属性
	logo = "特斯拉"
	# 私有成员属性
	__oil = "2.5L"
	
	# 公有成员方法
	def run(self):# self = obj  =>obj.logo
		print(self.logo,"这辆车会跑")		
	# 私有成员方法
	def __oil_info(self):
		print("我的油耗信息保密")

"""
绑定方法:
	(1)绑定到对象:自动把对象当成参数传递
	(2)绑定到类  :自动把类当成参数传递
"""
		
# 实例化对象 / 类的实例化 => 产生对象obj
obj = MyCar()

# (1)实例化的对象访问公有成员属性和方法
# 调用公有属性
res = obj.logo
print(res)
# 调用公有方法
'''obj.run() 对象在调用方法时候,自动把obj当成参数传递到run方法当中,不需要手动指定'''
obj.run()

# (2)实例化的对象动态添加公有成员属性和方法
# 添加成员属性
obj.color = "蓝色的"
print(obj.color)

# (1) 添加无参方法
def dipan():
	print("我是制造底盘的方法")
obj.dipan = dipan
obj.dipan()

# (2) 添加有参方法
def func(self,something):
	print(self.logo,something)
obj.func = func
obj.func(obj,"hello world")


# 创建绑定方法 (优化版)
import types
# MethodType(自定义方法,要绑定的对象)
"""
把func方法绑定在obj对象上,下次调用时,自动把obj当成参数进行传递,不需要手动指定
"""
obj.func2 = types.MethodType(func,obj)
obj.func2("hello world")

# (3) 添加lambda表达式
fangxiangpan = lambda : print("我是方向盘")
obj.fangxiangpan = fangxiangpan
obj.fangxiangpan()


# 查看obj该对象的成员 __dict__
print(obj.__dict__)
# obj.logo = "宝马"
# print(obj.logo)
"""

{
'color': '蓝色的', 
'dipan': <function dipan at 0x7fadee93fe18>, 
'func': <function func at 0x7fadee861400>, 
'func2': <bound method func of <__main__.MyCar object at 0x7fadee871e48>>, 
'fangxiangpan': <function <lambda> at 0x7fadee861488>
}

类当中的成员属性和方法归属于该类,生成的对象可以调用,只有使用权,没有所有权.
obj对象中如果有该属性,则调用自己的,如果没有,调用类成员的.
"""
# print(obj.__oil)  无法调用类内私有成员

类的相关操作

# ### 类的相关操作
"""
(1)定义的类访问公有成员属性和方法
(2)定义的类动态添加公有成员属性和方法
"""

class MyCar():
	#公有成员属性
	oil = "窝轮增压油耗10L"
	#私有的成员属性
	__price = "100万"
	
	# 普通公有方法  (只能用类来调用)
	def oil_info():
		# 对象.属性  或者 类.属性 |  除此之外不能直接使用成员属性
		print("我的油耗信息是:"+ MyCar.oil)
		
	# 普通的私有方法
	def __price_info():
		print("我的价格信息是")
	
# 实例化对象 => 对象
obj = MyCar()
print(obj) # obj => object
# 查看obj的内部成员 __dict__
print(obj.__dict__)

# (1)类访问公有成员属性和方法
# 公有属性
res = MyCar.oil
print(res)
# 公有方法
MyCar.oil_info()
'''obj.oil_info()  # 如果用对象调取方法 务必加上形参self,系统会自动把方法前面的对象,当成参数进行传递,系统自动执行的'''

# (2)定义的类动态添加公有成员属性和方法
# 为当前类MyCar添加成员属性
MyCar.color = "天蓝色"
print(MyCar.color)
print(MyCar.__dict__)

# 添加成员方法
#(1) 无参方法
def dahuangfeng():
	print("请叫我大黄蜂")
MyCar.dahuangfeng = dahuangfeng
MyCar.dahuangfeng()

#(2) 有参方法
def qingtianzhu(something):
	print("请叫我"+something)
MyCar.qingtianzhu = qingtianzhu
MyCar.qingtianzhu("大黄蜂")

#(3) lambda表达式
func = lambda : print("我会喵喵喵的叫")
MyCar.jiao = func
MyCar.jiao()

# MyCar.__price_info() #无法调用私有成员

关于对象和类的删除操作

# ### 关于对象和类的删除操作

"""
(1)实例化的对象删除公有成员属性和方法
(2)定义的类删除公有成员属性和方法
"""
'''私有成员 只限于本类内部使用,外部调用不了.'''

class Plane():
	logo = "播音747"
	__air_sister  = 20
	__captain = "王缸蛋"
	
	# 公有的绑定方法
	def fly1(self):
		print("播音747的起飞")
		
	# 普通方法->只能类调用
	def fly2():
		print("播音747,后面喷火,所以会飞")
		
	# 私有的绑定方法
	def __plane_info1(self):
		print("飞机上有%d" % (self.__air_sister))
		
	# 私有的普通方法
	def __plane_info2():
		print("飞机的机长是后村的%s" % (Plane.__captain))
	
	# 公有方法1
	def pub_func1(self):
		self.__plane_info1()
	
	# 公有方法2
	def pub_func2():
		Plane.__plane_info2()

# (1)实例化的对象删除公有成员属性和方法
# 实例化类产生对象obj
obj = Plane()
# print(obj.logo)
"""对象可以调用类中的公有成员,但是没有删除或者修改的权利,不为obj所有,归属为类"""
obj.logo = "歼20"
# 类可以调用对象的logo么? 不能调用
# 对象可以调用类中的成员,但是类不能调用对象的相关成员.对象可以是多个,彼此独立
# print(Plane.logo)
# print(obj.__dict__)
# 删除对象的成员属性
# del obj.logo
# print(obj.__dict__)
# 删除对象的成员方法
obj.fly_self = lambda : print("这是对象自己的成员方法")
obj.fly_self()
print(obj.__dict__)
del obj.fly_self
print(obj.__dict__)


# (2)定义的类删除公有成员属性和方法
Plane.ck = "乘客"
print(Plane.__dict__)
# 使用对象可以调用类中的成员
print(obj.ck)
# 删除类的成员属性
del Plane.ck
print(Plane.__dict__)
# print(obj.mashaji) error

Plane.fly3 = lambda n : print("我会飞")
# 都可以调用 无论是对象还是类
Plane.fly3(1)
obj.fly3()
# 删除类的成员方法
del Plane.fly3
print(Plane.__dict__)


# (3)如何在类的外部调用私有属性和方法?
# 私有属性和私有方法实际上采用了改名策略,没有真正的私有化
# (非法的)
print(obj._Plane__air_sister)
obj._Plane__plane_info1()

print(Plane._Plane__captain)
Plane._Plane__plane_info2()


# (4)利用公有方法调用私有成员
print("<===>")
obj.pub_func1()
Plane.pub_func2()

单继承

# ###-继承:一个类除了自身所拥有的属性方法之外,还获取了另外一个类的成员属性和方法
# ### 单继承
"""
继承:(1)单继承 : 一个子类只有一个父类
	 (2)多继承 : 一个子类可以有多个父类
	 
子类: 一个类继承另外一个类 , 当前这个类是子类
父类: 被其他类所继承的类 , 当前这个类是父类

python当中所有类都继承object
"""
# 在定义类时,小括号里面写的是父类名字;
# class MyClass(object):

# 定义一个父类

# 在定义类时,小括号里面写的是父类名字;
# class MyClass(object):

# 定义一个父类
class Human():
	hair = "土色"
	__sex = "男性"
	
	def eat(self):
		print("远古人类都会吃")
		
	def sleep(self):
		print("远古人类常常冬眠")
		
	def __beat_doudou(self):
		print("hello world")
		
	# 在父类当中定义公有成员方法调用相关私有成员
	def f_pub(self):
		print(self.__sex)
		self.__beat_doudou()
		
# (1) 子父继承后,子类可以使用父类的公有属性和方法
class Man(Human):
	pass
obj = Man()
# 调用父类公有成员属性
print(obj.hair)
obj.eat()

# (2) 子父继承后,子类不可以调用父类的私有属性和方法
class Woman(Human):
	# 在子类当中定义公有成员方法也不能调用父类的相关私有成员
	def pub_skill(self):
		print(self.__sex)
		self.__beat_doudou()
		
obj = Woman()
# obj.__sex
# obj.__beat_doudou()
# obj.pub_skill()
obj.f_pub()

# (3) 子父继承后,子类可以改写父类方法
'''
	子类重写父类方法后,默认调用自己的子类方法,
	如果没有在调用父类方法
'''
print("<=====>")
class Children(Human):
	def eat(self):
		print("吃零食")
obj = Children()
obj.eat()

多继承

# ### 多继承:一个子类继承了多个父类
class Father():
	f_property = "一枝梨花压海棠"
	def f_skill(self):
		print("说相声,说学逗唱,吃喝嫖赌,抽烟,喝酒,烫头")
		
class Mother():
	m_property = "一支红杏出墙来"
	def m_skill(self):
		print("拖地,做饭,洗衣服,购物,逛街,买包包")

# 在定义类的时候,把父类都写在括号里面,父类与父类之间用逗号隔开.
class Daughter(Father,Mother):
	pass

obj = Daughter()
print(obj.f_property)
obj.m_skill()

# ### super 用于调用父类的成员
'''
(1)super本身是一个类 super()是一个对象 用于调用父类的绑定方法
(2)super() 只应用在绑定方法中,默认自动传递self对象 (前提:super所在作用域存在self)
(3)super用途: 解决复杂的多继承调用顺序	
'''
class Father():
	f_property = "一枝梨花压海棠"
	def f_skill():
		print("说相声,说学逗唱,吃喝嫖赌,抽烟,喝酒,烫头")
		
class Mother():
	m_property = "一支红杏出墙来"
	def m_skill(self):
		print("拖地,做饭,洗衣服,购物,逛街,买包包")

class Son(Father,Mother):
	def son_skill1(self):
		# 调用父类Father 中的属性和方法
		print(Father.f_property)
		Father.f_skill()
		
	def son_skill2(self):
		# self.m_skill()
		# obj.m_skill()
		super().m_skill()
		print(super().m_property)
# 实例化对象 产生obj
obj = Son()
# obj.son_skill1()
print("<==>")
obj.son_skill2()
# Son.son_skill2()

菱形继承

# ### 菱形继承 (钻石继承)
"""
     Human
Man          Woman
	Children
"""
class Human():
    pty = 444
    def feelT(self):
        print("Human 天冷了")
        print(self.pty,"<==>")
        print("Human 天热了")

class Man(Human):
    pty = 333
    def feelT(self):
        print("Man 天冷了 1")
        super().feelT()
        print("Man 天热了 2")

class Woman(Human):
    pty = 222
    def feelT(self):
        print("Woman 天冷了 3")
        super().feelT()
        print("Woman 天热了 4")

class Children(Man,Woman):
    pty = 111
    def feelT(self):
        print("Children 天冷了 5")
        super().feelT()
        print("Children 天热了 6")

obj = Children()
obj.feelT()

listvar = Children.mro()
print(listvar)


'''
# 3.x 版本 super 采用广度优先原则
super 采用c3算法 按照顺序依次调用
类.mro() => 多继承之间,调用顺序的列表
[
	<class '__main__.Children'>, 
	<class '__main__.Man'>, 
	<class '__main__.Woman'>, 
	<class '__main__.Human'>, 
	<class 'object'>
]

super() 一定调用的是父类方法,同时能够解决多继承带来的复杂关系
super() 默认携带self对象进行传递,只应用在绑定方法里
'''

# 7 3 5 1 2 6 4 8 

# ###issubclass 判断子父关系 (带有血缘关系即可)
res = issubclass(Children,Man)
res = issubclass(Children,(Man,Woman))
res = issubclass(Children,Human)
print(res)

# ###isinstance 判断类型:(带有血缘关系即可)
res = isinstance(obj,Children)
print("<==>")
res = isinstance(obj,(Man,Woman))
res = isinstance(obj,Human)
print(res)
# res = isinstance(Children,Man) # error 判断不了子父关系
# print(res)

多态

#-多态:不同的子类对象,调用相同的父类方法,产生不同的执行结果
"""
重要特征:继承 重写
在不改变代码的前提下,实现了不同的功能
不同的对象调用了相同的方法(方法名字)而产生不同的功能
"""

# 士兵类
class Soldier():
	def attack(self):
		pass
		
	def back(self):
		pass

# 陆军类
class Army(Soldier):
	def attack(self):
		print("[陆军]以迅雷不及掩耳之响叮当之势,占领敌方的高地")
		
	def back(self):
		print("[陆军]撒丫子就跑")
		
# 海军类
class Navy(Soldier):
	def attack(self):
		print("[海军]给你两鱼雷,扔两个鱼叉子,插死一个算一个")
		
	def back(self):
		print("[海军]立刻跳船,下海喂鱼")
		
# 空军类
class AirForce(Soldier):
	def attack(self):
		print("[空军]给我二营长的意大利炮端上来,射它")
		
	def back(self):
		print("[空军]弃机跳伞,落地成盒")

# 实例化陆军类
obj_army = Army()
# 实例化海军类
obj_navy = Navy()
# 实例化空军类
obj_airforce = AirForce()

# 各就位准备
listvar = [obj_army,obj_navy,obj_airforce]


strvar = """
将军: 按1,让所有兵种攻击
	  按2,让所有兵种撤退
	  按3,空军上,其他人撤
"""
# 请将军下达命令:

sign = True
while sign:
	print(strvar)
	num = input("将军请下令:")
	
	for i in listvar:
		if num == "1":
			i.attack()
			
		elif num == "2":
			i.back()
			
		elif num == "3":
			if isinstance(i,AirForce):
				i.attack()
			else:
				i.back()
		elif num.upper() == "Q":
			print("战斗已结束,将军请休息")
			sign = False
			break
		else:
			print("风太大,我听不到")
			sign = False
			break

__init__魔术方法

# ### __init__魔术方法 (构造方法)
"""
	触发时机:实例化对象,初始化的时候触发
	功能:为该对象添加成员
	参数:至少一个self参数
	返回值:没有
"""
# (1)基本语法
# 在实例化对象的时候自动触发该方法 
class MyClass():
    # 至少一个参数 self
    def __init__(self):
        # 为该对象self 添加成员属性name
        self.name = "opesn"
		
# 实例化对象  => 返回对象 
'''MyClass()产生一个对象在__init__方法初始化之后进行返回,被obj变量接受'''
obj = MyClass()

print(obj.name)
# print(obj,type(obj))

# (2)init 有多个参数
class MyClass():
	def __init__(self,name):
		# 右边的name是参数传递进来的
		# 左边的name是自定义的成员属性
		self.name = name
# 如果init上面有参数,有几个,在实例化的时候就要填充几个,抛出self
obj = MyClass("hello world")
print(obj.name)

# (3)综合案例 (通过同一个类,产生不同的对象)
class Children():
    def __init__(self,name,skin):
        self.name = name
        self.skin = skin

    def drink(self):
        print("drink")

    def eat(self):
        print("eat")

    def children_info(self):
        print("  该对象的名字是:  "+self.name + "     该对象的肤色是   "+self.skin)

# 实例化类 => 产生对象
children1 = Children("opesn","黄色")
children1.children_info()

children2 = Children("张三","黑色")
children2.children_info()

children3  =Children("李四","白色")
children3.children_info()
# 产生得三个对象都是独立的个体,不会产生冲突,但可以共用同一个类的成员;

__new__ 魔术方法

#__new__ 魔术方法
'''
	触发时机:实例化类生成对象的时候触发(触发时机在__init__之前)
	功能:控制对象的创建过程
	参数:至少一个cls接受当前的类,其他根据情况决定
	返回值:通常返回对象或None
'''
# 新式类 python3.x
'''
如果你写new魔术方法,那么用你自己定义的
如果你不写new魔术方法,用object.__new__魔术方法自动调用
'''
class MyClass():
	a = 90
obj2 = MyClass()

# (1) 基本用法
class Boat(object):
	def __new__(cls):
		print(cls)
		# 类.方法 => object.__new__(cls) => 该类的对象
		obj = object.__new__(cls)
		return obj
		# return obj2
		# return None
	
obj = Boat()
print(obj,type(obj))
# print(obj.a)


# (2) __new__ 与 __init__
"""
__new__ 触发时机 要 快于 __init__ 都是在实例化对象的时候触发
__new__  用来制造对象的
__init__ 用来初始化对象的
__init__ 和 __new__ 参数是同步的 init里面有几个参数, new魔术方法就有几个参数,一一对应
*args,**kwargs 可以接受到所有参数
"""
class Boat(object):

	def __new__(cls,*args,**kwargs):
		# print(1)
		return object.__new__(cls)
	
	def __init__(self,*args,**kwargs):
		# print(args)
		# print(kwargs)
		self.name = args[0]
		self.color = kwargs['color']
		
	def boating(self):
		print("我给我的小船起的名字是{},船的颜色{}".format(self.name,self.color))
		
		
obj = Boat("泰坦尼克号",color="yellow")
obj.boating()

# (3) __init__ 只初始化自己本类的对象,其他对象不触发.不调用.
# 你可以返回其他类的对象,但是不会触发自己本类的init魔术方法;
class MyClass():
	a = 90
obj2 = MyClass()

class Boat(object):
	def __new__(cls,*args,**kwargs):
		return obj2
		
	# init 不会初始化其他类的对象,不调用
	def __init__(self,*args,**kwargs):
		print(1)
		
obj = Boat()
print(obj,type(obj))

单态模式

# ### 单态模式(单例模式) : 同一个类,无论实例化多少次,有且只有一个对象
"""
单态模式是为了只创建一个对象,最终节省内存空间.(应用在当前类只调用,不在为该对象添加成员的情况下)

如果当前该类对象存在,则把以前的该对象返回
如果当前该类对象不存在,通过父类object的__new__方法创建
"""
# (1) 基本写法
class Sington():
	# 定义一个私有的成员属性__obj , 用来存储接下来创建的唯一对象.
	__obj = None
	def __new__(cls):
		# 如果类的私有成员属性__obj 不存在 是一个None,那么通过父类object的new创建一个对象
		if cls.__obj is None:
			# 创建对象
			obj = object.__new__(cls)
			# 把对象存在私有成员属性__obj当中
			cls.__obj = obj
		# 将该类对象直接返回
		return cls.__obj

# 第一次 触发cls.__obj is None 返回真,创建对象
obj1 = Sington()
# 第二次 触发__new__ 发现cls.__obj is None 返回假 直接return cls.__obj
obj2 = Sington()
# 第三次 与 第二次相同
obj3 = Sington()
print(obj1,obj2)
print(obj1 is obj3)

# (2) 单态模式下,两个不同的变量指向同一个对象.
# 私有成员无法在类外或者在子类里面调用,只能在本类内部可以使用.
class Sington():
	__obj = None
	def __new__(cls,*args,**kwargs):
		if cls.__obj is None:
			cls.__obj = object.__new__(cls)
		return cls.__obj

	def __init__(self,name):
		self.name = name

obj1 = Sington("opesn")
# obj1.name = opesn
obj2 = Sington("hello wolrd")
# obj2.name = hello wolrd
print(obj1.name)
print(obj2.name)
print(obj1 is obj2)

__del__ 魔术方法

#__del__ 魔术方法(析构方法)
'''
	触发时机:当对象被内存回收的时候自动触发[1.页面执行完毕回收所有变量 2.所有对象被del的时候]
    功能:对象使用完毕后资源回收
	参数:一个self接受对象
	返回值:无
'''
class LangDog():
	def __init__(self,name):
		self.name = name
		
	def eatmeat(self):
		print("可爱的小狼{},喜欢吃肉".format(self.name))

	def __del__(self):
		print("该析构方法被触发~")

# (1)页面执行完毕回收所有变量
obj = LangDog("詹姆斯·旺旺")
obj.eatmeat()

# (2)所有对象被del的时候
"""在对象真正被完全del删除的时候触发."""
'''obj 和 obj2 是不同的两个变量指向同一个对象.'''
obj2 = obj
print(obj is obj2)
print("<====start===>")
del obj
del obj2
print("<====end===>")


# (3) 模拟文件的读取操作
# fp = open("文件名",mode="r",encoding="utf-8")
# res = fp.read()
# fp.close()

import os
# os.path.exists
class ReadFile():
	
	def __new__(cls,filename):
		# 如果文件不存在,连对象都不给
		if os.path.exists(filename):
			# 如果存在该文件,则创建对象
			obj = object.__new__(cls)
			return obj
		return print("该文件不存在~")			
			
	def __init__(self,filename):
		# 把文件对象赋值给成员属性fp
		self.fp = open(filename,mode="r",encoding="utf-8")
		
	def getcontent(self):
		# 读取文件内容
		res = self.fp.read()
		return res
		
	def __del__(self):
		# 关闭文件
		self.fp.close()
	
obj = ReadFile("123-opesn.txt")
res = obj.getcontent()
print(res)

__call__ 魔术方法

#__call__ 魔术方法
'''
	触发时机:把对象当作函数调用的时候自动触发
	功能: 模拟函数化操作
	参数: 参数不固定,至少一个self参数
	返回值: 看需求
'''
# (1)基本用法
class MyClass():
	def __call__(self):
		print(123)
		return 456
	
obj = MyClass()
res = obj()
print(res)


# (2)模拟一个做蛋糕的过程
import math
class MakeCake():	
	# 利用call方法进行统一的调用
	def __call__(self,something):
		print(something,"他的做法如下")
		self.step1()
		self.step2()
		self.step3()
		
	def step1(self):
		print("把鸡蛋打碎,搅拌面粉")
	def step2(self):
		print("烘焙蛋糕")		
	def step3(self):
		print("把蛋糕放嘴里,嚼一下")
		
cake = MakeCake()
cake("爱心蛋糕")

# (3) 模拟系统int强转
# int(10) => 10
# int(3,14) => 3
# int("456") => 456
# int(True) => 1

class MyInt():
	
	def myfunc(self,n,sign=1):
		# 把字符串当成代码执行 eval(n[1:].lstrip("0")) 产生一个整型
		if n.lstrip("0") == "": # 0000000000 lstrip("0") => ""
			return 0				
		return eval(n.lstrip("0")) * sign

	def __call__(self,n):
		# 判断是布尔类型
		if isinstance(n,bool):
			if n == True:
				return 1
			else:
				return 0
				
		# 判断是整型
		elif isinstance(n,int):
			return n
			
		# 判断是浮点型
		elif isinstance(n,float):
			if n < 0:
				res = math.ceil(n)				
			else:
				res = math.floor(n)
			return res
			
		# 判断是字符串类型
		elif isinstance(n,str):
			# 判断第一位符号位是正+ 还是负-
			if  (n[0] == "-" or n[0] == "+")   and      n[1:].isdecimal()     :
				# 判断正负号
				if n[0] == "-":
					sign = -1
				elif n[0] == "+":
					sign = 1
				# 直接返回对应的数值
				return self.myfunc(n[1:],sign)
			
			elif  n.isdecimal():
				# 能走到这个条件当中,一定没有带符号位
				return self.myfunc(n)
			else:
				return "抱歉,这个功能真没有~"
				
		# 其他
		else:
			return "抱歉,这个功能真没有~"
		
# "-000000092112"
myint = MyInt()
print(myint(False),type(myint(False)))
print(myint(123),type(myint(123)))

print(myint(3.15),myint(-5.15))
print(myint("999888"),type(myint("999888")))

print(myint("+789"),type(myint("-789")))
print(myint("789"),type(myint("789")))
print("<==123456=>")
# print(myint("30000"),type(myint("30000")))
print(myint(+-+-+-123),type(myint("30000")))
"""
# True  123
res = isinstance(123,bool)
print(res)

print(type(True))
if type(True) == bool:
	print(1234)
	

import math
print(int(3.14))  # 3
print(int(-3.14)) # -3
# ceil floor
n = 3.14
if n < 0:
	res = math.ceil(n)
	print(res)
else:
	res = math.floor(n)
	print(res)
	
print(int("313"))
"""	
# print(int("-00000"))
print("<====>")
# 没有符号的情况下
strvar = "00000"
res = strvar.lstrip("0")
print(res,type(res))

strvar = "-00000"
res = strvar[1:].lstrip("0")
print(res,type(res))	
		
print(myint(+-+-+-+-3345))

__str__ 魔术方法

#__str__ 魔术方法
'''
	触发时机: 使用print(对象)或者str(对象)的时候触发
	功能:     查看对象
	参数:     一个self接受当前对象
	返回值:   必须返回字符串类型
'''
# class MyClass():
	# pass
# obj = MyClass()
# print(obj)

class Cat():
	gift = "抓耗子"
	def __init__(self,name):
		self.name = name
		
	def cat_info(self):
		return "该对象的名字{},天生就能{}".format(self.name,self.gift)
		
	def __str__(self):
		return self.cat_info()

tom = Cat("汤姆")
# (1)print 来触发__str__魔术方法
# print(tom)
# (2)str强转 来触发__str__ 魔术方法
res = str(tom)
print(res)

__repr__ 魔术方法

#__bool__ 魔术方法
'''
	触发时机:使用bool(对象)的时候自动触发
	功能:强转对象
	参数:一个self接受当前对象
	返回值:必须是布尔类型
'''
'''
类似的还有如下等等(了解):
	__complex__(self)      被complex强转对象时调用
	__int__(self)          被int强转对象时调用
	__float__(self)        被float强转对象时调用
	...
	...
'''
class MyClass1():
	def __bool__(self):
		return False
		
obj = MyClass1()
res = bool(obj)
print(res)

__add__ 魔术方法

#__add__ 魔术方法  (与之相关的__radd__ 反向加法)
'''
	触发时机:使用对象进行运算相加的时候自动触发
	功能:对象运算
	参数:二个对象参数
	返回值:运算后的值
'''

class MyClass2():
	def __init__(self,num):
		self.num = num
	# __add__  对象在加号+的左侧触发
	def __add__(self,other):
		return self.num + other 
	# __radd__ 对象在加号+右侧时触发
	def __radd__(self,other):
		return self.num + other * 3
		
# 方式一	
a = MyClass2(5)
# self 接受到a  other 接收到2  => return self.num + 2 => return 5+2 => return 7
res = a+2
print(res)

# 方式二
# self 第一个参数一定接收到的是对象b , other 接受的是另外一个3 return self.num + 3 * 3 => return 3 + 9 => return 12
b = MyClass2(3)
res = 3 + b 
print(res)

# 方式三
# a+b => 触发add方法 self 接受a other接受b
"""
运作过程:
	self.num + b => 5 + b
	res = 5 + b
	5+b => 触发radd方法 self 接受b other接受5
	return self.num + 5 * 3 => return 3 + 15 => 18
	res = 18
"""
res = a + b
print(res)

__len__ 魔术方法

#__len__ 魔术方法
'''
	触发时机:使用len(对象)的时候自动触发 
	功能:用于检测对象中或者类中某个内容的个数
	参数:一个self接受当前对象
	返回值:必须返回整型
'''
'''
类似的还有如下等等(了解):
	__iter__(self)                 定义迭代容器中的元素的行为
	__reversed__(self)             定义当被 reversed() 调用时的行为
	__contains__(self, item)       定义当使用成员测试运算符(in 或 not in)时的行为
	...
	...
''' 
# len(对象) 返回类内部自定义成员的个数
class MyClass3():
	pty1 = 1
	pty2 = 2
	__pty3 = 3
	
	def myfunc1(self):
		pass
	def myfunc2(self):
		pass
	def __myfunc3(self):
		pass
		
	def __len__(self):
		# print(MyClass3.__dict__)
		dictvar = MyClass3.__dict__
		listvar = [i for i in dictvar if not(i.startswith("__") and i.endswith("__"))]
		
		"""
			[
				'pty1', 
				'pty2', 
				'_MyClass3__pty3', 
				'myfunc1', 
				'myfunc2', 
				'_MyClass3__myfunc3'
			]
		"""
		
		print(listvar)
		return len(listvar)
		
obj = MyClass3()
print(len(obj))

# "".startswith("__")
'''
{
	'__module__': '__main__', 
	'pty1': 1, 
	'pty2': 2, 
	'_MyClass3__pty3': 3, 
	'myfunc1': <function MyClass3.myfunc1 at 0x7fce6b000510>, 
	'myfunc2': <function MyClass3.myfunc2 at 0x7fce6b000598>, 
	'_MyClass3__myfunc3': <function MyClass3.__myfunc3 at 0x7fce6b000620>, 
	'__len__': <function MyClass3.__len__ at 0x7fce6b0006a8>, 
	'__dict__': <attribute '__dict__' of 'MyClass3' objects>, 
	'__weakref__': <attribute '__weakref__' of 'MyClass3' objects>, 
	'__doc__': None
}
123
'''
# 在类外只能添加公有的成员属性和方法
class Myceshi():
	abc = 90
	__ceshi111 = 10
	# 在类内可以添加私有成员属性方法;
	def ceshi20(self):
		# 获取类中的成员属性__ceshi111
		print(self.__ceshi111)
		# 在为当前这个对象增加私有成员属性__ceshi111
		self.__ceshi111  = self.__ceshi111 + 10
		print(self.__ceshi111)
	
obj = Myceshi()
# 在类外定义的成员属性__abc 不是私有的
# obj.__abc = 10
# print(obj.__abc)
# print(obj.__dict__)

# obj.ceshi20()
# print(obj.__dict__)
# print("<=--=>")
# obj.__ceshi111 = 20
# print(obj.__ceshi111)

print(obj.abc)
obj.abc += 80  # 赋值操作
print(obj.abc)
Myceshi.__aabbcc = 901
print(Myceshi.__aabbcc )

python 正则表达式

### 正则表达式定义和作用
"""
#正则表达式是什么?
	它是约束字符串满足某种形式的规则
#正则表达式有什么用?
    1.检测某个字符串是否符合规则.比如:判断手机号,身份证号是否合法
    2.提取网页字符串中想要的数据.比如:爬虫中,提取网站天气,信息,股票代码,星座运势等具体关键字
#在线测试工具  http://tool.chinaz.com/regex/
"""

### 正则表达式所包含的元素种类

#正则表达式由一些 [普通字符] 和一些 [元字符] 组成:
"""
    (1)普通字符包括大小写字母和数字
    (2)元字符具有特殊含义,大体种类分为如下:
        1.预定义字符集,字符组
        2.量词
        3.边界符
        4.分组       
"""

#### 

单个字符匹配

# ### 正则表达式
import re
# findall("正则表达式","要匹配的字符串") => 吧所有匹配的结果塞到列表中
# ###匹配单个字符

# (1) 预定义字符集
'''
\d匹配数字
\D匹配非数字
'''
listvar = re.findall("\d","asdfasdf 2sdf34sdf93sdf4asdf32 神秘男孩*^&")
print(listvar)# ['2', '3', '4', '9', '3', '4', '3', '2']
listvar = re.findall("\D","asdfasdf 2sdf34sdf93sdf4asdf32 神秘男孩*^&")
"""
['a', 's', 'd', 'f', 'a', 's', 'd', 'f', ' ', 's', 'd', 'f', 's', 'd', 'f', 's', 'd', 'f', 'a', 's', 'd', 'f', ' ', '神', '秘', '男', '孩', '*', '^', '&']
"""
print(listvar)

'''
\w 匹配字母或数字或下划线     (正则函数中,支持中文的匹配)
\W 匹配非字母或数字或下划线
'''
listvar = re.findall("\w","asdfasdf 89234sdf 神秘_电*波\r11\n\tsdd")
print(listvar)
# ['a', 's', 'd', 'f', 'a', 's', 'd', 'f', '8', '9', '2', '3', '4', 's', 'd', 'f', '神', '秘', '_', '电', '波', '1', '1', 's', 'd', 'd']
listvar = re.findall("\W","asdfasdf 89234sdf 神秘_电*波\r11\n\tsdd")
print(listvar) #[' ', ' ', '*', '\r', '\n', '\t']
'''
\s匹配任意的空白符
\S匹配任意非空白符
'''
listvar = re.findall("\s","asdfasdf 89234sdf 神秘_电*波\r11\n\tsdd")
print(listvar) #[' ', ' ', '\r', '\n', '\t']
listvar = re.findall("\S","asdfasdf 89234sdf 神秘_电*波\r11\n\tsdd")
print(listvar)
# ['a', 's', 'd', 'f', 'a', 's', 'd', 'f', '8', '9', '2', '3', '4', 's', 'd', 'f', '神', '秘', '_', '电', '*', '波', '1', '1', 's', 'd', 'd']

"""
\n匹配一个换行符
\t匹配一个制表符
"""
strvar = """
sadfa sadfasd	f
sadfasdf sadf	asdf
das    fa sdfa s	d
"""
listvar = re.findall("\n",strvar)
print(listvar)
# ['\n', '\n', '\n', '\n']
listvar = re.findall("\t",strvar)
print(listvar) #['\t', '\t', '\t']

# (2) 字符组 : 从字符组当中选一个,这一个有且只有一个,返回真,否则匹配不到
lst = re.findall("[123]","abc4d3")
print(lst)
print(re.findall('a[abc]b','aab abb acb adb'))
"""aab abb acb"""

# [0-9] 和 [0123456789] 等价
print(re.findall('a[0123456789]b','a1b a2b a3b acb ayb'))
print(re.findall("a[0-9]b",'a1b a2b a3b acb ayb'))
'''a1b a2b a3b'''

# 所有26个小写字母 [a-z]
print(re.findall('a[abcdefg]b','a1b a2b a3b acdb ayb adb'))
print(re.findall('a[a-g]b','a1b a2b a3b acdb ayb adb'))
"""acb adb"""

# 所有26个大写字母 [A-Z]
print(re.findall('a[ABCDEFG]b','a1b a2b a3b  aAb aDb aYb'))
print(re.findall('a[A-G]b','a1b a2b a3b  aAb aDb aYb'))
'''aAb aDb'''

# 所有大小写字母[A-z]
print(re.findall('a[0-9a-zA-Z]b','a-b aab aAb aWb ab a+b aqba1b')) 
print(re.findall('a[0-9A-z]b','a-b aab aAb aWb ab a+b')) 
'''aab aAb aWb'''

print(re.findall('a[0-9][*#/]b','a1/b a2b a29b a56b a456b'))
'''a1/b'''

# ^ 如果放到了字符组里面,表达除了,除了字符组里面的字符之外的所有字符,可以匹配
print(re.findall('a[^-+*/]b',"a%b ccaa*bda&bd"))
# 如果就是想匹配^ 加上\进行转义
print(re.findall('a[\^]b',"a^b"))
'''a%b a&b'''

多个字符匹配

# ### 正则表达式
# ### (二) 匹配多个字符
import re
# (1) 量词
'''1) ? 匹配0个或者1个a '''
print(re.findall('a?b','abbzab abb aab'))  
'''ab b ab ab b ab'''

'''2) + 匹配1个或者多个a '''
print(re.findall('a+b','b ab aaaaaab abb'))
"""ab aaaaaab ab"""

'''3) * 匹配0个或者多个a '''
print(re.findall('a*b','b ab aaaaaab abbbbbbb'))
'''b ab aaaaaab ab b b b b b b'''

'''4) {m,n} 匹配m个至n个a '''
print(re.findall('a{1,3}b','aaab ab aab abbb aaz aabb'))
'''aaab ab aab ab aab'''

# 贪婪匹配 与 非贪婪匹配 [语法:量词的后面加?号]
'''
# 贪婪匹配:    尽量多向后匹配 底层利用回溯算法
# 非贪婪匹配:  尽量少向后匹配
    (1)量词加上问号?表示非贪婪 惰性匹配
    (2).*?w  表示匹配任意长度任意字符遇到一个w就立即停止
'''
# 回溯算法,从左向右进行匹配,直到走到最后没有了,回头,找离右侧最近的一个匹配. (能找多的不找少的)
strvar = "刘能和刘铁锤和刘铁棍子子12子3"
print(re.findall("刘.",strvar))
print(re.findall("刘.?",strvar))
print(re.findall("刘.+",strvar))
print(re.findall("刘.*",strvar))
print(re.findall("刘.*子",strvar))

# 非贪婪匹配: 从左到右进行匹配,找到一个符合条件,就匹配成功返回[语法:量词的后面加?号]
print(re.findall("刘.??",strvar))
print(re.findall("刘.+?",strvar))
print(re.findall("刘.*?",strvar))
# 找到一个就返回
print(re.findall("刘.*?子",strvar))

# 贪婪匹配
print(re.findall('a.*b','aab ab aaaaab a!!!@#$bz')) 
#['aab ab aaaaab a!!!@#$b']
# 非贪婪匹配
print(re.findall('a.*?b','aab ab aaaaab a!!!@#$bz')) #
#aab ab  aaaaab a!!!@#$b

边界符

import re
'''
\b 退格,相当于光标回退一位,是一个转义字符
在正则表达式前面加上一个r,让转义字符失效
'''
# 匹配以字符d 结尾的单词
print(re.findall(r"d\b","word pwd adc"))
print(re.findall(r".*d\b","word pwd adc"))
print(re.findall(r"\S*?d\b","word pwd adc"))
"""
如果使用了^或$ , 意味着把这个字符串当成一个整体了
^,必须按照该字符开头,后面剩下的部分无所谓
$,必须按照该字符结尾,前面剩下的部分无所谓
^$同时存在,必须考虑开头和结尾都是对应字符
"""

strvar = "大哥大嫂大爷"
print(re.findall('大.',strvar)) #['大哥', '大嫂', '大爷']
print(re.findall('^大.',strvar))  #[大哥]
print(re.findall('大.$',strvar))  #['大爷']
print(re.findall('^大.$',strvar))  #[]
print(re.findall('^大.*?$',strvar))  #['大哥大嫂大爷']

print(re.findall('^g.*? ' , 'giveme 1gfive gay')) #.*?$
print(re.findall('five$' , 'aassfive')) #['five']
print(re.findall('^giveme$' , 'giveme'))  #['giveme']
print(re.findall("^g.*e",'giveme 1gfive gay'))	#['giveme 1gfive']
print(re.findall("^g.*?e",'giveme 1gfive gay'))	#['give']
# giveme gfive

匹配分组

# ### 正则表达式
import re
# (四) 匹配分组

# a|b 匹配字符a 或者 匹配字符b  把字符串长的写在前面,字符串短的写在后面
lst = re.findall("abcd|ab","abcdef abc abcd")
print(lst)

# 匹配分组 用括号()
print(re.findall('.*?_good','wusir_good alex_good secret男_good')) #'wusir_good', ' alex_good', ' secret男_good']
# 如果加上括号() 意味着把括号里面匹配的内容显示出现
print(re.findall('(.*?)_good','wusir_good alex_good secret男_good')) #['wusir', ' alex', ' secret男']
# 如果加上?: 意味着不显示括号里面匹配的内容
print(re.findall('(?:.*?)_good','wusir_good alex_good secret男_good'))

# 匹配小数 3.14 5.56 567.890  .89  5.
''' 让有意义的. 变得无意义,要用到\ '''
lst = re.findall("\d+\.\d+","4.132  6.78  9. 9. . 999.888")
print(lst)

# 匹配小数和整数
lst = re.findall("\d+\.\d+|\d+","4.132  6.78  9. 9. . 999.888 99 666 ")
print(lst)
# 把小数点部分表达一个整体,但是却不要括号里面匹配的内容 , 所有加上?: 表达不显示
# findall 默认优先显示括号里面的内容,加上?: 不单独显示了
lst = re.findall("\d+(?:\.\d+)?","4.132  6.78  9. 9. . 999.888 99 666 ")
print(lst)


# ### 分组命名
"""
1) 分组基础上定规则 ?P<组名>
2) (?:正则表达式) 表示取消优先显示功能
3) (?P<组名>正则表达式) 表示给这个组起一个名字
4) (?P=组名) 表示引用之前组的名字,引用部分匹配到的内容必须和之前那个组中的内容一模一样
"""
# 匹配标签  "<h1>这是一级大标题</h1>" 
strvar = "123<h1>这是一级大标题</h1> 123<h2>这是二级大标题</h2>"

# print(re.findall(r"<(.*?)>.*?<(?:.*?)>",strvar))
print(re.findall(r"<(.*?)>.*?<(.*?)>",strvar))
# 针对于第一个括号里面的内容,重复引用一下. 
# 如果有多个括号,依次用\1 \2 \3 \4 ... 依次引用即可 为了减少代码量;
print(re.findall(r"<(.*?)>.*?</\1>",strvar)) # \1 反向引用第一个括号里面的内容 


#(?P=tag) 把tag分组的内容重复引用一次
print("<==333==>")
strvar = "<h1>这是一级大标题</h1> <h2>这是二级大标题</h2>"
print(re.findall(r"<(?P<tag>.*?)>(.*?)</(?P=tag)>",strvar))
"""
(分组的名字+匹配的规则)
(?P<你自定义的名字>.*?)
<.*?>
<(?P<tag>.*?)>
(?P<名字>.*?)  => 分组命名

<    .*?    >
< (?P=tag)  >
"""

正则函数

# ###正则相关函数
# ### search 返回一个对象 一次获取一个值
# ### search  返回一个对象 一次获取一个值
res = re.search("\d+","abcdefg1p2cp445jkj")
print(res)
# group 获取对象里面的内容
print(res.group())

res = re.search("\d[*/]\d","3*4-6/8")
print(res.group())
res = re.findall("\d[*/]\d","3*4-6/8")
print(res)

strvar = "<h1>这是一级大标题</h1> <h2>这是二级大标题</h2>"
res = re.search(r"<(?P<tag>.*?)>(.*?)</(?P=tag)>",strvar)
# 直接group 获取的是匹配到的字符串
# ('h1', '这是一级大标题')
print(res.group())  #<h1>这是一级大标题</h1>
# 取出第一个括号里面的第一个内容
print(res.group(1)) #h1
# 取出第一个括号里面的第二个内容
print(res.group(2)) #这是一级大标题
# print(res.group(3))


# 匹配135或171的手机号
lst = re.findall("(?:135|171)\d{8}","13512356782 17118856782")
print(lst)

# 匹配www.baidu.com 或者 www.oldboy.com
res = re.search("(www)\.(baidu|opesn)\.(com)","www.baidu.com")
print(res.group())
print(res.group(1))
print(res.group(2))

"""
print("<===>")
res = re.search(r"(.*?)\d(.*?)\d(.*?)\1\2\3","a1b2cabc")
print(res.group())
res = re.findall(r"(.*?)\d(.*?)\d(.*?)\1\2\3","a1b2cabc")
print(res)
"""

res_obj = re.search("(\d).*?(\d)","ab1d2f2k5jkjkj3u6oi4s9")
res = res_obj.group()
print(res)
res= res_obj.group(1)
res= res_obj.group(2)
print(res)
res = res_obj.groups()  #用来获取所有括号里面匹配的内容
print(res)
res = res_obj.lastindex #用来获取最大索引值(跟圆括号的个数有关系)
print(res)


# (2) match 根 search 类似
"""
默认在正则表达式的前面加上了^ (必须以..为开头)
search 只需要在表达式前面加上^ 就可以取代match
"""
res = re.match("\d","d4d2f2k5jkjkj3u6oi4s9")
res = re.search("^\d","d4d2f2k5jkjkj3u6oi4s9")
print(res)
# print(res.group())


# (3) split 按照任意分隔符进行分割
strvar = "wusir|alex|secret;opesn"
listvar = strvar.replace(";","|").split("|")
print(listvar)

strvar = "wusir,alex|secret;hello%world"
res = re.split("[,|;%]",strvar)
print(res)

strvar = "wusir3434alex454545secret456456456hello111222world"
res = re.split("(\d+)",strvar) # 加上括号之后 所有匹配到的包括括号里面的都塞到列表
print(res)

# (4) sub 等价于 subn 相当于replace  区别在于返回值;
strvar = "wusir3alex3secret"
print(strvar.replace("3","-"))
strvar = "wusir34alex56secret"
res = re.sub("\d+","|",strvar)
res = re.sub("\d+","|",strvar,1)
print(res)
res = re.subn("\d+","|",strvar,1)
print(res) #返回一个元组,包含替换次数


# (5)finditer 和 findall 用法一样 区别于返回值,返回迭代器 [迭代器里面放的是一个个对象]
"""节省内存空间"""
from collections import Iterator
it1 = re.finditer("\d","sdf2sdfsdf3sdfsdf4")
print(isinstance(it1,Iterator))
# res = next(it1)
# print(res.group())
for i in it1:
	print(i.group())
    

# (6)compile 指定统一的匹配规则
"""
每次执行正则时,都需要重新编译
如果正则表达式不变,只是编译一次重复使用,可以加快效率,用compile
"""
rule = re.compile("\d+")
res = rule.search("ssdfs234sdfsdf234sfsdf")
print(res.group())
it2 = rule.finditer("ssdfs234sdfsdf234sfsdf")
print(res)
for i in it2:
	print(i.group())
    

"""
re.I  大小写匹配不敏感
re.M  支持跨行,使每行都能单独匹配^$
re.S  使.能够匹配换行\n
"""
# re.I 大小写匹配不敏感
rule = re.compile("<h1>(.*?)</h1>",flags=re.I)
strvar="<h1>111222</H1>"
res = rule.search(strvar)
if res:print(res.group())

# re.M 支持跨行,使每行都能单独匹配^$
rule = re.compile("^<h1>(.*?)</h1>$",flags=re.M)
strvar = """<h1>111</h1>
<h1>222</h1>
<h1>333</h1>
"""
res = rule.findall(strvar)
print(res)

# re.S 使.能够匹配换行\n
strvar = """give
123mefive
"""
rule = re.compile("(.*?)mefive",flags=re.S)
lst = rule.findall(strvar)
print(lst)

python 异常处理

程序错误分为两种:语法错误 和 异常错误
语法错误:代码没有按照python规定语法去写,发明创造产生的错误
异常错误:在代码语法正确的前提下,程序报错就是异常

#try...except...  基础语法  用于解决程序异常问题
#raise 可以主动抛异常,异常类可以自定义

#异常的分类
IndexError                索引超出序列的范围
KeyError                  字典中查找一个不存在的关键字
NameError                 尝试访问一个不存在的变量
IndentationError          缩进错误
AttributeError            尝试访问未知的对象属性
StopIteration             迭代器没有更多的值
AssertionError			 断言语句(assert)失败
EOFError                  用户输入文件末尾标志EOF(Ctrl+d)
FloatingPointError        浮点计算错误
GeneratorExit             generator.close()方法被调用的时候
ImportError               导入模块失败的时候
KeyboardInterrupt         用户输入中断键(Ctrl+c)
MemoryError               内存溢出(可通过删除对象释放内存)
NotImplementedError       尚未实现的方法
OSError                   操作系统产生的异常(例如打开一个不存在的文件)
OverflowError             数值运算超出最大限制
ReferenceError            弱引用(weak reference)试图访问一个已经被垃圾回收机制回收了的对象
RuntimeError              一般的运行时错误
SyntaxError               Python的语法错误
TabError                  Tab和空格混合使用
SystemError               Python编译器系统错误
SystemExit                Python编译器进程被关闭
TypeError                 不同类型间的无效操作
UnboundLocalError         访问一个未初始化的本地变量(NameError的子类)
UnicodeError              Unicode相关的错误(ValueError的子类)
UnicodeEncodeError        Unicode编码时的错误(UnicodeError的子类)
UnicodeDecodeError        Unicode解码时的错误(UnicodeError的子类)
UnicodeTranslateError     Unicode转换时的错误(UnicodeError的子类)
ValueError                传入无效的参数
ZeroDivisionError         除数为零

#获取错误行号和文件名(了解)
#(了解)系统底层获取行数和文件名的函数( 只有在程序异常时才能触发 ) 
def return_errorinfo(n):
	import sys
	f = sys.exc_info()[2].tb_frame.f_back
	if n==1:		
		return str(f.f_lineno)      #返回当前行数
	elif n == 2:	
		return f.f_code.co_filename #返回文件名	

了解异常

# ### 异常处理

# IndexError                索引超出序列的范围
listvar = [1,2,3,4,4,5,56,6,7]

# print(listvar[99])


# KeyError                  字典中查找一个不存在的关键字
# dictvar = {"a":1,"b":2,"鼓上骚":"石阡","午夜叉":"杜十娘","花和尚":"鲁智深"}

# dictvar["wangwen"]

# NameError                 尝试访问一个不存在的变量
# print(shenminanhai )


# IndentationError          缩进错误
# if 4==5:
	# print(1)
    # print(2)

# AttributeError            尝试访问未知的对象属性
# class Ceshi():
	# a = 4
	# def func(self):
		# print(123)
		
# obj = Ceshi()
# print(obj.ccc)


# StopIteration             迭代器没有更多的值
"""
def gen1():
	yield 1
	yield 2
	print(333)

mygen = gen1()
res = next(mygen)
res = next(mygen)
res = next(mygen)
print(res)
"""

# AssertionError			 断言语句(assert)失败    用在项目上线,测试人员测试代码用的
# 大胆的猜测一下, 如果1>3 我猜对了 什么事没有 如果我猜错了 直接报错,抛出异常
assert  1>3 

"""
if 1>3:
	pass
else:
	pass
"""

异常处理语法

# ### 异常处理
'''
# 基础语法
try:
	pass
except:
	pass
	
把有可能出问题的代码放到try这个代码块当中,如果出现报错出现异常,直接走except这个代码块
except 更像是elif 和 else的组合
'''
# (1) 单项分支的异常处理
try:
	listvar = [1,2,3]
	listvar[999]
except:
	pass


# (2) 多项分支的异常处理
try:
    dictvar = {"a":1,"b":2}
    dictvar["cccc"]
    listvar = [1,2,3]
    listvar[999]
except KeyError:
    print("该字典的键不存在")
except IndexError:
    print("该异常错误是索引超出范围")
    
    
# (3) 解决生成器越界的异常处理
def gen2():
	yield 3
	yield 4
	return 19
mygen2 = gen2()

try:
	res= next(mygen2)
	res= next(mygen2)
	res= next(mygen2)
	print(res)
	
	"""
	当我们直接打印对象e的时候,实际上触发了StopIteration 这个类里面的
	魔术方法 __str__
	__str__ 里面的逻辑接受到了实际return的返回值
	StopIteration as e    #给StopIteration类对象起别名是e
	"""
except StopIteration as e:
	print(e)

主动抛出异常

# ### raise 主动抛出异常
"""
raise + (异常错误类 + 异常错误类对象)
BaseException	所有异常错误的类父类 (基类,超类) (子类:衍生类 派生类)
Exception       常规错误的基类(了解)
"""
res= issubclass(Exception,BaseException)
print(res)

# (1) 基本语法 主动抛出异常
try:
	# raise BaseException
	raise BaseException()
except BaseException:
	print("我错了123")

# 简写:
try:
	raise
except:
	print("我还是错了")

# (2) 检验代码错误内容
#(了解)系统底层获取行数和文件名的函数( 只有在程序异常时才能触发 ) 
def return_errorinfo(n):
	import sys
	f = sys.exc_info()[2].tb_frame.f_back
	if n==1:		
		return str(f.f_lineno)      #返回当前行数
	elif n == 2:	
		return f.f_code.co_filename #返回文件名	

# return_errorinfo 必须通过抛出异常才能触发
def get_err(n):
	try:
		raise
	except:
		return return_errorinfo(n)
		


# 自定义异常错误类 (务必需要继承 BaseException)
class MyException(BaseException):
	def __init__(self,err_num,err_msg,err_line,err_file):
		# 抛出代号
		self.err_num = err_num
		# 错误消息
		self.err_msg = err_msg
		# 文件的行数
		self.err_line = err_line
		# 文件名 
		self.err_file = err_file
		
sex = "中性"
try:
	if sex == "中性":
		raise MyException(101,"人类没有中性",get_err(1),get_err(2))
except MyException as e:
	print(e.err_num)   # 抛出代号
	print(e.err_msg)   # 错误消息
	print(e.err_line)  # 文件的行数
	print(e.err_file)  # 文件名 

python 装饰器

# ### 装饰器:
"""
装饰器:为原函数拓展新功能,返回新函数替换旧函数
作用: 在不改变原来代码的前提下,增加新功能
语法特征: @
"""

# 第一步 装饰器原型 
def kuozhan(func):
	def newfunc():
		print("厕所前,蓬头垢面")
		func()
		print("厕所后,精神抖擞")
	return newfunc

def func():
	print("我是高富帅")

# 旧函数 = 新函数
func = kuozhan(func)
func()

print("<=-===2===>")
# 第二步 装饰器@符
'''@:系统会自动把下面的函数当成参数传递给@符右侧的函数,替换旧函数'''
def kuozhan(func):
	def newfunc():
		print("厕所前,头蓬构面")
		func()
		print("厕所后,精神抖擞")
	return newfunc

@kuozhan  
def func():
	print("我是白富美")

# func = kuozhan(func)
func()
"""
把func 函数 当成参数 传递给@符后面的kuozhan函数,
把kuozhan函数的返回值赋值给func
func = newfunc
func() <===> newfunc()
"""

print("==3==")
# 第三步 装饰器的嵌套
def kuozhan1(func):
	def newfunc():
		print("厕所前,牛头马面1")
		func()
		print("厕所前,人模狗样2")
	return newfunc

def kuozhan2(func):
	def newfunc():
		print("吃饭前,打豆豆3")
		func()
		print("吃饭后,睡觉觉4")
	return newfunc

@kuozhan2
@kuozhan1
def func():
	print("hello world")

func()
"""
从下往上看:
	func当成参数传递给kuozhan1
	# 变成如下形状:
	@kuozhan2
	newfunc

	把newfunc当成参数传递给kuozhan2
	func = newfunc

	func() <===> newfunc()

"""

print("<==4==>")
# 第四部 对带有参数的原函数进行装饰器扩展
"""原函数几个参数,扩展之后仍然几个参数,参数之间一一对应"""
def kuozhan(func):
	def newfunc(who,where):
		print("厕所前,干净整洁")
		func(who,where)
		print("厕所后,臭气熏天")
	return newfunc

@kuozhan
def func(who,where):
    print("{who}在{where}".format(who=who, where=where))
func("我","学习")


print("<==5==>")
# 第五步 对带有参数返回值的原函数进行装饰器扩展
def kuozhan(func):
	# 定义处:*args **kwargs 打包 收集参数
	def newfunc(*args,**kwargs):
		print("厕所前,萎靡不振")
		# 调用处:*args , **kwargs 解包
		res = func(*args,**kwargs)
		print("厕所后,兽性大发")
		# 最后返回列表
		return res
	return newfunc

@kuozhan
def func(*args,**kwargs):
	# 循环打印args里面所有内容
	for i in args:
		print("场所是"+i)
	# 具体指定谁留下了什么
	dictvar = {"p":"python","j":"java","s":"shell"}
	# "谁留下了黄金多少" => list ["","",""]
	res = [dictvar[a]+"留下了黄金:"+b for a,b in kwargs.items() if a in dictvar]
	# return lst
	return res
	
res = func("天上","人间",p="11克",j="21顿",s="32斤",abc=999)
print(res)


# 第六步 用类装饰器来扩展原函数
print("==6===?")
class KuoZhan():
	def __call__(self,func):
		return self.newfunc1(func)

	def newfunc1(self,func):
		def newfunc2():
			print("厕所前,饥肠辘辘")
			func()
			print("厕所后,酒足饭饱")
		return newfunc2
		
	def newfunc3(func):
		def newfunc4():
			print("厕所前,茶饭不思")
			func()
			print("厕所后,满口雌黄")
		return newfunc4

# 情况一
@KuoZhan()   #@KuoZhan() => @obj =>obj(func) => 应该返回一个函数 => func = newfunc2
def func():
	print("厕所进行时... ... ")


# 情况二
@KuoZhan.newfunc3
def func():
	print("厕所进行时... ... ")

func()
"""
uoZhan.newfunc3(func) => newfunc4 =>func = newfunc4 =>func() <===> newfunc4()
"""

# 第七步 带有参数的函数装饰器
"""根据不同的参数值,返回不同的功能"""
def outer(n):
	def kuozhan(func):
		def newfunc1(self):
			print("厕所前,老实巴交")
			func(self)
			print("厕所后,嘚瑟傲娇")
			
		def newfunc2(self):
			print("厕所前,浑身难受")
			func(self)
			print("厕所后,浑身发麻")			
			
		if n == 1:
			return newfunc1
		elif n == 2:
			return newfunc2
		# 把函数变成属性
		elif n == 3:
			return 5488
			
	return kuozhan

print("<===7==>")
class MyClass():
	
	@outer(1) # =>先算@符右边的值 然后=> @kuozhan => func1 = kuozhan(func1) => func1 = newfunc1
	def func1(self):
		print("前进一小步")
	
	@outer(2) # =>先算@符右边的值 然后=> @kuozhan => func2 = kuozhan(func2) => func2 = newfunc2
	def func2(self):
		print("文明一大步")

	@outer(3) # =>先算@符右边的值 然后=> @kuozhan => func3 = kuozhan(func3) => func3 = 5488
	def func3(self):
		print("来也冲,去也冲")
		
	#func3 = 5488

obj = MyClass()
obj.func1()
print("<===71==>")
obj.func2()
print("<===71==>")
# obj.func3()
print(obj.func3)


# 第八步 带有参数的类装饰器
"""
如果传的是参数1,我就为当前这个类添加成员属性和方法
如果传的是参数2,我就把当前类中的run方法变成属性
"""


class KuoZhan():
	ad = "贵族茅厕,欢迎您来,欢迎您下次再来"
	def __init__(self,num):
		self.num = num
		
	def __call__(self,cls):
		if self.num == 1:
			return self.func1(cls)
			# return newfunc
		elif self.num == 2:
			return self.func2(cls)
			
	def money(self):
		print("蹲坑每小时10元,包月1400")
			
	def func1(self,cls):
		def newfunc():
			# 添加成员属性
			self.addpty(cls)
			return cls()			
		return newfunc
		
	def addpty(self,cls):
		# 添加成员属性
		cls.ad = KuoZhan.ad
		# 添加成员方法
		cls.money = KuoZhan.money
		
	def func2(self,cls):
		def newfunc():
			# 更新把run方法变成属性
			self.updatepty(cls)
			return cls()
		return newfunc
		
	def updatepty(self,cls):
		# 判断一下 run 方法是否存在
		if "run" in cls.__dict__:
			# 把run方法执行一下,要里面的返回值
			res = cls.run()
			# 把返回值添加到成员属性run当中,把以前的run方法替换成run属性
			cls.run = res
		# 返回一个对象
		
			
"""
@ KuoZhan(1) => @obj
=> @obj => MyClass = obj(MyClass) 
=> MyClass = newfunc => MyClass() = newfunc() 
=> obj =  MyClass() = newfunc() = cls()
"""
@KuoZhan(1)  
class MyClass():
	def run():
		return "亢龙有悔"

obj = MyClass()
print(obj.ad)
obj.money()

@KuoZhan(2)  
class MyClass():
	def run():
		return "亢龙有悔"

obj = MyClass()
# print(MyClass.__dict__)
print(obj.run)
# {'__module__': '__main__', 
# 'run': <function MyClass.run at 0x7f4238a9ed08>, 
# '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None}


"""
# 注意点
def abc(cls):
	return cls.a

class bbb():
	a = 10
res = abc(bbb)
print(res)
# print(bbb.a)
# error  int object is not callable
# bbb = 13
# bbb()
"""

静态绑定方法

# ### 类中的方法
"""
普通方法:没有任何参数,只能用类来调用
绑定方法:(1)绑定到对象(默认传递参数->对象)(2)绑定到类(默认传递参数->类)
静态方法:不需要传递任何参数,对象和类都能调用
"""

class Dog():

	def __init__(self,name):
		self.name = name

	food = "骨头"
	# 普通方法
	def tian():
		print("小狗都爱舔一舔")
		
	# 绑定方法
	def jiao(self):
		print("小狗看到主人都喜欢叫,要{}".format(self.name))
	
	# 绑定到类的方法 类方法
	@classmethod
	def tail(cls):
		print("小狗喜欢摇尾巴")
		
	# 静态方法 
	@staticmethod
	def jump():
		print("小狗喜欢跳起来接飞盘")

obj = Dog("詹姆斯蛋")

# (1) 普通方法
# obj.tian() #error
Dog.tian()

# (2) 绑定方法(绑定对象的)
obj.jiao()
# Dog.jiao(Dog) error

# (3) 绑定方法(绑定到类)
# Dog.tail()   # 默认传类
# obj.tail()   # 默认先找到obj所归属的类,把类在传进去

# (4) 对象和类都能调用
obj.jump()
Dog.jump()

property

# ### @property
"""
可以把方法变成属性
可以实现属性的获取,设置,删除.
# 
自定义的名字+setter 设置  
自定义的名字+deleter 删除
"""

# 方法一
class MyClass():
	def __init__(self,name):
		self.name = name

	@property         # 获取值
	def username(self):
		# pass #可以控制是否能够获取到当前值
		return self.name	

	@username.setter  # 设置值 在设置值得时候触发
	def username(self,val):
		# pass
		self.name = val
		
	@username.deleter # 删除值 在删除值得时候触发
	def username(self):
		# del self.name
		pass
obj = MyClass("刘三胖子")
"""
# print(obj.username())
# 获取username值
print(obj.username)
# 设置username值
obj.username = 15
print(obj.username)
# 删除username值
del obj.username
print(obj.username)
"""

obj.username = 10
print(obj.username)
del obj.username
print(obj.username)




# 方法二
class MyClass():	
	def __init__(self,name):
		self.name = name
	
	def get_username(self):
		# pass #可以控制是否能够获取到当前值
		return self.name	

	# 设置值 在设置值得时候触发
	def set_username(self,val):
		# pass
		self.name = val
		
	# 删除值 在删除值得时候触发
	def del_username(self):
		del self.name
		pass
		
	# 参数顺序有要求 : 获取 , 设置 , 删除 ,按照这样的次序往property里面塞方法
	# 把定义的属性放到类的最下面
	username = property(get_username,set_username,del_username)	
	address =  property(get_username,set_username,del_username)	
		

	
print("<====>")
obj = MyClass("刘三胖子")
print(obj.username)

obj.username = "刘德华"
print(obj.username)

# del obj.username
# print(obj.username)


# address
print(obj.address)
posted @ 2020-08-18 09:03  helloord  阅读(305)  评论(0编辑  收藏  举报