前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python编程这两处陷阱,很容易忽视

Python编程这两处陷阱,很容易忽视

作者头像
double
发布2019-05-29 15:38:16
3530
发布2019-05-29 15:38:16
举报
文章被收录于专栏:算法channel算法channel

全文1929字,阅读时间3分钟,点击蓝色字体关注

号内福利

精华文章大合集: 认真就能打动人:273篇干货资料汇总

机器学习入门视频 吴恩达机器学习完整系列视频教程

承接上文:Python解惑之对象可变与不可变,文中提到,对象的可变(mutable object) 与不可变(immutable object)值得重视。不可变对象更改会创建很多新的对象,造成内存堆积;可变对象,易于修改,也会产生副作用。

分别通过两个经典例子解释:不可变和可变对象之陷阱。

不可变对象陷阱

思路:生成1百万个随机字符串,分别使用不可对象或可变对象合并字符串,比较花费时间。

生成随机字符串的代码:

代码语言:javascript
复制
import random import time
big = [chr(i) for i in range(65,91)]small = [chr(i) for i in range(97,123)] 
def randNStr(n):     ...:     result = []     ...:     for i in range(n):     ...:         strlen = random.randint(3,9)     ...:         result.append(''.join(random.sample(small+big,strlen)))     ...:     return result 

使用不可变对象方法:combine+s 再赋值给combine,这条语句:因为combine, s都为不可变对象,返回的结果就是新生成一个对象,对象不断堆积。

def immfn(n): ...: combine='' ...: res = randNStr(n) ...: beg = time.time() ...: print('beg time %s'%str(beg)) ...: for s in res: ...: combine = combine + s ...: #print(combine) ...: end = time.time() ...: print('end time %s'%str(end)) ...: print('elispe time: %s'%str(end-beg))

为了避免重复生成新的对象,使用可变对象,文中 Python解惑之对象可变与不可变 提到过,一般可迭代对象,都是可变的。

代码语言:javascript
复制
def mutfn(n):     ...:     combine=''     ...:     res = randNStr(n)     ...:     beg = time.time()     ...:     print('beg time %s'%str(beg))     ...:     combine = ''.join(res)     ...:     #print('print result:%s'%combine)     ...:     end = time.time()         ...:     print('end time %s'%str(end))     ...:     print('elispe time: %s'%str(end-beg)) 

此处使用 str.join(iter),接受可迭代对象,并只返回一个新对象。比较以上两种方法的计算时间,分别从10万,步长10万,终止到100万,比较分析合并字符串的时间。

可以看到可变对象只生成一个新对象的方法,比不可变对象在数据量越大情况下,优势更明显,呈现扩张的喇叭口,当数据为90万时,节省时间成本高达:(0.19-0.025)/0.025 = 6.6 倍。当数据量增长到1千万或更大时,优势更明显。

可变对象陷阱

BAT面试题26:一道Python填空题

这篇文章是号内推送过的一篇文章,也是Python一道经典面试题,非常容易掉入考官陷阱。再分析一遍。

题目是这样的:

代码语言:javascript
复制
def f(x,l=[]):    ...:     for i in range(x):    ...:        l.append(i*i)    ...:     print(l) 
f(2)f(3)
结果为: 
In [2]: f(2)                                                                                         [0, 1]
In [3]: f(3)                                                                                         [0, 1, 0, 1, 4]

原因,可变对象作为函数参数,并被设为默认值后,当被再次调用函数后,函数参数原来取值将被再次索引。

为了避免这个问题,可变对象的默认值一般取值为常数:None

代码语言:javascript
复制
def f(x,l=None):    ...:     if l is None:    ...:         l = []    ...:     for i in range(x):    ...:        l.append(i*i)    ...:     print(l)    ...:      

这样连续被调用时,将会按照预期输出。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员郭震zhenguo 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档