Python的惯例

Python编程技巧

迭代一个数组

Python 的for语句并不和C语言的一样,更像其他语言的foreach. 如果你需要在迭代中使用索引,标准的做法是:

array = [1, 2, 3, 4, 5]  # or whatever

for i in range(len(array)):
    # Do something with 'i'.

这是相当笨拙的,更干净简洁的做法是:

array = [1, 2, 3, 4, 5]  # or whatever

for i, e in enumerate(array):
    # Do something with index 'i' and its corresponding element 'e'.

打断无限循环

Python并不像C语言有do/while语句,它只有一个while循环语句和for循环语句,有时你并不会提前知道什么时候循环会结束,或者你需要打破循环。一个不能再普通的例子就是正在按行迭代一个文件内容:

file = open("some_filename", "r")

while 1:   # infinite loop
    line = file.readline()
    if not line:  # 'readline()' returns None at end of file.
        break

    # Process the line.

这样做并不聪明,但是足够规范。对于文件来说还有一个更漂亮的做法:

file = open("some_filename", "r")

for line in file:
    # Process the line.

注意Python中也有一个continue语句(就像C中的)来跳过本次循环进入下一次循环。

注意内置函数file()open() 一样,而且现在更流行了(因为对象的构造器应该和这个对象一个名字)

序列乘法

在Python中,链表和字符串都是序列,它们有很多一样的操作(比如 len()).一个不太明显的惯用手法是序列乘法.想要得到一个包含100个0的链表,你可以这么做:

zeroes = [0] * 100
类似地,可以这样做来获取一个包含100个空格的字符串:
spaces = 100 * " "
这很方便。

异常类

以前Python中的异常仅仅是简单的字符串。现在不同了,因为类有了很多新的进步。特别是,你可以为异常定义子类,可以选择性的捕捉一些异常或者捕捉它们的超类。异常类一般不复杂.一个典型的异常类看起来是这样的:

class MyException:
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return `self.value`

这样使用:

try:
    do_stuff()
    if something_bad_has_happened():
        raise MyException, "something bad happened"
except MyException, e:
    print "My exception occurred, value: ", e.value

列表生成式

这是Python中全新的一个特征,来源于函数式编程语言Haskell(很酷的编程语言,顺便告诉你,你应该看看haskell)

其思想是:有时你想要为具有某些特征的对象做一个链表,比如你想要为0到20的偶数做一个链表:

results = []
for i in range(20):
    if i % 2 == 0:
        results.append(i)

results 里面就是结果:[0, 2, 4, 6, 8, 10, 12, 14, 16, 18] (没有20,因为range(20)是从019).但是同样的事情你可以用列表生成式来做地更简洁些:

results = [x for x in range(20) if x % 2 == 0]

列表生成式是循环的语法糖.你可以做些更复杂的:

results = [(x, y)
           for x in range(10)
           for y in range(10)
           if x + y == 5
           if x > y]

结果 results[(3, 2), (4, 1), (5, 0)] . 所以你可以在方括号中写任意多个for和if语句(可能更多,详细参见文档), 你可以用列表生成式来实现快速排序算法:

def quicksort(lst):
    if len(lst) == 0:
        return []
    else:
        return quicksort([x for x in lst[1:] if x < lst[0]]) + [lst[0]] + \
               quicksort([x for x in lst[1:] if x >= lst[0]])

优美吗? :-)

函数式编程

Python实现了很多平常只出现在函数式编程语言(像lisp和ML)中的函数和特性。
map() reduce() filter() 函数
map() 需要一个函数和几个序列做参数(通常一个),然后对于序列的每个元素作为函数的参数,所有的返回值产生一个新的序列作为map的返回值。比如你想要把一个字符串链表转换成数字链表:

lst = ["1", "2", "3", "4", "5"]
nums = map(string.atoi, lst)  # [1, 2, 3, 4, 5]

(译者注:Py2.7中使用 map(int, lst) )
你可以对两个参数的函数使用map:

def add(x, y):
    return x + y

lst1 = [1, 2, 3, 4, 5]
lst2 = [6, 7, 8, 9, 10]
lst_sum = map(add, lst1, lst2)

# lst_sum == [7, 9, 11, 13, 15]

(译者注:这个函数可以有任意多参数,map的后面的参数要跟相应多的序列即可)
你可以使用 reduce()来把一个序列减少成一个值。第一个参数是函数,这个函数首先作用于序列的第一个和第二个元素,然后用返回的值继续和序列的第三个元素执行这个函数。。。直到剩下一个值,作为reduce的返回值.比如,你可以这么来求09的和:

reduce(lambda x, y: x+y, range(10))

(译者注:这里为了讲解,一般推荐直接用函数 sum() )

你可以使用 filter() 来生成一个序列的子集。比如,获取0到100的所有奇数:

nums = range(0,101)  # [0, 1, ... 100]

def is_odd(x):
    return x % 2 == 1

odd_nums = filter(is_odd, nums)  # [1, 3, 5, ... 99]

lambda 关键字

lambda 语句声明了一个匿名的函数,很多时候我们在reducemap等函数中使用的函数只使用了一次。这些函数可以被简洁地声明为匿名函数:

lst1 = [1, 2, 3, 4, 5]
lst2 = [6, 7, 8, 9, 10]
lst_elementwise_sum = map(lambda x, y: x + y, lst1, lst2)
lst1_sum = reduce(lambda x, y: x + y, lst1)
nums = range(101)
odd_nums = filter(lambda x: x % 2 == 1, nums)

注意,你仍然可以在lambda函数中使用这个匿名函数外定义的变量。这叫做“词法范围”(lexical scoping),在Python 2.2时官方性地给出了介绍.就像这样:

a = 1
add_a = lambda x: x + a
b = add_a(10)  # b == 11

lambda中的 a 是在上一行定义的。如果你认为这是显然的,很好!事实证明很多Python开发者花了很多时间来搞明白它。

apply 函数

在python中函数是对象,你可以像操作数和字符串一样操作它们(把它们存在变量中等等),有时你有一个函数对象,你想把程序中生成的一个序列作为参数传给这个函数:

# Sorry about the long variable names ;-)

args = function_returning_list_of_numbers()
f    = function_returning_a_function_which_operates_on_a_list_of_numbers()

# You want to do f(arg[0], arg[1], ...) but you don't know how many
# arguments are in 'args'.  For this you have to use 'apply':

result = apply(f, args)

# A trivial example:
args = [1, 1]
two = apply(lambda x, y: x + y, args)  # == 2

译者注:之所以我们不经常用apply() ,一般可以这么做:

args = [1, 1]
foo = lambda x, y: x+y
foo(*args)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值