两百行Python代码复刻一款《天天酷跑》游戏

大家好,欢迎来到 Crossin的编程教室 !

 
今天给大家带来一个趣味游戏的案例展示。最近趁着周末写了一个《天天酷跑》,拿来和大家一起重温经典的酷跑游戏。
 
先看一下游戏的效果吧
01

准备开发环境

俗话说,“工欲善其事,必先利其器”,我们先来介绍一下本次我们用到的库有哪些。(需要注意的是,由于很多的小伙伴都会反映很多库安装之后,会出现报错,找不到相应的模块),这是因为库版本的不同,所以跟大家详细的介绍一下程序所使用的各个环节及其对应的版本,这次我们使用的工具和其版本号如下所示:
PyCharm:2019.1.3
python3.5+,其中内置sys和random库
pygame:1.9.6
02

程序整体思路

介绍完我们的基础环境之后,接下来我们来介绍一下今天游戏设计的思路。

1).游戏初始化

  • 利用pygame创建特定大小的游戏窗口。
  • 显示游戏的初始界面,提示用户开始游戏
  • 在游戏界面中设置背景图片,并显示人物、障碍物和金币等物体。

2).游戏控制

  • 人物自动向前奔跑,按空格键控制人物跳跃。
  • 利用addObstacle函数创建障碍物。
  • 利用updateScreen函数不断更新界面中物体的显示。

3).碰撞检测

  • 利用ListenKeyBoard函数监控用户的键盘输入,并检测人物和障碍物金币等是否碰撞。
  • 人物和障碍物碰撞:当检测到人物和障碍物的位置信息有交集时,判断为碰撞,人物生命值减一,障碍物消灭。
  • 人物和金币碰撞:当人物撞到金币时,金币消灭,得分+100。
  • 当人物成功躲避障碍物时,得分+10。
  • 利用judgeState函数来判断游戏是否结束。
  • 游戏结束时显示最终得分,并提示用户按“Enter”键重新开始游戏。

两百行Python代码复刻一款《天天酷跑》游戏

03

带你一步一步写游戏

1).首先,整体看一下程序是如何实现初始化的:

两百行Python代码复刻一款《天天酷跑》游戏

程序是由pygame库为主体来实现的,首先程序中制定了游戏窗口的大小,以及程序不同模块的背景图,例如障碍物的图片,游戏进行时的背景图和游戏结束时的背景图。

2).游戏开始的界面

当运行程序后,程序首先会运行self.startGame这个函数,并给出游戏的介绍界面,提示用户开始游戏。

两百行Python代码复刻一款《天天酷跑》游戏

self.startGame函数中,首先绘制了游戏的初始界面,然后开始监控用户的键盘输入,当用户输出“ESC”键的时候,则直接退出游戏,否则的话,就进入真正的游戏。初始化的界面下图所示:

两百行Python代码复刻一款《天天酷跑》游戏

3).创建各类物体

进入游戏之后,我们就需要创建人物、障碍物和金币以及游戏背景的设置。由于人物和障碍物已经游戏背景都通过类的方式来创建的,且它们的类形式非常类似,这里我们就以障碍物和金币类来进行简单的讲解。

两百行Python代码复刻一款《天天酷跑》游戏

在障碍物类中,类的初构造函数中,主要设置了类对象的显示图像(self.surface)、坐标信息(self.x、self.y)和长宽信息(self.w、self.h)。而self.getPos函数用来返回当前对象的坐标和长宽信息,self.judgeCollision函数则是用来进行物体的碰撞检测。

在程序中,通过self.addObstacle函数就可以添加障碍物对象,并随机设置障碍物在游戏界面中所处的高度位置。在游戏中障碍物目标如下图所示。

两百行Python代码复刻一款《天天酷跑》游戏

上图中,被红色框框住的就是障碍物,可以看到,障碍物之间有着不同的高度坐标,以及不同的间隔宽度,这样才能为跑酷人物带来不同的难度挑战。人物则是被蓝色框框住的目标,而位于画面正上方,被绿色框框住的则是“剩余生命值和得分”的信息。

4).用户键盘监控和碰撞检测

通过对于用户的键盘输入监控,来控制人物的运动,例如是跳跃还是退出游戏。

两百行Python代码复刻一款《天天酷跑》游戏

上图中,我们可以看到当用户输入空格键时,如果人物当前的state是0,则人物要完成一级跳,如果人物当前的state是1,则人物要完成二级跳。如果当前self.game_state是1,表示人物已经死亡,那么当用户输入“Enter”键时,游戏将重新开始。

对于人物和障碍物或者是金币的碰撞检测,则是通过障碍物类中的self.judgeCollision函数来进行判断。

两百行Python代码复刻一款《天天酷跑》游戏

如果判断是金币的话,则用户的得分+100,金币被吃掉。否则的话,用户的生命值减一,障碍物消失掉。

5).游戏界面不断刷新和判断游戏结束

通过self.updateScreen函数,可以实现游戏界面的不断的刷新。

两百行Python代码复刻一款《天天酷跑》游戏

上述的程序中,分别对游戏背景的位置、剩余生命值和得分的数值以及障碍物的数量和人物的运动状态进行更新后,就可以利用screen.blit函数在游戏界面中展示出来,通过不断的更新,让游戏看起来就是不断的运动的过程。

 

通过self.judgeState函数,来判断游戏是否结束,如果游戏结束了,则会展示出用户所获得分,并提示用户按“Enter”键重新开始游戏。

两百行Python代码复刻一款《天天酷跑》游戏

以上就是今天为大家带来的关于跑酷游戏开发的分享和讲解,有兴趣的同学,可以自己把源码运行一下,在基础上还可以做一些改动和扩展。感受一下经典的跑酷游戏所带来的乐趣吧。

作者:菜鸟哥

来源:菜鸟学Python

转自:https://mp.weixin.qq.com/s/qC10UTA1aawd9oLnXfG-hA

别再问我exe反编译成Python脚本了!

来自公众号:凹凸数据

大家好,我是小五🧐

今年年初的时候,我写了一篇:别再问我Python打包成exe了!(终极版),相信解决了不少小伙伴的Pyinstaller打包问题。

不过我最近遇到了一个问题,自己打包好的exe文件还在,但是Python源文件不知什么时候被误删了。现在想改动一下功能,重写Python脚本工程量也太大了,怎么办?

请看下文:

作者简介

小小明,数据、Python爱好者。个人博客地址:https://blog.csdn.net/as604049322

今天我将教大家如何反编译exe文件,即将自己或别人写好的exe,还原成Python源码。

以最近写Python一键自动整理归类文件为例进行演示,运行所需的代码和文件都会在文末提供给大家。

别再问我exe反编译成Python脚本了!

打包成单文件所使用的命令为:

pyinstaller -Fw --icon=h.ico auto_organize_gui.py --add-data="h.ico;/"

打包成文件夹所使用的命令为:

pyinstaller -w --icon=h.ico auto_organize_gui.py --add-data="h.ico;."

不管是哪种打包方式都会留下一个exe文件。

首先我们需要从exe文件中抽取出其中的pyc文件:

抽取exe中的pyc文件

抽取pyinstaller打包的exe中的pyc文件,提取pyc文件有两种方法:

  1. 通过 pyinstxtractor.py 脚本提取pyc文件
  2. 通过 pyi-archive_viewer 工具提取pyc文件

脚本提取pyc文件

pyinstxtractor.py 脚本可以在github项目 python-exe-unpacker 中下载,地址:

https://github.com/countercept/Python-exe-unpacker

下载该项目后把其中的pyinstxtractor.py脚本文件复制到与exe同级的目录。

然后进入exe所在目录的cmd执行:

Python pyinstxtractor.py auto_organize_gui.exe

执行后便得到exe文件名加上_extracted后缀的文件夹:

别再问我exe反编译成Python脚本了!

对两种打包方式产生的exe提取出的文件结构稍有区别:

别再问我exe反编译成Python脚本了!

工具提取pyc文件

pyi-archive_viewer是PyInstaller自己提供的工具,它可以直接提取打包结果exe中的pyc文件。

详细介绍可参考官方文档:ttps://pyinstaller.readthedocs.io/en/stable/advanced-topics.html#using-pyi-archive-viewer

执行pyi-archive_viewer [filename]即可查看 exe 内部的文件结构:

pyi-archive_viewer auto_organize.exe

操作命令:

U: go Up one level
O <name>: open embedded archive name
X <name>: extract name
Q: quit

然后可以提取出指定需要提取的文件:

别再问我exe反编译成Python脚本了!

要提取其他被导入的pyc文件,则需要先打开PYZ-00.pyz

别再问我exe反编译成Python脚本了!

很显然,使用PyInstaller的pyi-archive_viewer 工具操作起来比较麻烦,一次只能提取一个文件,遇到子模块还需执行一次打开操作。

所以后面我也只使用pyinstxtractor.py 脚本来提取pyc文件。

反编译pyc文件为py脚本

有很多对pyc文件进行解密的网站,例如:

  • https://tool.lu/pyc/

不过我们直接使用 uncompyle6 库进行解码,使用pip可以直接安装:

pip install uncompyle6

uncompyle6可以反编译.pyc后缀结尾的文件,两种命令形式:

  1. uncompyle6 xxx.pyc>xxx.py
  2. uncompyle6 -o xxx.py xxx.pyc

以前面编码过程中生成的缓存为例进行演示:

uncompyle6 auto_organize.cpython-37.pyc>auto_organize.py

执行后便直接将.pyc文件反编译成Python脚本了:

别再问我exe反编译成Python脚本了!

从编译结果看注释也被保留了下来:

别再问我exe反编译成Python脚本了!

对于不是pyc后缀结尾的文件,使用uncompyle6反编译时会报出 must point to a Python source that can be compiled, or Python bytecode (.pyc, .pyo) 的错误。

所以我们需要先对提取出的内容人工修改后缀:

别再问我exe反编译成Python脚本了!

运行入口pyc文件反编译

对于从pyinstaller提取出来的pyc文件并不能直接反编译,入口运行类共16字节的 magic时间戳被去掉了。

如果直接进行反编译,例如执行 uncompyle6 auto_organize_gui.exe_extracted/auto_organize_gui.pyc

会报出如下错误:ImportError: Unknown magic number 227 in auto_organize_gui.exe_extractedauto_organize_gui.pyc

使用支持16进制编辑的文本编辑器查看一探究竟,这里我使用UltraEdit32

分别打开正常情况下编译出的pyc和从pyinstaller提取出来的pyc文件进行对比:

别再问我exe反编译成Python脚本了!

可以看到前16个字节都被去掉了,其中前四个字节是magic,这四个字节会随着系统和Python版本发生变化,必须一致。后四个字节包括时间戳和一些其他的信息,都可以随意填写。

我们先通过UltraEdit32向pyinstaller提取的文件添加头信息:

别再问我exe反编译成Python脚本了!

选择开头插入16个字节后,只需要替换前4个字节为当前环境下的magic:

别再问我exe反编译成Python脚本了!

然后执行:

uncompyle6 auto_organize_gui.exe_extracted/auto_organize_gui.pyc>auto_organize_gui.py

执行后可以看到文件已经顺利的被反编译:

别再问我exe反编译成Python脚本了!

依赖性pyc文件反编译

考虑再反编译导入的其他依赖文件:

别再问我exe反编译成Python脚本了!

先用UltraEdit32打开查看一下:

别再问我exe反编译成Python脚本了!

可以看到对于非入口运行的pyc文件是从12字节开始缺4个字节。

这里我们选择第13个字节再插入四个字节即可:

别再问我exe反编译成Python脚本了!

然后再执行:

uncompyle6 auto_organize_gui.exe_extracted/PYZ-00.pyz_extracted/auto_organize.pyc > auto_organize.py

然后成功的反编译出依赖的文件:

别再问我exe反编译成Python脚本了!

代码与原文件几乎完全一致:

别再问我exe反编译成Python脚本了!

批量反编译

如果一个exe需要被反编译的Python脚本只有3个以内的文件,我们都完全可以人工来操作。

但是假如一个exe涉及几十个甚至上百个Python脚本需要反编译的时候,人工操作未免工作量过于巨大,我们考虑将以上过程用Python实现,从而达到批量反编译的效果。

提取exe中的pyc

import os
import sys
import pyinstxtractor

exe_file = r"D:/PycharmProjects/gui_project/dist/auto_organize_gui.exe"
sys.argv = ['pyinstxtractor', exe_file]
pyinstxtractor.main()
# 恢复当前目录位置
os.chdir("..")
[*] Processing D:/PycharmProjects/gui_project/dist/auto_organize_gui.exe
[*] Pyinstaller version: 2.1+
[*] Python version: 37
[*] Length of package: 9491710 bytes
[*] Found 984 files in CArchive
[*] Beginning extraction...please standby
[*] Found 157 files in PYZ archive
[*] Successfully extracted pyinstaller archive: D:/PycharmProjects/gui_project/dist/auto_organize_gui.exe

You can now use a Python decompiler on the pyc files within the extracted directory

预处理pyc文件修护校验头

def find_main(pyc_dir):
    for pyc_file in os.listdir(pyc_dir):
        if not pyc_file.startswith("pyi-"and pyc_file.endswith("manifest"):
            main_file = pyc_file.replace(".exe.manifest""")
            result = f"{pyc_dir}/{main_file}"
            if os.path.exists(result):
                return main_file

pyc_dir = os.path.basename(exe_file)+"_extracted"
main_file = find_main(pyc_dir)
main_file

读取从pyz目录抽取的pyc文件的前4个字节作基准:

pyz_dir = f"{pyc_dir}/PYZ-00.pyz_extracted"
for pyc_file in os.listdir(pyz_dir):
    if pyc_file.endswith(".pyc"):
        file = f"{pyz_dir}/{pyc_file}"
        break
with open(file, "rb"as f:
    head = f.read(4)
list(map(hex, head))
['0x42''0xd''0xd''0xa']

校准入口类:

import shutil
if os.path.exists("pycfile_tmp"):
    shutil.rmtree("pycfile_tmp")
os.mkdir("pycfile_tmp")
main_file_result = f"pycfile_tmp/{main_file}.pyc"
with open(f"{pyc_dir}/{main_file}""rb"as read, open(main_file_result, "wb"as write:
    write.write(head)
    write.write(b""*12)
    write.write(read.read())

校准子类:

pyz_dir = f"{pyc_dir}/PYZ-00.pyz_extracted"
for pyc_file in os.listdir(pyz_dir):
    pyc_file_src = f"{pyz_dir}/{pyc_file}"
    pyc_file_dest = f"pycfile_tmp/{pyc_file}"
    print(pyc_file_src, pyc_file_dest)
    with open(pyc_file_src, "rb"as read, open(pyc_file_dest, "wb"as write:
        write.write(read.read(12))
        write.write(b""*4)
        write.write(read.read())

开始反编译

from uncompyle6.bin import uncompile

if not os.path.exists("py_result"):
    os.mkdir("py_result")
for pyc_file in os.listdir("pycfile_tmp"):
    sys.argv = ['uncompyle6''-o',
                f'py_result/{pyc_file[:-1]}'f'pycfile_tmp/{pyc_file}']
    uncompile.main_bin()
别再问我exe反编译成Python脚本了!

完整代码下载见文末。

这样我们只需将Python脚本、exe文件和pyinstxtractor.py脚本文件 放置到同一文件夹下,运行我们的Python脚本。即可反编译exe。

可以看到已经完美的反编译出exe其中的Python脚本:

别再问我exe反编译成Python脚本了!

好了,相信大家已经明白了反编译的原理。那么既然是攻防,如何防止自己打包的exe被反编译呢?

别再问我exe反编译成Python脚本了!

如何防止exe被反编译呢

只需在打包命令后面加上--key命令即可,例如文章开头的命令可以更换为:

pyinstaller -Fw --icon=h.ico auto_organize_gui.py --add-data="h.ico;/" --key 123456

123456是你用来加密的密钥,可以随意更换。

该加密参数依赖tinyaes,可以通过以下命令安装:

pip install tinyaes

打包后再次执行反编译:

exe_file = r"D:/PycharmProjects/gui_project/dist/auto_organize_gui.exe"
uncompyle_exe(exe_file, True)

结果只有入口脚本反编译成功,被依赖的脚本均被加密,无法直接被反编译:

别再问我exe反编译成Python脚本了!

可以看到抽取的中间结果变成了.pyc.encrypted格式,无法直接被反编译:

别再问我exe反编译成Python脚本了!

可以看到,常规手段就无法直接反编译了。

这个时候还想反编译就需要底层的逆向分析研究了,或者pyinstaller的源码完整研究一遍,了解其加密处理的机制,看看有没有破解的可能。

— EOF —

 

转自:https://mp.weixin.qq.com/s/GAYapTRX82cklHw9dT9vhg

在 Windows上写 Python 代码的最佳组合!

选自 Real Python,作者:Jon Fincher

在 Windows 上怎样做 Python 开发?是像大神那样使用纯文本编辑器,还是用更加完善的 IDE?到底是用自带的命令行工具,还是需要装新的 Terminal?本文将带你了解如何利用微软官方维护的 MS Terminal 与 VS Code,来为 Python 开发保驾护航。

 

使用 Windows 系统一大好处是它的应用太丰富了,甚至强大的 GPU 也能在闲暇时间做点其它「工作」。然而与 Linux 或 macOS 不同,在 Windows 上做开发总会遇到很多挑战,不论是文件编码、环境控制还是项目编译,开发过程中总会有一些神奇的收获。

 

这些对于初学者来说尤其突出:我们在安装某个库时可能出现各种依赖项错误,我们在读写文本时出现各种编码错误等等。

 

那么在 Windows 上如何做 Python 开发呢?相信大神们都会有自己的解决方案,但本文希望介绍微软官方发布的 Terminal 和 Visual Studio Code,希望它们能构建更流畅的 Windows 开发体验。

 

在 Windows上写 Python 代码的最佳组合!
Visual Studio Code 是程序员可以使用的最酷的代码编辑器之一,是一个可在所有平台上使用的开源、可扩展和轻量级编辑器。正是这些品质使微软的 VS Code 大受欢迎,并成为 Python 开发的绝佳平台。可能很多读者都比较熟悉 PyCharm 与 Jupyter Notebook 等常见的 Python IDE,但 VS Code 一样不会令你失望。

 

在本文中,你将学习到微软 Terminal 和 Visual Studio Code 的特性,包括:

 

  • 什么是微软 Terminal

  • 微软 Terminal 效果怎么样

  • 安装 Visual Studio Code

  • 发现并安装 Python 扩展

  • 编写简单的 Python 应用程序

  • 了解如何在 VS Code 中运行和调试现有 Python 程序

  • 将 VS Code 连接到 Git 和 GitHub,与全世界分享你的代码

我们假设你了解 Python 开发,并且已经在系统上安装了某种版本的 Python(如 Python 2.7、Python 3.6/3.7、Anaconda 或其他)。由于 VS Code 可兼容所有主流平台,因此你可能会看到略有不同的 UI 元素,并且可能需要修改某些命令。

 

新兴的微软 Terminal

 

Windows Terminal 是一个开源终端应用程序,由微软在今年 5 月份的 Build 开发者大会上推出。MS Terminal 支持 Command Prompt 和 PowerShell 的所有优点,基本上命令行已经可以和 Linux 相融合了,除此之外运行命令提示符也是没问题的。

 

在 MS Terminal 开源后,GitHub 的 Star 量增长得非常快,目前已经超过了 5 万。这足以说明这个项目非常受关注,在社区的开源改进下,这个工具一定挺好用。

 

在 Windows上写 Python 代码的最佳组合!
 
  • MS Terminal 开源地址:https://github.com/microsoft/terminal

 

当然,目前 MS Terminal 已经可以直接下载安装程序了,社区的体验也非常不错。因此如果我们在 Windows 上做 Python 开发,命令行工具就可以采用 MS Terminal,它能解决很大一部分的包安装、环境控制等问题。

 

MS Terminal 的效果怎么样

 

MS Terminal 最核心的功能就是支持多条选项卡,且每一个选项卡都可以连接到命令行 shell 或应用,例如 Command Prompt 或通过 SSH 访问树莓派等。下图展示了这种多选项卡的支持情况:

 

在 Windows上写 Python 代码的最佳组合!
 
此外,除了功能外,更重要的就是颜值,就像我们常用 zsh 来提供更美观的命令行一样。虽然 zsh 目前的 GitHub 收藏量已经达到 9.4 万了,但 ReadMe 文档清楚地写着它最好用于 macOS 或 Linux。而新发布的 MS Terminal 不论在界面还是在文字风格,都以前都强了很多。

 

背景透明度、文字高亮都可以自行定义,还能定义 emoji 等符号。如下为基本的展示,我们可以根据自己的需要调整整个界面。

 

在 Windows上写 Python 代码的最佳组合!
 
整个项目还在积极开发中,很多功能也都在完善与增加。不过既然是微软官方维护的开源项目,那么我们还是非常有信心的,至少在命令行部分可以降低开发过程中的各种报错。当然如果读者在 Windows 上有更好的命令行工具推荐,也可以在文末留言。

 

安装和配置 VS Code

 

前面介绍了开发中必不可缺的命令行工具,下面我们该聊一聊 VS Code 了,它是支持 Python 开发的核心工具。下面我们从最初的安装、环境管理到编写、测试、发布代码,介绍我们该如何优雅地使用 VS Code。

 

在任何平台上都可以安装 Visual Studio Code。官网提供了 Windows、Mac 和 Linux 的完整安装说明,并且会每月更新编辑器,其中包含新功能和错误修正。你可以在 Visual Studio Code 网站上找到所有安装内容:

 

在 Windows上写 Python 代码的最佳组合!

 

此外,除名称相近外,Visual Studio Code(简称 VS Code)与基于 Windows 的更大规模的 Visual Studio 几乎没有其他相同的地方。

 

Visual Studio Code 本身支持多种语言,并且它的一个扩展模型具有支持其他组件的丰富生态系统。VS Code 每月更新,你可以在微软 Python 博客中了解更新信息。任何用户都可以克隆微软的 VS Code Github 仓库并贡献自己的代码。

 

VS Code UI 已有详细记录,这里不予赘述:
在 Windows上写 Python 代码的最佳组合!
Python 扩展

 

如上所述,VS Code 通过详细记录的扩展模型支持多种编程语言的开发。Python 扩展使用户可以在 Visual Studio Code 中进行 Python 开发,具有以下特征:

 

  • 既支持 Python 3.4 及更高版本,也支持 Python 2.7 版本

  • 使用 IntelliSense 完成代码补全

  • Linting

  • 调试支持

  • 代码片段支持

  • 单元测试支持

  • 自动使用 conda 和虚拟环境

  • 在 Jupyter 环境和 Jupyter 笔记本中进行代码编辑

在 Windows上写 Python 代码的最佳组合!
Visual Studio Code 扩展不仅仅具有编程功能:

 

  • Keymaps 允许已经熟悉 Atom,Sublime Text,Emacs,Vim,PyCharm 或其他环境的用户更加容易上手。

  • 主题自定义 UI,无论您喜欢在明亮,黑暗或更丰富多彩的地方进行编码。

  • 语言包提供本地化体验。

 

以下是比较有用的一些其他扩展和设置:

 

  • GitLens 直接在编辑视窗中提供了大量有用的 Git 功能,包括非责任注释和存储库开发功能。

  • 通过从菜单中选择 File, Auto Save,可以轻松进行自动保存。默认延迟时间为 1000 毫秒,也可以重新配置。

  • Settings Sync 允许用户借助 GitHub 在不同的装置中同步自己的 VS Code 设置。如果用户在不同的计算机上工作,这有助于运行环境保持一致。

  • Docker 让用户可以快速轻松地使用 Docker,帮助创作 Dockerfile 和 docker-compose.yml,打包和部署项目,甚至为项目生成适当的 Docker 文件。

 

当然,在使用 VS Code 时,你可能会发现其他有用的扩展。请在评论中分享你的发现和设置!

 

单击活动栏(Activity Bar)上的「扩展」图标可以访问和安装新扩展和主题。用户可以输入关键词来搜索扩展程序,以多种方式对搜索结果进行排序,快速轻松地安装扩展程序。在本文中,在活动栏的 Extensions 项中键入 python 并单击 Install 即可安装 Python 扩展:
 

在 Windows上写 Python 代码的最佳组合!

用户可以通过相同的方式查找和安装上述任何扩展。

 

Visual Studio Code 配置文件

 

值得一提的是,Visual Studio Code 可通过用户和工作区设置(User and Workspace Settings)实现高度配置。

 

用户设置(User settings)在所有 Visual Studio Code 实例中都是全局性的,而工作区设置(Workspace Settings)是特定文件夹或项目工作区的本地设置。工作区设置为 VS Code 提供了极大的灵活性,工作区设置会在整篇文章中提到。工作区设置以.json 文件的形式存储在名为.vscode 的项目工作区本地文件夹中。
启动新的 Python 程序

 

让我们以一个新的 Python 程序来探索 Visual Studio Code 中的 Python 开发。在 VS Code 中,键入 Ctrl + N 打开一个新文件。(你也可以从菜单中选择「文件」-「新建」。)

 

无论你如何操作,你都应该看到一个类似于以下内容的 VS Code 窗口:
在 Windows上写 Python 代码的最佳组合!
打开新文件后,你即可以输入代码。

 

输入 Python 代码

 

作为测试,我们可以快速编码埃拉托斯特尼筛法(Sieve of Eratosthenes,它可以找出小于已知数的所有质数)。在刚打开的新选项卡中键入以下代码:
在 Windows上写 Python 代码的最佳组合!
等等,这是怎么回事?为什么 Visual Studio Code 没有进行任何关键词高亮显示,也没有进行任何自动格式化或任何真正有用的操作呢?它提供了什么?

 

答案是,VS Code 不知道它正在处理的是什么类型的文件。缓冲区被称为 Untitled-1,如果你查看窗口的右下角,则可以看到 Plain Text(纯文本)。

 

若要激活 Python 扩展,请保存文件(从菜单中选择 File-Save 或者从命令面板中选择 File-Save File 或者只使用 Ctrl + S)为 sieve.py。VS Code 将看到.py 扩展名并正确地将该文件转化为 Python 代码。

 

现在你的窗口视图应如下所示:
在 Windows上写 Python 代码的最佳组合!
这样就好多了!VS Code 会自动将文件重新格式化为 Python 代码,你可以通过检查左下角的语言模式予以验证。

 

如果你有多个 Python 安装(如 Python 2.7、Python 3.x 或 Anaconda),则可以通过单击语言模式指示器或者从命令面板中选择 Python: Select Interpreter 来更改 VS Code 所要使用的 Python 解释器。默认情况下,VS Code 支持使用 pep8 格式,但你也可以选择 black 或 yapf。
 
在 Windows上写 Python 代码的最佳组合!

 

现在可以添加其余的 Sieve 代码。若要查看 IntelliSense,请直接键入此代码而不要剪切和粘贴,你应该看到如下内容:

在 Windows上写 Python 代码的最佳组合!

当键入代码时,VS Code 会对 for 和 if 语句下面的行进行自动、适当的缩进,添加右括号,并给出内容提示。

 

运行 Python 代码

 

现在代码已经完成,你可以运行它了。没有必要让编辑器执行此操作:Visual Studio Code 可以直接在编辑器中运行此程序。保存文件(Ctrl + S),然后在编辑器窗口中单击右键并选择在终端(Terminal)中运行 Python 文件(Run Python File):

在 Windows上写 Python 代码的最佳组合!

你会看到终端窗格显示在窗口的底部,并显示代码输出结果。

 

编辑现有的 Python 项目

 

在 Sieve of Eratosthenes 示例中,你创建了一个 Python 文件。作为一个例子这很不错,但很多时候,你需要创建更大的项目,并在更长的时间内在它上面进行开发。

 

典型的新项目工作流程可能如下所示:

 

  • 创建一个文件夹来保存项目(可能包含一个新的 GitHub 项目)

  • 更改为新文件夹

  • 使用命令 code filename.py 创建初始 Python 代码

 

在 Python 项目(而不是单个 Python 文件)上使用 Visual Studio Code 开辟了更多功能,使得 VS Code 能够真正发挥作用。让我们来看看它在更大的项目中如何运作。

 

假如我们编写了一个计算器程序,该程序通过艾兹格·迪科斯彻(Edsger Dijkstra)调度场算法的一种变体来解析中缀符号(infix notation)编写的方程式。

 

为了说明 Visual Studio Code 以项目为中心的特征,我们现在开始在 Python 中重新创建调度场算法作为方程式评估库。相应 GitHub 地址:https://github.com/JFincher42/PyEval。

 

本地文件夹创建后,你可以快速打开 VS Code 中的整个文件夹。由于我们已经创建了文件夹和基本文件,所以首选方法(如上所述)做出如下修正:
cd /path/to/project
code .
当你这种方式打开时,VS Code 了解并将使用它看到的任何 virtualenv、pipenv 或 conda 环境。你甚至不需要首先启动虚拟环境。通过菜单中的 File, Open Folder、键盘上的 Ctrl+K, Ctrl+O 或者命令面板中的 File, Open Folder 等方式,你可以打开用户界面(UI)上的文件夹。

 

以下是创建的方程式 eval 库项目:
在 Windows上写 Python 代码的最佳组合!
当 Visual Studio Code 打开文件夹时,它还会再次打开上次打开的文件(这是可配置的)。你可以打开、编辑、运行和调试列出的任何文件。左侧活动栏中的资源管理器视图(Explorer view)提供文件夹中所有文件的视图,并显示当前选项卡集中有多少未保存文件。
代码测试的支持

 

VS Code 可以自动识别在 unittest、pytest 或 Nose 框架中编写的现有 Python 测试,但前提是在当前环境中安装了这些框架。作者在 unittest 框架中编写了一个用于方程式 eval 库的单元测试,你可以在这个例子中使用它。

 

若要运行项目中任何 Python 文件的现有单元测试,请单击右键并选择 Run Current Unit Test File。系统将提示指定测试框架,在项目中搜索测试的位置以及测试使用的文件名模式。

 

所有这些都保存为本地.vscode/settings.json 文件中的工作区设置,并可以进行修改。对于这个等式项目,你可以选择 unittest、当前文件夹和模式 *_test.py。

 

测试框架设置完成并显示测试后,你可以单击状态栏(Status Bar)上的 Run Tests 并从命令面板中选择一个 option 来运行所有测试:
在 Windows上写 Python 代码的最佳组合!
通过在 VS Code 中打开测试文件,单击状态栏上的 Run Tests,然后选择 Run Unit Test Method 以及其他要运行的特定测试,你还可以运行单个测试。这使得解决单个测试失败并重新运行失败的测试变得很简单,从而能够节省大量时间。测试结果显示在 Python Test Log 下的 Output 窗格中。
调试支持

 

即使 VS Code 是代码编辑器,直接在 VS Code 中调试 Python 也是可以的。VS Code 提供的诸多功能可以媲美好的代码调试器,包括:

 

  • 自动变量跟踪

  • 监看表达式

  • 断点

  • 调用堆栈检查

你可以在活动栏上的 Debug 视图中看到这些功能:
在 Windows上写 Python 代码的最佳组合!
调试器可以控制在内置终端或外部终端实例中运行的 Python 应用程序。它可以附加到已经运行的 Python 实例中,甚至可以调试 Django 和 Flask 应用程序。

 

在单个 Python 文件中调试代码就像按 F5 启动调试器一样简单。你可以按 F10 和 F11 分别跳过和进入函数,并按 Shift + F5 退出调试器。按 F9 设置断点,或者通过单击编辑器窗口中的左空白(lift margin)进行设置。

 

在开始调试更复杂的项目(包括 Django 或 Flask 应用程序)之前,你首先需要设置并选择调试配置。设置调试配置相对简单。从 Debug 视图中选择 Configuration 下拉列表(drop-down),然后选择 Add Configuration 和 Python:
在 Windows上写 Python 代码的最佳组合!

 

Visual Studio Code 将在当前名为.vscode/launch.json 的文件夹下创建一个调试配置文件,它允许用户设置特定的 Python 配置以及调试 Django 和 Flask 等特定应用程序的设置。

 

你还可以执行远程调试,并调试 Jinja 和 Django 模板。关闭编辑器中的 launch.json 文件,然后从 Configuration 下拉列表中为应用程序选择正确的配置。

 

Git 集成

 

VS Code 不仅内置对源代码控制管理的支持,还支持 Git 和 GitHub。你可以在 VS Code 中安装对其他 SCM 的支持,并列使用它们。用户可以从 Source Control 视图访问源代码控制:
 
在 Windows上写 Python 代码的最佳组合!
如果你的项目文件夹包含.git 文件夹,VS Code 会自动打开所有 Git / GitHub 功能。你可以执行以下诸多任务:

 

  • 将文件提交给 Git

  • 将更改推送到远程存储库(remote repo)并从中取出更改

  • check-out 现有或创建新的分支和标签(branch and tag)

  • 查看并解决合并冲突(merge conflict)

  • 查看差异(view diffs)

 
所有这些功能都可以直接从 VS Code UI 获得:
在 Windows上写 Python 代码的最佳组合!
VS Code 还可以识别编辑器外部进行的更改并且正确运作。

 

在 VS Code 中提交最近的更改相当简单。修改后的文件显示在 Source Control 视图中,并带有 M 标记,而新的未跟踪文件使用 U 标记。将鼠标悬停在文件上然后单击加号(+)可以暂存更改。在视图顶部添加提交消息,然后单击复选标记来提交更改:
 
在 Windows上写 Python 代码的最佳组合!

 

你也可以在 VS Code 中将本地提交(local commits)推送到 GitHub。从 Source Control 视图菜单中选择 Sync,或者单击分支指示器(branch indicator)旁边状态栏上的 Synchronize Changes。

 

所以在作者看来,Visual Studio Code 是最酷的通用编辑器之一,也是 Python 开发的最佳候选工具。希望你也可以在 Python 开发中尝试使用 Visual Studio Code 编辑器,相信不会令你失望的。
 
参考文章:
  • https://realpython.com/python-development-visual-studio-code/

  • https://devblogs.microsoft.com/commandline/introducing-windows-terminal/

— EOF —

 

转自:https://mp.weixin.qq.com/s/q-rz7moJYJVi_xwM_Eo5WQ

聊聊 PC 端自动化最佳方案:Pywinauto

1. 前言

上一篇文章,聊到 PC 端的一种自动化方案:WinAppDriver

有小伙伴后台留言,说「 pywinauto 」作为 WinAppDriver 的替代方案,也能完美完成 PC 端的自动化

2. 介绍

Pywinauto,完全由 Python 构建的一个模块,可以用于自动化 Windows 上的 GUI 应用程序

同时,它支持鼠标、键盘操作,在元素控件树较复杂的界面,可以辅助我们完成自动化操作

项目地址:https://github.com/pywinauto/pywinauto

支持的应用为下面 2 大类:

  • Win32 API  

    包含 MFC、VB6、VCL、simple WinForms controls and most of the old legacy apps

  • MS UI Automation

    包含 WinForms、WPF、Store apps、Qt5, browsers

其中

win32 API 的 backend 为「 win32

MS UI Automation 的 backend 为「 uia

3. 元素控件

和 WinAppDriver 类似,在编写自动化脚本之前,我们需要先获取元素控件的各类属性值

获取元素控件有 2 种方式:

  • 窗口内置方法

  • 检查工具

其中

窗口对象内置的 2 个方法都可以打印出当前页面的元素控件树

# 窗口对象中内置方法,打印窗体内所有元素控件
# 方式一:
窗体对象.print_control_identifiers()

# 方式二
窗体对象.dump_tree()

常用的检查工具也包含 2 种,分别是:Inspect.exe、Spy++

4. 实战一下

在实战之前,我们先安装依赖包 pywinauto

# 安装依赖
pip3 install pywinauto

接下来,我们还是以上篇文章中的例子来讲解完整的实现过程

4-1  打开微信客户端

首先,通过检查工具判断应用的 backend 属性值,PC 端微信的 backend 为「 uia 」

然后,实例化一个「 Application 」类

最后,使用该对象内置的函数创建一个应用对象

import pywinauto
from pywinauto.application import Application

# 获取应用对象
# 三种方式任选一种
# 方式一:应用进程pid(连接)
app = Application(backend='uia').connect(process=pid)

# 方式二:应用完整路径(连接)
app = Application(backend='uia').connect(path="D:Program Files (x86)TencentWeChatWeChat.exe")

# 方式三:打开应用(打开)
app = Application(backend='uia').start('D:Program Files (x86)TencentWeChatWeChat.exe')

需要指出的是,获取应用对象有上面 3 种方式,可以按需使用

4-2  获取窗体对象

通过检查工具获取窗体的属性列表,然后使用应用对象 + 窗体属性获取微信首页的窗体对象

聊聊 PC 端自动化最佳方案:Pywinauto

实现代码如下:

from pywinauto.win32functions import SetFocus

# 获取窗口对象
# 通过title及ClassName获取窗体对象
self.weixin_pc_window = self.app.window(title=u"微信", class_name="WeChatMainWndForPC")

self.weixin_pc_window.set_focus()

4-3  切换到聊天列

获取左侧聊天切换按钮,获取其坐标位置,模拟点击进入到聊天列表页面

from pywinauto import mouse

def __get_element_postion(self, element):
    """获取元素的中心点位置"""
    # 元素坐标
    element_position = element.rectangle()
    # 算出中心点位置
    center_position = (int((element_position.left + element_position.right) / 2),
                           int((element_position.top + element_position.bottom) / 2))
    return center_position

def start(self):
    # 1、获取左侧【聊天】切换元素
    chat_list_element = self.weixin_pc_window.child_window(title="聊天", control_type="Button")
    # 2、点击进入到聊天列表
    mouse.click(button='left',
                    coords=self.__get_element_postion(chat_list_element))

4-4  进入聊天页面,输入内容并发送

获取「 文件聊天助手 」元素,点击进入到聊天页面,找到输入框元素,使用内置方法输入内容,最后使用键盘模拟点击「 Enter 」键,发送消息

from pywinauto import mouse

# 3、点击【文件传输助手】进入到聊天页面
file_helper_element = self.weixin_pc_window.child_window(title="文件传输助手", control_type="ListItem")

mouse.click(button='left',
                    coords=self.__get_element_postion(file_helper_element))
# 4、获取输入框元素,模拟输入
        edit_element = self.weixin_pc_window.child_window(title=r"输入", control_type="Edit")

sleep(2)
# 输入内容
edit_element.type_keys("星安果")
# 使用键盘模拟回车,即:发送
send_keys('{ENTER}')

4-5  释放资源

完成操作后,可以调用应用对象的「 kill() 」函数关闭进程,释放掉资源

def teardown(self):
    """释放资源"""
    # 结束进程,释放资源
    self.app.kill()

5. 最后

上例中使用 pywinauto 完成了一个简单的发送消息的自动化步骤

实际项目中,结合鼠标、键盘可以实现很多复杂场景的自动化

pywinauto 和 WinAppDriver 都能很好的完成 PC 端的自动化,但是由于 WinAppDriver 支持 Appium,在脚本语法简洁性方面可能更有优势

 

– EOF –

转自:https://mp.weixin.qq.com/s/3qE1T2YeyoAqpqQdZYmkIA

强无敌,用 Python 复现基于北向资金的择时策略

大家好,我是帅东哥强无敌,用 Python 复现基于北向资金的择时策略

最近自己一直在学习理财相关的东西,所以后面一段时间,可能会多分享一些这方面的学习笔记

其实在学习之前,我一直在思考一个问题:为什么我们在市场上赚不了钱?可能基金还好点,只要行情不是特别差,你一直定投总会有多多少少有点收益的,但是其他市场就真不好说了。

观察了一下身边的朋友和同事,其实大多数人都是入门的。比如说有坚信价值投资的,拿着白马一拿就是好几年的;也有观察市场热点的,追涨杀跌玩的不亦乐乎。但是大家的收益都很一般,甚至亏钱的也不少。

所以,我在思考的时候就在想 价值投资和短线热点 这事。其实价值投资没有问题,但是拿的太久就是问题;短线热点也没有问题,但是没选对具体的个股基金就是问题。

并且,我自己是研究数据分析的,是不是可以在市场的基础上加一些数据分析导向的内容?或者是在数据的基础上,偏向于热点市场的板块?

目前来看,基于上面这个问题的思考,我是有一些小小的收获的。

但是我也还在学习中,今天的文章甚至后期的文章都只是一个阶段性的学习笔记,不敢说文章的方法适合于所有人。所以大家抄作业的时候也多多思考一下,毕竟方法是我的,但是钱是你的啊!


强无敌,用 Python 复现基于北向资金的择时策略

ok,说了些闲话,开始今天的正文。

今天的文章是对一个择时策略的复现,数据是基于每日大A北上资金进行的。这个策略很简单的一个应用:当市场处于持续低谷的时候,你可以加大你定投的比例;当市场开始火热一段时间了,你需要慢慢减少你定投的金额。

就像那句话:在别人贪婪的时候我恐惧,在别人空据的时候我贪婪。

以下是真正的正文:

在文章开始之前,先给大家普及一下北上资金的概念,懂的同学可以跳过去看下一节

北上资金?

在中国股市中有“南北”之称,一般“北”指的是沪深两市的股票,“南”指的是香港股票。因此,北上资金就是指从香港股票中流入大陆股市的资金,一般为香港资金以及国际资金。

从历史数据来看, 不管是长线短线,北上资金都比A股大部分投资者聪明。原因有很多,比如说:可能是外资的投资经验丰富信息渠道广,也有可能是内地部分游资通过北向资金通道进来,也就是换了一层马甲。

所以,在每天实盘的时候,大家可以关注北向资金的买入情况,偷懒一点的也可以跟着交易。但是但是但是,这里面有两个概念特别容易被大家混淆:净流入和净买入,其实它的公式很简单:

给大家解释下,外资每天买卖咱们A股都是有额度限制的,目前沪股通和深股通的额度都是每个交易日 520亿,而且是只要挂单就会占用额度,无论是否成交

所以,当日资金净流入会包含当日成交买入额和当日申报但未成交的买单金额,那么净流入金额一定会大于或等于净买入金额,这是两者最大的区别。

建议大家看北向资金的时候还是要看净买入金额,因为净流入金额只能代表北向资金的一个购买意愿,并不能代表真实交易。


常见的,一般 标准的 财经网站你应该会看到下面这种图:

强无敌,用 Python 复现基于北向资金的择时策略

强无敌,用 Python 复现基于北向资金的择时策略

但是很多时候你看到的都只是一个净流入的数据,并没有直接显示净买入的数据。

其实也不是说这个数据不对,只是说净买入数据会更准确些,更能反映当前北上资金的真实情况。这个数据最准确的就是在港交所了,而且是有盘中实时动态播报的,大家可以去了解一下。


强无敌,用 Python 复现基于北向资金的择时策略

说完基础知识,再来说今天的重点:基于北向资金的择时策略实现:

其实用一句话就可以解释所谓的择时选股策略:基于指标,对指数进行择时(即判断指数方向),如果方向向上,就进行选股

下图是华泰证券研究所的一篇报告,其中提到了一个基于北上资金的择时策略。正如文章开头所说,北上资金目前作为大A的风向标,具有一定的可参考性。

而报告中通过北上资金与沪深300的相关系数,也完美阐释了这一点:

强无敌,用 Python 复现基于北向资金的择时策略

该择时策略的具体内容是这样的:

强无敌,用 Python 复现基于北向资金的择时策略

策略理解起来很容易,但是怎么实现呢?

以下源码拿去即用(除了tushare需要安装,不过我想这个不用我教了吧),算是开源分享给大家。

1. 导入相应的库
# 导入相应的库
import tushare as ts
import datetime
import pandas as pd
import numpy as np
2. 通过接口 token 链接到 tushare
# 将 token 替换成你自己的就行
token = '替换成你自己的token'
pro = ts.pro_api(token)
3. 获取交易日的日期列表
# 获取所有交易日数据
trade_date = pro.trade_cal(start_date='20180101',end_date=datetime.datetime.today().strftime('%Y%m%d'))
date_list = list(trade_date[trade_date.is_open==1]['cal_date'].values)
4. 获取北上资金的日粒度数据

因为单次请求限制为300条,所以这一步可以分多次获取

# 单次请求限制为300条,分两次获取
df_data1 = pro.moneyflow_hsgt(start_date=date_list[0:300][0], end_date=date_list[0:300][-1])
df_data2 = pro.moneyflow_hsgt(start_date=date_list[300:600][0], end_date=date_list[300:600][-1])
df_data3 = pro.moneyflow_hsgt(start_date=date_list[600:][0], end_date=date_list[600:][-1])
# 合并数据
df_data = df_data1.append([df_data2, df_data3], ignore_index=True)
df_data = df_data.sort_values('trade_date',ascending=True).reset_index(drop=True)
# 重命名
df_data = df_data.rename(columns={'ggt_ss':'港股通-上海''ggt_sz':'港股通-深圳''hgt':'沪股通''sgt':'深股通''north_money':'北向资金''south_money':'南向资金'})

资金对应的单位是 百万,为了方便查看,这里需要进行单位的转换

# 单位换算:百万->亿
df_data['港股通-上海'] = df_data['港股通-上海']*0.01
df_data['港股通-深圳'] = df_data['港股通-深圳']*0.01
df_data['沪股通'] = df_data['沪股通']*0.01
df_data['深股通'] = df_data['深股通']*0.01
df_data['北向资金'] = df_data['北向资金']*0.01
df_data['南向资金'] = df_data['南向资金']*0.01

这里有一点需要注意,因为有个别日期北上资金是无法进行交易的。例如:6月30日-7月1日香港特别行政区纪念日、重阳节、圣诞节等均会有休市情况发生。

所以,有必要剔除掉这些北上资金休市的情况。

观察数据你会发现,如果根据 北上资金=0 这个条件去筛选,那恰好某一天的买入卖出刚好相等,这种情况也会被过滤掉,这明显是不合理的。

解决方法:根据 df_data[‘沪股通’].isna() 字段是否为空进行判断,代码如下:

# 剔除北上暂停交易的交易日
df_data2 = df_data.loc[~df_data['沪股通'].isna(), :].reset_index(drop=True)

数据处理完毕之后,对应的数据应该是这个样子的:

强无敌,用 Python 复现基于北向资金的择时策略

5. 核心策略实现

再来回顾一下策略的内容:

强无敌,用 Python 复现基于北向资金的择时策略

对了,图中的 252 表示大A一年中的交易日,你没看错,就这么多

而 1.5 倍标准差则是研报中规定的,至于为什么选这个数而不是其他 1倍、2倍呢?

研报中也有解释原因:其中一共选取了10组不同的上下限标注差,并且分别进行了回测,最终 上限+1.5 下限-1.5 的年化收益率最高,达到了 37.54%

ok,既然人家已经都做过了充分的回测,那我们就直接实现拿来用就好

核心代码如下:

"""遍历每一个交易日,对北上进行分析"""
signal = '无信号'
for index, row in df_data2.iterrows():
    if index<252:
        continue
    df_data_temp = df_data2.iloc[index-252:index]
    # 计算近 252 天的平均数和标准差
    average = df_data_temp['北向资金'].sum()/252
    std = df_data_temp['北向资金'].std()
    # 计算上下限
    up_line = float(format(average + std * 1.5'.4f'))
    down_line = float(format(average - std * 1.5'.4f'))

以上分别是计算出当天(从数据开始交易日的第252天起)以前 252 天的平均值、标准差、上限和下限

剩下的就是对结果进行判断和输出就ok,代码如下:

# 判断并输出
if row['北向资金'] >= up_line:
 signal = '看多'
 print('{0}:<{1}> 北上净买入:{2}亿元,看多线:{3}亿元, 看空线:{4}亿元'.format(row['trade_date'], signal, format(row['北向资金'], '.4f'), up_line, down_line))
elif row['北向资金'] <= down_line:
 signal = '看空'
 print('{0}:<{1}> 北上净买入:{2}亿元,看多线:{3}亿元, 看空线:{4}亿元'.format(row['trade_date'], signal, format(row['北向资金'], '.4f'), up_line, down_line))

if index == df_data2.shape[0]-1:
 print('n最新数据n{0}: <{1}> n北上净买入:{2}亿元,看多线:{3}亿元, 看空线:{4}亿元n'.format(row['trade_date'], signal, format(row['北向资金'], '.4f'), up_line, down_line))

截取了输出结果的今年的部分,如下图:

强无敌,用 Python 复现基于北向资金的择时策略

可以看到,截止到目前(8月30日收盘),策略给出的观点是看空,并且是从 7月26日 起就一直看空了,直到今天也是看空阶段。

去券商网站上看一下北上资金的历史数据,图是这样的:

强无敌,用 Python 复现基于北向资金的择时策略

从7月26号之后的(图中的红箭头)该策略给出的观点就是看空,但是你仔细看一下研报给的策略条件是,人家说的是:该日北向资金流入规模,而我们通过 tushare 获取到的是:北向资金的净买入金额

因为每日的净流入较净买入大很多,所以对应的 1.5倍标准差就需要相应的改动一下。

比如说,当你改成 上限+0.8 下限-0.8,它对应的策略是这样的:

强无敌,用 Python 复现基于北向资金的择时策略

当然了,这里的 0.8 其实是我自己乱改的,并没有经过回测验证,在这只是为了说明对应的数据不同,参数也要有所调整。

感兴趣的话大家可以去回测一下净买入金额对应的不同参数的收益结果,选一个最大的结果对应的参数,然后就可以开启轻松的定投模式了。

其实,我是有回测出最优参数的,但是担心你们用我的参数到时候亏钱了输不起,目前还是不公开出来了。

建议自己多试试,投资本就没有不劳而获的东西!或许你的参数收益会比我更优呢!

推荐阅读

1. pandas100个骚操作

2. 机器学习原创系列

3. 数据科学干货下载

最后给大家分享《10本数据挖掘电子书》,包括数据分析、统计学、数据挖掘、机器学习。
现在免费分享出来,有需要的读者可以下载学习,在下面的公众号「数据挖掘工程师」里回复关键字:数据挖掘,就行。