Skip to content

Latest commit

 

History

History
321 lines (199 loc) · 9.06 KB

qa-control-flow.md

File metadata and controls

321 lines (199 loc) · 9.06 KB

如何结束退出一个python脚本

问题 链接

import sys
sys.exit()

foo is None 和 foo == None的区别

问题 链接

if foo is None: pass
if foo == None: pass

如果比较相同的对象实例,is总是返回True 而 == 最终取决于 "eq()"

>>> class foo(object):
    def __eq__(self, other):
        return True

>>> f = foo()
>>> f == None
True
>>> f is None
False

>>> list1 = [1, 2, 3]
>>> list2 = [1, 2, 3]
>>> list1==list2
True
>>> list1 is list2
False

另外

(ob1 is ob2) 等价于 (id(ob1) == id(ob2))

如何在循环中获取下标

问题 链接

使用enumerate

for idx, val in enumerate(ints):
    print idx, val

python中如何将一行长代码切成多行

问题 链接

例如:

e = 'a' + 'b' + 'c' + 'd'
变成
e = 'a' + 'b' +
    'c' + 'd'

括号中,可以直接换行

a = dostuff(blahblah1, blahblah2, blahblah3, blahblah4, blahblah5,
            blahblah6, blahblah7)

非括号你可以这么做

a = '1' + '2' + '3' + \
    '4' + '5'
或者
a = ('1' + '2' + '3' +
    '4' + '5')

可以查看下代码风格: style guide 推荐是后一种,但某些个别情况下,加入括号会导致错误

为何1 in [1,0] == True执行结果是False

问题 链接

有如下

>>> 1 in [1,0]             # This is expected
True
>>> 1 in [1,0] == True     # This is strange
False
>>> (1 in [1,0]) == True   # This is what I wanted it to be
True
>>> 1 in ([1,0] == True)   # But it's not just a precedence issue!
                           # It did not raise an exception on the second example.

Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
      1 in ([1,0] == True)
      TypeError: argument of type 'bool' is not iterable

这里python使用了比较运算符链

1 in [1,0] == True

将被转为

(1 in [1, 0]) and ([1, 0] == True)

很显然是false的

同样的

a < b < c

会被转为

(a < b) and (b < c) # b不会被解析两次

具体文档

Python中的switch替代语法

问题 链接

python中没有switch,有什么推荐的处理方法么

使用字典:

def f(x):
    return {
        'a': 1,
        'b': 2,
    }.get(x, 9)

Python Cookbook中的几种方式

Readable switch construction without lambdas or dictionaries

Exception-based Switch-Case

Using a Dictionary in place of a 'switch' statement

使用 'if x is not None' 还是'if not x is None'

问题 链接

我总想着使用 'if not x is None' 会更加简明

但是google的Python风格指南使用的却是 'if x is not None'

性能上没有什么区别,他们编译成相同的字节码

Python 2.6.2 (r262:71600, Apr 15 2009, 07:20:39)
>>> import dis
>>> def f(x):
...    return x is not None
...
>>> dis.dis(f)
2           0 LOAD_FAST                0 (x)
            3 LOAD_CONST               0 (None)
            6 COMPARE_OP               9 (is not)
            9 RETURN_VALUE
>>> def g(x):
...   return not x is None
...
>>> dis.dis(g)
2           0 LOAD_FAST                0 (x)
            3 LOAD_CONST               0 (None)
            6 COMPARE_OP               9 (is not)
            9 RETURN_VALUE

在风格上,我尽量避免 'not x is y' 这种形式,虽然编译器会认为和 'not (x is y)'一样,但是读代码的人或许会误解为 '(not x) is y'

如果写作 'x is not y' 就不会有歧义

最佳实践

if x is not None:
    # Do something about x

在非创建全局变量的地方使用全局变量

问题 链接

如果我在一个函数中创建了全局变量,如何在另一个函数中使用?

回答:

你可以在给全局变量赋值的函数中声明 global

globvar = 0

def set_globvar_to_one():
    global globvar    # Needed to modify global copy of globvar
    globvar = 1

def print_globvar():
    print globvar     # No need for global declaration to read value of globvar

set_globvar_to_one()
print_globvar()       # Prints 1

我猜想这么做的原因是,全局变量很危险,Python想要确保你真的知道你要对一个全局的变量进行操作

如果你想知道如何在模块间使用全局变量,查看其他回答

如何检测一个变量是否存在

问题 链接

我想检测一个变量是否存在,我现在是这么做的

try:
    myVar
except NameError:
    # Doint smth

存在其他不是使用exception的方式么?

回答

检测本地变量

if 'myVar' in locals():
    # myVar exists.

检测全局变量

if 'myVar' in globals():
    # myVar exists.

检测一个对象是否包含某个属性

if hasattr(obj, 'attr_name'):
    # obj.attr_name exists.

Python中是否存在三元运算符

问题 链接

三元运算在Python2.5中被加入

a if test else b

使用

>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'

官方文档:

Conditional expressions

Is there an equivalent of C’s ”?:” ternary operator?

Python中的do-while

问题 链接

实现方法

while True:
    stuff()
    if fail_condition:
        break

或者

stuff()
while not fail_condition:
    stuff()

相对于range() 应该更倾向于实用xrange()?

问题 链接

why or why not?

就性能而言, 特别是当你迭代一个大的range, xrange()更优. 但是, 有一些情况下range()更优

  • 在Python3中, range() 等价于 python2.x的 xrange(), 而xrange()不存在了.(如果你的代码将在2和3下运行, 不能使用xrange)

  • range()在某些情况下更快, 例如, 多次重复遍历同一个序列.

  • xrange()并不适用于所有情况, 例如, 不支持slices以及任意的list方法

在Python中,“i += x”和“i = i + x”什么时候不等

问题链接

这完全取决于i这个对象。

+=调用了__iadd__方法(如果存在—不存在就退一步调用__add__),然而+调用__add__方法^1

从一个API的角度,__iadd__期望被使用在恰当的位置修改易变的对象(返回的对象也是转变后的),而__add__应该返回某些东西的一个新的实例。对于不可变对象,两种方法都返回新的实例,但__iadd__会把新的实例放在和旧实例名字相同的命名空间里。这就是为什么

i = 1
i += 1

看上去增量i,实际上,你得到了一个新的数值,并且转移到了i的最上面—丢掉了旧的数值的引用。在这种情况下,i += 1i = i + 1是完全一样的。但是,对于大多数可变对象,这是完全不同的:

一个具体的例子:

a = [1, 2, 3]
b = a
b += [1, 2, 3]
print a  #[1, 2, 3, 1, 2, 3]
print b  #[1, 2, 3, 1, 2, 3]

对比一下:

a = [1, 2, 3]
b = a
b = b + [1, 2, 3]
print a #[1, 2, 3]
print b #[1, 2, 3, 1, 2, 3]

注意第一个例子,从ba代表相同的对象开始,当我对b使用+=,实际上它改变了ba看起来也改变了- -毕竟他们代表同一个列表)。但是在第二个例子里,当我进行b = b + [1, 2, 3]操作时,b被引用并且和一个新的列表[1, 2, 3]联系了起来。之后在b的命名空间保存了这个关联的列表- -不考虑b之前的序列。