用 Python 时间也算不短了,但总感觉自己在用写 C++ 代码的思维写 Python,没有真正用到其作为脚本语言的优势。之前刷 LeetCode 时,自己的 Python 代码总是很长,很像披着 Python 外衣的 C++ 代码(放在这里,不断重构中)。
想来大概是因为觉得python简单,平时只是零零碎碎的学习,也没有去读别人的代码,导致掌握的不够深入。回想起前段时间的面试,面试官看我简历写熟悉Python,就问了两个Python的问题:
- Python 中常用的优化技巧(能够提升 Python 执行效率的,除了算法层面)
- 按照 value 从小到大输出 dict 中的 key-value值。
我支支吾吾半天,就是没有答到点上,直接导致被拒(后来整理的内容放在这里)。所谓知耻而后勇,经过一段时间对 Python 的重新学习,才慢慢发现 Python 的一些强大与美妙之处。
从排序说起!
程序中经常用到排序函数,Python 提供了 sort 和 sorted 函数,一个原地排序,一个返回排序后的新结果,函数原型很简单:
1 |
sort([cmp[, key[, reverse]]]) |
自己用的最多的类似下面的语句:
1 2 3 4 |
>>> 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 可谓是理解透彻了。比如要要根据值的大小输出字典内容,那么就可以像下面这样优雅地解决:
1 2 3 |
>>> 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
即可:
1 2 3 4 |
>>> 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 中元组是可被比较的)。所以上面的排序问题可以用下面的代码来解决:
1 2 3 |
>>> 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代码。比如要判断一个数字是否是回文数字,可能会习惯性地写出下面这样的代码:
1 2 3 4 5 6 7 8 9 |
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++会更加合适,单对这题来说,其实有比上面更高效的方法)!
想来大概是因为觉得python简单,平时只是零零碎碎的学习,也没有去读别人的代码,导致掌握的不够深入。回想起前段时间的面试,面试官看我简历写熟悉Python,就问了两个Python的问题:
- Python 中常用的优化技巧(能够提升 Python 执行效率的,除了算法层面)
- 按照 value 从小到大输出 dict 中的 key-value值。
我支支吾吾半天,就是没有答到点上,直接导致被拒(后来整理的内容放在这里)。所谓知耻而后勇,经过一段时间对 Python 的重新学习,才慢慢发现 Python 的一些强大与美妙之处。
从排序说起!
程序中经常用到排序函数,Python 提供了 sort 和 sorted 函数,一个原地排序,一个返回排序后的新结果,函数原型很简单:
1 |
sort([cmp[, key[, reverse]]]) |
自己用的最多的类似下面的语句:
1 2 3 4 |
>>> 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 可谓是理解透彻了。比如要要根据值的大小输出字典内容,那么就可以像下面这样优雅地解决:
1 2 3 |
>>> 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
即可:
1 2 3 4 |
>>> 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 中元组是可被比较的)。所以上面的排序问题可以用下面的代码来解决:
1 2 3 |
>>> 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代码。比如要判断一个数字是否是回文数字,可能会习惯性地写出下面这样的代码:
1 2 3 4 5 6 7 8 9 |
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 |