数据类型及其内置方法、类型转换
目录
基本数据类型
1.如何理解数据类型
例如:日常生活中表示姓名用文本、表示年龄用数字、表示体重用小数,在代码程序中也需要有不同的数据类型来表示不同的数据状态
2.如何查看数据的数据类型
type() 这个方法可以用来查看数据的数据类型
name = 'liyifeng'
print(type(name)) (结果:<class 'str'>)
数据类型的概述
1.数据类型之整形--int
本质:整形其实就是整数
使用规范:
age = 10
主要使用场所:
年龄、年份、人数等
内置方法:
没有,整型就是整数,主要就是用来计算的,所以没什么内置方法
类型转换:
print(type(int('12345678'))) # 字符串内部是纯数字情况可以转换
print(type(int('1nuuuuuh46781'))) # 字符串里面必须是纯数字才可以转换
print(type(int('67567.33'))) # 小数点也算一个字符,所以也不可以
进制的转换:
十进制转换其他进制
bin() 是将十进制转二进制 0b是二进制数的标识
print(bin(100)) # 0b1100100
oct() 是将十进制转八进制 0o是八进制数的标识
print(oct(100)) # 0o144
hex() 是将十进制转十六进制 0x是十六进制数的标识
print(hex(100)) # 0x64
ps:如果数字前面没有任何标识,默认就是十进制
其他进制转换十进制
通过各进制特有的标识,我们就可以是哪个进制转换的十进制,同样我们也可以人为的指定进制数
print(int(0b1100100)) # 100
print(int(0o144)) # 100
print(int(0x64)) # 100
print(int('0b1100100', 2)) # 100
print(int('0o144', 8)) # 100
print(int('0x64', 16)) # 100
2.数据类型之浮点型--float
本质:
浮点型其实就是小数
使用规范:
salary = 10989.23
weight = 88
主要使用场所:
体重、工资、克数等
内置方法:没有,主要用于参与数学运算
类型转换:
争对浮点型的类型转换,它比整型稍微好一点,可以识别一个小数点,但仅限识别一个
print(float('123')) # 123.0
print(type(float('123'))) # float
print(float('123a123'))
print(float('123.12')) # 可以识别一个小数点
print(float('123.123.1.2.2.2.2.2.2')) # 不可以
特殊情况:主要针对的是布尔值,False就是0.0,True就是1.0
补充说明:
python对数字不敏感,很容易出错,算着算着可能就会失真,但是它还是可以做许多事情,厉害的不是它本身,是它的一些模块,可以通过模块来修改它的缺点
3.数据类型之字符型,也称字符串类型--str
本质:用来描述一些事情,也就是文本信息
使用规范:
name = "zhangran"
address = '金华市婺城区西关街道'
hobby = ''' 看悬疑剧'''
nick_name = """wlAJD"""
为什么定义字符串需要有这么多方式?
原因:在我们定义字符串的内部可能也需要使用到引号,这时候引号部分可能提前结束,容易冲突报错。为了避免字符串冲突了报错,所以我们给出了多种方式。例如:"老师说:"周日你们可以把这周学的进行一个总结"",这个情况下就会出现报错,周日你们可以把这周学的进行一个总结,这部分内容就不会在引号的范围内。
为什么前面三引号是注释的语法,这里又是字符串的语法?
原因:如果三引号左边没有变量名与赋值符号它就是注释,那如果三引号的左边有变量名和赋值符号,那它就是字符串类型。
合理使用引号,明确定义字符串的符号与内部文字的符号不冲突。
类型转换:
任何数据类型都可以转为字符串型,他只是在最外层加了’‘,它兼容了所有的数据类型
print(str(12), type(str(12))) # 12 <class 'str'>
print(str(123.11), type(str(123.11))) # 123.11 <class 'str'>
print(str([1, 2, 3, 4]), type(str([1, 2, 3, 4]))) # [1, 2, 3, 4] <class 'str'>
print(str({'name': 'jason'}), type(str({'name': 'jason'}))) # {'name': 'jason'} <class 'str'>
print(str(True), type(str(True))) # True <class 'str'>
print(str((1, 2, 3, 4)), type(str((1, 2, 3, 4)))) # (1, 2, 3, 4) <class 'str'>
print(str({1, 2, 3, 4}), type(str({1, 2, 3, 4}))) # {1, 2, 3, 4} <class 'str'>
内置方法:
[1.索引取值]
单个字符,支持负数,想取哪个就取哪个
str = 'hello world'
print(str[0]) # h
# 支持负数的取法
print(str[-1])
[2.切片取值]
多个字符,其中的数字代表着的是索引,采用的也是'顾头不顾尾'的概念,切片的顺序是默认从左向右的,在负向切片的时候需要注意
str = 'hello world'
print(str[0:4]) # hell
print(str[-1:-4]) # 取不到值
print(str[-4:-1]) # orl
print(str[-1:-4:-1]) # dlr 可以通过第三个参数的正负一 控制方向
[3.间隔与方向]
str = 'hello world'
print(str[:]) # 什么都不写,默认取到所有的
print(str[::2]) # 表示间隔一个取一个 hlowrd
print(str[::3]) # 表示间隔俩个取一个 hlwl
[4.统计字符串中字符的个数]
需要注意的是在字符串中空格也算一个字符,在统计字符串的个数的时候也会把它算在内
print(len(str)) # 11
[5.移除字符串首尾指导的字符]
.strip()默认移除的是首尾的空格符号,经常会用在我们登录的时候的操作
.strip('$')可以用来移除指定的值
.lstrip('$')移除左边的指定的值
.rstrip('$')移除右边的指定的值
name = ' zhang '
print(len(name)) # 开始name的字符串长度为 9
print(name.strip(), len(name.strip())) # 通过移除后 长度只剩 5
res = name.strip()
这里需要注意的是它不会改变原来的值,只是重新创建了一个新的数据,如果想要永久的保存这个新的值可以给这个值也绑定一个名字
[6.按照指定的字符切割字符串]
当字符串中出现连续的特征符号,就可以考虑使用字符切割,切割字符串以后结果出现的是一个列表
.split('|', maxsplit=1)) 里面的maxsplit表示从左往右 只切一次 ['zhang', '123|run']
.rsplit('|', maxsplit=1)) 表示从右往右 只切一次 ['zhang|123', 'run']
info = 'zhan|123|run'
res = info.split('|') # 切割字符串之后结果是一个列表
print(res, type(res)) # ['zhang', '123', 'run'] <class 'list'>
[7.字符串大小写相关]
.lower() 将字符串里的大写全部转换为小写
.upper() 将字符串里的小写全部转换为大写
注意:只是字母之间转换,数字、符号、空格等不能参与转换
.islower() 判断字符串中所有的字母是否是全小写
.isupper() # 判断字符串中所有的字母是否是全大写
[8.字符串的格式化输出]
方式一:等价于%S占位,前把文本编辑好,需要占位的地方输入{}来展位,可以设置多个占位,然后通过 变量名.format('数据值','数据值'......)
res1 = 'my name is {} my age is {}'
print(res1.format('zhangran', 18))
方式二:利用索引值,先用{}进行占位,里面输入索引,然后在使用的时候按照索引顺序输入值,,可以多次使用
res2 = 'my name is {0} my age is {1} {0} my friends always called me {2}'
print(res2.format('zhangran', 18, 'zhangxiaoran'))
方式三:支持关键字取值(按k取值),也支持重复使用在{}输入k值,然后在使用的时候输入k值的数据值就可以了
res3 = '{name} {name} {age} my name is {name} my age is {age}'
print(res3.format(name='jason', age=18))
方式四:使用变量名,先将数据值绑定给变量,然后在使用的时候直接在{}里输入变量名就可是使用,同样也可以重复多次使用,最推荐使用的方法
name = 'zhangran'
age = 18
print(f'my name is {name} my age is {age} {name} {age}')
[9.统计字符串中指定字符出现的次数]
.count(),底层实现的操作就是使用的是for循环,它内部自己用来比较是否与你输入的一直,然后自己再给累加,得出结果
str = 'jjsokjflpkfpzfifmcuioijjjALJAGAGAGFETEYEUEJDHDGDGSBSBS'
print(str.count('j')) # 6
print(str.count('GA')) # 2
[10.判断字符串的开头或者结尾]
可以查找的是单个字符,也可以是多个字符,返回的结果是布尔值
.startswith 表示的是开头的字符
.endswith 表示的是结尾的字符
res = 'jason say ha ha ha heiheihei'
print(res.startswith('jason'))
print(res.startswith('j'))
print(res.startswith('b'))
print(res.endswith('heiheihei'))
print(res.endswith('hei'))
print(res.endswith('h'))
[11.字符串的替换]
变量名.replace('old_str','new_str' ,1),从左到右依次替换,可指定替换的个数
[12.字符串的拼接]
.join([]),前面一个字符串,后面跟.join(),join()里面写一个列表、元组,进行字符串拼接,但是列表中的数据必须都是字符串类型
res1 = 'hello'
res2 = 'world'
print(''.join(['hello', 'world', 'hahaha'])) # join方法拼接
print('|'.join(['hello', 'world', 'hahaha'])) # join方法拼接
print('$'.join(['jason', 'say', 666])) # 列表中的数据都必须是字符串类型 报错!!!
字符串支持加号拼接
res1 = 'hello'
res2 = 'world'
print(res1 + res2)
字符串支持乘号重复
res1 = 'hello'
res2 = 'world'
print(res1 * 10)
[13.判断字符串中是否是纯数字]
isdigit(),返回的是布尔值,判断字符串是不是纯数字,可以使用在登录的情况,可以防止网站崩溃
print('123'.isdigit()) # True
print('123a'.isdigit()) # False
print(''.isdigit()) # False
[14.查找某个字符对应的索引值]
.index 可以用来查找字符的索引
.find 也可以用来查找字符的索引
.index与.find都可以用来查找索引 ,但是在一定范围内查找是否存在字符,前者如果没有则报错,后者没有返回的是-1,-1表示的是没有,报错,没有办法执行
print(res.index('d',0,5)) # 会报错
print(res.find('d',0,5)) # -1
[15.正文相关操作]
.title(),首字母大写
.capitalize(),只有第一个字母大写
res = 'my name is zhangran'
print(res.title()) # My Name Is Zhangran
print(res.capitalize()) # My name is zhangran
4.数据类型之列表--list
本质:
可以存储许多数据,不限制类型,方便存取
基本使用:
a = [1,2,3,4,5,6,7]
左边取一个变量名,然后用赋值符号连接,右边用中括号,中括号里面放入存储的数据,数据之间用逗号隔开
内置方法:
[1.索引取值]
列表通过索引取值,可以任意取到数据中的任意一个数据值
l1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(l1[4]) # 5
[2.切片取值]
列表通过切片取值,可以取到单个、多个数据值,正反向都可以取值
默认从0开始,可以自己设置起始位置和终止位置
l1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(l1[:2]) # [1, 2]
print(l1[-2:-4:-1]) # [8, 7]
[3.间隔与方向]
列表通过间隔/方向取值,第三个数值用来判断方向和间隔数
l1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(l1[-2:-7:-2]) # [8, 6, 4]
[4.统计列表中的数据值个数]
l1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(len(l1)) # 9
[5.列表的增删改查]
1.列表中增加数据
尾部追加数据值.append()列表在调用内置方法时不会产生新的数据,而是修改的自身的数据,括号内无论写什么数据类型,它只是按照一个数据值插入,在尾部添加数据。
l1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
l1.append('新增数据')
res = l1.append([1, 1, 1])
print(l1) # [1, 2, 3, 4, 5, 6, 7, 8, 9, '新增数据', [1, 1, 1]]
print(res) # None
列表中任意位置添加数据.insert(索引值),通过索引来定位想在哪个位置添加数据,括号内无论写什么数据类型,它只是按照一个数据值插入
l1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
l1.insert(3, 'ddd')
l1.insert(4,[1,2,3])
print(l1) # [1, 2, 3, 'ddd', [1, 2, 3], 4, 5, 6, 7, 8, 9]
扩展列表.extend,底层的结构式通过for+.append循环,主要是用来扩展列表的,只适用于支持for循环的,如果是数字就会报错
l1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
l2 = ['aa', 'bb', 'cc']
l1.extend(l2)
l1.extend(123) # 报错
l1.extend({'name':'a','age':18})
print(l1) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 'aa', 'bb', 'cc', 'name', 'age']
2.修改
变量名[索引] = 数据值,表示的是将索引对应的值不再绑向原来的值,绑向新的数据值
列表在管理数据的时候,在内存中申请一块空间,然后存放一个列表,与几个数据就会有几层,每层都有一个索引内存地址,然后指向数据值,当我们将某个索引地址重新指向新的值的时候,就会舍弃原来的值,就会改变为新的值
l1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
l1[2] = 'aa'
print(l1) # [1, 2, 'aa', 4, 5, 6, 7, 8, 9]
3.删除
通用删除策略: del l1[0]
l1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
del l1[3]
print(l1) # [1, 2, 3, 5, 6, 7, 8, 9]
指名道姓的删除,在括号里明确写出要删除的值
l2 = ['name', 123, 'jsaon', 'karry']
l2.remove('name')
print(l2) # [123, 'jsaon', 'karry']
先取出,然后在删除,可以先取出来进行其他操作,默认取出的是列表最后一位数据,可以自己写入索引
l3 = ['name', 123, 'jsaon', 'karry']
l3.pop(2)
res = l3.pop(2)
print(res)
print(l3)
[6.查看数据对应的索引值]
列表中查看数据对应的索引值,利用 变量名.index(数据值) 即可查到该数据值的索引
l3 = ['name', 123, 'jason', 'karry']
print(l3.index('jason')) # 2
[7.统计数据值的个数]
变量名:.count('数据值')
[8.排序的方法]
变量名.sort(),列表中排数的方法默认为升序,降序为sort(reverse=True)
l = [1, 4, 6, 8, 3, 9, 6, 2, 5]
l.sort()
l.sort(reverse=True)
print(l) # [1, 2, 3, 4, 5, 6, 6, 8, 9]
print(l) # [9, 8, 6, 6, 5, 4, 3, 2, 1]
[9.翻转的使用]
变量名.reverse()
l = ['aaa', 'bbb', 'ccc', 'ddd', 'eee']
l.reverse()
print(l) # ['eee', 'ddd', 'ccc', 'bbb', 'aaa']
[10.比较运算]
列表中数字的比较大小是跟字符串一样的,按照第一位来进行比较
列表中不同数据之间是不能进行比较
字符的比较是通过它们自身的编码来进行比较的
5.数据类型之字典--dict
本质:
与列表一样也可以存放许多数据,但跟列表不一样的是它更直观,存储的数据可以直观的看到所表示的是什么
基本使用:
b = {'username': 'mengmeng', 'age': 18, 'hobby': 'running'}
语言描述:
变量名后跟赋值符号,数据用花括号来保存,数据与数据用逗号隔开,他的数据书写格式是‘kv’键值对
'k' 指的是对V的描述性性质的信息 一般是字符串
'v' 指的是真实的数据值 可以是任意数据类型
内置方法:
[1.取值方法]
取值操作:字典是无序的,因此它不通过索引取值,它是通过K:V键值对存放的
.get() 方法,如果存在这个K值就就找到对应的V值,如果不存在的话,返回的是None而事实上它可以写入俩个参数,可以不写,不写返回的是None,如果写入的话,对应的没有输入的K值就会返回所输入的第二个值
d = {'name': 'zr', 'age': 18, 'hobby': 'xxx'}
print(d.get('name')) # zr
print(d.get('collage', '金职院')) # 金职院
[2.统计键值对的方法]
d = {'name': 'zr', 'age': 18, 'hobby': 'xxx'}
print(len(d)) # 3
[3.修改数据的方法]
变量名[k值] = ‘修改数据值’
当字典中有查找的K值时,就更改对应的V值
当字典中没有查找的K值时,就会新增一对键值对
d = {'name': 'zr', 'age': 18, 'hobby': 'xxx'}
d['name'] = 'zxr'
d['nickname'] = 'ddd'
print(d) # {'name': 'zxr', 'age': 18, 'hobby': 'xxx'}
print(d) # {'name': 'zxr', 'age': 18, 'hobby': 'xxx', 'nickname': 'ddd'}
变量名[k值] = ‘数据值’
当字典中没有查找的K值时,就会新增一对键值对
d = {'name': 'zr', 'age': 18, 'hobby': 'xxx'}
d['name'] = 'zxr'
d['nickname'] = 'ddd'
print(d) # {'name': 'zxr', 'age': 18, 'hobby': 'xxx', 'nickname': 'ddd'}
.update() K键存在则是修改,K键不存在则是新增,用法与上面的一致
d = {'name': 'zr', 'age': 18, 'hobby': 'xxx'}
d.update({'name':'zxrhh'})
print(d) # {'name': 'zxrhh', 'age': 18, 'hobby': 'xxx'}
d.update({'collage':'xxx'})
print(d) # {'name': 'zxrhh', 'age': 18, 'hobby': 'xxx', 'collage': 'xxx'}
[4.删除数据的方法]
d = {'name': 'zr', 'age': 18, 'hobby': 'xxx'}
方式1:通用的删除方式,以键值对为单位删除
del d['name']
print(d) # {'age': 18, 'hobby': 'xxx'}
方式2:pop会有一个返回值,这个返回值是我们要删除的K值对应的数据值,可以拿来使用
res = d.pop('name')
print(d, res) # {'age': 18, 'hobby': 'xxx'} zr
方式3:随机删除
.popitem()
print(d) # {'name': 'zr', 'age': 18}
[5. 获取键值对的K值或V值]
字典中 .keys()方法获取到的是所有的k值
values()方法获取到的是所有的v值
items()方法获取到的是字典的信息
d = {'name': 'zr', 'age': 18, 'hobby': 'xxx'}
print(d.keys()) # dict_keys(['name', 'age', 'hobby'])
print(d.values()) # dict_values(['zr', 18, 'xxx'])
print(d.items()) # dict_items([('name', 'zr'), ('age', 18), ('hobby', 'xxx')])
[6. 快速构建字典的方法]
.fromkeys()给的值默认情况下所有的键都用一个
通过这个方法快速的生成的字典的时候,如果第二个参数是可变类型的时候,当第二个是列表的时候,前面的三个参数指向的不是对应的值,而是整个列表
{'name': ['zz', 18, 123], 'age': ['zz', 18, 123], 'hobby': ['zz', 18, 123]}
可以是前面的三个键,重新指向新的值,然后在进行加值
d = dict.fromkeys([1, 2, 3], None)
print(d)
new_dict = dict.fromkeys(['name', 'age', 'hobby'], []) # {'name': [], 'age': [], 'hobby': []}
# new_dict['name'].append('zz')
# new_dict['age'].append(18)
# new_dict['hobby'].append(123)
# {'name': ['zz', 18, 123], 'age': ['zz', 18, 123], 'hobby': ['zz', 18, 123]}
new_dict['name'] = []
new_dict['name'].append('zz')
new_dict['age'] = []
new_dict['age'].append(18)
new_dict['hobby'] = []
new_dict['hobby'].append(123)
print(new_dict) # {'name': ['zz'], 'age': [18], 'hobby': [123]}
6.数据类型之元组--tuple
本质:
可以存储许多数据,不限制类型,方便存也方便取,写法与列表一样,他们俩的区别在于列表可以修改数据而元组不可以修改
基本使用:
a = (1,2,3,4,5,6,7)
当元组内只有一个数据值时,我们也应该形成习惯后面加一个逗号,如果不加的话,那么括号里的是什么类型就是什么类型,t4 = ('name', )
语言描述:
左边取一个变量名,然后用赋值符号连接,右边用小括号,小括号里面放入存储的数据,数据之间用逗号隔开
类型转换:
支持for循环的类型都可以进行转换
print(tuple([1, 2, 3, 4, 5])) # (1, 2, 3, 4, 5)
print(tuple({'n': 'c', 'd': 'v'})) # ('n', 'd')
print(tuple({1, 2, 3, 4, 5})) # (1, 2, 3, 4, 5)
内置方法:
[1.索引取值]
t1 = (0, 2, 3, 4, 5, 6, 7)
print(t1[3]) # 4
[2.切片取值]
t2 = (0, 2, 3, 4, 5, 6, 7)
print(t2[:3]) # (0, 2, 3)
[3.间隔与方向]
t3 = (0, 2, 3, 4, 5, 6, 7)
print(t3[-1:-4:-2]) # (7, 5)
[4.统计数据值的个数]
t2 = (11, 22, 11, 22, 22, 33, [11, 22])
print(t2.count(22)) # 3
[5.查找数据值的索引]
t2 = (11, 22, 11, 22, 22, 33, [11, 22])
print(t2.index(22)) # 1
[6.增删改查]
元组里面查找时可以进行的
元组里面不支持进行修改,即不能进行增加数据,元组对应的底层结构上是元组绑定给一个变量(绑向变量的内存地址不能进行修改),元组里面的索引也不可以进行修改,包括元组里面索引指向的值也是不可以进行修改的
t1 = (0, 2, 3, 4, 5, 6, 7)
print(t1) # (0, 2, 3, 4, 5, 6, 7)
虽然元组的索引不能改变绑定的地址,但是元组里的索引绑定的列表是可以进行改变的,因为它没有改变元组的索引的内存地址
t2 = (11, 22, 33, [11, 22])
t2[-1].append(33)
print(t2) # (11, 22, 33, [11, 22, 33])
7.数据类型之布尔值--bool
本质:
用来表示事物的正确与否,是不是,可不可以
布尔类型其实在我们现实生活中处处可见,例如我们在打开支付宝的时候就会用到,是否处于登录状态
存储布尔值的名字一般使用is开头
布尔值为False的数据有:0 None 空字符串 空列表 空字典 ...,除此之外所有的数据对于的布尔值都是True
基本使用:
is_right = True
is_delete = False
8.数据之集合--set
本质:
它只有俩字方式去重和关系运算,平时生活中用的也就是在这俩俩种情况下
去重:去掉重复的数据
关系运算:判断俩个数据之间的关系,例如:共同点赞、共同好友
基本使用:
c = {1, 2, 3, 4, 5}
它与字典定义空集合的区别:
a = {}
b = {}
print(type(d1)) # <class 'dict'>
print(type(s1)) # <class 'dict'>
c = set() # 必须使用关键字才能定义空集合
print(type(c)) # <class 'set'>
内置方法:
1.在定义空字符的时候需要注意使用关键字,否则是一个空字典,set()
2.集合内的数据有要求,必须是不可变类型(整型 浮点型 字符串 元组 布尔值)
3.它是一个冷门知识点,通常只用在俩个方面,去重和关系运算
4.去重,一般用于数据中有好多重复的数据,假使要一份名单,那就不需要那些重复的数据,数据量小的时候,可以直接看出来,但是数据量大的时候,就需要用这个方法
5,关系运算,一般用于共同点赞,共同好友等
s1 = {1, 2, 4, 5, 4, 5, 4, 5, 4, 5, 4}
print(s1) # {1, 2, 4, 5}
l1 = ['aa', 'bb', 'cc', 'aa', 'cc', 'bb', 'aa']
# 去掉重复的
s2 = set(l1)
print(s2) # {'bb', 'aa', 'cc'} 返回的是一个集合
l1 = list(s2)
print(l1) # ['bb', 'cc', 'aa']
f1 = {'aa', 'tt', 'bb', 'cc'}
f2 = {'aa', 'ff', 'bb', 'zz', 'll'}
# 1.求f1和f2的共同好友
print(f1 & f2) # {'bb', 'aa'}
# 2.求f1/f2独有好友
print(f1 - f2) # {'tt', 'cc'}
print(f2 - f1) # {'ff', 'zz', 'll'}
# 3.求f1和f2所有的好友
print(f1 | f2) # {'ll', 'tt', 'aa', 'zz', 'ff', 'cc', 'bb'}
# 4.求f1和f2各自独有的好友(排除共同好友)
print(f1 ^ f2) # {'tt', 'zz', 'll', 'ff', 'cc'}
# 5.父与子集
s1 = {1, 9, 3, 8, 5, 6, 7}
s2 = {2, 1, 4}
s3 = {1, 3, 5}
# s1是否是s2的父集 s2是不是s1的子集 其实就是在判断是不是包含在对方里
print(s1 > s2) # False
print(s1 < s2) # False
print(s1 > s3) # True