Python技术

Python技术 's Blog


  • 首页

  • 标签

  • 归档

  • 关于

实用炫酷!这样写Python代码四两拨千斤!

发表于 2021-04-15 | 分类于 python

判断一个程序员水平的高低,不能光看他的发量,也不能光看他的代码量,还要看他代码蕴含的思想,代码的质量。代码蕴含的思想主要体现在各种设计模式的运用上,而代码的质量就既要实现需求,又要保证代码的简洁优雅。保证代码质量是需要长期积累,养成良好的编程习惯,不断思考优化的。

今天就给大家介绍一种实用的保证代码简洁的武功—— Python 推导四式。

什么是推导式

推导式 comprehensions(又称解析式),是 python 的一种独有特性。推导式是可以从一个数据序列构建另一个新的数据序列。

看定义很抽象,下面我们来看看具体的例子,通过例子来学习这四种推导式。

列表推导式

我们先来看一个需求:

快速创建一个包含元素1-9的平方的列表

面对这个需求,我们通常的实现方式是这样的:

1
2
3
4
lis = []
for i in range(1, 10):
    lis.append(i*i)
print(lis) # [1, 4, 9, 16, 25, 36, 49, 64, 81]

用列表推导式怎么实现呢?你只需要一行代码:

1
2
lis = [x * x for x in range(1, 10)]
print(list) # [1, 4, 9, 16, 25, 36, 49, 64, 81]

这就是推导式。我们可以看到列推导式的语法是这样的:

变量名 = [表达式 for 变量 in 列表]

再来一个复杂点的:

1
2
3
list = [x * y for x in range(1, 10) for y in range(1, 10)]
print(lis)
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 2, 4, 6, 8, 10, 12, 14, 16, 18, 3, 6, 9, 12, 15, 18, 21, 24, 27, 4, 8, 12, 16, 20, 24, 28, 32, 36, 5, 10, 15, 20, 25, 30, 35, 40, 45, 6, 12, 18, 24, 30, 36, 42, 48, 54, 7, 14, 21, 28, 35, 42, 49, 56, 63, 8, 16, 24, 32, 40, 48, 56, 64, 72, 9, 18, 27, 36, 45, 54, 63, 72, 81]

这个是多个变量的类型,因此我们可以扩展上面的语法:

变量名 = [表达式 for 变量 in 列表 for 变量 in xxx]

当然,还有一种带条件的列推导式,它的语法是这样的:

变量名 = [表达式 for 变量 in 列表 if 条件]

我们来看一个需求:快速创建一个包含1-10之间所有偶数的列表。

1
2
lis = [i for i in range(1, 11) if i % 2 == 0]
print(lis) # [2, 4, 6, 8, 10]

字典推导式

字典推导式的形式和列表推导式类似,语法也是类似的,只不过字典推导式返回的结果是字典。

变量名 = {key: value表达式}

我们来看一个例子:

dic = {x: x/2 for x in range(1,11) if x % 2 == 0}
print(dic) # {2: 1.0, 4: 2.0, 6: 3.0, 8: 4.0, 10: 5.0}

如果这里我写成下面这种方式,返回的结果是什么呢?

dic = {'half': x/2 for x in range(1,11) if x % 2 == 0}
print(dic) 

大家可以自己尝试运行一下,看跟你想的结果是不是一样的。

集合推导式

看了前面两个推导式,想必你已经知道集合推导式怎么写了。语法如下:

变量名 = {表达式 for 变量 in 列表 for 变量 in xxx}

或者

变量名 = {表达式 for 变量 in 列表 if 条件}

来一个实际的例子:创建一个存储10个偶数的集合。

1
2
set1 = {x for x in range(10) if x % 2 == 0}
print(set1) # {0, 2, 4, 6, 8}

元组推导式

我们先来看一个例子:

1
2
tup=(x for x in range(1,10))
print(tup) # <generator object <genexpr> at 0x1101fade0>

看到这个结果打印是不是有点懵?

上面的代码返回的变量其实是一个生成器,并不是一个元组。其实没有真正的元组推导式,我们只能用一个类似的方法来生成元组,暂且叫做“伪元组推导式”吧。

上面的例子我们来改进一下:

1
2
tup=tuple(x for x in range(1,10))
print(tup) # (1, 2, 3, 4, 5, 6, 7, 8, 9)

在前面加上 tuple 来显式进行类型转换就行了。

总结

这里介绍了四种 python 的推导式,主要是用来简化 循环的代码,生成不同的数据结构用的。当然,从这些基础的表达式语法出发,还可以运用到复杂的推导式,大家在写代码时留心使用就会发现它的强大之处。这种一行代码既简洁明了,又可以在新手面前炫技,用起来不要太爽!

示例代码:(https://github.com/JustDoPython/python-examples/tree/master/xianhuan/smartcode)

阅读全文 »

眼前一亮!Python 高手都是这样处理数据的!

发表于 2021-04-11 | 分类于 python

工欲善其事,必先利其器!我们想要更轻松更有效率地开发,必须学会一些“高级”技能。前不久看到一位 Python 高僧的代码,其中使用了一个短小精悍的模块,我认为还蛮有用的,今天分享给大家。

这个模块就叫 glom ,是 Python 处理数据的一个小模块,它具有如下特点:

  • 嵌套结构并基于路径访问
  • 使用轻量级的Pythonic规范进行声明性数据转换
  • 可读、有意义的错误信息
  • 内置数据探测和调试功能

看起来比较抽象,对不对?下面我们用实例来给大家演示一下。

安装

作为 Python 内置模块,相信你一定知道怎么安装:

pip3 install glom

几秒钟就搞定!

简单使用

我们来看看最简单的用法:

1
2
3
4

d = {"a": {"b": {"c": 1}}}
print(glom(d, "a.b.c")) # 1

在这里,我们有一个嵌套三层的 json 结构,我们想获取最里层的 c 对应的值,正常的写法应该是:

1
2
3

print(d["a"]["b"]["c"])

如果到这里,我说 glom 比传统方式好一些,因为你不用一层层地写中括号和引号,你会不会嗤之以鼻?

好,我们再来看看下面的情况:

1
2
3
4

d = {"a": {"b": None}}
print(d["a"]["b"]["c"])

遍历到一个 None 对象,你会收到下面的错误:

1
2
3
4
5
6
7

Traceback (most recent call last):
  File "/Users/cxhuan/Documents/python_workspace/mypy/pmodules/pglom/glomstudy.py", line 10, in <module>
    print(d["a"]["b"]["c"])
TypeError: 'NoneType' object is not subscriptable


我们来看看 glom 的处理方式:

1
2
3
4
5
6

from glom import glom

d = {"a": {"b": None}}
print(glom(d, "a.b.c"))

同样地,glom 不能把错误的输出成对的,你会得到以下错误:

1
2
3
4
5
6
7
8
9
10
11
12

Traceback (most recent call last):
  File "/Users/cxhuan/Documents/python_workspace/mypy/pmodules/pglom/glomstudy.py", line 11, in <module>
    print(glom(d, "a.b.c"))
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/glom/core.py", line 2181, in glom
    raise err
glom.core.PathAccessError: error raised while processing, details below.
 Target-spec trace (most recent last):
 - Target: {'a': {'b': None}}
 - Spec: 'a.b.c'
glom.core.PathAccessError: could not access 'c', part 2 of Path('a', 'b', 'c'), got error: AttributeError("'NoneType' object has no attribute 'c'")

如果你仔细看报错内容,你就会发现这报错内容极其详细,一目了然,这对于找程序 bug 简直是神器!

复杂用法

刚才简单的例子,让大家对 glom 有了直观的认识,接下来我们看看 glom 的 glom 方法的定义:

glom(target, spec, **kwargs)

我们看看参数的含义:

  • target:目标数据,可以是dict、list或者其他任何对象
  • spec:是我们希望输出的内容

下面我们来使用这个方法。

先看一个例子。我们有一个 dict ,想要获取出 所有 name 的值,我们可以通过 glom 来实现:

1
2
3
4
5

data = {"student": {"info": [{"name": "张三"}, {"name": "李四"}]}}
info = glom(data, ("student.info", ["name"]))
print(info) # ['张三', '李四']

如果用传统方式的话,我们可能会需要遍历才能获取到,但是使用 glom ,我们只需要一行代码就可以了,输出是一个数组。

如果你不想输出数组,而是想要一个 dict 的话,那也是很简单的:

1
2
3
4

info = glom(data, {"info": ("student.info", ["name"])})
print(info) # {'info': ['张三', '李四']

我们只需要将原来的数组赋值给一个字典来接收就好了。

搞定麻烦需求

假如我现在有两组数据,我要取出 name 的值:

1
2
3
4
5
6
7
8
9

data_1 = {"school": {"student": [{"name": "张三"}, {"name": "李四"}]}}
data_2 = {"school": {"teacher": [{"name": "王老师"}, {"name": "赵老师"}]}}

spec_1 = {"name": ("school.student", ["name"])}
spec_2 = {"name": ("school.teacher", ["name"])}
print(glom(data_1, spec_1)) # {'name': ['张三', '李四']}
print(glom(data_2, spec_2)) # {'name': ['王老师', '赵老师']}

我们通常是这么写,对吗?假如我们有好多组数据,每组都是类似的取法呢?这时候我们就会想办法避免一个个重复写 N 行参数了,我们可以使用 Coalesce 方法:

1
2
3
4
5
6
7
8
9

data_1 = {"school": {"student": [{"name": "张三"}, {"name": "李四"}]}}
data_2 = {"school": {"teacher": [{"name": "王老师"}, {"name": "赵老师"}]}}

spec = {"name": (Coalesce("school.student", "school.teacher"), ["name"])}
 
print(glom(data_1, spec)) # {'name': ['张三', '李四']}
print(glom(data_2, spec)) # {'name': ['王老师', '赵老师']}

我们可以用 Coalesce 把多个需求聚合起来,然后针对同一个 spec 来取值就行了。

下面再来一个大杀器——取值计算。glom 还可以对取值进行简单计算,我们来看例子:

1
2
3
4
5

data = {"school": {"student": [{"name": "张三", "age": 8}, {"name": "李四", "age": 10}]}}
spec = {"sum_age": ("school.student", ["age"], sum)}
print(glom(data, spec)) # {'sum_age': 18}

总结

介绍了这么多,大家应该知道 glom 的厉害之处了吧,据说很多大佬都喜欢使用呢。其实它还有很多其他的实用功能有待大家去发掘,这里就不一一介绍了。如果你觉得今天分享的模块有用,点个“在看”支持一下吧!

示例代码:(https://github.com/JustDoPython/python-examples/tree/master/xianhuan/glom)

阅读全文 »

别以为,有了人脸识别就万事无忧了

发表于 2021-04-09 | 分类于 python

标题图

人脸识别是一个既方便又安全的个人鉴权解决方案,被应用在各个场景中,从各种app,打卡门禁,到遍布各处的自动售卖机,已经和我们的生活密切结合了,不过可别掉以轻心,安全问题无小事

阅读全文 »

秀的一批,那些你不得不知的 PyCharm 高效操作

发表于 2021-04-06 | 分类于 python

封面

熟话说,工欲善其事,必先利其器,PyCharm 作为最好用的 IDE 工具,有着各种各样的骚操作,这是高级开发工程师必须熟悉的基本技能。

阅读全文 »

这就是你需要的铁饭碗

发表于 2021-04-05 | 分类于 python

前两天看了 码农翻身 公号作者刘欣 的一篇文件 我去北京吃了顿散伙饭

讲述了曾经理论上看起来绝不会倒的部门解散的事情

理论上说,只要IBM不倒,这个部门肯定不会倒

多么有讽刺意味,再强健的组织,再权威的承诺,都是靠不住的

同时让我想到技术人的35岁坎儿

今天就技术人职场,谈谈一些看法,期望对你有所启发

阅读全文 »

开眼界!Python 遍历文件可以这样做!

发表于 2021-03-17 | 分类于 python

Python 对于文件夹或者文件的遍历一般有两种操作方法,一种是至二级利用其封装好的 walk 方法操作:

1
2
3
4
5
6
7
8

import os
for root,dirs,files in os.walk("/Users/cxhuan/Downloads/globtest/hello"):
    for dir in dirs:
        print(os.path.join(root, dir))
    for file in files:
        print(os.path.join(root, file))

上面代码运行结果如下:

1
2
3
4
5
6
7
8
9
/Users/cxhuan/Downloads/globtest/hello/world
/Users/cxhuan/Downloads/globtest/hello/.DS_Store
/Users/cxhuan/Downloads/globtest/hello/hello3.txt
/Users/cxhuan/Downloads/globtest/hello/hello2.txt
/Users/cxhuan/Downloads/globtest/hello/hello1.txt
/Users/cxhuan/Downloads/globtest/hello/world/world1.txt
/Users/cxhuan/Downloads/globtest/hello/world/world3.txt
/Users/cxhuan/Downloads/globtest/hello/world/world2.txt

上述程序,将 os.walk 读取到的所有路径 root 、目录名 dirs 与文件名 files ,也就是三个文件数组利用 foreach 循环输出。join方法就是将其路径与目录名或者文件名连接起来,组成一个完整的目录。

另一种是用递归的思路,写成下面的形式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

import os
files = list()
def dirAll(pathname):
    if os.path.exists(pathname):
        filelist = os.listdir(pathname)
        for f in filelist:
            f = os.path.join(pathname, f)
            if os.path.isdir(f):
                dirAll(f)
            else:
                dirname = os.path.dirname(f)
                baseName = os.path.basename(f)
                if dirname.endswith(os.sep):
                    files.append(dirname+baseName)
                else:
                    files.append(dirname+os.sep+baseName)


dirAll("/Users/cxhuan/Downloads/globtest/hello")
for f in files:
    print(f)

运行上面代码,得到的结果和上面一样。

这两种方法都没问题,就是写起来比较麻烦,特别是第二种,一不小心还有可能写出 bug 。

今天我们来介绍第三种方法——利用 glob 模块来遍历文件。

简介

glob 是 python 自带的一个操作文件的模块,以简洁实用著称。由于这个模块的功能比较简单,所以也很容易上手和使用。它主要用来查找符合特定规则的文件路径。使用这个模块来查找文件,只需要用到*、? 和 [] 这三个匹配符:

1
2
3
 * : 匹配0个或多个字符;
 ? : 匹配单个字符;
 [] :匹配指定范围内的字符,如:[0-9]匹配数字。

glob.glob 方法

glob.glob 方法主要返回所有匹配的文件路径列表。它只有一个参数 pathname ,定义了文件路径匹配规则,这里可以是绝对路径,也可以是相对路径。

使用 * 匹配

我们可以用 * 匹配零个或者多个字符。

输出目录下的子目录或者文件:

1
2
3
4

for p1 in glob.glob('/Users/cxhuan/Downloads/globtest/*'):
    print(p1)

运行上面代码,会将 globtest 文件夹下仅有的目录输出出来,输出内容如下:

1
2
3

/Users/cxhuan/Downloads/globtest/hello

我们也可以通过制定层级来遍历文件或者文件夹:

1
2
3
4

for p in glob.glob('/Users/cxhuan/Downloads/globtest/*/*'):
    print(p)

上面的代码会遍历 globtest 文件夹以及子文件夹,将所有的文件或文件夹路径打印出来:

1
2
3
4
/Users/cxhuan/Downloads/globtest/hello/world
/Users/cxhuan/Downloads/globtest/hello/hello3.txt
/Users/cxhuan/Downloads/globtest/hello/hello2.txt
/Users/cxhuan/Downloads/globtest/hello/hello1.txt

我们也可以对文件或者文件夹进行过滤:

1
2
3
4

for p in glob.glob('/Users/cxhuan/Downloads/globtest/hello/*3.txt'):
    print(p)

上面代码值匹配 hello 目录下的文件名末尾为 ‘3’ 的 txt 文件,运行结果如下:

1
/Users/cxhuan/Downloads/globtest/hello/hello3.txt

使用 ? 匹配

我们可以用问号(?)匹配任何单个的字符。

1
2
3
4

for p in glob.glob('/Users/cxhuan/Downloads/globtest/hello/hello?.txt'):
    print(p)

上面的代码输出 hello 目录下的以 ‘hello’ 开头的 txt 文件,输出结果如下:

1
2
3
4
5

/Users/cxhuan/Downloads/globtest/hello/hello3.txt
/Users/cxhuan/Downloads/globtest/hello/hello2.txt
/Users/cxhuan/Downloads/globtest/hello/hello1.txt

使用 [] 匹配

我们可以使用 [] 来匹配一个范围:

1
2
3
4

for p in glob.glob('/Users/cxhuan/Downloads/globtest/hello/*[0-2].*'):
    print(p)

我们想要得到 hello 目录下的文件名结尾数字的范围为 0到2的文件,运行上面代码,获得的输出为:

1
2
/Users/cxhuan/Downloads/globtest/hello/hello2.txt
/Users/cxhuan/Downloads/globtest/hello/hello1.txt

glob.iglob 方法

python 的 glob 方法可以对文件夹下所有文件进行遍历,并返回一个 list 列表。而 iglob 方法一次只获取一个匹配路径。下面是一个简单的例子来说明二者的区别:

1
2
3
4
5
6
7
8
p = glob.glob('/Users/cxhuan/Downloads/globtest/hello/hello?.*')
print(p)

print('----------------------')

p = glob.iglob('/Users/cxhuan/Downloads/globtest/hello/hello?.*')
print(p)

运行上面代码,结果返回是:

1
2
3
4
5

['/Users/cxhuan/Downloads/globtest/hello/hello3.txt', '/Users/cxhuan/Downloads/globtest/hello/hello2.txt', '/Users/cxhuan/Downloads/globtest/hello/hello1.txt']
----------------------
<generator object _iglob at 0x1040d8ac0>

从上面的结果我们可以很容易看到二者的区别,前者返回的是一个列表,后者返回的是一个可迭代对象。

我们针对这个可迭代对象做一下操作看看:

1
2
3
4
p = glob.iglob('/Users/cxhuan/Downloads/globtest/hello/hello?.*')
print(p.__next__())
print(p.__next__())

运行结果如下:

1
2
/Users/cxhuan/Downloads/globtest/hello/hello3.txt
/Users/cxhuan/Downloads/globtest/hello/hello2.txt

我们可以看到,针对这个可迭代对象,我们一次可以获取到一个元素。这样做的好处是节省内存,试想如果一个路径下有大量的文件夹或者文件,我们使用这个迭代对象不用一次性全部获取到内存,而是可以慢慢获取。

总结

今天分享的模块虽然功能简单,但是对于我们遍历文件或者目录来说足够使用了,并且方法简单易懂,值得大家经常使用。如果你觉得今天分享的模块有用,点个“在看”支持一下吧!

示例代码:(https://github.com/JustDoPython/python-examples/tree/master/xianhuan/glob)

阅读全文 »

弃繁就简!一行代码搞定 Python 日志!

发表于 2021-03-16 | 分类于 python

写了这么多年的 Python ,我一直都是使用 Python 自带的 logging 模块来记录日志,每次需要写一些配置将日志输出到不同的位置,设置不同日志输出格式,或者将日志进行分文件和压缩等。这个日志模块没什么问题,直到我无意中发现了一个神器,我才发觉原来记日志可以这么简单的!这个神器就是 loguru 。

阅读全文 »

上班摸鱼程序,再也不怕领导偷偷出现在身后了

发表于 2021-03-15 | 分类于 python

当你在上班摸鱼的时候,领导总会偷偷摸摸的出现在你的背后,例如小编曾经偷偷摸摸看《轻音》被抓包了。今天我们就用 Python 来破解这个摸鱼被抓的套路,主要的思路是用 opencv 调用电脑摄像头检测和比对人脸,当领导出现在后面的时候打开指定的应用程序浑水摸鱼。

阅读全文 »

谁说程序员不懂浪漫,当代码遇到文学...

发表于 2021-03-09 | 分类于 python

封面

一提到程序员,大家的第一印象都是性格内向,不善言语,衣服搭配全是格子衫加牛仔裤。实则不然,别看我们整天和机器打交道,一天下来可能也说不了几句话,但我们程序员群体也是人呀,也有七情六欲,也是懂浪漫的,今天派森酱就带你领略下程序员另类的浪漫。

阅读全文 »

惊艳!用 Python 送女神们别样的礼物!

发表于 2021-03-07 | 分类于 惊艳!用 Python 送女神们别样的礼物!

今天是 3 月 8 日,统称三八妇女节!

但是!请注意,三八妇女节不是妇女的节日,而且一个很有特殊意义的节日,阿酱在这里先祝各位女神们节日快乐!

关于三八妇女节

三八妇女节不是妇女的节日,而且关于女权的事!

三八妇女节由来:

19世纪,资本主义迅速发展,资本家开始雇佣女工,但女工与男工同工不同酬,女工每天工作十六七个小时,没有休息日,境况十分悲惨。 1908年3月8日,1500名妇女在纽约市游行,要求缩短工作时间,提高劳动报酬,享有选举权,禁止使用童工。

5月,美国社会党决定以2月的最后一个星期日作为国bai的妇女节。1910年8月,第二届国际社会主义妇女代表大会在丹麦哥本哈根召开,大会通过将美国妇女举行游行示威的3月8日这一天定为国际妇女节。

而中国妇女第一次纪念三八节,是在1924年。在中国共产党的领导下,广州的劳动妇女联合了各界被压迫妇女举行纪念会。

在联合国介绍国际妇女节的网页上,把“三八”国际妇女节的起源归因于20世纪初期系列的妇女运动大事,这些事件包括:

1909年,美国社会党人将2月28日定为全国妇女日;

1910年,第二国际哥本哈根会议上以克拉拉·蔡特金为首的来自17个国家的100余名妇女代表筹划设立国际妇女节,但未规定确切的日期;

1911年3月19日,奥地利、丹麦、德国和瑞士等国有超过100万妇女集会庆祝国际妇女节;

1913年2月的最后一个周日,俄罗斯妇女以示威游行的方式庆祝了她们的国际妇女节;

1914年3月8日,欧洲多国妇女举行反战示威游行;

1917年3月8日(俄历2月23日),为纪念在一战中丧生的近200万俄罗斯妇女,俄罗斯妇女举行罢工,拉开了“二月革命”的序幕,4天后,沙皇被迫退位,临时政府宣布赋予妇女选举权。

20世纪初这一系列发生在欧洲和美洲的女权运动共同促成了“三八”国际妇女节的诞生。

在当今社会,无论在家庭还是工作中,女性的地位显得越来越重要,一个女人结婚后需要平衡家庭和事业,在家中要照顾小孩,在外要努力工作!

所以我觉得 女人:很伟大!

给女神们特别的礼物

今天我用 Python 给女神们制作了别样的礼物,愿大家永远健康美丽!礼物详情如下:

上图是今天送给女神们别样的礼物,上图由两部分组成,一部分是桃心,一部分是玫瑰花,python 分两部分完成巨作,详解如下:

画桃心代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

# 画大号爱心(位置随机)
for x, y in list(zip(list1, list2)):
    t.penup()
    t.goto(x, y)
    t.pendown()
    t.fillcolor("#FF6A6A")
    t.begin_fill()
    t.pencolor("#FF6A6A")
    t.forward(40)
    t.circle(20, 180)
    t.right(90)
    t.circle(20, 180)
    t.forward(40)
    t.end_fill()
    t.penup()
    t.goto(x, y)
# 画中号爱心(位置随机)
for x, y in list(zip(list5, list6)):
    t.pendown()
    t.fillcolor("#FFA07A")
    t.begin_fill()
    t.pencolor("#FFA07A")
    t.forward(30)
    t.circle(15, 180)
    t.right(90)
    t.circle(15, 180)
    t.forward(30)
    t.end_fill()
    t.penup()
    t.goto(x, y)
# 画小号爱心(位置随机)
for x, y in list(zip(list3, list4)):
    t.pendown()
    t.fillcolor("#FFD39B")
    t.begin_fill()
    t.pencolor("#FFD39B")
    t.forward(20)
    t.circle(10, 180)
    t.right(90)
    t.circle(10, 180)
    t.forward(20)
    t.end_fill()
    t.penup()
    t.goto(x, y)
# 画点点(位置随机)
for x, y in list(zip(list7, list8)):
    t.pendown()
    t.fillcolor("#FF6A6A")
    t.begin_fill()
    t.pencolor("#FF6A6A")
    t.circle(3, 360)
    t.end_fill()
    t.penup()
    t.goto(x, y)

画玫瑰花代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# 初始位置设定
s = 0.2
# t.setup(450*5*s, 750*5*s)
t.pencolor("black")
t.fillcolor("#FF4040")
t.speed(100)
t.penup()
t.goto(0, 900 * s)
t.pendown()
# 绘制花朵形状
t.begin_fill()
t.circle(200 * s, 30)
DegreeCurve(60, 50 * s)
t.circle(200 * s, 30)
DegreeCurve(4, 100 * s)
t.circle(200 * s, 50)
DegreeCurve(50, 50 * s)
t.circle(350 * s, 65)
DegreeCurve(40, 70 * s)
t.circle(150 * s, 50)
DegreeCurve(20, 50 * s, -1)
t.circle(400 * s, 60)
DegreeCurve(18, 50 * s)
t.fd(250 * s)
t.right(150)
t.circle(-500 * s, 12)
t.left(140)
t.circle(550 * s, 110)
t.left(27)
t.circle(650 * s, 100)
t.left(130)
t.circle(-300 * s, 20)
t.right(123)
t.circle(220 * s, 57)
t.end_fill()
# 绘制花枝形状
t.left(120)
t.fd(280 * s)
t.left(115)
t.circle(300 * s, 33)
t.left(180)
t.circle(-300 * s, 33)
DegreeCurve(70, 225 * s, -1)
t.circle(350 * s, 104)
t.left(90)
t.circle(200 * s, 105)
t.circle(-500 * s, 63)
t.penup()
t.goto(170 * s, -30 * s)
t.pendown()
t.left(160)
DegreeCurve(20, 2500 * s)
DegreeCurve(220, 250 * s, -1)

# 绘制一个绿色叶子
t.fillcolor('#00CD00')
t.penup()
t.goto(670 * s, -180 * s)
t.pendown()
t.right(140)
t.begin_fill()
t.circle(300 * s, 120)
t.left(60)
t.circle(300 * s, 120)
t.end_fill()
t.penup()
t.goto(180 * s, -550 * s)
t.pendown()
t.right(85)
t.circle(600 * s, 40)
# 绘制另一个绿色叶子
t.penup()
t.goto(-150 * s, -1000 * s)
t.pendown()
t.begin_fill()
t.rt(120)
t.circle(300 * s, 115)
t.left(75)
t.circle(300 * s, 100)
t.end_fill()
t.penup()
t.goto(430 * s, -1070 * s)
t.pendown()
t.right(30)
t.circle(-600 * s, 35)

t.done()

写在最后

以上就是今天给女神们特别的礼物,在这个专属的日子里希望每个美丽的小姐姐都貌美如花!活得潇洒!

参考

https://blog.csdn.net/su_2018/article/details/88351847

总结

祝女神们节日快乐,希望家里有女神的男同胞们好好爱惜身边的伴侣!

阅读全文 »

python 让我重获尊严

发表于 2021-03-05 | 分类于 python

前段时间,被儿子鄙视了,为了找回作为父亲的尊严,我豁出去了,本以为是根硬骨头,结果,太出乎意外了……

因起

去年发现家附近,有个马场,约了下试骑,孩子挺喜欢

这家马场设施齐全,工作人员态度也不错,最重要的是,还可以在线预约,可以省去很多麻烦

经过再三考虑,加上架不住销售的鼓吹,报名了

打算开启孩子的精进之旅,对未来充满着希望

可怜天下父母心呀

障碍

前几次课,体验不错

上完之后,在公众号上一约,才发现事情并非之前想的那样顺利

首先是慢,其次周末太火爆约经常约不上,一打听,大部分家长都是在每一和周二提前把周末的约好了

其次,教练资源每天上午10点放出往后六天的,常常因为工作忘记

更麻烦的是,孩子非得约自己喜欢的教练,这个教练态度温和,水平高超,获奖无数,妥妥的香饽饽,更使约课雪上加霜

接连几个星期都没有约上课,孩子也没法持续训练,对我也又了抱怨之情

我这个做爸爸的,还真无处辩驳……

改变

真的就没有办法了吗?

当然不是,只是有没有将自己逼到必须解决的份上,所谓

置之死地而后生

持续几次之后,有点不耐烦了,突然想到

咱不是会 Python 吗,写个爬虫,自动预约呗

于是利用工作之余琢磨如何实现自动预约

公众号应用

对于公众号应用,实际上是一个普通的 H5 网页,为了安全,会限制只能用微信浏览器访问,以及方便直接用微信登录

实现方式是通过公众号提供的链接转化接口,将普通链接转化为需要微信验证的链接

通过转化后的链接,必须在微信应用的自带浏览器中访问,请求后会获取一些用户的身份信息,比如 Openid,昵称,性别等

这时需要用户来确认是否同意该公众号获取自己的这些信息

当用户同意后,就会跳转到实际的页面里,这时会附带上一些用户的特征信息

这时,访问的就是公众号应用的原始 URL 了

提取链接

微信内置浏览器有个复制链接的功能,可以获取当前页面的 URL

提取链接

然后在电脑的浏览器中打开,一般就能看到和在微信里访问相同的页面

通过这样的方式,我发现这个公众号的 URL 中有 Openid 信息,应该是做用户识别用的

如果能在电脑浏览器中打开,下面的事情就简单了

编写爬虫

通过浏览器的请求分析功能查看关键操作的请求 (一般按 F12 就可以进入调试模式)

将请求复制为 curl 格式

curl 请求转 Python 代码

这样的好处是,复制全请求的全部内容

这时你可能会觉得,应该编写 Python 代码了

确实是可以了,不过将复制的请求内容编写成 Python 语句可不是件容易的事情,如果你这么干过的话,光做引号配对就非常耗时了

好在,我们可以利用在线转化工具,粘贴复制就可搞定,我推荐 https://curl.trillworks.com/ 这个工具

将复制的 curl 格式请求,粘贴在左边,然后选择要转换为的语言,比如 Python

右边瞬间就有了结果

curl 请求转 Python 代码

将结果复制出来,会发现大部分编码工作已经完成了

剩下的就是一些小调整了,比如将参数动态化,设置一些逻辑等等

部署

最后将代码作成定时服务,如果有云服务器,写个 crontab 就好了

也可以做成一个定义任务,可以参考这一篇文章 公交闹钟 —— 再也不用白等车了 其中有详细定时任务的制作教程

经过一番折腾,终于为孩子约上了喜欢的教练的课,而且不用每次守着手机无奈的等待,也重新找回了做为父亲的尊严……

总结

很多朋友经常会问,如何学习一门编程语言,又如何利用

其实就是在学中用,用中学,不断地利用学到的技能,解决实际中的问题,甚至创造出一些机会来实践,这便是学习和利用的捷径

之前也写过一些关于应用的文章,请参考,比如

美图太多,Python 帮你挑选最合适的

老板让很快处理数百图片,我该辞职吗

硬核老爸,我用 Python

个人品牌,我用 Python

唯有不断地练习,才能快速成长,关注我们,将为您的精进之旅增加强劲的动力

比心

参考

  • https://curl.trillworks.com/
  • https://cn.python-requests.org/zh_CN/latest/
  • http://www.ruanyifeng.com/blog/2019/09/curl-reference.html
阅读全文 »

吐血推荐 | 珍藏多年的 Chrome 插件,务必收藏

发表于 2021-03-01 | 分类于 python

封面

熟话说,工欲善其事,必先利其器,Chrome 作为程序员使用最多的浏览器有着数不清的优点,简洁高效,强大的控制面板,支持各种插件等。当然也有一个一直被我们吐槽的缺点,就是内存占用高,好在现在硬件便宜,可是说是瑕不掩瑜。

阅读全文 »

达叔走了,别只发声感叹就完了

发表于 2021-03-01 | 分类于 python

前两天刷到吴孟达(下称 达叔)因肝癌入院的文章,心头一惊,没想短短几天,达叔便离我们而去……

哀思之后,就又回到自己正常的生活之中了,可是,有没有想过,带走达叔的原因?

一个我们现在的每个人都无法回避的问题 —— 健康

健康对每个人的重要性是不言而喻的,好的健康意味着拥有更长的时间,意味着遇到更多的机会,意味着更高质量的生活

即使知道健康的重要性,可是在巨大的生活压力之下,如何才能保持健康呢?

下面分享一下我的故事:如何从三高、超重到健康、精力充沛的华丽转变

期待对你有所启发

情况

我是在北京一家软件公司工作,工作繁忙,从早到晚或是伏案工作,或是各种会议

平时还参与了《Python 技术》公号的写作,写作需要长时间伏案工作,同时需要耗费很多时间

另外,我以组长身份还参加了《笑来写作训练营》,每日需要做管理,开例会,还有定期轮值(主持班级里一天的活动)

生活上,我是个十足的宝爸,大部分空闲时间都用于陪孩子,而去这一点非常重要,特别对孩子的成长,以及未来的家庭生活

总之工作生活忙累,每天时间紧张,以至于身体逐渐变差,变得肥胖,无力,困乏

一度以为是年龄导致的问题,结果体检报告会告诉实际情况:三高,超重,脂肪肝

思考

连续几年的健康不达标,不得不思考对策,于是开始想各种改善方法

节食,择食,锻炼…… 都用上,不过坚持不了多久,就被繁忙的生活冲掉了

看了不少关于健身的书,下载了多款健身 app,订阅了无数健身课程,制订了健全面健身计划,然并卵

直到有一天,刷到樊登老师关于跑步的一段视频

介绍了他是如何从一个完全不会跑步,且不打算跑步的状态,如何变得离不开跑步的

我一下子有了跑步的兴趣,于是就从去年(20年)12月初开始尝试跑,结果一直到现在,3个月过去了,根本就停不下来

行动

开始跑步时,我根本不相信我会跑到停不下来

跑步的第一天,我按照心率超过140就停的方法,跑了不到 100 米就得停了,走一会儿,看看手环,到了 140 以下,接着跑

这样第一天跑完了,感觉轻松自如,如果这样也叫跑步的话第一次感觉体验不错

于是第二天接着跑,一样的方式,还是感觉不累,于是坚持跑了一个星期

到第二周时,有了些腿部酸痛,肌肉紧绷,这时特别想要放弃,但看着已经跑了一周,放弃可惜,跑完后做做退步放松运动,继续跑

这样接着跑了一个周,两个周,直到一个月,感觉自己没怎么坚持就跑下来了

最大的变化是可以抱起儿子飞奔了(主要是因为起得晚,赶校车)

这个变化,像一个奖励,激励我跑下去

于是又跑了一个月,感觉身体轻松多了,徒步,登山,爬楼梯,感到轻松自如

更多的是感觉自己的身体充满了能量,一个冬天没有感冒(之前必感冒至少一次)

就这样,一直跑了下来,特别是在 -19 摄氏度的天气里,也坚持跑了,不同以往的是不是用意志力逼迫自己坚持的,而是靠一种强烈的愿望

变化

经过这三个月的锻炼积累,我的变化太大了

更健康

跑到第二个月,做也验血测验,结果发现,之前超标的指标全部正常

体重从 86 kg,下降到现在的 80 kg

更自信

开始跑步时,感觉不好意思,纠结于什么时候跑,用什么姿势,是否可以坚持……

而现在随心所欲,自然而然,想怎么跑就怎么跑,内心只有自己,有种冥想的感觉

生活中,工作上也有了更多的自信

更热情

每天跑步,常常会遇到一些锻炼的,遛狗的,保安保洁的人,可以很自然的和他们打招呼

与人交流底气十足,因而更加随和,因为充满力量,所以更加包容,因为精力充沛,所以更加耐心

这些小小的变化,带来的极大的人际关系改善

更有能量

也许你不知道的是

我们的大脑是最先受到身体的影响,然后才受知识的影响

身体好了,大脑工作起来就好更加顺畅,思考的更深入更持久

看问题不会停留在一个点上,思维更加开阔

于是就有了更多的正能量: 积极,热情,利他

这一点在《笑来写作训练营》中尤为突出,大家对我的评价是: 充满了正能量

总结

健康对我们很重要,只要开始锻炼就能像投资一样,投资健康,将来会成为巨大的财富,不仅是最好,在过程中就能享受到,不仅锻炼了身体,还为我提供了澎湃的动力,一致于我的工作生活都是围绕着锻炼展开的

总结以下几点,期望很助于你开启健康生活

  1. 健身不等于锻炼,锻炼是为了更健康
  2. 跑步是很好的锻炼,正确的指导方法很重要,推荐参考《跑步治愈》
  3. 跑步时放松心态,享受跑步过程
  4. 一周是个坎,需要做放松运动
  5. 跑步的时间不重要,根据自身情况做安排
  6. 偶尔中断不要紧,继续锻炼就好,我们要的不是连续不断,而是更健康

对达叔缅怀之后,开启自己的健康生活,才是对达叔最好的致敬

比心

参考

  • 跑步治愈
  • 微信互联网平民创业
阅读全文 »

巨细!Python 爬虫详解!!!

发表于 2021-02-23 | 分类于 巨细!Python 爬虫详解!!!

什么是爬虫

爬虫(又称为网页蜘蛛,网络机器人,在 FOAF 社区中间,更经常的称为网页追逐者); 它是一种按照一定的规则,自动地抓取网络信息的程序或者脚本。

如果我们把互联网比作一张大的蜘蛛网,那一台计算机上的数据便是蜘蛛网上的一个猎物,而爬虫程序就是一只小蜘蛛,他们沿着蜘蛛网抓取自己想要的猎物/数据。

阅读全文 »

用 Python 将 html 转为 pdf、word

发表于 2021-02-22 | 分类于 python

在日常中有时需将 html 文件转换为 pdf、word 文件。网上免费的大多数不支持多个文件转换的情况,而且在转换几个后就开始收费了。

阅读全文 »

用 Appium 自动收取蚂蚁森林能量

发表于 2021-02-15 | 分类于 python

支付宝集 5 福让小编打开了尘封已久的蚂蚁森林小程序,它刚出来那会儿小编也算是一个重度用户,看着一直被偷的能量总想以德服人。今天就用 Python + Appium 写一个自动收取能量的脚本,完成之后再也没人能从小编手上将能量偷走了

启动入口

还不会使用 Appium 的小伙伴可以先看看本公众号上的《解放双手,提高生产力,这款神器你值得拥有》学习和使用 Appium

下面代码是支付宝的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.support import expected_conditions as EC

desired_capabilities = {
    'platformName': 'Android',  # 操作系统
    'deviceName': '2a254a02',  # 设备 ID
    'platformVersion': '10.0.10',  # 设备版本号,在手机设置中查看
    'appPackage': 'com.eg.android.AlipayGphone',  # app 包名
    'appActivity': 'AlipayLogin',  # app 启动时主 Activity
    'noReset': True  # 是否保留 session 信息 避免重新登录
}

driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_capabilities)
# 设置等待超时时间
wait = WebDriverWait(driver, 60)

点击进入蚂蚁森林

支付宝上的蚂蚁森林的图标按钮位置每个人按照各自的习惯都不相同,小编的图标位置在全部-->最近使用里面,可以用蚂蚁森林文字找到图标并点击

1
2
3
4
5
# 点击全部图标
wait.until(EC.element_to_be_clickable((By.ID, 'com.alipay.android.phone.openplatform:id/more_app_icon'))).click()
# 找到蚂蚁森林
wait.until(EC.element_to_be_clickable((By.XPATH, '//android.widget.TextView[contains(@text, "蚂蚁森林")]'))).click()
time.sleep(1)

收集能量

在蚂蚁森林中并不能通过用 id 的方式定位到能量球,只能用在能量球可能出现的区域用坐标点击,start_x,end_x,start_y,end_y 是这个区域左上角和右下角的坐标位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 获取手机屏幕宽高
width = int(driver.get_window_size()['width'])
height = int(driver.get_window_size()['height'])

# 收取能量
def collect_energy(driver, width, height):
    # 能量球可能出现的区域坐标
    start_x = 150
    end_x = 900
    start_y = 540
    end_y = 900

    for x in range(start_x, end_x, 50):
        for y in range(start_y, end_y, 50):
            x_scale = int((int(x) / width) * width)
            y_scale = int((int(y) / height) * height)
            # 点击指定坐标
            TouchAction(driver).press(x=x_scale, y=y_scale).release().perform()
    print('能量收取完毕')

收取好友能量

自己的能量收取完之后,点击 找能量 进入好友的蚂蚁森林收取好友的能量,直到出现返回我的森林页面

1
2
3
4
5
6
7
8
9
10
11
12
13
def search_energy(driver, width, height):
    x = int((int(1000) / width) * width)
    y = int((int(1550) / height) * height)
    # 点击指定坐标
    TouchAction(driver).press(x=x, y=y).release().perform()
    time.sleep(1)
    is_collected = is_element_exist_by_xpath(driver, '//android.widget.Button[contains(@text, "返回我的森林")]')
    if is_collected:
        print('能量全部收集完毕')
        return

    collect_energy(driver, width, height)
    search_energy(driver, width, height)

总结

用 Appium 很简单的就将蚂蚁森林的能量球自动化了,看完这篇文章后希望小伙伴可以活学活用将其他 APP 应用中的重复的操作也自动化,省事又省力

示例代码:https://github.com/JustDoPython/python-examples/tree/master/moumoubaimifan/AntForest

阅读全文 »

派森酱带你用 Python 实现中间人攻击

发表于 2021-02-08 | 分类于 python

封面

中间人攻击,顾名思义,就是客户端和服务端的通信被第三者拦截了,这样通信双方的通信内容就会被窃听。你可能会认为,没关系啊,窃听就窃听呗,反正又没什么重要的信息,那如果我告诉你,攻击者不但可以窃听你们的通信内容,甚至可以修改你们的通信内容,你还会这么认为么。

阅读全文 »

程序设计神器 之 实体

发表于 2021-02-07 | 分类于 python

程序处理的是概念

程序是什么?

简单说,程序是处理数据的计算机代码

几乎所有的程序都可以分为三部分

输入–> 处理 –> 输出

程序可以理解成一个加工处理数据的过程,或者工具

那么被加工的数据又是什么呢?

阅读全文 »

看到他留给世界的最后一篇作文,我慌了!

发表于 2021-02-06 | 分类于 python
1

据新浪娱乐讯,2月3日,赵英俊家人发表讣告,称赵英俊因病医治无效,于2021年2月3日14时33分在北京病逝,享年43岁。

阅读全文 »

如何像黑客一样优雅的使用命令行

发表于 2021-02-01 | 分类于 python

封面

提起黑客,我们脑海中浮现的第一个画面就是一动不动的坐在电脑前,眼睛注视着屏幕,伴随着手指在键盘上飞快的移动,屏幕上的字符也在不停闪烁,终于,在按下 Enter 键的那一刻,整栋大楼的系统瘫痪了,是不是觉得很酷呀。

阅读全文 »
1 2 … 18
Python Geek Tech

Python Geek Tech

一群热爱 Python 的技术人

348 日志
54 分类
57 标签
RSS
GitHub 知乎
Links
  • 纯洁的微笑
© 2019 - 2021 Python Geek Tech
由 Jekyll 强力驱动
主题 - NexT.Mist