Demo1 基础语法
01:注释
##单行注释,用#号注释
“”"
多行注释,三个双引号
“”"
02: 输出语句
print(内容1,内容2,…),可输出多个内容并用逗号隔开,内容中双引号内写字符串
print('hello',110)
03:变量
money=50
print("钱包:",money)
money=money-10
print("钱包还剩:",money,"元")
04:数据类型
- type()通过print输出数据类型信息
print(type("黑马"))
name="黎明"
print(type(name))#查看变量类型
print(type(100))
print(type(2.3))
05: 数据类型的转换 数据类型(待转数据)
- 数字类型转换为字符串
num_str=str(20)
print(type(num_str))
- 字符串转数字
num=int("11")
print(type(num))
06:标识符,字符串
- 标识符由英文,数字,下划线组成,且开头不能是数字
- 字符串定义方式:‘字符串’;“字符串”:“”“字符串”“”三引号和注释相同,也可换行
name="""lijie
angxu
"""
- 字符串的分割split,最终存入列表对象中,字符串本身不变,得到的是新对象。
语法:字符串.split(分割符字符串)
split_result=str.split(",")
#split使用
my_str="hello python ITheima"
sp_result=my_str.split(" ")
print(sp_result)
生成的结果是列表类型:
由于得到的结果以列表形式存在,所以可以在split()后面直接跟[]截取对应内容。
#截取得到的列表中第二个字符串
sp_result2=my_str.split(" ")[1]
print(sp_result2)
- 字符串拼接,使用“加号”拼接,无法拼接非字符串类型
name="黎明"
address="北京市大兴区"
tel=123456
print(name+"live in"+address)
#print(name+"live in"+address+tel) 无法拼接整数型变量tel
07:格式化
- 字符串格式化 %占位符
name="liming"
tel2=123789
message="大学生 %s" % name
print(message)
#%s 表示用%占位,将要拼接的字符串放到s所在的位置,如果有多个要拼接的字符串或整数(如果用%s,其实是将整数转换为字符串类型),可用括号括起来:%(内容1,内容2)
message1="大学生 %s 电话:%s" % (name,tel2)
print(message1)
"""
- 格式符号:
"""
%s:将内容装换为字符串,放入占位位置
%f:将内容装换为浮点型(小数),放入占位位置,
%d:将内容装换为整数,放入占位位置
精度控制m.n:m控制宽度,n控制小数,%5d表示将整数的宽度控制在5位,对于数字11,表示为【空格】【空格】【空格】11
%7.2f的11.345表示为【】【】11.35 小数点算一位 ,四舍五入为5
"""
name2="xiaoming"
old=20
heigh=1.75
message3="%s 年龄:%d 身高:%f"%(name2,old,heigh)
print(message3)
- 字符串,表达式格式化-快速写法
目前通过%占位的方式已经很方便,并且可以实现精度控制,可是追求效率的话还有更简洁的方式:语法结构:
f"内容随意{变量}"
#字符串格式化方式:f"{变量名}"
name5="awei"
age5=24
#之所以用f是因为format表示格式化
print(f"姓名:{name5},年龄:{age5}")
注:
- 可以通过f"{变量}{变量}"的方式快速格式化
- 这种方式不用理会变量类型,不需要做精度控制,适合对精度无要求的快速使用
- 可以将变量换成表达式
print(f"姓名:{},年龄:{age5*2}")#表达式:age5*2
#表达式格式化
print(f"5*3的结果是{5*3}")
print("3*6的结果是%d"%(3*6))
08: pass语句
-
Python pass是空语句,是为了保持程序结构的完整性。pass 不做任何事情,一般用做占位语句,可用于测试语句块。
-
以下实例在字母为 o 时 执行 pass 语句块:
for letter in 'Runoob':
if letter == 'o':
pass
print ('执行 pass 块')
print ('当前字母 :', letter)#如果不等于o输出当前值
print ("Good bye!")
09: 输入函数input
#01输出函数input()
#print("请告诉我你是谁!")
#name=input()#提示信息可以直接写到input()函数括号里,
name=input("请告诉我你是谁!")
print("你是%s"% name)
#输入数字类型
num=input("请输入密码:")
print("input函数会将输入数字转换为:",type(num))
注意:
- input()函数会将输入的数值转换成str字符串类型,所以如果我们需要输出结果是数字类型,需要用到强制类型转换**。
- 无论键盘输入什么类型的数据,获取到的数据永远是字符串类型。
num=input("请输入密码:")
num=int(num)
print("input函数会将输入数字转换为:",type(num))
print("passwor:",num)
10:数据容器
- 定义:数据容器就是一种可以存储多个元素的Python数据类型
- Python中的数据容器:列表list,元组tuple,字典dict,字符串str,集合set
- 定义方式总结:列表[元素],元组(元素),字符串"",字典{},集合{}
str1="万过薪月,员序程马黑来,nohtyp学"#创建字符串
#方法一:先倒序,再切片
result2=str1[::-1][9:14]
print(result2)
#方法二 直接从后往前取取
result1=str1[9:4:-1]#得到新序列
print(result1)
"""由于元组和字符串都不支持修改,所以对他们进行切片得到的是新序列,并不影响原来的序列"""
#方法三 split分隔“,”,此逗号是中文逗号,切完片是以列表形式存在,然后用replace将“来”替换为空
result3=str1.split(",")[1].replace("来","")[::-1]
print(f"result3的结果:{result3}")
#split使用
my_str="hello python ITheima"
sp_result=my_str.split(" ")
print(sp_result)
#截取得到的列表中第二个字符串
sp_result2=my_str.split(" ")[1]
print(sp_result2)
Demo2 列表List
Python的数据结构:序列,序列中的每个值都有其对应的位置值,称之为索引,索引从0开始
01列表:列表可进行索引,切片,加,乘,检查成员的操作,列表定义后,数据项用逗号隔开【数据 1,数据2…】
list1=['Goole',123,'Runnable',2000]
02索引:可以从0开始,也可以从尾部开始-1
print(list1[0])
print(list1[-1])#从右到左最后一个元素是-1,-2,等
print(list1[-2])
03截取列表元素【a:b】,截取列表中下标从a到b的元素,但不包括b
print(list1[0:2])
print(list1[1:-2])#从第二位开始(包含第二位)到倒数第二位(不包括)
print(list1[1:])#输出从第一个元素到最后一个元素
04更新列表,增加append()方法,删除del语句
list2=['Goole',1234,'Runnable',3000,'liming']
list2.append('baidu')
print(list2[5])#输出新添加的元素查看是否成功添加
del list2[1]#删除原来列表中第三个元素1234
print(list2)
05嵌套列表
list3=['a',12,'b']
list4=['d',13]
list5=[list3,list4]
print(list5)
#如果要取出list4中的13
print(list5[1][1])
06列表函数
len(list)
求列表元素个数。
print('数组长度: %d'%(len(list3)) )#用%d链接字符串与整数
max(list)
返回列表最大值。min(list)
返回列表最小值。list(seq)
将元组转换为列表。
07列表方法
- 函数与方法的区别:函数是一个封装的代码单元,可以提供特定的功能,在Python中,如果将函数定义为类class的成员,则函数会称为方法。
- 函数可以直接通过函数名调用:num=add(1,2),方法必须通过类的对象调用,
student=Student() num=student.add(1,2)
。 list.copy()
方法:复制列表 。list.append(obj)
方法:在列表末尾添加元素obj。list.count(obj)
方法:在列表中统计obj出现的次数。list.extend(sep)
方法:在列表末尾增加扩展一个新列表seq。list.insert(index,obj)
方法:将对象obj插入列表。list.index(obj)
方法:在列表中找到与obj相同的值并输出其索引位置即下标。list.pop([index=-1])
方法:删除列表中的一个元素(默认是最后一个),并返回元素值。list.reverse()
方法:反向列表元素。list.sort(key=None,reverse=False)
方法:对原列表排序,key是用来比较的元素,reverse–排序规则,Ture表示降序,False表示升序(默认)。
list6=[1,3,2,5,0]
list6.sort()#默认升序
print(list6)
list.clear()
方法:清空列表。
08列表的遍历
#利用for循环
print("------for遍历----")
for elem in list8:
print(elem)
#利用while循环
print("------while遍历----")
index=0
while index<=len(list8):
print(list8[index])
index+=1
两种循环的区别:
1.while循环自定义循环条件,通过定义变量index控制每次取的位置与上一次相隔多远。例如只取偶数位置的元素。并可以通过控制条件达到无限循环。
2.for循环不可以自定循环条件,只可以一个个从容器中取出数据。将遍历的容器内容遍历完成后就会停止。
Demo3 元组Tuple
01元组定义,创建
- 定义:元组与列表相似,但元组使用小括号()定义,并且元组内元素一旦被定义就无法更改,而且不能删除单个元素。
- 创建元组:tuple=(元素1,元素2,…),也可以不用括号
- 当我们需要在程序内封装数据,又不希望封装的数据被更改,就可以选择元组。
tuple=('google','Run',123)#定义元组
# 创建空元组方法
t2=()
t3=tuple()
02. 元组的索引,修改
- 元组索引,截取与字符串类似,下标索引从0开始,可以进行截取,组合等。
#定义元组
tuple1=("beijing","hanghai",123,"nanjing",56)
#对元组进行索引
print(tuple1[1])#索引
print(tuple1[1:3])#截取,注意不包括第四个元素
- 修改元组:元组中的元素是不可更改的,但是可以对元组进行链接组合
#02修改元组
tuple2=("anhui",666)
tuple3=tuple1+tuple1
print(tuple3)
- 删除元组:元组中元素不可删除,但是可以del语句删除整个元组
#03删除元组
del(tuple3)
print(tuple3)
删除后整个元组不存在,运行报错
03元组运算符
- 与字符串一样,元组之间可以用+,+=,*号进行运算,即元组可以组合,复制,运算后形成新元组,并没有单独对某一元素操作,而是对整体操作。
#元组运算符:+,+=,*
tup1=(1,2,3)
tup2=(4,5,6)
tup3=tup1+tup2#加号运算
print(tup3)
tup1+=tup2
print(tup1)
tup2=tup2*2
print(tup2)
04元组内置函数
- 与列表类似:len(tuple):计算元组元素个数;max(tuple):返回最大值
min(tuple):返回最小值;tuple(iterable):将可迭代系列转换为元组
list=['Google',1,5]
tuple1=tuple(list)
print(tuple1)
05元组不可变
list=['Google',1,5]
tuple1=tuple(list)
print(tuple1)
print(id(tuple1))#输出原来元组内存地址
#重新赋值
tuple1 =(6,7)
print(tuple1)
print(id(tuple1))#输出重新赋值的元组内存地址
"""可以发现,重新复制元组,绑定到新对象,而不是修改了原来的对象"""
06元组截取
- 在 Python
中,如果你使用一个索引范围来截取一个元组,那么返回的将是一个新的元组,其中包含从开始索引(包含)到结束索引(不包含)的所有元素。 - 如果你截取的范围只包含一个元素,则 Python 会返回该元素的值,但是在该值后面会自动添加一个逗号。以明确表示这是一个元组而不是一个单独的值。
#04当我们需要在程序内封装数据,不改变数据时就需要用元组定义
tuple1=(5,'hello','banana')
print(tuple1[1:2])#输出:('hello',)
Demo4 字典
01:字典的定义
- 之所以称之为字典,是因为它就像英文词典一样,每个单词对应着某一汉语解释,字典中数据又是键值对形式存在,一一对应,字典是另一种可变容器模型,且可以存储任意类型对象。字典的每个键值对用冒号:分割,每个对之间用逗号,分割。整个字典用花括号包裹
- 例:d={key1:value1,key2:value2}
- 键必须是唯一的,值可以不唯一。值可以取任意类型数据,但键是不可变的,如字符串,数字,或者元组
- 字典中的元素是无序的,不能通过索引访问,只能通过键来访问值
- 字典的键不可以重复出现,如果同时创建两个键名相同的字典,最后一个创建的键会被记住,后面调用键名输出时会输出最后 创建的键名对应的value.
02:字典的创建
#创建列表
tinydict = {'name': 'runoob', 456:123, 'url': 'www.baidu.com'}
print(tinydict)#打印字典
print(len(tinydict))#查看字典的数量
print(type(tinydict))#查看类型
#使用内建函数dict()创建字典1、冒号改成等号 2、键虽然没有双引号,但本质上它还是字符串,因此在进行访问等操作时仍然需要加上访问
thisdict = dict(brand="Porsche", model="911", year=1963)
#我们可以在方括号内传入键来访问字典中的值,或者用get()函数
x = thisdict["model"]
x = thisdict.get("model")
03字典的修改
tinydic2=dict(a=1,b=2,c=3)
#修改
tinydic2['a']=4
print('a对应的值:%d' % tinydic2['a'])
#添加
tinydic2['d']=5
print('d对应的值:%d' % tinydic2['d'])#判断是否加入成功
#删除字典元素
del(tinydic2["a"])#删除a对应的值
print(tinydic2)
tinydic2.clear()#清空字典但字典仍存在
print(tinydic2)
del(tinydic2)#删除字典,字典不再存在
print(tinydic2)
Demo5 集合
01集合定义
- 集合(set)是一个无序,无重复元素的序列,可以用大括号{}或set()函数创建,创建空集合必须用set()函数而不是{},因为{}是用来创建空字典的。
- 由于集合是无序的,所以集合不支持下标索引访问,但是和列表一样,允许修改。
02创建集合
parame={"name","age","sex"}
print(parame)
parame2=set('name')
print(parame2)
- 用set()创建集合,只能有一个参数,要实现与正常方式创建含有多个字符串的集合元素,可通过在set()方法再加一个括号,set((‘元素1’,‘元素2’))
parame1=set('name')#此集合元素是单个字母,
parame2=set(('name','sex'))
print(parame1)
print(parame2)
03修改集合
#修改集合
parame3={1,2,3,4}
#01增加元素
parame3.add(5)
parame3.update([6])#update方法添加元素,参数是列表[],元组(),或者字典{}
print(parame3)
#02移除元素
parame3.remove(4)#如果元素不存在会报错
print(parame3)
parame3.discard(4)#如果元素不存在不会报错
#03清空集合
parame4={1,2,3,4,7}
print(parame4)
parame4.clear()
print(parame4)
#判断元素是否在集合中
parame5={1,2,3,4,7}
print(1 in parame5)#结果是ture
数据容器对比总结:
01 将数据容器进行分类
-
是否支持下标索引:
支持:列表[],元组(),字符串----序列类型
不支持:字典{},集合{}------非序列类型 -
是否支持重复元素
支持:列表[],元组(),字符串----序列类型
不支持:字典{},集合{}------非序列类型 -
是否可以修改
支持:列表,集合,字典
不支持:元组,字符串
02 数据容器的通用操作
- 遍历:五类数据容器均支持for循环遍历,列表元组,字符串支持while循环,集合,字典不支持(无法下标索引)
- 功能方法:len(容器名),max(容器名),min(容器名)
- 类型转换:list(容器):将给定容器转列表类型;set(容器):将容器转换集合,tuple(容器):将容器转换为元组;str(容器):将容器转换为字符串。
- 排序功能:sorted(容器,【reverse=ture】默认)
#排序函数sorted(),默认升序
list1=[1,4,2,7,9]
print(sorted(list1))
#反向排序
print(sorted(list1,reverse=True))
Demo6 条件控制,循环语句
注意:
1、每个条件后面要使用冒号 :,表示接下来是满足条件后要执行的语句块。
2、使用缩进来划分语句块,相同缩进数的语句在一起组成一个语句块。
3、在 Python 中没有 switch…case 语句,但在 Python3.10 版本添加了 match…case
01 while循环语句
- 格式:
while 判断条件(condition):
执行语句(statements)……
#end关键字,在输出print()中,可以使输出元素在同一行,并用某符号隔开
a,b=0,1
while b<10:
print(b,end=" " )#用空格隔开
"""print(b, end=",") 用逗号隔开隔开"""
a,b=b,a+b
#以下实例使用了 while 来计算 1 到 100 的总和:
sum=0
count=1
while count<=100:
sum+=count
count+=1
print("总和是%d "% sum)
02 If语句
if condition1:
statment_block_1
elif condition2:
statment_block_2
else:
statment_block_3
"""
如果 "condition_1" 为 True 将执行 "statement_block_1" 块语句
如果 "condition_1" 为False,将判断 "condition_2"
如果"condition_2" 为 True 将执行 "statement_block_2" 块语句
如果 "condition_2" 为False,将执行"statement_block_3"块语句
"""
03 match case语句
- Python 3.10 增加了 match…case 的条件判断,不需要再使用一连串的 if-else 来判断了。
- match 后的对象会依次与 case 后的内容进行匹配,如果匹配成功,则执行匹配到的表达式,否则直接跳过,_ 可以匹配一切。
语法格式如下:
match subject:
case <pattern_1>:
<action_1>
case <pattern_2>:
<action_2>
case <pattern_3>:
<action_3>
case _:
<action_wildcard>
-
case _: 类似于 C 和 Java 中的 default:,当其他 case 都无法匹配时,匹配这条,保证永远会匹配成功。
-
一个 case 也可以设置多个匹配条件,条件使用 | 隔开,例如:
case 401|403|404:
return "Not allowed"
04 For循环
- Python for 循环可以遍历任何可迭代对象,如一个列表或者一个字符串。
- for循环的一般格式如下:
for 临时变量 in 待处理数据集:#每循环一次将待处理数据集中数据赋值给临时变量
<statements>
else:
<statements>
- 列表的使用:创建一个列表,并用循环输出其内容
sites = ["Baidu", "Google","Runoob","Taobao"]
for site in sites:
print(site)
- 字符串:输出字符串的单个字符
word = 'runoob'
for letter in word:
print(letter)
- 整数:可使用内置函数rang()来确定输出范围,如果你需要遍历数字序列,可以使用内置 range() 函数。它会生成数列,
语法:range(num):获取一个从0开始,到num结束的数字序列,不包含num
# 1 到 5 的所有数字:
for number in range(1, 6):
print(number)
- 也可以使 range()函数 以指定数字开始并指定不同的增量(甚至可以是负数,有时这也叫做’步长’):
for i in range(1,10,2):#步长为2
print(i)
05 乘法表
- 法一:
#外层循环控制行
for i in range(1,10):
#内层循环控制列
for j in range(1,i+1):
print(f"{i}*{j}={i*j}\t" ,end=" ")#\t控制左对齐,end控制间隙
#外层循环输出空行
print()
- 法二:
#外层循环控制行
for i in range(1,10):
#内层循环控制列
for j in range(1,i+1)
print("{}*{}={}\t".format(i,j,i*j) ,end=" ")
#外层循环输出空行
print()
Demo7 函数
01 定义
是组织好的,可重复的,用来实现特定功能的代码段
#len()是python内置函数,是python官方写好的,可重复使用加粗样式的
02 结构:
def 函数名(参数):
函数体
return 返回值
03 无参函数定义例子:
#01:定义一个无参函数
def func1():
print("hello world!")
return 0
#02:调用函数
func1()
04 有参函数定义:
#03:有参函数
def add( x, y):#x,y为形参
result=x+y
print(f"{x}+{y}的计算结果:{result}")
print("{}+{}={}".format(x,y,x+y))#第二种输出方式
add(4,5)#4,5是实参
05 函数返回值
- 前面的例子都是在函数中将运算结果直接通过函数print()输出,函数体之外直接通过函数名调用即可,不用再调用print()函数完成输出。
- 如果使用return语句返回函数体运算结果:
#函数返回值
def add2(a,b):
sum=a+b
return sum #通过返回值将运算结果返回给调用者
r=add(7,8)
print(r)
06 无返回值
"""
1:即使我们不主动写返回值,函数仍会有返回值,此时是None
2:None是一个特殊字面量,用于表述空,无意义的意思
3:None又有假的意思,与False一样,在调用函数式,有时需要用返回值作为判断条件
"""
def test():
print("测试函数体")
mess=test()
print(f"函数返回值:{mess}")
print(f"函数返回值类型:{type(mess)}")
if not mess:
print("返回值为空,也就是错,才输出此句话!")
Demo08函数的参数传递
01 多种参数传递
#1:位置参数:调用函数时根据 函数定义的参数位置传递参数
def fun(name,age,gender):
print(f"姓名:{name},年龄:{age},性别:{gender}")
fun('Tom',20,'男')
"""传递的参数和定义的参数顺序及个数必须相同"""
#2:关键字参数:采用键值对的形式
fun(name='Tom',age=20,gender='男')
fun(name='Tom',gender='男',age=20)#顺序可以任意
#3:位置参数+关键字参数
fun('Tom',age=20,gender='男')#混合使用,但是位置参数必须在前,且匹配参数顺序
#4:缺省参数(默认参数):定义函数时提供默认值,如果调用函数时候没有传入对应参数则使用默认值,否则使用传入参数
def fun1(name,age,gender='男'):
print(f"姓名:{name},年龄:{age},性别:{gender}")
fun1(name='Tom',age=20)
fun1(name='Tom',age=20,gender='女')
#5:不定长参数(参数数量任意)
def fun2(*args):
print(args)
"""传进的参数都会被变量args收集,它会根据传进参数的位置合并为一个元组tuple,args是元组类型,这就是位置传递"""
fun2("Tom",17,'男')
fun2("TAndy",'女')
#关键字传递的不定长,以键值对形式传入,以字典的形式输出
def fun3(**kwargs):
print(
kwargs
)
fun3(name="li",age=18)
02匿名函数
- 函数作为参数
#函数作为参数传递
def testfunc(computer):
result=computer(1,2)
print(result)
def computer(x,y):
return x+y
testfunc(computer)
"""这是一种计算逻辑的传递,不是数据的传递"""
- lambda匿名函数
(1)函数的定义:用def关键字定义,可以定义带有名称的函数。
(2)lambda关键字,可以定义匿名函数(无名称)
**区别:**有名称的函数可以重复调用,无名称的函数只可以临时使用一次
(3)语法:lambda (参数):函数体
#lambda关键字定义匿名函数
def testfunc1(computer1):
result=computer1(1,2)#computer1是函数,未定义,下面直接用lambda函数定义。
print(result)
testfunc1(lambda x,y:x+y)
Demo09 函数案例
01 案例描述:
1,定义一个全局变量Money:用来记录银行卡余额(默认50000),
2,定义一个全局变量name:记录用户名(启动程序时输入)
3,定义如下函数:
查询余额函数;存款函数;取款函数;主菜单函数,通过输入不同的数字进入不同的操作页面
4,要求:
程序启动后要求输入客户名,
查余额,存款,取款后都会返回主菜单,
存款,取款后都应显示一下余额,
客户选择退出或者输入错误,程序会退出,否则一直运行
02 源码:
Money=50000
name=None
#用户输入用户名
name=input("请输入用户名")
#查余额函数
def query(show_head):
if(show_head):#通过show_head控制打不打印
print("--------查余额---------")
print("%s 卡内余额:%d"%( name,Money))
#存款函数
def saving(num_money):
print("--------存款---------")
global Money#通过 global将Money在函数体内定义为全局变量
Money+=num_money
print("%s存款%d成功" % (name,num_money))
query(False)#不打印头
#取款函数
def getMoney(num_money):
print("--------取款---------")
global Money
Money-=num_money
print("%s取款款%d成功" % (name,num_money))
query(False)
#主菜单
def main():
#提示:
print("--------主菜单---------")
print(f"---{name}你好-----请选择以下操作------")
print("查询余额输入 \t[1]")#通过\t制表符控制对齐
print("存款输入\t\t[2]")
print("取款输入\t\t[3]")
print("退出\t\t\t[4]")
return input("请输入要进行的操作序号:")#返回输入值
while True:
key_press=main()#获取输入值
if key_press=="1":
query(True)
continue # 查询后自动退出返回主菜单
elif key_press=="2":
num = int(input("输入存款金额")) # 由于input输入的都是字符串,所以要强制转换为int类型
saving(num)
continue
elif key_press=="3":
num = int(input("输入取款金额"))
getMoney(num)
continue
elif key_press=="4":
print("退出程序!")
break
Demo10重要知识点总结:
- type()函数查看数据类型
- 字符串可以用,单引号,双引号,三引号。字符串的分割函数
字符串.split(“分割”)
,结果存入列表对象。[‘字符串1’,‘字符串2’]。
由于最终以列表形式存在,所以可以直接通过下标索引。
字符串.split(“分割”)[2]
,分割后的第三个列表元素。 - input()输入函数,会将输入值转化为str类型,如果需要数字类型需要进行强制类型转换。
x=input("密码:") x=int(x)
- 数据容器:(1)字符串:先倒序再切片
str(::-1)[2:4]
(2)元组tuple,元素不可修改,整个元组可删除del(tuple)
,两个元组可相加,元组可以截取内容赋值给其他变量,自身不变。tuple[1:3],不可对单个元素操作,可以对整体操作。(3)
\t :表示空4个字符,类似于文档中的缩进功能,相当于按一个Tab键。
\n :表示换行,相当于按一个 回车键
\n\t : 表示换行的同时空4个字符。