首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

全网目前最全python例子六、Python利器

Python利器

Python中的三大利器包括:迭代器,生成器,装饰器,利用好它们才能开发出最高性能的Python程序,涉及到的内置模块itertools提供迭代器相关的操作。此部分收录有意思的例子共计14例。

1 寻找第n次出现位置

def search_n(s, c, n):

size =

fori, xinenumerate(s):

ifx == c:

size +=1

ifsize == n:

returni

return-1

print(search_n("fdasadfadf","a",3))# 结果为7,正确

print(search_n("fdasadfadf","a",30))# 结果为-1,正确

2 斐波那契数列前n项

def fibonacci(n):

a, b =1,1

for_inrange(n):

yielda

a, b = b, a + b

list(fibonacci(5))# [1, 1, 2, 3, 5]

3 找出所有重复元素

fromcollectionsimportCounter

def find_all_duplicates(lst):

c = Counter(lst)

returnlist(filter(lambdak: c[k] >1, c))

find_all_duplicates([1,2,2,3,3,3])# [2,3]

4 联合统计次数

Counter对象间可以做数学运算

fromcollectionsimportCounter

a = ['apple','orange','computer','orange']

b = ['computer','orange']

ca = Counter(a)

cb = Counter(b)#Counter对象间可以做数学运算

ca + cb# Counter({'orange': 3, 'computer': 2, 'apple': 1})

# 进一步抽象,实现多个列表内元素的个数统计

def sumc(*c):

if(len(c)

return

mapc = map(Counter, c)

s = Counter([])

foricinmapc:# ic 是一个Counter对象

s += ic

returns

#Counter({'orange': 3, 'computer': 3, 'apple': 1, 'abc': 1, 'face': 1})

sumc(a, b, ['abc'], ['face','computer'])

5 groupby单字段分组

天气记录:

a = [{'date':'2019-12-15','weather':'cloud'},

{'date':'2019-12-13','weather':'sunny'},

{'date':'2019-12-14','weather':'cloud'}]

按照天气字段weather分组汇总:

fromitertoolsimportgroupbyfork, itemsingroupby(a,key=lambdax:x['weather']):

print(k)

输出结果看出,分组失败!原因:分组前必须按照分组字段排序,这个很坑~

cloud

sunny

cloud

修改代码:

a.sort(key=lambdax: x['weather'])fork, itemsingroupby(a,key=lambdax:x['weather']):

print(k)

foriinitems:

print(i)

输出结果:

cloud

{'date':'2019-12-15','weather':'cloud'}

{'date':'2019-12-14','weather':'cloud'}

sunny

{'date':'2019-12-13','weather':'sunny'}

6 itemgetter和key函数

注意到sort和groupby所用的key函数,除了lambda写法外,还有一种简写,就是使用itemgetter:

a = [{'date':'2019-12-15','weather':'cloud'},

{'date':'2019-12-13','weather':'sunny'},

{'date':'2019-12-14','weather':'cloud'}]fromoperatorimportitemgetterfromitertoolsimportgroupby

a.sort(key=itemgetter('weather'))fork, itemsingroupby(a, key=itemgetter('weather')):

print(k)

foriinitems:

print(i)

结果:

cloud

{'date':'2019-12-15','weather':'cloud'}

{'date':'2019-12-14','weather':'cloud'}

sunny

{'date':'2019-12-13','weather':'sunny'}

7 groupby多字段分组

itemgetter是一个类,itemgetter('weather')返回一个可调用的对象,它的参数可有多个:

fromoperatorimportitemgetterfromitertoolsimportgroupby

a.sort(key=itemgetter('weather','date'))fork, itemsingroupby(a, key=itemgetter('weather')):

print(k)

foriinitems:

print(i)

结果如下,使用weather和date两个字段排序a,

cloud

{'date':'2019-12-14','weather':'cloud'}

{'date':'2019-12-15','weather':'cloud'}

sunny

{'date':'2019-12-13','weather':'sunny'}

注意这个结果与上面结果有些微妙不同,这个更多是我们想看到和使用更多的。

8 sum函数计算和聚合同时做

Python中的聚合类函数sum,min,max第一个参数是iterable类型,一般使用方法如下:

a = [4,2,5,1]

sum([i+1foriina])# 16

使用列表生成式[i+1 for i in a]创建一个长度与a一行的临时列表,这步完成后,再做sum聚合。

试想如果你的数组a长度十百万级,再创建一个这样的临时列表就很不划算,最好是一边算一边聚合,稍改动为如下:

a = [4,2,5,1]

sum(i+1foriina)# 16

此时i+1 for i in a是(i+1 for i in a)的简写,得到一个生成器(generator)对象,如下所示:

In [8]:(i+1foriina)

OUT [8]: at0x000002AC7FFA8CF0>

生成器每迭代一步吐出(yield)一个元素并计算和聚合后,进入下一次迭代,直到终点。

9 list分组(生成器版)

frommathimportceil

def divide_iter(lst, n):

yieldlst

return

i, div =, ceil(len(lst) / n)

whilei

yieldlst[i * div: (i +1) * div]

i +=1

list(divide_iter([1,2,3,4,5],))# [[1, 2, 3, 4, 5]]

list(divide_iter([1,2,3,4,5],2))# [[1, 2, 3], [4, 5]]

10 列表全展开(生成器版)

#多层列表展开成单层列表

a=[1,2,[3,4,[5,6],7],8,["python",6],9]def function(lst):

foriinlst:

iftype(i)==list:

yieldfromfunction(i)

else:

yieldi

print(list(function(a)))# [1, 2, 3, 4, 5, 6, 7, 8, 'python', 6, 9]

11 测试函数运行时间的装饰器

#测试函数执行时间的装饰器示例importtimedef timing_func(fn):

def wrapper():

start=time.time()

fn()#执行传入的fn参数

stop=time.time()

return(stop-start)

returnwrapper@timing_funcdef test_list_append():

lst=[]

foriinrange(,100000):

lst.append(i)@timing_funcdef test_list_compre():

[iforiinrange(,100000)]#列表生成式

a=test_list_append()

c=test_list_compre()

print("test list append time:",a)

print("test list comprehension time:",c)

print("append/compre:",round(a/c,3))

test list append time:0.0219423770904541

test list comprehension time:0.007980823516845703

append/compre:2.749

12 统计异常出现次数和时间的装饰器

写一个装饰器,统计某个异常重复出现指定次数时,经历的时长。

importtimeimportmath

def excepter(f):

i =

t1 = time.time()

def wrapper():

try:

f()

exceptExceptionase:

nonlocali

i +=1

print(f': ')

t2 = time.time()

ifi == n:

print(f'spending time:')

returnwrapper

关键词nonlocal常用于函数嵌套中,声明变量i为非局部变量;

如果不声明,i+=1表明i为函数wrapper内的局部变量,因为在i+=1引用(reference)时,i未被声明,所以会报unreferenced variable的错误。

使用创建的装饰函数excepter,n是异常出现的次数。

共测试了两类常见的异常:被零除和数组越界。

n =10# except count

@excepterdef divide_zero_except():

time.sleep(0.1)

j =1/(40-20*2)

# test zero divived exceptfor_inrange(n):

divide_zero_except()

@excepterdef outof_range_except():

a = [1,3,5]

time.sleep(0.1)

print(a[3])# test out of range exceptfor_inrange(n):

outof_range_except()

打印出来的结果如下:

division by zero:1

division by zero:2

division by zero:3

division by zero:4

division by zero:5

division by zero:6

division by zero:7

division by zero:8

division by zero:9

division by zero:10

spending time:1.01

list index out of range:1

list index out of range:2

list index out of range:3

list index out of range:4

list index out of range:5

list index out of range:6

list index out of range:7

list index out of range:8

list index out of range:9

list index out of range:10

spending time:1.01

13 定制递减迭代器

#编写一个迭代器,通过循环语句,实现对某个正整数的依次递减1,直到0.class Descend(Iterator):

def __init__(self,N):

self.N=N

self.a=

def __iter__(self):

returnself

def __next__(self):

whileself.a

self.N-=1

returnself.N

raiseStopIteration

descend_iter=Descend(10)

print(list(descend_iter))

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

核心要点:

1__nex__名字不能变,实现定制的迭代逻辑

2raise StopIteration:通过raise中断程序,必须这样写

14 测试运行时长的装饰器

#测试函数执行时间的装饰器示例importtimedef timing(fn):

def wrapper():

start=time.time()

fn()#执行传入的fn参数

stop=time.time()

return(stop-start)

returnwrapper

@timingdef test_list_append():

lst=[]

foriinrange(,100000):

lst.append(i)

@timingdef test_list_compre():

[iforiinrange(,100000)]#列表生成式

a=test_list_append()

c=test_list_compre()

print("test list append time:",a)

print("test list comprehension time:",c)

print("append/compre:",round(a/c,3))

# test list append time: 0.0219# test list comprehension time: 0.00798# append/compre: 2.749

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200311A0QG7C00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券