写点什么

实用且简洁的 Python 语法

作者:小张想搞机
  • 2023-05-30
    广东
  • 本文字数:3473 字

    阅读完需:约 11 分钟

实用且简洁的Python语法

简介

你在写Python时是否经常觉得这段或那段代码太冗余,太啰嗦了,不够整洁?


正如 Python 之禅所说:


Beautiful is better than ugly.

(优美胜于丑陋)

Explicit is better than implicit.

(明了胜于晦涩)

Simple is better than complex.

(简洁胜于复杂)

Complex is better than complicated.

(复杂胜于凌乱)

Flat is better than nested.

(扁平胜于嵌套)


为了不让自己或别人看自己代码时发火(ー_ー)!!,我们通常会给重要的代码旁写上注释,但好像…有些代码写上注释还是感觉不够好,似乎还缺了点什么,你这么想的话,那应该就是代码的问题了


那就让我们来学习一些实现同等功能下但更简洁明了的代码写法吧:)

三元表达式

你是否也写过类似的代码


age = int(input('请输入你的年龄:'))if age >= 18:    res = '已成年'else:    res = '未成年'print(res)
复制代码


虽然以上代码一眼看过去可以很清楚的明白代码意思,但好像……,有点太啰嗦了,明明只需要实现一个功能,却有 4 行代码,让我们看看三元表达式是怎么写的


age = int(input('请输入你的年龄:'))res = '已成年' if age >= 18 else '未成年'print(res)
复制代码


是不是感觉发现了新大陆:)(如果你学过或者见过当我没说)


三元表达式的特点就是简洁,上面那段代码不懂的话可以看看三元表达式的写法


赋值对象 = 返回值1 if条件判断 else 返回值2
复制代码


三元表达式中只能有一个条件判断,也就是只能 if 条件 else 的形式,如果 if 条件成立,返回 if 左边的返回值,如果条件不成立,返回 else 后面的返回值了,else 后面可以直接写返回值,不需要也不能写条件,三元表达式里不需要冒号:


以下是用三元表达式的方法写函数返回值


def judge(age):    return '已成年' if age >= 18 else '未成年'print(judge(18))
复制代码

列表生成式

你是否有这种需求,就是把循环遍历的数据添加到列表里,比如这样:


list1 = []for i in range(10):    for j in range(1,i+1):        list1.append((j,i))print(list1)
复制代码


其实要把循环遍历的数据添加到列表里也有和三元表达式一样简洁的写法,写法如下:


赋值对象 = 返回值 for循环 if条件判断
复制代码


其中 for 循环可以有多个,for 循环后还可以再写 for 循环,也就是多重循环,不过最好不要嵌套过多的循环,过多的循环会造成效率问题内存占用问题,并且,for 循环和 if 条件判断不需要冒号:




这是用列表生成式的写法完成上一段代码的需求


# 这里的列表生成式用了多重循环,去掉一个循环就是平时看到的那种生成式list1 = [][list1.append((j,i)) for i in range(10) for j in range(1,i+1)]print(list1)
复制代码




以下是一个列表生成式使用例子要求:把字典 dic 里值为整数偶数的键添加到一个列表里


dic = {'name' : '张三', 'age' : 18, 'grade' : 3, 'class' : 18, 'money' : 5000, 'height' : 180, 'weight' : 53}new_dic = [value for value in dic if type(dic.get(value)) is int and dic.get(value) % 2 ==0]print(new_dic)
复制代码


以上是列表生成式的用法但不限于此

集合生成式

集合生成式和列表生成式写法一模一样,这里就不过多赘述了,只不过集合生成式生成的集合里不能有重复的值,其他的只需要把列表的中括号[]换成集合的大括号{}就好了

字典生成式

字典生成式是 Python 所有数据结构里最后一个有生成式的数据结构,让我们看看字典生成式的写法和用法吧:)写法如下:


赋值对象 = 返回值 for循环 if 条件判断
复制代码


字典生成式除了返回的值和括号不一样,其他都和列表生成式一样的,同样支持多重 for 循环和 if 条件判断,只是返回值必须是键值对形式(i:j),否则就变成了集合生成式了




例子


# 因为字典的键是唯一的,所以这个字典里的键和值相等值dic = {i:j for i in range(10)for j in range(1,i+1)}print(dic)
复制代码


也可以把字典的值固定为一个定值,例如


dic = {i:None for i in range(10) if i % 2 == 1}print(dic)
复制代码


但如果把字典的键设为定值的话,这个字典生成式的结果就只有一个值,因为字典里键是唯一的,如果出现重复,后面的会把前面的给代替掉

zip 函数

zip函数就如同它的名字一样,用来把数据缝合在一起并压缩


zip(iterable)
复制代码


zip 函数的参数为可迭代对象,返回的对象是一个迭代器对象,zip 函数的原理就是把可迭代对象的值以此取出来放到一个元组里,以下是一个例子


names = ('Micheal', 'Jack', 'Sophia', 'Maria', 'Lisa')scores = (75, 80,85,90,95)res = zip(names, scores)print(list(res))print(tuple(res))# 由于zip函数返回的对象是迭代器对象,第一个print已经把res遍历了一次# 所以第二个print遍历不到任何值,打印的就是空元组了
复制代码


在可迭代对象长度不一样的情况下,zip 会向长度最短的对齐,例如


names = ('Micheal', 'Jack', 'Sophia')scores = (75, 80,85,90,95)print(list(zip(names, scores)))
>>>[('Micheal', 75), ('Jack', 80), ('Sophia', 85)]
复制代码


再次说明一下,zip 函数返回的是迭代器对象,如果想把 zip 的返回值变成可迭代对象(也就是平时见到的列表,元组,字典,集合之类的数据结构),必须进行类型转换,就是把 zip 函数作为参数传给某个数据结构的函数,否则只能通过__next__()来取值,要是有不懂迭代器对象和可迭代对象的可以去百度一下


names = ('Micheal', 'Jack', 'Sophia', 'Maria', 'Lisa')scores = (75, 80,85,90,95)res = zip(names, scores)print(list(res))  # 这是可迭代对象
复制代码


names = ('Micheal', 'Jack', 'Sophia', 'Maria', 'Lisa')scores = (75, 80,85,90,95)res = zip(names, scores)print(res)  # 这是迭代器对象print(res.__next__())
复制代码

enumerate 函数

enumerate函数和 range 函数有一点点像,都可以从函数对象中取值,但 enumerate 函数是从已有的可迭代对象中取值,同时取索引,每取一个值下一个索引自动加一,并且不能指定步长


enumerate(iterable, start=0)
复制代码


iterable 是可迭代对象,start 是索引起始值,默认从 0 开始




这么一看是不是感觉没什么用,到恰恰相反,接下来看一个实例


names = ('Micheal', 'Jack', 'Sophia', 'Maria', 'Lisa')for name in names:    print(name, names.index(name))
>>>Micheal 0 Jack 1 Sophia 2 Maria 3 Lisa 4
复制代码


如果用 enumerate 可以这样写


names = ('Micheal', 'Jack', 'Sophia', 'Maria', 'Lisa')for index, name in enumerate(names):    print(name, index)
>>>Micheal 0 Jack 1 Sophia 2 Maria 3 Lisa 4
复制代码


可以看出 enumerate 主要用在 for 循环中取值以及索引的场景下




这是指定索引起始值的情况


names = ('Micheal', 'Jack', 'Sophia', 'Maria', 'Lisa')for index, name in enumerate(names, 3):    print(name, index)
>>>Micheal 3 Jack 4 Sophia 5 Maria 6 Lisa 7
复制代码




for index, name in enumerate(names):
复制代码


这个是解压赋值,因为 enumerate 返回的是一个元组,元组的第一个值是索引,第二个是迭代的对象


# enumerate的返回值names = ('Micheal', 'Jack', 'Sophia', 'Maria', 'Lisa')for res in enumerate(names):    print(res)
>>>(0, 'Micheal') (1, 'Jack') (2, 'Sophia') (3, 'Maria') (4, 'Lisa')
复制代码

Python 之禅

以下是 Python 之禅,要是有感兴趣的可以看看:)


The Zen of Python, by Tim Peters

Beautiful is better than ugly.

(优美胜于丑陋)

Explicit is better than implicit.

(明了胜于晦涩)

Simple is better than complex.

(简洁胜于复杂)

Complex is better than complicated.

(复杂胜于凌乱)

Flat is better than nested.

(扁平胜于嵌套)

Sparse is better than dense.

(间隔胜于紧凑)

Readability counts.

(可读性很重要)

Special cases aren't special enough to break the rules.Although practicality beats purity.

(尽管实用性胜过纯粹性,但特例也不足以凌驾于规则之上)

Errors should never pass silently.

(不要忽略任何错误)

Unless explicitly silenced.

(除非你确定要这么做)

In the face of ambiguity, refuse the temptation to guess.

(面对临摹两可,拒绝猜测)

There should be one-- and preferably only one --obvious way to do it.

(找到一种最好是唯一的一种方法去解决问题)

Although that way may not be obvious at first unless you're Dutch.

(虽然这并不容易,因为你不是 Python 之父)

Now is better than never.

(做也许好过不做)

Although never is often better than right now.

(但不假思索就动手还不如不做)

If the implementation is hard to explain, it's a bad idea.

(如果你的方案难以理解,那肯定不是一个好方案)

If the implementation is easy to explain, it may be a good idea.

(如果你的方案很容易解读,那很有可能是一个好方案)

Namespaces are one honking great idea -- let's do more of those!

(命名空间是一种很绝妙的理念,我们应该多加利用)


发布于: 2023-05-30阅读数: 27
用户头像

Pythoning,SQLiteing,前段ing 2023-04-25 加入

还未添加个人简介

评论

发布
暂无评论
实用且简洁的Python语法_Python_小张想搞机_InfoQ写作社区