

一日一技:用一个奇技淫巧把字符串转成特定类型
我们有时候可能会需要把一个字符串转换成对应的类型。例如,把'123'转换为int类型的123;或者把'3.14'转成浮点数3.14。前提条件是不能使用eval或者exec。这是一个非常简单的功能,常规做法直接使用if判断就可以了:123456def convert(data, target_type): if target_type == 'int': return int(data) elif target_type == 'float': return float(data) ...有些同学觉得写if判断麻烦,也可能会用字典来处理:1234567def convert(data, target_type): type_map = { '..
更多

一日一技:如何正确为历史遗留代码补充单元测试?
我们知道,在软件工程中,单元测试是保证软件质量的重要手段之一。一个优秀的代码,单元测试的代码量,经常会超过被测试的代码本身。一个理想化的开发团队,可能有三分之二的时间是在写测试,剩下的三分之一时间才是写业务代码。如果你的项目是从一开始就写单元测试,那么你写起来应该轻松又愉快,因为单元测试会促使你的代码自身变成可测试的代码。但如果你接手了一个大项目,里面已经有几十万行代码了,那么给这些代码补单元测试会让你知道什么叫做痛不欲生。你会发现有一些函数,它让你不知道怎么写测试代码。我们来看一个例子:我想测试的是business_code里面,check_data_dup分别返回True或者False的时候,下面代码的逻辑。也就是说,我只关心第18-27行的逻辑。这个时候不关心MySQL和Redis。但是每次测试都要..
更多

一日一技:Python如何动态替换对象的方法?
今天有同学在公众号粉丝群问了这样一个问题:他的问题,简单来说,就是想动态替换一个对象的实例方法,简化代码如下:123456789101112class Test: def __init__(self, name): self.name = name def work(self, job): print(f'{self.name}正在{job}')def work(self, job1, job2): print(f'{self.name}正在同时做两个工作,分别是{job1}和{job2}')t = Test('kingname')t.work = work当我们在替换之前,直接运行t.work('job'),效果如下:这个同学期望在替换以后,运行t.work..
更多

一日一技:如何实现带timeout的input?
我们知道,在Python里面,可以使用input获取用户的输入。例如:但有一个问题,如果你什么都不输入,程序会永远卡在这里。有没有什么办法,可以给input设置超时时间呢?如果用户在一定时间内不输入,就自动使用默认值。要实现这个需求,在Linux/macOS系统下面,我们可以使用selectors。这是Python自带的模块,不需要额外安装。对应的代码如下:123456789101112131415import sysimport selectorsdef timeout_input(msg, default='', timeout=5): sys.stdout.write(msg) sys.stdout.flush() sel = selectors.DefaultSelector()..
更多

一日一技:把自然语言描述的时间转成标准格式
如果你使用过嘀嗒清单或者Todoist,那你应该知道他们有一个很好用的功能,那就是自动识别任务中的时间,例如:1下周二下午三点给老板发邮件它会自动识别为:今天,公众号粉丝群里面,有一个叫做NowAnti的同学推荐了一个项目,叫做司南,它就可以让Python实现这样的功能。我们来看看这个第三方库怎么使用。首先pip安装它:1python3 -m pip install sinan安装完成以后,使用方法非常简单:1234from sinan import Sinanobj = Sinan('下周二下午三点给老板发邮件')result = obj.parse()print(result)运行效果如下图所示:这个库不仅可以解析时间,它还可以解析更复杂的语句,例如:12>>> obj = Sina..
更多

一日一技:使用Python翻译HTML中的文本字符串
相信大家都用过浏览器的翻译网页功能,例如对于下图这个英文网页:一键翻译成中文以后是这样的:你可能会觉得这个功能很简单,不就是字符串替换吗?那你可以试一试把下面这个HTML片段中的标签下面的英文翻译成中文。其它标签中的不要改动:123<div><p>if you want to parse date and time, your could use <em>datetimeem>, by use this library, you can generate now time by one line code <span>datetime.datetime.now()span> this is so easy.p>div>在标签中的dat..
更多

一日一技:让你的正则表达式可读性提高一百倍
正则表达式这个东西,强大是强大,但写出来跟个表情符号一样。自己写的表达式,过一个月来看,自己都不记得是什么意思了。比如下面这个:1pattern = r"((?:\(\s*)?[A-Z]*H\d+[a-z]*(?:\s*\+\s*[A-Z]*H\d+[a-z]*)*(?:\s*[\):+])?)(.*?)(?=(?:\(\s*)?[A-Z]*H\d+[a-z]*(?:\s*\+\s*[A-Z]*H\d+[a-z]*)*(?:\s*[\):+])?(?![^\w\s])|$)"有没有什么办法提高正则表达式的可读性呢?我们知道,提高代码可读性的方法之一就是写注释,那么正则表达式能不能写注释呢?例如对于下面这个句子:1msg = '我叫青南,我的密码是:123kingname456,请注意保密。'我要提取其中的..
更多

一日一技:如何让自己的工具函数在Python全局可用?
我们在开发Python项目的时候,经常会写一些工具函数。为了在项目里面多个.py文件中使用这个工具函数,就不得不在多个地方都导入它,非常麻烦。例如下面这个例子:在A.py和C.py文件都要使用clean_msg这个工具函数,那么他们就都要从util.py中导入clean_msg。这似乎理所当然。但今天我在看icecream/builtins.py源代码的时候,突然发现了一个高级用法,可以让我们使用工具函数的时候,就像使用Python的print函数一样,不用导入,而是直接使用。我们先来看看效果:大家注意A.py和C.py,我并没有导入clean_msg而是直接使用了这个函数。并且运行完全正常。关键原理就在入口文件main.py,被我框住的3行:1234import builtinsfrom util im..
更多

一日一技:Any与TypeVar,让IDE的自动补全更好用
相信有很多同学在写Python的时候,会使用类型标注来提高代码的可读性,同时还能帮助IDE实现自动补全。假设我们现在获得了一个对象,这个对象可能是列表也可能是生成器,我写一个函数,获取它的第一个元素。代码很简单:123456789101112131415161718192021222324252627282930313233from typing import Iteratorfrom contextlib import suppressclass People: def __init__(self, name): self.name = name def eat(self): print(f'{self.name}正在吃饭') def walk(self):..
更多

一日一技:如何从大量商品数据里面找到降价商品?
相信很多做爬虫的同学都会爬电商网站,每天爬一次,然后监控商品是否降价。如果你只监控一个商品,那么是否降价这非常容易判断,但如果你要找到这个网站里面所有降价的商品,那就非常麻烦了。如下图所示,是美国电商沃尔玛的全站商品数据:每个商品每天都会爬一次,一共有61w+条数据。里面有N个商品降价了,现在需要把这些降价的商品找出来。商品有十几万个,如果你分别找到每个商品的ID,然后用ID再找到这个商品每一天的数据,最后看它是否降价,这个工作量非常大,速度也会非常慢。Pandas内部使用了SIMB技术来对并行计算进行优化,我们需要尽量在不使用for循环的情况下,完成这个任务。为了简单起见,我们假设降价就是指今天比昨天的价格低,不考虑先涨价再降价的情况。要解决这个问题,我们需要使用DataFrame的pct_change..
更多