- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章wtfPython—Python中一组有趣微妙的代码【收藏】由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
wtfPython是github上的一个项目,作者收集了一些奇妙的Python代码片段,这些代码的输出结果会和我们想象中的不太一样; 。
通过探寻产生这种结果的内部原因,可以让我们对Python里的一些细节有更广泛的认知.
1.字典键的隐式转换 。
1
2
3
4
|
some_dict
=
{}
some_dict[
5.5
]
=
"Ruby"
some_dict[
5.0
]
=
"JavaScript"
some_dict[
5
]
=
"Python"
|
输出如下:
>>> some_dict {5.0: "Python", 5.5: "Ruby"} >>> some_dict[5.5] "Ruby" >>> some_dict[5.0] "Python" >>> some_dict[5] "Python" 。
原因:
Python的字典键的比较是通过哈希值来比较的 。
在Python里如果两个不可变对象的值相等,那他们的哈希也是一样的 。
因此此处hash(5) == hash(5.0)是True的,所以键被隐式的转换了 。
2.生成器执行时间的差异 。
1
2
3
|
array
=
[
1
,
8
,
15
]
g
=
(x
for
x
in
array
if
array.count(x) >
0
)
array
=
[
2
,
8
,
22
]
|
输出:
>>> print(list(g)) [8] 。
原因 。
在一个生成器表达式里,in的操作是在声明时求值的,而if是在运行期求值的 。
所以在运行期之前,array已经被重新分配成了[2,8,22],x的值也是2,8,22 。
3.在列表迭代式删除item 。
1
2
3
4
5
6
7
8
9
10
11
12
|
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)
|
输出:
>>> list_1 [1, 2, 3, 4] >>> list_2 [2, 4] >>> list_3 [] >>> list_4 [2, 4] 。
原因 。
其实只有list3才算是合格的写法,对一个正在迭代的对象进行修改并不是一个很好的选择,正确的做法应该是建立一份该对象的拷贝来进行迭代 。
对于list1,del item删除的只是item变量而不是变量指向的数据,对列表本身没有影响 。
对于list2和list4,因为列表的迭代是根据索引来的,第一次删掉了索引为0的1,剩下[2, 3, 4],然后移除索引 1(此时为3),剩下了[2, 4],此时只有2个元素,循环结束 。
4.else的不同处理 。
对于循环的else 。
1
2
3
4
5
6
7
|
def
does_exists_num(l, to_find):
for
num
in
l:
if
num
=
=
to_find:
print
(
"Exists!"
)
break
else
:
print
(
"Does not exist"
)
|
输出:
>>> some_list = [1, 2, 3, 4, 5] >>> does_exists_num(some_list, 4) Exists! >>> does_exists_num(some_list, -1) Does not exist 。
对于try的else 。
1
2
3
4
5
6
|
try
:
pass
except
:
print
(
"Exception occurred!!!"
)
else
:
print
(
"Try block executed successfully..."
)
|
输出:
Try block executed successfully... 。
原因 。
循环后的else只会在经过了所有迭代且没有出现break的时候才会执行 。
一个try模块后的else会在try里的代码成功执行完后去执行 。
5.python里的is 。
1
2
3
4
5
6
7
8
|
>>> a = 256
>>> b = 256
>>> a is b
True
>>> a = 257
>>> b = 257
>>> a is b
False
|
原因 。
is和==是不一样的;is判断的是两个对象是否是同一个对象,而==判断的是两个对象的值是否相等;即is是既要值相等又要引用一致 。
在Python中-5~256因为被经常使用所以被设计成固定存在的对象 。
6.循环里的局部变量泄露 。
代码段1 。
1
2
3
4
|
for
x
in
range
(
7
):
if
x
=
=
6
:
print
(x,
': for x inside loop'
)
print
(x,
': x in global'
)
|
输出:
6 : for x inside loop 6 : x in global 。
代码段2 。
1
2
3
4
5
6
|
# This time let's initialize x first
x
=
-
1
for
x
in
range
(
7
):
if
x
=
=
6
:
print
(x,
': for x inside loop'
)
print
(x,
': x in global'
)
|
输出:
6 : for x inside loop6 : x in global 。
代码段3 。
1
2
3
|
x
=
1
print
([x
for
x
in
range
(
5
)])
print
(x,
': x in global'
)
|
在Python2.x里的输出:
[0, 1, 2, 3, 4](4, ': x in global') 。
在Python3.x里的输出:
[0, 1, 2, 3, 4]1 : x in global 。
原因 。
对于代码段1,在Python中,for循环可以使用包含他们的命名空间的变量,并将他们自己定义的循环变量保存下来;* 对于代码段2,如果我们在全局命名空间里显示定义for循环变量,则循环变量会重新绑定到现有变量上.
对于代码段3,在Python3.x中改变了对列表解析的语法形式;Python2.x中,列表解析的语法形式为:[… for var in item1, item2, …];而Python3.x的列表解析式为:[… for var in (item1, item2, …)],这种情况下不会发生循环变量的泄露 。
7.+和+=的区别 。
代码段1 。
1
2
3
|
a
=
[
1
,
2
,
3
,
4
]
b
=
a
a
=
a
+
[
5
,
6
,
7
,
8
]
|
输出:
>>> a [1, 2, 3, 4, 5, 6, 7, 8] >>> b [1, 2, 3, 4] 。
代码段2 。
1
2
3
|
a
=
[
1
,
2
,
3
,
4
]
b
=
a
a
+
=
[
5
,
6
,
7
,
8
]
|
。
输出:
>>> a [1, 2, 3, 4, 5, 6, 7, 8] >>> b [1, 2, 3, 4, 5, 6, 7, 8] 。
原因 。
a = a + b的操作生成了一个新的对象并建立了一个新的引用 。
a += b是在a这个列表上做extend操作 。
8.关于try—finally里的return 。
1
2
3
4
5
|
def
some_func():
try
:
return
'from_try'
finally
:
return
'from_finally'
|
输出:
>>> some_func() 'from_finally' 。
原因 。
在try…finally这种写法里面,finally中的return语句永远是最后一个执行 。
一个函数的return的值是由最后一个return语句来决定的 。
9.True=False 。
1
2
3
|
True
=
False
if
True
=
=
False
:
print
(
"I've lost faith in truth!"
)
|
输出:
I've lost faith in truth.
原因 。
最开始的时候,Python是没有bool类型的(使用0表示false,使用非0值表示真),后来加上了True,False和bool类型;但是为了向后兼容性,True和False并没有被设置成常量,而只是一个内建变量,所以可以被赋值修改 在Python3当中,因为并没有向后兼容,所以不会有这种情况发生 。
10.一步操作,从有到无 。
1
2
3
4
5
6
7
8
|
some_list
=
[
1
,
2
,
3
]
some_dict
=
{
"key_1"
:
1
,
"key_2"
:
2
,
"key_3"
:
3
}
some_list
=
some_list.append(
4
)
some_dict
=
some_dict.update({
"key_4"
:
4
})
|
输出:
>>> print(some_list) None >>> print(some_dict) None 。
原因 。
许多修改序列/映射对象的方法(例如list.append, dict.update, list.sort等等)都是直接修改对象并返回一个None;所以平常碰到这种直接修改的操作,应该避免直接赋值.
11.Python的for 。
1
2
3
|
for
i
in
range
(
4
):
print
(i)
i
=
10
|
输出:
0 1 2 3 。
原因 。
Python的for循环机制是每次迭代到下一项的时候都会解包并分配一次;即range(4)里的四个值在每次迭代的时候都会解包一次并赋值;所以i = 10对迭代没有影响.
总结 。
以上所述是小编给大家介绍的wtfPython—Python中一组有趣微妙的代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我网站的支持! 。
最后此篇关于wtfPython—Python中一组有趣微妙的代码【收藏】的文章就讲到这里了,如果你想了解更多关于wtfPython—Python中一组有趣微妙的代码【收藏】的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
文档:https://www.xfyun.cn/doc/spark/PPTGeneration.html 价格方面提供了免费1000点的额度,生成一次是10点,正好10
我有一个工具按钮和一个分配给它的操作。但该操作没有点击事件,也没有点击代码。因此该按钮被禁用,如何将其更改为启用? 谢谢! 最佳答案 当某个操作没有 OnExecute 处理程序时,该操作始终处于禁用
我有一个 C 程序,它初始化两个结构并尝试打印它们的值。请参阅下面的代码。 #include #include typedef struct node{ int data; struc
我在回答 this question当我想到这个例子时: #include void func(int i); void func(); int main (){ func(); r
这些bug可能够你喝一壶的。 1、被断言(assert)包含的代码 常发生在切换到release版本时,执行结果乖乖的,最终查找结果是assert括号里的代码在release下是不执行的。
我正在谈论一个独立的对象,稍后我想使用 saveOrUpdate() 进行更新。 我们如何同时设置 null 和clear()引用的集合? A[1:1]B[1:M]C B 到 C 的引用可以为空,这意
我最近完成了 Marjin Haverbeke 的书“Eloquent Javascript, Second Edition”中的一项挑战。 One had to create此控制台输出使用 for
我写了一个 HtmlHelper 表达式,我花了很多时间将标题标签放入我的下拉列表中,如下所示: public static HtmlString SelectFor( thi
你知道有哪些开放的软件项目有特别有趣/写得很好的单元测试吗? 编写单元测试对我来说通常感觉很奇怪,因为它似乎太随机、太密集、太稀疏,……阅读一些现实世界的例子(而不是书籍、图书馆示例代码等)会很棒。
我有一个我目前正在使用的 Silverlight 应用程序,它为其 MVVM 框架实现了 Caliburn.Micro。一切正常,但我注意到一些绑定(bind)中的一些有趣之处。我拥有的是处理应用程序
我通过 swscale 运行 png 图像数据以获取 YUV420P 数据,然后使用 MSMPEG4V1 编解码器对该帧进行编码,从而在 iPhone 上对一些视频进行编码。在 api 文档中,avc
我写了一个页面,发现 addEventListener("loadedmetadata",fun) 在 firefox 上运行不正确 我正在尝试修复一个旧软件的错误。在加载视频和页面时,该软件尝试在页
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我是一名优秀的程序员,十分优秀!