python学习零碎记三

本文是廖雪峰教程学习记录,廖雪峰链接:http://blog.csdn.NET/GarfieldEr007/article/details/52422494?locationNum=1&fps=1


切片、迭代、enumerate、collections.Iterable、isinstance、列表生成式、生成器generator、map()、reduce()、lambda函数、join、filter、strip、修饰器decorator、偏函数functools.partial


①切片

取list中的元素:L[a:b:c],索引a开始的b个元素中,每c个取一个

>>> L=['A','B','C','D','E']

>>> L[0:3]
['A', 'B', 'C'] #取索引0开始,索引3前的元素

>>> L[-3:-1]
['C', 'D'] #取索引-3开始,索引-1前的元素

>>> L[-2:] #索引-2以后的元素
['D', 'E']


>>> L=range(100)

>>> L[:10:2] #前10个数,每两个取一个
[0, 2, 4, 6, 8]


>>> (1, 2, 3, 4, 5)[2:5]#tuple
(3, 4, 5)
>>> 'ABCDEFG'[2:5] #string
'CDE'

>>> u'ABCDEFG'[2:5]#Unicode
u'CDE'


二、迭代

for循环遍历list、tuple、dict、字符串等,这种遍历成为迭代。

遍历dict:

>>> d={'a':1,'b':2,'c':3}#默认迭代的是key
>>> for key in d:
...     print key
...
a
c
b

>>> for value in d.itervalues():#迭代value
...     print value
...
1
3
2
>>> for k,v in d.iteritems(): #key、value一起迭代
...     print k,v
...
a 1
c 3
b 2


通过collections模块的Iterable类型可判断对象是否可迭代:

>>> from collections import Iterable
>>> isinstance('abc',Iterable)
True

import和from……import的区别:直接输Iterable到程序中,而不用使用collections.Iterable

>>> import collections
>>> isinstance('abc',collections.Iterable)
True


Python内置的enumerate函数可把list转变成索引-元素对,使得可以在for循环中迭代索引、元素对:

>>> for i, value in enumerate(['A','B','C']):
...     print i, value
...

当然也可以:

>>> for i in range(3):
...     print i, ['A','B','C'][i]
...


for循环中同时引用两个变量还如:

>>> for x, y in [(1, 1), (2, 4), (3, 9)]: 

...     print x, y

 ... 


三、列表生成式

List Comprehensions,强大的创建list的生成式:

>>> range(1,11) #生成简单1~10
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> L=[]
>>> for i in range(1,11): #生成1*1 ~10*10
...     L.append(i*i)
...
>>> L
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> [i*i for i in range(1,11)] #简化上述循环
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

>>> [i*i for i in range(1,11) if i%2 ==0]#后面还可跟if
[4, 16, 36, 64, 100]

>>> [m+n for m in 'ABC' for n in 'XYZ']#还可两层循环
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

列表生成式可列出当前目录下所有目录和文件,一行代码即可实现:

>>> import os #os模块
>>> [d for d in os.listdir('.')] #listdir可列出文件和目录
['a.py', 'a.pyc', 'b.py', 'def.py', 'math.py', 'test1.py', 'while.py']


上述二中,dict的key、value一起迭代的for循环也可以用列表生成式:

>>> d={'a':'A','b':'B','c':'C'}#key和value不是同种类型时好像有问题来着?报错了
>>> [k + '='+ v for k,v in d.iteritems()]
['a=A', 'c=C', 'b=B']

将list中的所有字符串变成小写:

>>> L=['Hello', 'World', 'Hello', 'Everyone']
>>> [s.lower() for s in L]
['hello', 'world', 'hello', 'everyone']


四、生成器

在Python中,这种一边循环一边计算的机制,称为生成器(Generator),这样可以节省内存,元素需要时再生成。

generator的生成方法有两种:

一直接把列表生成式的[]改为():

>>> L=[x*x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g=(x*x for x in range(10))
>>> g
<generator object <genexpr> at 0x000000000312BA20>
>>> g.next()
0
>>> g.next()
1
>>> for n in g:
...     print n
...
4
9
16
25
36
49
64
81

generator生成的第二种方法:

斐波拉契数列用列表生成式表达不出来,可用函数表达,在函数定义中包含yield关键字,就变成了generator:

def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b #将普通函数的print b
a, b = b, a + b
n=n + 1

五、

变量可以指向函数

>>> f=abs
>>> f(-10)
10

函数名可以看成变量,如abs可以看成一个变量,指向一个可以计算绝对值的函数。

函数可以接收另一个函数作为参数,即高阶函数。

六、map()/reduce()

map()函数有两个参数:一个是函数,另一个是序列,map 将传入的函数依次作用到序列的每个元 素,并把结果作为新的list返回。

eg:

>>> def f(x):
...     return x*x
...
>>> map(f,[1,2,3,4,5,6,7,8,9])
[1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> map(f,range(1,10))
[1, 4, 9, 16, 25, 36, 49, 64, 81]


>>> map(str,range(1,10))
['1', '2', '3', '4', '5', '6', '7', '8', '9']


reduce用法。

reduce把一个函数作用在一个序列[x1,x2,x3...]上,这个函数须接收两个参数,reduce把结果继续和序列的下一个元素做累积运算,即为:

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

eg:

序列求和

>>> def add(x, y):
...     return x + y
...
>>> reduce(add, [1, 2, 3, 4])
10

将字符串'13579'转成数字13579可使用reduce和map函数:

>>> def str2int(s):
...     def fx(x, y):
...             return x*10+y
...     def char2num(s):
...             return {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}[s]
...     return reduce(fn, map(char2num, s))
...
>>> str2int('12345')
12345

可用lambda函数精简该函数:

>>> def char2num(s):
...     return {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}[s]
...
>>> def str2int(s):
...     return reduce(lambda x, y: x*10+y, map(char2num, s))
...

lambda函数:起到一个函数速写的作用。允许在代码内嵌入一个函数的定义

>>> f=lambda x, y, z: x+y+z
>>> f(1,2,3)
6

练习:

1、利用 map() 函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输 入: ['adam', 'LISA', 'barT'] ,输出: ['Adam', 'Lisa', 'Bart'] 。

>>> def f(s):
...     L=[]
...     L.append(s[0:1].upper())
...     for i in range(1,4):
...             L.append(s[i:i+1].lower())
...     return ''.join(L) #''.join(L)可把list的各元素连起来转化成字符串,''单引号中可填用#什么连接各元素,如空格,加号
...

>>> map(f, ['adam','LISA','barT'])
['Adam', 'Lisa', 'Bart']


2、Python提供的 sum() 函数可以接受一个list并求和,请编写一个 prod() 函数,可以接受一个list并利用 reduce() 求 积。

>>> L=[1,2,3,4]

>>> def mul(x,y):
...     return x*y
...

>>> def prod(L):
...     return reduce(mul,L)
...
>>>
>>> prod(L)
24

七、filter

Python内建的 filter() 函数用于过滤序列。

filter()接收一个函数和一个序列,把传入的函数一次作用于每个序列里的元素,来觉得是否舍弃该元素。

把一个序列的空字符串删掉:

>>> def not_empty(s):
...     return s and s.strip()# strip() 方法用于移除字符串头尾指定的字符(默认为空格)。
...
>>> filter(not_empty,['A', '', 'B', None, 'C', ' '])
['A', 'B', 'C']

 strip() 方法用于移除字符串头尾指定的字符(默认为空格)。

>>> str="000000hello how are you00000"
>>> str.strip('0')
'hello how are you'
>>> str="    hello how are you    "
>>> str.strip()
'hello how are you'


八、sorted

sorted函数可以对list排序

>>> sorted([4,2,5,11])
[2, 4, 5, 11]

sorted也可以接收一个比较函数实现自定义排序:

>>> def reversed_cmp(x,y):
...     if x>y:
...             return -1
...     if x<y:
...             return 1
...     return 0
...
>>> sorted([4,2,5,11], reversed_cmp)
[11, 5, 4, 2]


九、函数作为返回值

高阶函数除了可以把函数作为入参,也可以把函数作为返回值

可变参数的求和,不是立即需要和,而是在后面的代码中,根据需要再计算怎么办?可以不返回求和的结果,而是返回求 和的函数!

>>> def lazy_sum(*args):
...     def sum():
...             ar=0
...             for n in args:
...                     ar=ar+n
...             return ar
...     return sum
...

>>> f
<function sum at 0x000000000381EF28>
>>> f() #调用f时,才真正计算求和结果

25

当调用 lazy_sum() 时,每次调用都会返回一个新的函数,即使传入相同的参数:

>>> f1=lazy_sum(1,3,5,7,9)
>>> f2=lazy_sum(1,3,5,7,9)
>>> f1==f2
False

当 lazy_sum 返回函数 sum 时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closur e)”

返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。


十、装饰器

>>> def now():
...     print '2013-12-25'
...
>>> f=now
>>> f()
2013-12-25

>>> f.__name__ #函数对象有个__name__属性,可以拿到函数的名字
'now'

们要增强 now() 函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改 now() 函数的定 义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。

>>> def log(func): #定义一个能打印日志的decorator
...     def wrapper(*args, **kw):
...             print 'call %s():' % func.__name__
...             return func(*args, **kw)
...     return wrapper
...

借助Python 的@语法,把decorator置于函数的定义处:

>>> @log #把@log放到此处,相当于执行了now=log(now)
... def now():
...     print '2013-12-25'
...

>>> now()
call now():
2013-12-25

>>> now.__name__
'wrapper'

上面@log处,相当于执行now=log(now),原来的now()函数仍存在,只不过现在同名的now变量指向了新的函数,

于是调用now()执行新的函数。

若decorator需传入参数

>>> def log(text):
...     def decorator(func):
...             def wrapper(*args,**kw):
...                     print '%s %s():' % (text, func.__name
__)
...                     return func(*args,**kw)
...             return wrapper
...     return decorator
...
>>> @log('execute') #相当于执行了log('execute')(now)
... def now():
...     print '2013-12-25'
...
>>> now()
execute now():
2013-12-25

此时:

>>> now.__name__
'wrapper'

__name__从now变成了wrapper,需要把原始函数的 __name__ 等属性复制 到 wrapper() 函数中,import functools 后,在定义 wrapper() 的前面加 上 @functools.wraps(func) 即可。

练习:

1、请编写一个decorator,能在函数调用的前后打印出 'begin call' 和 'end call' 的日志。


十一、偏函数

Python的 functools 模块提供了很多有用的功能,其中一个就是偏函数(Partial function)

>>> int('100000',base=2)
32

若想把大量的二进制转化为十进制,可定义带默认参数base=2的函数int2来简化:

def int2(x, base=2):

return int(x, base)

functools.partial可不需要再自定义int2

>>> import functools
>>> int2=functools.partial(int,base=2)
>>> int2('100000')
32

可知functools.partial的作用是把函数的某些参数设为默认参数,返回一个新的函数。

创建偏函数,参数可以当做是①函数对象②*args③**kw这三个参数

故上面base=2可当做是固定了关键字参数。


>>> max2=functools.partial(max,10)#10作为*args的一部分传到左边
>>> max2(5,6,7) #max(10,5,6,7)
10


十二、模块

(一)

一个.py文件是一个模块。为避免不同人写的模块名字相同,可按目录来组织模块,称为包package。

每个包目录下有个__init__.py文件,可为空文件,也可有代码,它也是模块,模块名是包名。


#!/usr/bin/env python#使可以在Linux运行

# -*- coding: utf-8 -*-#使用标准utf-8编码

'test_module.py' #模块的第一个字符串被视为文档的注释,可用变量__doc__访问

__author__ = 'hello' #__author__作者

import sys

def test():
args = sys.argv#sys模块的argv变量是个list,储存了所有变量,  

#执行python test_module.py hello aa时,sys.argv=['test_module.py',#'hello', 'aa']
if len(args)==1:
print 'Hello World'
print args
elif len(args)==2:
print 'Hello, %s' % args[1]
print args
else:
print 'Too many arguments'
print args

if __name__=='__main__': #在命令行运行test_module模块时,Python解释器把变量__name__置为#__main,若在其他地方import test_module时,不执行test()函数
test()

print ' aaaaa ',__name__#导入时,__此处__name__为test_module


(二)模块别名

try: 

import cStringIO as StringIO#优先使用cStringIO

except ImportError: # 导入失败会捕获到ImportError

import StringIO#导入cStringIO失败才用StringIO

(三)模块函数变量作用域

公有变量:可被外部访问,如abc

私有变量:不希望被外部访问,定义时可用_前缀,如_abc

特殊变量:__name__、__doc__、__author__等

(四)搜索路径

>>> import sys

>>> sys.path
['', 'C:\\WINDOWS\\SYSTEM32\\python27.zip', 'C:\\Python27\\DL
Ls', 'C:\\Python27\\lib', 'C:\\Python27\\lib\\plat-win', 'C:\
\Python27\\lib\\lib-tk', 'C:\\Python27', 'C:\\Python27\\lib\\
site-packages']

>>>sys.path.append('********')

十三、__future__模块

该模块提供把Python下个版本的特性代码导入当前版本,来测试新版本特性。

在2.7的版本中,可使用unicode_literals来使用3.x的版本的字符串表示方法:2.7的'xxx'表str,u'xxx'表unicode,3.x的'xxx'和u'xxx'都表unicode,3.x以'xxx'表示的str前面必须加b,即b'xxx',表二进制字符串。

from __future__ import unicode_literals

在2.x中运行3.x的除法,可用__future__中的division实现:2.x中,两整数相除也为整数,3.x两整数相除都为精确商,若得到像2.x的整数结果,可用//表示。


















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值