如果有更好的技巧或者是一些心得也可以分享给我~
- test = [1, 2, 3, 4, 5]
- # 从索引最开始到结束,每隔两个取出一个
- # 实际上就是肉眼数的奇数位,索引的偶数位
- odds = test[::2]
- print(odds) # 结果 -> [1, 3, 5]
- # 从索引第一位到结束,每隔两个取出一个
- # 实际上就是肉眼数的偶数位,索引的奇数位
- evens = test[1::2]
- print(evens) # 结果 -> [2, 4]
- # 对于byte的字符串来说还有神奇的特效(only byte)
- byte_str = b'abcd'
- print(byte_str[::-1]) # 结果 -> dcba
- # 尽量不要很复杂的切片方式,尽量能够多次解决复杂
- # 不要同时出现start end stride三个参数
- # 1. 例子没有
- # list, dict, set都有对列表表达式的支持
- # 列表表达式代替使用map和filter,可以避免写lambda函数
- # 2. 例子
- # 列表表达式处理多重for循环
- martix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
- flat_list = [x for row in martix for x in row]
- print(flat_list) # 结果 -> [1, 2, 3, 4, 5, 6, 7, 8, 9]
- # 拆解代码大致就是:
- new_list = []
- for row in martix:
- for x in row:
- new_list.append(x)
- # 3.例子
- # 从一个列表中找出一个数字大于4且是偶数的
- a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
- # 第一种
- b = [x for x in a if x > 4 if x % 2 ==0]
- # 第二种
- c = [x for x in a if x > 4 and x % 2 ==0]
- # 结果都是一样的,只是判断上的区别
- # Tips:
- # 列表表达式能用就尽量用,可以缩减一些代码量,但是不要写的过于复杂
- # 太复杂的表达式,查bug更难找,而且也不利于别人进行维护
- # 原因很简单,列表表达式需要开辟较大的内存空间进行存储
- """
- 官方解释: 生成器表达式,它是对推导和生成器的一种泛化。
- 生成器在运行时不会将整个输出序列呈现出来,而是会估值为迭代器,
- 这个迭代器每次可以根据生成器表达式产生一项数据。
- """
- # 1. 例子
- # 读取一个多行文本,统计每一行的长度
- it = (len(x) for x in open('<文件路径>/<文件名>.<文件后缀>')
- print(it) # 结果 -> <generator object <genexpr> at 某个内存地址>
- # 需要输出时就用next
- print(next(it))
- # 原因很简单,封装的比range好
- test = ['vannila', 'chocolate', 'pecan', 'strawberry']
- # 第一种
- for i , flavor in enumerate(test):
- print('%d: %s' % (i + 1, flavor))
- # 结果如下
- >>>
- 1: vannila
- 2: chcolate
- 3: pecan
- 4: strawberry
- # 解释一下: i + 1 实际上就是为了更好看,如果不i + 1,实际上就是索引的位置.
- # 第二种
- for i , flavor in enumerate(test, 1):
- print('%d: %s' % (i, flavor))
- # 结果一样, 实际上就是在enumerate的函数中已经封装了
- # 显得更简便,而且同时能输出索引位置或输出实际中的计数位
- #except的例子就不说了,用过都知道#直接上
- else的例子
- #函数的功能就是: 加载一个json,
- 返回对应key的值def load_json_key(data, key) try: result_dict = json.loads(data) except ValueError as err: raise KeyError from err
- else: return result_dict[key]
- """
- 解释:
- 实际上这个else可要可不要,因为写在try里面也是可以的
- 但是如果为了代码的可阅读性,else是一个很必要的东西
- 代码阅读上就知道try里面是代码中可能存在错误的的地方
- 如果写在一堆的话,还有错误,那你的except就要增加多几个了
- 而且写代码也并不建议嵌套try-except,毕竟那不服合代码的风格.
- """
- #
- finally的话,
- 实际上就一个代码清理的过程#一般用在IO或者数据库读写上,
- 用来关闭流,
- 例子就不写了.
- # coding: utf-8
- from concurrent.futures import ThreadPoolExecutor as Pool
- # from multiprocessing import Pool
- import requests
- import time
- urls = ["http://www.gzcc.cn", "http://jwxw.gzcc.cn",
- "http://www.baidu.com", "http://www.qq.com",
- "http://www.163.com", "http://www.sohu.com"]
- def
- task
- (url, timeout=10)
- :
- return requests.get(url=url, timeout=timeout)
- if __name__ == '__main__':
- start_1 = time.time()
- for each_url in urls:
- response = task(url=each_url)
- print('%s, %s' % (response.url, response.status_code))
- end_1 = time.time()
- print("顺序执行的时长: %f" % (end_1 - start_1))
- start_2 = time.time()
- pool = Pool(max_workers=4)
- # pool = Pool(processes=4)
- processes = pool.map(task, urls)
- for each_process in processes:
- print('%s, %s' % (each_process.url, each_process.status_code))
- end_2 = time.time()
- print("并行执行的时长: %f" % (end_2 - start_2))
- # 第一种的结果: 1.4s
- # 第二种的结果: 0.4s
- # 结果的提升是肯定有的,但是和网络情况有关系。
- # 关于导入的包 concurrent.future
- # 对于这个包里面的ThreadPoolExecutor和multiprocessing的Pool对比,作用实际上差不多,具体时间差异我还没怎么测试过.
- # 但是如果你认真看源码的话会发现,实际上future的包在process的那一块也是调用multiprocessing的
- # 按照源码的意思就是在子线程中运行多个python的解释器,从而实现并行.
- # 但是一般的代码或者多线程爬虫上基本体会不出,因为爬虫的核心还是在网络速度上,而一般的代码也没必要
- # 除非计算矩阵或者其他的需要巨大计算量的时候再考虑使用.
- # 例子
- rate = 1.45
- seconds = 3 * 60 + 42
- cost = rate * seconds / 60
- print(cost) # 结果很奇怪: 5.364999999999999
- # 这时候可能会想到用round的函数
- # 1、如果这时你的需求是不足一分也当一分的计算
- # 类似于向上取整round的方法会把结果变成5.36而不是5.37
- # 2、如果没有要求的时候使用round就可以了
- #
- # 针对第一种问题,就引出一个decimal的方法了,改写一下
- from decimal import Decimal
- rate = Decimal('1.45')
- seconds = Decimal(3 * 60 + 42)
- cost = rate * seconds / Decimal(60)
- print(cost) # 结果 -> 5.365
- # 重点说下这里。
- # 有个很奇怪的地方,有兴趣的可以研究下为什么。
- # 把rate的那个1.45去掉单引号包围,再运行就明白为什么奇怪了
- # 反观结果, 5.365貌似也不是我们想要的,这里就引入一个quantize方法了
- # 在代码顶部加上
- from decimal import ROUND_UP
- # cost还是刚刚的cost
- rounded = cost.quantize(Decimal('0.01'), rounding=ROUND_UP)
- print(rounded) # 结果 -> 5.37
- # 兜兜转转就到结果这里了.一般这些情况都是对精度要求很高才需要,一般情况就当看不见好了.
- 你的代码在导包的时候写了import *,你自己开发是很明白有什么方法的.
- 但是在协作开发或者开源项目的时候尽量避免.
- 因为其他开发者并不知道里面的方法是干啥的.
- # 例如一些数据库的配置,selenium的webdriver的配置,甚至开发的模式配置可以通过一些json格式的配置文件进行维护.
- # 好处1: 在于这样管理项目不用"东奔西跑",为了一个全局变量找半天
- # 好处2: 在协同开发的时候,可以不用变动的代码的情况下,根据自己的开发环境确定一些全局配置
- # 缺点的话,实际上也算不上缺点.就是每次都要读取一次配置文件,代码的速度会减慢一点点,但是并不碍事.
回到顶部: 传送门
来源: https://juejin.im/post/5a17d1a6f265da432d27c871