python编程技巧--python--cookbook学习笔记(5)

时间:2021-12-09 16:03:23

[0]

你想遍历一个可迭代对象,但是它开始的某些元素你并不感兴趣,想跳过它们。比如说我们想要跳过一个文本文件开头的注释。

可以使用一个叫做dropwhile()的函数,它会一直跳过直道函数的返回值不为真。

 from itertools import dropwhile
     with open('/etc/passwd') as f:
        for line in dropwhile(lambda line: line.startswith('#'), f):
         print(line, end='')

如果已经事先知道了要跳过元素的数量,可以使用islice跳过固定的值。

[1]

利用itertools.chain()

a,b = [1,2],[3,4]
for x in chain(a, b):
     print(x)

[2]:

假如我们有大量的文本数据需要处理,我们不可能一次全部读入内存,如果直接在一个函数里面进行展开,就会增加模块的耦合度。所以我们需要做的是将数据处理的步骤分割成许多小的模块。那么就需要利用生成器来传递数据流,这样占用的内存是非常小的。

import os

import fnmatch
import gzip
import bz2
import re

def gen_find(filepat, top):
    ''' Find all filenames in a directory tree that match a shell wildcard pattern '''
    for path, dirlist, filelist in os.walk(top):
        for name in fnmatch.filter(filelist, filepat):
            yield os.path.join(path,name)

def gen_opener(filenames):
    for filename in filenames:
        if filename.endswith('.gz'):
            f = gzip.open(filename, 'rt')
        elif filename.endswith('.bz2'):
            f = bz2.open(filename, 'rt')
        else:
            f = open(filename, 'rt')
        yield f
        f.close()

def gen_concatenate(iterators):
    for it in iterators:
        yield from it

def gen_grep(pattern, lines):
    pat = re.compile(pattern)
    for line in lines:
        if pat.search(line):
            yield line

lognames = gen_find('access-log*', 'www')
files = gen_opener(lognames)
lines = gen_concatenate(files)
pylines = gen_grep('(?i)python', lines)
for line in pylines:
    print(line)

[3]:

def flatten(s):
    if not isinstance(s,Iterable) or isinstance(s,str):
        yield s
        return
    for item in s:
        yield from flatten(item)

[4]next

a = next((i for i in range(1,10) if not i%4))

[5]forelse

for i in range(5):
    if i==10:break#跳过else
else:
    print(i)

[6]itertools.proudct 可以进行k层循环的迭代.等价于 [(x,y,z..) for x in a for y in b for z in s…]

python编程技巧--python--cookbook学习笔记(5)

这个问题如果自己来写可能会这样:

K,M = map(int,input().split(' '))
max_num = 0
L = []
for i in range(K):
    s = input().split(' ')
    L.append([int(j)**2 for j in s[1:]])
def dfs(i,ans):
    global max_num
    if i == K:max_num = max(max_num,ans%M);return
    for each in L[i]:
        dfs(i+1,ans+each)
dfs(0,0)
print(max_num)

但是利用product方法可以这样写:

from itertools import *
N = []
K, M = map(int, raw_input().split())

for _ in range(K):
     s = input().split()
     N.appendappend([int(j)**2 for j in s[1:]])      

max_num = 0
for i in product(*N):
    max_num = max(sum(i)%M, max_num)

print max_num

(7) 利用numpy模块可以对矩阵进行转置和一维化。(注意要是矩阵才可以,即规则的大小)

import numpy

N, M = map(int,raw_input().split())

my_array = numpy.array( [map(int, raw_input().split()) for i in range(N)] )
print numpy.transpose(my_array)
print my_array.flatten()