help: 查看函数或者对象的帮助文档
type: 查看对象的类型
dir: 查看包下有哪些函数和类
字符串处理是写程序遇到的最多的一个场景,如果是以前,我可能会这样写:
>>> name = 'john' >>> age = 27 >>> content = 'Hello, my name is ' + name + ', I am ' + str(age) + '.' >>> print(content) Hello, my name is john, I am 27. >>>
上面这种写法,用了大量字符串拼接,一个是容易写错,而且遇到类型不匹配还需要自己转换。
使用字符串的format方法后,会优雅很多:
>>> content = 'Hello, My name is {}, I am {}'.format(name, age) >>> >>> print(content) Hello, My name is john, I am 27 >>>
和字符串处理相关的,还有一个join方法。如果有多个变量,想拼接成一个字符串,且用竖线分隔,可以这样:
>>> name = 'john' >>> address = 'Beijing' >>> email = 'faker@mail.com' >>> >>> arr = [name, address, email] >>> '|'.join(arr) 'john|Beijing|faker@mail.com' >>>
如何把数组中的多个元素赋值给多个变量,如果是以前,我可能会这样写:
>>> arr = ['john', 'Beijing', 'faker@mail.com'] >>> >>> name = arr[0] >>> address = arr[1] >>> email = arr[2]
现在我会这样写:
>>> name, address, email = arr
如果你想跳过数组中的某个变量,可以用下划线:
>>> arr = ['john', 'Beijing', 'faker@mail.com'] >>> name, _, email = arr
假设有一个这样的场景,需要动态创建一个字典,每个key对应一个列表,如果key不存在则需要先创建这个key,再往key中append元素。常规写法:
>>> list [['friuit', 'apple'], ['friuit', 'orange'], ['friuit', 'banana'], ['friuit', 'pear'], ['device', 'phone'], ['device', 'laptop'], ['device', 'mac']] >>> data = {} >>> for (k,v) in list: ... if k not in data: ... data[k] = [] ... data[k].append(v) ... >>> data {'friuit': ['apple', 'orange', 'banana', 'pear'], 'device': ['phone', 'laptop', 'mac']} >>>
比较pythonic的写法:
>>> data = {} >>> list [['friuit', 'apple'], ['friuit', 'orange'], ['friuit', 'banana'], ['friuit', 'pear'], ['device', 'phone'], ['device', 'laptop'], ['device', 'mac']] >>> >>> [data.setdefault(k, []).append(v) for (k,v) in list] [None, None, None, None, None, None, None] >>> data {'friuit': ['apple', 'orange', 'banana', 'pear'], 'device': ['phone', 'laptop', 'mac']} >>>
举个例子,如何将一个文件中的每一行读取出来,并组成一个列表。如果是以前,我可能会这样写:
>>> filename = 'balance_query_input.txt' >>> f = open(filename, encoding='utf-8') >>> items = f.readlines() >>> for item in items: ... item = item.strip() >>> f.close() >>>
如果是现在,我会这样写:
>>> items = [x.strip() for x in open(filename, encoding='utf-8').readlines()]
如果想同时过滤掉文件中的空行和长度不足4的行,可以这样:
>>> items = [ x.strip() for x in open(filename, encoding='utf-8').readlines() if len(x.strip())>4 ] >>>
如何对列表中的每个元素,调用一个方法?如果是以前,我可能会这样写:
>>> items = [ x.strip() for x in open(filename, encoding='utf-8').readlines() if len(x.strip())>4 ] >>> >>> for item in item: ... deal(item) ...
现在我会这样写:
>>> [ deal(item) for item in items ]
总之,学会使用列表推导后,基本上不用写for循环了。
其实列表推导的效果,使用map同样能实现,但是据说由于map是内置函数,所以效率会高一些。举个例子,对一个列表中所有元素增加10,首先定义一个inc函数:
>>> arr = [x for x in range(10)] >>> >>> arr [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> >>> def inc(val): ... return val + 10 ...
先演示使用列表推导的实现方式:
>>> [inc(x) for x in arr] [10, 11, 12, 13, 14, 15, 16, 17, 18, 19] >>>
再演示使用map的实现方式:
>>> [x for x in map(inc, arr)] [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
lambda表达式的作用是,创建匿名对象。好处就是,不用单独定义函数了。使用lambda表达式对上面的代码再进一步简化:
>>> [x for x in map(lambda x:x+10, arr)] [10, 11, 12, 13, 14, 15, 16, 17, 18, 19] >>>
假设现在有一些文件,名称按照数字命名,如果使用sorted默认排序,将会按照字符串来处理,这并不是我们想要的结果:
>>> data ['1.PDF', '10.PDF', '11.PDF', '12.PDF', '13.PDF', '2.PDF', '3.PDF', '4.PDF', '5.PDF', '6.PDF', '7.PDF', '8.PDF', '9.PDF'] >>> sorted(data) ['1.PDF', '10.PDF', '11.PDF', '12.PDF', '13.PDF', '2.PDF', '3.PDF', '4.PDF', '5.PDF', '6.PDF', '7.PDF', '8.PDF', '9.PDF'] >>>
我们想按照数字大小进行排序,则需要使用sorted的自定义key参数:
>>> data ['1.PDF', '10.PDF', '11.PDF', '12.PDF', '13.PDF', '2.PDF', '3.PDF', '4.PDF', '5.PDF', '6.PDF', '7.PDF', '8.PDF', '9.PDF'] >>> >>> >>> sorted(data, key=lambda i:int(i.split('.')[0])) ['1.PDF', '2.PDF', '3.PDF', '4.PDF', '5.PDF', '6.PDF', '7.PDF', '8.PDF', '9.PDF', '10.PDF', '11.PDF', '12.PDF', '13.PDF'] >>>
参数key是一个函数,接收data中的每个元素,并返回一个值。
如果想对一个字典进行排序,也可以使用key进行处理,使得sorted很灵活:
>>> data [{'key': '1'}, {'key': '2'}, {'key': '100'}, {'key': '55'}, {'key': '6'}] >>> >>> sorted(data, key=lambda i:int(i['key'])) [{'key': '1'}, {'key': '2'}, {'key': '6'}, {'key': '55'}, {'key': '100'}] >>>
lambda表达式、map、filter、sorted这几个神器,还有很多高阶应用,欢迎各位读者补充。
多线程+队列,是一种编程模型,被称为生产者/消费者模型。
假设有一个队列中保存着所有待处理任务,如果这些任务是可以并行处理互不干扰,则可以使用这种编程模型。
举个例子,要把所有URL中的html内容解析出结构化数据并存储起来。这种场景就可以使用生产者/消费者模型。
import queue from threading import Thread import threading # 任务队列,存放待处理任务,可由多个线程并行处理 task_queue = queue.Queue() # 结果队列,存放结构化数据,由单线程逐个获取并存储到数据库 result_queue = queue.Queue() # 多线程任务逻辑,不停从任务队列中领取任务,并将处理结果塞入结果队列。 def do_deal(): while True: item = '' try: item = task_queue.get_nowait() except queue.Empty as e: log("task queue is empty, sleep a while.") time.sleep(1) continue data = deal(item) result_queue.put(data) # 单线程从结果队列获取结构化数据,并存储到数据库或者文件 def do_save(): while True: record = '' try: record = result_queue.get_nowait() except queue.Empty as e: log("result queue is empty. sleep a while.") time.sleep(1) continue log('record:' + record) f = open(OUTPUT, 'a') f.write(record) f.close() # 创建任务队列 tasks_list = [ x for x in filter(lambda x: True if x.split('/')[4]+x.split('/')[5] not in done_list else False, [ y.strip() for y in open(INPUT).readlines() ]) ] [ task_queue.put(x) for x in tasks_list ] # 启动多个任务处理线程 for i in range(6): Thread(target=do_deal, name='producer'+str(i)).start() # 启动单个结果处理线程 Thread(target=do_save, name='consumer1').start()