Python入门笔记
1.比如在游戏中经常需要从一个点移动到另一个点,给出坐标、位移和角度,就可以计算出新的坐标: # math包提供了sin()和 cos()函数,我们先用import引用它: import math def move(x, y, step, angle): nx = x + step * math.cos(angle) ny = y - step * math.sin(angle) return nx, ny 这样我们就可以同时获得返回值: >>> x, y = move(100, 100, 60, math.pi / 6) >>> print x, y 151.961524227 70.0 但其实这只是一种假象,Python函数返回的仍然是单一值: >>> r = move(100, 100, 60, math.pi / 6) >>> print r (151.96152422706632, 70.0) 用print打印返回结果,原来返回值是一个tuple! 但是,在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple,但写起来更方便。 range()函数可以创建一个数列: >>> range(1, 101) [1, 2, 3, ..., 100] 请利用切片,取出: 1. 前10个数; 2. 3的倍数; 3. 不大于50的5的倍数。 L = range(1, 101) print L[0:10] print L[2::3] print L[4:51:5] 2.倒序切片 对于list,既然Python支持L[-1]取倒数第一个元素,那么它同样支持倒数切片,试试: >>> L = ['Adam', 'Lisa', 'Bart', 'Paul'] >>> L[-2:] ['Bart', 'Paul'] >>> L[:-2] ['Adam', 'Lisa'] >>> L[-3:-1] ['Lisa', 'Bart'] >>> L[-4:-1:2] --第三个参数2:每个两个数取一个,也即取数之间间隔1 ['Adam', 'Bart'] 记住倒数第一个元素的索引是-1。倒序切片包含起始索引,不包含结束索引。 3.迭代dict的key和value 我们了解了如何迭代 dict 的key和value,那么,在一个 for 循环中,能否同时迭代 key和value?答案是肯定的。 首先,我们看看 dict 对象的 items() 方法返回的值: >>> d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 } >>> print d.items() [('Lisa', 85), ('Adam', 95), ('Bart', 59)] 可以看到,items() 方法把dict对象转换成了包含tuple的list,我们对这个list进行迭代,可以同时获得key和value: >>> for key, value in d.items(): ... print key, ':', value ... Lisa : 85 Adam : 95 Bart : 59 和 values() 有一个 itervalues() 类似, items() 也有一个对应的 iteritems(),iteritems() 不把dict转换成list,而是在迭代过程中不断给出 tuple,所以, iteritems() 不占用额外的内存。 4.List.enumerate()函数用法 对于有序集合,元素确实是有索引的。有的时候,我们确实想在 for 循环中拿到索引,怎么办? 方法是使用 enumerate() 函数: >>> L = ['Adam', 'Lisa', 'Bart', 'Paul'] >>> for index, name in enumerate(L): ... print index, '-', name ... 0 - Adam 1 - Lisa 2 - Bart 3 - Paul 使用 enumerate() 函数,我们可以在for循环中同时绑定索引index和元素name。但是,这不是 enumerate() 的特殊语法。实际上,enumerate() 函数把: ['Adam', 'Lisa', 'Bart', 'Paul'] 变成了类似: [(0, 'Adam'), (1, 'Lisa'), (2, 'Bart'), (3, 'Paul')] 因此,迭代的每一个元素实际上是一个tuple: for t in enumerate(L): index = t[0] name = t[1] print index, '-', name 如果我们知道每个tuple元素都包含两个元素,for循环又可以进一步简写为: for index, name in enumerate(L): print index, '-', name 这样不但代码更简单,而且还少了两条赋值语句。 可见,索引迭代也不是真的按索引访问,而是由 enumerate() 函数自动把每个元素变成 (index, element) 这样的tuple,再迭代,就同时获得了索引和元素本身。 5.生成列表 要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],我们可以用range(1, 11): >>> range(1, 11) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 但如果要生成[1x1, 2x2, 3x3, ..., 10x10]怎么做?方法一是循环: >>> L = [] >>> for x in range(1, 11): ... L.append(x * x) ... >>> L [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 但是循环太繁琐,而列表生成式则可以用一行语句代替循环生成上面的list: >>> [x * x for x in range(1, 11)] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 这种写法就是Python特有的列表生成式。利用列表生成式,可以以非常简洁的代码生成 list。 任务 请利用列表生成式生成列表 [1x2, 3x4, 5x6, 7x8, ..., 99x100] 提示:range(1, 100, 2) 可以生成list [1, 3, 5, 7, 9,...] range函数第三个参数表示生成数列的步长 print [y * (y + 1) for y in range(1,101,2)] 6.条件过滤 列表生成式的 for 循环后面还可以加上 if 判断。例如: >>> [x * x for x in range(1, 11)] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 如果我们只想要偶数的平方,不改动 range()的情况下,可以加上 if 来筛选: >>> [x * x for x in range(1, 11) if x % 2 == 0] [4, 16, 36, 64, 100] 有了 if 条件,只有 if 判断为 True 的时候,才把循环的当前元素添加到列表中。 任务 请编写一个函数,它接受一个 list,然后把list中的所有字符串变成大写后返回,非字符串元素将被忽略。 提示: 1. isinstance(x, str) 可以判断变量 x 是否是字符串; 2. 字符串的 upper() 方法可以返回大写的字母。 def toUppers(L): return [l.upper() for l in L if isinstance(l,str)] print toUppers(['Hello', 'world', 101]) 二、函数及类的用法 1.map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。 例如,对于list [1, 2, 3, 4, 5, 6, 7, 8, 9] 如果希望把list的每个元素都作平方,就可以用map()函数: 因此,我们只需要传入函数f(x)=x*x,就可以利用map()函数完成这个计算: def f(x): return x*x print map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) 输出结果: [1, 4, 9, 10, 25, 36, 49, 64, 81] 注意:map()函数不改变原有的 list,而是返回一个新的 list。 利用map()函数,可以把一个 list 转换为另一个 list,只需要传入转换函数。 2.python中reduce()函数 reduce()函数也是Python内置的一个高阶函数。reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传入的函数 f 必须接收两个参数,reduce()对list的每个元素反复调用函数f,并返回最终结果值。 例如,编写一个f函数,接收x和y,返回x和y的和: def f(x, y): return x + y 调用 reduce(f, [1, 3, 5, 7, 9])时,reduce函数将做如下计算: 先计算头两个元素:f(1, 3),结果为4; 再把结果和第3个元素计算:f(4, 5),结果为9; 再把结果和第4个元素计算:f(9, 7),结果为16; 再把结果和第5个元素计算:f(16, 9),结果为25; 由于没有更多的元素了,计算结束,返回结果25。 上述计算实际上是对 list 的所有元素求和。虽然Python内置了求和函数sum(),但是,利用reduce()求和也很简单。 reduce()还可以接收第3个可选参数,作为计算的初始值。如果把初始值设为100,计算: reduce(f, [1, 3, 5, 7, 9], 100) 3.filter()函数是 Python 内置的另一个有用的高阶函数,filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。 例如,要从一个list [1, 4, 6, 7, 9, 12, 17]中删除偶数,保留奇数,首先,要编写一个判断奇数的函数: def is_odd(x): return x % 2 == 1 然后,利用filter()过滤掉偶数: filter(is_odd, [1, 4, 6, 7, 9, 12, 17]) 结果:[1, 7, 9, 17] 利用filter(),可以完成很多有用的功能,例如,删除 None 或者空字符串: def is_not_empty(s): return s and len(s.strip()) > 0 filter(is_not_empty, ['test', None, '', 'str', ' ', 'END']) 结果:['test', 'str', 'END'] 注意: s.strip(rm) 删除 s 字符串中开头、结尾处的 rm 序列的字符。 当rm为空时,默认删除空白符(包括'\n', '\r', '\t', ' '),如下: a = ' 123' a.strip() 结果: '123' a='\t\t123\r\n' a.strip() 结果:'123'
4.多层表达式
for循环可以嵌套,因此,在列表生成式中,也可以用多层 for 循环来生成列表。
对于字符串 'ABC' 和 '123',可以使用两层循环,生成全排列:
>>> [m + n for m in 'ABC' for n in '123']
['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']
翻译成循环代码就像下面这样:
L = []
for m in 'ABC':
for n in '123':
L.append(m + n)
任务
利用 3 层for循环的列表生成式,找出对称的 3 位数。例如,121 就是对称数,因为从右到左倒过来还是 121。
?不会了怎么办
百位的循环从 1-9,十位和个位的循环从 0-9。
参考代码:
print [100 * n1 + 10 * n2 + n3 for n1 in range(1, 10) for n2 in range(10) for n3 in range(10) if n1==n3]