在Python3中初学者应会的一些基本的提升效率的小技巧

有时候我反问我自己,怎么不知道在Python 3中用更简单的方式做“这样”的事,当我寻求答案时,随着时间的推移,我当然发现更简洁、有效并且bug更少的代码。总的来说(不仅仅是这篇文章),“那些”事情总共数量是超过我想象的,但这里是第一批不明显的特性,后来我寻求到了更有效的/简单的/可维护的代码。
字典

字典中的keys()和items()

你能在字典的keys和items中做很多有意思的操作,它们类似于集合(set):


aa = {‘mike': ‘male', ‘kathy': ‘female', ‘steve': ‘male', ‘hillary': ‘female'}

bb = {‘mike': ‘male', ‘ben': ‘male', ‘hillary': ‘female'}

aa.keys() & bb.keys() # {‘mike', ‘hillary'} # these are set-like
aa.keys() - bb.keys() # {‘kathy', ‘steve'}
# If you want to get the common key-value pairs in the two dictionaries
aa.items() & bb.items() # {(‘mike', ‘male'), (‘hillary', ‘female')}

太简洁啦!

在字典中校验一个key的存在

下面这段代码你写了多少遍了?


dictionary = {}
for k, v in ls:
  if not k in dictionary:
    dictionary[k] = []
  dictionary[k].append(v)

这段代码其实没有那么糟糕,但是为什么你一直都需要用if语句呢?


from collections import defaultdict
dictionary = defaultdict(list) # defaults to list
for k, v in ls:
  dictionary[k].append(v)

这样就更清晰了,没有一个多余而模糊的if语句。

用另一个字典来更新一个字典


from itertools import chain
a = {‘x': 1, ‘y':2, ‘z':3}
b = {‘y': 5, ‘s': 10, ‘x': 3, ‘z': 6}

# Update a with b
c = dict(chain(a.items(), b.items()))
c # {‘y': 5, ‘s': 10, ‘x': 3, ‘z': 6}

这样看起来还不错,但是不够简明。看看我们是否能做得更好:


c = a.copy()
c.update(b)

更清晰而且更有可读性了!

从一个字典获得最大值

如果你想获取一个字典中的最大值,可能会像这样直接:


aa = {k: sum(range(k)) for k in range(10)}
aa # {0: 0, 1: 0, 2: 1, 3: 3, 4: 6, 5: 10, 6: 15, 7: 21, 8: 28, 9: 36}
max(aa.values()) #36

这么做是有效的,但是如果你需要key,那么你就需要在value的基础上再找到key。然而,我们可以用过zip来让展现更扁平化,并返回一个如下这样的key-value形式:


max(zip(aa.values(), aa.keys()))
# (36, 9) => value, key pair

同样地,如果你想从最大到最小地去遍历一个字典,你可以这么干:


sorted(zip(aa.values(), aa.keys()), reverse=True)
# [(36, 9), (28, 8), (21, 7), (15, 6), (10, 5), (6, 4), (3, 3), (1, 2), (0, 1), (0, 0)]

在一个list中打开任意数量的items

我们可以运用*的魔法,获取任意的items放到list中:


def compute_average_salary(person_salary):
  person, *salary = person_salary
  return person, (sum(salary) / float(len(salary)))

person, average_salary = compute_average_salary([“mike”, 40000, 50000, 60000])
person # ‘mike'
average_salary # 50000.0

这不是那么有趣,但是如果我告诉你也可以像下面这样呢:


def compute_average_salary(person_salary_age):
  person, *salary, age = person_salary_age
  return person, (sum(salary) / float(len(salary))), age

person, average_salary, age = compute_average_salary([“mike”, 40000, 50000, 60000, 42])
age # 42

看起来很简洁嘛!

当你想到有一个字符串类型的key和一个list的value的字典,而不是遍历一个字典,然后顺序地处理value,你可以使用一个更扁平的展现(list中套list),像下面这样:


# Instead of doing this
for k, v in dictionary.items():
  process(v)

# we are separating head and the rest, and process the values
# as a list similar to the above. head becomes the key value
for head, *rest in ls:
  process(rest)

# if not very clear, consider the following example
aa = {k: list(range(k)) for k in range(5)} # range returns an iterator
aa # {0: [], 1: [0], 2: [0, 1], 3: [0, 1, 2], 4: [0, 1, 2, 3]}
for k, v in aa.items():
  sum(v)

#0
#0
#1
#3
#6

# Instead
aa = [[ii] + list(range(jj)) for ii, jj in enumerate(range(5))]
for head, *rest in aa:
  print(sum(rest))

#0
#0
#1
#3
#6

你可以把list解压成head,*rest,tail等等。

Collections用作计数器

Collections是我在python中最喜欢的库之一,在python中,除了原始的默认的,如果你还需要其他的数据结构,你就应该看看这个。

我日常基本工作的一部分就是计算大量而又不是很重要的词。可能有人会说,你可以把这些词作为一个字典的key,他们分别的值作为value,在我没有接触到collections中的Counter时,我可能会同意你的做法(是的,做这么多介绍就是因为Counter)。

假设你读的python语言的维基百科,转化为一个字符串,放到一个list中(标记好顺序):


import re
word_list = list(map(lambda k: k.lower().strip(), re.split(r'[;,:(.s)]s*', python_string)))
word_list[:10] # [‘python', ‘is', ‘a', ‘widely', ‘used', ‘general-purpose', ‘high-level', ‘programming', ‘language', ‘[17][18][19]']

到目前为止看起来都不错,但是如果你想计算这个list中的单词:


from collections import defaultdict # again, collections!
dictionary = defaultdict(int)
for word in word_list:
  dictionary[word] += 1

这个没有那么糟糕,但是如果你有了Counter,你将会节约下你的时间做更有意义的事情。


from collections import Counter
counter = Counter(word_list)
# Getting the most common 10 words
counter.most_common(10)
[(‘the', 164), (‘and', 161), (‘a', 138), (‘python', 138),
(‘of', 131), (‘is', 102), (‘to', 91), (‘in', 88), (‘', 56)]
counter.keys()[:10] # just like a dictionary
[‘', ‘limited', ‘all', ‘code', ‘managed', ‘multi-paradigm',
‘exponentiation', ‘fromosing', ‘dynamic']

很简洁吧,但是如果我们看看在Counter中包含的可用的方法:


dir(counter)
[‘__add__', ‘__and__', ‘__class__', ‘__cmp__', ‘__contains__', ‘__delattr__', ‘__delitem__', ‘__dict__',
‘__doc__', ‘__eq__', ‘__format__', ‘__ge__', ‘__getattribute__', ‘__getitem__', ‘__gt__', ‘__hash__',
‘__init__', ‘__iter__', ‘__le__', ‘__len__', ‘__lt__', ‘__missing__', ‘__module__', ‘__ne__', ‘__new__',
‘__or__', ‘__reduce__', ‘__reduce_ex__', ‘__repr__', ‘__setattr__', ‘__setitem__', ‘__sizeof__',
‘__str__', ‘__sub__', ‘__subclasshook__', ‘__weakref__', ‘clear', ‘copy', ‘elements', ‘fromkeys', ‘get',
‘has_key', ‘items', ‘iteritems', ‘iterkeys', ‘itervalues', ‘keys', ‘most_common', ‘pop', ‘popitem', ‘setdefault',
‘subtract', ‘update', ‘values', ‘viewitems', ‘viewkeys', ‘viewvalues']

你看到__add__和__sub__方法了吗,是的,Counter支持加减运算。因此,如果你有很多文本想要去计算单词,你不必需要Hadoop,你可以运用Counter(作为map)然后把它们加起来(相当于reduce)。这样你就有构建在Counter上的mapreduce了,你可能以后还会感谢我。

扁平嵌套lists

Collections也有_chain函数,其可被用作扁平嵌套lists


from collections import chain
ls = [[kk] + list(range(kk)) for kk in range(5)]
flattened_list = list(collections._chain(*ls))

同时打开两个文件

如果你在处理一个文件(比如一行一行地),而且要把这些处理好的行写入到另一个文件中,你可能情不自禁地像下面这么去写:


with open(input_file_path) as inputfile:
  with open(output_file_path, ‘w') as outputfile:
    for line in inputfile:
      outputfile.write(process(line))

除此之外,你可以在相同的一行里打开多个文件,就像下面这样:


with open(input_file_path) as inputfile, open(output_file_path, ‘w') as outputfile:
  for line in inputfile:
    outputfile.write(process(line))

这样就更简洁啦!
从一堆数据中找到星期一

如果你有一个数据想去标准化(比如周一之前或是之后),你也许会像下面这样:


import datetime
previous_monday = some_date - datetime.timedelta(days=some_date.weekday())
# Similarly, you could map to next monday as well
next_monday = some_date + date_time.timedelta(days=-some_date.weekday(), weeks=1)

这就是实现方式。
处理HTML

如果你出于兴趣或是利益要爬一个站点,你可能会一直面临着html标签。为了去解析各种各样的html标签,你可以运用html.parer:

from html.parser import HTMLParser

class HTMLStrip(HTMLParser):

  def __init__(self):
    self.reset()
    self.ls = []

  def handle_data(self, d):
    self.ls.append(d)

  def get_data(self):
    return ‘'.join(self.ls)

  @staticmethod
  def strip(snippet):
    html_strip = HTMLStrip()
    html_strip.feed(snippet)
    clean_text = html_strip.get_data()
    return clean_text

snippet = HTMLStrip.strip(html_snippet)

如果你仅仅想避开html:

escaped_snippet = html.escape(html_snippet)

# Back to html snippets(this is new in Python 3.4)
html_snippet = html.unescape(escaped_snippet)
# and so forth ...
(0)

相关推荐

  • 盘点提高 Python 代码效率的方法

    第一招:蛇打七寸:定位瓶颈 首先,第一步是定位瓶颈.举个简单的栗子,一个函数可以从1秒优化到到0.9秒,另一个函数可以从1分钟优化到30秒,如果要花的代价相同,而且时间限制只能搞定一个,搞哪个?根据短板原理,当然选第二个啦. 一个有经验的程序员在这里一定会迟疑一下,等等?函数?这么说,还要考虑调用次数?如果第一个函数在整个程序中需要被调用100000次,第二个函数在整个程序中被调用1次,这个就不一定了.举这个栗子,是想说明,程序的瓶颈有的时候不一定一眼能看出来.还是上面那个选择,程序员的你应该有

  • Python 多线程抓取图片效率对比

    目的: 是学习python 多线程的工作原理,及通过抓取400张图片这种IO密集型应用来查看多线程效率对比 import requests import urlparse import os import time import threading import Queue path = '/home/lidongwei/scrapy/owan_img_urls.txt' #path = '/home/lidongwei/scrapy/cc.txt' fetch_img_save_path =

  • 分享Python开发中要注意的十个小贴士

    大家请注意:这篇文中假设我们都用的是Python 3 1. 列表推导式 你有一个list:bag = [1, 2, 3, 4, 5] 现在你想让所有元素翻倍,让它看起来是这个样子: [2, 4, 6, 8, 10] 大多初学者,根据之前语言的经验会大概这样来做 bag = [1, 2, 3, 4, 5] for i in range(len(bag)): bag[i] = bag[i] * 2 但是有更好的方法: bag = [elem * 2 for elem in bag] 很简洁对不对?这

  • Python while、for、生成器、列表推导等语句的执行效率测试

    一个功能的实现,可以用多种语句来实现,比如说:while语句.for语句.生成器.列表推导.内置函数等实现,然而他们的效率并不一样.写了一个小程序来测试它们执行的效率. 测试内容: 将一个数字大小为20万的数字,依次取绝对值,放到列表中,测试重复1千次. 测试程序: 复制代码 代码如下: import time,sys  reps = 1000                #测试重复次数  nums = 200000              #测试时数字大小      def tester(

  • 几个提升Python运行效率的方法之间的对比

    在我看来,python社区分为了三个流派,分别是python 2.x组织,3.x组织和PyPy组织.这个分类基本上可以归根于类库的兼容性和速度.这篇文章将聚焦于一些通用代码的优化技巧以及编译成C后性能的显著提升,当然我也会给出三大主要python流派运行时间.我的目的不是为了证明一个比另一个强,只是为了让你知道如何在不同的环境下使用这些具体例子作比较. 使用生成器 一个普遍被忽略的内存优化是生成器的使用.生成器让我们创建一个函数一次只返回一条记录,而不是一次返回所有的记录,如果你正在使用pyth

  • Python利用IPython提高开发效率

    一.IPython 简介 IPython 是一个交互式的 Python 解释器,而且它更加高效. 它和大多传统工作模式(编辑 -> 编译 -> 运行)不同的是, 它采用的工作模式是:执行 -> 探索 ,而大部分和数据分析相关的代 码都含有探索式操作(比如试误法和迭代法),所以 IPython 能大大提高编码效率. IPython 发展到现在,它不仅仅只是一个加强版的 Python shell 了, 它集成了 GUI 控制台,这可以让你直接进行绘图操作:它还有一个基于 Web 的交互式笔记

  • Python中map和列表推导效率比较实例分析

    本文实例讲述了Python中map和列表推导效率比较.分享给大家供大家参考.具体分析如下: 直接来测试代码吧: #!/usr/bin/env python # -*- coding: utf-8 -*- # list comprehension and map import time def test(f, name): st = time.time() f() print '%s %ss'%(name, time.time()-st) TIMES = 1000 ARR = range(1000

  • 提升Python程序运行效率的6个方法

    Python是一个很酷的语言,因为你可以在很短的时间内利用很少的代码做很多事情.不仅如此,它还能轻松地支持多任务,比如多进程等.Python批评者有时会说Python执行缓慢.本文将尝试介绍6个技巧,可加速你的Python应用程序. 1.让关键代码依赖于外部包 虽然Python让许多编程任务变得容易,但它可能并不总能为紧急的任务提供最佳性能.你可以为紧急的任务使用C.C++或机器语言编写的外部包,这样可以提高应用程序的性能.这些包都是不能跨平台的,这意味着你需要根据你正在使用的平台,寻找合适的包

  • 教你用Type Hint提高Python程序开发效率

    简介 Type Hint(或者叫做PEP-484)提供了一种针对Python程序的类型标注标准. 为什么使用Type Hint?对于动态语言而言,常常出现的情况是当你写了一段代码后,隔段时间你可能忘记这个方法的原型是什么样子的了,你也不清楚具体应该传入什么类型的参数,这样往往需要你去阅读代码才能定义每个类型具体是什么.或者当你使用一个文档并不是特别完全的第三方库,你不知道这个库应该如何使用,这都会很痛苦. 现在,借助Type Hint,你可以实现: 1.实现类型检查,防止运行时出现的类型不符合情

  • 六个窍门助你提高Python运行效率

    不喜欢Python的人经常会吐嘈Python运行太慢.但是,事实并非如此.尝试以下六个窍门,来为你的Python应用提速. 窍门一:关键代码使用外部功能包 Python简化了许多编程任务,但是对于一些时间敏感的任务,它的表现经常不尽人意.使用C/C++或机器语言的外部功能包处理时间敏感任务,可以有效提高应用的运行效率.这些功能包往往依附于特定的平台,因此你要根据自己所用的平台选择合适的功能包.简而言之,这个窍门要你牺牲应用的可移植性以换取只有通过对底层主机的直接编程才能获得的运行效率.以下是一些

随机推荐