用 Python 时间也算不短了,但总感觉自己在用写 C++ 代码的思维写 Python,没有真正用到其作为脚本语言的优势。之前刷 LeetCode 时,自己的 Python 代码总是很长,很像披着 Python 外衣的 C++ 代码(放在这里,不断重构中)。

想来大概是因为觉得python简单,平时只是零零碎碎的学习,也没有去读别人的代码,导致掌握的不够深入。回想起前段时间的面试,面试官看我简历写熟悉Python,就问了两个Python的问题:

Python 中常用的优化技巧(能够提升 Python 执行效率的,除了算法层面)

按照 value 从小到大输出 dict 中的 key-value值。

我支支吾吾半天,就是没有答到点上,直接导致被拒(后来整理的内容放在这里)。所谓知耻而后勇,经过一段时间对 Python 的重新学习,才慢慢发现 Python 的一些强大与美妙之处。

从排序说起!

程序中经常用到排序函数,Python 提供了 sort 和 sorted 函数,一个原地排序,一个返回排序后的新结果,函数原型很简单:

sort([cmp[, key[, reverse]]])

自己用的最多的类似下面的语句:

>>> l = [43, 12, 4, 6]

>>> l.sort()

>>> l

[4, 6, 12, 43]

曾经窃以为这就体现了 Python 的简单优雅,不像 C++ STL中那样还需要指定迭代器范围,然后对 sort 的理解也就止步于此。后来遇到稍微复杂一点的排序场景,自己就 Google-Stackoverflow-Copy,解决了眼前的问题,但是从来没有去深挖(这也就导致那次面试中中没有回答出来上面的第二个问题)。

sort 之美

后来去看了下 sort 的函数说明,包括 cmp, key, reverse 参数究竟怎么去用,又写了几个例子,以为这下子对 sort 可谓是理解透彻了。比如要要根据值的大小输出字典内容,那么就可以像下面这样优雅地解决:

>>> d = {1: 'z', 2:'y', 3: 'x'}

>>> print sorted(d.items(), key=lambda x: x[1])

[(3, 'x'), (2, 'y'), (1, 'z')]

我甚至可以得到一个根据value排序的字典,只需要用 collections.OrderedDict 即可:

>>> from collections import OrderedDict

>>> sorted_d = OrderedDict(sorted(d.items(), key=lambda x: x[1]))

>>> sorted_d

OrderedDict([(3, 'x'), (2, 'y'), (1, 'z')])

sort 之魅

我以为我对 sort 理解足够了,直到在 hackerrank 遇到这个题目。

给定一个只包含大小写字母,数字的字符串,对其进行排序,保证:

所有的小写字母在大写字母前面

所有的字母在数字前面

所有的奇数在偶数前面

考虑用 sort 函数来完成排序。开始之前,再来看看文档对sort函数中key的说明:

key parameter to specify a function to be called on each list element prior to making comparisons. The value of the key parameter should be a function that takes a single argument and returns a key to use for sorting purposes.

通俗讲,key 用来决定在排序算法中 cmp 比较的内容,key 可以是任何可被比较的内容,比如元组(python 中元组是可被比较的)。所以上面的排序问题可以用下面的代码来解决:

>>> s = "Sorting1234"

>>> "".join(sorted(s, key=lambda x: (x.isdigit(), x.isdigit() and int(x) % 2 == 0, x.isupper(), x.islower(), x)))

'ginortS1324'

这里,lambda 函数将输入的字符转换为一个元组,然后 sorted 函数将根据元组(而不是字符)来进行比较,进而判断每个字符的前后顺序。

如果同样的程序用 C++ 来写的话,可能需要一个复杂的仿函数,来定义排序的规则,远没有 Python 这般简洁优雅。

再探 Python

Python 是一门简单方便的语言,相信这是大部分人对 Python 的第一感觉。初学 Python,我们可能痴迷于 Python 的列表解析,list 切片,字典推导,或者是陶醉在各种强大的第三方库里,比如网络库 requests,科学计算库 numpy,web开发框架 Django 等。

但是实际写程序中,我们经常会写出许多繁杂的、丑陋的Python代码。比如要判断一个数字是否是回文数字,可能会习惯性地写出下面这样的代码:

def isPalindrome(x):

if x < 0:

return False

reversed_x = 0

original_x = x

while x > 0:

reversed_x = reversed_x * 10 + x % 10

x /= 10

return reversed_x == original_x

仔细一看,这简直就是 C++ 代码,完全没有 Python 的优雅与简单。那么,该怎样写才能够显的 Pythonic 呢?其实,用 Python 的话只要一行就可以啦(这里不考虑效率,如果考虑效率的话,C++会更加合适,单对这题来说,其实有比上面更高效的方法)!

def isPalindrome(x):

return x >= 0 and str(x) == str(x)[::-1]

那么如何养成用 Pythonic 的思维解决问题呢?我觉得首先要对 Python 十分熟悉,精通大部分函数以及 Python 的特色:比如装饰器,迭代器,生成器以等,下面举几个简单的例子:

# 函数式编程

>>> nums = map(int, "123456789" )

>>> nums

[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])

15

>>> sum(nums)

45

# 生成器

>>> mygenerator = (x*x for x in range(3))

>>> for i in mygenerator:

... print i

...

0

1

4

>>> for i in mygenerator:

... print i

...

# lambda 匿名函数

>>> c = lambda *z: z

>>> c( 10, 'test')

(10, 'test')

# 迭代

>>> l = [i**2 for i in range(9)]

>>> l_iter = iter(l)

>>> next(l_iter)

0

>>> next(l_iter)

1

>>> next(l_iter)

4

# 数据结构 set

>>> set_a = set([i for i in range(1,9,2)])

>>> set_b = set([i for i in range(0,9,2)])

>>> print set_a | set_b

set([0, 1, 2, 3, 4, 5, 6, 7, 8])

其次,要多读一些 Pythonic 的代码,学习别人如何优雅地使用python。这里我推荐去看 Leetcode 的 Discuss,里面有许多惊才艳艳的代码。特别推荐 @StefanPochmann,许多代码让我获益匪浅,比如这里对 iter() 的使用。

再来看一个问题,按照二进制位反转 32 位的一个整形无符号数字。用 Python 可以写出很简单直观的代码,如下:

def reverseBits(n):

bit_str = '{0:032b}'.format(n)

reverse_str = bit_str[::-1]

return int(reverse_str, 2)

当然,上面不考虑效率,这里有一个利用分治法思想的高效的方法。

Python 是一门高效、简单、方便的语言,但这并不意味你不花时间就可以用的很好。

更多阅读

python的key函数_由 sort 中 key 的用法浅谈 python相关推荐

  1. 翻译pdf中的英文 python_浅谈python实现Google翻译PDF,解决换行的问题

    我们复制PDF到Google翻译时,总是会出现换行的情况,如果自己手动去除,那就太麻烦了. 那么用Python就可以解决,复制到粘贴板以后,Python程序自动可以把\n换成空格,然后我们就可以复制到 ...

  2. 关于python格式对齐的问题_[宜配屋]听图阁 - 浅谈python str.format与制表符\t关于中文对齐的细节问题...

    写了一个练手的爬虫...在输出的时候出现了让人很不愉♂悦的问题 像这样: 令人十分难受啊! #------------------------------------------ 在此之前先说一下py ...

  3. [python] 字典 pop(key)函数:删除字典中key及其值,并返回该值

    功能 删除字典给定键 key 及对应的值,返回值为被删除的值.key 不在字典中,则返回 default 值. 一般会在更新字典的时候用到. 语法 value_deleted = dict_name. ...

  4. python回测函数_【手把手教你】动量指标的Python量化回测

    我认为投资专业的学生只需要两门教授得当的课堂:如何评估一家公司,以及如何考虑市场价格.--巴菲特 01 引言 本文延续"手把手教你使用Python的TA-Lib"系列,以资金流量指 ...

  5. rails 调用php函数_潜藏在PHP安全的边缘——浅谈PHP反序列化漏洞

    潜藏在PHP安全的边缘--浅谈PHP反序列化漏洞 注意事项:1.本篇文章由复眼小组的瞳话原创,未经允许禁止转载2.本文一共1376字,8张图,预计阅读时间6分钟3.本文比较基础,请大佬酌情观看,如果有 ...

  6. vb6调用python识别训练例子_在vb6中创建的“标准”dll在python中调用时会出现访问冲突...

    从vb6dll导出函数的最简单方法是使用vbAdvance add-in,现在它是免费软件.在 您面临的问题是,您需要在调用导出的线程上初始化VB6运行时.这包括初始化COM单元(STA).最简单的方 ...

  7. python列表查找值_查找列表中某个值的位置(python)

    p=list.index(value) list为列表的名字 value为查找的值 p为value在list的位置 Python3.2.2列表操作总结 list操作:快速创建list.新增item.删 ...

  8. python sys模块作用_浅谈Python中的模块

    模块 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式.在Python中,一个.py文件就称之为一个模块(Mod ...

  9. python命名规则数字开头的成语_浅谈Python中带_的变量或函数命名

    搜索热词 Python 的代码风格由 PEP 8 描述.这个文档描述了 Python 编程风格的方方面面.在遵守这个文档的条件下,不同程序员编写的 Python 代码可以保持最大程度的相似风格.这样就 ...

  10. python中怎么调用函数_浅谈Python中函数的定义及其调用方法

    一.函数的定义及其应用 所谓函数,就是把具有独立功能的代码块组织成为一个小模块,在需要的时候调用函数的使用包含两个步骤 1.定义函数–封装独立的功能 2.调用函数–享受封装的成果 函数的作用:在开发时 ...

最新文章

  1. 如何解决ORA-12547错误!
  2. Codeforces 920D Tanks (看题解)
  3. layui table 单元格适应宽高
  4. 如何解决Maven依赖本地仓库eclipse报错的问题
  5. 特征工程框架及技术要点
  6. oracle数据库建语句吗,Oracle建表语句是什么_数据库
  7. java地铁最短_南京地铁最短路径以及最少换乘算法C++不用类
  8. 我自己在学arm7——ourdev
  9. pid纠偏算法C语言,基于MATLAB环境下智能PID纠偏控制算法的仿真分析.pdf
  10. python写身份证_python 关于身份证号码的相关操作
  11. 三维重建(知识点详细解读、主要流程)
  12. Python走心的42个代码例子
  13. python sin_Python入门之三角函数sin()函数实例详解
  14. 戴尔笔记本一键重装win7系统教程
  15. 【快速幂取模】NOI 7833:幂的末尾
  16. 金仓数据库 KingbaseGIS 使用手册(6.8. 几何对象输入函数)
  17. 编程初学者快速上手实战套路
  18. Web自动化测试面试
  19. 盘点SCI、SSCI、EI……的前世今生
  20. 电子科技大学 易查分网站 爬虫 批量爬取成绩

热门文章

  1. python 中搞错工作路径的意思导致的相对路径产生bug:[Errno 2] No such file or directory:
  2. LaTeX 参考文献的处理
  3. 致远oa系统报价_致远oa价格(致远oa系统登录)
  4. 优秀工程师必备的一项技能,你解锁了吗?
  5. opencv实践中遇到的问题
  6. 《Python编程从入门到实践 第二版》第十六章练习
  7. 笔记本/台式电脑数据迁移的简单办法
  8. 【C语言】案例十六:掷骰子(随机数)
  9. [半监督学习] Tri-Training: Exploiting Unlabeled Data Using Three Classifiers
  10. Wing Loss 论文阅读笔记