word 代码块_如何优雅的写好 Pythonic 代码?
(点击上方公众号,可快速关注一起学Python)
Python 与其它语言(比如Java或者C++)相比有比较大的区别,其中最大的特点就是非常简洁。如果按照其它语言的思路来写Python代码,则会使得代码繁琐复杂,并且容易出现Bug。在Python语言中,有个词很火,Pythonic。有的同学可能不明白这个词的意义,小编的理解就是用Python的写法写代码,而非是其它语言的通用的写法,写出Python的特点,写出Python的风格。
下面,就通过几个示例来看一下不同思维的Python代码的差异。
1、变量值交换
这个问题最常见,大家从最开始写Java及C++等语言代码都会遇到这个问题。通常是通过一个临时变量来实现的:
tmp = aa = bb = tmp
而Python中可以直接交换两个变量,即:
a, b = b, a
2、列表推导式
列表推导式是Java及C++等语言没有的特性,能够很简洁的实现for循环,可以应用于列表,集合或者字典。
例如我们要求20以内的整除3的数的平方的列表,可以用如下代码实现:
numbers = []for x in xrange(20): if x % 3 == 0: numbers.append(x*x)
而通过列表推导式一行代码即可实现:
numbers = [x*x for x in range(20) if x % 3 == 0]
列表推导式也可以用于集合和字典,将[...]变为{...}即可。集合和字典的实现如下所示:
集合:
numbers = {x * x for x in range(0, 20) if x % 3 == 0}
字典:
numbers = {x: x * x for x in range(0, 20) if x % 3 == 0}
3、字符串拼接
这是一个老生常谈的问题,当我们需要将数个字符串拼接的时候,习惯性的使用 "+" 作为连接字符串的手段。
然而,由于像字符串这种不可变对象在内存中生成后无法修改,合并后的字符串会重新开辟出一块内存空间来存储。因此每合并一次就会单独开辟一块内存空间,这样会占用大量的内存空间,严重影响代码的效率。
words = ['I', ' ', 'love', ' ', 'Python', '.']
sentence = ''for word in words: sentence += '' + word
解决这个问题的办法是使用字符串连接的join,Python写法如下:
words = ['I', ' ', 'love', ' ', 'Python', '.']
sentence = ''.join(words)
4、如何快速翻转字符串
Java或者C++等语言的写法是新建一个字符串,从最后开始访问原字符串:
a = 'I love Python.'
reverse_a = ''for i in range(0, len(a)): reverse_a += a[len(a) - i - 1]
而Python则将字符串看作list,而列表可以通过切片操作来实现反转:
a = 'I love Python.'reverse_a = a[::-1]
5、for/else语句
在C语言或Java语言中,我们寻找一个字符是否在一个list中,通常会设置一个布尔型变量表示是否找到:
cities = ['BeiJing', 'TianJin', 'JiNan', 'ShenZhen', 'WuHan']tofind = 'Shanghai'
found = Falsefor city in cities: if tofind == city: print 'Found!' found = True breakif not found: print 'Not found!'
而Python中的通过for...else...会使得代码很简洁,注意else中的代码块仅仅是在for循环中没有执行break语句的时候执行:
cities = ['BeiJing', 'TianJin', 'JiNan', 'ShenZhen', 'WuHan']tofind = 'Shanghai'
for city in cities: if tofind == city: print 'Found!' breakelse: # 执行else中的语句意味着没有执行break print 'Not found!'
另外,while以及try关键字都可以和else搭配使用,具体可以参考小编之前写的文章 Python中else块那点事。
6、迭代对象善用enumerate类
enumerate类接收两个参数,其中一个是可以迭代的对象,另外一个是开始的索引。比如,我们想要打印一个列表的索引及其内容,可以用如下代码实现:
cities = ['BeiJing', 'TianJin', 'JiNan', 'ShenZhen', 'WuHan']
index = 0for city in cities: index = index + 1 print index, ':', city
而通过使用enumerate则极大简化了代码,这里索引设置为从1开始(默认是从0开始):
cities = ['BeiJing', 'TianJin', 'JiNan', 'ShenZhen', 'WuHan']for index, city in enumerate(cities, 1): print index, ":", city
7、通过lambda来定义函数
lambda可以返回一个可以调用的函数对象,会使得代码更为简洁。若不使用lambda则需要单独定义一个函数:
def f(x): return x * x
map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
使用lambda后仅仅需要一行代码:
map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])
这里注意,lambda生成的是一个可以像其他函数一样使用的函数对象,即
def f(x): return x * x
等价于
lambda x: x * x
8、应用上下文管理
在打开文件时,通常是通过捕获异常来进行实现的,并且在finally模块中对文件来进行关闭:
try: file = open('python.txt') for line in file: print lineexcept: print "File error!"finally: file.close()
而通过上下文管理中的with语句可以让代码非常简洁:
with open('python.txt') as file: for line in file: print line
具体原理可以参考小编之前写的 with语句那点事。
9、使用装饰器
装饰器在Python中应用特别广泛,其特点是可以在具体函数执行之前或者之后做相关的操作,比如:执行前打印执行函数的相关信息,对函数的参数进行校验;执行后记录函数调用的相关流水日志等。使用装饰器最大的好处是使得函数功能单一化,仅仅处理业务逻辑,而不附带其它功能。
在函数调用前打印时间函数名相关的信息,不使用装饰器可以用如下代码实现:
from time import ctime
def foo(): print('[%s] %s() is called' % (ctime(), foo.__name__)) print('Hello, Python')
这样写的问题是业务逻辑中会夹杂参数检查,日志记录等信息,使得代码逻辑不够清晰。所以,这种场景需要使用装饰器:
from time import ctime
def deco(func): def decorator(*args, **kwargs): print('[%s] %s() is called' % (ctime(), func.__name__)) return func(*args, **kwargs) return decorator
@decodef foo(): print('Hello, Python')
如果想深入理解装饰器,可以阅读小编之前写的 深入理解Python中的装饰器。
10、使用生成器
生成器与列表最大的区别就是,列表是一次性生成的,需要较大的内存空间;而生成器是需要的时候生成的,基本不占用内存空间。生成器分为生成器表达式和生成器函数。
先看一下列表:
l = [x for x in range(10)]
改为生成器只需要将[...]变为(...),即
g = (x for x in range(10))
至于生成器函数,是通过yield关键字来实现的,我们以计算斐波那契数列为例,使用列表可以用如下代码来实现:
def fib(max): n, a, b = 0, 0, 1 fibonacci = [] while n < max: fibonacci.append(b) a, b = b, a + b n = n + 1 return fibonacci
而使用生成器则变为:
def fib(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b n = n + 1
对生成器感兴趣的可以深入阅读小编之前写的文章 生成器那点事 及 深入理解生成器及协程。
11、Counter的使用
通常的词频统计中,我们的思路是:
需要一个字典,key值存储单词,value存储对应的词频。当遇到一个单词,判断是否在这个字典中,如果是,则词频加1;如果否,则字典中新增这个单词,同时对应的词频设置为1。
对应的Python代码实现如下:
#统计单词出现的频次def computeFrequencies(wordList): #词频字典 wordfrequencies = {}
for word in wordList: if word not in wordfrequencies: # 单词不在单词词频字典中, 词频设置为1 wordfrequencies[word] = 1 else: # 单词在单词词频字典中, 词频加1 wordfrequencies[word] = wordfrequencies[word] + 1 return wordfrequencies
有没有更简单的方式呢?答案是肯定的,就是使用Counter。collection 中的 Counter 类就完成了这样的功能,它是字典类的一个子类。Python代码变得无比简洁:
# 统计单词出现的频次def computeFrequencies(wordList): #词频字典 wordfrequencies = Counter(wordList) return wordfrequencies
感兴趣的可以深入阅读小编之前写的文章 Python中的词频统计。
12、链式比较
在实际数字比较中,我们可能需要多次比较多次,比如我们判断学习成绩是否位于某个区间:
x = 79
>>> x < 80 and x > 70True
而更Pythonic的写法变身链式比较,即:
x = 79
>>> 80 < x < 90False
>>> 70 < x < 80True
这种写法给人的感受也更为直观易懂。
13、函数返回多个值
在Java语言中,当函数需要返回多个值时,通常的做法是生成一个Response对象,然后将要返回的值写入对象内部。而Python不需要这样做,可以直接返回多个值:
def f(): error_code = 0 error_desc = "成功" return error_code, error_desc
使用的时候也会非常简单:
code, desc = f()print code, desc
14、使用*运算符
*运算符和** 运算符完美的解决了将元组参数、字典参数进行 unpack,从而简化了函数定义的形式,如:
def fun(*args): for eacharg in args: print 'tuple arg:', eacharg
fun('I', 'love', 'Python')
运行的结果为:
tuple arg: I
tuple arg: love
tuple arg: Python
感兴趣的可以深入阅读小编之前写的文章 Python 中的*args和**kwargs。
15、找出列表中出现最多的数
这是经常会遇到的一个问题。解决这个问题的其中一个思路是按照标题11提供的词频统计的方法,先统计词频,然后遍历字典,找出具有最大词频的数字。有没有更简洁的方式?
当然,Python代码如下:
num = [1, 3, 3, 4, 5, 6, 3, 6, 6, 6]
print max(set(num),key=num.count)
这些Pythonic的代码是否让你耳目一新?你还能写出哪些Pythonic的代码?在留言区跟大家分享一下吧!
提醒福利
之前给大家推荐的《Python核心技术与实战》还在优惠期,原价¥99,限时优惠¥68,不要错过了。既然你要学Python为什么不跟着知名公司的一线程序员学呐?100天,带你进阶高手。扫码免费试看
(完)
看完本文有收获?请转发分享给更多人
关注「Python那些事」,做全栈开发工程师
点「在看」的人都变好看了哦
word 代码块_如何优雅的写好 Pythonic 代码?相关推荐
- java 静态代码块_关于Java你不知道的那些事之代码块
前言 普通代码块:在方法或语句中出现的{},就被称为代码块 静态代码块:静态代码块有且仅加载一次,也就是在这个类被加载至内存的时候 普通代码块和一般语句执行顺序由他们在代码中出现的次序决定,先出现先执 ...
- 优雅的写出 JavaScript 代码
目录 前言 避免使用 js 糟粕和鸡肋 编写简洁的 JavaScript 代码 使用 ES6/ES7 新特性 Babel ESLint Prettier 采用函数式编程 优雅的敲 JS 代码的几个原则 ...
- java 代码块_详解java中的四种代码块
在java中用{}括起来的称为代码块,代码块可分为以下四种: 一.简介 1.普通代码块: 类中方法的方法体 2.构造代码块: 构造块会在创建对象时被调用,每次创建时都会被调用,优先于类构造函数执行. ...
- svn如何隐藏代码路径_程序员课堂—如何通过改善代码风格来消灭隐藏bug
写在前面:一名有三年Android开发经验的女程序员(欢迎大家关注我 ~期待和大家一起交流和学习Android的相关知识) 正如食物腐烂之前,可能会发出异味.当代码存在隐藏问题时,代码也会表现出一些异 ...
- java中静态变量,静态代码块,静态方法,实例变量,匿名代码块的加载顺序
1. java中静态变量,静态代码块,静态方法,实例变量,匿名代码块 在Java中,使用{}括起来的代码称为代码块,代码块可以分为以下四种: (1)普通代码块:就是类中方法的方法体 public vo ...
- java 代码块 作用_Java核心(三):代码块的作用
Java中用{ }括起来的代码段就是代码块,他分为如下几种类型 位置 作用 局部代码块 在方法当中使用,作用是控制变量的生命周期. 局部代码块的变量,只能在代码块内部使用,在执行结束后会被Java回收 ...
- java 静态代码块有什么用,java编程开发静态代码块的使用方法都有哪些
代码块是程序员在学习java编程开发的时候会接触到的一个代码,而今天我们就通过案例分析来了解一下,java编程开发静态代码块的使用方法都有哪些. (一)java静态代码块静态方法区别 一般情况下,如果 ...
- java 静态代码块的作用_Java中什么是静态代码块,有什么作用?
在java中使用static关键字声明的代码块.静态块用于初始化类,为类的属性初始化.每个静态代码块只会执行一次.静态代码块随着类加载而加载,有多个静态代码块的,按代码块前后顺序加载. 由于JVM在加 ...
- 代码块:在Java中用{}括起来的代码
代码块:在Java中用{}括起来的代码 (1)在Java中用{}括起来的代码. (2)代码块分类:(根据其位置和声明的不同) A:局部代码块 在方法定义中,用于限定变量的生命周期,及早释放,提高内存利 ...
最新文章
- java 自定义validate_Golang-03 自定义validator,实现java注解功能-Go语言中文社区
- 横波与纵波的本质区别是什么?——偏振
- 企业级UML/MDA工具Trufun 2007系列发布!
- kafka数据可靠性深度解读
- Docker的四种网络模式和相关网络命令等操作
- java 数组 截取_Java成长孵化园---认识java(day09)
- mogilefs杂记(2)
- CCF201812-2 小明放学
- ORACLE startup报错之ORA-01154ORA-01155ORA-01033ORA-03113
- 华为盒子m330能生鸿蒙吗,不仅能看片 教你怎么玩转华为M330盒子
- windows10安装dll文件
- 如何用Python解析JSON数据
- android照片批量上传照片,一键批量上传手机照片到QQ相册功能 节省手机流量
- 停车、投票、领证,区块链如何在「智慧城市」建设中大显身手?
- 巧妙的位运算及模运算
- [CF505E]Mr. Kitayuta vs. Bamboos/[海军国际项目办公室]迷途竹林
- Maven项目自动更新/修复Javadoc
- Bmob后端云初体验
- 网易视频云郭再荣:打造一体化多场景的视频云平台
- sqlplus 汉字乱码问题的解决——windows
热门文章
- #ifdef __cplusplus是什么意思
- 程序员的SOHO:接单到完成的全过程
- Python 3.8 稳定版正式发布,新特性全面解读
- 鼠标点击时隐藏java代码,js实现点击展开隐藏效果(实例代码)
- mybatis核心配置_MyBatis 核心配置综述之StatementHandler
- 我是不会运行你的代码吗?不,我是不会导入自己的数据!
- 详细讲述CV的创作与包装
- 经济学家忽悠老百姓的“万能公式”
- 1.13 编程基础之综合应用 47 大整数除法方法 python
- Linux学习之diction的编译与使用