前言
前面基础知识部分的知识点较为杂乱,后面有总结好的知识点和例题,可以直接在目录里跳转。如果忘记了可以再跳转回去看详解的知识点。还有一些看起来不大聪明的问题,都是博主在学习过程中的疑问,如果知道的话可以直接跳过。
对于博客中如有错误的地方,还望各位海涵,欢迎在评论区里指出。如有更好的方法,也欢迎各位在评论区里教教我,毕竟博主也是小白,这篇相当于是我的学习笔记,我看了一些学习笔记都不怎么针对小白,或者说小白比较难懂,故此分享出来大家一起进步!
一、基础知识
任何语言刚开始,都是要先用这个语言跟世界打声招呼,来吧。
print("hello world!")
这是我们写的第一条语句,print是打印的意思,这句话的意思是说把hello world打印下来。
至此,我们才真正开始了python之旅。
1、注释、变量和简单的数据类型
1.1注释
注释是指(⊙o⊙)…代码之间不需要的那部分或需要被解释的那部分
注释的格式分为单行注释和多行注释(一般Ctrl+/就可以完成大部分语言的注释,只要找到需要注释的部分,同时按下Ctrl+/就可以了)
1.1.1单行注释
在需要注释的语句前加“#”
# print("hello Monster")
1.1.2多行注释
在需要注释的多行语句上方和下方加三个双引号完事儿。
"""
name="aoteman"
print(name.title())
print(name.upper())
print(name.lower())
"""
1.2变量的命名和使用
a、变量名只能包含字母、数字和下划线,且不能用数字开头。
eg:变量可命名为 message_1 但不能命名为1_message。
b、变量名不能包含空格,但可以使用下划线来分隔其中的单词。
eg:变量名greeting_message可行,但greeting message会引发错误。
c、不要用Python关键字和函数名用作变量名,即不要使用Python保留用于特殊用途的单词。
eg:print
d、变量名应既简短又具有描述性,至少让人一眼就可以看出来你的变量名是干啥用的。
eg:name 比 n 好,student_name 比 s_n 好。
e、慎用小写字母l和大写字母O,因为这真的长得有点像数字1和0。
注意:为便于区分,应使用小写的Python变量名,虽然在变量名中使用大写字母不会导致错误,但是大写字母在变量名中多指代常量。
在命名时可以使用驼峰命名法、匈牙利命名法和帕斯卡命名法(因为博主脑袋不大够用,匈牙利命名法和帕斯卡命名法略显复杂,故不作介绍)
驼峰命名法分为大驼峰和小驼峰,就像下面这只骆驼(图是网上找的),标识符第一个单词用大写字母来表示的叫大驼峰,比如:LuoTuo、DaTuoFen
小驼峰的第一个单词小写,比如:studentName、coolBoy。
小知识
在同一行代码中可以同时给多个变量赋值,这有助于提高代码的可读性。
x,y,z=0,0,0
1.2字符串
由引号引起来的都是字符串,其中引号可以是单引号也可以是双引号。
eg:
"hello Monster"
'hello Monster'
1.2.1.用方法修改字符串的大小写
title()将每个单词的首字母改成大写
upper()将字符串全部改为大写
lower()将字符串全部改为小写
代码如下:
name="aoteman"
print(name.title())
print(name.upper())
print(name.lower())
运行结果
1.2.2.在字符串中使用变量(f字符串)
如果你想在字符串中插入变量的值,可在引号前加上字母f,再将要插入的变量放入花括号,这样Python可以把每个变量都替换为其值。
eg:
first_name="mr"
last_name="monster"
full_name=f"{first_name} {last_name}"
print(full_name)
# 结果:Mr Monster
这种字符串叫f字符串,f是format(设置格式)的简写。
使用f字符串可以完成很多任务,如利用与变量关联的信息来创建完整的消息。
eg:
first_name="Mr"
last_name="Monster"
full_name=f"{first_name} {last_name}"
print(f"Hello,{full_name.title()}!")
# 结果:Hello,Mr Monster!
1.2.3使用制表符或换行符来添加空白
\t在字符串中添加制表符
\n在字符串中添加换行符
name="\n\t mr \n\t monster"
print(f"my dear {name.title()}")name="\t mr \t monster"
print(f"my dear {name.title()}")name="\n mr \n monster"
print(f"my dear {name.title()}")
运行结果
小知识
\t 制表符:
在python中 \t 在打印的时候,代表着四个空格,也就是一个tab。它会把前面那个字符串的长度补齐到4,或者4的倍数。最少补齐1个空格,最多补4个。看不懂没关系,看例子就好啦~
#不加制表符
print("hello"+"happy")
print("abc"+"123")
#加制表符,hello补三个空格,abc补一个
print("hello"+'\t'+"happy")
print("abc"+'\t'+"123")
#hello补2个空格,ab补2个
print("helloo"+'\t'+"happy")
print("ab"+'\t'+"123")
#hello补4个空格,a补3个
print("helloooo"+'\t'+"happy")
print("a"+'\t'+"123")
看结果
1.2.4删除空白
rstrip()删除字符串末尾空白
lstrip()删除字符串开头空白
strip()删除字符串两侧空白
name=" aote man "
print(name.rstrip())
print(name.lstrip())
print(name.strip())
#运行结果,为了可观,我把空格换成了-的形式
"""
-aote man
aote man-
aote man
"""
但是这种删除只是暂时性的,如果再次询问还是会有。
若想永久删除这个字符串中的空白,必须将删除操作的结果关联到变量。
name=" monster "
name=name.strip()
经过以上操作,此时monster两侧的空白被完全删除了,即使再调用name也不会有空格。
1.3数
1.3.1 整数
1、在python中,可以对整数执行加(+)减(-)乘(*)除(/)运算。
2、使用两个乘号表示平方运算。
3、可以使用圆括号()来修改运算次序。
#1、在python中,可以对整数执行加(+)减(-)乘(*)除(/)运算。
201+189 #390
3269-9 #3260
5*6 #30
3/2 #1.5
#2、使用两个乘号表示平方运算。
2**2 #4
2**3 #8
#3、可以使用圆括号来修改运算次序。
2+3*4 #14
(2+3)*4 #20
提示:表达式中有空格是不影响计算的
1.3.2浮点数
python将所有带小数点的数称为浮点数。
浮点数和整数的区别:
1、浮点数带小数点
2、浮点数只要碰上整数,结果一定是浮点数。
3、任意两个数相除,结果一定是浮点数,即使这两个数都是整数
整数所说的那三条知识点浮点数同样适用,毕竟本质上它们都是数嘛。
0.1+0.1 #0.2
2*0.1 #0.2
2/0.1 #20.0
4/2 #2.0
但需要注意的是,结果包含的小数位数可能是不确定的:
0.2+0.1 # 0.30000000000000004
3*0.1 #0.30000000000000004
不过几乎所有语言都存在这种问题,所以不必担心。
小知识
书写很大的数时,可以使用下划线将其中的数字进行分组,python不会将下划线打印出来。
2*12_000_000_000
# 结果: 24000000000
1.3.3常量
常量类似于变量,在程序的整个生命周期内其值保持不变。一般情况下程序员会使用全大写来指出应将某个变量视为常量。为便于区分,变量应尽量使用小写。
小结
2、列表
2.1 啥是列表,怎样访问列表元素
列表是由一系列按特殊顺序排列的元素组成,在python中用方括号[元素1,元素2,元素3]表示列表,列表中用,(英文逗号)隔开。
访问列表的元素也很简单,只需要将该元素的位置(索引)告诉python即可。
eg:
#创建列表name=[]
#添加列表元素
name=['my','dear','mr','monster']
#访问列表,注意索引从0开始而不是1
#大多数编程语言都是这么规定的,从0开始数.
print(name[0])#访问列表的第一个元素
print(name[-1])#访问列表的倒数第一个元素
print(name)
#运行结果
# my
# monster
# ['my', 'dear', 'mr', 'monster']
2.2使用列表中的各个值
列表元素的使用eg:
name=['my','dear','mr','monster']
print(f"I will attack the {name[-1].title()}!")
# 结果: I will attack the Monster!
2.3修改添加和删除元素
1、修改列表元素,直接改就成。
name=['a','b','c','d']
name[0]='apple'
#结果 ['apple', 'b', 'c', 'd']
2、添加、删除元素
.append(‘需要添加的元素’)在列表后添加元素
.insert(位置 ,'需要添加的元素 ')在列表任意位置添加元素,但是添加了新元素后,新元素之后的既有元素索引都会向右移一位。
del 列表名[ ]在列表特定位置删除元素
.pop()删除列表末尾的元素
.remove(‘元素’)找到特定元素并删除它,但注意,方法.remove()只删除第一个指定的值,如果要删除的值在列表中会出现多次的话,就需要利用循环来确保将每个值都删除干净了。
name=['a','b','c','d']
name.append('e') #['a', 'b', 'c', 'd', 'e']
name.pop() #['a', 'b', 'c', 'd']
name.insert(1,'haha') #['a', 'haha', 'b', 'c', 'd']
#此时这里b的索引向后移了一位,b原本是1,现在变成了2
del name[1] #['a', 'b', 'c', 'd']
name.remove('b') #['a', 'c', 'd']
关于.pop()实际上也可以删除任意位置的元素,只需要在圆括号内指定需要被删除的元素的索引即可。
eg:
name=['a','b','c','d']
name.pop(1)
print(name) #['a', 'c', 'd']
2.4组织列表
.sort()永久性地修改列表元素的排序
.sorted()对列表临时排序
.reverse()倒着打印列表(永久性修改,但随时可以恢复原状,只要再次调用.reverse()就可以了)
len()快速获悉列表长度
name=['apple','export','import','banana','orange']
name.sort() #['apple', 'banana', 'export', 'import', 'orange']
#方法.sort()还可以按与字母顺序相反的顺序排列列表元素,只需向sort()方法传递参数reverse=True即可,但同样,对列表元素的修改是永久性的
name.sort(reverse=True) #['orange', 'import', 'export', 'banana', 'apple']
name.reverse() #注意,这里.reverse()方法倒着打印列表同.sort()一样,也是永久性修改
#结果:['orange', 'banana', 'import', 'export', 'apple']
len(name) #列表一共有5个元素 所以结果 5
#len()获取列表元素数时从1开始
关于.sort()方法,如果想要保留列表原来的排列顺序,同时以特定的顺序呈现它们,可使用.sorted()。
不过这里稍有不同的是,不再是name.sorted(),而是sorted(name)。同样的,.sortde()还可以按与字母顺序相反的顺序排列列表元素,只需向sort()方法传递参数reverse=True即可。
name=['apple','export','import','banana','orange']
print(sorted(name)) #['apple', 'banana', 'export', 'import', 'orange']
print(name) #['apple', 'export', 'import', 'banana', 'orange']
小结
3、操作列表(for循环)
当我们需要对列表中的元素进行相同的操作时,for循环就诞生啦。
先来简简单单的看个例子:
使用for循环来打印魔术师名单上的所有名字
magicians=['alice','david','carolina']
for magician in magicians:print(magician)
运行结果
注意到了吗
for循环的结构:for 新变量的名字 in 列表名 :
以上例子中 magician就是新变量的名字,列表将列表元素赋值给新变量,然后我们再打印变量,直到列表元素全部打印出来为止,程序结束。这样的循环往复就叫for循环。
3.1在for循环中执行更多操作
先来个群发短信开开胃
对于刚才的魔术师名单,我们想要给他们每一个人群发一条短信,指出他们的表演非常精彩。利用我们在之前学到的f字符串,我们该怎么写呢?
嗯,揭晓答案。
magicians=['alice','david','carolina']
for magician in magicians:print(f"OMG,{magician.title()} Your performance was really great !")
运行结果
问题来了,如果你觉得这不够,想在这条短信的下面再问候一下人家呢?
来思考一下。
再打印一条消息不就好咯。
小知识:
加上换行符\n可以在每次迭代结束后都插入一个空行,这会使代码更易读。
magicians=['alice','david','carolina']
for magician in magicians:print(f"OMG,{magician.title()} Your performance was really great !")print(f"I'm looking forward to your next performance~{magician.title()}\n")
运行结果
冒号(“:”)君:“怎么没人注意到我呢?[○・`Д´・ ○] !”
莫慌,现在就让我们来感受一下冒号君的魅力吧!
还是以给魔术师群发短信为例。
magicians=['alice','david','carolina']
for magician in magicians:print(f"OMG,{magician.title()} Your performance was really great !")
print(f"I'm looking forward to your next performance~{magician.title()}\n")
先来看运行结果
发现什么了吗?
没错!这两串代码唯一的区别就是上一个问候魔术师的print缩进了,但是这个没有。
我们一句一句来看
magicians=['alice','david','carolina']
#创建列表,建立循环
for magician in magicians:print(f"OMG,{magician.title()} Your performance was really great !")#这里print缩进了,代表这是个for循环的代码块,也就是说这代表是在for循环的内部
print(f"I'm looking forward to your next performance~{magician.title()}\n")
#这里没有缩进代表不是for循环代码块里的东西,不参与循环
没错,冒号君的作用就是:声明以下代码是额滴,额滴,都是额滴。属于这个循环的代码会缩进。
3.2创建数值列表(range()函数)
3.2.1使用函数range()
在python的学习历程中,存储、创建、使用是非常常见的。函数range()让我们能够轻松生成一系列数。
for value in range(1,9):print(value)
上述代码好像应该打印1-9,但实际上不会打印9
这是编程语言中常见的差一行为,函数range()让python从指定的第一个值开始数,并在指定的最后一个值(9)停止,因为在9处程序就已经停止了,所以输出不会打印9。
如果你想打印1-9,需要使用(1-10)
for value in range(1,10):print(value)
在使用range()时,如果输出不符合预期,可以尝试将值加1或减1。调用函数时,也可以只指定一个参数,这样它将从0开始。例如range(6)返回数0~5。
3.2.2使用range()创建数字列表
要创建数字列表,可使用函数list()将range()的结果直接转换为列表。如果将range()作为list()的参数,输出将是一个数字列表。
在之前的例子中,我们只是将数字打印出来了,想将这组数字转换为列表,可以使用list():
numbers=list(range(1,11))
print(numbers)
#[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
使用函数range()时,还可以指定步长。为此,可给这个函数指定第三个参数,python将根据这个步长来生成数。
numbers=list(range(1,11,2))
print(numbers)
#[1, 2, 3, 4, 5]
在上述例子中,函数range()从2开始数,然后不断加2,直到达到或超过终值(11)。
使用函数range()几乎能够创建任何需要的数集。例如,如何创建一个列表,其中包含前10个整数的平方呢?
squares=[]
for value in range(1,11):square=value**2squares.append(squaer)
print(squares)
#[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
当然,上述代码较为繁复,熟练之后我们可以更简洁优雅。
squares=[]
for value in range(1,11):squares.append(value**2)
print(squares)
#[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
既然追求优雅,还有没有更优雅一点的代码捏?
of course!
3.2.3列表解析
列表解析我愿称之为一步到胃(到"squares"的胃)
squares=[value**2 for value in range(1,11)]
print(squares)
这样就可以不必费心再将数一个一个加进squares里了,而是直接在内部运算。
如果你问我如何列表解析,我只能告诉你:“年轻人,要去悟,只可意会不可言传也。”
3.2.3对数字列表进行简单的统计计算
简单介绍几个函数min()找出最小值、max()找出最大值、sum()求总和。
squares=[]
for value in range(1,11):squares.append(value**2)
print(min(squares))
print(max(squares))
print(sum(squares))
#1
#100
#385
3.3使用列表的一部分
其实不止可以操纵列表,也可以操纵列表的一部分哟,python将此称之为切片,操作如其名,就是将数据切成一片一片的来使用。
3.3.1切片
以上一节的例子举例
squares=[value**2 for value in range(1,11)]
#[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
print(squares[0:4])#切片,切下从索引0开始数,一直到索引4的数
#[1, 4, 9, 16]
#print(squares[起始索引:结束索引])注意:索引从0开始数,且到索引4的时候就结束了,故并未打印索引4。
实际上如果是从头开始切的话,不用特意提示python从索引0开始,因为它默认从0开始。
squares=[value**2 for value in range(1,11)]
#[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
print(squares[:4])
#[1, 4, 9, 16]
结果是一样的哟~
python不仅仅可以把头切下来,还可以切身体
squares=[value**2 for value in range(1,11)]
#[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
print(squares[4:7])
#[25, 36, 49]
#同样,这里并未打印索引7
当然也可以切尾巴
squares=[value**2 for value in range(1,11)]
#[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
print(squares[7:])
#[64, 81, 100]
甚至可以用负数来告诉python从倒数第几个开始切
squares=[value**2 for value in range(1,11)]
#[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
print(squares[-3:])
#[64, 81, 100]
想怎么切就怎么切,站着切,坐着切,字符串也可以切。
time="2019-1-2 11:10:19"
print(time[:9])
#2019-1-2
而且跳着切也可以,给python指定第三个值,告诉python在指定范围内每隔多少元素切一个
squares=[value**2 for value in range(1,11)]
#[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
print(squares[:10:2])
#[1, 9, 25, 49, 81]
总之自由度很高啦。
3.3.2遍历切片
说到遍历,肯定离不开for循环啦
times=["2019-1-2 11:10:19","2019-1-3 9:46:18","2019-1-4 11:55:20"]
for time in times:print(time[:9])
#2019-1-2
#2019-1-3
#2019-1-4
我们遍历times,遍历一个数据,就将这个数据存入time中,并将time切片打印出来,直到将times遍历完。
我们也可以在遍历时先给times切片,不过这个切片是针对整个times而言的。
times=["2019-1-2 11:10:19","2019-1-3 9:46:18","2019-1-4 11:55:20"]
for time in times[:2]:print(time)
#2019-1-2 11:10:19
#2019-1-3 9:46:18
3.4复制列表
我们经常需要根据既有列表创建一个全新的列表,此时就用得到复制列表。要复制列表,方法是同时省略起始索引和终止索引([ : ])。这让python创建始于第一个元素,终止于最后一个元素的切片,即整个列表的副本。
#我最喜欢的食物列表
my_foods=["pizza","falafel","carrot cake"]
#我朋友跟我喜欢吃的东西几乎一模一样
friend_foods=my_foods[:]
print(friend_foods)
#['pizza', 'falafel', 'carrot cake']
切片的方法和直接赋值不同,利用切片复制列表是两个列表,而直接赋值虽然列表名不同,但实质上是一个列表。
先来看切片的
#我最喜欢的食物列表
my_foods=["pizza","falafel","carrot cake"]
#我朋友跟我喜欢吃的东西几乎一模一样
friend_foods=my_foods[:]
#但我还喜欢吃冰淇淋
my_foods.append('ice cream')
#我的朋友还喜欢吃巧克力
friend_foods.append('chocolate')
print(my_foods)
print(friend_foods)
#['pizza', 'falafel', 'carrot cake', 'ice cream']
#['pizza', 'falafel', 'carrot cake', 'chocolate']
再对比一下直接赋值的
#我最喜欢的食物列表
my_foods=["pizza","falafel","carrot cake"]
#我朋友跟我喜欢吃的东西几乎一模一样
friend_foods=my_foods
#但我还喜欢吃冰淇淋
my_foods.append('ice cream')
#我的朋友还喜欢吃巧克力
friend_foods.append('chocolate')
print(my_foods)
print(friend_foods)
#['pizza', 'falafel', 'carrot cake', 'ice cream', 'chocolate']
#['pizza', 'falafel', 'carrot cake', 'ice cream', 'chocolate']
结果完全不同了,把赋给my_foods的值也赋给了friend_food,赋给friend_food的值也赋给了my_foods。实质上变成了同一个列表,没啥意义。
3.5元组
列表非常适合用于存储在程序运行期间可能变化的数据集,python将不能修改的值称为不可变的,而不可变的列表叫做元组。
3.5.1定义元组
元组看起来很像列表,不同的是列表用[ ]中括号,而元组用()圆括号。定义元组后就可以使用索引来访问其元组,就像访问列表元素一样。
综上所述,元组一共有三个特点
1、元组很像列表,其区别在于元组用()圆括号定义。
2、元组可以像列表一样用索引来访问其元素。
3、元组中被定义的值不可变。
#咱来定义一个元组alphabet
numbers=(1,2,3)
print(numbers[1])
#2
#尝试修改其中元素
numbers[0]='5'
#报错信息:TypeError: 'tuple' object does not support item assignment
TypeError: ‘tuple’ object does not support item assignment“tuple”直译过来就是类型错误:‘tuple’ 对象不支持项目分配,说人话就是’tuple’ 对象只支持读不支持写。
因此得出特点3,元组中被定义的值不可被改写,也就是不可变。
注意:严格地说,元组是由逗号标识的,圆括号只是让元组看起来更整洁、更清晰。如果你要定义只包含一个元素的元组,必须在这个元素后面加上逗号:numbers=(1,),但其实不加逗号也不会报错,只是不规范罢了。创建只包含一个元素的元组通常没有意义,但自动生成的元组有可能只有一个元素。
3.5.2遍历元组中的所有值
像列表一样,也可以使用for循环来遍历元组中的所有值。
numbers=(1,2,3)
for number in numbers:print(number)
#1
#2
#3
4、if 语句
if语句又称条件语句,是通过判断指定表达式的值来决定执行还是跳过某些语句。
举个栗子
#创建一个letter列表
letters=['aa','bb','cc','dd']
#for循环打印出字母表中的每一个元素
for letter in letters:if letter=='aa':#如果字母='aa'print(a.upper())#则在打印的时候,将aa全部改成大写else:#否则print(a.title())#仅首字母大写
#AA
#Bb
#Cc
#Dd
提到条件语句,我们就不得不提到运算符。
补充:运算符(转载宁静与致远)
版权声明:本文为CSDN博主「宁静与致远」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42076902/article/details/124752241
运算符是描述数据运算的符号,在python中主要分为五类:算术运算符、赋值运算符、复合赋值运算符、比较运算符、逻辑运算符。
1.算术运算符
运算符 | 描述 | 实例 |
---|---|---|
+ | 加 | 1 + 1 输出结果为 2 |
- | 减 | 1 - 1 输出结果为 0 |
* | 乘 | 2 * 2 输出结果为 4 |
/ | 除 | 10 / 2 输出结果为 5 |
// | 整除 | 9 // 4 输出结果为2 |
% | 取余(取模) | 9 % 4 输出结果为 1 |
** | 指数 | 2 **4 输出结果为 16,即 2 * 2 * 2 * 2 |
() | 小括号 | 小括号用来提高运算优先级,即 (1 + 2) * 3 输出结果为 9 |
ps:混合运算优先级顺序:( ) 高于 ** 高于 * / // % 高于 + -
2.赋值运算符
运算符 | 描述 | 实例 |
---|---|---|
= | 赋值 | 将=右侧的结果赋值给等号左侧的变量 |
案例:
单个变量赋值
num = 1
print(num)
多个变量赋值
num1, float1, str1 = 10, 0.5, 'hello world'
print(num1)
print(float1)
print(str1)
多变量赋相同值
a = b = 10
print(a)
print(b)
3.复合赋值运算符
运算符 | 描述 | 实例 |
---|---|---|
+= | 加法赋值运算符 | c+=a等价于c=c+a |
-= | 减法赋值运算符 | c-=a等价于c=c-a |
*= | 乘法赋值运算符 | c*=a等价于c=c*a |
/= | 除法赋值运算符 | c/=a等价于c=c/a |
//= | 整除赋值运算符 | c//=a等价于c=c//a |
%= | 取余赋值运算符 | c%=a等价于c=c%a |
**= | 幂赋值运算符 | c*=a等价于c=c**a |
最后一列是c**=a由于Markdown使用双星会加粗,所以暂时用单星表示
a = 100
a += 1
# 输出101 a = a + 1,最终a = 100 + 1
print(a)b = 2
b *= 3
# 输出6 b = b * 3,最终b = 2 * 3
print(b)c = 10
c += 1 + 2
# 输出13, 先算运算符右侧1 + 2 = 3, c += 3 , 推导出c = 10 + 3
4.比较运算符
运算符 | 描述 | 实例 |
---|---|---|
== | 判断相等。如果两个操作数的结果相等,则条件结果为真(True),否则条件结果为假(False) | 如a=3,b=3,则(a=b)为True |
!= | 不等于。如果两个操作数的结果不相等,则条件为真(True),否则条件结果为假(False) | 如a=3,b=3,则(a==b)为True如a=1,b=3,则(a!=b)为True |
> | 运算符左侧操作数结果是否大于右侧操作数结果,如果大于,则条件为真,否则为假 | 如a=7,b=3,则(a>b)为True |
< | 运算符左侧操作数结果是否小于右侧操作数结果,如果小于,则条件为真,否则为假 | 如a=7,b=3,则(a<b)为False |
>= | 运算符左侧操作数结果是否大于等于右侧操作数结果,如果大于,则条件为真,否则为假 | 如a=7,b=3,则(a<b)为False如a=3,b=3,则(a>=b)为True |
<= | 运算符左侧操作数结果是否小于等于右侧操作数结果,如果小于,则条件为真,否则为假 | 如a=3,b=3,则(a<=b)为True |
# 定义变量a与b
a = 7
b = 5# a与b比较运算结果
print(a == b) # False
print(a != b) # True
print(a < b) # False
print(a > b) # True
print(a <= b) # False
print(a >= b) # True
5.逻辑运算符
运算符 | 描述 | 实例 |
---|---|---|
and | x and y | 布尔"与":如果x为False,x and y返回False,否则它返回y的值。 True and False,返回False。 |
or | x or y | 布尔"或":如果x是True,它返回True,否则它返回y的值。 Falseor True,返回True。 |
not | not y | 布尔"非":如果x为True,返回False。如果x为False,它返回True。 not True返回False,not False返回True。 |
4.1.条件测试
每条语句的核心都是一个值为true或false的表达式,这种表达式称为条件测试。python根据条件测试的值为true还是false来决定是否执行if语句中的代码,如果条件测试的值为true,python就执行紧跟在if语句后面的代码,如果为false,则忽略后面的代码。
在学习条件测试之前,我们先来复习一下运算符(很重要哦)
1、 ==相等运算符,相等时返回true,不同返回false
2、!=不等运算符
3、 >= 、 > 、 < 、 <=数值比较
4、and / or 检查多个条件
4.1.1 条件测试
嗯……咱直接上代码吧。
a='2'
a=='3'
#False
a='2'
a!='3'
#True
a='2'
a<='3'
#True
a='2'
a=='2'and a=='3'#(这里改成or就是True)
#False
age_0=18
age_1=20
age_0 >=15 or age_1 >=25
#True
car='Audi'
car=='audi'
#False
#注意:python严格区分大小写,如果两个大小写不同的值被视为不相等。
#如果大小写很重要,这种行为有其优点。但如果大小写无关紧要,只想检查变量的值的话,可将变量的值转换为小写,再进行比较:
car='Audi'
car.lower()=='audi'
#True
在上述代码中我们提到python严格区分大小写。实际上在我们玩某些游戏的时候,取的用户名也是通通小写处理或大写处理,以保证用户名独一无二。(只是某些)
4.1.2 检查特定值是否包含在列表中
话不多说,上代码
#我最喜欢吃的食物列表
my_foods=["pizza","falafel","carrot cake"]
'pizza' in my_foods
#True
'cake' in my_foods
#False
4.1.3 布尔表达式
随着我们对编程的了解越来越深入,将会遇到术语布尔表达式,它不过是条件测试的别名。布尔值(true、false)通常用于记录条件,如游戏是否正在运行,或者用户是否可以编辑网站的特定内容。
game_activite=True
can_edit=False
在跟踪程序状态或程序中重要的条件方面,布尔值提供了一种高效的方式。
4.2 if语句
理解条件测试后就可以开始编写if语句了。if语句有很多种,选择使用哪种取决于要测试的条件数。
4.2.1 简单的if语句
最简单的if语句只有一个测试和一个操作
if age >=18:#条件测试的结果为True就会执行后面的代码print("You're already an adult")
4.2.2 if-else语句
if-else 在条件测试通过时执行一个操作,在没有通过时执行另一个操作。
就像我们开头编写的那个if语句一样,它就是if-else语句。
#创建一个letter列表
letters=['aa','bb','cc','dd']
#for循环打印出字母表中的每一个元素
for letter in letters:if letter=='aa':#如果字母循环到'aa'print(a.upper())#则在打印的时候,将aa全部改成大写else:#否则print(a.title())#仅首字母大写
#AA
#Bb
#Cc
#Dd
4.2.3 if-elif-else 语句
if-elif-else 一次检查每个条件测试,直到遇到通过了的条件测试
例,来看一个根据年龄段收费的游乐场
条件:
4岁以下免费
4~18岁收费25人民币
18岁(含)以上收费40人民币
#假如你今年25岁
age=25
if age < 4:print("小朋友可以不用门票")
elif 4 < age <18:print("您需要支付25元")
else age>=18:print("您需要支付40元")
运行结果怎么样呢?
报错惹hahahaha
报错信息:SyntaxError: invalid syntax(语法错误:无效语法)
让我们康康python是如何提示的
age的a那里有个箭头,这是为啥捏?
因为else之后不能有东西,也就是说你必须写成下面这个样子。
#假如你今年25岁
age=25
if age < 4:print("小朋友可以不用门票")
elif 4 < age <18:print("您需要支付25元")
else :print("您需要支付40元")
else就是个舔狗,如果有幸能让他出场,他只能执行不能讲条件。
当然,这个代码写得并不优雅。如果是你,你会怎么改呢?
书上给的答案是:
#假如你今年25岁
age=25
if age < 4:print("小朋友可以不用门票")
elif age < 18:print("您需要支付25元")
else :print("您需要支付40元")
这么写的原因是:elif其实是另一个if语句,当python发现年龄大于4岁时会自动执行下一个语句。同理,如果年龄大于等于18,python会自动执行下一个语句,直到满足条件为止。所以我们大可不必将条件写得如此细致。代码能简洁明了就简洁明了,优雅,永不过时~
那就有同志问了,25岁以下的单身青年也是父母的宝宝呀,能不能加个条件打个折扣。
嗯,满足o( *  ̄︶ ̄ * )o
例:根据年龄段收费的游乐场
4岁以下免费
4~18岁收费25元
18~25(含)岁收费30元
25岁以上收费40元
加了一个条件该怎么写呢?
再加个elif呗!
age = 20
if age < 4:print("小朋友不用缴费")
elif age < 18:print("您需要交25元")
elif age <= 25:print("您需要交30元")
else :print("您需要交40元")
如果这个游乐场因为物美价廉火爆了,也有超过65岁的爷爷奶奶想来刺激一把,咱为了安全考虑需要给他们打印一条特殊提示,这时候你会怎么写?
再加一个elif?没错,重点是怎么加
有同志说我可以这样加
age = 20
if age < 4:print("小朋友不用缴费")
elif age < 18:print("您需要交25元")
elif age <= 25:print("您需要交30元")
elif age > 65:print("您辛苦了,进园每隔500米配置有凉亭及工作人员,如您感到不适,本园的工作人员将会为您提供帮助")
else :print("您需要交40元")
有问题吗?没问题,但不够优雅。如果是我,我会酱紫写(如下)
age = 20
if age < 4:print("小朋友不用缴费")
elif age < 18:print("您需要交25元")
elif age <= 25:print("您需要交30元")
elif age < 65:print("您需要交40元")
elif age >=65:print("您辛苦了,进园每隔500米配置有凉亭及工作人员,如您感到不适,本园的工作人员将会为您提供帮助。")
我们发现,else这个替补队员不见了,实际上在python中else是可以不存在的,这告诉我们一个道理:舔狗舔到最后一无所有。
4.2.4 多条件测试
if-elif-else结构功能强大,但仅适合用于只有一个条件满足的情况:遇到通过了的测试后,python就跳过余下的测试。然而我们常常会遇到多条件的情况:多个条件同时考虑,这时候应该使用一系列不包含elif和else代码块的简单if语句。
例如:假设你经营着一家比萨店,如果客人点了两种配料,就需要确保在其比萨中含有这些配料。
Pizza_Shop=['mushrooms','extra cheese']
if 'mushrooms' in Pizza_Shop:print("adding mushrooms.")
if 'pepperoni' in Pizza_Shop:print("adding pepperoni.")
if 'extra cheese' in Pizza_Shop:print("adding extra cheese.")
print("\nFinished making your pizza")
'''
adding mushrooms.
adding extra cheese.Finished making your pizza
'''
以上代码如果使用if-elif-else的结构的话将不能正常运行。
4.2.5 例题
通过结合使用if语句和列表,可以完成一些有趣的任务。
1.检查特殊元素
继续前面的比萨店示例,那位客人想要pepperoni,可是我们pepperoni已经没有了,我们该怎么提醒顾客呢?
参考:
Pizza_Shop=['mushrooms','extra cheese','pepperoni']
for Pizza_Shop in Pizza_Shop:if Pizza_Shop == 'pepperoni':print("Sorry, this food ingredient is out of stock")else:print(f"adding {Pizza_Shop}.")
'''
adding mushrooms.
adding extra cheese.
Sorry, this food ingredient is out of stock
'''
2.确定列表不是空的
在上一题条件’pepperoni已经没有了’不变的情况下,如果客人不想加任何配料呢,也就是Pizza_Shop=[ ],这时如何处理?
参考:
Pizza_Shop=[]
if Pizza_Shop == 'pepperoni':for Pizza_Shop in Pizza_Shop:print("Sorry, this food ingredient is out of stock")print(f"adding {Pizza_Shop}.")
else:print("Are you sure you want plain pizza?")#询问顾客是否只要原味比萨
#Are you sure you want plain pizza?
3.使用多个列表
假如顾客想要[‘mushrooms’,‘extra cheese’,‘pepperoni’,‘French fries’]这些配料,但是你的店里只有[‘mushrooms’,‘extra cheese’]这些东西,请检查顾客想要的配料是否是比萨店供应的配料,再决定是否在比萨中添加它。
Customer_wants=['mushrooms','extra cheese','pepperoni','French fries']
Pizza_Shop=['mushrooms','extra cheese','pepperoni']
for Pizza_Shop in Pizza_Shop:if Pizza_Shop in Customer_wants:print(f"adding {Pizza_Shop}.")else:print(f"sorry, we don't have {Customer_wants}.")
print("\nFinished making your pizza")
'''
adding mushrooms.
adding extra cheese.
adding pepperoni.Finished making your pizza
'''
5、 字典是什么?
字典在现实中是给定一个特定的词,然后进行词义拓展及延伸,词与词义存在着一种对应关系。Python中的字典也如此,给定一个键,然后进行键的拓展或延伸(值),这种称为键值对。字典由无数个键值对组成,每个键都与一个值相关联。你可以使用键来访问相关联的值,与键相关联的值可以是数、字符串、列表乃至字典。事实上,可以将任何python对象用作字典的值。
一个简单的字典
来看一个包含外星人的游戏,这些外星人的颜色和分数各不相同。下面是一个简单的字典,存储了有关特定外星人的信息。
alien_0={'color':'green','points':'5'}
print(alien_0['color'])
print(alien_0['points'])
'''
green
5
'''
使用字典
在python中,字典用放在花括号{ }中的一系列键值对表示,如前面的示例所示:
alien_0={'color':'green','points':'5'}
键值对是两个相关联的值。指定键时,python将返回与之相关联的值。键和值之间用冒号分隔(如’color’:‘green’),而键值对之间用逗号分隔(如上述alien_0代码)。在字典中,想存储多少个键值对都可以。不过键必须是唯一的,如字符串,数字。但值不必,值可以取任何数据类型。
字典的形式大抵如下:
变量名={'键1':'值1','键2':'值2',......,'键n':'值n'}
但倘若值是数字的话,不必加 ’ ’ ,eg:
name={'键1':123,'键2':45.6,'键n':123, 98.6: 37}
print(name[98.6])
#37
注意: 变量名不建议命名为 dict, 'dict '是 Python 的关键字和内置函数。
创建字典
1、使用大括号 { } 创建空字典:
#使用{}创建空字典
name = {}
#打印字典
print(name)
#查看字典数量
print(len(name))
#查看字典类型
print(type(name))
#结果
'''
{}
0
<class 'dict'>
'''
2、用内置函数dict来创建字典
name = dict()
#打印字典
print(name)
#查看字典数量
print(len(name))
#查看字典类型
print(type(name))
#结果
'''
{}
0
<class 'dict'>
'''
简而言之,dict()内置函数就是用来创建一个字典
访问和添加键值对
以外星人游戏为例
1、如何访问键值对
访问格式:字典名[‘需要访问的值的键’]
‘color’:‘green’ 这里的’color’就是键,‘green’是值,’:'用冒号分隔,连起来就是键值对。
alien_0={'color':'green','points':'5'}
print(alien_0['color'])
#green
2、如何添加键值对
添加格式:字典名[‘需要添加的键’]=‘需要添加的值’
alien_0['height']='20px'
print(alien_0)
#输出结果为 {'color': 'green', 'points': '5', 'height': '20px'}
使用字典来存储用户提供的数据或在编写能自动生成大量键值对的代码时,通常需要先定义一个空字典,然后添加键值对。
aline_0={}
alien_0['height']='20px'
alien_0['color']='green'
alien_0['points']='5'
print(alien_0)
#{'color': 'green', 'points': '5', 'height': '20px'}
修改和删除键值对
1、如何修改键值对的值
修改格式:字典名[‘键名’]=‘修改后的值’
eg:把外星人的颜色改成蓝色(外星人之前我们定义时是绿色的)
alien_0['color']='blue'
print(alien_0)
#运行结果 {'color': 'blue', 'points': '5', 'height': '20px'}
2、如何删除键值对
删除格式: del 字典名[‘需要删除的键’]
注意:只需要指定键,键值对会一并删除,并且是永久删除。
del alien_0['height']
print(alien_0)
#运行结果 {'color': 'blue', 'points': '5'}
由类似对象组成的字典
当字典量需求较大时,可以使用以下方法:
字典名 = {
[空格]*4 键值对(英文逗号)
[空格]*4 键值对(英文逗号)
[空格]*4 }
如下:
languages={'jen':'python','sarah':'c','edward':'ruby','phil':'python',}
使用get()来访问值
有时我们会遇到没有查到键值对的情况,此时系统会报错。为了避免系统报错,我们可以使用get()来访问值。
方法get()在指定的键不存在时返回一个默认值。
访问格式:
变量=字典名.get(‘键’,‘默认值’)
a={'color': 'blue', 'width': '500px'}
b=a.get('height','have not this')#如果字典中有'height'这个值,将获得与之相关联的值
print(b)
#运行结果是have not this
注意: 调用get()时,如果没有指定第二个参数且指定的值不存在,python将返回None。这个特殊值表示没有相应的值,None并非错误,而是一个表示所需值不存在的特殊值。
遍历字典
说到遍历,就不得不提到我们的好朋友for循环了,由于键值对中有一个键一个值,故取两个变量为其储存。除了for循环外,还要用到方法items(),方法items()返回一个键值对列表。
看例子:
languages={'jen':'python','sarah':'c',}
for key,value in languages.items():print(f"\nKey:{key}")print(f"\nValue:{value}")
'''
Key:jenValue:pythonKey:sarahValue:c
'''
遍历字典中所有键
在python中,遍历字典时会默认遍历所有的键,故直接遍历即可。但非要指定个什么方法的话,可用keys()。
languages={'jen':'python','sarah':'c',}
for key in languages().keys():print(f"\nKey:{key}")
'''
Key:jenValue:pythonKey:sarahValue:c
'''
相信有的同志已经复制代码跑一下了,也有眼尖的同志发现了这代码不对劲。
让我们跑一下看看发生什么事了
报错:
<module>for key in languages().keys():TypeError: 'dict' object is not callable
我来翻译一下哈
<报错模块>for key in languages().keys():#也就是说这地方出错了
类型错误:“dict”对象不可调用
原因:languages是一个字典对象,而在调用其keys()方法时使用了函数调用的括号,导致解释器将其当做函数调用,因此抛出了TypeError: ‘dict’ object is not callable的异常。应该将第3行改为for key in languages.keys():,即去掉括号。这样就能正确地遍历字典的键了。
TypeError: ‘dict’ object is not callable通常是由什么导致
这个错误通常由
1、将一个不可调用的对象(如字典、列表等)当作函数来调用所导致的。
2、在代码中使用了类似于函数调用的语法,但是被调用的对象并不是一个函数,而是一个字典或其他类型的对象。
3、这种错误也可能出现在尝试调用不支持调用操作的对象上。
TypeError: ‘dict’ object is not callable普遍解决方法
1、检查代码,看看是否正确使用括号之类的。如我们刚刚报错的那个代码,就是由于多加了一个括号,在代码中使用了类似于函数调用的语法才导致错误。
2、若还是没解决就查看一下被调用的函数类型是否支持被调用。
正确代码
languages={'jen':'python','sarah':'c',}
for key in languages.keys():print(f"\nKey:{key}")
'''
Key:jenKey:sarah
'''
在讲类型错误前我们讲过——在python中,遍历字典时会默认遍历所有的键,直接遍历输出将不变。
languages={'jen':'python','sarah':'c',}
for key in languages:print(f"\nKey:{key}")
'''
Key:jenKey:sarah
'''
遍历字典中的所有值
如果想要遍历字典中所有的值,可以使用values()来返回一个值列表,不包含任何键。
languages={'jen':'python','sarah':'c','edward':'ruby','phil':'python',}
for language in languages.values():print(language.title())
但是这种方法没有考虑到里面的值是否重复,因此为剔除重复项可以使用集合set,集合中的每一个值都是独一无二的。
languages={'jen':'python','sarah':'c','edward':'ruby','phil':'python',}
for language in set(languages.values()):print(language.title())
对于集合set,也可以用花括号直接创建
languages={'python','ruby','python','c'}
print(languages)
#{'c', 'ruby', 'python'}
集合与字典很像,都是用{ }创建的,不同的是集合里没有键值对。
集合与列表也很像,不同的是列表是用[ ]创建的。
不同于列表和字典,集合不会以特定的顺序存储元素。
嵌套
有时候需要将一系列字典储存在列表中,或将列表储存在字典中,这称为嵌套。
在字典中存储列表
将字典嵌套在列表里,以外星人为例,字典alien_0包含一个外星人中所有的信息,alien_1,alien_2同理。
#创建三个外星人字典
alien_0={'color':'green','points':5}
alien_1={'color':'blue','points':10}
alien_2={'color':'red','points':15}
#将字典存储在列表中
aliens=[alien_0,alien_1,alien_2]
#循环aliens列表,将每个外星人的信息赋给alien,并打印出来
for alien in aliens:print(alien)
'''
{'color': 'green', 'points': 5}
{'color': 'blue', 'points': 10}
{'color': 'red', 'points': 15}
'''
把列表存储在字典里
以四个好兄弟ヽ( ̄ω ̄( ̄ω ̄〃)ゝ最喜欢的语言为例。
#创建最喜欢的语言的字典
favorite_languages={'jen':['python','ruby'],'sarah':['c'],'edward':['ruby','c'],'phil':['python','haskell'],
}
#设置两个变量来分别存储好兄弟的名字和他们分别最爱的语言,并以键值对的形式打印出来
for name,favorite in favorite_languages.item():print(f"\n{name.title()}'s favoirte languages are:")for language in languages:print(f"\t{language.title()}")
'''
Jen's favoirte languages are:PythonRubySarah's favoirte languages are:CEdward's favoirte languages are:RubyCPhil's favoirte languages are:PythonHaskell
'''
在字典中存储字典
假如张三邀请李四去洗脚城洗脚被抓,张三对李四说:“兄弟,别怕,警察没有证据。”这时警察邪魅一笑,拿出电脑记录,两人大吃一惊!这!
users={'张三':{'first':'Zhang','last':'San','technician':1,},'李四':{'first':'Li','last':'Si','technician':2,},}
#设置两个变量来分别存储用户名和用户信息,并以键值对的形式打印出来
for username,user_info in users.items():#打印用户名print(f"\n姓名:{username}")#将姓和名连接起来full_name=f"{user_info['first']}{user_info['last']}"technician=user_info['technician']print(full_name.title())print(f"{username}点的{technician}号技师")
'''
姓名:张三
Zhangsan
张三点的1号技师姓名:李四
Lisi
李四点的2号技师
'''
这原来是用python字典储存的两人洗脚的证据,上面清清楚楚的记录着两人的姓名和点的技师,啊!python字典的魅力真大!
注:请正规洗脚。
6、用户输入
还是张三带着李四去洗脚被抓了,警察将这两位请进局里喝茶,然后将他们的名字录入系统,利用python如何实现呢?
用input()
#输入(“请输入你的名字:”)python在执行这句话时会停下来让你输入名字
name=input("Please enter your name:")
#Please enter your name:
#这时你可以在冒号后面输入信息,也就是你的名字张三
#Please enter your name:张三
#event同理,输入(“你做了什么:”)
event=input("What have you done:")
#张三带李四去洗脚了
print(f"你叫{name}你{event}了")
'''
Please enter your name:张三What have you done:带李四去洗脚
你叫张三你带李四去洗脚了
'''
警察除了需要知道张三和李四的名字和所犯何事,还需要知道他们的年龄一类,如:
age=input("tell me your age:")
#在张三输入年龄后,程序才开始下一步指令。
#如果张三大于18岁,就欢迎他来到这里
if age >=18:print("welcome here")
#否则就告诉他,他要去少管所
else:print("Sorry, you should go to the juvenile detention center")
可是这时候看似没问题的代码程序报错了,难道代码运行真的是玄学吗?
咱先看看报错信息
<module>if age >=18:TypeError: '>=' not supported between instances of 'str' and 'int'
#翻译:类型错误:“>=”不支持……(⊙o⊙)…不会译了
简单来说就是输入的年龄不能直接当成数字运算。
这时候int()就登场了。
int()可以帮助我们把文本型数值转化为数字。这下重新输入就不会报错啦
age=input("tell me your age:")
#定义了age之后将其转化为数值类型
age=int(age)
if age >=18:print("welcome here")
else:print("Sorry, you should go to the juvenile detention center")
'''
tell me your age:19
welcome here
'''
小tip:
求模运算符
求模运算符%在处理数值中是个很有用的工具。它将两个数相除并返回余数,你可以借此得知一个数是否为另一个数的倍数。
例如:
3679%27
#输出结果为7
在上面这个例子中可以看出,3679并不是27的倍数,这里3679%27的意思是3679/27=x个27相乘+7=3679,例如4%3=1,10%4=2。当输出结果为0时才是倍数,如6%3 输出结果为0。
7、while循环
for循环用于针对集合中的每个元素都执行一个代码块,而while循环则不断运行,直到指定的条件不满足为止。
例如:
num=25 #设置条件变量
while num<=100: #while 条件:print(num) #语句num+=5 #num每一次都+5直到num>100不满足进入循环的条件后退出
'''
25
30
35
...
90
95
100
'''
正如电视剧《开端》那般,既然可以进入循环,那么就一定有可以退出循环的方法。
A、退出循环的方法:
1、 让用户选择退出
假如张三暗恋李四,想跟他表白,但又怕他拒绝,怎么办呢?张三想到了个好办法,他写了一个python程序,在李四上班开电脑时弹出来。这个程序以张三的口吻问李四:“你喜欢我吗?”如果李四说喜欢,那就弹到下一个框内说:“我也喜欢你。”然后结束程序对话。如果李四说的不喜欢,那就弹到下一个框内说:“我不信!”然后继续重复之前的操作,直到张三说喜欢为止。
#提醒李四只要输入yes就可以退出程序
print("enter 'yes' to end the program.")
#张三问:你爱我吗?
ZhangSan="Do you love me:"
#将李四的回答存储在LiSi里
LiSi=""
#如果李四的回答不是yes
while LiSi !='yes':
#则LiSi=input(ZhangSan)也就是那句"Do you love me:"LiSi=input(ZhangSan)#并且输出我不信print("I don't believe it")
#如果李四回答的是yes,则输出我也爱你
print("i love you too!")
可是有小同志就发现了,代码运行到ZhangSan="Do you love me:"这里没有用input,但我们还是可以输入,而且最后的输出会多一条I don’t believe it
enter 'yes' to end the program.Do you love me:no
I don't believe itDo you love me:yes
I don't believe it
i love you too!
先来解决为什么张三那里没有用input我们还是可以在输入框输入信息。(知道的同学可以直接跳过)
咱先来了解一下这段代码的运行流程:先打印print(“enter ‘yes’ to end the program.”),然后将"Do you love me: “存储在ZhangSan这个变量中(注意,这时候是不打印"Do you love me: “的),然后设置空字符串变量LiSi=””。进入while循环中,先判断LiSi是否等于yes,因为这时候还没有打印Do you love me:所以我们还没有输入字符串,所以肯定不等于yes,故继续运行下一句LiSi=input(ZhangSan),这时候Do you love me:才会被打印出来,我们能得以输入,然后重新进行判断。故此,其实不是我们没用input,而是我们自个儿不知道罢了。
再来解决输出多一条的问题。
从上面的流程中我们已经知道,如果我们要在Do you love me:后面输入字符串的话,肯定要先循环一遍while,既然已经循环过一遍了,那I don’t believe it肯定就被打印出来了,也就是所谓的“多一条”。
那如何解决呢?加个if语句利用break就OK了。
2、 使用break退出循环
break非常霸道,它不管测试是否结束,直接停下。
print("enter 'yes' to end the program.")
ZhangSan="Do you love me: "
LiSi=""
while LiSi !='yes':LiSi=input(ZhangSan)#向python说明,如果用户输入了yes就 ** 直接退出while循环 ** 输出我也爱你,否则输出我不信if LiSi =='yes':breakelse:print("I don't believe it")
print("i love you too!")
同for一样,只要是循环都可以嵌套使用。while嵌套for或者if,for嵌套if之类的都OK。倘若是for嵌套while或if嵌套for或while之类的各位小同志可以去尝试一下。
一个小插曲(可以直接跳过):
对于为什么张三那里没有用input我们还是可以在输入框输入信息。 chatGPT告诉了我一个原因,以下是原话: 这是因为命令行解释器可以直接从用户键盘输入获取文本数据,并将其提供给正在运行的程序进行处理。
这……触及到了我的
初看这句话时我很懵,不知道GPT究竟要表达什么……于是乎我去搜了一下命令行解释器是什么。(知道的同志可以直接跳过)
命令行解释器是一个单独的软件程序,它可在用户和操作系统之间提供直接的通讯。命令行解释器是解释器的一种,用于对命令行进行解释执行。
解释器是一种电脑程序,能够把高级编程语言一行一行直接转译运行。解释器不会一次把整个程序转译出来,只像一位“中间人”,每次运行程序时都要先转成另一种语言再作运行,因此解释器的程序运行速度比较缓慢。它每转译一行程序叙述就立刻运行,然后再转译下一行,再运行,如此不停地进行下去。
这是百度上的定义,实话说我看得半懂不懂的,于是又去搜了一些别人的解释,以下为梧桐雪的解释
命令行是用户和操作系统交互输入命令的地方(如windows的cmd和mac的终端),使用的是操作系统的指令;
解释器是用户和python交互的地方,使用的是python语言。
我们在命令行中输入python之后会出现(>>>),这个时候,我们就进入了python解释器了。
在cmd里进入python后可以直接在cmd里使用python,也就是说cmd可以直接从用户键盘输入获取文本数据,并将其提供给python进行处理。
我们可以理解为命令行是一个大城市(操作系统即OS),在这个城市中我们使用普通话(命令行指令)进行交流,而解释器是大城市里面的一个小县城,在这个县城中,我们使用方言(python语言)进行交流。
各位可以去原文看看。原文链接:https://blog.csdn.net/weixin_41855010/article/details/105087184
……GPT这句话的意思是我用命令行进入了解释器,然后输入代码,继而用python处理吗?可我是直接在Spyder里运行的代码呀,我都没在cmd里运行python(博主用的windows系统)。如下图片
难道Spyder的控制台就是一个命令行解释器吗?
小知识:spyder是python的一个简单集成开发环境,通俗的讲,他就是python的一个编辑器。除了Spyder外还有Pycharm和Visual Studio Code等等,想要具体了解的可以阅读以下文章http://t.csdn.cn/6VVDD
另外在python的世界中有python /ipython /cpython /jython以及pypy。这些都是python的解释器,就我目前所知呢,Spyder用的Ipython,pycharm用的cpython,这些解释器的区别可以去看这篇文章http://t.csdn.cn/7ETDO
GPT:Spyder的console不能算作严格意义上的命令行解释器,因为它并不是一个独立的程序,而是Spyder集成开发环境(IDE)中的一个组件。虽然Spyder的console可以接受用户在控制台输入的命令并执行它们,但它不支持像标准命令行界面那样运行系统级别的命令。此外,Spyder的console还提供了许多其他功能,如代码补全、变量查看等,这些功能通常不包括在传统的命令行解释器中。因此,尽管Spyder的console可以用于与Python交互,但它不是一个完整的命令行解释器。
这段话也是GPT告诉我的,实际上我只能确定Spyder里的控制台console是解释器,但是否为命令行解释器我也不知道,对GPT的话存疑。
至此我已经基本确认这句话是一个蒙太奇式谎言,这句话是真的,命令行解释器真的可以直接从用户键盘输入获取文本数据,并真的可以将其提供给正在运行的程序进行处理。
不对的是
GPT在答非所问呐!而且还成功的带偏我了!
我的问题是:为什么张三那里没有用input我们还是可以在输入框输入信息?
GPT:这是因为命令行解释器可以直接从用户键盘输入获取文本数据,并将其提供给正在运行的程序进行处理。
它压根没回答我的问题……
这就相当于我问它西红柿炒鸡蛋怎么炒,它回答我说用不粘锅炒。乍一看没问题,再一看还是没问题,可处处都有问题。
小声哔哔:GPT是真的会一本正经的胡说八道。而如果GPT真的全面推广开来,以这玩意儿的恐怖程度+全民娱乐至死的互联网环境来说,届时互联网到处都是谎言,谎言和真相夹杂在一起,随随便便的造谣就可以毁掉好多普通人的一生。现在还没全面推广开来就因为互联网上的网暴毁了好多人,这些人还有少部分得以沉冤昭雪,等到全面推广开了,到处都是蒙太奇,被毁掉的人这一生就只能白白被毁掉了。
在写下这篇博客的时候,我刷到了一些牛头不对马嘴的帖子,其中给出的链接是捏造的,网页也是PS的,压根搜不到。实际上在目前的一些网页上已经有了看起来像是GPT写的帖子,而且机器人充斥着评论区,这些东西的拥有者随便几句话就可以带歪一个群体的思想,拥有人工智能群体的人可以利用羊群效应轻易控制我们,这让我感觉到有些毛骨悚然。
在这里小声哔哔几句,希望看见的同志在上网时能够擦亮眼睛独立思考,避免掉入从众心理的坑里,其次再提醒一句,虽然人工智能没有思想,但使用它的人有思想,善恶一念间。以上只是个人见解,希望能早日完善相关法律法规,希望那一天到来时是适应了社会发展而非超越社会发展的存在沟通过。
继续我们的python之旅吧。
3、 退出循环最简单的方法
直接退出终端窗口!当然是在你遇到无限循环,而又没有设置break和退出值的时候才阔以介样做了啦,要不然数据丢失了怎么办哇~
B、使用标志
倘若遇到复杂且庞大的程序,导致程序停止的事件就会非常多,仅凭肉眼观察程序是否停止极其困难。此时可以定义一个变量,用于判断整个程序是否处于活动状态,这个变量叫标志。这个标志会在程序中充当红绿灯,当它为TRUE时,程序继续运行,并在任何事件导致标志的值为FALSE时让程序停止。我们只需要检查标志是否为TRUE便可判断整个程序是否处于活动状态。
print("enter 'yes' to end the program.")
ZhangSan="Do you love me: "
LiSi=""
active = True
while LiSi !='yes':LiSi=input(ZhangSan)#向python说明,如果用户输入了yes就 ** 直接退出while循环 ** 输出我也爱你,否则输出我不信if LiSi =='yes':active = Falseelse:print("I don't believe it")
print("i love you too!")
到这里就可能会有同志要问了,这些代码是不是还可以优化?我们直接去掉while语句仅用if试试。
print("enter 'yes' to end the program.")
ZhangSan="Do you love me: "
LiSi=input(ZhangSan)
active = True
if LiSi =='yes':active = False
else:print("I don't believe it")LiSi=input(ZhangSan)
print("i love you too!")
可惜优化虽是优化,但是仅能循环两次,远远达不到张三的要求
enter 'yes' to end the program.Do you love me: no #第一次循环
I don't believe itDo you love me: no #第二次循环
i love you too!#直接输出i love you too!
如何优化,交给在座的各位。
C、在循环中使用continue
continue可以从头到尾执行程序,直到不能执行为止。
num=0
while num < 10:num+=1if num % 2 ==0:continueprint(num)
'''
1
3
5
7
9
'''
在这段代码里continue仅仅会结束符合num % 2 ==0条件的循环,并不影响其他循环。
D、使用while循环处理列表和字典
for循环是一种遍历列表的有效方式,但不应在for循环中修改列表,否则将导致Python难以跟踪其中元素。要在遍历列表的同时对其进行修改,可使用while循环。通过将while循环同列表和字典结合起来使用,可收集、储存并组织大量输入,供以后查看和显示。
说简单些就是,一般不要在for循环里进行直接修改列表之类的操作,若想在遍历列表时修改元素的话,可以利用while辅助修改。具体请看如下。
1、 在列表之间移动元素
倘若李四同张三决裂,张三一气之下打算跟八个女的结婚不扯证,那张三如何确定跟八个女生中的哪个结了婚呢?也就是说,把八个女生按照字母排序,结完上一个结下一个,把还未结婚的放在一个表里,已经结完的放在一个表里,把还未结婚的一个一个结,结完的放在已经结完的表里,如何做呢?
#首先先创造两个表,一个还未结婚的,一个结完婚的
marrying = ['A','B','C','D','E','F','G','H']
married = []
while marrying:marry = marrying.pop()married.append(marry)
#显示所有已经结完婚的对象
print(married)
有聪明的同志发现了一个问题
marry = marrying.pop()
married.append(marry)
把这两句代码结合起来不是更方便吗?
让我们结合起来看看
marrying = ['A','B','C','D','E','F','G','H']
married = []
while marrying:married = marrying.pop()
print(married)
#运行结果只剩个A了,所以不行呀
2、 删除为特定值的所有列表元素
如果张三一个不注意,在与其结婚的那八个人中,有四个是姐妹(ABCD),为了不让她们发现彼此的存在,只好不同她们结婚,想要同时把她们从married删去,该怎么做呢?while可以帮助张三删除为特定值的所有列表元素(这里把BCD换成A)。
married = ['H', 'G', 'F', 'E', 'A', 'A', 'A', 'A']
while 'A' in married:married.remove('A')
print(married)
'''
['H', 'G', 'F', 'E']
'''
使用用户输入来填充字典
假如张三正打算同别人结婚时,李四前来阻止,李四还爱着张三,张三见李四回心转意故把那八个女孩全甩了(其中张三只跟EF结了婚,GH还没结)。八个女孩中的老大A知道真相后,打算结合其她姐妹把张三暴揍一顿,请问如何让屏幕前的观众告诉A其她几个女孩是谁,并且是否跟张三结过婚?
#先创建一个空字典
names = {}
#设置标志方便查看程序还在进行
active = Truewhile active:#告诉老大A有几个女孩,并且同张三是否结过婚name = input("Please tell me the names of several other girls:")married = input("Has she ever married Zhang San(married/marrying):")#将数据存储在字典内names[name]=married#询问是否还有别的女孩,如果还有,则继续输入,若无,则结束程序打印名单other = input("May I ask if there are any more?(yes/no):")if other == 'no' :active = False
print(f"\n{names}")
程序最后跑出来的结果
Please tell me the names of several other girls:EHas she ever married Zhang San(married/marrying):marriedMay I ask if there are any more?(yes/no):yesPlease tell me the names of several other girls:FHas she ever married Zhang San(married/marrying):marriedMay I ask if there are any more?(yes/no):yesPlease tell me the names of several other girls:GHas she ever married Zhang San(married/marrying):marryingMay I ask if there are any more?(yes/no):yesPlease tell me the names of several other girls:HHas she ever married Zhang San(married/marrying):marryingMay I ask if there are any more?(yes/no):no{'E': 'married', 'F': 'married', 'G': 'marrying', 'H': 'marrying'}
8、函数
我想了半天该怎么衔接这一章节的知识……算了,不衔接了。
函数相当于是带名字的代码块,用于完成具体的工作。要执行函数定义的特定任务,可调用该函数。需要在程序中多次执行同一项任务时,无须反复编写完成该任务的代码,只需要调用执行该任务的函数,让python运行其中的代码即可。
举个小栗子儿~
以下函数叫张三,一旦调用他,他就会说我爱李四。
def ZhangSan():print("i love LiSi")
ZhangSan()
"""i love LiSi"""
1、此处使用了def 向python指出了函数名ZhangSan(),这是函数定义。
2、在圆括号内()可以指出函数为完成任务需要什么样的信息。在这里,因为不需要什么信息就能完成工作,故括号里是空的。
3、定义以冒号:结尾。
4、在冒号后所有缩进行构成了函数体
5、可以看出最后i love LiSi这里我并没有向平常一样用#而是三引号"“” 文档 “”",这个也可以注释。
代码行print(“i love LiSi”)是函数体内唯一一行代码,因此函数ZhangSan()只做一项工作,那就是打印i love LiSi。
6、要调用这个函数,直接输入函数名即可。
简要总结一下
def 函数名:""" 注意:函数名一定带有圆括号() """代码块(缩进的都是函数体)
函数名(函数调用)
向函数传递信息
那说了在函数名的括号里传递信息,传递什么信息咯。
举个栗子,假如李四看见了刚才的代码,python打印的是
i love LiSi,可是李四不能确定是谁给他打印的这条消息,万一他以为是钻石王老五给他的讯息呢?那张三不白瞎啦,故有以下代码
def ZhangSan(name):print(f"{name} love LiSi")
ZhangSan('ZhangSan')
"""ZhangSan love LiSi"""
name就是我们需要传递的信息,通过在括号里添加name,可让函数接受俺们给name指定的任何值,也就是调用函数时的(‘ZhangSan’),这里的name可以是张三,也可以是ZhangSan,还可以是ZS,可以随便赋。
调用函数时,无论传入什么名字,都将生成相应的输出。
实参和形参
在以上函数传递信息那里,函数名里的name就是形参,顾名思义,形式上的参数,即函数完成工作所需的信息。在调用函数时,括号里的参数ZhangSan是实参,顾名思义,实际的参数,即调用函数时传递给函数的信息。举个栗子,图书馆占位,大家一般喜欢用一本书占位子,也就是告诉别人这个位置有人了,这里的书就是形参,python里的形参就相当于那本书,告诉python这里占个位儿。等人来了,人就是实参,也就是这个位置确确实实有人了。
传递实参
函数定义中可以包含多个形参,因此在函数的调用中也可能包含多个实参。向函数传递实参的方法有很多,如下:
1、位置实参
2、关键字实参
3、使用字典和列表
1、位置实参
在调用函数时,每个实参都必须对应每个形参,因此,基于形参实参顺序位置的关联方式是最简单的。
举个栗子:
def love(name,lover):print(f"my name is {name}")print(f"i love {lover}")
love('ZhangSan','LiSi')
"""
my name is ZhangSan
i love LiSi
"""
使用位置实参这种关联方式时,一定要注意顺序,顺序不同,所得出的结果就不同。
def love(name,lover):print(f"my name is {name}")print(f"i love {lover}")
love('LiSi','ZhangSan')
'''
my name is LiSi
i love ZhangSan
'''
事实上呢,咱也不知道李四到底爱不爱张三,咱也不知道,咱也不敢问呐。对于张三来说大抵就是:等到世界颠倒你会来爱我~
对于位置实参,咱也可以多次调用哈
def love(name,lover):print(f"my name is {name}")print(f"i love {lover}")
love('朱一龙','苦瓜打怪兽')
'''
my name is 朱一龙
i love 苦瓜打怪兽
'''
想调用多少次就调用多少次,每一次的人都不一样。
这时候就有同志会问,如果我不想在意顺序怎么传递实参呢?
2、关键字实参
如果不想受到顺序之类的束缚,那就直接指定我传的这个实参是哪个形参的呗。
def love(name,lover):print(f"my name is {name}")print(f"i love {lover}")
love(lover='苦瓜打怪兽',name='朱一龙')
'''
my name is 朱一龙
i love 苦瓜打怪兽
'''
你看,即使顺序不同,程序也还是按照正确的方向运行了。
这里因为直接在实参中将名称和值关联起来,所以向函数传递实参时不会混淆。
3、默认值
想象以下情景,如果只有形参没有传递实参会怎么样呢?
Let me try try
def ZhangSan(name):print(f"{name} love LiSi")
ZhangSan()
'''
报错信息:
TypeError: ZhangSan() missing 1 required positional argument: 'name'
类型错误:ZhangSan()缺少1个必需的位置参数:'name'
'''
所以说实参是必不可少,如果有时候真的没有实参可以使用默认值。
在编写函数时,可以给每个形参都指定默认值,在给形参指定了实参后,python会使用实参,若没有指定实参,则使用默认值,避免不必要的报错。
倘若爱苦瓜打怪兽的人很多,我们就可以把苦瓜打怪兽设置成默认值,这样的话可以只传递一个实参
def love(name,lover='苦瓜打怪兽'):print(f"my name is {name}")print(f"i love {lover}")
love(name='朱一龙')
'''
my name is 朱一龙
i love 苦瓜打怪兽
'''
在这里python依然将这个实参视为位置实参,实参自动匹配到第一个形参。倘若把两个形参的位置调换会发生什么呢?
def love(lover='苦瓜打怪兽',name):print(f"my name is {name}")print(f"i love {lover}")
love(name='朱一龙')
'''
SyntaxError: non-default argument follows default argument
语法错误:默认参数后面跟着非默认参数
'''
python不允许默认参数后跟着非默认参数,即使是以下情景
def love(lover='苦瓜打怪兽',name):print(f"my name is {name}")print(f"i love {lover}")
love(lover='朱一龙')
亦或以下场景
def love(data,lover='苦瓜打怪兽',name):print(f"today is {data}")print(f"my name is {name}")print(f"i love {lover}")
love(data='sunday',name='朱一龙')
都是错误的。
但是可以这样
def love(data,lover='苦瓜打怪兽',name='LiSi'):print(f"today is {data}")print(f"my name is {name}")print(f"i love {lover}")
love(data='sunday',name='朱一龙')
'''
today is sunday
my name is 朱一龙
i love 苦瓜打怪兽
'''
还阔以酱紫
def love(data,lover='苦瓜打怪兽',name='朱一龙'):print(f"today is {data}")print(f"my name is {name}")print(f"i love {lover}")
love('sunday')
'''
today is sunday
my name is 朱一龙
i love 苦瓜打怪兽
'''
酱紫
def love(data,lover='苦瓜打怪兽',name='LiSi'):print(f"today is {data}")print(f"my name is {name}")print(f"i love {lover}")
love('sunday','ZhangSan')
'''
today is sunday
my name is LiSi
i love ZhangSan
'''
位置实参、关键字实参以及默认值阔以混合使用,调用时也可以混合调用,其函数调用是等效的。但是注意使用默认值时,必须先在参数列表中列出没有默认值的形参,再列出有默认值的实参,好让python能够正确地解读位置实参。
返回值
1、返回简单值
函数在处理数据时,返回的一个或一组值称为返回值。在函数中可使用return语句将值返回到调用函数的代码行。返回值能够将程序的大部分繁重工作移入函数中去完成,从而简化主程序。
def name(first_name,last_name):#首先先声明函数
#这个函数描述了返回一个完整的名字并大写首字母full_name=f"{first_name} {last_name}"return full_name.title()
#调用有返回值的函数时,需要提供一个变量
lover=name('Zhang','San')
print(lover)
#Zhang San
调用返回值的函数时,需要提供一个变量,以便将返回的值赋给它,如若没有的话,python会默认咱没写完。
虽然说在这里看起来好像比之前更麻烦了,之前只需要name(‘Zhang’,‘San’)就行,现在却多了这么多步骤。但其实如果是需要大量分别存储名和姓的程序中,这里只需要调用函数就行,就会比较方便。
2、让实参变成可选的
假如李四在张三和王老五之间摇摆不定,就上一小节我们名字的例子,让实参变成可选的,我们该怎么做呢?
可使用默认值
#声明函数,给形参middle_name指定一个空的默认值
def name(first_name,last_name,middle_name=''):
#并且在用户没有提供中间名时不使用这个形参if middle_name:#如果middle_name=true,则使用中间名full_name=f"{first_name} {middle_name} {last_name}"else:#如果middle_name=false,则不使用full_name=f"{first_name} {last_name}"return full_name.title()#返回一个完整的名字
lover=name('Zhang','San')
print(lover)
lover=name('wang','lao','wu')
print(lover)
'''
Zhang San
Wang Wu Lao
'''
在函数体中,python将非空字符串解读为true,因此如果函数调用中提供了中间名,if middle_name将为true。
问题:为什么想让实参变成可选的就需要指定一个空的默认值呢?
这里以middle_name为例,设置了空的默认值利用if语句判断是否为true,以此达到让参数变成可选的目的。
3、返回字典
函数可以返回任何类型的值,包括列表与字典等较为复杂数据。
def name(first_name,last_name):person = {'first':first_name,'last':last_name}return person
lover = name('Zhang','San')
print(lover)
#{'first': 'Zhang', 'last': 'San'}
和上一小节的知识点连接,向字典里添加张三的年龄,怎么添加呢?
def name(first_name,last_name,age=None):person={'first':first_name,'last':last_name}if age: #如果age是trueperson['age']=age #则键'age'就等于agereturn person
lover = name('Zhang', 'San',25)
print(lover)
在条件测试中none相当于false,相当于空值。
4、结合使用函数和while循环
可将函数同本书前面介绍的任何python结构结合起来用。
举个栗子:尝试使用名和姓跟用户打招呼
#有两个名字的,也有三个名字的,为了照顾到更多人,需要选择是否要中间名
def name(first_name,last_name,middle_name=None):if middle_name:full_name=f"{first_name} {middle_name} {last_name}"else:full_name=f"{first_name} {last_name}"return full_name.title()
#开始循环,主要是让用户自己说出自己的名字
while True:print("Please tell me your first name and last name")print("Enter 'exit' to exit the program")f_name=input("first name:")if f_name == 'exit':breakm_name=input("middle_name:")l_name=input("last_name:")#在程序结尾设置一个input可以提升用户使用的舒适感ex=input("Do you want to exit now(exit/no):")if ex == 'exit':break
lover = name(f_name,l_name,m_name=None)
print(f"hello {lover}")
在以上代码中我犯了一个小错误,有人发现吗?
揭晓答案吧
以下是正确答案
def name(first_name,last_name,middle_name=None):if middle_name:full_name=f"{first_name} {middle_name} {last_name}"else:full_name=f"{first_name} {last_name}"return full_name.title()
while True:print("Please tell me your first name and last name")print("Enter 'exit' to exit the program")f_name=input("first name:")if f_name == 'exit':breakm_name=input("middle_name:")l_name=input("last_name:")ex=input("Do you want to exit now(exit/no):")if ex == 'exit':break
lover = name(f_name,l_name,m_name)
print(f"hello {lover}")
'''
运行结果:
两个名的
Please tell me your first name and last name
Enter 'exit' to exit the programfirst name:zhangmiddle_name:last_name:sanDo you want to exit now(exit/no):exit
hello Zhang San
'''
'''
三个名的
Please tell me your first name and last name
Enter 'exit' to exit the programfirst name:wangmiddle_name:laolast_name:wuDo you want to exit now(exit/no):exit
hello Wang Lao Wu
'''
在开始时我们已经设置了middle_name的默认值,但在最后lover那儿我们又设置了一遍,在input那儿又输入了一次middle_name(回车也算)python搞不清楚这个值究竟取谁肯定会报错啦,即使值是一样的,也是会报错滴~
传递列表
函数可以提高列表的处理效率,将列表传递给函数后,函数就能直接访问其内容。
举个栗子:假如李四发现了张三之前的情人,打算一个一个的跟张三以前的情人打招呼,用python怎么实现?
def lovers(names):for name in names:print(f"hello {name}!")
lovernames = ['A','B','C','D','E']
lovers(lovernames)
'''
hello A!
hello B!
hello C!
hello D!
hello E!
'''
在函数中修改列表
将列表传递给函数后,函数就可以对其修改,而且这种修改是永久性的。
让我们回顾一下张三同八个女生结婚的事:倘若李四同张三决裂,张三一气之下打算跟八个女的结婚不扯证,那张三如何确定跟八个女生中的哪个结了婚呢?也就是说,把八个女生按照字母排序,结完上一个结下一个,把还未结婚的放在一个表里,已经结完的放在一个表里,把还未结婚的一个一个结,结完的放在已经结完的表里,如何做呢?为了简化,我们就只跟ABCD结婚。
marrying=['A','B','C','D']
married=[]
while marrying: #假如marrying为true,这里marrying本来就为truemarry = marrying.pop()married.append(marry)
print(married)
在以上代码中,我们如何写在函数里并在函数中修改列表呢?
如下
def lover(marrying,married):while marrying:marry = marrying.pop()married.append(marry)print(married)
marrying=['A','B','C','D']
married=[]
lover(marrying,married)
#['D', 'C', 'B', 'A']
有了函数后,我们只需要修改数据调用函数即可。
但是这样做会出现一个问题,如下代码和运行结果
def lover(marrying,married):while marrying:marry = marrying.pop()married.append(marry)print(married)
marrying=['A','B','C','D']
married=[]
lover(marrying,married)
print(marrying)
'''
['D', 'C', 'B', 'A']
[]
'''
我们可以发现,列表被修改了,如果不想修改列表,但是又要达到目的该怎么办呢?很简单,在调用函数时加个切片[:]就可以了,这样被修改的就是列表的副本而非列表。
def lover(marrying,married):while marrying:marry = marrying.pop()married.append(marry)print(married)
marrying=['A','B','C','D']
married=[]
lover(marrying[:],married)
print(marrying)
传递任意数量的实参
在很多时候,我们预先并不知道函数需要接受多少个实参,这时候就可以用星号 " * " 创建一个空元组,并将收到的所有值都封装到这个元组中。怎么用呢?举个栗子!
来细细数一数张三有多少个情人
def ZhangSan(*zs):print(zs)
ZhangSan('A')
ZhangSan('A','B','C','D')
'''
('A',)
('A', 'B', 'C', 'D')
'''
看,zs就是空元组的名字,*是创建空元组的标志,由此我们可以看出无论是一个实参还是多个实参,只要有空元组python都可以吸收,实际上这些实参被封装到了一个元组中(这里的元组就是zs)。
将函数存储在模块中
使用函数的优点之一是将代码块与主程序分离。实际上还可以更进一步,将函数存储在称为模块的独立文件中,再将模块导入(import)到程序中。
在软件工程中,耦合度是指系统中组件之间相互连接的程度。在 Python 中,耦合通常指两个或多个模块之间的依赖关系。如果一个模块依赖于另一个模块,那么这两个模块就是紧密耦合的。这种紧密耦合会导致修改一个模块时需要修改依赖它的模块,这往往会增加代码的复杂度和维护成本。相反,如果两个模块之间的依赖关系很少或者没有,那么它们就是松散耦合的。这种松散耦合可以提高程序的可重用性、可维护性和可扩展性。因此,Python 程序员通常会尽量减少模块之间的耦合程度,以提高代码的质量和可维护性。
在耦合度高的代码山中,常常牵一发而动全身。
1、导入模块
先了解一下模块的概念。
依我自个儿的理解呢,模块相当于一个更高级的函数。
来看看官方解释
离散的程序单位。且对于编译、与其他单位相结合和装入来说是可标识的,或者程序中能从逻辑上分开的一个部分。
来源:《计算机科学技术名词 》 (第三版)
再来看看GPT的解释
模块是指将代码分成一个个独立的部分,每个部分都有自己的功能,并且可以被其他程序或脚本调用和重用的一种编程方式。在许多编程语言中,模块被用于组织代码、减少重复代码、提高代码的可重用性和可维护性。例如,在Python中,模块是一个包含Python代码的文件,可以通过import语句在其他Python程序中使用它。
网友的解释
大型软件系统中的一个具有独立功能的部分。
来源:https://cidian.hwcha.com/mbgggzbe.html
由此可以总结出模块的几个特点
1、是一个离散的单位(离散:数值只能用自然数或整数单位计算的数据。也就是说是一个整数单位,要么就是一个模块,要么就是两个,不可能1.5个)
2、可标识(就是有名字,可以通过import利用模块名字将其导入我们正在写的程序中)
3、能从逻辑上分开。(就是有独立功能嘛)
其实就是一个高级一点的函数嘛,若要究其区别呢,就是一个函数的集大成者?小声哔哔:这些专业书籍真的很喜欢把简单的东西复杂化诶(可能只是我不懂吧)
进入正题。
先来创建一个模块
点击左上角file(文件),然后会弹出来一个 new file(新文件)意思是说创建一个新文件,点击它,你就会得到一个.py为后缀的文件(这里我新建的模块名叫 untitled3 )。
用我们之前的写的函数放进我们新建的模块 untitled3.py 里,保存好。
这里有个地方需要注意
点击保存时(我圈起来的地方就是保存)需要注意下面的那个地址和你编写代码的主要文件(这里是temp.py,我在这里面编代码)的保存地址是一样的,否则会报错,报错信息如下。
ModuleNotFoundError: No module named 'temp'
#模块找不到错误:没有名为“temp”的模块
注意地址,两个文件前面的地址一模一样。
2、导入特定的函数
还可以导入模块中的特定函数,这种导入方法的语法如下,以untitled3模块里的ZhangSan函数为例
#导入特定函数的语法为
#from module_name import function_name
#如果是想导入多个函数的话,函数名间用逗号,隔开
#from module_name import function_0,function_1,function_2
from untitled3 import ZhangSan
ZhangSan('a','b','c')
除了导入模块/特定的函数,也可以导入所有的函数:使用星号(*)即可,其语法如下
from module_name import *
但是代入所有函数的时候需要注意:星号让python将模块中的所有函数都复制覆盖到这个程序文件中,如果在本文件中有函数的名称和模块中的函数名称重名冲突了,星号会让模块中的函数覆盖到此文件原有的函数上,所以用星号需要慎重。
3、使用as指定别名
如果要导入的函数和本文件中的函数名称有所冲突,可以使用as给模块中的函数指定别名,以避免这种冲突。
from untitled3 import ZhangSan as zs
zs('a','b','c')
还可以给模块指定别名使代码更简洁
import untitled3 as ut
ut.ZhangSan('a','b','c')
函数编写指南
在编写函数时应遵循以下规则,否则容易被别的程序员揍。
1、应给函数指定描述性名称,叫人望文生义。
2、在给函数以及模块命名时,记得使用驼峰命名法。
3、每个函数都应该包含简要地阐述其功能的注释,该注释紧紧跟在函数定义的后面,并采用文档字符串格式。(这一条我也没遵守,我是跟着书打的字,以书为准。文档字符串是(“”" 文档 “”")这个样子的)
4、给形参、实参指定默认值时,等号两边不要有空格。
def name(first_name,last_name,middle_name=None):
#你看,我就没有空格
5、程序和模块包含多个函数时,可使用两个空格将相邻函数分开,这样看得更清楚些嘛。
6、所有的import都应该在程序文件的开头,唯一例外的情形是——在文档开头使用注释来描述这整个程序。
9、类
在前言的介绍中我们已经知道什么是面向对象编程,先来介绍几个概念。括号里的内容是我的碎碎念,不必看。(倘若只是想学了找工作并不研究什么编程语言什么的,其实不需要看那么多,只是我个人的学习习惯导致我想知道这些的所有知识,要不然浑身不舒服,感觉没学透彻没学好。ps:这个习惯导致我学东西会把线拉得很长,学得很慢,常常因为跟不上学校老师的节奏而放弃学东西,而且常常因为线拉得长学到最后自个儿都忘了前面学过的知识。以前我总觉得这个习惯非常不好,但后面时间充裕一些了之后,也说不准究竟是好习惯还是坏习惯了,无法适应快节奏的生活就注定会被淘汰吗?)
一、什么是类?
1、类是一种抽象的概念。
2、类:具有相同的特性(数据元素)和行为(功能)的对象的抽象就是类。对象的抽象就是类,类的具体化就是对象,也可以说类的实例化就是对象,类实际上就是一种数据类型。类具有属性用数据结构来描述类的属性。类具有操作,它是对象的行为的抽象,用操作名和实现该操作的方法来描述。
总结:
1、类是抽象的
2、拿老虎举例,简单来说老虎是一类动物,它有东北虎、西南虎、白虎、黑虎,这些统一叫老虎。而你养了一只老虎,取名叫虎瓜,虎瓜就是一个对象,老虎就是一个类。
3、类实际上是一种数据类型,可以用数据结构来描述类的属性,可以被操作,用操作名和实现该操作的方法来描述。
二、什么是对象?
1、对象是一种具体概念
2、对象:对象是人们要进行研究的任何事物,它不仅能表示具体的事物,还能表示抽象的规则、计划或事件。对象具有状态,一个对象用数据值来描述它的状态。对象还有操作,用于改变对象的状态,对象及其操作就是对象的行为。对象实现了数据和操作的结合,使数据和操作封装于对象的统一体中。
举个具体的例子
在python中创建一个狗类,狗会坐下(sit),会打滚(roll_over)
class Dog: #class是创建类的标志def _init_(self,name,age): #这个是方法,我之后会讲解self.name=nameself.age=agedef sit(self): #模拟小狗坐下的函数print(f"{self.name} is now sitting.")def roll_over(self): #模拟小狗打滚的函数print(f"{self.name} rolled over!")
在这里,class Dog就是类,这里是用函数来模拟小狗的行为。
当我们给小狗赋予名字时,小狗便成了一个对象,之后我们便围绕着我们创造的小狗来编程,这叫面向小狗编程。
三、类与对象之间是什么关系?
类的实例化就是对象,而对象的抽象就是类,类描述了一组有相同特性(属性)和相同行为的对象。例如:人是一个类,具体哪一个人就是一个对象,每一个对象都符合这个类的标准。一个类的所有对象都有相同的属性(都是人),但是有着不同的属性值(名字,长相、身高)。
————————————————
以上三个概念引用的是CSDN博主「++kc」的原创文章,原文链接:https://blog.csdn.net/weixin_42433025/article/details/119320844
四、面向对象编程是什么?
面向对象编程(Object-Oriented Programming, OOP)是一种基于对象的编程范式,它是一种从现实世界中抽象出问题的解决方法的编程理论。OOP 的核心思想是将问题或任务划分为一系列的对象来描述和解决,在程序中通过定义对象的属性和方法来实现对问题的描述和解决。
常见的面向对象编程语言有 Java、C++、Python 等,它们都支持类、对象、继承、多态等 OOP 的特性。
举个例子来说,如果要设计一个购物车系统,我们可以将购物车视为一个对象,它有自己的属性和方法,例如购物车中可以添加、删除商品,计算购物车中的总价,结算等等。我们可以定义一个 ShoppingCart 类来描述购物车的属性和方法,通过实例化这个类来创建一个购物车对象,然后就可以对这个购物车对象进行各种操作。
这个购物车对象可以与其他对象进行交互,例如商品对象、用户对象等等,通过定义它们的属性和方法,实现更加复杂的功能。这就是面向对象编程的思想。
面向小狗编程就是面向对象编程!
此为网图,侵删。
创建和使用类
使用类几乎可以模拟任何东西,还是那个Dog类,它表示的不是特定的小狗,而是任何小狗。对于大多数宠物狗,除了名字和年龄以外,它们还会撒泼打滚。Dog类将包含它们,这个类让Python知道如何创建表示小狗的对象。编写这个类后,可以使用它来创建表示特定小狗的实例。
根据Dog类创建的每个实例都将储存小狗的名字和年龄,我们赋予了每条小狗蹲下(sit())和打滚(roll_over())的能力:
class Dog:#一次模拟小狗的简单尝试def __init__(self,name,age):#初始化属性name和ageself.name=nameself.age=agedef sit(self):#模拟小狗收到命令时蹲下print(f"{self.name} is now sitting.")def roll_over(self):#模拟小狗收到命令时打滚print(f"{self.name} rolled over!")
上述代码中__init__(self,name,age):是一个特殊函数,先康康整体。
def __init__(self,name,age):#初始化属性name和ageself.name=nameself.age=age
方法_init_():我分成知识点。
1、类中的函数称为方法,也就是说在类里,函数就是方法,方法就是函数。
2、你在前面学到的有关函数的一切都适用于方法,就目前而言,唯一重要的差别是调用的方式不同。
3、_ init _():是一个特殊方法,每当我们根据Dog类创建新实例时,python都会自动运行它。
在这个方法的名称中,开头和末尾各有两个下划线,这是一种约定,旨在避免python默认方法与普通方法发生名称冲突。最最重要的是 init 两侧的下划线必须要有,否则python使用类来创建实例时,将不会自动调用这个方法。
注意: 类里不是必须要有默认方法的_(:з」∠)_一个类可以只包含构造函数和其他自定义方法,而没有默认方法。
在上述代码中我们将方法’’ _ init _()''定义成包含三个形参:self、name和age。在这个方法的定义中,形参self必不可少,而且必须位于其他形参的前面。
why?
because python在调用这个方法创建Dog实例时将自动传入self的实参,这个时候没有形参的话会报错,每个与实例相关联的方法调用都将自动传递实参self,为什么python会自动传入实参self呢?因为self是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
以小狗类为例:
class Dog:
#python想要通过小狗类创建实例就要调用这里的默认方法,并传递实参self,这里的self指的是通过小狗类创建的实例本身。def __init__(self,name,age):#实例名=默认方法里的名字#实例年龄=默认方法里的年龄self.name=nameself.age=agedef sit(self): #实例坐下#小狗收到命令时蹲下print(f"{self.name} is now sitting.")def roll_over(self): #实例打滚#小狗收到命令时打滚print(f"{self.name} rolled over!")
你看,实例的创建离不开实参self吧。
self.name=name获取与形参name相关联的值,并将其赋给变量name,然后该变量被关联到当前创建的实例。self.age=age的作用类似。像这样可以通过实例访问的变量称为属性。
天马行空一回嗷,既然self.name都要等于name了,而且后面两个坐下和打滚的方法也没有用到name和age,只用到了self.name和self.age,那么我们可不可以……?
class Dog:def __init__(self,self.name,self.age):def sit(self): #实例坐下#小狗收到命令时蹲下print(f"{self.name} is now sitting.")def roll_over(self): #实例打滚#小狗收到命令时打滚print(f"{self.name} rolled over!")
#报错信息:
'''
SyntaxError: invalid syntax
语法错误:无效语法
'''
为什么不能这么做呢?因为形参的命名不规范,所以报错信息是语法错误,形参的命名规范在之前形参那里我没讲,详情请看这篇文章:https://www.fke6.com/html/59706.html,讲得比较细。
根据类创建实例
可以将类视为如何创建实例的说明,Dog类是一系列说明,让python知道如何创建表示特定小狗的实例。
下面通过Dog类来创建一个表示特定小狗的实例
my_dog = Dog('willie',6)
print(f"hello {my_dog.name}")
print(f"it is {my_dog.age} years old")
在这里,my_dog就是我们创建的实例。
知识点汇总
1、访问属性
若想通过实例访问属性,可以使用句点表示法(这里的句点是英文的句号)
In [5]:my_dog.name
Out[5]: 'willie'In [6]:my_dog.age
Out[6]: 6
注意:想要访问属性一定是要在创建实例之后。否则会报错。
报错信息:
NameError: name 'my_dog' is not defined
命名错误:未定义名称 'my_dog'
出现这个错误时一般就是名字找不到或者命名错误。
2、调用方法
在创建了实例之后可以通过句点表示法来调用Dog类中定义的任何方法了。
my_dog.sit()
#willie is now sitting.my_dog.roll_over()
#willie rolled over!
3、创建多个实例
很简单
my_dog = Dog('willie',6)
print(f"hello {my_dog.name}")
print(f"it is {my_dog.age} years old")your_dog = Dog('lucy',6)
print(f"hello {my_dog.name}")
print(f"it is {my_dog.age} years old")'''
hello willie
it is 6 years old
hello willie
it is 6 years old
'''
在这里创建了两只小狗,即使是给第二只小狗指定同样的姓名和年龄,python依旧会根据Dog类创建另一个实例,这两个实例是不同的。
使用类和实例
先来做个小练习:创建一个汽车类(class Car),属性有制造商(make)、汽车型号(model)、生产年份(2019),返回一个对汽车进行描述(car_describe)的字符串。
准备好了吗?
3
2
1
揭晓答案
'''
创建一个汽车类(class Car),属性有制造商(make)、
汽车型号(model)、生产年份(year)
'''
class Car:def _init_(self,make,model,year):self.make = makeself.model = modelself.year = year
#返回一个对汽车进行描述的字符串。def car_describe(self):long_name = f"{self.make} {self.model} {self.year}"return long_name.title()
new_car = Car('audi','a4',2019)
print(new_car.car_describe())
#结果报错信息
'''
TypeError: Car() takes no arguments
类型错误:Car()不接受参数
'''
思考一下上述代码为什么出错。
因为_init_应该是双下划线,这里是一个比较容易出错的地方,要记住哦!
再次修改代码运行康康,这下子就没错啦
class Car:def __init__(self,make,model,year):self.make = makeself.model = modelself.year = year
#返回一个对汽车进行描述的字符串。def car_describe(self):long_name = f"{self.make} {self.model} {self.year}"return long_name.title()
new_car = Car('audi','a4',2019)
print(new_car.car_describe())
'''
Audi A4 2019
'''
为了让这个类更有趣,下面我们给它添加一个随时间变化的属性,用于存储汽车的总里程。
给属性指定默认值
创建实例时,有些属性可以不用形参来定义,可在__init__方法中指定其默认值,比如即将登场的里程数odometer_reading,其初始值为0,定义一个函数read_odometer使其读取这辆汽车的里程数(不必纠结英文,就是一个变量名罢了)
class Car:def __init__(self,make,model,year):self.make = makeself.model = modelself.year = year#设定默认值self.odometer_reading = 0
#返回一个对汽车进行描述的字符串。def car_describe(self):long_name = f"{self.make} {self.model} {self.year}"return long_name.title()#构造函数 def 读取_里程表,odometer是里程表的意思def read_odometer(self):print(f"现在走了{self.odometer_reading}里")
new_car = Car('audi','a4',2019)
print(new_car.car_describe())
#调用函数
new_car.read_odometer()
'''
Audi A4 2019
现在走了0里
'''
但是呢,我们既然要记录汽车的里程数,肯定不是无意义的0吧,既然不是0就肯定要改变属性值吧。想要改变属性值有3个方法:1、直接通过实例修改 2、通过方法设置修改属性 3、通过方法进行递增。
1、直接修改属性值
通过实例直接访问属性并修改
new_car = Car('audi','a4',2019)
print(new_car.car_describe())
#通过实例直接访问属性并修改
new_car.odometer_reading = 23
new_car.read_odometer()
2、通过方法设置修改属性
#设置函数,通过返回实参修改mileage的值,mileage 里程def update_odometer(self,mileage): #update 更新,使现代化self.odometer_reading = mileage
new_car = Car('audi','a4',2019)
print(new_car.car_describe())
#自己设置里程数
new_car.update_odometer(23)
new_car.read_odometer()
3、通过方法递增
#设置函数def update_odometer(self,mileage):self.odometer_reading = mileagedef increment_odometer(self,mileage): #increment 增量的意思self.odometer_reading += mileage#self.odometer_reading + mileage = mileage
new_car = Car('audi','a4',2019)
print(new_car.car_describe())
#自己设置里程数
new_car.update_odometer(23)
new_car.read_odometer()
#里程数增加
new_car.increment_odometer(100)
new_car.read_odometer()
这里有个bug,在里程数增加后就不能向后调,故如果有人尝试将里程数往回调的时候我们需要禁止他这样做。
以下是完整代码
class Car:def __init__(self,make,model,year):self.make = makeself.model = modelself.year = yearself.odometer_reading = 0
#返回一个对汽车进行描述的字符串。def car_describe(self):long_name = f"{self.make} {self.model} {self.year}"return long_name.title()def read_odometer(self):print(f"现在走了{self.odometer_reading}里")#更新里程表def update_odometer(self,mileage):self.odometer_reading = mileage#给里程表设置增量def increment_odometer(self,mileage):#如果实际里程>=之前的里程if mileage >= self.odometer_reading :self.odometer_reading += mileageprint(f"更新里程,现在走了{self.odometer_reading}里")else:print("里程数还能往回走的吗笨蛋")
new_car = Car('audi','a4',2019)
print(new_car.car_describe())
#实例更新汽车的里程数为23
new_car.update_odometer(23)
#更新后读取里程数
new_car.read_odometer()
#实例里程数的增量增加-100
new_car.increment_odometer(-100)
'''
Audi A4 2019
现在走了23里
里程数还能往回走的吗笨蛋
'''
突然发现自己能写这么长的代码,是不是有点小小的骄傲捏?
继承
编写类时,并非总是要从空白开始。如果要编写的类是另一个现成类的特殊版本,可以使用继承。一个类继承另一个类,将自动获得另一个类的所有属性和方法。原有的类称为父类,而新类称为子类。子类继承了父类的所有属性和方法,同时还可以定义自己的属性和方法。
也就是原有的类是父亲,后来的类(子女)继承了父类也就是父类的2.0版本,不过略有不同罢了。
在既有类的基础上创建新类时,通常需要调用父类的方法__init__()这将初始化父类在__init__()方法中定义的所有属性,从而让子类包含这些属性。
沿用之前创建的汽车类,咱来模拟电动汽车,让各位看看继承是个什么事。
class Car:def __init__(self,make,model,year):self.make = makeself.model = modelself.year = yearself.odometer_reading = 0
#返回一个对汽车进行描述的字符串。def car_describe(self):long_name = f"{self.make} {self.model} {self.year}"return long_name.title()def read_odometer(self):print(f"现在走了{self.odometer_reading}里")#更新里程表def update_odometer(self,mileage):self.odometer_reading = mileage#给里程表设置增量def increment_odometer(self,mileage):#如果实际里程>=之前的里程if mileage >= self.odometer_reading :self.odometer_reading += mileageprint(f"更新里程,现在走了{self.odometer_reading}里")else:print("里程数还能往回走的吗笨蛋")
#电动汽车(汽车)这里的()括号里放父类,代表继承
class ElectricCar(Car):
#既然要继承,至少硬件是要的,就比如你爸有两条腿,你也得有两条腿才行def __init__(self,make,model,year):#这里的super是一个特殊函数,让ElectricCar能够调用父类的方法,#让ElectricCar实例包含这个方法中的所有属性。#父类也称为超类(superclass),super这个名字就是这么来的super().__init__(make, model, year)
别看上述代码长,不必看car,只用看后面的电动汽车(ElectricCar)类是怎么继承汽车(Car)类的就好啦。
在ElectricCar继承时,我们强调了几点。
1、在类名后的()括号里放父类,代表继承。
2、子类和父类的硬件要一致,也就是说两者的初始属性要一致。
3、super是一个特殊函数,作用有两个:a、让ElectricCar能够调用父类的方法。b、让ElectricCar实例包含这个方法中的所有属性。这两个作用其实是一个,只是详细讲了。
4、super名字来源于父类,父类也称为超类(superclass),super名字就是这么来的。
实际上除了这些,还有两个要点要记住
5、父类和子类必须在一个文件中。
6、父类必须在子类之前。(先有父亲才有儿子呢嘛)
好,接下来来测试一下我们继承的子类能不能用吧 ~
class Car:忽略
class ElectricCar(Car):def __init__(self,make,model,year):super().__init__(make,model,year)
test = ElectricCar('yadi','s','2018')
print(test.car_describe())
'''
Yadi S 2018
'''
早上宿管阿姨查寝,必须起床,起了床要去上班,上完班回来中午没睡觉搞python,下午还要上课,困死啦!!!悲苦的大学牲。
言归正传,想要搞清楚继承这玩意儿呢,光知道规则不行,还要把以继承为中心的所有知识点学透才行。
现在请同学们想象自己是汽车制造商的孩子,你创建了电动汽车。想要重创父辈的辉煌,你将经历ABC三个阶段。
A、 给子类定义属性和方法。
世界上任何亲子关系,就算是基因99%相似的人也不可能完全一模一样,所以我们把孩子分出来肯定有孩子自己的特点,而这个特点就是属性和方法。
你该怎么在你身上添加区分你和你父辈的特点呢?你看中了电瓶车,故要在电瓶车上找特点。电瓶车最大的特点就是电瓶,如何描述电瓶?这里用电瓶容量(battery_capacity )。
class Car:忽略
class ElectricCar(Car):def __init__(self,make,model,year):super().__init__(make,model,year)#给电瓶容量设置初始值(属性特点)self.battery_capacity = 75#给电瓶车构造一个描述电瓶容量的方法(方法特点)def describe_battery(self):print(f"现在电瓶容量有{self.battery_capacity}")
test = ElectricCar('yadi','s','2018')
print(test.car_describe())
test.describe_battery()
有个错误记录一下,有则改之无则加勉。
方法名和属性名一样会导致属性错误(AttributeError)。如下
class Car:忽略
class ElectricCar(Car):def __init__(self,make,model,year):super().__init__(make,model,year)#注意属性的名称self.battery_capacity = 75#注意方法的名称def battery_capacity(self):print(f"现在电瓶容量有{self.battery_capacity}")
test = ElectricCar('yadi','s','2018')
print(test.car_describe())
test.describe_battery()
这样做呢会导致以下报错信息。
<module>test.describe_battery()AttributeError: 'ElectricCar' object has no attribute 'describe_battery'
属性错误:ElectricCar”对象没有属性“describe_battery”
实话说咱有这个属性吗?有,肯定有,那为啥笨蛋python会说没有呢?因为属性名和方法名一样,python分辨不出来你后面调用的这玩意儿到底是属性名呀还是方法名。我们是人类当然知道,但python只是程序,它没有脑袋。
接下来我们先来升级一下我们之前写的代码。电瓶可以有默认值,但是也可以升级,如果我们想让电瓶容量自己定的话,可以怎么升级我们之前写的代码?
很简单。甚至我们都不需要在__init__()里设置默认值,我们只需要将默认值设在方法的形参那儿即可
class Car:忽略
class ElectricCar(Car):def __init__(self,make,model,year):super().__init__(make,model,year)def describe_battery(self,capacity = 75):#给方法设置默认值,如果有capacity的实参,则self.battery_capacity = capacity,如果没有,那就是默认值咯self.battery_capacity = capacityprint(f"现在电瓶容量有{self.battery_capacity}")
test = ElectricCar('yadi','s','2018')
print(test.car_describe())
test.describe_battery(80)
'''
Yadi S 2018
现在电瓶容量有80
'''
B、 重写父类的方法。
就跟做皇帝一样,皇帝的儿子是太子,太子想要让这个国家向上亦或延续,或多或少都会在太上皇施行的制度上有所改革,再好的制度随着时代的变化都会有所不适合的,所以需要重写父类方法。
总而言之就一句:假如父类的方法不适用子类模拟的实物的行为就可以重写。为此,可以在子类中定义一个与要重写父类的方法同名的方法(有点绕,但重要),python会优先子类的方法。
假如在Car类里有一个useless方法,而你在ElectricCar用不到,就可以重写它。如下
class ElectricCar(Car):忽略def useless(self):print("我现在是有用的方法")
就是这样……简单。
此时如果再调用useless方法,python将忽略Car类里的useless()。
咱抵着一个代码薅,( • ̀ω•́ )✧不知不觉间已经写了很多了。下面展示目前为止的完整代码。
class Car:def __init__(self,make,model,year):self.make = makeself.model = modelself.year = yearself.odometer_reading = 0
#返回一个对汽车进行描述的字符串。def car_describe(self):long_name = f"{self.make} {self.model} {self.year}"return long_name.title()def read_odometer(self):print(f"现在走了{self.odometer_reading}里")#更新里程表def update_odometer(self,mileage):self.odometer_reading = mileage#给里程表设置增量def increment_odometer(self,mileage):#如果实际里程>=之前的里程if mileage >= self.odometer_reading :self.odometer_reading += mileageprint(f"更新里程,现在走了{self.odometer_reading}里")else:print("里程数还能往回走的吗笨蛋")
#电动汽车(汽车)这里的()括号里放父类,代表继承
class ElectricCar(Car):def __init__(self,make,model,year):super().__init__(make,model,year)def describe_battery(self,capacity = 75):self.battery_capacity = capacityprint(f"现在电瓶容量有{self.battery_capacity}")
test = ElectricCar('yadi','s','2018')
print(test.car_describe())
test.describe_battery(80)
这么多代码很难管理吧。
古之善用天下者,必量天下之权,而揣诸侯之情。想要在汽车行业闯出自己的一片天地,也要有耳听八方,整合及调动资源的能力。这就是我们接下来将要介绍的C阶段。
C、 将实例用作属性。
属性和方法清单以及文件都越来越长,在这种情况下,可能需要将类的一部分提取出来作为一个独立的类。这样可以将大型类拆分成多个小类。
这个可能有点难理解,我画个图(如果这里面的图有看不清楚的可以评论私信我)。
解释一下下面的图嗷
1、从第一步到第二步,也就是从分类到把类转换成属性这一步,为什么要这么做?实际上我也不知道,可能是为了方便吧,确实方便了许多的亚子。
2、3那个曲线上的那一坨文字都是属于第二步的讲解,第三步的讲解在曲线之下。
不知道你们看懂没有,反正我看书有点花,看图也有点花,那再总结一下步骤吧。
(1)、把描述同一个东西的方法分出来形成单独的一个类。(其实这里不论是描述同一个东西还是什么,主打的就是一个想怎么分类就怎么分类,不必按照这个分类要求来)
(2)、把分出来的类转换成实例,再引进到你需要的类里。这里就是把描述电瓶的单独分了一个类,然后转换成实例引进电动车类里。
(3)、第三步就是如何在电动车的实例里调用电瓶实例的问题了。
这下子应该清晰一些了吧,来看看例子。
class Car:忽略
class Battery:
#第一步:分类def __init__(self,capacity = 75):self.battery_capacity = capacitydef describe_battery(self):print(f"现在电瓶容量有{self.battery_capacity}")
class ElectricCar(Car):def __init__(self,make,model,year):super().__init__(make,model,year)
#第二步,把分完的类作为实例引入我们所需要的类中self.battery = Battery()
# 下面这些方法已经装到电瓶类里了
# self.battery_capacity = 75
# def describe_battery(self):
# print(f"现在电瓶容量有{self.battery_capacity}")
test = ElectricCar('yadi','s','2018')
print(test.car_describe())
#test.describe_battery(80)
#第三步,使用电瓶类
test.battery.describe_battery()
二、python库
datetime库
pandas库
写在最后:给各位同志的建议
如果想要代码写得简洁又优雅,可以进入python网站搜索阅读“PEP 8 —Style Guide for Python Code”,阅读PEP 8 格式设置指南,可以大致浏览一下,有个印象就差不多啦。