标签分类 热门分类
当前位置:首页 > > 机器学习电子书网盘下载
零起点Python机器学习快速入门 零起点Python机器学习快速入门
码小辫

码小辫 提供上传

资源
43
粉丝
49
喜欢
831
评论
20

    零起点Python机器学习快速入门 PDF 原书超清版

    机器学习电子书
    • 发布时间:

    给大家带来的一篇关于机器学习相关的电子书资源,介绍了关于零起点、Python机器学习方面的内容,本书是由电子工业出版社出版,格式为PDF,资源大小85.1 MB,何海群编写,目前豆瓣、亚马逊、当当、京东等电子书综合评分为:8.9

  • 零起点Python机器学习快速入门 PDF 下载
  • 下载地址:https://pan.baidu.com/s/12k8dQgQmofazPzAwiyZ9D
  • 分享码:6p93
  • 读者评价

    最近在学习相关,所以买来好好研究一下,大概看了一下,还不错,待后续研究

    这本书不要买了,个人意见就是看作者展示没有代码注释的ppt, 就是把作者的代码截图给你,每行代码什么意思自己去百度 ; 讲得走马观花,最垃圾的一本书,不知道作者怎么想的,还吹牛逼说只要会Excel就能看懂,是作者学霸吧; 我是之前看了python基础的,pandas会用了来买的。

    Python在科学计算领域,有两个重要的扩展模块:Numpy和Scipy。其中Numpy是一个用python实现的科学计算包。包括: 一个强大的N维数组对象Array; 比较成熟的(广播)函数库; 用于整合C/C++和Fortran代码的工具包

    零起点python机器学习快速入门 这本书第5章5-4示例import zsys import ztools两个模块是什么,怎么导入不了,复制源代码过去了,也运行不得,有一起的朋友吗?

    编辑推荐

    适读人群 :计算机行业、金融行业,数据分析、大数据研究人员等。不需要任何编程、交易经验,也不需要具备超强的数据分析能力,只要会使用Excel就可以轻松学会本书讲解的知识点。

    作者简介

    何海群,网名:字王,CHRD前海智库CTO,《中华大字库》发明人,出版书籍20余部,在人工智能、数据分析等方面具有20年一线专业经验;zwPython开发平台、zwQuant量化软件设计师,中国“Python创客”项目和“Python产业联盟”发起人,国内**Python量化课程:《Python量化实盘·魔鬼训练营》创始人,极宽量化开源团队的创始人。1990年,发明国内**个VR数据手套并获得专利授权,被业界称为“中国VR之父”;1992年,论文《人工智能与中文字型设计》入选《广东青年科学家文集》,现已成为中文字库行业三大基础建模理论之一;1997年,出版国内首部网络经济专著《网络商战》;2008年,在北京联合创办国内**4A级网络公关公司,服务过200余家国际五百强企业,被公关协会誉为:中国网络公关事业的开创者与启蒙者;2012年,发布国内**自主研发的智能中文字库设计软件《x2ttf涂鸦造字》,全功能全免费公益软件;2016年,推出国内首套纯python开源量化软件:zwQuant,以及国内**Tick级别开源金融大数据项目:zwDat金融数据包。研究成果有:“小数据”理论,快数据模型,黑天鹅算法,GPU超算工作站、MTRD多节点超算集群算法、“1+N”网络传播模型、人工智能“足彩图灵法则”等。

    内容简介

    本书采用独创的黑箱模式,MBA案例教学机制,结合一线实战案例,介绍Sklearn人工智能模块库和常用的机器学习算法。书中配备大量图表说明,没有枯燥的数学公式,普通读者,只要懂Word、Excel,就能够轻松阅读全书,并学习使用书中的知识,分析大数据。本书具有以下特色:独创的黑箱教学模式,全书无任何抽象理论和深奥的数学公式。首次系统化融合Sklearn人工智能软件和Pandas数据分析软件,不用再直接使用复杂的Numpy数学矩阵模块。系统化的Sklearn函数和API中文文档,可作为案头工具书随时查阅。基于Sklearn Pandas模式,无须任何理论基础,全程采用MBA案例模式,懂Excel就可看懂。

    内容节选

    set集合

    会保留下来唯一的那些元素

    #集合的创建方式:
    tang = [123,123,456,789]
    #方式1,通过set()创建
    tang = set(tang) 
    print (tang) #{123, 456, 789}
    tang = set()
    tang = set([123,123,456,456,789])
    print (tang) #{123, 456, 789}
    
    #方式2
     tang = {1,1,1,3,4}
    
    #集合的操作:
    #No.1:
    a = {1,2,3,4}
    b = {2,3,4,5}
    #取并集方式1
    print (a.union(b)) #{1,2,3,4,5}
    #取并集方式2
    print (a|b) #{1,2,3,4,5}
    a.intersection(b) #取交集,{2,3,4}
    a&b #同样是取交集
    a.difference(b) #得到a与b之间的差异值,a和b相比1是b中没有的,所以返回1
    print (a - b) #{1}
    print (b - a) #{5}
    
    #No.2:
    a = {1,2,3,4,5,6}
    b = {2,3,4} 
    #b是否为a的子集
    b.issubset(a) #True
    b <= a #True
    b > a #False
    a <= a #True
    a = {1,2,3}
    a.add(4)
    print(a) #{1,2,3,4}
    #对a集合做修改
    a.update([4,5,6])
    print (a) #{1,2,3,4,5,6}
    #删除元素
    a.remove(1)
    print(a) #{2,3,4,5,6}
    a.pop() #弹出元素
    print (a) #{3,4,5,6}

    循环

    #while循环
    tangs = set(['tang','bo','hu'])
    while tangs: #while后跟集合,表示集合中一旦没有元素就会退出循环
        tang = tangs.pop()
        print (tang)
    
    #for循环
    tangs2 = set(['xiao','bai','long'])
    for name in tangs2:
        print (name)
    
    #根据列表长度来进行循环输出
    tang = [1,2,5,8,0]
    for i in range(len(tang)):
        print (tang[i])

    函数

    #定义函数
    def print_value():
        print('你好吗')
        print('我很好')
    #调用函数
    print_value()
    
    #定义带参数的函数
    def add_ab(a,b):
        return (a+b)
    tang = add_ab(3,5)
    print (tang) #8
    
    #定义带参数的函数,顺便给参数赋值
    def add_ab(a=1,b=2):
        return (a+b)
    tang = add_ab()
    print (tang) #3
    
    #接收不定个数的参数用*args
    def add_number(a,*args):
        for i in args:
            a += i
        return a
    print (add_number(1,2,3)) #1代表a,结果为6
    
    #接收不定个数的键值对参数用**kwargs
    def add_number2(a,**kwargs):
        for arg,value in kwargs.items():#kwargs相当于字典可以调用items方法
            print (arg,value)
    add_number2(1,x=2,y=3)

    目录

    • 第 1 章 从阿尔法狗开始说起1
    • 1.1 阿尔法狗的前世今生.......1
    • 1.2 机器学习是什么.....2
    • 1.3 机器学习大史记.....3
    • 1.4 机器学习经典案例......... 11
    • 第 2 章 开发环境......13
    • 2.1 数据分析首选 Python.....13
    • 2.2 用户运行平台.......18
    • 2.3 程序目录结构.......19
    • 2.4 Spyder 编辑器界面设置.20
    • 2.5 Python 命令行模式.........26
    • 2.6 Notebook 模式......27
    • 2.7 模块库控制面板...29
    • 2.8 使用 pip 更新模块库......33
    • 第 3 章 Python 入门案例....39
    • 3.1 案例 3-1:第一次编程“hello,ziwang” ....39
    • 3.2 案例 3-2:增强版“hello,ziwang” ..42
    • 3.3 案例 3-3:列举系统模块库清单.......44
    • 3.4 案例 3-4:常用绘图风格.........45
    • 3.5 案例 3-5:Pandas 常用绘图风格.......47
    • 3.6 案例 3-6:常用颜色表 cors.....49
    • 3.7 案例源码.....50
    • 第 4 章 Python 基本语法....58
    • 4.1 数据类型.....58
    • 案例 4-1:基本运算.......59
    • 4.2 字符串.........61
    • 案例 4-2:字符串入门...61
    • 案例 4-3:字符串常用方法.....63
    • 4.3 List 列表......64
    • 案例 4-4:列表操作.......65
    • 4.4 Tuple 元组...66
    • 案例 4-5:元组操作.......67
    • 4.5 Dictionary 字典.....68
    • 案例 4-6:字典操作.......68
    • 4.6 数据类型转换.......70
    • 案例 4-7:控制语句.......71
    • 案例 4-8:函数定义.......73
    • 4.7 案例源码.....75
    • 第 5 章 Python 人工智能入门与实践......85
    • 5.1 从忘却开始.85
    • 5.2 Iris 经典爱丽丝.....89
    • 案例 5-1:Iris 爱丽丝 ....90
    • 案例 5-2:爱丽丝进化与文本矢量化.........92
    • 5.3 AI 操作流程95
    • 5.4 数据切割函数.......98
    • 案例 5-3:Iris 爱丽丝分解 ......99
    • 案例 5-4:线性回归算法.......103
    • 5.5 案例源码...109
    • 第 6 章 机器学习经典算法案例(上) . 116
    • 6.1 线性回归... 116
    • 6.2 逻辑回归算法.....124
    • 案例 6-1:逻辑回归算法.......125
    • 6.3 朴素贝叶斯算法.127
    • 案例 6-2:贝叶斯算法.129
    • 6.4 KNN 近邻算法 ...130
    • 案例 6-3:KNN 近邻算法.....133
    • 6.5 随机森林算法.....135
    • 案例 6-4:随机森林算法.......139
    • 6.6 案例源码...140
    • 第 7 章 机器学习经典算法案例(下) .149
    • 7.1 决策树算法.........149
    • 案例 7-1:决策树算法.151
    • 7.2 GBDT 迭代决策树算法.........153
    • 案例 7-2:GBDT 迭代决策树算法.154
    • 7.3 SVM 向量机 .......156
    • 案例 7-3:SVM 向量机算法.157
    • 7.4 SVM-cross 向量机交叉算法..159
    • 案例 7-4:SVM-cross 向量机交叉算法....160
    • 7.5 神经网络算法.....161
    • 案例 7-5:MLP 神经网络算法........165
    • 案例 7-6:MLP_reg 神经网络回归算法...168
    • 7.6 案例源码...170
    • 第 8 章 机器学习组合算法 .........183
    • 8.1 CCPP 数据集......183
    • 案例 8-1:CCPP 数据集........184
    • 案例 8-2:CCPP 数据切割....186
    • 案例 8-3:读取 CCPP 数据集.........189
    • 8.2 机器学习统一接口函数.........192
    • 案例 8-4:机器学习统一接口.........193
    • 案例 8-5:批量调用机器学习算法.201
    • 案例 8-6:一体化调用.205
    • 8.3 模型预制与保存.208
    • 案例 8-7:储存算法模型.......210
    • 案例 8-8:批量储存算法模型.........213
    • 案例 8-9:批量加载算法模型.........215
    • 案例 8-10:机器学习组合算法.......219
    • 8.4 案例源码...224
    • 附录 A Sklearn 常用模块和函数.242
    • 附录 B 极宽量化系统模块图......266

    读书笔记

    Python3.6及TensorFlow的安装和配置流程(图解)

    python3.6.3安装图文教程 TensorFlow安装配置方法

    一、Python官网下载自己电脑和系统对应的Python安装包。

     网址:下载地址

    一直往下拉到Files,这里我下载的是Windows x86-64 executable installer

    (注意:要装TensorFlow必须安装64位的Python,TensorFlow不支持32位)<

    二、下载python-3.6.3-amd64.exe应用程序

    下载完成后得到一个python-3.6.3-amd64.exe应用程序,右击以管理员身份运行该安装包;可以选择默认一路安装,也可以customize,自定义想要安装的路径;

     建议install for all users, 这里我安装的路径为D:\Python36;

     勾选 add to PATH ,可以省去后面的配置系统环境变量的步骤;一路next完成安装。

    三、测试是否安装成功

    打开cmd,输入Python;(如下图表明已安装成功)

    若显示python不是系统命令,说明系统环境变量未配置成功;下面介绍系统环境变量的配置。

    计算机(或我的电脑)-右键属性-环境变量-系统变量-path,双击打开path的编辑窗,加入Python的安装路径。如D:\Python36\Scripts\;D:\Python36\;(若在末尾不用加分号)

    确定之后重新cmd测试是否安装成功。

    四、安装后找到Python3.6文件夹

    安装完后可以在系统所有应用程序中找到Python3.6文件夹;

    为了方便可以把IDLE右键发送到桌面快捷方式。

    至此,Python3.6的安装就结束了。

    下面介绍TensorFlow的安装

    在上面的Python安装过程中,通常已经安装好了pip,下面就可以用pip来方便地安装各种开发需要的工具包。

    1.去下面的网址下载你需要的包。(TensorFlow,nltk,numpy 等等都可以找到)

    点击:下载地址

    2.这里以tensorflow为例,下载一个对应版本的TensorFlow

    3.把该文件放到Python安装路径下的Scripts文件夹下,如D:\Python36\Scripts

    4.打开cmd, 进入该路径,输入 pip install tensorflow-1.4.0-cp36-cp36m-win_amd64.whl

    按回车开始安装。

    安装成功的结果:

    其他工具包的安装都可以仿照此例,如自然语言处理NLTK的安装如下:

    下面就可以开始你的Python开发了。

    Win7 64位下python3.6.5安装配置图文教程

    一、安装python

    1、首先进入网站下载:点击打开链接(或自己输入网址),进入之后如下图,选择图中红色圈中区域进行下载。

    关注公众号:资料在线,干货满满。

    2、下载完成后如下图所示

    3、双击exe文件进行安装,如下图,并按照圈中区域进行设置,切记要勾选打钩的框,然后再点击Customize installation进入到下一步:

    4、对于上图中,可以通过Browse进行自定义安装路径,也可以直接点击Install进行安装,点击install后便可以完成安装了。

    5、为了检查我们的python是否安装成功,可以在命令窗口中输入python进行查询,如显示下图一的信息则表示成功了,如显示第二张图的信息则表示出错了。

    二、认识编程环境

    1、在开始运行处运行命令cmd,进行dos模式,输入python,即可进行python的交互式环境。

    2、进行到IDLE界面

    3、交互式界面可以用于简单的学习,编写较大程序时应到具体的python文件中,python文件默认的后缀为.py,我们可以新建文本文件,然后把后缀扩展名改为.py,然后

    最后选择菜单中的Run下的run module即可运行,快捷键为F5。

    第一次自己动手安装,还有许多问题要解决。

    安装过程小插曲,运行的时候提示:

    解决方法如下:

    (1)把C:\Windows\SysWOW64的api-ms-win-crt-runtime-l1-1-0.dll删除掉。

    (2)重新安装api-ms-win-crt-runtime-l1-1-0.dll(其实这个就是VC redit.exe里面的)

    安装VC redit.exe程序解决

    是VC的一个程序:VC redit.exe 下载链接

    下载安装完成两个目录下都会有了, 重启电脑,这时候就可以正常运行。

    python小白一枚,还有许多需要学习的地方,先记录一下。下一篇再整理一些pip安装教程。

    还有一个小补充:

    EOL while scanning string literal,提示这个异常的原因是:这个异常造成的原因是字符串,引号没有成对出现。

    win10下python3.5.2、tensorflow和matplotlib安装教程

    win10环境下搭建python3.5.2和tensorflow

    在win10环境下搭建python3.5.2和tensorflow平台,供大家参考,具体内容如下

    操作步骤如下:

    1、官网(https://www.python.org/ )下载python3.5.2 

    选择Downloads-Windows

    选择64位executable installer

    2、安装过程,双击.exe可执行文件

    一路默认下去!

      

    3、安装成功后打开cmd命令窗口

    print(“Hello World!”)回车后出现HelloWorld!即可

    4、python -m pip install -U pip 用来更新pip

    5、win10安装tensorflow (可参考 网址

    这里我安装tensorflow-cpu版本

    · 在命令行输入:pip install --upgrade --ignore-installed tensorflow

    6、安装库的方法

    下载库的网址:链接地址

     

     cp35代表适用python3.5版本,win64表示适用于64位电脑,下载版本如下红色字所示文件:

    以安装库matplotlib为例:

    至此环境搭建完成!

    注意事项:

    库报错

    解决:所有库必须统一来源、统一安装,下载网址

    win10下tensorflow和matplotlib安装教程

    本文介绍了一系列安装教程,具体如下

    1.安装Python

    版本选择是3.5.1,因为网上有些深度学习实例用的就是这个版本,跟他们一样的话可以避免版本带来的语句规范问题

    python的下载官网

    2.安装easy_install

    • 在Python的官网下载easy_install的安装包,下载地址
    • 下载完成后解压zip,解压后双击setup.py,会跳出一个黑框闪一下,这时python目录下的scripts文件夹中有了easy_install的应用程序文件。
    • 接下来配置环境变量:计算机→系统属性→高级系统设置→环境变量→双击path→添加Python和scripts的路径
    • win+R+cmd打开命令行,输入easy_install virtualenv,回车

    安装了easy_install之后安装Python库就方便了,直接在命令行中输入easy_install+libname就行了。但试验了几次后发现pip比较适合我这种小白,所以安装了pip。

    3.安装pip

    • 在命令行里输入easy_install pip,回车
    • 检查pip是否成功安装,直接在命令行里输入pip
    • pip版本升级,在命令行里输入:python -m pip install -U pip

    注意空格,比如python与-m之间就有个空格

    4.安装tensorflow

    确定计算机联网了,网速也要保证,有次我的网速太慢了,不得已一个组件一个组件的下,最后再输入以下那条命令,也成功了,但网速快的话是可以自动一次性下载完成的

    在命令行输入:pip install --upgrade --ignore-installed tensorflow

    安装完成后在Python中输入import tensorflow 可能会出现找不到模块的错误,这时需要安装MSVCP140.DLL,下载安装完成后重启电脑就可以了,下载地址

    5.安装matplotlib

    特别只出一个Python第三方组件库,内容很全:链接地址

    • 从刚才提到的第三方库中下载matplotlib,选择文件时注意cp35代表适用Python3.5版本,win64表示适用于64位电脑
    • 记住下载的matplotlib的路径,我一般会放在Python文件夹下
    • 打开命令行,输入cd 安装路径,回车。如果把所有下载的组件都放到这个安装路径的话,用cd转到这个路径再用pip安装就很方便
    • 在命令行继续输入pip install 文件名,文件名一定要写对写全。用这种法还可以安装很多组件,比如我文件夹下的那个pywin32。示例图如下:

    可以用一个简单的例子验证matplotlib是否安装正确,由于我还没有开始学matplotlib,这个例子用的是其他文章里的 (可以发现这篇文章里让安装的各种组件,在安装tensorflows的时候就已经自动安装好了,若是网速不够导致timeout,就要挨个下载安装这些组件)            

     例子:

    以上就是本文的全部内容,希望对大家的学习有所帮助

    Python高级编程技巧总结

    符合语言习惯的 Python 优雅编程技巧

    Python最大的优点之一就是语法简洁,好的代码就像伪代码一样,干净、整洁、一目了然。要写出 Pythonic(优雅的、地道的、整洁的)代码,需要多看多学大牛们写的代码,github 上有很多非常优秀的源代码值得阅读,比如:requests、flask、tornado,下面列举一些常见的Pythonic写法。
    0. 程序必须先让人读懂,然后才能让计算机执行。

    “Programs must be written for people to read, and only incidentally for machines to execute.”

    1. 交换赋值

    ##不推荐
    temp = a
    a = b
    b = a 
    ##推荐
    a, b = b, a # 先生成一个元组(tuple)对象,然后unpack

    2. Unpacking

    ##不推荐
    l = ['David', 'Pythonista', '+1-514-555-1234']
    first_name = l[0]
    last_name = l[1]
    phone_number = l[2] 
    ##推荐
    l = ['David', 'Pythonista', '+1-514-555-1234']
    first_name, last_name, phone_number = l
    # Python 3 Only
    first, *middle, last = another_list

    3. 使用操作符in

    ##不推荐
    if fruit == "apple" or fruit == "orange" or fruit == "berry":
      # 多次判断 
    ##推荐
    if fruit in ["apple", "orange", "berry"]:
      # 使用 in 更加简洁

    4. 字符串操作

    ##不推荐
    colors = ['red', 'blue', 'green', 'yellow']
    result = ''
    for s in colors:
      result += s # 每次赋值都丢弃以前的字符串对象, 生成一个新对象 
    ##推荐
    colors = ['red', 'blue', 'green', 'yellow']
    result = ''.join(colors) # 没有额外的内存分配

    5. 字典键值列表

    ##不推荐
    for key in my_dict.keys():
      # my_dict[key] ... 
    ##推荐
    for key in my_dict:
      # my_dict[key] ...
    # 只有当循环中需要更改key值的情况下,我们需要使用 my_dict.keys()
    # 生成静态的键值列表。

    6. 字典键值判断

    ##不推荐
    if my_dict.has_key(key):
      # ...do something with d[key] 
    ##推荐
    if key in my_dict:
      # ...do something with d[key]

    7. 字典 get 和 setdefault 方法

    ##不推荐
    navs = {}
    for (portfolio, equity, position) in data:
      if portfolio not in navs:
          navs[portfolio] = 0
      navs[portfolio] += position * prices[equity]
    ##推荐
    navs = {}
    for (portfolio, equity, position) in data:
      # 使用 get 方法
      navs[portfolio] = navs.get(portfolio, 0) + position * prices[equity]
      # 或者使用 setdefault 方法
      navs.setdefault(portfolio, 0)
      navs[portfolio] += position * prices[equity]

    8. 判断真伪

    ##不推荐
    if x == True:
      # ....
    if len(items) != 0:
      # ...
    if items != []:
      # ... 
    ##推荐
    if x:
      # ....
    if items:
      # ...

    9. 遍历列表以及索引

    ##不推荐
    items = 'zero one two three'.split()
    # method 1
    i = 0
    for item in items:
      print i, item
      i += 1
    # method 2
    for i in range(len(items)):
      print i, items[i]
    ##推荐
    items = 'zero one two three'.split()
    for i, item in enumerate(items):
      print i, item

    10. 列表推导

    ##不推荐
    new_list = []
    for item in a_list:
      if condition(item):
        new_list.append(fn(item)) 
    ##推荐
    new_list = [fn(item) for item in a_list if condition(item)]

    11. 列表推导-嵌套

    ##不推荐
    for sub_list in nested_list:
      if list_condition(sub_list):
        for item in sub_list:
          if item_condition(item):
            # do something... 
    ##推荐
    gen = (item for sl in nested_list if list_condition(sl) \
          for item in sl if item_condition(item))
    for item in gen:
      # do something...

    12. 循环嵌套

    ##不推荐
    for x in x_list:
      for y in y_list:
        for z in z_list:
          # do something for x &amp; y 
    ##推荐
    from itertools import product
    for x, y, z in product(x_list, y_list, z_list):
      # do something for x, y, z

    13. 尽量使用生成器代替列表

    ##不推荐
    def my_range(n):
      i = 0
      result = []
      while i &lt; n:
        result.append(fn(i))
        i += 1
      return result # 返回列表
    ##推荐
    def my_range(n):
      i = 0
      result = []
      while i &lt; n:
        yield fn(i) # 使用生成器代替列表
        i += 1
    *尽量用生成器代替列表,除非必须用到列表特有的函数。

    14. 中间结果尽量使用imap/ifilter代替map/filter

    ##不推荐
    reduce(rf, filter(ff, map(mf, a_list)))
    ##推荐
    from itertools import ifilter, imap
    reduce(rf, ifilter(ff, imap(mf, a_list)))
    *lazy evaluation 会带来更高的内存使用效率,特别是当处理大数据操作的时候。

    15. 使用any/all函数

    ##不推荐
    found = False
    for item in a_list:
      if condition(item):
        found = True
        break
    if found:
      # do something if found... 
    ##推荐
    if any(condition(item) for item in a_list):
      # do something if found...

    16. 属性(property)

    =
    ##不推荐
    class Clock(object):
      def __init__(self):
        self.__hour = 1
      def setHour(self, hour):
        if 25 &gt; hour &gt; 0: self.__hour = hour
        else: raise BadHourException
      def getHour(self):
        return self.__hour
    ##推荐
    class Clock(object):
      def __init__(self):
        self.__hour = 1
      def __setHour(self, hour):
        if 25 &gt; hour &gt; 0: self.__hour = hour
        else: raise BadHourException
      def __getHour(self):
        return self.__hour
      hour = property(__getHour, __setHour)

    17. 使用 with 处理文件打开

    ##不推荐
    f = open("some_file.txt")
    try:
      data = f.read()
      # 其他文件操作..
    finally:
      f.close()
    ##推荐
    with open("some_file.txt") as f:
      data = f.read()
      # 其他文件操作...

    18. 使用 with 忽视异常(仅限Python 3)

    ##不推荐
    try:
      os.remove("somefile.txt")
    except OSError:
      pass
    ##推荐
    from contextlib import ignored # Python 3 only
    with ignored(OSError):
      os.remove("somefile.txt")

    19. 使用 with 处理加锁

    ##不推荐
    import threading
    lock = threading.Lock()
    lock.acquire()
    try:
      # 互斥操作...
    finally:
      lock.release()
    ##推荐
    import threading
    lock = threading.Lock()
    with lock:
      # 互斥操作...

    20. 参考

    1) Idiomatic Python: http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html
    2) PEP 8: Style Guide for Python Code: http://www.python.org/dev/peps/pep-0008/

    有关Python的22个编程技巧

    1. 原地交换两个数字

    Python 提供了一个直观的在一行代码中赋值与交换(变量值)的方法,请参见下面的示例:

    x,y= 10,20
    print(x,y)
    x,y= y,x
    print(x,y)
    #1 (10, 20)
    #2 (20, 10)

    赋值的右侧形成了一个新的元组,左侧立即解析(unpack)那个(未被引用的)元组到变量 <a> 和 <b>。

    一旦赋值完成,新的元组变成了未被引用状态并且被标记为可被垃圾回收,最终也完成了变量的交换。

    2. 链状比较操作符

    比较操作符的聚合是另一个有时很方便的技巧:

    n= 10
    result= 1< n< 20
    print(result)
    # True
    result= 1> n<= 9
    print(result)
    # False

    3. 使用三元操作符来进行条件赋值

    三元操作符是 if-else 语句也就是条件操作符的一个快捷方式:

    [表达式为真的返回值] if [表达式] else [表达式为假的返回值]

    这里给出几个你可以用来使代码紧凑简洁的例子。下面的语句是说“如果 y 是 9,给 x 赋值 10,不然赋值为 20”。如果需要的话我们也可以延长这条操作链。

    x = 10 if (y == 9) else 20

    同样地,我们可以对类做这种操作:

    x = (classA if y == 1 else classB)(param1, param2)

    在上面的例子里 classA 与 classB 是两个类,其中一个类的构造函数会被调用。

    下面是另一个多个条件表达式链接起来用以计算最小值的例子:

    def small(a,b,c):
    returnaifa<= banda<= celse(bifb<= aandb<= celsec)
    print(small(1,0,1))
    print(small(1,2,2))
    print(small(2,2,3))
    print(small(5,4,3))
    #Output
    #0 #1 #2 #3

    我们甚至可以在列表推导中使用三元运算符:

    [m**2 if m > 10 else m**4 for m in range(50)]
    #=> [0, 1, 16, 81, 256, 625, 1296, 2401, 4096, 6561, 10000, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209, 2304, 2401]

    4. 多行字符串

    基本的方式是使用源于 C 语言的反斜杠:

    multiStr= “select * from multi_row
    where row_id < 5”
    print(multiStr)
    # select * from multi_row where row_id < 5

    另一个技巧是使用三引号:

    multiStr= “””select * from multi_row
    where row_id < 5″””
    print(multiStr)
    #select * from multi_row
    #where row_id < 5

    上面方法共有的问题是缺少合适的缩进,如果我们尝试缩进会在字符串中插入空格。所以最后的解决方案是将字符串分为多行并且将整个字符串包含在括号中:

    multiStr= (“select * from multi_row ”
    “where row_id < 5 ”
    “order by age”)
    print(multiStr)
    #select * from multi_row where row_id < 5 order by age

    5. 存储列表元素到新的变量中

    我们可以使用列表来初始化多个变量,在解析列表时,变量的数目不应该超过列表中的元素个数:【译者注:元素个数与列表长度应该严格相同,不然会报错】

    testList= [1,2,3]
    x,y,z= testList
    print(x,y,z)
    #-> 1 2 3

    6. 打印引入模块的文件路径

    如果你想知道引用到代码中模块的绝对路径,可以使用下面的技巧:

    import threading
    import socket
    print(threading)
    print(socket)
    #1- <module ‘threading' from ‘/usr/lib/python2.7/threading.py'>
    #2- <module ‘socket' from ‘/usr/lib/python2.7/socket.py'>

    7. 交互环境下的 “_” 操作符

    这是一个我们大多数人不知道的有用特性,在 Python 控制台,不论何时我们测试一个表达式或者调用一个方法,结果都会分配给一个临时变量: _(一个下划线)。

    >>> 2+ 1
    3
    >>> _
    3
    >>> print_
    3
    “_” 是上一个执行的表达式的输出。

    8. 字典/集合推导

    与我们使用的列表推导相似,我们也可以使用字典/集合推导,它们使用起来简单且有效,下面是一个例子:

    testDict= {i: i *iforiinxrange(10)}
    testSet= {i *2foriinxrange(10)}
    print(testSet)
    print(testDict)
    #set([0, 2, 4, 6, 8, 10, 12, 14, 16, 18])
    #{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

    注:两个语句中只有一个 <:> 的不同,另,在 Python3 中运行上述代码时,将 <xrange> 改为 <range>。

    9. 调试脚本

    我们可以在 <pdb> 模块的帮助下在 Python 脚本中设置断点,下面是一个例子:

    import pdb
    pdb.set_trace()

    我们可以在脚本中任何位置指定 <pdb.set_trace()> 并且在那里设置一个断点,相当简便。

    10. 开启文件分享

    Python 允许运行一个 HTTP 服务器来从根路径共享文件,下面是开启服务器的命令:

    # Python 2
    python -m SimpleHTTPServer
    # Python 3
    python3 -m http.server

    上面的命令会在默认端口也就是 8000 开启一个服务器,你可以将一个自定义的端口号以最后一个参数的方式传递到上面的命令中。

    11. 检查 Python 中的对象

    我们可以通过调用 dir() 方法来检查 Python 中的对象,下面是一个简单的例子:

    test= [1,3,5,7]
    print(dir(test))
    [‘__add__', ‘__class__', ‘__contains__', ‘__delattr__', ‘__delitem__', ‘__delslice__', ‘__doc__', ‘__eq__', ‘__format__', ‘__ge__', ‘__getattribute__', ‘__getitem__', ‘__getslice__', ‘__gt__', ‘__hash__', ‘__iadd__', ‘__imul__', ‘__init__', ‘__iter__', ‘__le__', ‘__len__', ‘__lt__', ‘__mul__', ‘__ne__', ‘__new__', ‘__reduce__', ‘__reduce_ex__', ‘__repr__', ‘__reversed__', ‘__rmul__', ‘__setattr__', ‘__setitem__', ‘__setslice__', ‘__sizeof__', ‘__str__', ‘__subclasshook__', ‘append', ‘count', ‘extend', ‘index', ‘insert', ‘pop', ‘remove', ‘reverse', ‘sort']

    12. 简化 if 语句

    我们可以使用下面的方式来验证多个值:

    if m in [1,3,5,7]:

    而不是:

    if m==1 or m==3 or m==5 or m==7:

    或者,对于 in 操作符我们也可以使用 ‘{1,3,5,7}' 而不是 ‘[1,3,5,7]',因为 set 中取元素是 O(1) 操作。

    13. 一行代码计算任何数的阶乘

    Python 2.x.
    result= (lambdak: reduce(int.__mul__,range(1,k+1),1))(3)
    print(result)
    #-> 6
    Python 3.x.
    import functools
    result= (lambdak: functools.reduce(int.__mul__,range(1,k+1),1))(3)
    print(result)
    #-> 6

    14. 找到列表中出现最频繁的数

    test= [1,2,3,4,2,2,3,1,4,4,4]
    print(max(set(test),key=test.count))
    #-> 4

    15. 重置递归限制

    Python 限制递归次数到 1000,我们可以重置这个值:

    import sys
    x=1001
    print(sys.getrecursionlimit())
    sys.setrecursionlimit(x)
    print(sys.getrecursionlimit())
    #1-> 1000
    #2-> 1001

    请只在必要的时候采用上面的技巧。

    16. 检查一个对象的内存使用

    在 Python 2.7 中,一个 32 比特的整数占用 24 字节,在 Python 3.5 中利用 28 字节。为确定内存使用,我们可以调用 getsizeof 方法:

    在 Python 2.7 中

    import sys
    x=1
    print(sys.getsizeof(x))
    #-> 24
    在 Python 3.5 中
    import sys
    x=1
    print(sys.getsizeof(x))
    #-> 28

    17. 使用 __slots__ 来减少内存开支

    你是否注意到你的 Python 应用占用许多资源特别是内存?有一个技巧是使用 __slots__ 类变量来在一定程度上减少内存开支。

    import sys
    classFileSystem(object):
    def __init__(self,files,folders,devices):
    self.files= files
    self.folders= folders
    self.devices= devices
    print(sys.getsizeof(FileSystem))
    classFileSystem1(object):
    __slots__= [‘files','folders','devices']
    def __init__(self,files,folders,devices):
    self.files= files
    self.folders= folders
    self.devices= devices
    print(sys.getsizeof(FileSystem1))
    #In Python 3.5
    #1-> 1016
    #2-> 888

    很明显,你可以从结果中看到确实有内存使用上的节省,但是你只应该在一个类的内存开销不必要得大时才使用 __slots__。只在对应用进行性能分析后才使用它,不然地话,你只是使得代码难以改变而没有真正的益处。

    【译者注:在我的 win10 python2.7 中上面的结果是:

    #In Python 2.7 win10
    #1-> 896
    #2-> 1016

    所以,这种比较方式是不那么让人信服的,使用 __slots__ 主要是用以限定对象的属性信息,另外,当生成对象很多时花销可能会小一些,具体可以参见 python 官方文档:

    The slots declaration takes a sequence of instance variables and reserves just enough space in each instance to hold a value for each variable. Space is saved because dict is not created for each instance. 】

    18. 使用 lambda 来模仿输出方法

    import sys
    lprint=lambda *args:sys.stdout.write(” “.join(map(str,args)))
    lprint(“python”,”tips”,1000,1001)
    #-> python tips 1000 1001

    19.从两个相关的序列构建一个字典

    t1= (1,2,3)
    t2= (10,20,30)
    print(dict(zip(t1,t2)))
    #-> {1: 10, 2: 20, 3: 30}

    20. 一行代码搜索字符串的多个前后缀

    print(“http://www.google.com”.startswith((“http://”,”https://”)))
    print(“http://www.google.co.uk”.endswith((“.com”,”.co.uk”)))
    #1-> True
    #2-> True

    21. 不使用循环构造一个列表

    import itertools
    test= [[-1,-2],[30,40],[25,35]]
    print(list(itertools.chain.from_iterable(test)))
    #-> [-1, -2, 30, 40, 25, 35]

    22. 在 Python 中实现一个真正的 switch-case 语句

    下面的代码使用一个字典来模拟构造一个 switch-case。

    def xswitch(x):
    returnxswitch._system_dict.get(x,None)
    xswitch._system_dict= {‘files': 10,'folders': 5,'devices': 2}
    print(xswitch(‘default'))
    print(xswitch(‘devices'))
    #1-> None
    #2-> 2

     

    Python 3.7中dataclass装饰器用法详解

    Python 3.7新功能之dataclass装饰器详解

    前言

    Python 3.7 将于今年夏天发布,Python 3.7 中将会有许多新东西:

    • 各种字符集的改进
    • 对注释的推迟评估
    • 以及对dataclass的支持

    最激动人心的新功能之一是 dataclass 装饰器。

    什么是 Data Class

    大多数 Python 开发人员编写过很多像下面这样的类:

    class MyClass:
     def __init__(self, var_a, var_b):
     self.var_a = var_a
     self.var_b = var_b

    dataclass 可以为简单的情况自动生成方法,例如,一个__init__接受这些参数并将其分配给自己,之前的小例子可以重写为:

    @dataclass
    class MyClass:
     var_a: str
     var_b: str

    那么通过一个例子来看看如何使用吧

    星球大战 API

    可以使用 requests 从星球大战 API 获取资源:

    response = requests.get('https://swapi.co/api/films/1/')
    dictionary = response.json()

    让我们来看看 dictionary (简化过)的结果:

    {
     'characters': ['https://swapi.co/api/people/1/',… ],
     'created': '2014-12-10T14:23:31.880000Z',
     'director': 'George Lucas',
     'edited': '2015-04-11T09:46:52.774897Z',
     'episode_id': 4,
     'opening_crawl': 'It is a period of civil war.\r\n … ',
     'planets': ['https://swapi.co/api/planets/2/', … ],
     'producer': 'Gary Kurtz, Rick McCallum',
     'release_date': '1977-05-25',
     'species': ['https://swapi.co/api/species/5/',…],
     'starships': ['https://swapi.co/api/starships/2/',…],
     'title': 'A New Hope',
     'url': 'https://swapi.co/api/films/1/',
     'vehicles': ['https://swapi.co/api/vehicles/4/',…]

    封装 API

    为了正确地封装一个 API,我们应该创建一个用户可以在其应用程序中使用的对象,因此,在Python 3.6 中定义一个对象来包含requests对 /films/endpoint的响应:

    class StarWarsMovie:
     def __init__(self,
       title: str,
       episode_id: int,
       opening_crawl: str,
       director: str,
       producer: str,
       release_date: datetime,
       characters: List[str],
       planets: List[str],
       starships: List[str],
       vehicles: List[str],
       species: List[str],
       created: datetime,
       edited: datetime,
       url: str
       ):
    
     self.title = title
     self.episode_id = episode_id
     self.opening_crawl= opening_crawl
     self.director = director
     self.producer = producer
     self.release_date = release_date
     self.characters = characters
     self.planets = planets
     self.starships = starships
     self.vehicles = vehicles
     self.species = species
     self.created = created
     self.edited = edited
     self.url = url
    
     if type(self.release_date) is str:
      self.release_date = dateutil.parser.parse(self.release_date)
    
     if type(self.created) is str:
      self.created = dateutil.parser.parse(self.created)
    
     if type(self.edited) is str:
      self.edited = dateutil.parser.parse(self.edited)

    仔细的读者可能已经注意到这里有一些重复的代码。

    这是使用 dataclass 装饰器的经典案例,我们需要创建一个主要用来保存数据的类,只需一点验证,所以让我们来看看我们需要修改什么。

    首先,data class 自动生成一些 dunder 方法,如果我们没有为 data class 装饰器指定任何选项,则生成的方法有:__init__,__eq__和__repr__,如果你已经定义了__repr__但没定义__str__,默认情况下 Python(不仅仅是 data class)将实现返回__repr__的输出__str__方法。因此,只需将代码更改为以下代码即可实现四种 dunder 方法:

    @dataclass
    class StarWarsMovie:
     title: str
     episode_id: int
     opening_crawl: str
     director: str
     producer: str
     release_date: datetime
     characters: List[str]
     planets: List[str]
     starships: List[str]
     vehicles: List[str]
     species: List[str]
     created: datetime
     edited: datetime
     url: str

    我们去掉了__init__方法,以确保 data class 装饰器可以添加它生成的对应方法。不过,我们在这个过程中失去了一些功能,我们的 Python 3.6 构造函数不仅定义了所有的值,还试图解析日期,我们怎样才能用 data class 来做到这一点呢?

    如果要覆盖 __init__,我们将失去 data class 的优势,因此,如果要处理任何附加功能可以使用新的 dunder 方法:__post_init__,让我们看看__post_init__方法对于我们的包装类来说是什么样子的:

    def __post_init__(self):
     if type(self.release_date) is str:
      self.release_date = dateutil.parser.parse(self.release_date)
    
     if type(self.created) is str:
      self.created = dateutil.parser.parse(self.created)
    
     if type(self.edited) is str:
      self.edited = dateutil.parser.parse(self.edited)

    就是这样! 我们可以使用 data class 装饰器在用三分之二的代码量实现我们的类。

    更多好东西

    通过使用装饰器的选项,可以为用例进一步定制 data class,默认选项是:

    @dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)
    • init决定是否生成__init__ dunder 方法
    • repr决定是否生成__repr__ dunder方法
    • eq对__eq__ dunder 方法也是如此,它决定相等性检查的行为(your_class_instance == another_instance)
    • order 实际上创建了四种 dunder 方法,它们确定所有检查小于,and/or,大于的行为,如果将其设置为 true,则可以对对象列表进行排序。

    最后两个选项确定对象是否可以被哈希化,如果你想使用你的 class 的对象作为字典键的话,这是必要的。

    更多信息请参考:PEP 557 -- Data Classes

    python类装饰器用法实例

    本文实例讲述了python类装饰器用法。分享给大家供大家参考。具体如下:

    #!coding=utf-8 
    registry = {} 
    def register(cls): 
      registry[cls.__clsid__] = cls 
      return cls 
    @register 
    class Foo(object): 
      __clsid__ = '123-456' 
      def bar(self): 
        pass 
    print registry 
    
    

    运行结果如下:

    {'123-456': <class '__main__.Foo'>}

    希望本文所述对大家的Python程序设计有所帮助。

    Python 使用类写装饰器的小技巧

    最近学到了一个有趣的装饰器写法,就记录一下。

    装饰器是一个返回函数的函数。写一个装饰器,除了最常见的在函数中定义函数以外,Python还允许使用类来定义一个装饰器。

    1、用类写装饰器

    下面用常见的写法实现了一个缓存装饰器。

    def cache(func):
      data = {}
      def wrapper(*args, **kwargs):
        key = f'{func.__name__}-{str(args)}-{str(kwargs)})'
        if key in data:
          result = data.get(key)
          print('cached')
        else:
          result = func(*args, **kwargs)
          data[key] = result
          print('calculated')
        return result
      return wrapper

    看看缓存的效果。

    @cache
    def rectangle_area(length, width):
      return length * width
    rectangle_area(2, 3)
    # calculated
    # 6
    rectangle_area(2, 3)
    # cached
    # 6

    装饰器的@cache是一个语法糖,相当于func = cache(func),如果这里的cache不是一个函数,而是一个类又会怎样呢?定义一个类class Cache, 那么调用func = Cache(func)会得到一个对象,这时返回的func其实是Cache的对象。定义__call__方法可以将类的实例变成可调用对象,可以像调用函数一样调用对象。然后在__call__方法里调用原本的func函数就能实现装饰器了。所以Cache类也能当作装饰器使用,并且能以@Cache的形式使用。

    接下来把cache函数改写为Cache类:

    class Cache:
      def __init__(self, func):
        self.func = func
        self.data = {}
      def __call__(self, *args, **kwargs):
        func = self.func
        data = self.data
        key = f'{func.__name__}-{str(args)}-{str(kwargs)})'
        if key in data:
          result = data.get(key)
          print('cached')
        else:
          result = func(*args, **kwargs)
          data[key] = result
          print('calculated')
        return result

    再看看缓存结果,效果一样。

    @Cache
    def rectangle_area(length, width):
      return length * width
    rectangle_area(2, 3)
    # calculated
    # 6
    rectangle_area(2, 3)
    # cached
    # 6

    2、装饰类的方法

    装饰器不止能装饰函数,也经常用来装饰类的方法,但是我发现用类写的装饰器不能直接用在装饰类的方法上。(有点绕…)

    先看看函数写的装饰器如何装饰类的方法。

    class Rectangle:
      def __init__(self, length, width):
        self.length = length
        self.width = width
      @cache
      def area(self):
        return self.length * self.width
    r = Rectangle(2, 3)
    r.area()
    # calculated
    # 6
    r.area()
    # cached
    # 6

    但是如果直接换成Cache类会报错,这个错误的原因是area被装饰后变成了类的一个属性,而不是方法。

    class Rectangle:
      def __init__(self, length, width):
        self.length = length
        self.width = width
      @Cache
      def area(self):
        return self.length * self.width
    r = Rectangle(2, 3)
    r.area()
    # TypeError: area() missing 1 required positional argument: 'self'
    Rectangle.area
    # <__main__.Cache object at 0x0000012D8E7A6D30>
    r.area
    # <__main__.Cache object at 0x0000012D8E7A6D30>

    回头再来看看没有装饰器的情况,Python在实例化对象后把函数变成了方法。

    class Rectangle:
      def __init__(self, length, width):
        self.length = length
        self.width = width
    
      def area(self):
        return self.length * self.width
    
    Rectangle.area
    # <function Rectangle.area at 0x0000012D8E7B28C8>
    r = Rectangle(2, 3)
    r.area
    # <bound method Rectangle.area of <__main__.Rectangle object

    因此解决办法很简单,要用类写的装饰器来装饰类的方法,只需要把可调用对象包装成函数就行。

    # 定义一个简单的装饰器,什么也不做,仅仅是把可调用对象包装成函数
    def method(call):
      def wrapper(*args, **kwargs):
        return call(*args, **kwargs)
      return wrapper
    class Rectangle:
      def __init__(self, length, width):
        self.length = length
        self.width = width
      @method
      @Cache
      def area(self):
        return self.length * self.width
    r = Rectangle(2, 3)
    r.area()
    # calculated
    # 6
    r.area()
    # cached
    # 6

    或者用@property还能直接把方法变成属性。

    class Rectangle:
      def __init__(self, length, width):
        self.length = length
        self.width = width
      @property
      @Cache
      def area(self):
        return self.length * self.width
    r = Rectangle(2, 3)
    r.area
    # calculated
    # 6
    r.area
    # cached
    # 6

    总结

    用类写装饰器并非什么特别的技巧,一般情况下确实没必要这么写,不过这样就可以用一些类的特性来写装饰器,比如类的继承,也算是提供了另一种思路吧。

    用Python实现2048小游戏操作步骤

    前言

    2048游戏规则:简单的移动方向键让数字叠加,并且获得这些数字每次叠加后的得分,当出现2048这个数字时游戏胜利。同时每次移动方向键时,都会在这个4*4的方格矩阵的空白区域随机产生一个数字2或者4,如果方格被数字填满了,那么就GameOver了。

    主逻辑图

    逻辑图解:黑色是逻辑层,蓝色是外部方法,红色是类内方法,稍后即可知道~

    下面容我逐行解释主逻辑main()函数,并且在其中穿叉外部定义的函数与类。

    主逻辑代码解读(完整代码见文末)

    主逻辑main如下,之后的是对主函数中的一些方法的解读:

    def main(stdscr):
     def init():
     #重置游戏棋盘
     game_field.reset()
     return 'Game'
    
     def not_game(state):
     #画出 GameOver 或者 Win 的界面
     game_field.draw(stdscr)
     #读取用户输入得到action,判断是重启游戏还是结束游戏
     action = get_user_action(stdscr)
     responses = defaultdict(lambda: state) #默认是当前状态,没有行为就会一直在当前界面循环
     responses['Restart'], responses['Exit'] = 'Init', 'Exit' #对应不同的行为转换到不同的状态
     return responses[action]
    
     def game():
     #画出当前棋盘状态
     game_field.draw(stdscr)
     #读取用户输入得到action
     action = get_user_action(stdscr)
    
     if action == 'Restart':
      return 'Init'
     if action == 'Exit':
      return 'Exit'
     if game_field.move(action): # move successful
      if game_field.is_win():
      return 'Win'
      if game_field.is_gameover():
      return 'Gameover'
     return 'Game'
    
    
     state_actions = {
      'Init': init,
      'Win': lambda: not_game('Win'),
      'Gameover': lambda: not_game('Gameover'),
      'Game': game
     }
    
     curses.use_default_colors()
     game_field = GameField(win=32)
    
     state = 'Init'
    
     #状态机开始循环
     while state != 'Exit':
     state = state_actions[state]()

    逐条解读(代码框内会标注是来自外部,无标注则是来自内部):定义主函数

    def main(stdscr):
     def init():
     #重置游戏棋盘
     game_field.reset()

    reset出自外部定义的类,game_field=GameField的一个方法reset:

      外部:

     def reset(self):
     if self.score > self.highscore:
      self.highscore = self.score
     self.score = 0
     self.field = [[0 for i in range(self.width)] for j in range(self.height)]
     self.spawn()
     self.spawn()
    #其中highscore为程序初始化过程中定义的一个变量。记录你win游戏的最高分数记录。
     return 'Game'

    返回一个游戏进行中的状态。game_field=GameField状态在后面有定义:

    主函数底部定义:

     state_actions = {
      'Init': init,
      'Win': lambda: not_game('Win'),
      'Gameover': lambda: not_game('Gameover'),
      'Game': game
     }
     def not_game(state):
     #画出 GameOver 或者 Win 的界面
     game_field.draw(stdscr)

    draw是导入的类game_field=GameField中的方法:

    #来自外部类
     def draw(self, screen):
     help_string1 = '(W)Up (S)Down (A)Left (D)Right'
     help_string2 = ' (R)Restart (Q)Exit'
     gameover_string = '  GAME OVER'
     win_string = '  YOU WIN!'
    #定义各个字符串
     def cast(string):
      screen.addstr(string + '\n')
    
     def draw_hor_separator():
      line = '+' + ('+------' * self.width + '+')[1:]
      separator = defaultdict(lambda: line)
      if not hasattr(draw_hor_separator, "counter"):
      draw_hor_separator.counter = 0
      cast(separator[draw_hor_separator.counter])
      draw_hor_separator.counter += 1
    
     def draw_row(row):
      cast(''.join('|{: ^5} '.format(num) if num > 0 else '| ' for num in row) + '|')
    
     screen.clear()
     cast('SCORE: ' + str(self.score))
     if 0 != self.highscore:
      cast('HGHSCORE: ' + str(self.highscore))
     for row in self.field:
      draw_hor_separator()
      draw_row(row)
     draw_hor_separator()
     if self.is_win():
      cast(win_string)
     else:
      if self.is_gameover():
      cast(gameover_string)
      else:
      cast(help_string1)
     cast(help_string2)
    #这里面的draw方法的字函数我就不做多的解释了,很简单的一些概念。
    #但是又运用到了很优秀的精简代码。
    #有的地方建议去查一下python的一些高级概念,我就不做多的介绍了。

    这里面的draw方法的字函数我就不做多的解释了,很简单的一些概念。

    但是又运用到了很优秀的精简代码。

    有的地方建议去查一下python的一些高级概念,我就不做多的介绍了。

     #读取用户输入得到action,判断是重启游戏还是结束游戏
     action = get_user_action(stdscr)

    读取用户行为,函数来自于代码初始的定义

    #来自外部定义的函数
    def get_user_action(keyboard): 
     char = "N"
     while char not in actions_dict: 
     char = keyboard.getch()
     return actions_dict[char]

    在结尾处,也即是主函数执行的第三步,定义了state = state_actions[state]()这一实例:

    #主函数底部:
     state = 'Init'
    
     #状态机开始循环
     while state != 'Exit':
     state = state_actions[state]()
     responses = defaultdict(lambda: state) #默认是当前状态,没有行为就会一直在当前界面循环
     responses['Restart'], responses['Exit'] = 'Init', 'Exit' #对应不同的行为转换到不同的状态
     return responses[action]
     def game():
     #画出当前棋盘状态
     game_field.draw(stdscr)
     #读取用户输入得到action
     action = get_user_action(stdscr)
    
     if action == 'Restart':
      return 'Init'
     if action == 'Exit':
      return 'Exit'
     if game_field.move(action): # move successful
      if game_field.is_win():
      return 'Win'
      if game_field.is_gameover():
      return 'Gameover'
     return 'Game'
    #game()函数的定义类似于上面已经讲过的not_game(),只是game()有了内部循环
    #即如果不是Restart/Exit或者对move之后的状态进行判断,如果不是结束游戏,就一直在game()内部循环。

    game()函数的定义类似于上面已经讲过的not_game() ,只是game()有了内部循环,即如果不是Restart/Exit或者对move之后的状态进行判断,如果不是结束游戏,就一直在game()内部循环。

     state_actions = {
      'Init': init,
      'Win': lambda: not_game('Win'),
      'Gameover': lambda: not_game('Gameover'),
      'Game': game
       }
    
     curses.use_default_colors()
     game_field = GameField(win=32)
    
    
     state = 'Init'
    
     #状态机开始循环
     while state != 'Exit':
     state = state_actions[state]()
    #此处的意思是:state=state_actions[state] 可以看做是:
    #state=init()或者state=not_game(‘Win')或者是另外的not_game(‘Gameover')/game()

    此处的意思是:state=state_actions[state] 可以看做是:state=init()或者state=not_game(‘Win')或者是另外的not_game(‘Gameover')/game()

    废话不多说,上一个我的成功的图,另外,可以通过设置最后几行中的win=32来决定你最终获胜的条件!

    完整代码

    #-*- coding:utf-8 -*-
    import curses
    from random import randrange, choice # generate and place new tile
    from collections import defaultdict
    letter_codes = [ord(ch) for ch in 'WASDRQwasdrq']
    actions = ['Up', 'Left', 'Down', 'Right', 'Restart', 'Exit']
    actions_dict = dict(zip(letter_codes, actions * 2))
    def transpose(field):
     return [list(row) for row in zip(*field)]
    
    def invert(field):
     return [row[::-1] for row in field]
    
    class GameField(object):
     def __init__(self, height=4, width=4, win=2048):
     self.height = height
     self.width = width
     self.win_value = win
     self.score = 0
     self.highscore = 0
     self.reset()
    
     def reset(self):
     if self.score > self.highscore:
      self.highscore = self.score
     self.score = 0
     self.field = [[0 for i in range(self.width)] for j in range(self.height)]
     self.spawn()
     self.spawn()
    
     def move(self, direction):
     def move_row_left(row):
      def tighten(row): # squeese non-zero elements together
      new_row = [i for i in row if i != 0]
      new_row += [0 for i in range(len(row) - len(new_row))]
      return new_row
    
      def merge(row):
      pair = False
      new_row = []
      for i in range(len(row)):
       if pair:
       new_row.append(2 * row[i])
       self.score += 2 * row[i]
       pair = False
       else:
       if i + 1 < len(row) and row[i] == row[i + 1]:
        pair = True
        new_row.append(0)
       else:
        new_row.append(row[i])
      assert len(new_row) == len(row)
      return new_row
      return tighten(merge(tighten(row)))
    
     moves = {}
     moves['Left'] = lambda field:    \
      [move_row_left(row) for row in field]
     moves['Right'] = lambda field:    \
      invert(moves['Left'](invert(field)))
     moves['Up'] = lambda field:    \
      transpose(moves['Left'](transpose(field)))
     moves['Down'] = lambda field:    \
      transpose(moves['Right'](transpose(field)))
    
     if direction in moves:
      if self.move_is_possible(direction):
      self.field = moves[direction](self.field)
      self.spawn()
      return True
      else:
      return False
    
     def is_win(self):
     return any(any(i >= self.win_value for i in row) for row in self.field)
    
     def is_gameover(self):
     return not any(self.move_is_possible(move) for move in actions)
    
     def draw(self, screen):
     help_string1 = '(W)Up (S)Down (A)Left (D)Right'
     help_string2 = ' (R)Restart (Q)Exit'
     gameover_string = '  GAME OVER'
     win_string = '  YOU WIN!'
     def cast(string):
      screen.addstr(string + '\n')
    
     def draw_hor_separator():
      line = '+' + ('+------' * self.width + '+')[1:]
      separator = defaultdict(lambda: line)
      if not hasattr(draw_hor_separator, "counter"):
      draw_hor_separator.counter = 0
      cast(separator[draw_hor_separator.counter])
      draw_hor_separator.counter += 1
    
     def draw_row(row):
      cast(''.join('|{: ^5} '.format(num) if num > 0 else '| ' for num in row) + '|')
    
     screen.clear()
     cast('SCORE: ' + str(self.score))
     if 0 != self.highscore:
      cast('HGHSCORE: ' + str(self.highscore))
     for row in self.field:
      draw_hor_separator()
      draw_row(row)
     draw_hor_separator()
     if self.is_win():
      cast(win_string)
     else:
      if self.is_gameover():
      cast(gameover_string)
      else:
      cast(help_string1)
     cast(help_string2)
    
     def spawn(self):
     new_element = 4 if randrange(100) > 89 else 2
     (i,j) = choice([(i,j) for i in range(self.width) for j in range(self.height) if self.field[i][j] == 0])
     self.field[i][j] = new_element
    
     def move_is_possible(self, direction):
     def row_is_left_movable(row): 
      def change(i): # true if there'll be change in i-th tile
      if row[i] == 0 and row[i + 1] != 0: # Move
       return True
      if row[i] != 0 and row[i + 1] == row[i]: # Merge
       return True
      return False
      return any(change(i) for i in range(len(row) - 1))
    
     check = {}
     check['Left'] = lambda field:    \
      any(row_is_left_movable(row) for row in field)
    
     check['Right'] = lambda field:    \
       check['Left'](invert(field))
    
     check['Up'] = lambda field:    \
      check['Left'](transpose(field))
    
     check['Down'] = lambda field:    \
      check['Right'](transpose(field))
    
     if direction in check:
      return check[direction](self.field)
     else:
      return False
    def main(stdscr):
     def init():
     #重置游戏棋盘
     game_field.reset()
     return 'Game'
     def not_game(state):
     #画出 GameOver 或者 Win 的界面
     game_field.draw(stdscr)
     #读取用户输入得到action,判断是重启游戏还是结束游戏
     action = get_user_action(stdscr)
     responses = defaultdict(lambda: state) #默认是当前状态,没有行为就会一直在当前界面循环
     responses['Restart'], responses['Exit'] = 'Init', 'Exit' #对应不同的行为转换到不同的状态
     return responses[action]
    
     def game():
     #画出当前棋盘状态
     game_field.draw(stdscr)
     #读取用户输入得到action
     action = get_user_action(stdscr)
    
     if action == 'Restart':
      return 'Init'
     if action == 'Exit':
      return 'Exit'
     if game_field.move(action): # move successful
      if game_field.is_win():
      return 'Win'
      if game_field.is_gameover():
      return 'Gameover'
     return 'Game'
    
    
     state_actions = {
      'Init': init,
      'Win': lambda: not_game('Win'),
      'Gameover': lambda: not_game('Gameover'),
      'Game': game
     }
     curses.use_default_colors()
     game_field = GameField(win=32)
     state = 'Init'
     #状态机开始循环
     while state != 'Exit':
     state = state_actions[state]()
    curses.wrapper(main)

     

    上一篇:Keras快速上手:基于Python的深度学习实战  下一篇:Python可以这样学

    展开 +

    收起 -

     
    机器学习 相关电子书
    关于机器学习的学习笔记

    Copyright 2018-2020 xz577.com 码农之家

    电子书资源由网友、会员提供上传,本站记录提供者的基本信息及资源来路

    鸣谢: “ 码小辫 ” 公众号提供回调API服务、“ 脚本CDN ”提供网站加速(本站寻求更多赞助支持)

    版权投诉 / 书籍推广 / 赞助:520161757@qq.com

    上传资源(网友、会员均可提供)

    查看最新会员资料及资源信息