pycharm的安装和使用
"""
pycharm设置界面(ctrl+alt+s)
修改编辑界面字体
修改控制台界面字体
如何快速创建文件(alt+insert)
格式化python代码,使编程风格好看
如何撤销代码的修改(ctrl + z)
如何取消撤销的代码的修改(ctrl + shift + z)
快速重命名(shift + F6)
快速注释代码(ctrl + /)
快速取消注释代码(ctrl + /)
"""
字符串常用方法_大小写
# 判断字符串 变成‘标题’
In [1]: 'Hello'.istitle()
Out[1]: True
In [2]: 'hello'.istitle()
Out[2]: False
In [7]: 'heLLo'.islower()
Out[7]: False
In [8]: 'heLLo'.isupper()
Out[8]: False
# 将字符串全部变为大写
In [3]: 'hello'.upper()
Out[3]: 'HELLO'
# 将字符串全部变为小写
In [4]: 'heLLo'.lower()
Out[4]: 'hello'
In [5]: 'heLLo'.title()
Out[5]: 'Hello'
In [6]: 'heLLo'.swapcase()
Out[6]: 'HEllO'
"""
[[:digit:]] [[:alnum:]]
[[:upper:]] [[:lower:]]
[[:space:]]
"""
字符串判断练习_变量名是否合法
"""
变量名是否合法?
1.变量名可以由字母,数字或下划线组成
2.变量名只能以字母或下划线开头
s = 'hello@'
1.判断变量名的第一个元素是否为字母或下划线: s[0]
2.如果第一个元素符合条件,判断除了第一个元素的其他元素:s[1:]
"""
"""
1.变量名的第一个字符是否为字母或下划线
2.如果是,继续判断(4)
3.如果不是,报错,不合法
4.依次判断除了第一个字符之外的其他字符
5.判断这个字符是否为数字或下划线
"""
python的常用内置方法
"""
In [1]: min(2,4)
Out[1]: 2
In [2]: max(2,4)
Out[2]: 4
In [3]: sum(range(1,101))
Out[3]: 5050
In [4]: sum(range(2,101,2))
Out[4]: 2550
In [5]: sum(range(1,101,2))
Out[5]: 2500
# 枚举:返回索引值和对应的value值
In [8]: for i,v in enumerate('hello'):
...: print(str(i) + '--------->' + v)
...:
0--------->h
1--------->e
2--------->l
3--------->l
4--------->o
In [9]: s1 = 'abc'
In [10]: s2 = '123'
In [11]: for i in zip(s1,s2):
...: print(i)
...:
('a', '1')
('b', '2')
('c', '3')
In [12]: for i in zip(s1,s2):
...: print(''.join(i))
...:
a1
b2
c3
In [13]: for i in zip(s1,s2):
...: print('-'.join(i))
...:
a-1
b-2
c-3
"""
列表的创建
"""
数值类型:int float (long)
布尔型
字符串
列表(list)
"""
# 数组:存储同一种数据类型的集和 scores=[1,2,33,44]
# 列表(打了激素的数组):可以存储任意数据类型的集和
# li = [1,2.2,True,'hello']
# print(li,type(li))
#
#
# # 列表里面是可以嵌套列表的
# li = [1,2,3,False,'python',[1,2,3,4,5]]
# print(li,type(li))
import random
li = list(range(10))
random.shuffle(li)
print(li)
列表的特性
service = ['http','ssh','ftp']
# 索引
# 正向索引
print(service[0])
# 反向索引
print(service[-1])
# 切片
print(service[::-1]) # 列表的反转
print(service[1::]) # 除了第一个之外的其他元素
print(service[:-1]) # 除了最后一个之外的其他元素
# 重复
print(service * 3)
# 连接
service1 = ['mysql','firewalld']
print(service + service1)
# 成员操作符
print('firewalld' in service)
print('ftp' in service)
print('firewalld' not in service)
print('ftp' not in service)
# 列表里面嵌套列表
service2 = [['http',80],['ssh',22],['ftp',21]]
# 索引
print(service2[0][0])
print(service2[-1][1])
列表练习
"""
根据用于指定月份,打印该月份所属的季节。
提示: 3,4,5 春季 6,7,8 夏季 9,10,11 秋季 12, 1, 2 冬季
"""
列表练习
假设有下面这样的列表:
names = ['fentiao','fendai','fensi','fish']
输出的结果为:'I have fentiao,fendai,fensi and fish'
"""
列表元素的增加
service = ['http', 'ssh', 'ftp']
# 1.
# print(service + ['firewalld'])
# append:追加,追加一个元素到列表中
service.append('firewalld')
print(service)
# extend:拉伸,追加多个元素到列表中
service.extend(['hello','python'])
print(service)
# insert:在索引位置插入元素
service.insert(0,'firewalld')
print(service)
列表元素的删除
"""
In [1]: li = [1,2,3,4]
In [2]: li.pop()
Out[2]: 4
In [3]: li.pop(0)
Out[3]: 1
In [4]: li.pop(3)
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-4-e9f9f299015e> in <module>()
----> 1 li.pop(3)
"""
service = ['http', 'ssh', 'ftp']
# remove
# service.remove('ftp')
# print(service)
# service.remove('https')
# print(service)
# claer:清空列表里面的所有元素
# service.clear()
# print(service)
# del(python关键字) 从内存中删除列表
# del service
# print(service)
# print('删除列表第一个索引对应的值:',end='')
# del service[1]
# print(service)
print('删除前两个元素之外的其他元素:',end='')
del service[2:]
print(service)
列表元素的修改
service = ['ftp','http', 'ssh', 'ftp']
# 通过索引,重新赋值
# service[0] = 'mysql'
# print(service)
# 通过slice(切片)
service[:2] = ['mysql','firewalld']
print(service)
列表元素的查看
"""
# service = ['ftp','http', 'ssh', 'ftp','ssh','ssh']
#
# # 查看元素出现的次数
# print(service.count('ftp'))
#
# # 查看制定元素的索引值(也可以指定范围)
# print(service.index('ssh'))
# print(service.index('ssh',4,8))
#
# # 排序查看(按照ascii码进行排序)
# print(service.sort(reverse=True))
# print(service)
#
#
# # 对字符串排序不区分大小写
# phones = ['alice','bob','harry','Borry']
# # phones.sort(key=str.lower)
# phones.sort(key=str.upper)
# print(phones)
列表练习
"""
stack = [1,2,3,4]
栈的工作原理:先进后出
入栈
出栈
栈顶元素
栈的长度
栈是否为空
stack = []
info = """
栈操作
1.入栈
2.出栈
3.栈顶元素
4.栈的长度
5.栈是否为空
"""
while True:
print(info)
choice = input('请输入选择:')
if choice == '1':
item = input('入栈元素:')
stack.append(item)
print('元素%s入栈成功' %(item))
elif choice == '2':
# 先判断栈是否为空
if not stack:
print('栈为空,不能出栈')
else:
item = stack.pop()
print('元素%s出栈成功' %(item))
elif choice == '3':
if len(stack) == 0:
print('栈为空,无栈顶元素')
else:
print('栈顶元素为%s' %(stack[-1]))
elif choice == '4':
print('栈的长度为%s' %(len(stack)))
elif choice == '5':
if len(stack) == 0:
print('栈为空')
else:
print('栈不为空')
elif choice == 'q':
print('欢迎下次使用')
break
else:
print('请输入正确的选择'
列表练习02
队列的工作原理:先进先出
入队
出队
队头
队尾
队列是否为空
显示队列元素
stack = []
info = """
队列管理
1.入队
2.出队
3.队头
4.队尾
5.队列是否为空
6.显示队列长度
exit:退出管理
"""
while True:
print(info)
choice = input('请输入选择:')
if choice == '1':
item = input('入队元素:')
stack.append(item)
print('元素%s入队成功' % item)
elif choice == '2':
if len(stack) == 0:
print('队内无元素,不能出队')
else:
print('%s元素出队成功' % (stack[0]))
stack.pop(0)
elif choice == '3':
if len(stack) == 0:
print('队内无元素,无队头')
else:
print('%s元素为队头' % (stack[0]))
elif choice == '4':
if len(stack) == 0:
print('队内无元素,无队尾')
else:
print('%s元素为队尾' % (stack[-1]))
elif choice == '5':
if len(stack) == 0:
print('队列为空')
else:
print('队列不为空')
elif choice == '6':
print('队列长度为%s' % (len(stack)))
elif choice == 'exit':
print('欢迎下次使用')
break
else:
print('输入选择有错,请重新输入')
用户管理系统练习
"""
1). 系统里面有多个用户, 用户信息目前保存在列表里面;
users = ['root', 'westos']
passwds = ['123', '456']
2). 用户登陆(判断用户登陆是否成功):
1). 判断用户是否存在?(inuser in users)
2). 如果存在:
1). 判断用户密码是否正确?
(先找出用户对应的索引值, 根据passwds[索引值拿出该用户的密码)
如果正确: 登陆成功, 退出循环;
如果密码不正确, 重新登陆, 总共有三次登陆机会
3). 如果不存在:
重新登陆, 总共有三次登陆机会
"""
管理员列表练习
"""
# 1. 后台管理员只有一个用户: admin, 密码: admin
# 2. 当管理员登陆成功后, 可以管理前台会员信息.
# 3. 会员信息管理包含:
# 1.添加会员信息
# 2.删除会员信息
# 3.查看会员信息
# 4.退出
"""
print ('管理员登陆'.center(50, '*'))
inuser = input('UserName:')
inpasswd = input('Password:')
# 现存用户名
users = ['root', 'westos']
# 现存用户密码
passwds = ['123', '456']
if inuser == 'admin' and inpasswd == 'admin':
print( '管理员登陆成功')
print ('用户信息管理'.center(50, '*'))
while True:
print ("""
1 -添加用户信息
2 -删除用户信息
3 -查看用户信息
4 -退出
""")
choice = input('请选择你的操作:')
if choice == '1':
print ('添加用户信息'.center(50, '*'))
addUser = input('添加用户:')
if addUser in users:
print ('用户%s已经存在' % addUser)
else:
addPasswd = input('密码:')
# 把用户名和密码添加到列表中
users.append(addUser)
passwds.append(addPasswd)
print ('添加用户%s成功' %addUser)
elif choice == '2':
print('删除用户信息'.center(50,'*'))
delUser = input('删除的用户:')
delIndex = users.index(delUser)
users.remove(delUser)
passwds.pop(delIndex)
print ('删除用户%s成功' %delUser)
elif choice == '3':
print ('查看用户信息'.center(50,'*'))
print ('\t用户名\t密码')
userCount = len(users) #2
for i in range(userCount): # 0 ,1
print( '\t%s\t%s' %(users[i],passwds[i]))
elif choice == '4':
exit()
else:
print ('请输入正确的选择')
else:
print ('管理员登陆失败!')
元组的创建
"""
列表:打了激素的数组
元组:带了紧箍咒的列表
不可变数据类型,没有增删改查
可以存储任意数据类型
"""
# 定义元组
t = (1,1.2,True,'westos')
print(t,type(t))
# 如果元组里面包含可变数据类型,可以间接修改元组内容
t1 = ([1,2,3],4)
t1[0].append(4)
print(t1)
t2 = ()
print(t2)
t3 = tuple([])
print(t3)
l4 = list(())
print(l4)
# 元组如果只有一个元素,后面一定要加逗号,否则数据类型不确定
t4 = (1,)
print(t4,type(t4))
元组的特性
tuple = (1,1.0,True,'westos')
# 索引
print(tuple[0])
print(tuple[-1])
# 切片
print(tuple[1:])
print(tuple[:-1])
print(tuple[::-1])
# 连接
# 不同的数据类型可以连接麼(除了数值类型之外,不同的数据类型之间不可以连接)
print(tuple + (1,2,3))
# print(tuple + [4,5,6])
# print(tuple + 'westos')
# 重复
print(tuple * 5)
# for循环
for i in tuple:
print(i)
#成员操作符
print(1 in tuple)
print(i not in tuple)
元组的常用方法
t = (1,2,'a','c','a')
# 查看元素的索引值
print(t.index('c'))
# 查看元素在元组中出现的次数
print(t.count('a'))
元组的应用场景
# # 1.变量交换数值
# a = 1
# b = 2
# b,a = a,b
# """
# 1.先把(a,b)封装成了一个元组 (1,2)
# 2. b,a = a,b ===> b,a = (1,2)
# 3. b = (1,2)[0] a =(1,2)[1]
# """
# print(a,b)
#
#
# # 打印变量值
# name = 'westos'
# age = 11
# t = (name,age)
# print('name:%s,age:%d' %(name,age))
# print('name:%s,age:%d' %t)
#
#
# # 元组的赋值:有多少个元素,就用多少个变量接收
# t = ('Westos',10,100)
# name,age,score = t
# print(name,age,score)
#
#
# scores = (100,89,45,78,65)
# # # 先对元组进行转换
# # scoreli = list(scores)
# # scoreli.sort()
# # print(scoreli)
# scores_sort = sorted(scores)
# print(scores_sort)
# 比赛计分器
scores = (100,89,98,60,90,67)
#scores.sort()
scores = sorted(scores)
# python2中*middle不能使用的
min_score,*middle,max_score = scores
print(min_score,'~~~~',*middle, '~~~~~~',max_score)
print('最终成绩为:%s' %(sum(middle)/4))
"""
当一个变量=xxx的时候,约定为: 指向地址的过程
浅拷贝:copy.copy()
深拷贝:copy.deepcopy()
"""
"""
In [38]: import copy
In [39]: a = [11,22]
In [40]: b = [33,44]
In [41]: c = [a,b]
In [42]: c
Out[42]: [[11, 22], [33, 44]]
In [43]: d = copy.copy(c)
In [44]: id(c)
Out[44]: 140233732341960
In [45]: id(d)
Out[45]: 140233713050888
In [46]: id(c[0])
Out[46]: 140233732292488
In [47]: id(d[0])
Out[47]: 140233732292488
In [48]: id(a)
Out[48]: 140233732292488
In [49]: e = copy.deepcopy(c)
In [50]: id(e)
Out[50]: 140233732321800
In [51]: id(c)
Out[51]: 140233732341960
In [52]: id(c[1])
Out[52]: 140233731307720
In [53]: id(e[1])
Out[53]: 140233713173832
In [54]: id(d[1])
Out[54]: 140233731307720
"""
"""
In [55]: a = [11,22]
In [56]: b = [33,44]
In [57]: c = [a,b]
In [58]: d = copy.copy(c)
In [59]: e = copy.deepcopy(c)
In [60]: id(c)
Out[60]: 140233732324104
In [61]: id(d)
Out[61]: 140233740633608
In [62]: id(e)
Out[62]: 140233732090888
In [63]: c.append([55,66])
In [64]: c
Out[64]: [[11, 22], [33, 44], [55, 66]]
In [65]: d
Out[65]: [[11, 22], [33, 44]]
In [66]: e
Out[66]: [[11, 22], [33, 44]]
"""
"""
如果copy.copy()拷贝的是元组,那么它不会进行浅拷贝,仅仅是指向
因为元组是不可变数据类型,那么意味着数据一定不能修改,因此用copy.copy的
时候它会自动判断,是指向
如果,用copy.copy() copy.deepcopy()对一个全部是不可变类型的数据进行
数据拷贝,那么它们的结果相同,都是引用
如果拷贝的是一个拥有可变类型的数据,那么deepcopy依然是深拷贝,而copy.copy
还是指向
In [73]: a = [11,22]
In [74]: b = [33,44]
In [75]: c = (a,b)
In [76]: c
Out[76]: ([11, 22], [33, 44])
In [77]: d = copy.copy(c)
In [78]: id(c)
Out[78]: 140233732322440
In [79]: id(d)
Out[79]: 140233732322440
In [80]: e = copy.deepcopy(c)
In [81]: id(e)
Out[81]: 140233713145672
In [82]: id(c)
Out[82]: 140233732322440
In [83]: id(c[1])
Out[83]: 140233713122504
In [84]: id(e[1])
Out[84]: 140233731173640
In [85]: id(d[1])
Out[85]: 140233713122504
In [86]: a.append(55)
In [87]: c
Out[87]: ([11, 22, 55], [33, 44])
In [88]: e
Out[88]: ([11, 22], [33, 44])
"""
集和的定义
# 集和里面的元素是不可重复的
s = {1,2,3,4,5,6,6,3,3,2}
print(s,type(s))
s1 = {1}
print(s1,type(s1))
# 如何定义一个空集和
s2 = {} #默认情况是dict,称为字典
print(s2,type(s2))
# 定义一个空集和
s3 = set([])
print(s3,type(s3))
# 集和应用1:列表去重
li = [1,2,3,4,1,2,3]
print(list(set(li)))
集和的特性
"""
集和支持的特性只有 成员操作符(索引 切片 重复 连接 均不支持)
"""
s = {1,2,3}
print(1 in {1,2,3})
print(1 not in s)
# for循环
for i in s:
print(i,end=' ')
print()
print('~~~~~~')
# for + index
for i,v in enumerate(s):
print('index: %s,value:%s' %(i,v))
集和的常用方法
"""
# # 可变数据类型
# # 添加顺序,和在集合中存储的顺序不同
# s = {6,7,3,1,2,3}
# # 增加
# s.add(8)
# s.add(4)
# print(s)
#
# # 增加多个元素
# s.update({9,10,11})
# print(s)
#
# # 删除
# s.pop()
# s.pop()
# print(s)
#
# # 删除指定元素(元素要存在)
# s.remove(3)
# print(s)
# 交集 并集 差集
s1 = {1, 2, 3}
s2 = {2, 3, 4}
# 并集
print('并集:', s1.union(s2))
print('并集:', s1 | s2)
# 交集
print('交集:',s1.intersection(s2))
print('交集:',s1 & s2)
# 差集
# 可以理解为s1中有哪些s2中没有的元素
print('差集:',s1.difference(s2)) # s1 - (s1&s2)
# 可以理解为s2中有哪些s1中没有的元素
print('差集:',s2.difference(s1)) # s2 - (s1&s2)
print('差集:',s1-s2)
print('差集:',s2-s1)
# 对等差分:并集 - 交集
print('对等差分:',s1.symmetric_difference(s2))
print('对等差分:',s1^s2)
s3 = {1,2}
s4 = {1,2,3}
# s3是否为s4的子集
print(s3.issubset(s4))
# s3是否为s4的超集
# 什么是超集?
print(s3.issuperset(s4))
# 两个集和是不是不相交
print(s3.isdisjoint(s4))
"""
华为机测题:
明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性
他先用计算机生成了N个1~1000之间的随机整数(N<=1000),N是用户输入的,对于
其中重复的数字,只保留一个,把其余相同的数字去掉,不同的数对应着不同的学生的学号,然后再把这些
数从小到大排序,按照排好的顺序去找同学做调查,请你协助明明完成“去重”与排序工作
"""
字典的创建
d = {}
print(type(d))
# 字典:key-value 键值对存储的一种数据结构
# value值可以是任意数据类型:int float long list tuple set dict
d = {
'a':[18,'男','玩手机'],
'b':[18,'男','修手机']
}
print(d)
print(d['b'])
d2 = {
'a':1,
'b':2
}
print(d2)
d3 = {
'a':{1,2,3},
'b':{2,3,4}
}
print(d3)
# 字典的嵌套
students = {
'06163012':{
'name':'a',
'age':18,
'score':90
},
'03162003':{
'name':'b',
'age':19,
'score':80
}
}
print(students['03162003']['name'])
# 工厂函数
d5 = dict(a=1,b=2)
print(d5)
字典的特性
d = {
'1':'a',
'8':'b',
'2':'a'
}
print(d['1'])
# 字典不支持索引
# print(d[0])
# 字典不支持切片
# print(d[::-1])
# 字典的重复和连接是无意义的,字典的key是唯一的
# 成员操作符:判断的是 某个值是否为字典的key
print('1' in d)
print('1' not in d)
# 字典的for 循环 默认遍历字典的key值
for key in d:
print(key)
# 遍历字典
for key in d:
print(key,d[key])
字典的增加
services = {
'http': 80,
'ftp': 21,
'ssh': 22
}
"""
1.增加一个元素
1).如果key值存在,则更新对应的value值
2).如果key值不存在,则添加对应的key-value值
"""
# services['mysql'] = 3306
# print(services)
# services['http'] = 443
# print(services)
"""
2.添加多个key-value值
1).如果key值存在,则更新对应的value值
2).如果key值不存在,则添加对应的key-value值
"""
# service_backup = {
# 'tomcat':8080,
# 'https':443,
# 'http':8888
# }
#
# services.update(service_backup)
# print(services)
# services.update(flask=9000,http=999)
# print(services)
"""
3.setdefault添加key值:
1).如果key值存在,则不做修改
2).如果key值不存在,则添加对应的key-value值
"""
services.setdefault('http',9000)
print(services)
services.setdefault('oracle',44575)
print(services)
字典的删除
"""
services = {
'http': 80,
'ftp': 21,
'ssh': 22,
'mysql':3306
}
# 1.del关键字
# del services['http']
# print(services)
"""
2.pop删除指定的key的key-value值
1.)如果key存在,删除,并且返回删除key对应的value值
2.)如果key不存在,直接报错
"""
# item = services.pop('http')
# print(item)
# print(services)
"""
3.popitem删除最后一个key-value
"""
# item = services.popitem()
# print('删除的key-value对应的是:',item)
# print(services)
"""
4.清空字典内容
"""
services.clear()
print(services)
字典的修改与查看
service = {
'http':80,
'mysql':3306
}
# 查看字典里面的key值
print(service.keys())
# 查看字典里面的所有value值
print(service.values())
# 遍历字典
for k,v in service.items():
print(k,'---->',v)
for k in service:
print(k,'---->',service[k])
# 查看指定key对应的value值
# key值不存在,程序会报错
print(service['http'])
# print(service['https'])
"""
get 方法获取指定key对应的value值
如果key值存在,返回对应的value值
如果key值不存在,默认返回None,如果需要指定返回的值,传值即可
"""
print(service.get('https'))
字典的练习
"""
重复的单词: 此处认为单词之间以空格为分隔符, 并且不包含,和.;
1. 用户输入一句英文句子;
2. 打印出每个单词及其重复的次数;
"""
字典练习02
"""
# 数字重复统计:
1). 随机生成1000个整数;
2). 数字的范围[20, 100],
3). 升序输出所有不同的数字及其每个数字重复的次数;
"""
import random
all_num = []
for i in range(1000):
all_num.append(random.randint(20,100))
sorted_num = sorted(all_num)
num_dict={}
for num in sorted_num:
if num in num_dict:
num_dict[num] += 1
else:
num_dict[num] = 1
for k,v in num_dict.items():
print(k,'----->',v)
字典的练习03
"""
# 1. 随机生成100个卡号;
# 卡号以6102009开头, 后面3位依次是 (001, 002, 003, 100),
# 2. 生成关于银行卡号的字典, 默认每个卡号的初始密码为"redhat";
# 3. 输出卡号和密码信息, 格式如下:
卡号 密码
6102009001 000000
"""
"""
fromkeys第一个参数可以是 list/tuple/str/set
将第一个参数的元素作为字典的key值
并且所有key的value值一致,都为'00000000'
"""
# print({}.fromkeys({'1','2'},'0000000'))
#存储所有卡号列表,也可以通过集合来存储
card_ids = []
# 生成100个卡号
for i in range(100):
# %.3d代表这个整型数占3位 eg:1--->001
s = '6102009%.3d' %(i+1)
# 将每次生成的卡号都加入到列表中
card_ids.append(s)
card_ids_dict = {}.fromkeys(card_ids,'redhat')
# print(card_ids_dict)
print('卡号\t\t\t\t\t密码')
for key in card_ids_dict:
print('%s\t\t\t%s' %(key,card_ids_dict[key]))
is 和==的区别
"""
id:在内存中存储的位置
type:变量的类型
value:变量的值
== :type,value
is:type,value,id
结论:
is 表示两个变量的值是否在同一块内存空间
== 表示的是值是否相等
总结: is 返回的值是True ==返回的一定是true
In [1]: a = '1'
In [2]: b = 1
In [3]: a == b
Out[3]: False
In [4]: a = '1'
In [5]: b = a
In [6]: a is b
Out[6]: True
In [7]: li = [1,2,3]
In [8]: li1 = li
In [9]: li == li1
Out[9]: True
In [10]: li2 = li.copy()
In [11]: id(li)
Out[11]: 140233732343752
In [12]: id(li1)
Out[12]: 140233732343752
In [15]: id(li2)
Out[15]: 140233732186888
In [16]: id(li1)
Out[16]: 140233732343752
In [17]: id(li)
Out[17]: 140233732343752
In [18]: li2
Out[18]: [1, 2, 3]
In [19]: li
Out[19]: [1, 2, 3]
In [20]: li1
Out[20]: [1, 2, 3]
In [21]: li == li1
Out[21]: True
In [22]: li == li2
Out[22]: True
In [23]: li1 == li2
Out[23]: True
In [24]: li2 is li
Out[24]: False
In [25]: li2 is li1
Out[25]: False
In [26]: li1 is li
Out[26]: True
"""