python汇编模式,WTF Python: 开启你的懵逼模式

a79919ca421abb346f89607a9725ad55.png

What the f*ck Python?

Python很流行很易学,但有时,Python代码片段的结果可能让小白们直接懵逼,现在大邓跟你一起开启懵逼模式

wtf-1 开胃菜hash

some_dict = {}some_dict[5.5] = "Ruby"some_dict[5.0] = "JavaScript"some_dict[5] = "Python"print(some_dict[5.5])print(some_dict[5.0])print(some_dict[5])

分析:

Ruby

Python

Python

Python字典检查相等,并比较key的hash值,以确定两个键是否相同。

同值不变的对象总是在Python中相同的hash值。

print(5==5.0)print(hash(5)==hash(5.0))

TrueTrue

wtf-2 生成器的if与in运行时间不同

array = [1, 8, 15]g = (x for x in array if array.count(x) > 0)array = [2, 8, 22]print(list(g))

分析:

[8]

在Python的生成器语法中,in语句是在声明时就计算执行的,而if语句则是在运行时(调用g时)计算执行的。

也就是说,一开始我们告诉Python,当我们运行g时,g生成器in语句是在声明时确定有array有1、8、15,但是if语句是基于执行时查看发现array只有2、8、22,经过计算只有8出现1次。所以返回[8]。

tips:大家自己揣摩把,我解释的也不是很给力。

wtf-3 迭代时修改字典

x = {0: None}for i in x:

del x[i]

x[i+1] = None

print(i)

0

1

2

3

4

分析:

只运行了5次,就停止了。

Python不支持迭代时对字典进行编辑(其实迭代时候也不能更改字典的容量)。

wtf-4 迭代时删除列表元素

list_1 = [1, 2, 3, 4]list_2 = [1, 2, 3, 4]list_3 = [1, 2, 3, 4]list_4 = [1, 2, 3, 4]for idx, item in enumerate(list_1):

del item

for idx, item in enumerate(list_2):

list_2.remove(item)for idx, item in enumerate(list_3[:]):

list_3.remove(item)for idx, item in enumerate(list_4):

list_4.pop(idx)

print(list_1)print(list_2)print(list_3)print(list_4)

分析:

[1, 2, 3, 4][2, 4][][2, 4]

在迭代ing时对自己进行修改是万万不可取的!!正确的做法是,使用备份数据迭代时对原数据进行修改。如list3,使用的是list3[:]。

some_list = [1, 2, 3, 4]print(id(some_list))print(id(some_list[:]))

4369310792

4369313544

del remove pop的区别

delvarname仅仅删除局部或全局命名空间的varname所绑定的数据,这也是为什么list_1没有收到影响。

removeremove函数移除的是第一个匹配(match)的元素。

poppop函数移除指定索引index值的元素,并且返回该元素。

为什么输出的是[2,4]?

第一次迭代 list2或者list4 为[1,2,3,4],index=0的元素为1。移除1

第二次迭代 list2或者list4 为[2,3,4],index=1的元素为3。移除3

第三次迭代 list2或者list4 为[3,4],没有index=2的元素,不再移除元素

所以,最后list2或者list4输出的是[2,4]

wtf-5 字符串后的反斜杠

print("\\ some string \\")print(r"\ some string")

运行正常

\ some string \

\ some string

但这里,却运行出问题

print(r"\ some string \")

File "", line 1

print(r"\ some string \")

^

SyntaxError: EOL while scanning string literal

分析:

在raw字符串(以r为前缀)中,反斜杠没有特殊含义。

但是反斜杠不能再字符串末尾。

wtf-6 创建句型字符串

这部分不是python的奇葩问题,而是仅仅是为了学习运行效率。

import timeit

def add_string_with_plus(iters):

s = ""

for i in range(iters):

s += "xyz"

#当s长度等于3倍的iters时,断言。程序停止。

assert len(s) == 3*iters

def add_string_with_format(iters):

fs = "{}"*iters

s = fs.format(*(["xyz"]*iters))

assert len(s) == 3*iters

def add_string_with_join(iters):

l = []

for i in range(iters):

l.append("xyz")

s = "".join(l)

assert len(s) == 3*iters

%timeit add_string_with_plus(10000)%timeit add_string_with_format(10000)%timeit add_string_with_join(10000)

分析:

1000 loops, best of 3: 1.63 ms per loop

1000 loops, best of 3: 778 µs per loop

1000 loops, best of 3: 1.44 ms per loop

从上面的例子我们以后要注意,拼接大量字符串时,+ 是很低效率的。最高效的是format,其次是join。

wtf-7 +=与+效率PK

def addequal():

s1 = ''

for i in range(10000):

s1 += str(i) + str(i+1)

return s1

def addonly():

s1 = ''

for i in range(10000):

s1 = s1 + str(i) + str(i+1)

return s1

%timeit addequal()%timeit addonly()

分析:

100 loops, best of 3: 8.48 ms per loop

10 loops, best of 3: 28.5 ms per loop

+= 比 + 快很多。+= 方法是在s1原地进行赋值覆盖操作,而+方法,相当于重新新建一个s1,并把值赋值给s1。所以+=更高效。

wtf-8 is 与 ==

a = 256b = 256print('256 id',id(256))print('a id:',id(a))print('b id:',id(b))print('a is b:',a is b)print('a == b:',a == b)

256 id 4297632096a id: 4297632096b id: 4297632096a is b: Truea == b: True

再来看看257

c = 257d = 257print('257 id',id(257))print('c id:',id(c))print('d id:',id(d))print('c is d:',c is d)print('c == d:',c == d)

257 id 4370421936c id: 4370422000d id: 4370420880c is d: Falsec == d: True

分析:

isis判断的是左右两边变量指向的是不是同一个对象(我们这里可以用变量的id判断是不是同一个对象。)

====判断的是左右两边的变量值是否相等。

当我们一启动python时,[-5,256]范围内的数值会被立刻分配出去。在上面的代码我们可以看到256、a、b的id都是相同的。

wtf-9 is not ... 不是 is (not ...)

print('not none' is not None)print('not none' is (not None))

TrueFalse

分析:

如果is not两边指向的是同一个对象,则返回False,否则返回True

😜好内容要多分享!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值