目录
- 用字典映射代替其他语言中switch case 语句
- 列表推导式
- None的特殊性与误区
- 自定义对象与bool的对应关系
- 装饰器的副作用
- 编程能力
- 海象运算符
- 用f关键字做字符串拼接
- 装饰器:@dataclass数据类
以前章节主打基础知识,目的是让你具备不断学习、更新知识体系的能力。这要远远好于把所有知识点罗列出来。
本章节没有主线,只是关于上述主线章节的零碎升级、补充。
毕竟,好的产品,是打磨出来的,没有一蹴而就。这里的产品,不只是app、网站,还包括课程、项目。
七月老师:
虽然是谋生手段,但兴趣爱好,却是具有更加强大的力量。这是件很幸福的事情。
一、用字典映射代替switch case 语句
1.其他语言的switch case
语句
关于条件分支语句,其他语言是用switch case
语句。例如,C#中:
switch(day)
{
case 0 :
dayname = "Sunday";
break;
case 1 :
dayname = "Monday";
break;
case 2 :
dayname = "Tuesday";
break;
...
default :
dayname = "Unknown";
break;
}
python中,官方建议可以用if else
代替上述语句。
但是,老师认为不合适。
因为其他语言中也有if else
,如果能代替,为什么还要多出个switch case
语句呢?只有if else
不就可以了吗?
因此,老师的建议是,用字典映射来代替其它语言中的switch case
语句,更简洁、好用。
2.字典映射
day = 0 #定义一个变量,目的是接受下标数值
switcher = {
0 : 'Sunday',
1 : 'Monday',
2 : 'Tuesday',
}
dayname = switcher[day] #使用下标,来访问字典
print(dayname)
-->
Sunday
当day = 2
时,结果是什么?
day = 2 #变量被重新赋值为2
switcher = {
0 : 'Sunday',
1 : 'Monday',
2 : 'Tuesday',
}
dayname = switcher[day]
print(dayname)
-->
Tuesday
当day = 6
时,结果是什么?
day = 6 #变量被重新赋值为6
switcher = {
0 : 'Sunday',
1 : 'Monday',
2 : 'Tuesday',
}
dayname = switcher[day]
print(dayname)
-->
error ❌ #因为字典switcher中,找不到key=6的元素
3.用内置get
函数来访问字典
当变量的值,超出了字典中的key范围时,就必须换一种字典的访问方式。
即,内置的get
方法,来访问字典。
day = 6 #变量被重新赋值为6
switcher = {
0 : 'Sunday',
1 : 'Monday',
2 : 'Tuesday',
}
dayname = switcher.get(day,'Unknown') #内置的`get`函数
# Unknown:指定当day对应的key不存在时,函数调用将返回的结果
print(dayname)
-->
Unknown
上述利用内置函数get
,并补上Unknown
,本质上,就是在模拟其他语言中switch case
语句里的default分支。
两种字典访问方式对比
通过下标访问 | 用内置函数get访问 | |
---|---|---|
优点 | 简单、直接 | 有容错性 |
4.函数编程融入字典映射
上述字典中的value,只是个字符串,顶多是个lambda表达式。
而,我们知道,其他语言switch case
中的case
下面,是可以写代码块、写很多行的。
那么,python中的字典又如何模拟呢?
其实,key对应的value不只是字符串,也可以是函数。这跟函数式编程思维中的将函数赋值给变量是一个道理。
day = 0
def get_sunday(): #先定义,后调用
return 'Sunuday'
def get_monday():
return 'Monday'
def get_tuesday():
return 'Tuesday'
switcher = {
0 : get_sunday, # key对应的value也可以是函数(名)
1 : get_monday,
2 : get_tuesday,
}
dayname = switcher.get(day,'Unknown')() #因为从字典switcher中,得到的key所对应的value,是函数名。所以要加个小括号()方能调用执行
print(dayname)
-->
Sunuday
day = 6
def get_sunday(): #先定义,后调用
return 'Sunuday'
def get_monday():
return 'Monday'
def get_tuesday():
return 'Tuesday'
switcher = {
0 : get_sunday, # key对应的value也可以是函数(名)
1 : get_monday,
2 : get_tuesday,
}
dayname = switcher.get(day,'Unknown')()
print(dayname)
-->
error ❌ #在get函数中,默认值是'Unknown',即字符串str型。不是函数名!因为Unknown()没意义
为了解决上述问题,应该对默认值的情况,重新定义一个函数。
因为,字典中的value值都用的是函数,所以建议默认值也要用函数。
day = 6
def get_sunday():
return 'Sunuday' #这里只是返回了字符串常量。真正写业务,是可以有很多的逻辑的
def get_monday():
return 'Monday'
def get_tuesday():
return 'Tuesday'
def get_default(): #重新定义一个返回默认值的函数
return 'Unknown'
switcher = {
0 : get_sunday,
1 : get_monday,
2 : get_tuesday,
}
dayname = switcher.get(day,get_default)() #这里的get_default,是默认情况下的函数名
print(dayname)
-->
Unknown
七月老师:
其他语言中的switch case下,也是不建议写很多的业务逻辑的,应该是写个方法,case只是调用这个方法。
具体的业务逻辑应该写在方法内部,而不是直接写在case语句下面。
二、列表推导式
叫法很奇怪,其本质跟数学中的集合推导式是一样的。
具有python特色,很pythonic。因为简洁优雅,其他语言中没有。
用途:根据已有的列表,创建一个新的列表。
1.例题
将列表[1,2,3,4,6,7,8,]
中的每个元素,都做平方,得到一个新的列表?
(1)写法1:
使用之前的for
循环控制语句,进行遍历
a = [1,2,3,4,6,7,8]
b = [] #定义一个空列表,以接受新的列表元素
for x in a:
b.append(x*x) #⭐使用内置函数append(),将新的列表元素添加到列表b中
print(b)
-->
[1, 4, 9, 16, 36, 49, 64]
(2)写法2:
只用高阶函数中的map函数,也能遍历
a = [1,2,3,4,6,7,8]
r = map(lambda x:x*x,a)
print(list(r))
-->
[1, 4, 9, 16, 36, 49, 64]
(3)写法3:
使用列表推导式
a = [1,2,3,4,6,7,8]
b = [x*x for x in a] #结构:How怎么算 Who算谁 #里面是个for循环,但又不是真的for循环
print(b)
-->
[1, 4, 9, 16, 36, 49, 64]
上述的列表推导式,本质上其实就是对写法1的简化。
小知识点:
平方运算,不止可以写为x*x
,还可以x**2
。后者的指数运算很方便,因为当100个x相乘时,就直接x**100
。七月老师:
如果是对列表中的全部元素进行操作,那么其实用map函数更好用。因为其他语言中也都有,用习惯了。
2.推荐的使用场景
当对非全部元素进行操作,即有选择性的操作时,比较方便。
例题
将列表[1,2,3,4,6,7,8,]
中的每个大于等于5的元素,都做平方,得到一个新的列表?
写法1:
使用高阶函数中的filter函数
a = [1,2,3,4,6,7,8]
r = filter(lambda x:x*x if x>=5 else None,a)
print(list(r))
-->
[6, 7, 8] # ?
写法2:
使用列表推导式
a = [1,2,3,4,6,7,8]
b = [x*x for x in a if x >=5] #只要加个条件筛选即可
print(b)
-->
[36, 49, 64]
3.常见误区
虽然叫列表推导式,但是,不只是能推到列表。
还可以推导集合set、元组tuple、字典dic。
(1)“集合推导式”
a = {1,2,3,4,6,7,8} #集合
b = [x*x for x in a if x >=5]
#因为这里的中括号[],并不是列表推导式的固定字符。如果想得到集合,那么这里就应该是集合符合{}
print(b)
-->
[36, 49, 64] #结果仍是列表
改为:
a = {1,2,3,4,6,7,8} #集合
b = {x*x for x in a if x >=5} #列表推导式的符号改为集合符号{}
print(b)
-->
{64, 49, 36} #结果是集合
(2)“字典推导式”
例题1:
将字典{'喜小乐':18,'石敢当':20,'横小五':15}
中的key提取出来,单独制成一个列表?
students = {
'喜小乐':18,
'石敢当':20,
'横小五':15
}
b = [key for key,value in student] #列表一个形参即可,但字典因为有键值对,必须两个形参
print(b)
-->
error ❌ #字典不能直接被for in循环遍历
通过调用字典的items()方法,来取出很多条目中的一个:
students = {
'喜小乐':18,
'石敢当':20,
'横小五':15
}
b = [key for key,value in student.items()]
print(b)
-->
['喜小乐', '石敢当', '横小五']
例题2:
将字典{'喜小乐':18,'石敢当':20,'横小五':15}
中的key与value位置颠倒,制成一个新的字典?
students = {
'喜小乐':18,
'石敢当':20,
'横小五':15
}
b = {value:key for key,value in students.items()} #这里的推导式符号是字典符号{},因为得到的是一个字典
print(b)
-->
{18: '喜小乐', 20: '石敢当', 15: '横小五'}
(3)“元组推导式”
推导式符号,变为中括号时:
students = {
'喜小乐':18,
'石敢当':20,
'横小五':15
}
b = (key for key,value in students.items()) #推导式符号改为元组 #前面只能是key
print(b)
-->
<generator object <genexpr> at 0x0000022569729930> #得到的不是元组,而是可遍历的对象generator
students = {
'喜小乐':18,
'石敢当':20,
'横小五':15
}
b = (key for key,value in students.items())
for x in b:
print(x)
-->
喜小乐
石敢当
横小五
之所以元组会出现这样一个情况:得到一个generator对象,是因为元组是不可变的,它很多行为和列表等一些典型的可变的是有区别的。
Comments | NOTHING