资讯专栏INFORMATION COLUMN

python的一些误区

yimo / 740人阅读

摘要:忽略了的版本这是一个在上不断被人提起的问题。不幸的是它只运行在系统上。误解了全局解释器锁意味着只有一个线程在一个程序可以运行在任何时间。规定的解决方案是使用模块。滥用使得上的一个大神花了很多时间去解决它。这可能会产生一些非常不必要的后果。

原文链接放在这里:1: http://nafiulis.me/potential-pythonic-pitfalls.html
很多问题没搞懂,先放在这里,慢慢改。
python是一门非常有趣的语言。它提供了许多非常方便的标准库和许多内置命令是我们轻松完成任务.但是好东西太多了就有选择恐惧症了,以至于我们不能很好第利用这个标准库和它的基本机构。下面列出了一些对python新手来说很简单有效的陷阱。


忽略了python的版本

这是一个在StackOverflow上不断被人提起的问题。当你完美的代码跑在别人的电脑上就报错是怎样一种体验,所以这个时候就需要检查你们的python版本是否一致。确保代码跑在自己知道的python版本上。你可以通过以下代码查看python版本:

$ python --version
Python 2.7.9
python版本管理

pyenv是一个不错的python版本管理工具。不幸的是它只运行在*nix系统上。在Mac OS上,你可以简单用brew install pyenv安装,在linux系统中,有一个自动安装器automatic installer

纠结于用一行代码解决所有问题

许多人夸口说我多牛用一行代码就解决了所有问题,即便他们的代码比正常写的更缺少效率,而且这些代码也会更难以阅读,甚至会出现歧义。比如说:

l = [m for a, b in zip(this, that) if b.method(a) != b for m in b if not m.method(a, b) and reduce(lambda x, y: a + y.method(), (m, a, b))]

老实说上面的代码是我自己为了说明这件事情写的。但是我可是真的见过有许多人这样干过。如果你只是简单通过把东西添加到一个list或者一个set中来显摆自己解决复杂问题的手段,那么你有可能会得不偿失。

一行代码控并不是什么巨大的成就,尽管有时候看起来特别聪明。优秀的代码是简洁但是更注重高效和易读。

错误地初始化set

这是一个更加微妙的问题,有时候会让你措手不及。set推导式起来有点像list推导式.

>>> { n for n in range(10) if n % 2 == 0 }
{0, 8, 2, 4, 6}
>>> type({ n for n in range(10) if n % 2 == 0 })

上面的例子说明了这点。set有点像放在容器中的list
它们的区别是set没有重复的值和无序的。人们通常会把{}认为是一个空的set,可它不是,它是一个空的dict.

>>> {}
{}
>>> type({})

所以如果我们想要初始化一个空的set,就直接使用set()

>>> set()
set()
>>> type(set())

注意一个空的set可以表示成set(),但是一个包含了元素的集合要被定义成set([1, 2])的样子。


误解了GIL

GIL(全局解释器锁)意味着只有一个线程在一个Python程序可以运行在任何时间。 这意味着当我们不能创建一个线程,并期望它并行运行。 Python解释器实际上做的是快速切换不同的运行线程。 但这是一个非常简单的版本。 在许多实例中程序并行运行,像使用C扩展的库时。 但Python代码运行时,大多数时候不会并行执行。换句话说,线程在Python中不像在Java或c++中一样。

许多人会尝试为Python辩解说,这些都是真正的线程。 3 这确实是真的,但并不能改变这样一个事实:Python处理线程的方式不同于你期望的那样。 Ruby也有类似的情况(还有一个解释器锁)。

规定的解决方案是使用multiprocessing模块。multiprocessing模块提供的过程类基本上可以很好地覆盖分歧。 然而,分歧比线程代价高得多。所以并行运行不总是好的。

然而,这个问题不是每个Python程序都会遇到。PyPy-stm就是Python的一个实现不受GIL影响的例子。 实现建立在其他平台上的像JVM(Jython) 或CLR(IronPython)没有GIL的问题。

总之,在使用时要小心线程类,你得到的可能不是你想要的。

使用过时的样式类

在Python 2有两种类型的类,“旧式”类,“新风格”类。 如果 你使用Python 3,那么你正在使用默认的“新风格”类。 为了确保你使用 “新风格”在Python 2类,您需要继承object或者任何你创建的不总是继承内建指令intlist的新类 。 换句话说,你的基类,应该总是继承object

class MyNewObject(object):
    # stuff here

这些"新类"修复了一些非常基本的出现在老式类中问题,如果你感兴趣可以查看文档

错误的迭代

下面的这些错误对新手来说非常常见:

for name_index in range(len(names)):
    print(names[name_index])

很明显没有必要使用len, 实际上遍历列表用非常简单的语句就可以实现:

 for name in names:
    print(name)  

此外,还有一大堆其他的工具在你处理简化迭代。 例如,zip可以用来遍历两个列表:

for cat, dog in zip(cats, dogs):
    print(cat, dog)

如果我们要考虑索引和值列表变量,我们可以使用enumerate

 for index, cat in enumerate(cats):
    print(cat, index)

在itertools中还有很多功能可以选择。如果itertools中有你想要的功能就很方便的拿来用。但是也不要过于为了用它而用它。

itertools滥用使得StackOverflow上的一个大神花了很多时间去解决它。

使用了可变的默认参数

我看过很多如下:

def foo(a, b, c=[]):
    # append to c
    # do some more stuff

不要使用可变的默认参数,而不是使用以下:

  def foo(a, b, c=None):
    if c is None:
        c = []
    # append to c
    # do some more stuff  

下面这个例子可以很直观地帮我们理解这个问题:

In[2]: def foo(a, b, c=[]):
...     c.append(a)
...     c.append(b)
...     print(c)
...
In[3]: foo(1, 1)
[1, 1]
In[4]: foo(1, 1)
[1, 1, 1, 1]
In[5]: foo(1, 1)
[1, 1, 1, 1, 1, 1]

相同的 c 被引用一次又一次的每一次调用该函数。 这可能会产生一些非常 不必要的后果。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/37543.html

相关文章

  • Python进阶:切片误区与高级用法

    摘要:与纯占位符相对应,非纯占位符的切片是非空列表,对它进行操作赋值与删除,将会影响原始列表。不同位置的替换非等长替换删除元素切片占位符可以带步长,从而实现连续跨越性的替换或删除效果。 2018-12-31 更新声明:切片系列文章本是分三篇写成,现已合并成一篇。合并后,修正了一些严重的错误(如自定义序列切片的部分),还对行文结构与章节衔接做了大量改动。原系列的单篇就不删除了,毕竟也是有单独成...

    liaorio 评论0 收藏0
  • Python - 装饰器使用过程中误区

    摘要:然而,当我们想要获取被包装函数的参数或源代码时,同样不能得到我们想要的结果。这是在中的,版本已被修复,参考。如同上面我们所看到的,可以帮我们解决和的问题,但对于获取函数的参数或源代码则束手无策。 装饰器基本概念 大家都知道装饰器是一个很著名的设计模式,经常被用于 AOP (面向切面编程)的场景,较为经典的有插入日志,性能测试,事务处理,Web权限校验, Cache等。 Python...

    1fe1se 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<