# list列表 详细

'''
List 列表
java中也有List,概念为集合
python中List为列表 有点像java中的数组 但也像集合
用[]创建一个list 列表
是通过下标获取元素的
'''

list_test1=[]
print(list_test1) #[]
print(type(list_test1)) # <class 'list'>
# list_test1[0]='index1' #IndexError: list assignment index out of range
# 看来空list不同通过索引进行赋值添加

list_test2=['red','blue','green']
print(list_test2)
print(list_test2[0])
# 循环输出list
for name in list_test2:
    print(name)
print(list_test2[-1]) # 也可以逆向索引输出

print(list_test2[0:1]) # 截取输出

# 更新列表元素
print('改变前,',id(list_test2)) # 改变前, 2181753287552
print('元素改变前',id(list_test2[0])) # 元素改变前 2181753224176
list_test2[0]='while'
print(list_test2) # 列表是可变类型
print('改变后,',id(list_test2)) # 改变后, 2181753287552
print('元素改变后',id(list_test2[0])) # 元素改变后 2181753627888
#探究一下这个变量的内存地址
# 可见list_test2的地址并没有变化 ,但列表中的元素改变了 ,元素的地址发送了变化

# 删除列表元素
list_test3=['index1','index2','index3']
print(list_test3) # ['index1', 'index2', 'index3']
del list_test3[1]
print(list_test3) # ['index1', 'index3']
# del list_test3[5] # IndexError: list assignment index out of range 删除注意范围

# 操作符
list_test4=['index1','index2','index3']
list_test5=['index1','index2','index3']
#可以看出值相同的列表,地址是不同的
print(id(list_test4)) #2018910802880
print(id(list_test5)) # 2018910825600
#组合列表
print(list_test4+list_test5)
#重复输出列表
print(list_test4*3)
# 判断元素是否存在列表
print('index' in list_test4) # False
print('index1' in list_test4) # True
# 循环迭代列表
for x in list_test4:
    print(x,end=' ')
print()
# 嵌套列表
list_a=['a','b','c']
list_b=['e','f','g']
list_c=[list_a,list_a]
print(list_c)
#得到嵌套列表中的元素
print(list_c[0]) #得到a列表
print(list_c[0][0]) #得到a列表中的第一个值
# List列表中的常用函数与方法
list_test1=['index0','index1','index2','index3']

#获取列表元素个数
print(len(list_test1))
# 获取列表中的最大值,最小值
print(max(list_test1))
print(min(list_test1))
#转换为列表
a="123456"
print(type(a)) # <class 'str'>
a=list(a)
print(a) # ['1', '2', '3', '4', '5', '6']
print(type(a)) # <class 'list'>
a=[1,2,3,4,5,6]
print(list(a))
a=(1,2,3,4,5,6,7)
print(type(a)) # <class 'tuple'>
a=list(a)
print(type(a)) #<class 'list'>
a={1,2,3,4,5,6}
print(type(a)) # <class 'set'>
a=list(a)
print(type(a)) #<class 'list'>

# 常用方法

#在列表末尾添加元素
list_test2=[]
# 直接list_test2[0]='0' 会报错
list_test2.append("0")
print(list_test2)  # ['0']添加成功
# 加点数据
list_test2.append("1")
list_test2.append("1")
list_test2.append("3")
list_test2.append("4")
list_test2.append("5")
list_test2.append("3")
print(list_test2) # ['0', '1', '1', '3', '4', '5', '3']
# 统计某元素在列表中出现的次数
print(list_test2.count("3")) # 2

# 在列表后追加另一个序列的值 (其实就是用新列表扩展原来的列表)
list_test3=[8,8,8,6,9]
print(list_test2.extend(list_test3)) # None输出none 说明这个方法没有返回值
print(list_test2) # ['0', '1', '1', '3', '4', '5', '3', 8, 8, 8, 6, 9]

# 找到某值第一次出现的索引位置
print(list_test2.index('1')) # 1 失败会抛异常

# 向列表中插入元素
# list_test3.insert(10) # TypeError: insert expected 2 arguments, got 1 两个参数 索引和值
list_test3.insert(10,3) # 索引超过长度会默认在最后插入
print(list_test3) # [8, 8, 8, 6, 9, 3]
list_test3.insert(-3,100)  # 也可以用负索引插入
print(list_test3) # [8, 8, 8, 100, 6, 9, 3]

# 移出元素 pop
print(list_test3.pop()) # 3   默认移出最后一个元素
print(list_test3) # [8, 8, 8, 100, 6, 9]
print(list_test3.pop(2)) # 8  还可以指定索引位弹出
print(list_test3) # [8, 8, 100, 6, 9]

# 移出列表中某值的第一个匹配项 remove
print(list_test3.remove(8)) # None 说明没有返回值
print(list_test3) # [8, 100, 6, 9]

# 反向列表中的元素  reverse
print(list_test3.reverse()) # None 没有返回值
print(list_test3) # [9, 6, 100, 8]

# 对列表元素进行排序 list.sort( key=None, reverse=False) Flase升序(默认)     True 降序
list_test3.sort(reverse=True)
print(list_test3)

# 清空列表
list_test3.clear()
print(list_test3) #[]

# 赋值列表
list_test3=list_test2.copy()
print(list_test3) # ['0', '1', '1', '3', '4', '5', '3', 8, 8, 8, 6, 9]
print(id(list_test2)) #2073999662016
print(id(list_test3)) #2073999661952  复制出来地址不同
# 元组详细

'''
元组与列表相似 但元组是不可变的数据类型  处于元组中的元素不能被修改
元组用()表示
'''
#创建元组
tup1=()
# tup1[0]=1 #TypeError: 'tuple' object does not support item assignment
# print(tup1)
print(type(tup1))

#注意点  当元组只包含一个元素时,要在那个元素后面加上逗号,否则()会被当成运算符
tup1=(50)
print(type(tup1)) # <class 'int'>
tup1=(50,)
print(type(tup1)) # <class 'tuple'>

# 访问元组元素依旧是通过索引来访问的
print(tup1[0]) # 50

# 修改元组
# tup1[0]=100 # TypeError: 'tuple' object does not support item assignment
#但可以对元组进行连接 从而创建一个新元组
tup1=(50,100)
tup2=(80,90)
print(tup1+tup2) # (50, 100, 80, 90)

#删除元组 元组不可修改,所以也不能删除其中的元素 只能通过del删除整个元组
del tup2
# print(tup2) #NameError: name 'tup2' is not defined

#遍历元组
for value in tup1:
    print(value) # 50   100
# 元组中的常用函数和方法

# len() 元组中元组个数
#max(),min()  最大最小值

#tuple() 将可迭代序列转化成元组
list=[1,2,3,4,6]
tuple1=tuple(list)
print(tuple1) #  (1, 2, 3, 4, 6)
dict={'name':'zxy','age':18}
tuple1=tuple(dict)
print(tuple1) # ('name', 'age')

# 关于元组是不可变的
# 所谓元组的不可变指的是元组所指向的内存中的内容不可变。
list=[1,2,3,4,5]
print(id(list)) # 2063075181632
list[0]=100
print(id(list)) #  2063075181632

tuple1=(1,2,3,4,5,6)
print(id(tuple1)) #3098764856288
tuple1=(1,2,3,4,5,8)
print(id(tuple1)) #3098764857056

#重新赋值的元组 tup,绑定到新的对象了,不是修改了原来的对象。
# 字典详细

'''
字典是可变数据类型
可以存储任意的对象
是键值对形式的 key:value
字典包含在{}中
可以按map理解
'''

#创建字典
dict={} # 空字典
dict1={'name':'zxy','age':18}
print(dict)
print(dict1)

#访问字典中的值
print(dict1['name'])
#访问不存在的key 会出错误
# print(dict1['height']) # KeyError: 'height'
#修改字典
dict1['name']='new zxy'
print(dict1)
dict['addKey']='value'
print(dict) # {'addKey': 'value'}

#删除字典元素
del dict1['age']
print(dict1) # {'name': 'new zxy'}
#清空字典
dict1.clear()
print(dict1) #{}
#删除字典
del dict1
# print(dict1) # NameError: name 'dict1' is not defined

# 字典 key(键)的特性
#1. 不允许同一个键出现两次,如果有两个相同的键,后一个键的值将会被记住
dict1={'name':'key_name1','age':18,'name':'key_name2'}
print(dict1) # {'name': 'key_name2', 'age': 18}

#2. 键的值不能变,所以可用数字,字符串,元组当键(不可变类型),不能用可变类型当键
dict={(1,2,3):'tup123'}
print(dict)
# dict={[1,2,3]:'lsit123'} # TypeError: unhashable type: 'list'
# print(dict)
# 字典中的函数和方法
dict1={'name':'zxy','age':18,'height':180,'weight':130,123:456}
print(dict1)
# 获取key的个数
print(len(dict1))

print(str(dict1)) # {'name': 'zxy', 'age': 18, 'height': 180, 'weight': 130, 123: 456} 输出字典

print(type(dict1)) # <class 'dict'> 获取类型

# 常用方法
dict2={'name':'zxy','age':18,'height':180,'weight':130,123:456}
# 清空字典
print(dict2) # {'name': 'zxy', 'age': 18, 'height': 180, 'weight': 130, 123: 456}
dict2.clear()
print(dict2) # {}

#copy 拷贝 (浅拷贝)
'''
直接赋值:其实就是对象的引用(别名)。

浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象。

深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象。
'''
# 深拷贝需要引入copy模块
import  copy

dict={'user':'zxy','num':[1,2,3]} #创建字典dict
a=dict.copy() # 将dict拷贝至a,浅拷贝
b=dict #直接赋值
c=copy.deepcopy(dict)
print(dict) # {'user': 'zxy', 'num': [1, 2, 3]}
print(a) # {'user': 'zxy', 'num': [1, 2, 3]}
print(b) # {'user': 'zxy', 'num': [1, 2, 3]}
print(c) # {'user': 'zxy', 'num': [1, 2, 3]}
dict['add']='add'

print(dict) # {'user': 'zxy', 'num': [1, 2, 3], 'add': 'add'}
print(a)  # {'user': 'zxy', 'num': [1, 2, 3]}
print(b) # {'user': 'zxy', 'num': [1, 2, 3], 'add': 'add'}
print(c) # {'user': 'zxy', 'num': [1, 2, 3]}
#会发现直接赋值的b的值也增加了add这个key
dict['num'].append(4) #修改dict内部list的值
print(dict)  # {'user': 'zxy', 'num': [1, 2, 3, 4], 'add': 'add'}
print(a) # {'user': 'zxy', 'num': [1, 2, 3, 4]}
print(b) # {'user': 'zxy', 'num': [1, 2, 3, 4], 'add': 'add'}
print(c) # {'user': 'zxy', 'num': [1, 2, 3]}
# 会发现拷贝的字典a中 list内的值也被改变了
# 深拷贝完全不会受拷贝对象的改变而改变

# 创建字典
print(dict.fromkeys((1, 2, 3))) # {1: None, 2: None, 3: None}
print(dict.fromkeys((1,2,3),(10,10,10,10))) # {1: (10, 10, 10, 10), 2: (10, 10, 10, 10), 3: (10, 10, 10, 10)}
# 相当于第二个参数是每个key的默认值

dict={'user':'zxy','num':[1,2,3]} #创建字典dict
#返回指定键的值,如果不存在,则返回默认值
print(dict.get('user')) # zxy
print(dict.get('age')) # None
print(dict.get('age',"test")) # test 为默认值

#判断key是否在字典中
print('user' in dict) #True

#以列表返回可遍历的(键, 值) 元组数组
print(dict.items()) # dict_items([('user', 'zxy'), ('num', [1, 2, 3])])

#  返回一个迭代器,可以使用 list() 来转换为列表
print(dict.keys()) # dict_keys(['user', 'num'])

#  和get()类似, 但如果键不存在于字典中,将会添加键并将值设为default;
# 存在则返回 不存在则添加 值为default的值
print(dict.setdefault('age')) # None
print(dict) # {'user': 'zxy', 'num': [1, 2, 3], 'age': None}
print(dict.setdefault('weight', 100)) # 100
print(dict) # {'user': 'zxy', 'num': [1, 2, 3], 'age': None, 'weight': 100}

#把字典dict2的键/值对更新到dict里
dict2={'name':'zxy','age':18,'height':180,'weight':130,123:456}
print(dict.update(dict2)) # None 没有返回值
print(dict) # {'user': 'zxy', 'num': [1, 2, 3], 'age': 18, 'weight': 130, 'name': 'zxy', 'height': 180, 123: 456}

# 返回值的迭代器,是字典中所有的值
print(dict.values()) # dict_values(['zxy', [1, 2, 3], 18, 130, 'zxy', 180, 456])

#删除字典给定键 key 所对应的值,返回值为被删除的值。key值必须给出。 否则,返回default值。
# dict.pop('777') # KeyError: '777'
print(dict.pop('777', 'ok')) # ok 没有key返回默认值
print(dict.pop('name')) # zxy

#随机返回并删除字典中的最后一对键和值。
print(dict.popitem()) # (123, 456)
print(dict.popitem()) # ('height', 180)
# 集合类型详细

'''
集合(set)是一个无序的不重复元素序列。
可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
'''
set1={1,2,3}
set2={}
set3=set()
print(type(set1)) #<class 'set'>
print(type(set2)) #<class 'dict'>
print(type(set3)) #<class 'set'>

set1={1,2,3,4,1,2,3,4}
print(set1) # {1, 2, 3, 4}去重

# 判断元素是否在集合中
print(1 in set1) # True

# 添加元素
set4=set() #创建一个空集合
set4.add(1)
set4.add(2)
print(set4) #{1, 2}
# 还有一个方法,也可以添加元素,且参数可以是列表,元组,字典等,语法格式如下
set4.update((1,2,3,4,5,6))
print(set4) # {1, 2, 3, 4, 5, 6}


# print(set4[0]) # TypeError: 'set' object is not subscriptable

# 移出元素 从集合中移出某元素  元素不存在 会报错
print(set4.remove(4)) # None 没有返回值
print(set4) # {1, 2, 3, 5, 6}
# set4.remove(4) # KeyError: 4
#  移出元素 元素不存在 不会报错
set4.discard(4)# 不会报错
# 随机删除集合中的元素
print(set4) # {1, 2, 3, 5, 6}
print(set4.pop()) # 1
print(set4) #{2, 3, 5, 6}
print(set4.pop()) # 2
print(set4.pop()) # 3
#难道是弹出第一个?
#再测试
test={8,9,10,5,6,7,10,9,5,4}
print(test) # {4, 5, 6, 7, 8, 9, 10}
print(test.pop()) # 4
# set 集合的 pop 方法会对集合进行无序的排列,然后将这个无序排列集合的左面第一个元素进行删除。
# 这里又发现了一个问题 为什么我的test集合被排序了?
test={'zxt','78q','899w','zxy','qwer'}
print(test) # {'78q', '899w', 'qwer', 'zxy', 'zxt'} 顺序还是被改变了
test={5679,14451,2233,9981,7749,659,782,783,781,1,69,45}
print(test) # {1, 69, 7749, 781, 782, 5679, 783, 45, 14451, 659, 2233, 9981}
# 查资料得出:set的数值过小时,可能会出现这种自动排序的现象,但数据大一点后,就会发现其实并没有自动排序

#计算集合中的元素个数
print(len(test)) # 12
#清空集合
test.clear()
print(test) # set()
#判断元素是否存在集合中
s={1,2,3,4,5,6}
print(1 in s) # True
print(7 in s) # False
# 集合的常用函数和方法

set1=set()
# 新增元素
set1.add("1")
print(set1) #{'1'}

# 清除元素
set1.clear()
print(set1) # set()

# 拷贝集合
a={1,2,3,4,5}
b=a.copy()
print(b) # {1, 2, 3, 4, 5}
b.update({1,2,6,8,9,10,11})

#删除集合中的指定元素
b.discard(1)

print(a);print(b)

#差集
z=a.difference(b)
x=b.difference(a)
print(z) #{1}
print(x) # {6, 8, 9, 10, 11}

#交集
z=a.intersection(b)
print(z) # {2, 3, 4, 5}

#并集
z=a.union(b)
print(z) # {1, 2, 3, 4, 5, 6, 8, 9, 10, 11}
# 斐波拉切数量
a,b=0,1
while b<10:
    print(b,end=",")
    a,b=b,a+b
# end 关键字 将结果输出到同一行,并按指定字符结尾
print()
# 乘法表
for i in range(10):
    for j in range(10):
        sum=i*j
        print(f"{i}*{j}={sum}",end=" ")
    print()

# 冒泡排序
list=[9,8,6,1,10,7,5,4]

for i in range(len(list)-1):
    for j in range(len(list)-1-i):
        if list[j]>list[j+1]:
            temp=list[j];list[j]=list[j+1];list[j+1]=temp
print(list)
# 条件控制语句

# if语句
'''
java中
if(){}else{}
if(){}else if(){} else{}
'''
if (1>3):
    print("1>3")
elif 5>4:
    print("5>4")
else:
    print("this is elese")
# 可以看出python中省去了()和{} 看起来比较简洁 但是 对缩进和格式的要求比较高
# 当然加上括号也没什么关系
# 但是要注意  python中没有 switch-case语句

#做一个输入测试
# a=input("请输入数字选择菜单")
# a=int(a)
# if a==0:
#     print("首页")
# elif a==1:
#     print("用户管理")
# elif a==2:
#     print("系统管理")
# else:
#     print("暂未开发")

# if 条件中常用的操作运算符
'''
<,<=,>,>=,==,!=
'''

#if嵌套  与java相似  注意缩进格式
a=6
if a%2==0:
    if a%5==0:
        print("能被2和5整除")
    else:
        print("能被2整除,但不能被5整数")
else:
    print("不能被2和5整除")
# 循环控制语句

'''
while循环
java 的格式  while(条件){}
'''
# 有限循环
# a=1
# while a<10:
#     print(a)
#     a=a+1


# 无限循环 在服务器上客户端的实时请求可以用无限循环  利用 ctrl+c 终止
# while True:
#     num=int(input("请输入一个数:"))
#     print(f"输入了num:{num}")
# print("循环结束")

# while.. else...
#在while条件为False时执行else
# count=0
# while count<5:
#     print(f"count小于五,现在是{count}")
#     count=count+1
# else:
#     print(f"count大于5,现在是{count}")

#for 循环
# python中可以使用for else
list=[1,2,3,4,5,6,7]
for x in list:
    if x==3:
        print(x)
        break #  终止循环
else:
    print("我是else")
print("循环完成")
'''
3
循环完成
'''
for x in list:
    if x==3:
        print(x)
else:
    print("我是else")
print("循环完成")
'''
3
我是else
循环完成
'''
#可见break破坏循环后,else中语句不会执行
for x in list:
    if x==3:
        print(x)
        continue
else:
    print("我是else")
print("循环完成")
'''
3
我是else
循环完成
'''
#continue 也会执行else中的语句

#range函数 循环中常用的
#普通range
for i in range(5):
    print(i,end=" ")
#0 1 2 3 4
print()
#范围range
for i in range(9,15):
    print(i,end=" ")
#9 10 11 12 13 14

#步长range
print()
for i in range(0,10,2):
    print(i,end=" ")
# 0 2 4 6 8


# pass 语句
'''
Python pass是空语句,是为了保持程序结构的完整性。
pass 不做任何事情,一般用做占位语句,如下实例
点开python很多方法时,都只看到一个pass,就会好奇,为什么没有详细的源码块,而只有一个pass?
原因:
python是C语言实现的,尽管有很多标准库是由python代码实现,但是涉及到底层支撑架构的功能还是C代码。
一些IDE为了对这些进行友好代码提示,会弄和底层一样的访问接口,而其实现直接写 pass 略过。
'''
print()
i=sum=0
while i<=4:
    sum+=i
    i=i+1
print(sum)