python基础进阶归纳
切片
取一个list或tuple的部分元素 如取前3元素 >>> L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack'] L[0] L[1]或循环取比较麻烦 切片取 >>> L[0:3] //取前3 >>> L[:3] //取前3 >>> L[1:3] //取索引1开始元素到索引3元素 2个 >>> L[-2:] //取倒数2开始的元素 >>> L[::5] //取索引0 5 10...的元素 >>> L[:] //取出所有 即复制
迭代(Iteration)
前面也学过 for key in item 遍历list或tuple 也可以遍历索引 用enumerate >>> for i, value in enumerate(['A', 'B', 'C']): print(i, value) 那遍历dist怎么办 也可以通过for ... in d = {'a': 1, 'b': 2, 'c': 3} >>> for key in d: //遍历key print(key) for value in d.values() //遍历value for k, v in d.items() //遍历k v //判断是否可以遍历迭代 >>> isinstance([1,2,3], Iterable) # list是否可迭代 True >>> isinstance(123, Iterable) # 整数是否可迭代 False
列表生成式
>>> list(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] 但有更简化的方式 >>> [x * x for x in range(1, 11)] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] //for循环后面还可以加上if判断 >>> [x * x for x in range(1, 11) if x % 2 == 0] [4, 16, 36, 64, 100] //还可以使用两层循环 >>> [m + n for m in 'ABC' for n in 'XYZ'] ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ'] //字符串变成小写 >>> L = ['Hello', 'World', 'IBM', 'Apple'] >>> [s.lower() for s in L] ['hello', 'world', 'ibm', 'apple'] //汇总:表达式不难理解 [变量 forin 过滤条件] 过滤条件可以用if 不能用if... else... 因为else是确定值了不是判断的过滤条件 应当放到forin前面 如 >>> [x if x % 2 == 0 else -x for x in range(1, 11)] [-1, 2, -3, 4, -5, 6, -7, 8, -9, 10]
生成器generator
首先list表达式符号[] generator表达式符号() list有多少元素直接占多少空间 获取list直接获取所有 如下所示 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 <generator object <genexpr> at 0x1022ef630> >>> for n in g: //一个个取出generator ... print(n) //上例是通过()符号定义generator 也可以通过函数def的方式定义 def fib(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b n = n + 1 return 'done' //上例中带yield表示函数是一个generator函数 yield是输出的元素值 >>> for n in fib(6): ... print(n) ... 1 1 2 3 5 8 //如上 用forin不能获取函数的返回值 返回值是在异常StopIteration信息中 如下获取 >>> g = fib(6) >>> while True: ... try: ... x = next(g) ... print('g:', x) ... except StopIteration as e: ... print('Generator return value:', e.value) ... break ... g: 1 g: 1 g: 2 g: 3 g: 5 g: 8 Generator return value: done
函数
一个简单的内置函数的例子 >>> abs(-10) 10 //注意:变量可以指向函数 >>> f = abs >>> f(-10) 10 //注意:变量名千万不能取函数名称 会导致函数不能使用 >>> abs = 10 >>> abs(-10) Traceback (most recent call last): //注意:定义的函数也可以传入函数作为参数 def add(x, y, f): return f(x) + f(y) 调用add(-5, 6, abs)时 返回abs(-5) + abs(6) 的结果
map()
有个函数 >>> def f(x): ... return x * x 有个list [1, 2, 3, 4, 5, 6, 7, 8, 9] 现在要把list每个元素去调函数 返回list 如下 L = [] for n in [1, 2, 3, 4, 5, 6, 7, 8, 9]: L.append(f(n)) print(L) 现在有更简便的方法map() map有2个参数 第一个是函数 第二个是Iterable >>> list(map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])) [1, 4, 9, 16, 25, 36, 49, 64, 81]
reduce()
reduce()与map()基本相似 map参数中的函数参数只有1个 reduce中函数的参数2个 如 >>> def fn(x, y): ... return x * 10 + y ... >>> reduce(fn, [1, 3, 5, 7, 9]) 13579
filter()过滤
filter()与map语法一致 不同的是filter()中函数是返回值为true或false 以此过滤集合 如过滤为余数为1 def is_odd(n): return n % 2 == 1 list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])) # 结果: [1, 5, 9, 15] 如 过滤回数(正读 反读都一样如98789)数 def is_palindrome(n): return str(n) == str(n)[::-1] filter(is_palindrome, range(1, 1000))
sorted()排序
//对list排序 >>> sorted([36, 5, -12, 9, -21]) [-21, -12, 5, 9, 36] //也可以通过key=函数 自定义排序 >>> sorted([36, 5, -12, 9, -21], key=abs) [5, 9, -12, -21, 36] //字母排序按ascii码排序 大写字母<小写字母 >>> sorted(['bob', 'about', 'Zoo', 'Credit']) ['Credit', 'Zoo', 'about', 'bob'] //忽略大小写 >>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower) ['about', 'bob', 'Credit', 'Zoo'] //反向排序reverse=True >>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True) ['Zoo', 'Credit', 'bob', 'about']
函数作为返回值
如定义个简单的函数 def calc_sum(*args): ax = 0 for n in args: ax = ax + n return ax //上例改下 def中再定义def def lazy_sum(*args): def sum(): ax = 0 for n in args: ax = ax + n return ax return sum //调用lazy_sum 返回值是一个函数 >>> f = lazy_sum(1, 3, 5, 7, 9) >>> f <function lazy_sum.<locals>.sum at 0x101c6ed90> //再调用函数f得到结果 >>> f() 25 //注意注意!返回函数不能带有后续可变的变量 如 def count(): fs = [] for i in range(1, 4): def f(): return i*i fs.append(f) return fs f1, f2, f3 = count() //期望结果1 4 9 但是实际结果 9 9 9 //因为i是循环可变的 函数f()返回i*i 等i最后为3时才会return //解决方法就是新建一个返回函数的函数 该函数参数绑定可变变量 如下f(j) def count(): def f(j): def g(): return j*j return g fs = [] for i in range(1, 4): fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f() return fs
lambda 匿名函数
就是lambda函数 如: def f(x): return x * x 可以简化写法 f = lambda x: x * x def is_odd(n): return n % 2 == 1 L = list(filter(is_odd, range(1, 20))) 简化写成 L = list(filter(lambda n: n%2==1,range(1, 20)))
装饰器
前面也了解到 变量可以指向函数 如下 >>> def now(): ... print('2015-3-25') ... >>> f = now >>> f() 2015-3-25 >>> f.__name__ //获取到实际的函数名称 'now' //假如上例的def now()函数 我想不修改代码的情况下新增日志 类似代理模式 //新增log代理函数 参数为函数 返回函数 def log(func): def wrapper(*args, **kw): print('call %s():' % func.__name__) return func(*args, **kw) return wrapper 将@log写在now函数上面即完成代理 如下 @log def now(): print('2015-3-25') //这样的话我们可以发现调用now函数实际上调wrapper函数 还需将__name__改下 @functools.wraps(func)注解是将__name__改成原函数 def log(func): @functools.wraps(func) def wrapper(*args, **kw): print('call %s():' % func.__name__) return func(*args, **kw) return wrapper //若要用@log('message')这种带参数注解可以这样写 def log(text): def decorator(func): @functools.wraps(func) def wrapper(*args, **kw): print('%s %s():' % (text, func.__name__)) return func(*args, **kw) return wrapper return decorator
偏函数functools
functools int()可将字符串转整数 >>> int('12345') 12345 或将其它进制转为10进制 >>> int('12345', base=8) 5349 //可以定义函数int2省略一个参数 def int2(x, base=2): return int(x, base) >>> int2('1000000') 64 还有更简便的方法 功能一致 >>> int2 = functools.partial(int, base=2) //functools.partial作用就是将base=2作为一个参数给int函数 如 max2 = functools.partial(max, 10) 将10作为1个参数给max函数 max2(1,2,3) 就相当于max(1,2,3,10)