标签分类
当前位置:首页 > > Python3.5编程电子书网盘下载
Python编程:从入门到实践 Python编程:从入门到实践
码小辫

码小辫 提供上传

资源
46
粉丝
32
喜欢
878
评论
1

    Python编程:从入门到实践 PDF 中文扫描版

    Python3.5编程电子书
    • 发布时间:

    给大家带来的一篇关于Python3.5编程相关的电子书资源,介绍了关于入门、实践、Python编程方面的内容,本书是由中国工信出版集团出版,格式为PDF,资源大小9.85M,埃里克·马瑟斯编写,目前豆瓣、亚马逊、当当、京东等电子书综合评分为:7.2

  • Python编程:从入门到实践 PDF 下载
  • 下载地址:https://pan.baidu.com/s/1PHTNFkURXdiiEArr2LP-cg
  • 分享码:cbs3
  • Python编程:从入门到实践

    Python编程:从入门到实践电子书封面

    疑惑解答

    问:为何选择这本书学习Python?

    答:效率高,代码更容易阅读、调试和扩展,用途广泛:游戏、WEB应用、商业问题、学术研究……,有码农之家的Python专区作为学习资料的下载基地,和知识坚强的后盾。

    :我完全没有编程经验,能读懂这本书吗?

    :没问题,本书从基础编程知识开始,循序渐进,层层深入,适合零基础读者阅读。自出版以来,本书帮助众多新手和有其他语言编程经验的程序员成为拥有扎实基础的Python程序员,收货无数好评。

    :读完本书会后,我能达到怎样的水平?

    :本书旨在让你尽快的学会Python。通过阅读本书你将迅速掌握编程概念,打下件数的基础,并养成良好的习惯,读完本书,你就可以开始学习Python高级技术,能够轻松地掌握其他编程语言。

    读者评价

    这本书还算有意思,让我大致了解了python编程到底是什么意思,假装在编辑器上写上几行代码,甚至超越了hello,world的水平。连智商只有50的老夫都学会了list、字典啊、各种条件判断呀、奇怪的函数呀等等。真是一本step by step的好教材。

    从编程小白的角度看,入门极佳。手把手教的感觉,却绝不啰嗦。什么叫入门书?一本书读下来,行文上不卡壳,逻辑上不跳跃,读者如爬楼梯,一步一步即可登楼。

    架构非常漂亮,基本一本书描绘了Python的一幅“景象”,它不是教科书式的分章节阐释语法,仅在前半部分讲到一些基本的表达(如果已经有面向对象编程基础的,就只剩下语法问题),后面的三个操作案例分别是游戏开发、简单的数据可视化和web应用,没有太复杂的概念延伸,入门可,但基本不会重读

    我最开始看的是《深入浅出 python 》,基于《深入浅出统计学》和《深入浅出数据分析》的良好印象。但《深入浅出 python 》一点都不浅!!它就是任务型的,有时候一个问题我可能需要自己在网上研究两天才能解决,满满的挫败感啊!而《Python编程:从入门到实践》在学习中几乎不会遇到什么疑惑,对小白非常友好!!

    很显然这是我读过的海量 Python 入门书籍中如白马驹过裂隙般平淡无奇的一本,必须要说的是这本书并不是特别系统和全面,里面的所有内容其实都是围绕着最后的三个案例而设计的。不过,这可能是入门书籍中最简单清晰的一本,如果学习者连这本都不下去的话,那基本也没有一本更简单的书带你入门了。当然,随着阅读的进行,一个隐晦的公理也昭然若揭。如果不自己操作代码,看再多的入门教程也是没有用的。起码你得明确的知道,写一门语言是该用来干什么的。比如,我就知道。我学 Python 纯粹是为了轻松一点毕业。我研究生的课余生活实在是过于花团锦簇,以至于如何写出一个看起来不那么寒碜的论文就成了非常实际且迫切需要解决的问题。Python 拯救了我,我没有花费特别大的精力就用 OpenCV 实现了一个看起来还挺有深度(但其实一点不复杂)的项目,当时我觉得 C 语言和 Python 的差别就像一匹马和一辆无照电瓶车的距离:电瓶车更快,但很显然骑马更具有操纵感。可惜的是在这之后我就很久没有碰过 Python 了,以至于再拿起 Python 的时候要找本书重新过一遍语法。当然对我而言,即使不碰编程语言也没有太大所谓,毕竟已经不需要再拿它来谋一份营生,但闲的时候还总是放不下,毕竟心里还有个 Kaggle 的念想。不试试总像是缺点什么一样。我在想,看这本书的人应该是学习 Python 的青年中,对自己智力最没有信心的那一波了。当然这不重要。重要的是,你有很多不同的理由——甚至是极为功利的理由——认识一个东西或者一件事(或者一个人),但要热爱它,并能与之共同前行,则需要一个很纯粹的,也许是很模糊但必须非常直接可感的理由。当我们真正找到这样一个理由的时候,也许才是步入某座殿堂大门的开始。

    本人艺术生,现在转程序员中。完全零基础小白。在各大论坛混迹了很久,都推荐从python入手,于是就开始了求学之路。一开始都说笨方法那本书很好,我买了看,发现书里的是2.7的内容,不过也看的下去,可是一知半解很迷糊,毕竟纯小白。后来又无意间搜到了这本书,跟着学了几页,太棒了!知识点解释的很到位,我这种白痴都看得懂,每一步都有解释,一步一步循循善诱,真的想给写这本书的人一个大大的拥抱。有点基础的可能会觉得这本书很啰嗦,但是对我这种毫无基础的人来说,简直神书。学到pygame那一章节制作外星人游戏,开始犯迷糊,不过解释都看得懂,只不过让我自己写是做不到的。后来学到了django,就完全看不懂了,我觉得是我前端经验不够。所以现在打算去学前端。然后再回过头学django,然后再从另一本笨方法慢慢看起。

    2016年出版的书,豆瓣评分高达8.6,基于 Python3.5 同时也兼顾 Python2.7 ,作者推荐的编辑器 Geany 我没用过,不好做评论,不过个人推荐使用 Pycharm 或者 Sublime。书中涵盖的内容是比较精简的,没有艰深晦涩的概念,最重要的是每个小结都附带有”动手试一试”环节,学编程最佳的方式就是多动手、多动脑。很多初学者看完书之后不知道下一步怎么办,快速提高编程能力的最佳途径就是做项目,而这本书巧妙地安排了三个实践项目,一个游戏、一个Web和一个数据可视化项目,如果你跟着教程把项目做下来,相信你的编程功底绝对会上升一个层次。作者还专门安排了一个章节是讲单元测试,会写单元测试是初级程序员进阶到高级程序员的必备技能。此外,附录中还提到了git,作为延伸阅读,最后还告诉你遇到问题该如何去解决。推荐理由:第一:书的标题中肯,不偏不倚,正如书的内容一样,从入门到实践,不像那种标题党动不动就是《XXX从入门到精通》。第二:全书都在灌输一个理念:编写可读、清晰的代码。很多初学者在刚开始没有形成良好的编程习惯,代码非常个性化,以至于除了机器能读懂代码,没人读得懂,这给后期的维护带来巨大隐患。第三:本书的翻译质量很高,向作者和译者致敬

    内容精选

    Python自带了一个在终端窗口中运行的解释器,让你无需保存并运行整个程序就能尝试运行Python代码片段。本书将以如下方式列出代码片段:

    >>> print("Hello Python interpreter!")
    Hello Python interpreter!

    将一条消息存储到变量中,将其打印出来;再将变量的值修改为一条新消息,并将其打印出来。

    message = 'Hello World'
    print(message)
    
    message = 'Hello Python'
    print(message)

    如果你可以邀请任何人一起共进晚餐(无论是在世的还是故去的),你会邀请哪些人?请创建一个列表,其中包含至少3个你想邀请的人;然后,使用这个列表打印消息,邀请这些人来与你共进晚餐。

    names = ['Cannon', 'Leg', 'God']
    
    print(names[0] + ', invite you to have a dinner')
    print(names[1] + ', invite you to have a dinner')
    print(names[2] + ', invite you to have a dinner')

    内容简介

    本书是一本针对所有层次的Python读者而作的Python入门书。全书分两部分:首部分介绍用Python 编程所必须了解的基本概念,包括matplotlib、NumPy和Pygal等强大的Python库和工具介绍,以及列表、字典、if语句、类、文件与异常、代码测试等内容;第二部分将理论付诸实践,讲解如何开发三个项目,包括简单的Python 2D游戏开发,如何利用数据生成交互式的信息图,以及创建和定制简单的Web应用,并帮读者解决常见编程问题和困惑。

    编辑推荐

    上到有编程基础的程序员,下到10岁少年,想入门Python并达到可以开发实际项目的水平,本书是读者优选!

    本书是一本全面的从入门到实践的Python编程教程,带领读者快速掌握编程基础知识、编写出能解决实际问题的代码并开发复杂项目。

    书中内容分为基础篇和实战篇两部分。基础篇介绍基本的编程概念,如列表、字典、类和循环,并指导读者编写整洁且易于理解的代码。另外还介绍了如何让程序能够与用户交互,以及如何在代码运行前进行测试。实战篇介绍如何利用新学到的知识开发功能丰富的项目:2D游戏《外星人入侵》,数据可视化实战,Web应用程序。

    媒体推荐

    亚马逊读者评论

    “我读过很多本为Python初学者所写的入门书,到目前为止,这是我特别喜爱的一本。这本Python编程书内容全面,讲解详细,编排合理,真是太棒了!”

    “这本书用平实的语言向初学者解释各种概念,没有过早引入隐晦难懂的技术术语。我至少有8本介绍Python的书,但大多数没读多少页就读不下去了;而阅读这本书的时候,我能更轻松地理解其中的概念并且一直坚持读完。” 

    作者简介

    作者:[美]埃里克·马瑟斯(Eric Matthes) 译者:袁国忠

    Eric Matthes

    高中科学和数学老师,现居住在阿拉斯加,在当地讲授Python入门课程。他从5岁开始就一直在编写程序。

    袁国忠

    自由译者;2000年起专事翻译,主译图书,偶译新闻稿、软文;出版译著40余部,其中包括《C++ Prime Plus中文版》《CCNA学习指南》《CCNP ROUTE学习指南》《面向模式的软件架构:模式系统》《Android应用UI设计模式》《风投的选择:谁是下一个十亿美元级公司》等,总计700余万字;专事翻译前,从事过三年化工产品分析和开发,做过两年杂志和图书编辑。

    目录

    • 第一部分 基础知识
    • 第1章 起步 2
    • 1.1 搭建编程环境 2
    • 1.1.1 Python 2和Python 3 2
    • 1.1.2 运行Python代码片段 3
    • 1.1.3 Hello World程序 3
    • 1.2 在不同操作系统中搭建Python编程环境 3
    • 1.2.1 在Linux系统中搭建Python编程环境 3
    • 1.2.2 在OS X系统中搭建Python编程环境 6
    • 1.2.3 在Windows系统中搭建Python编程环境 8
    • 1.3 解决安装问题 12
    • 1.4 从终端运行Python程序 13
    • 1.4.1 在Linux和OS X系统中从终端运行Python程序 13
    • 1.4.2 在Windows系统中从终端运行Python程序 13
    • 1.5 小结 14
    • 第2章 变量和简单数据类型 15
    • 2.1 运行hello_world.py时发生的情况 15
    • 2.2 变量 16
    • 2.2.1 变量的命名和使用 16
    • 2.2.2 使用变量时避免命名错误 17
    • 2.3 字符串 18
    • 2.3.1 使用方法修改字符串的大小写 19
    • 2.3.2 合并(拼接)字符串 19
    • 2.3.3 使用制表符或换行符来添加空白 20
    • 2.3.4 删除空白 21
    • 2.3.5 使用字符串时避免语法错误 22
    • 2.3.6 Python 2中的print语句 23
    • 2.4 数字 24
    • 2.4.1 整数 24
    • 2.4.2 浮点数 25
    • 2.4.3 使用函数str()避免类型错误 25
    • 2.4.4 Python 2中的整数 26
    • 2.5 注释 27
    • 2.5.1 如何编写注释 27
    • 2.5.2 该编写什么样的注释 28
    • 2.6 Python之禅 28
    • 2.7 小结 30
    • 第3章 列表简介 31
    • 3.1 列表是什么 31
    • 3.1.1 访问列表元素 32
    • 3.1.2 索引从0而不是1开始 32
    • 3.1.3 使用列表中的各个值 33
    • 3.2 修改、添加和删除元素 33
    • 3.2.1 修改列表元素 34
    • 3.2.2 在列表中添加元素 34
    • 3.2.3 从列表中删除元素 35
    • 3.3 组织列表 39
    • 3.3.1 使用方法sort()对列表进行永久性排序 39
    • 3.3.2 使用函数sorted()对列表进行临时排序 40
    • 3.3.3 倒着打印列表 41
    • 3.3.4 确定列表的长度 41
    • 3.4 使用列表时避免索引错误 42
    • 3.5 小结 43
    • 第4章 操作列表 44
    • 4.1 遍历整个列表 44
    • 4.1.1 深入地研究循环 45
    • 4.1.2 在for循环中执行更多的操作 46
    • 4.1.3 在for循环结束后执行一些操作 47
    • 4.2 避免缩进错误 47
    • 4.2.1 忘记缩进 48
    • 4.2.2 忘记缩进额外的代码行 48
    • 4.2.3 不必要的缩进 49
    • 4.2.4 循环后不必要的缩进 49
    • 4.2.5 遗漏了冒号 50
    • 4.3 创建数值列表 51
    • 4.3.1 使用函数range() 51
    • 4.3.2 使用range()创建数字列表 51
    • 4.3.3 对数字列表执行简单的统计计算 53
    • 4.3.4 列表解析 53
    • 4.4 使用列表的一部分 54
    • 4.4.1 切片 54
    • 4.4.2 遍历切片 56
    • 4.4.3 复制列表 56
    • 4.5 元组 59
    • 4.5.1 定义元组 59
    • 4.5.2 遍历元组中的所有值 59
    • 4.5.3 修改元组变量 60
    • 4.6 设置代码格式 61
    • 4.6.1 格式设置指南 61
    • 4.6.2 缩进 61
    • 4.6.3 行长 61
    • 4.6.4 空行 62
    • 4.6.5 其他格式设置指南 62
    • 4.7 小结 63
    • 第5章 if语句 64
    • 5.1 一个简单示例 64
    • 5.2 条件测试 65
    • 5.3 if语句 70
    • 5.4 使用if语句处理列表 76
    • 5.5 设置if语句的格式 80
    • 5.6 小结 80
    • 第6章 字典 81
    • 6.1 一个简单的字典 81
    • 6.2 使用字典 82
    • 6.3 遍历字典 87
    • 6.4 嵌套 93
    • 6.5 小结 99
    • 第7章 用户输入和while循环 100
    • 7.1 函数input()的工作原理 100
    • 7.2 while循环简介 104
    • 7.3 使用while循环来处理列表和字典 110
    • 7.4 小结 113
    • 第8章 函数 114
    • 8.1 定义函数 114
    • 8.2 传递实参 116
    • 8.3 返回值 121
    • 8.4 传递列表 126
    • 8.5 传递任意数量的实参 130
    • 8.6 将函数存储在模块中 133
    • 8.7 函数编写指南 136
    • 8.8 小结 137
    • 第9章 类 138
    • 9.1 创建和使用类 138
    • 9.2 使用类和实例 142
    • 9.3 继承 147
    • 9.4 导入类 153
    • 9.5 Python标准库 159
    • 9.6 类编码风格 161
    • 9.7 小结 161
    • 第10章 文件和异常 162
    • 10.1 从文件中读取数据 162
    • 10.2 写入文件 169
    • 10.3 异常 172
    • 10.4 存储数据 180
    • 10.5 小结 186
    • 第11章 测试代码 187
    • 11.1 测试函数 187
    • 11.2 测试类 193
    • 11.3 小结 199
    • 第二部分 项  目
    • 项目1 外星人入侵 202
    • 第12章 武装飞船 203
    • 12.1 规划项目 203
    • 12.2 安装Pygame 204
    • 12.3 开始游戏项目 207
    • 12.4 添加飞船图像 211
    • 12.5 重构:模块game_functions 214
    • 12.6 驾驶飞船 216
    • 12.7 简单回顾 223
    • 12.8 射击 224
    • 12.9 小结 231
    • 第13章 外星人 232
    • 13.1 回顾项目 232
    • 13.2 创建第一个外星人 233
    • 13.3 创建一群外星人 236
    • 13.4 让外星人群移动 242
    • 13.5 射杀外星人 246
    • 13.6 结束游戏 250
    • 13.7 确定应运行游戏的哪些部分 255
    • 13.8 小结 256
    • 第14章 记分 257
    • 14.1 添加Play按钮 257
    • 14.2 提高等级 264
    • 14.3 记分 267
    • 14.4 小结 283
    • 项目2 数据可视化 284
    • 第15章 生成数据 285
    • 15.1 安装matplotlib 285
    • 15.2 绘制简单的折线图 287
    • 15.3 随机漫步 295
    • 15.4 使用Pygal模拟掷骰子 303
    • 15.5 小结 311
    • 第16章 下载数据 312
    • 16.1 CSV文件格式 312
    • 16.2 制作交易收盘价走势图:JSON格式 324
    • 16.3 小结 337
    • 第17章 使用API 338
    • 17.1 使用Web API 338
    • 17.2 使用Pygal可视化仓库 344
    • 17.3 Hacker News API 350
    • 17.4 小结 353
    • 项目3 Web应用程序 354
    • 第18章 Django入门 355
    • 18.1 建立项目 355
    • 18.2 创建应用程序 360
    • 18.3 创建网页:学习笔记主页 369
    • 18.4 创建其他网页 373
    • 18.5 小结 381
    • 第19章 用户账户 382
    • 19.1 让用户能够输入数据 382
    • 19.2 创建用户账户 392
    • 19.3 让用户拥有自己的数据 400
    • 19.4 小结 408
    • 第20章 设置应用程序的样式并对其进行部署 409
    • 20.1 设置项目“学习笔记”的样式 409
    • 20.2 部署“学习笔记” 419
    • 20.3 小结 435
    • 附录A 安装Python 436
    • 附录B 文本编辑器 441
    • 附录C 寻求帮助 447
    • 附录D 使用Git进行版本控制 451
    • 后记 460

    读书笔记

    详解Python函数any()和all()的用法和区别

    Python函数any()和all()的用法及区别介绍

    引子

    平常的文本处理工作中,我经常会遇到这么一种情况:用python判断一个string是否包含一个list里的元素。

    这时候使用python的内置函数any()会非常的简洁:

    fruits = ['apple', 'orange', 'peach']
    str = "I want some apples"
    if any(element in str for element in fruits):
      print "string contains some fruits."

    any()

    其实any函数非常简单:判断一个tuple或者list是否全为空,0,False。如果全为空,0,False,则返回False;如果不全为空,则返回True。

    all()

    all函数正好和any相反:判断一个tuple或者list是否全为不为空,0,False。如果全不为空,则返回True;否则返回False。

    这里需要注意的是,空tuple和空list的返回值是True

    python中内建函数all()和any()的区别

    all(x) 是针对x对象的元素而言,如果all(x)参数x对象的所有元素不为0、”、False或者x为空对象,则返回True,否则返回False
    如:

    In [25]: all(['a', 'b', 'c', 'd']) #列表list,元素都不为空或0
    Out[25]: True
    In [26]: all(['a', 'b', '', 'd']) #列表list,存在一个为空的元素
    Out[26]: False
    In [27]: all([0, 1,2, 3]) #列表list,存在一个为0的元素
    Out[27]: False
    In [28]: all(('a', 'b', 'c', 'd')) #元组tuple,元素都不为空或0
    Out[28]: True
    In [29]: all(('a', 'b', '', 'd')) #元组tuple,存在一个为空的元素
    Out[29]: False
    In [30]: all((0, 1,2, 3)) #元组tuple,存在一个为0的元素
    Out[30]: False
    In [31]: all([]) # 空列表
    Out[31]: True
    In [32]: all(()) # 空元组
    Out[32]: True

    any(x)是判断x对象是否为空对象,如果都为空、0、false,则返回false,如果不都为空、0、false,则返回true

    In [33]: any(['a', 'b', 'c', 'd']) #列表list,元素都不为空或0
    Out[33]: True
    In [34]: any(['a', 'b', '', 'd']) #列表list,存在一个为空的元素
    Out[34]: True
    In [35]: any((0,1)) #元组tuple,存在一个为空的元素
    Out[35]: True
    In [36]: any((0,'')) #元组tuple,元素都为空
    Out[36]: False
    In [37]: any(()) # 空元组
    Out[37]: False
    In [38]: any([]) # 空列表
    Out[38]: False

    python中any()和all()如何使用

    any(iterables)和all(iterables)对于检查两个对象相等时非常实用,但是要注意,any和all是python内置函数,同时numpy也有自己实现的any和all,功能与python内置的一样,只不过把numpy.ndarray类型加进去了。因为python内置的对高于1维的ndarray没法理解,所以numpy基于的计算最好用numpy自己实现的any和all。

    本质上讲,any()实现了或(OR)运算,而all()实现了与(AND)运算。

    对于any(iterables),如果可迭代对象iterables(至于什么是可迭代对象,可关注我的下篇文章)中任意存在每一个元素为True则返回True。特例:若可迭代对象为空,比如空列表[],则返回False。
    官方文档如是说:

    Return True if any element of the iterable is true. If the iterable is empty, return False.

    伪代码(其实是可以运行的python代码,但内置的any是由C写的)实现方式:

    def any(iterable):
        for element in iterable:
            if element:
                return True
        return False

    对于all(iterables),如果可迭代对象iterables中所有元素都为True则返回True。特例:若可迭代对象为空,比如空列表[],则返回True。

    官方文档如是说:

    Return True if all elements of the iterable are true (or if the iterable is empty).

    伪代码(其实是可以运行的python代码,但内置的all是由C写的)实现方式:

    def all(iterable):
        for element in iterable:
            if not element:
                return False
        return True

    python的模块由两类语言开发,一类为纯python,一类为编译型语言,比如C/C++/Fortran。绝大多数标准库由纯python开发,这是由于python语言具有简洁性及短的开发周期。这些模块的源码很容易获得,在ipython下可用module??打印到屏幕上查看,或者写一个脚本保存起来,比如下面这样:

    import os
    import inspect as inspect
    import pandas as pd
    
    path = r"D:\python3_dev\package_down"
    os.chdir(path)
    
    series = inspect.getsource(pd.Series)
    with open("pd_series_code.py", "w") as f:
        f.write(series)

    当然,也可以到python安装包下查找,但是效率很低。

    python inspect.getsource(object)只能查看用python写的module, class, method, function, traceback, frame, or code object。可以看看getsource的文档字符串,了解其基本功能。

    >>>inspect.getsource.__doc__
    'Return the text of the source code for an object.\n\n    
    The argument may be a module, class, method, function, traceback, frame,\n    
    or code object.  The source code is returned as a single string.  An\n    
    OSError is raised if the source code cannot be retrieved.'

    对于有些模块,通常是关乎运行性能的,一般都由编译型语言开发,比如os模块和for循环N多层的线性代数等模块。所以无法通过getsource方法获得源码,通常会抛出一个TypeError异常。要查看这些模块的源码,需要到GitHub上的python/cpython目录下找,比如在Objects目录下可找到listobject.c,这是list模块的C代码。

    那么怎么知道一个模块是内置的呢?可用type(object)或object.__module__。比如

    >>>type(all)
    builtin_function_or_method
    >>>all.__module__
    'builtins'

    一个2X3 ndarray 的例子。用numpy自己实现的all很容易判断两个array是否相等,但python内置的却抛出了异常。

    >>>x = np.ones((2,3))
    >>>x1 = np.ones((2,3))
    >>>np.all(x==x1)
    True
    >>>xe = x==x1
    >>>xe.all()
    True
    >>>all(xe)#这里调用了python内置模块all()
    ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

    但是,还有更pythonic的写法,因为numpy有一个模块array_equal,可以直接判断两个array是否完全相等或某个轴相等,其实他也是用np.all实现的。

    >>>np.array_equal(x, x1)
    True

    其实也不要惊讶,这只是python的常规操作。轮子已经被匠人造好,拿来用就OK了!如果你觉得自己可以造出更金光闪闪的轮子,那就抡起你的斧头;如果觉得已经够完美,那就拿来主义,不要再造了。

     

    python线程锁相关技巧和操作示例

    Python线程下使用锁的技巧分享

    使用诸如Lock、RLock、Semphore之类的锁原语时,必须多加小心,锁的错误使用很容易导致死锁或相互竞争。依赖锁的代码应该保证当出现异常时可以正常的释放锁。

    典型代码如下:

    try:
      lock.acquire()
      #关键部分
      ...
    finally:
      lock.release()

    另外,所有种类的锁还支持上下文管理协议(写起来更简洁):

    with语句自动获取锁,并且在控制流离开上下文时自动释放锁。

    with lock:
      #关键部分
      ...

    此外,编写代码时一般应该避免同时获取多个锁,例如下面就应该尽量避免:

    这通知很统一导致应用程序神秘死锁,尽管与集中策略可以避免出现这种情况(如分层锁定),但是最好在编写代码时避免这种嵌套锁。

    with lock_A:
      #关键部分
      ...
      with lock_B:
        #B的关键部分
        ...

    尽管在Python中可以使用各种锁和同步原语的组合编写非常传统的多线程程序,但有一种首推的编程方式要优于其他所有编程方式:即将多线程程序组织为多个独立任务的集合,这些任务之间通过消息队列进行通信,例如下面要讲的queue模块。

    Python多线程编程之多线程加锁操作示例

    Python语言本身是支持多线程的,不像PHP语言。

    下面的例子是多个线程做同一批任务,任务总是有task_num个,每次线程做一个任务(print),做完后继续取任务,直到所有任务完成为止。

    # -*- coding:utf-8 -*-
    #! python2
    import threading
    start_task = 0
    task_num = 10000
    mu = threading.Lock()  ###通过工厂方法获取一个新的锁对象
    class MyThread(threading.Thread):  ###类MyThread继承基类threading.Thread
      def run(self): ##线程启动的入口函数,子类需重写
        global start_task
        global mu
        global start_task
        while start_task < task_num:  ##如果任务没有完成,则继续
          if mu.acquire():  ##加锁
            if start_task < task_num:
              print start_task
              start_task = start_task + 1
            mu.release()  ##释放锁
    def test():
      thread_all = []
      for i in range(6): ##for循环创建6个线程
        t = MyThread() ##创建线程
        thread_all.append(t)
        t.start()  ###启动线程
      for i in range(6):
        thread_all[i].join()  ##等待线程结束
    if __name__ == "__main__":
      test()
    
    

    运行上述代码,则输出1~9999

    测试加锁与不加锁效果:将任务数设置为1千万或者以上,在多核机器上将print输出分别保存,就能说明问题。

    python线程中同步锁详解

    在使用多线程的应用下,如何保证线程安全,以及线程之间的同步,或者访问共享变量等问题是十分棘手的问题,也是使用多线程下面临的问题,如果处理不好,会带来较严重的后果,使用python多线程中提供Lock Rlock Semaphore Event Condition 用来保证线程之间的同步,后者保证访问共享变量的互斥问题

    Lock & RLock:互斥锁 用来保证多线程访问共享变量的问题
    Semaphore对象:Lock互斥锁的加强版,可以被多个线程同时拥有,而Lock只能被某一个线程同时拥有。
    Event对象: 它是线程间通信的方式,相当于信号,一个线程可以给另外一个线程发送信号后让其执行操作。
    Condition对象:其可以在某些事件触发或者达到特定的条件后才处理数据

    1、Lock(互斥锁)

    请求锁定 — 进入锁定池等待 — 获取锁 — 已锁定 — 释放锁

    Lock(指令锁)是可用的最低级的同步指令。Lock处于锁定状态时,不被特定的线程拥有。Lock包含两种状态——锁定和非锁定,以及两个基本的方法。

    可以认为Lock有一个锁定池,当线程请求锁定时,将线程至于池中,直到获得锁定后出池。池中的线程处于状态图中的同步阻塞状态。

    构造方法:
    Lock()

    实例方法:
    acquire([timeout]): 使线程进入同步阻塞状态,尝试获得锁定。
    release(): 释放锁。使用前线程必须已获得锁定,否则将抛出异常。

    if mutex.acquire():
     counter += 1
     print "I am %s, set counter:%s" % (self.name, counter)
      mutex.release()

    2、RLock(可重入锁)

    RLock(可重入锁)是一个可以被同一个线程请求多次的同步指令。RLock使用了“拥有的线程”和“递归等级”的概念,处于锁定状态时,RLock被某个线程拥有。拥有RLock的线程可以再次调用acquire(),释放锁时需要调用release()相同次数。

    可以认为RLock包含一个锁定池和一个初始值为0的计数器,每次成功调用 acquire()/release(),计数器将+1/-1,为0时锁处于未锁定状态。

    构造方法:
    RLock()

    实例方法:
    acquire([timeout])/release(): 跟Lock差不多。

    3、Semaphore(共享对象访问)

    咱们再聊聊Semaphore ,说实话Semaphore是我最晚使用的同步锁,以前类似的实现,是我用Rlock实现的,相对来说有些绕,毕竟Rlock 是需要成对的锁定和开锁的》。。。

    Semaphore管理一个内置的计数器,
    每当调用acquire()时内置计数器-1;
    调用release() 时内置计数器+1;
    计数器不能小于0;当计数器为0时,acquire()将阻塞线程直到其他线程调用release()。

    直接上代码,我们把semaphore控制为3,也就是说,同时有3个线程可以用这个锁,剩下的线程也之只能是阻塞等待了…

    #coding:utf-8
    #blog xiaorui.cc
    import time
    import threading
    
    semaphore = threading.Semaphore(3)
    
    def func():
     if semaphore.acquire():
      for i in range(3):
       time.sleep(1)
       print (threading.currentThread().getName() + '获取锁')
      semaphore.release()
      print (threading.currentThread().getName() + ' 释放锁')
    
    
    for i in range(5):
     t1 = threading.Thread(target=func)
     t1.start()

    4、Event(线程间通信)

    Event内部包含了一个标志位,初始的时候为false。
    可以使用使用set()来将其设置为true;
    或者使用clear()将其从新设置为false;
    可以使用is_set()来检查标志位的状态;

    另一个最重要的函数就是wait(timeout=None),用来阻塞当前线程,直到event的内部标志位被设置为true或者timeout超时。如果内部标志位为true则wait()函数理解返回。

    import threading
    import time
    
    class MyThread(threading.Thread):
     def __init__(self, signal):
      threading.Thread.__init__(self)
      self.singal = signal
    
     def run(self):
      print "I am %s,I will sleep ..."%self.name
      self.singal.wait()
      print "I am %s, I awake..." %self.name
    
    if __name__ == "__main__":
     singal = threading.Event()
     for t in range(0, 3):
      thread = MyThread(singal)
      thread.start()
    
     print "main thread sleep 3 seconds... "
     time.sleep(3)
    
     singal.set()
    
    

    5、Condition(线程同步)

    可以把Condition理解为一把高级的琐,它提供了比Lock, RLock更高级的功能,允许我们能够控制复杂的线程同步问题。threadiong.Condition在内部维护一个琐对象(默认是RLock),可以在创建Condigtion对象的时候把琐对象作为参数传入。Condition也提供了acquire, release方法,其含义与琐的acquire, release方法一致,其实它只是简单的调用内部琐对象的对应的方法而已。Condition还提供了如下方法(特别要注意:这些方法只有在占用琐(acquire)之后才能调用,否则将会报RuntimeError异常。):

    Condition.wait([timeout]):

    wait方法释放内部所占用的琐,同时线程被挂起,直至接收到通知被唤醒或超时(如果提供了timeout参数的话)。当线程被唤醒并重新占有琐的时候,程序才会继续执行下去。

    Condition.notify():

    唤醒一个挂起的线程(如果存在挂起的线程)。注意:notify()方法不会释放所占用的琐。

    Condition.notify_all()
    Condition.notifyAll()

    唤醒所有挂起的线程(如果存在挂起的线程)。注意:这些方法不会释放所占用的琐。

    对于Condition有个例子,大家可以观摩下。

    from threading import Thread, Condition
    import time
    import random
    
    queue = []
    MAX_NUM = 10
    condition = Condition()
    
    class ProducerThread(Thread):
     def run(self):
      nums = range(5)
      global queue
      while True:
       condition.acquire()
       if len(queue) == MAX_NUM:
        print "Queue full, producer is waiting"
        condition.wait()
        print "Space in queue, Consumer notified the producer"
       num = random.choice(nums)
       queue.append(num)
       print "Produced", num
       condition.notify()
       condition.release()
       time.sleep(random.random())
    
    
    class ConsumerThread(Thread):
     def run(self):
      global queue
      while True:
       condition.acquire()
       if not queue:
        print "Nothing in queue, consumer is waiting"
        condition.wait()
        print "Producer added something to queue and notified the consumer"
       num = queue.pop(0)
       print "Consumed", num
       condition.notify()
       condition.release()
       time.sleep(random.random())
    
    
    ProducerThread().start()
    ConsumerThread().start()
    

    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实现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)

     

    《Python编程:从入门到实践》第四章:操作列表

    4-1 比萨 

    想出至少是三种你喜欢的比萨,将其名称存储在一个列表中,再使用for循环将每种比萨的名称都打印出来。

    修改这个for循环,使其打印包含比萨名称的矩阵,而不仅仅是比萨的名称。对于每种比萨,都显示一行输出,如“I like pepperoni pizza”。

    在程序末尾添加一行代码,它不在for循环中,指出你有多喜欢比萨。输出应包含针对每种比萨的消息,还有一个总结性矩阵,如“I really love pizza!”

    pizza = ['banana','durian','apple']
    for x in pizza:
    	print("I like %s pizza"%x)
    print("I really love Pizza")

    结果:

    I like banana pizza
    I like durian pizza
    I like apple pizza
    I really love Pizza

    4-2 动物

    想出至少三种有共同特征的动物,将这些动物的名称存储在一个列表中,再使用for 循环将每种动物的名称都打印出来。

    修改这个程序,使其针对每种动物都打印一个句子,如“A dog would make a great pet”。

    在程序末尾添加一行代码,指出这些动物的共同之处,如打印诸如“Any of these animals would make a great pet!”这样的句子。

    animals = ['dog','cat','mouse']
    for x in animals:
    	print("A %s would make a great pet"%x)
    print("Any of these animals would make a great pets")

    结果:

    A dog would make a great pet
    A cat would make a great pet
    A mouse would make a great pet
    Any of these animals would make a great pets

    4-3 数到20

    使用一个for 循环打印数字1~20(含)。

    numbers = list(range(1,21))
    for num  in numbers:
    	print(num)

    结果:

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

    4-4 一百万

    创建一个列表,其中包含数字1~1 000 000,再使用一个for 循环将这些数字打印出来(如果输出的时间太长,按Ctrl + C停止输出,或关闭输出窗口)。

    numbers = list(range(1,1000000))
    for num  in numbers:
    	print(num)

    结果:

    4-5 计算1~1 000 000的总和

    创建一个列表,其中包含数字1~1 000 000,再使用min() 和max() 核实该列表确实是从1开始,到1 000 000结束的。另外,对这个列表 调用函数sum() ,看看Python将一百万个数字相加需要多长时间。

    numbers = list(range(1,1000001))
    print(min(numbers))
    print(max(numbers))
    print(sum(numbers))

    结果:

    1
    1000000
    500000500000
    

    4-6 奇数

    通过给函数range() 指定第三个参数来创建一个列表,其中包含1~20的奇数;再使用一个for 循环将这些数字都打印出来.

    numbers = list(range(1,21,2))
    for num in numbers:
    	print(num)

    结果:

    1
    3
    5
    7
    9
    11
    13
    15
    17
    19

    4-7 3的倍数

    创建一个列表,其中包含3~30内能被3整除的数字;再使用一个for 循环将这个列表中的数字都打印出来。

    numbers = list(range(3,31,3))
    for num in numbers:
    	print(num)

    结果:

    3
    6
    9
    12
    15
    18
    21
    24
    27
    30

    4-8 立方

    将同一个数字乘三次称为立方。例如,在Python中,2的立方用2**3 表示。请创建一个列表,其中包含前10个整数(即1~10)的立方,再使用一个for 循 环将这些立方数都打印出来。

    numbers = list(range(1,10))
    result =[]
    for num in numbers:
    	result.append(num**3)
    for num in result:
    	print(num)

    结果:

    1
    8
    27
    64
    125
    216
    343
    512
    729

    4-9 立方解析

    使用列表解析生成一个列表,其中包含前10个整数的立方

    result = [num**3 for num in range(1,11)]
    for x  in result:
    	print(x)

    结果:

    1
    8
    27
    64
    125
    216
    343
    512
    729
    1000

    4-10 切片

    选择你在本章编写的一个程序,在末尾添加几行代码,以完成如下任务。

    打印消息“The first three items in the list are:”,再使用切片来打印列表的前三个元素。

    打印消息“Three items from the middle of the list are:”,再使用切片来打印列表中间的三个元素。

    打印消息“The last three items in the list are:”,再使用切片来打印列表末尾的三个元素。

    items1 = list(range(1,6))
    print("The first three items in the list are.")
    print(items1[0:3])
    print("The items from the middle of the list are ")
    print(items1[1:4])
    print("The last three items in the list are ")
    print(items1[-3:])

    结果:

    The first three items in the list are.
    [1, 2, 3]
    The items from the middle of the list are 
    [2, 3, 4]
    The last three items in the list are 
    [3, 4, 5]

    4-11 你的比萨和我的比萨

    在你为完成练习4-1而编写的程序中,创建比萨列表的副本,并将其存储到变量friend_pizzas 中,再完成如下任务。
    在原来的比萨列表中添加一种比萨。

    在列表friend_pizzas 中添加另一种比萨。

    核实你有两个不同的列表。为此,打印消息“My favorite pizzas are:”,再使用一个for 循环来打印第一个列表;打印消息“My friend's favorite pizzas are:”,再使用一 个for 循环 来打印第二个列表。核实新增的比萨被添加到了正确的列表中。

    pizza = ['banana','durian','apple']
    friend_pizzas = pizza[:]
    friend_pizzas.append('pumkin')
    print("My favorite pizzas are:")
    for pi in pizza:
    	print(pi)
    print("My friend's favorite pizzas are:")
    for pi in friend_pizzas:
    	print(pi)

    结果:

    My favorite pizzas are:
    banana
    durian
    apple
    My friend's favorite pizzas are:
    banana
    durian
    apple
    pumkin

    4-12 使用多个循环

    在本节中,为节省篇幅,程序foods.py的每个版本都没有使用for 循环来打印列表。请选择一个版本的foods.py,在其中编写两个for 循环,将各 个食品列表都打印出来

    my_foods = ['pizza','falafel','carrot cake']
    friend_food = my_foods[:]
    print("My favorite foods are:")
    for food in my_foods:
    	print(food)
    print("My friend's favorite foods are:")
    for food in friend_food:
    	print(food)

    结果:

    My favorite foods are:
    pizza
    falafel
    carrot cake
    My friend's favorite foods are:
    pizza
    falafel
    carrot cake

    4-13 自助餐 自助餐

    有一家自助式餐馆,只提供五种简单的食品。请想出五种简单的食品,并将其存储在一个元组中。

    使用一个for 循环将该餐馆提供的五种食品都打印出来。

    尝试修改其中的一个元素,核实Python确实会拒绝你这样做。

    foods = ('apple','banana','orange','pea','peach')
    for food in foods:
    	print(food)
    foods[0]='tea'

    结果:

    apple
    banana
    orange
    pea
    peach
    Traceback (most recent call last):
      File "G:\practice\pythonpratice\hellow.py", line 4, in <module>
        foods[0]='tea'
    TypeError: 'tuple' object does not support item assignment

    餐馆调整了菜单,替换了它提供的其中两种食品。请编写一个这样的代码块:给元组变量赋值,并使用一个for 循环将新元组的每个元素都打印出来。

    foods = ('apple','banana','orange','pea','peach')
    for food in foods:
    	print(food)
    print("Change")
    foods = ('tea','banana','pip','pea','peach')	
    for food in foods:
    	print(food)

    结果:

    apple
    banana
    orange
    pea
    peach
    Change
    tea
    banana
    pip
    pea
    peach

     

    《Python编程:从入门到实践》第五章:if语句

    5-1 条件测试

    编写一系列条件测试;将每个测试以及你对其结果的预测和实际结果都打印出来。你编写的代码应类似于下面这样:

    car = 'subaru'
    print("Is car == 'subaru'? I predict True.")
    print(car == 'subaru')  
    print("\nIs car == 'audi'? I predict False.")
    print(car == 'audi')

    详细研究实际结果,直到你明白了它为何为True 或False 。

    创建至少10个测试,且其中结果分别为True 和False 的测试都至少有5个。

    car ='subaru'
    print("Is car == 'subarur'? I predict True.")
    print(car == 'subaru')
    
    print("\nIs car == 'audi'? I predict False")
    print(car =='audi')

    结果:

    Is car == 'subarur'? I predict True.
    True
    
    Is car == 'audi'? I predict False
    False

    5-3 外星人颜色 外星人颜色#1

    假设在游戏中刚射杀了一个外星人,请创建一个名为alien_color 的变量,并将其设置为'green' 、'yellow' 或'red' 。

    编写一条if 语句,检查外星人是否是绿色的;如果是,就打印一条消息,指出玩家获得了5个点。

    编写这个程序的两个版本,在一个版本中上述测试通过了,而在另一个版本中未通过(未通过测试时没有输出)。

    #Q1
    print('Question one')
    alien_color ='green'
    if alien_color =='green':
    	print('you have won five point')
    #Q2
    print("\nQuestion two")
    alien_color = 'red'
    if alien_color == 'green':
    	print('you have won five point')

    结果:

    Question one
    you have won five point
    
    Question two

    5-4 外星人颜色 外星人颜色#2

    像练习5-3那样设置外星人的颜色,并编写一个if-else 结构。

    如果外星人是绿色的,就打印一条消息,指出玩家因射杀该外星人获得了5个点。

    如果外星人不是绿色的,就打印一条消息,指出玩家获得了10个点。

    编写这个程序的两个版本,在一个版本中执行if 代码块,而在另一个版本中执行else 代码块。

    print("Question one")
    alien_color = 'green'
    if alien_color == 'green':
    	print('you have won five point')
    else:
    	print('you ha wo ten point')
    print("\nQuestion two")
    alien_color = 'red'
    if alien_color == 'green':
    	print('you have won five point')
    else:
    	print('you have wo ten point')

    结果:

    Question one
    you have won five point
    
    Question two
    you have wo ten point

    5-5 外星人颜色 外星人颜色#3

    将练习5-4中的if-else 结构改为if-elif-else 结构。

    如果外星人是绿色的,就打印一条消息,指出玩家获得了5个点。

    如果外星人是黄色的,就打印一条消息,指出玩家获得了10个点。

    如果外星人是红色的,就打印一条消息,指出玩家获得了15个点。

    编写这个程序的三个版本,它们分别在外星人为绿色、黄色和红色时打印一条消息。

    print("Question one")
    alien_color = 'green'
    if alien_color == 'green':
    	print('you have won five point')
    elif alien_color == 'yellow':
    	print('you have wo ten point')
    elif alien_color=='red':
    	print('you have won fifteen point')
    print("\nQuestion two")
    alien_color = 'red'
    if alien_color == 'green':
    	print('you have won five point')
    elif alien_color == 'yellow':
    	print('you have wo ten point')
    elif alien_color=='red':
    	print('you have won fifteen point')
    print('\nQuestion three')
    alien_color = 'red'
    if alien_color == 'green':
    	print('you have won five point')
    elif alien_color == 'yellow':
    	print('you have wo ten point')
    elif alien_color=='red':
    	print('you have won fifteen point')

    结果:

    Question one
    you have won five point
    
    Question two
    you have won fifteen point
    
    Question three
    you have won fifteen point

    5-6 人生的不同阶段

    设置变量age 的值,再编写一个if-elif-else 结构,根据age 的值判断处于人生的哪个阶段。

    如果一个人的年龄小于2岁,就打印一条消息,指出他是婴儿。

    如果一个人的年龄为2(含)~4岁,就打印一条消息,指出他正蹒跚学步。

    如果一个人的年龄为4(含)~13岁,就打印一条消息,指出他是儿童。

    如果一个人的年龄为13(含)~20岁,就打印一条消息,指出他是青少年。

    如果一个人的年龄为20(含)~65岁,就打印一条消息,指出他是成年人。

    如果一个人的年龄超过65(含)岁,就打印一条消息,指出他是老年人。

    age = 30
    if age < 2:
    	print('It is a baby')
    elif age >= 2 and age < 4:
    	print('It learns walking')
    elif age >= 4 and age < 13:
    	print('he is a child')
    elif age >= 13 and age < 20:
    	print('he is a teenager')
    elif age >= 20 and age < 65:
    	print('he is an adult')
    else:
    	print('he is a the old')

    结果:

    he is an adult

    5-7 喜欢的水果

    创建一个列表,其中包含你喜欢的水果,再编写一系列独立的if 语句,检查列表中是否包含特定的水果。

    将该列表命名为favorite_fruits ,并在其中包含三种水果。

    编写5条if 语句,每条都检查某种水果是否包含在列表中,如果包含在列表中,就打印一条消息,如“You really like bananas!”。

    favorite_fruits = ['apple','banana','orange']
    if 'orange' in favorite_fruits:
    	print('you really like orange')
    if 'apple' in favorite_fruits:
    	print('you really like apple')
    if 'banana' in favorite_fruits:
    	print('you really like banana')
    if 'mango' in favorite_fruits:
    	print('you really like mango')
    if 'pipeapple' in favorite_fruits:
    	print('you really like pipeapple')

    结果:

    you really like orange
    you really like apple
    you really like banana

    5-8 以特殊方式跟管理员打招呼

    创建一个至少包含5个用户名的列表,且其中一个用户名为'admin' 。想象你要编写代码,在每位用户登录网站后都打印一条问 候消息。遍历用户名列表,并向每位用户打印一条问候消息。

    如果用户名为'admin' ,就打印一条特殊的问候消息,如“Hello admin, would you like to see a status report?”。

    否则,打印一条普通的问候消息,如“Hello Eric, thank you for logging in again”。

    users =['Nancy','Lucky','Tony','admin','Mary']
    for user  in users:
    	if user =='admin':
    		print("Hello admin,would you like to see a status report")
    	else:
    		print("Hello %s ,thank you for logging in again"%user)

    结果:

    Hello Nancy ,thank you for logging in again
    Hello Lucky ,thank you for logging in again
    Hello Tony ,thank you for logging in again
    Hello admin,would you like to see a status report
    Hello Mary ,thank you for logging in again

    5-9 处理没有用户的情形

    在为完成练习5-8编写的程序中,添加一条if 语句,检查用户名列表是否为空。

    如果为空,就打印消息“We need to find some users!”。

    删除列表中的所有用户名,确定将打印正确的消息。

    users =['Nancy','Lucky','Tony','admin','Mary']
    if users:
    	for user  in users:
    		if user == 'admin':
    			print("Hello admin,would you like to see a status report")
    		else:
    			print("Hello %s ,thank you for logging in again"%user)
    		# users.remove(user)
    else:
    	print('We need to find some users!')
    users=[]
    print("\n")
    if users:
    	for user  in users:
    		if user == 'admin':
    			print("Hello admin,would you like to see a status report")
    		else:
    			print("Hello %s ,thank you for logging in again"%user)
    		users.remove(user)
    else:
    	print('We need to find some users!')

    结果:

    Hello Nancy ,thank you for logging in again
    Hello Lucky ,thank you for logging in again
    Hello Tony ,thank you for logging in again
    Hello admin,would you like to see a status report
    Hello Mary ,thank you for logging in again
    
    
    We need to find some users!

    5-10 检查用户名

    按下面的说明编写一个程序,模拟网站确保每位用户的用户名都独一无二的方式。

    创建一个至少包含5个用户名的列表,并将其命名为current_users 。

    再创建一个包含5个用户名的列表,将其命名为new_users ,并确保其中有一两个用户名也包含在列表current_users 中。

    遍历列表new_users ,对于其中的每个用户名,都检查它是否已被使用。如果是这样,就打印一条消息,指出需要输入别的用户名;否则,打印一条消息,指 出这个用户名未被使用。 确保比较时不区分大消息;换句话说,如果用户名'John' 已被使用,应拒绝用户名'JOHN' 。

    current_users =['Nancy','Lucky','Tony','admin','Mary']
    new_user = ['Alice','Nancy']
    for user in new_user:
    	if user in current_users or user.upper() in current_users or user.lower() in current_users or user.title() in current_users:
    		print('had been used,please enter another user name')
    	else:
    		print('not been used')
    
    

    结果:

    not been used
    had been used,please enter another user name

    5-11 序数 序数

    序数表示位置,如1st和2nd。大多数序数都以th结尾,只有1、2和3例外。

    在一个列表中存储数字1~9。

    遍历这个列表。

    在循环中使用一个if-elif-else 结构,以打印每个数字对应的序数。输出内容应为1st 、2nd 、3rd 、4th 、5th 、6th 、7th 、8th 和9th ,但每个序 数都独占一行。

    numbers = list(range(1,10))
    for num in numbers :
    	if num == 1:
    		print('%dst'%num)
    	elif num == 2:
    		print('%dnd'%num)
    	elif num == 3:
    		print('%drd'%num)
    	else:
    		print('%dth'%num)

    结果:

    1st
    2nd
    3rd
    4th
    5th
    6th
    7th
    8th
    9th

     

    《Python编程:从入门到实践》课后习题及答案

    前言

    此书适合python初学者使用,代码基于py3,优点:简单易懂,缺点:知识过于基础,对一些基础的延伸并没有详解,点到辄止,所以只能作为类似【罗汉拳】的基础招式使用。

    并且此书的优点也仅仅在于基础知识的友好度max,其后的三个项目没有一个有用的,而且友好度也成直线下降,看完基础部分就可以直接看懂后面项目的人,我只能说你真特么是个天才,而且像pygame这种四五年都没更新的模块来做的外星人项目,你确定以后能用的上吗?

    第二章

    变量和简单数据类型

    # 2-1 简单消息: 将一条消息存储到变量中, 再将其打印出来。
    var = 'hello_world!'
    print(var)
    
    # 2-2 多条简单消息: 将一条消息存储到变量中,将其打印出来; 
    # 再将变量的值修改为一条新消息, 并将其打印出来。
    var = 'hello_world!'
    print(var)
    var = 'hello_python!'
    print(var)
    
    # 2-3 个性化消息: 将用户的姓名存到一个变量中, 并向该用户显示一条消息。 
    # 显示的消息应非常简单, 如“Hello Eric, would you like to learn some Python today?”。
    user_name = 'Eric'
    print('Hello '+ user_name +', would you like to learn some Python today?')
    
    # 2-4 调整名字的大小写: 将一个人名存储到一个变量中, 再以小写、 大写和首字母大写的方式显示这个人名。
    user_name = 'Eric'
    print(user_name.lower())
    print(user_name.upper())
    print(user_name.title())
    
    # 2-5 名言: 找一句你钦佩的名人说的名言, 将这个名人的姓名和他的名言打印出来。 输出应类似于下面这样(包括引号) :
    Albert Einstein once said, “A person who never made a mistake never tried anything new.”
    print('Albert Einsteinonce said,"A person who never made a mistake never tried anything new."')
    
    # 2-6 名言2: 重复练习2-5, 但将名人的姓名存储在变量famous_person 中, 再创建要显示的消息, 
    # 并将其存储在变量message 中, 然后打印这条消息。
    famous_person = 'Albert Einstein'
    message = 'A person who never made a mistake never tried anything new.'
    print(famous_person + 'once said,"' + message + '"')
    
    # 2-7 剔除人名中的空白: 存储一个人名, 并在其开头和末尾都包含一些空白字符。 
    # 务必至少使用字符组合"\t" 和"\n" 各一次。打印这个人名, 以显示其开头和末尾的空白。 
    # 然后, 分别使用剔除函数lstrip() 、 rstrip() 和strip() 对人名进行处理, 并将结果打印出来。
    user_name = ' Eric '
    print('\t'+ user_name.lstrip() + '\n\n')
    print('\t'+ user_name.rstrip() + '\n\n')
    print('\t'+ user_name.strip() + '\n\n')
    
    # 2-8 数字8: 编写4个表达式, 它们分别使用加法、 减法、 乘法和除法运算, 但结果都是数字8。 
    # 为使用print 语句来显示结果, 务必将这些表达式用括号括起来, 也就是说, 你应该编写4行类似于下面的代码:print(5 + 3)
    print(5 + 3)
    print(10 - 2)
    print(2 * 4)
    print(int(16 / 2))
    
    # 2-9 最喜欢的数字: 将你最喜欢的数字存储在一个变量中, 再使用这个变量创建一条消息, 
    # 指出你最喜欢的数字, 然后将这条消息打印出来。
    fav_nub = 0
    print('我最喜欢的数字是:' + str(fav_nub) +'!')
    
    # 2-10 添加注释: 选择你编写的两个程序, 在每个程序中都至少添加一条注释。 
    # 如果程序太简单, 实在没有什么需要说明的, 就在程序文件开头加上你的姓名和当前日期, 再用一句话阐述程序的功能。
    var = 'hello_world!'
    这句是将hello_world!字符串赋值给变量var
    print(var)
    将var变量打印出来
    
    # 2-11 Python之禅: 在Python终端会话中执行命令import this , 并粗略地浏览一下其他的指导原则。
    ①win+r 打开运行窗口
    ②输入cmd打开命令提示符
    ③输入python进入cpython
    ④输入import this
    Beautiful is better than ugly.
    Explicit is better than implicit.
    Simple is better than complex.
    Complex is better than complicated.
    Flat is better than nested.
    Sparse is better than dense.
    Readability counts.
    Special cases aren't special enough to break the rules.
    Although practicality beats purity.
    Errors should never pass silently.
    Unless explicitly silenced.
    In the face of ambiguity, refuse the temptation to guess.
    There should be one-- and preferably only one --obvious way to do it.
    Although that way may not be obvious at first unless you're Dutch.
    Now is better than never.
    Although never is often better than *right* now.
    If the implementation is hard to explain, it's a bad idea.
    If the implementation is easy to explain, it may be a good idea.
    Namespaces are one honking great idea -- let's do more of those!
    

    第三章

    list 列表简介

    # 3-1 姓名: 将一些朋友的姓名存储在一个列表中, 并将其命名为names 。 
    # 依次访问该列表中的每个元素, 从而将每个朋友的姓名都打印出来。
    names = ['张三','李四','王五']
    print(names[0])
    print(names[1])
    print(names[2])
    
    
    # 3-2 问候语: 继续使用练习3-1中的列表, 但不打印每个朋友的姓名, 而为每人打印一条消息。 
    # 每条消息都包含相同的问候语, 但抬头为相应朋友的姓名。
    names = ['张三','李四','王五']
    print(names[0] + ',你好!')
    print(names[1] + ',你好!')
    print(names[2] + ',你好!')
    
    
    
    # 3-3 自己的列表: 想想你喜欢的通勤方式, 如骑摩托车或开汽车, 并创建一个包含多种通勤方式的列表。 根
    # 据该列表打印一系列有关这些通勤方式的宣言, 如“I wouldlike to own a Honda motorcycle”。
    travel_mode = ['小汽车','摩托车','自行车']
    print('我想拥有一辆:' + travel_mode[0])
    print('我想拥有一辆:' + travel_mode[1])
    print('我想拥有一辆:' + travel_mode[2])
    
    # 3-4 嘉宾名单 : 如果你可以邀请任何人一起共进晚餐(无论是在世的还是故去的),你会邀请哪些人? 
    # 请创建一个列表, 其中包含至少3个你想邀请的人; 然后, 使用这个列表打印消息, 邀请这些人来与你共进晚餐。
    inv_list = ['马云','马化腾','李彦宏']
    for inv_name in inv_list:
    	print('尊敬的:' + inv_name + '(先生/女士),诚挚的邀请您参加今晚的宴会!')
    
    # 3-5 修改嘉宾名单 : 你刚得知有位嘉宾无法赴约, 因此需要另外邀请一位嘉宾。
    # 以完成练习3-4时编写的程序为基础, 在程序末尾添加一条print 语句, 指出哪位嘉宾无法赴约。
    # 修改嘉宾名单, 将无法赴约的嘉宾的姓名替换为新邀请的嘉宾的姓名。
    # 再次打印一系列消息, 向名单中的每位嘉宾发出邀请。
    inv_list = ['马云','马化腾','李彦宏']
    print(inv_list[0] + '因故无法赴宴!')
    inv_list[0] = 'jack_Ma'
    for inv_name in inv_list:
    	print('尊敬的:' + inv_name + '(先生/女士),诚挚的邀请您参加今晚的宴会!')
    	#这题出的真有毛病,马云马化腾要是都缺席了,李彦宏就要收三次短信,我要是李彦宏第一个开除你……
    
    
    
    # 3-6 添加嘉宾 : 你刚找到了一个更大的餐桌, 可容纳更多的嘉宾。 请想想你还想邀请哪三位嘉宾。
    # 以完成练习3-4或练习3-5时编写的程序为基础, 在程序末尾添加一条print 语句, 指出你找到了一个更大的餐桌。
    # 使用insert() 将一位新嘉宾添加到名单开头。
    # 使用insert() 将另一位新嘉宾添加到名单中间。
    # 使用append() 将最后一位新嘉宾添加到名单末尾。
    # 打印一系列消息, 向名单中的每位嘉宾发出邀请。
    inv_list = ['马云','马化腾','李彦宏']
    inv_list.insert(0,'雷军')
    inv_list.insert(2,'柳传志')
    inv_list.append('赵本山')
    for inv_name in inv_list:
    	print('尊敬的:' + inv_name + '(先生/女士),诚挚的邀请您参加今晚的宴会!')
    
    # 3-7 缩减名单 : 你刚得知新购买的餐桌无法及时送达, 因此只能邀请两位嘉宾。
    # 以完成练习3-6时编写的程序为基础, 在程序末尾添加一行代码, 打印一条你只能邀请两位嘉宾共进晚餐的消息。
    # 使用pop() 不断地删除名单中的嘉宾, 直到只有两位嘉宾为止。 每次从名单中弹出一位嘉宾时, 都打印一条消息, 
    # 让该嘉宾知悉你很抱歉, 无法邀请他来共进晚餐。
    # 对于余下的两位嘉宾中的每一位, 都打印一条消息, 指出他依然在受邀人之列。
    # 使用del 将最后两位嘉宾从名单中删除, 让名单变成空的。 打印该名单, 核实程序结束时名单确实是空的。
    print('--------------------')
    inv_list = ['马云','马化腾','李彦宏']
    inv_list.insert(0,'雷军')
    inv_list.insert(2,'柳传志')
    inv_list.append('赵本山')
    for inv_name in inv_list:
    	print('尊敬的:' + inv_name + '(先生/女士),诚挚的邀请您参加今晚的宴会!')
    print('抱歉,只能邀请两位嘉宾共进晚餐')
    n = int(len(inv_list))
    while n > 2:
    	last_name = inv_list.pop()
    	print(last_name + ',别来了')
    	n = n-1
    for inv_name in inv_list:
    	print(inv_name + '接着来吧!混蛋')
    #急着下班,这样写有点乱,建议加个中间list_temp
    
    # 3-8 放眼世界 : 想出至少5个你渴望去旅游的地方。
    # 将这些地方存储在一个列表中, 并确保其中的元素不是按字母顺序排列的。91
    # 按原始排列顺序打印该列表。 不要考虑输出是否整洁的问题, 只管打印原始Python列表。92
    # 使用sorted() 按字母顺序打印这个列表, 同时不要修改它。93
    # 再次打印该列表, 核实排列顺序未变。94
    # 使用sorted() 按与字母顺序相反的顺序打印这个列表, 同时不要修改它。9596
    # 再次打印该列表, 核实排列顺序未变。97
    # 使用reverse() 修改列表元素的排列顺序。 打印该列表, 核实排列顺序确实变了。9899
    # 使用reverse() 再次修改列表元素的排列顺序。 打印该列表, 核实已恢复到原来的排列顺序。100101
    # 使用sort() 修改该列表, 使其元素按字母顺序排列。 打印该列表, 核实排列顺序确实变了。
    # 使用sort() 修改该列表, 使其元素按与字母顺序相反的顺序排列。 打印该列表, 核实排列顺序确实变了。
    traver_place = ['BeiJing','NanJing','XiAn','LuoYang','GuangZhou']
    print(traver_place)
    print(sorted(traver_place))
    print(traver_place)
    traver_place.reverse()
    print(sorted(traver_place))
    print(traver_place)
    traver_place.reverse()
    print(traver_place)
    traver_place.reverse()
    print(traver_place)
    traver_place.sort()  
    print(traver_place)
    traver_place.sort(reverse=True)  
    print(traver_place)
    #什么神经病题目,可能会有遗漏,但是不会报错
    
    # 3-9 晚餐嘉宾 : 在完成练习3-4~练习3-7时编写的程序之一中, 使用len() 打印一条消息, 指出你邀请了多少位嘉宾来与你共进晚餐。
    inv_list = ['马云','马化腾','李彦宏']
    print('共邀请了:' + str(len(inv_list)) + '位宾客!')
    
    # 3-10 尝试使用各个函数 : 想想可存储到列表中的东西, 如山岳、 河流、 国家、 城市、 语言或你喜欢的任何东西。 
    # 编写一个程序, 在其中创建一个包含这些元素的列 表, 然后, 对于本章介绍的每个函数, 都至少使用一次来处理这个列表。
    #略……
    
    

    第四章

    list 列表操作

    # 4-1 比萨 : 想出至少三种你喜欢的比萨, 将其名称存储在一个列表中, 
    # 再使用for 循环将每种比萨的名称都打印出来。
    # 修改这个for 循环, 使其打印包含比萨名称的句子, 而不仅仅是比萨的名称。 
    # 对于每种比萨, 都显示一行输出, 如“I like pepperoni pizza”。
    # 在程序末尾添加一行代码, 它不在for 循环中, 指出你有多喜欢比萨。 
    # 输出应包含针对每种比萨的消息, 还有一个总结性句子, 如“I really love pizza!”。
    pizzas = ['pizzaA','pizzaB','pizzaC']
    for temp in pizzas:
    	print(temp)
    for temp2 in pizzas:
    	print('I like:' + temp2 +'!')
    print('老喜欢吃披萨了,比如:' + str(pizzas) + ',I really love pizza!' )
    
    # 4-2 动物 : 想出至少三种有共同特征的动物, 将这些动物的名称存储在一个列表中, 再使用for 循环将每种动物的名称都打印出来。
    # 修改这个程序, 使其针对每种动物都打印一个句子, 如“A dog would make a great pet”。
    # 在程序末尾添加一行代码, 指出这些动物的共同之处, 如打印诸如“Any of these animals would make a great pet!”这样的句子。
    animals = ['dog','cat','bird']
    for temp in animals:
    	print(temp)
    print('A '+ animals[0] + ' would make a great pet1')
    print('A '+ animals[1] + ' would make a great pet2')
    print('A '+ animals[2] + ' would make a great pet3')
    print('Any of these animals would make a great pet')
    
    # 4-3 数到20 : 使用一个for 循环打印数字1~20(含) 。
    temp = list(range(1,21))
    for t in temp:
    	print(t)
    
    # 4-4 一百万 : 创建一个列表, 其中包含数字1~1 000 000, 再使用一个for 循环将这些数字打印出来
    # (如果输出的时间太长, 按Ctrl + C停止输出, 或关闭输出窗口) 。
    # temp = list(range(1,1000001))
    # for t in temp:
    	# print(t)
    
    # 4-5 计算1~1 000 000的总和 : 创建一个列表, 其中包含数字1~1 000 000, 再使用min() 和max() 核实该列表确实是从1开始, 
    # 到1 000 000结束的。 另外, 对这个列表调用函数sum() , 看看Python将一百万个数字相加需要多长时间。
    temp = list(range(1,1000001))
    print(min(temp))
    print(max(temp))
    print(sum(temp))
    
    # 4-6 奇数 : 通过给函数range() 指定第三个参数来创建一个列表, 其中包含1~20的奇数; 再使用一个for 循环将这些数字都打印出来。
    temp = list(range(1,21,2))
    for t in temp:
    	print(t)
    
    # 4-7 3的倍数 : 创建一个列表, 其中包含3~30内能被3整除的数字; 再使用一个for 循环将这个列表中的数字都打印出来。
    temp = list(range(3,31))
    temp2 = []
    for t in temp:
    	if t % 3 == 0:
    		temp2.append(t)
    print(temp2)
    # 4-8 立方 : 将同一个数字乘三次称为立方。 例如, 在Python中, 2的立方用2**3 表示。 请创建一个列表, 其中包含前10个整数(即1~10) 
    # 的立方, 再使用一个for 循环将这些立方数都打印出来。
    temp = list(range(1,11,1))
    temp2 = []
    for t in temp:
    	t = t ** 2
    	temp2.append(t)
    print(temp2)
    #4-8方法2
    for value in range(3,31,3):  
        print(value)  
    
    
    # 4-9 立方解析 : 使用列表解析生成一个列表, 其中包含前10个整数的立方。
    lists = [value**3 for value in range(1,11)]  
    print(lists)
    	
    # 4-10 切片 : 选择你在本章编写的一个程序, 在末尾添加几行代码, 以完成如下任务。
    # 打印消息“The first three items in the list are:”, 再使用切片来打印列表的前三个元素。
    # 打印消息“Three items fromthe middle of the list are:”, 再使用切片来打印列表中间的三个元素。
    # 打印消息“The last three items in the list are:”, 再使用切片来打印列表末尾的三个元素。
    lists = ['1','2','3','4','5','6','7'] 
    print('The first three items in the list are:')
    temp1 = lists[:3]
    for t1 in temp1:
    	print(t1)
    print('Three items fromthe middle of the list are:' )
    temp2 = lists[2:5]
    for t2 in temp2:
    	print(t2)
    print('Three items fromthe middle of the list are:')
    temp3 = lists[-3:]
    for t3 in temp3:
    	print(t3)
    	
    # 4-11 你的比萨和我的比萨 : 在你为完成练习4-1而编写的程序中, 创建比萨列表的副本, 并将其存储到变量friend_pizzas 中, 
    # 再完成如下任务。在原来的比萨列表中添加一种比萨。在列表friend_pizzas 中添加另一种比萨。
    # 核实你有两个不同的列表。 为此, 打印消息“My favorite pizzas are:”, 再使用一个for 循环来打印第一个列表; 
    # 打印消息“My friend's favorite pizzas are:”, 再使用一个for 循环来打印第二个列表。 核实新增的比萨被添加到了正确的列表中。
    my_pizzas = ['pizzaA','pizzaB','pizzaC']
    friend_pizzas = my_pizzas[:]
    my_pizzas.append('my_pizzaD')
    friend_pizzas.append('friend_pizzaD')
    print('My favorite pizzas are: ')
    for temp in my_pizzas:
    	print(temp)
    print('My friend\'s favorite pizzas are: ')
    for temp in friend_pizzas:
    	print(temp)
    
    
    # 4-12 使用多个循环 : 在本节中, 为节省篇幅, 程序foods.py的每个版本都没有使用for 循环来打印列表。 请选择一个版本的foods.py, 
    # 在其中编写两个for 循环, 将各个食品列表都打印出来。	
    my_foods = ['pizza', 'falafel', 'carrot cake']	
    for t in my_foods:
    	print(t)
    	
    # 4-13 自助餐 : 有一家自助式餐馆, 只提供五种简单的食品。 请想出五种简单的食品, 并将其存储在一个元组中。
    # 使用一个for 循环将该餐馆提供的五种食品都打印出来。
    # 尝试修改其中的一个元素, 核实Python确实会拒绝你这样做。
    # 餐馆调整了菜单, 替换了它提供的其中两种食品。 请编写一个这样的代码块: 给元组变量赋值, 
    # 并使用一个for 循环将新元组的每个元素都打印出来。
    food = ('冰淇淋','苹果','牛肉','羊肉','火锅')	
    for f in food:
    	print(f)
    food[0] = '1'
    food = ('1','2','牛肉','羊肉','火锅')	
    for f in food:
    	print(f)
    	
    # 4-14 PEP 8 : 请访问https://python.org/dev/peps/pep-0008/ , 阅读PEP 8格式设置指南。 
    # 当前, 这些指南适用的不多, 但你可以大致浏览一下。
    #略……………………
    
    # 4-15 代码审核 : 从本章编写的程序中选择三个, 根据PEP 8指南对它们进行修改。
    # 每级缩进都使用四个空格。 对你使用的文本编辑器进行设置, 使其在你按Tab键时都插入四个空格; 
    # 如果你还没有这样做, 现在就去做吧(有关如何设置, 请参阅附录B) 。
    # 每行都不要超过80字符。 对你使用的编辑器进行设置, 使其在第80个字符处显示一条垂直参考线。
    # 不要在程序文件中过多地使用空行。
    #略……………………
    	
    

    第五章

    if语句

    # 5-1 条件测试 : 编写一系列条件测试; 将每个测试以及你对其结果的预测和实际结果都打印出来。 你编写的代码应类似于下面这样:
    # car = 'subaru'
    # print("Is car == 'subaru'? I predict True.")
    # print(car == 'subaru')
    # print("\nIs car == 'audi'? I predict False.")
    # print(car == 'audi')
    # 详细研究实际结果, 直到你明白了它为何为True 或False 。
    # 创建至少10个测试, 且其中结果分别为True 和False 的测试都至少有5个。
    car = 'bmw'
    cars = ['bmw','audi']
    #T
    print(car == 'bmw')
    #F
    print(car != 'bmw')
    #T
    print(car == car)
    #F
    print(car == car.title())
    #T
    print(car == 'bmw' or  car == 'audi')
    #F
    print(car == 'bmw' and car == 'audi')
    #T
    print(int(len(car)) == int(len('bmw')))
    #F
    print(int(len(car)) == int(len('audi')))
    #T
    print('bmw' in cars)
    #F
    print('audi' not in cars)
    

    第六章

    字典

    # 6-1 人 : 使用一个字典来存储一个熟人的信息, 包括名、 姓、 年龄和居住的城市。 
    # 该字典应包含键first_name 、 last_name 、 age 和city 。 将存储在该字典中的每项信息都打印出来。
    mayun = {'first_name':'Ma','last_name':'Yun','age':'54','city':'HangZhou'}
    for key,value in mayun.items():
    	print('key:' + key)
    	print('value:' + value)
    
    
    # 6-2 喜欢的数字 : 使用一个字典来存储一些人喜欢的数字。 请想出5个人的名字, 
    # 并将这些名字用作字典中的键; 想出每个人喜欢的一个数字, 并将这些数字作为值存
    # 储在字典中。 打印每个人的名字和喜欢的数字。 为让这个程序更有趣, 通过询问朋友确保数据是真实的。
    dics = {'jack':'1','john':'2','kaiven':'3','popo':'4','lili':'5'}
    for k,v in dics.items():
    	print(k + '最喜欢的数字是: ' + v)
    
    
    # 6-3 词汇表 : Python字典可用于模拟现实生活中的字典, 但为避免混淆, 我们将后者称为词汇表。
    # 想出你在前面学过的5个编程词汇, 将它们用作词汇表中的键, 并将它们的含义作为值存储在词汇表中。
    # 以整洁的方式打印每个词汇及其含义。 为此, 你可以先打印词汇, 在它后面加上一个冒号, 再打印词汇的含义; 
    # 也可在一行打印词汇, 再使用换行符(\n ) 插入一个空行, 然后在下一行以缩进的方式打印词汇的含义。
    #我真是良心up主啊,看到了6-4,,又把6-3复杂的写了一遍………………
    dics = {'list':'列表','var':'变量','int':'整型','boolean':'布尔','str':'字符串'}
    print('dics[\'list\']'+':' + dics['list'])
    print('dics[\'var\']'+':' + dics['var'])
    print('dics[\'int\']'+':' + dics['int'])
    print('dics[\'boolean\']'+':' + dics['boolean'])
    print('dics[\'str\']'+':' + dics['str'])
    	
    	
    # 6-4 词汇表2 : 既然你知道了如何遍历字典, 现在请整理你为完成练习6-3而编写的代码, 
    # 将其中的一系列print 语句替换为一个遍历字典中的键和值的循环。 确定该循环正确无误后, 
    # 再在词汇表中添加5个Python术语。 当你再次运行这个程序时, 这些新术语及其含义将自动包含在输出中。
    dics = {'list':'列表','var':'变量','int':'整型','boolean':'布尔','str':'字符串'}
    for k,v in dics.items():
    	print(k + ':' + v + '\n')
    
    	
    # 6-5 河流 : 创建一个字典, 在其中存储三条大河流及其流经的国家。 其中一个键—值对可能是'nile': 'egypt' 。
    # 使用循环为每条河流打印一条消息, 如“The Nile runs through Egypt.”。
    # 使用循环将该字典中每条河流的名字都打印出来。
    # 使用循环将该字典包含的每个国家的名字都打印出来。
    rivers = {'nile':'egypt','huanghe':'china','changjiang':'china'}
    for k , v in rivers.items():
    	print('The ' + k + ' runs through ' + v + ' .')
    for k in rivers.keys():
    	print(k)
    for v in rivers.values():
    	print(v)
    
    
    # 6-6 调查 : 在6.3.1节编写的程序favorite_languages.py中执行以下操作。
    # 创建一个应该会接受调查的人员名单, 其中有些人已包含在字典中, 而其他人未包含在字典中。
    # 遍历这个人员名单, 对于已参与调查的人, 打印一条消息表示感谢。 对于还未参与调查的人, 打印一条消息邀请他参与调查。
    favorite_languages = {
    	'amada':'C',
    	'jacky':'java',
    	'frank':'c++',
    	'polly':'php',
    	'maily':'.net'
    	}
    lists = ['amada','jacky','mayun','admin']
    temp = []
    for k in favorite_languages.keys():
    	temp.append(k)
    print(temp)
    for s in lists:
    	if s in temp:
    		print('1')
    	else:
    		print ('2')
    		
    # 6-7 人 : 在为完成练习6-1而编写的程序中, 再创建两个表示人的字典, 然后将这三个字典都存储在一个名为people 的列表中。 
    # 遍历这个列表, 将其中每个人的所有信息都打印出来。
    mayun0 = {'first_name':'Ma0','last_name':'Yun0','age':'540','city':'HangZhou0'}
    mayun1 = {'first_name':'Ma1','last_name':'Yun1','age':'541','city':'HangZhou1'}
    mayun2 = {'first_name':'Ma2','last_name':'Yun','age':'542','city':'HangZhou2'}
    people = [mayun0,mayun1,mayun2]
    # print(people)
    for i in people[:]:
    	print(i)
    
    
    
    
    # 6-8 宠物 : 创建多个字典, 对于每个字典, 都使用一个宠物的名称来给它命名; 在每个字典中, 包含宠物的类型及其主人的名字。 
    # 将这些字典存储在一个名为pets的列表中, 再遍历该列表, 并将宠物的所有信息都打印出来。
    dog ={'name':'dog1','age':'3'}
    cat ={'name':'cat1','age':'4'}
    bird ={'name':'bird1','age':'1'}
    pets = [dog,cat,bird]
    for p in pets:
    	print(p)
    
    # 6-9 喜欢的地方 : 创建一个名为favorite_places 的字典。 在这个字典中, 将三个人的名字用作键; 对于其中的每个人, 
    # 都存储他喜欢的1~3个地方。 为让这个练习更有趣些, 可让一些朋友指出他们喜欢的几个地方。 遍历这个字典, 
    # 并将其中每个人的名字及其喜欢的地方打印出来。
    favorite_places = {'jack':'beijing','paul':'shanghai','lili':'hangzhou'}
    for fp in favorite_places.items():
    	print(fp)
    
    
    # 6-10 喜欢的数字 : 修改为完成练习6-2而编写的程序, 让每个人都可以有多个喜欢的数字, 然后将每个人的名字及其喜欢的数字打印出来。
    dics = {'jack':['1','2'],'john':['3','4']}
    for k,v in dics.items():
    	print(k + '最喜欢的数字是: ' )
    	for v1 in v:
    		print(v1)
    
    
    
    # 6-11 城市 : 创建一个名为cities 的字典, 其中将三个城市名用作键; 对于每座城市, 都创建一个字典, 
    # 并在其中包含该城市所属的国家、 人口约数以及一个有关该城市的事实。 在表示每座城市的字典中, 
    # 应包含country 、 population 和fact 等键。 将每座城市的名字以及有关它们的信息都打印出来。
    cities = {'beijing':{'country':'china','population':'100','fact':'超级堵'},'guangzhou':{'country':'china','population':'300','fact':'超级堵2'},'shanghai':{'country':'china','population':'200','fact':'超级堵1'}}
    for k,v in cities.items():
    	print('城市:'+k+ '的信息: ')
    	for k1,v1 in v.items():
    		print(k1,v1)
    
    
    # 6-12 扩展 : 本章的示例足够复杂, 可以以很多方式进行扩展了。 请对本章的一个示例进行扩展: 添加键和值、 调
    # 整程序要解决的问题或改进输出的格式
    	
    # 略………………
    

    第七章

    用户输入和while 循环

    #本章节代码中暂不涉及try-catch,所以默认为用户输入的符合所需要的输入类型
    
    
    # 7-1 汽车租赁 : 编写一个程序, 询问用户要租赁什么样的汽车, 并打印一条消息, 如“Let me see if I can find you a Subaru”。
    msg = input('请输入您要租赁的汽车名称:')
    print('Let me see if I can find you a ' + msg)
    
    
    # 7-2 餐馆订位 : 编写一个程序, 询问用户有多少人用餐。 如果超过8人, 就打印一条消息, 指出没有空桌; 否则指出有空桌。
    msg = input ('请输入用餐人数:')
    if int(msg) > 8:
    	print('没有空桌')
    else :
    	print('有空桌')
    
    # 7-3 10的整数倍 : 让用户输入一个数字, 并指出这个数字是否是10的整数倍。
    msg = input('请输入一个数字,将自动计算是否为10的整数倍:')
    if int(msg) % 10 == 0 :
    	print(msg + '是 10 的整数倍')
    else:
    	print(msg + '不是 10 的整数倍')
    
    # 7-4 比萨配料 : 编写一个循环, 提示用户输入一系列的比萨配料, 并在用户输入'quit' 时结束循环。 每当用户输入一种配料后, 
    # 都打印一条消息, 说我们会在比萨中添加这种配料。
    msg1 = ('请输入一种披萨配料,输入‘quit’后会退出程序,请输入:')
    while True:
    	msg = input(msg1)
    	if 'quit' in msg:
    		break
    	else:
    		print('我们会在比萨中添加这种配料: ' + msg)
    #这个input必须写在循环里,不然会一直输出
    
    
    # 7-5 电影票 : 有家电影院根据观众的年龄收取不同的票价: 不到3岁的观众免费; 3~12岁的观众为10美元; 超过12岁的观众为15美元。 
    # 请编写一个循环, 在其中询问用户的年龄, 并指出其票价。
    msg = '请输入你的年龄:'
    while True:
    	msg1 = input(msg)
    	if 'quit' in msg1:
    		print('已退出')
    		break
    	elif int(msg1) <3:
    		print('免费')
    	elif 3 <= int(msg1) <12:
    		print('\$10')
    	elif int(msg1) >= 12:
    		print('\$15')
    	
    
    
    # 7-6 三个出口 : 以另一种方式完成练习7-4或练习7-5, 在程序中采取如下所有做法。
    # 在while 循环中使用条件测试来结束循环。
    # 使用变量active 来控制循环结束的时机。
    # 使用break 语句在用户输入'quit' 时退出循环。
    #7-6(1)
    msg1 = ('请输入一种披萨配料,输入‘quit’后会退出程序,请输入:')
    active1 = True
    while active1:
    	msg = input(msg1)
    	if 'quit' in msg:
    		active1 = False
    	else:
    		print('我们会在比萨中添加这种配料: ' + msg)
    		
    #7-6(2)
    ac = True
    msg = '请输入你的年龄:'
    while ac:
    	msg1 = input(msg)
    	if 'quit' in msg1:
    		print('已退出')
    		break
    	elif int(msg1) <3:
    		print('免费')
    	elif 3 <= int(msg1) <12:
    		print('\$10')
    	elif int(msg1) >= 12:
    		print('\$15')
    
    # 7-7 无限循环 : 编写一个没完没了的循环, 并运行它(要结束该循环, 可按Ctrl +C, 也可关闭显示输出的窗口) 。
    while 1:
    	print('1')
    	
    # 7-8 熟食店 : 创建一个名为sandwich_orders 的列表, 在其中包含各种三明治的名字; 再创建一个名为finished_sandwiches 的空列表。 
    # 遍历列表sandwich_orders , 对于其中的每种三明治, 都打印一条消息, 如I made your tuna sandwich , 
    # 并将其移到列表finished_sandwiches 。 所有三明治都制作好后, 打印一条消息, 将这些三明治列出来。
    sandwich_orders = ['s1','s2','s3','s4']
    finished_sandwiches = []
    act = True
    while act:
    	if int(len(sandwich_orders)) != 0:
    		cu_sw = sandwich_orders.pop()
    		finished_sandwiches.insert(0,cu_sw)
    	else:
    		act = False
    print(finished_sandwiches)
    
    
    # 7-9 五香烟熏牛肉(pastrami) 卖完了 : 使用为完成练习7-8而创建的列表sandwich_orders , 
    # 并确保'pastrami' 在其中至少出现了三次。 在程序开头附近添加这样的代码: 打印一条消息, 指出熟食店的五香烟熏牛肉卖完了; 
    # 再使用一个while 循环将列表sandwich_orders 中的'pastrami' 都删除。 确认最终的列表finished_sandwiches 中不包含'pastrami' 。
    print('熟食店的五香烟熏牛肉卖完了')
    sandwich_orders = ['s1','pastram','s2','pastram','s3','pastram','s4']
    print(sandwich_orders)
    while 'pastram' in sandwich_orders:
    	sandwich_orders.remove('pastram')
    print(sandwich_orders)
    
    # 7-10 梦想的度假胜地 : 编写一个程序, 调查用户梦想的度假胜地。 
    # 使用类似于“If you could visit one place in the world, where would you go?”的提示, 并编写一个打印调查结果的代码块.
    names = '请输入你的姓名:'
    places = '请输入你想去的地点:'
    dics = {}
    ac = True
    while ac:
    	name = input(names)
    	place = input(places)
    	dics[name] = place
    	repeat = input('还有其他人回答吗?(yes/no)')
    	if repeat == 'no':
    		ac = False
    print(dics)
    

    第八章

    函数

    # 8-1 消息 : 编写一个名为display_message() 的函数, 它打印一个句子, 指出你在本章学的是什么。 
    # 调用这个函数, 确认显示的消息正确无误。
    def display_message():
    	print('本章学习内容:def(函数)')
    display_message()
    
    # 8-2 喜欢的图书 : 编写一个名为favorite_book() 的函数, 其中包含一个名为title 的形参。 这个函数打印一条消息, 
    # 如One of my favorite books isAlice in Wonderland 。 调用这个函数, 并将一本图书的名称作为实参传递给它。
    def favorite_book(title,price):
    	print('One of my favorite books is: ' + title)
    favorite_book('java程序设计','')
    
    # 8-3 T恤 : 编写一个名为make_shirt() 的函数, 它接受一个尺码以及要印到T恤上的字样。 
    # 这个函数应打印一个句子, 概要地说明T恤的尺码和字样。
    # 使用位置实参调用这个函数来制作一件T恤; 再使用关键字实参来调用这个函数。
    def make_shirt(size,msg):
    	if msg == '':
    		print('这件t恤衫的尺寸是:' + size + '; 印花文字为:' + '空')
    	else:
    		print('这件t恤衫的尺寸是:' + size + ';印花文字为:' + msg)
    make_shirt('XXXL','')
    make_shirt('XXXL',msg = 'hello_world!')
    
    # 8-4 大号T恤 : 修改函数make_shirt() , 使其在默认情况下制作一件印有字样“I love Python”的大号T恤。 
    # 调用这个函数来制作如下T恤: 一件印有默认字样的大号T恤、 
    # 一件印有默认字样的中号T恤和一件印有其他字样的T恤(尺码无关紧要) 。
    def make_shirt(size,msg = 'I love Python'):
    	print('这件t恤衫的尺寸是:' + size + ';印花文字为:' + msg)
    make_shirt('大号T恤')
    make_shirt('中号T恤')
    make_shirt('小号T恤','其他字样')
    
    # 8-5 城市 : 编写一个名为describe_city() 的函数, 它接受一座城市的名字以及该城市所属的国家。 
    # 这个函数应打印一个简单的句子, 如Reykjavik is in Iceland 。 给用于存储国家的形参指定默认值。 
    # 为三座不同的城市调用这个函数, 且其中至少有一座城市不属于默认国家。
    def describe_city(city_name,city_belong_country = 'china'):
    	print(city_name + ' is in ' + city_belong_country)
    describe_city('shanghai')
    describe_city('beijing')
    describe_city('DC','america')
    
    # 8-6 城市名 : 编写一个名为city_country() 的函数, 它接受城市的名称及其所属的国家。 
    # 这个函数应返回一个格式类似于下面这样的字符串:"Santiago, Chile"
    # 至少使用三个城市-国家对调用这个函数, 并打印它返回的值。
    def city_country(city_name,city_belong_country):
    	city_country1 = city_name + ',' +city_belong_country
    	return city_country1
    a = city_country('shanghai','china')
    b = city_country('beijing','china')
    c = city_country('DC','America')
    print(a)
    print(b)
    print(c)
    
    # 8-7 专辑 : 编写一个名为make_album() 的函数, 它创建一个描述音乐专辑的字典。 
    # 这个函数应接受歌手的名字和专辑名, 并返回一个包含这两项信息的字典。 使用这个函数创建三个表示不同专辑的字典, 
    # 并打印每个返回的值, 以核实字典正确地存储了专辑的信息。给函数make_album() 添加一个可选形参, 
    # 以便能够存储专辑包含的歌曲数。 如果调用这个函数时指定了歌曲数, 就将这个值添加到表示专辑的字典中。 调用这个
    # 函数, 并至少在一次调用中指定专辑包含的歌曲数。
    def make_album(singer_name,album_name,song_number = ''):
    	if song_number:
    		s_a =  {'singer_name':singer_name,'album_name':album_name,'song_number' : song_number}
    	else:
    		s_a = {'singer_name':singer_name,'album_name':album_name}
    	return s_a
    a = make_album('HanHong','QingZangGaoYuan','5')
    b = make_album('AndiLiu','WangQingShui')
    c = make_album('LiuHuan','YouAndMe','7')
    print(a)
    print(b)
    print(c)
    
    # 8-8 用户的专辑 : 在为完成练习8-7编写的程序中, 编写一个while 循环, 让用户输入一个专辑的歌手和名称。 
    # 获取这些信息后, 使用它们来调用函数make_album() , 并将创建的字典打印出来。 在这个while 循环中, 务必要提供退出途径。
    def make_album(singer_name,album_name,song_number = ''):
    	if song_number:
    		s_a =  {'singer_name':singer_name,'album_name':album_name,'song_number' : song_number}
    	else:
    		s_a = {'singer_name':singer_name,'album_name':album_name}
    	return s_a
    
    s_n_inp = '请输入歌手名:(输入’quit‘后退出)'
    a_n_inp = '请输入专辑名:(输入’quit‘后退出)'
    ac = True
    while ac:
    	a = input(s_n_inp)
    	b = input(a_n_inp)
    	if a == 'quit' or b == 'quit' :
    		break
    	else:
    		c = make_album(a,b)
    		print(c)
    
    # 8-9 魔术师 : 创建一个包含魔术师名字的列表, 并将其传递给一个名为show_magicians() 的函数, 这个函数打印列表中每个魔术师的名字。
    name_list = ['mag1','mag2','mag3']
    def show_magicians():
    	for name in name_list:
    		print(name)
    show_magicians()
    
    # 8-10 了不起的魔术师 : 在你为完成练习8-9而编写的程序中, 编写一个名为make_great() 的函数, 
    # 对魔术师列表进行修改, 在每个魔术师的名字中都加入字样“theGreat”。 调用函数show_magicians() , 确认魔术师列表确实变了。
    name_list = ['mag1','mag2','mag3']
    name_change = []
    def make_great(name_list,name_change):
    	while name_list:
    		cur = name_list.pop()
    		cur = 'great' + cur
    		name_change.append(cur)
    	
    def show_magicians(name_change):
    	for name in name_change:
    		print(name)
    		
    make_great(name_list,name_change)
    show_magicians(name_change)
    
    
    # 8-11 不变的魔术师 : 修改你为完成练习8-10而编写的程序, 在调用函数make_great() 时, 向它传递魔术师列表的副本。 
    # 由于不想修改原始列表, 请返回修改后的列表, 并将其存储到另一个列表中。 分别使用这两个列表来调用show_magicians() , 
    # 确认一个列表包含的是原来的魔术师名字, 而另一个列表包含的是添加了字样“the Great”的魔术师名字。
    name_list = ['mag1','mag2','mag3']
    name_change = []
    
    def make_great(name_list,name_change):
    	while name_list:
    		cur = name_list.pop()
    		cur = 'great' + cur
    		name_change.append(cur)
    def show_magicians(name_change)
    	for name in name_change:
    		print(name)
    
    make_great(name_list[:],name_change)
    show_magicians(name_list)
    show_magicians(name_change)
    
    	
    
    # 8-12 三明治 : 编写一个函数, 它接受顾客要在三明治中添加的一系列食材。 这个函数只有一个形参(它收集函数调用中提供的所有食材) , 
    # 并打印一条消息, 对顾客点的三明治进行概述。 调用这个函数三次, 每次都提供不同数量的实参。
    def sand_make(*ingredients):
    	print( '添加的食材有:')
    	for i in ingredients:
    		print('--' + i)
    	
    sand_make('1','2','3','4')
    sand_make('0')
    sand_make('1','2')
    
    
    # 8-13 用户简介 : 复制前面的程序user_profile.py, 在其中调用build_profile() 来创建有关你的简介; 
    # 调用这个函数时, 指定你的名和姓, 以及三个描述你的键-值对。
    def user_profile(first,last,**else_info):
    	name_file = {}
    	name_file['first_name'] = first
    	name_file['last_name']  = last
    	for k ,v in else_info.items():
    		name_file[k] = v
    	return name_file
    
    user_a = user_profile('ma','yun',company = 'TaoBao',Sex = 'man')
    print(user_a)
    user_b = user_profile('1','2',Sex = 'man')
    print(user_b)
    	
    
    
    # 8-14 汽车 : 编写一个函数, 将一辆汽车的信息存储在一个字典中。 这个函数总是接受制造商和型号, 还接受任意数量的关键字实参。 
    # 这样调用这个函数: 提供必不可少的信息, 以及两个名称—值对, 如颜色和选装配件。 这个函数必须能够像下面这样进行调用:
    # car = make_car('subaru', 'outback', color='blue', tow_package=True)
    # 打印返回的字典, 确认正确地处理了所有的信息。
    def car_msg(manufacturer,model,**else_info):
    	bas_msg = {}
    	bas_msg['manufacturer'] = manufacturer
    	bas_msg['model'] = model
    	for k ,v in else_info.items():
    		bas_msg[k] = v
    	return bas_msg
    	
    car = car_msg('subaru', 'outback', color='blue', tow_package=True)
    print(car)
    
    

    第九章

    # 9-1 餐馆 : 创建一个名为Restaurant 的类, 其方法__init__() 设置两个属性: restaurant_name 和cuisine_type 。 创建一个名
    # 为describe_restaurant() 的方法和一个名为open_restaurant() 的方法, 其中前者打印前述两项信息, 而后者打印一条消息, 指出餐馆正在营业。
    # 根据这个类创建一个名为restaurant 的实例, 分别打印其两个属性, 再调用前述两个方法。
    class Restaurant():
    	def __init__(self,restaurant_name,cuisine_type):
    		"""初始化属性restaurant_name和cuisine_type"""
    		self.restaurant_name = restaurant_name
    		self.cuisine_type = cuisine_type
    	def describe_restaurant(self):
    		print(self.restaurant_name)
    		print(self.cuisine_type)
    	def open_restaurant(self):
    		print('Restaurant is open')
    restaurant = Restaurant('A','B')
    print(restaurant.restaurant_name,'',restaurant.cuisine_type)
    restaurant.describe_restaurant()
    restaurant.open_restaurant()
    
    
    # 9-2 三家餐馆 : 根据你为完成练习9-1而编写的类创建三个实例, 并对每个实例调用方法describe_restaurant() 。
    class Restaurant():
    	def __init__(self,restaurant_name,cuisine_type):
    		"""初始化属性name和age"""
    		self.restaurant_name = restaurant_name
    		self.cuisine_type = cuisine_type
    	def describe_restaurant(self):
    		print(self.restaurant_name)
    		print(self.cuisine_type)
    	def open_restaurant(self):
    		print('Restaurant is open')
    restaurant1 = Restaurant('A1','B1')  
    restaurant1.describe_restaurant()  
    restaurant2 = Restaurant('A2','B2')  
    restaurant2.describe_restaurant()
    restaurant3 = Restaurant('A3','B3')
    restaurant3.describe_restaurant() 
    
    
    # 9-3 用户 : 创建一个名为User 的类, 其中包含属性first_name 和last_name , 还有用户简介通常会存储的其他几个属性。 在类User 中定义一个名
    # 为describe_user() 的方法, 它打印用户信息摘要; 再定义一个名为greet_user() 的方法, 它向用户发出个性化的问候。
    # 创建多个表示不同用户的实例, 并对每个实例都调用上述两个方法
    class User():
    	def __init__(self, first_name,last_name):
    		self.first_name = first_name
    		self.last_name = last_name
    	def describe_user(self):
    		print('用户名称为:' + self.first_name + self.last_name)
    	def greet_user(self):
    		print('你好! ' + self.first_name + self.last_name)
    		
    user_a = User('Ma','Yun')
    user_b = User('cheng','Long')
    user_c = User('Li','LianJie')
    user_a.describe_user()
    user_b.describe_user()
    user_c.describe_user()
    user_a.greet_user()
    user_b.greet_user()
    user_c.greet_user()
    
    # 9-4 就餐人数 : 在为完成练习9-1而编写的程序中, 添加一个名为number_served 的属性, 并将其默认值设置为0。
    # 根据这个类创建一个名为restaurant 的实例; 打印有多少人在这家餐馆就餐过, 然后修改这个值并再次打印它。
    # 添加一个名为set_number_served() 的方法, 它让你能够设置就餐人数。 调用这个方法并向它传递一个值, 然后再次打印这个值。
    # 添加一个名为increment_number_served() 的方法, 它让你能够将就餐人数递增。 调用这个方法并向它传递一个这样的值:
    # 你认为这家餐馆每天可能接待的就餐人数。
    class Restaurant():
    	def __init__(self,restaurant_name,cuisine_type):
    		self.restaurant_name = restaurant_name
    		self.cuisine_type = cuisine_type
    		self.number_served = 1
    	def describe_restaurant(self):
    		print(self.restaurant_name)
    		print(self.cuisine_type)
    	def open_restaurant(self):
    		print('Restaurant is open')
    	def number_served_info(self):
    		print('[' + self.restaurant_name + '] 这家餐馆每天可能接待的就餐人数: ' + str(self.number_served))
    		print('来 [' + self.restaurant_name + '] 吃 [' + self.cuisine_type + '] 的人有:'+str(self.number_served)+' 人!')
    	def set_number_served(self,number_info):
    		self.number_served = number_info
    	def increment_number_served(self,name_add):
    		self.number_served += name_add
    
    restaurant = Restaurant('紫光阁','北京菜')
    restaurant.number_served = 30
    restaurant.set_number_served(1)
    restaurant.increment_number_served(100)
    restaurant.increment_number_served(100)
    restaurant.increment_number_served(100)
    restaurant.increment_number_served(100)
    restaurant.number_served_info()
    
    
    # 9-5 尝试登录次数 : 在为完成练习9-3而编写的User 类中, 添加一个名为login_attempts 的属性。
    # 编写一个名为increment_login_attempts() 的方法,它将属性login_attempts 的值加1。
    # 再编写一个名为reset_login_attempts() 的方法, 它将属性login_attempts 的值重置为0。
    # 根据User 类创建一个实例, 再调用方法increment_login_attempts() 多次。 打印属性login_attempts 的值,
    # 确认它被正确地递增; 然后, 调用方法reset_login_attempts() , 并再次打印属性login_attempts 的值, 确认它被重置为0。
    class User():
    	def __init__(self, first_name, last_name):
    		'''主方法,内涵first_name,last_name两个形参'''
    		self.first_name = first_name
    		self.last_name = last_name
    		self.login_attempts = 0
    
    	def describe_user(self):
    		'''打印用户名称方法'''
    		print('用户名称为:' + self.first_name + self.last_name)
    		# print('共登录用户量:' + str(self.login_attempts))
    		print('共登录用户量:(重置中……)'+str(self.login_attempts))
    
    	def greet_user(self):
    		'''打印问候'''
    		print('你好! ' + self.first_name + self.last_name)
    
    	def increment_login_attempts(self,number):
    		self.login_attempts += number
    		print('共登录用户量:' + str(self.login_attempts))
    
    	def reset_login_attempts(self):
    		self.login_attempts = 0
    
    user_a = User('Ma','Yun')
    user_a.increment_login_attempts(1)
    user_a.increment_login_attempts(1)
    user_a.increment_login_attempts(1)
    user_a.reset_login_attempts()
    user_a.describe_user()
    
    # 9-6 冰淇淋小店 : 冰淇淋小店是一种特殊的餐馆。 编写一个名为IceCreamStand 的类, 让它继承你为完成练习9-1或练习9-4
    # 而编写的Restaurant 类。 这两个版本的Restaurant 类都可以, 挑选你更喜欢的那个即可。 添加一个名为flavors 的属性,
    # 用于存储一个由各种口味的冰淇淋组成的列表。 编写一个显示这些冰淇淋的方法。 创建一个IceCreamStand 实例, 并调用这个方法。
    class Restaurant():
    	def __init__(self,restaurant_name,cuisine_type):
    		"""初始化属性restaurant_name和cuisine_type"""
    		self.restaurant_name = restaurant_name
    		self.cuisine_type = cuisine_type
    	def describe_restaurant(self):
    		print(self.restaurant_name)
    		print(self.cuisine_type)
    	def open_restaurant(self):
    		print('Restaurant is open')
    class IceCreamStand(Restaurant):
    	def __init__(self,restaurant_name,cuisine_type):
    		super().__init__(restaurant_name,cuisine_type)
    		self.favorite = ['orange','apple']
    	def show_ice(self):
    		for i in self.favorite:
    			print(i)
    
    IceCreamStand1 = IceCreamStand('beijingfandian','beijingcai')
    IceCreamStand1.show_ice()
    
    # 9-7 管理员 : 管理员是一种特殊的用户。 编写一个名为Admin 的类, 让它继承你为完成练习9-3或练习9-5而编写的User 类。
    # 添加一个名为privileges 的属性, 用于存储一个由字符串(如"can add post" 、 "can delete post" 、 "can ban user" 等)
    # 组成的列表。 编写一个名为show_privileges() 的方法, 它显示管理员的权限。 创建一个Admin 实例, 并调用这个方法。
    class User():
    	def __init__(self, first_name,last_name):
    		self.first_name = first_name
    		self.last_name = last_name
    	def describe_user(self):
    		print('用户名称为:' + self.first_name + self.last_name)
    	def greet_user(self):
    		print('你好! ' + self.first_name + self.last_name)
    
    class Admin(User):
    	def __init__(self,first_name,last_name):
    		super().__init__(first_name,last_name)
    		self.privileges = ['can add post','can del post','can ban user']
    	def show_privileges(self):
    		# print(self.privileges)
    		for i in self.privileges:
    			print("管理员权限有:" + i)
    Admin1 = Admin('Ma','Yun')
    Admin1.show_privileges()
    
    
    # 9-8 权限 : 编写一个名为Privileges 的类, 它只有一个属性——privileges , 其中存储了练习9-7 所说的字符串列表。
    # 将方法show_privileges() 移到这个类中。 在Admin 类中, 将一个Privileges 实例用作其属性。
    # 创建一个Admin 实例, 并使用方法show_privileges() 来显示其权限。
    class User():
    	def __init__(self, first_name,last_name):
    		self.first_name = first_name
    		self.last_name = last_name
    	def describe_user(self):
    		print('用户名称为:' + self.first_name + self.last_name)
    	def greet_user(self):
    		print('你好! ' + self.first_name + self.last_name)
    
    class Admin(User):
    	def __init__(self,first_name,last_name):
    		super().__init__(first_name,last_name)
    		self.b = Privileges()
    		# self.privileges = ['can add post','can del post','can ban user']
    	# def show_privileges(self):
    	# 	# print(self.privileges)
    	# 	for i in self.privileges:
    	# 		print("管理员权限有:" + i)
    
    class Privileges():
    	def __init__(self):
    		self.privileges = ['can add post','can del post','can ban user']
    	def show_privileges(self):
    		for i in self.privileges:
    			print("管理员权限有:" + i)
    
    Admin1 = Admin('Ma','Yun')
    Admin1.b.show_privileges()
    
    # 9-9 电瓶升级 : 在本节最后一个electric_car.py版本中, 给Battery 类添加一个名为upgrade_battery() 的方法。
    # 这个方法检查电瓶容量, 如果它不是85, 就将它设置为85。 创建一辆电瓶容量为默认值的电动汽车, 调用方法get_range() ,
    # 然后对电瓶进行升级, 并再次调用get_range() 。 你会看到这辆汽车的续航里程增加了。
    class Car():
    	"""docstring for Car"""
    
    	def __init__(self, make, model, year):
    		self.make = make
    		self.model = model
    		self.year = year
    		self.odometer_reading = 0
    
    	def get_descriptive_name(self):
    		long_name = str(self.year) + ' ' + self.make + ' ' + self.model
    		return long_name
    
    	# 打印里程消息
    	def read_odometer(self):
    		print("This car has " + str(self.odometer_reading) + " miles on it.")
    
    	# 更新里程数
    	def update_odometer(self, milegeage):
    		if milegeage >= self.odometer_reading:
    			self.odometer_reading = milegeage
    		else:
    			print("You can't roll back an odometer!")
    
    	def increment_odometer(self, miles):
    		self.odometer_reading += miles
    
    
    class Battery():
    	"""docstring for Battery"""
    
    	def __init__(self, battery_size=70):
    		self.battery_size = battery_size
    
    	def describe_battery(self):
    		print("This car has a " + str(self.battery_size) + "-kWh battery")
    
    	def upgrade_battery(self):
    		if self.battery_size != 85:
    			self.battery_size = 85
    
    	def get_range(self):
    		if self.battery_size == 70:
    			range = 240
    		elif self.battery_size == 85:
    			range = 270
    		message = "This car can go approximately " + str(range)
    		message += "miles on a full charge."
    		print(message)
    		self.upgrade_battery()
    
    
    class ElectricCar(Car):
    	"""docstring for ElectricCar"""
    
    	def __init__(self, make, model, year):
    		super().__init__(make, model, year)
    		self.battery_size = Battery()
    
    	def describe_battery(self):
    		self.battery_size.battery_size()
    
    	def get_range(self):
    		self.battery_size.get_range()
    
    
    my_tesla = ElectricCar('tesla', 'model s', 2016)
    my_tesla.get_range()
    my_tesla.get_range()
    
    # 9-10 导入Restaurant 类 : 将最新的Restaurant 类存储在一个模块中。 在另一个文件中, 导入Restaurant 类, 创建一个Restaurant 实例, 并调
    # 用Restaurant 的一个方法, 以确认import 语句正确无误。
    # restaurant.py
    class Restraurant():
    	"""docstring for  Restraurant"""
    
    	def __init__(self, restaurant_name, cuisine_type):
    		self.restaurant_name = restaurant_name
    		self.cuisine_type = cuisine_type
    		self.number_served = 0
    
    	def describe_restaurant(self):
    		print(self.restaurant_name, ":", self.cuisine_type)
    
    	def open_restaurant(self):
    		print("Is opening")
    
    	def set_number_served(self, number):
    		self.number_served = number
    
    	def get_number_served(self):
    		return self.number_served
    
    	def increment_number_served(self, number):
    		while self.number_served < number:
    			print(self.number_served)
    			self.number_served += 1
    
    # coding.py
    from restraurant import Restraurant
    
    restraurant1 = Restraurant('A', 'B')
    print(restraurant1.restaurant_name, " ", restraurant1.cuisine_type)
    restraurant1.describe_restaurant()
    restraurant1.open_restaurant()
    print(restraurant1.get_number_served())
    restraurant1.set_number_served(2)
    print(restraurant1.get_number_served())
    restraurant1.increment_number_served(10)
    
    # 9-11 导入Admin 类 : 以为完成练习9-8而做的工作为基础, 将User 、 Privileges 和Admin 类存储在一个模块中, 再创建一个文件, 在其中创建一个Admin 实例
    # 并对其调用方法show_privileges() , 以确认一切都能正确地运行。
    # user.py
    class User():
    	"""docstring for User"""
    
    	def __init__(self, first_name, last_name):
    		self.first_name = first_name
    		self.last_name = last_name
    		self.login_attempts = 0
    
    	def describe_name(self):
    		print("fitst_name :", self.first_name, " last_name: ", self.last_name)
    
    	def greet_user(self):
    		print("hello, ", self.first_name, " ", self.last_name)
    
    	def increment_login_attempts(self):
    		self.login_attempts += 1
    
    	def reset_login_attempts(self):
    		self.login_attempts = 0
    
    
    class Privileges():
    	"""docstring for Privileges"""
    
    	def __init__(self):
    		self.privileges = ['can add post', 'can ban user', 'can delete post']
    
    	def show_privileges(self):
    		print(self.privileges)
    
    
    class Admin(User):
    	"""docstring for Admin"""
    
    	def __init__(self, first_name, last_name):
    		super().__init__(first_name, last_name)
    		self.privileges = Privileges()
    
    	def show_privileges(self):
    		self.privileges.show_privileges()
    
    # coding.py
    from user import Admin
    
    admin = Admin("Alice", 'Bob')
    admin.show_privileges()
    
    # 9-12 多个模块 : 将User 类存储在一个模块中, 并将Privileges 和Admin 类存储在另一个模块中。 再创建一个文件, 在其中创建一个Admin 实例, 并对其调用方
    # 法show_privileges() , 以确认一切都依然能够正确地运行。
    
    # privileges.py
    class Privileges():
        """docstring for Privileges"""
        def __init__(self):
            self.privileges = ['can add post','can ban user','can delete post']
        def show_privileges(self):
            print(self.privileges)
    # admin.py
        class Admin(User):
    	    """docstring for Admin"""
    
    	    def __init__(self, first_name, last_name):
    		    super().__init__(first_name, last_name)
    		    self.privileges = Privileges()
    
    	    def show_privileges(self):
    		    self.privileges.show_privileges()
    # user.py
    class User():
    	"""docstring for User"""
    
    	def __init__(self, first_name, last_name):
    		self.first_name = first_name
    		self.last_name = last_name
    		self.login_attempts = 0
    
    	def describe_name(self):
    		print("fitst_name :", self.first_name, " last_name: ", self.last_name)
    
    	def greet_user(self):
    		print("hello, ", self.first_name, " ", self.last_name)
    
    	def increment_login_attempts(self):
    		self.login_attempts += 1
    
    	def reset_login_attempts(self):
    		self.login_attempts = 0
    # coding.py
    from user import User
    from admin import Admin
    from privilege import Privilege
    
    admin = Admin("Alice", 'Bob')
    admin.show_privileges()
    
    # 9-13 使用OrderedDict : 在练习6-4中, 你使用了一个标准字典来表示词汇表。 请使用OrderedDict 类来重写这个程序,
    # 并确认输出的顺序与你在字典中添加键—值对的顺序一致。
    from collections import OrderedDict
    favorite_languages = OrderedDict()
    favorite_languages['ken'] = 'C'
    favorite_languages['jack'] = 'PHP'
    favorite_languages['ben'] = 'JAVA'
    favorite_languages['phile'] = 'R'
    
    for k,v in favorite_languages.items():
    	print(k+'___'+v)
    
    # 9-14 骰子 : 模块random 包含以各种方式生成随机数的函数, 其中的randint() 返回一个位于指定范围内的整数,
    # 例如, 下面的代码返回一个1~6内的整数:
    # from random import randint
    # x = randint(1, 6)
    # 请创建一个Die 类, 它包含一个名为sides 的属性, 该属性的默认值为6。 编写一个名为roll_die() 的方法,
    # 它打印位于1和骰子面数之间的随机数。 创建一个6面的骰子, 再掷10次。 创建一个10面的骰子和一个20面的骰子, 并将它们都掷10次。
    # 9-14 骰子 : 模块random 包含以各种方式生成随机数的函数, 其中的randint() 返回一个位于指定范围内的整数,
    # 例如, 下面的代码返回一个1~6内的整数:
    # from random import randint
    # x = randint(1, 6)
    # 请创建一个Die 类, 它包含一个名为sides 的属性, 该属性的默认值为6。 编写一个名为roll_die() 的方法,
    # 它打印位于1和骰子面数之间的随机数。 创建一个6面的骰子, 再掷10次。 创建一个10面的骰子和一个20面的骰子, 并将它们都掷10次。
    
    from random import randint
    class Die():
    	def __init__(self):
    		self.sides = 6
    	def roll_die(self):
    		x = randint(1,6)
    		self.sides = x
    		print(self.sides)
    
    	def roll_die10(self):
    		x = randint(1, 10)
    		self.sides = x
    		print(self.sides)
    
    	def roll_die20(self):
    		self.sides = randint(1, 20)
    		print(self.sides)
    
    die = Die()
    print("----------6  sides-------------")
    for i in range(10):
    	die.roll_die()
    print("----------10 sides-------------")
    for i in range(10):
    	die.roll_die10()
    print("----------20 sides-------------")
    for i in range(10):
    	die.roll_die20()
    
    # 9-15 Python Module of the Week : 要了解Python标准库, 一个很不错的资源是网站Python Module of the Week。
    # 请访问http://pymotw.com/ 并查看其中的目录, 在其中找一个你感兴趣的模块进行探索, 或阅读模块collections 和random 的文档
    

    第十章

    文件与异常

    # 10-1 Python学习笔记 : 在文本编辑器中新建一个文件, 写几句话来总结一下你至此学到的Python知识,
    # 其中每一行都以“In Python you can”打头。 将这个文件命名为learning_python.txt,
    # 并将其存储到为完成本章练习而编写的程序所在的目录中。 编写一个程序, 它读取这个文件, 并将你所写的内容打印三次:
    # 第一次打印时读取整个文件; 第二次打印时遍历文件对象; 第三次打印时将各行存储在一个列表中, 再在with 代码块外打印它们。
    f_name = 'msg/learning_python.txt'
    with open(f_name) as f_name1:
    	print('_________"1"___________')
    	print(f_name1.read().rstrip())
    with open(f_name) as f_name1:
    	print('_________"2"___________')
    	for i in f_name1:
    		print(i.rstrip())
    with open(f_name) as f_name1:
    	print('_________"3"___________')
    	lines = f_name1.readlines()
    	for i in lines:
    		print(i.rstrip())
    
    # 10-2 C语言学习笔记 : 可使用方法replace() 将字符串中的特定单词都替换为另一个单词。 下面是一个简单的示例,
    # 演示了如何将句子中的'dog' 替换为'cat':
    # >>> message = "I really like dogs."
    # >>> message.replace('dog', 'cat')
    # 'I really like cats.'
    # 读取你刚创建的文件learning_python.txt中的每一行, 将其中的Python都替换为另一门语言的名称, 如C。 将修改后的各行都打印到屏幕上。
    f_name = 'msg/learning_Python.txt'
    with open(f_name) as f_name1:
    	lines = f_name1.readlines()
    for line in lines:
    	c = line.replace('Python','C++')
    	print(c)
    # 10-3 访客 : 编写一个程序, 提示用户输入其名字; 用户作出响应后, 将其名字写入到文件guest.txt中。
    name_info = 'msg/name_info_10_3.txt'
    with open(name_info, 'r+') as name_info1:
    	while True:
    		name_msg = input('请输入你的姓名:')
    		if name_msg == 'quit':
    			break
    		elif name_msg == 'cls':
    			name_info1.truncate()
    			break
    		else:
    			name_info1.write('我的名字叫:' + name_msg + '\n')
    
    # 10-4 访客名单 : 编写一个while 循环, 提示用户输入其名字。 用户输入其名字后, 在屏幕上打印一句问候语,
    # 并将一条访问记录添加到文件guest_book.txt中。 确保这个文件中的每条记录都独占一行。
    f_name = 'msg/name_info_10_4.txt'
    with open(f_name,'a') as f_name1:
    	while True:
    		msg10_4 = input('请输入你的姓名:')
    		if msg10_4 == 'quit':
    			break
    		elif msg10_4 == 'cls':
    			f_name1.truncate()
    			break
    		else:
    			print('你好!' + msg10_4)
    			f_name1.write('登录的人是: '+ msg10_4 + '\n')
    
    # 10-5 关于编程的调查 : 编写一个while 循环, 询问用户为何喜欢编程。 每当用户输入一个原因后, 都将其添加到一个存储所有原因的文件中。
    f_name = 'msg/name_info_10-5.txt'
    with open(f_name, 'a') as f_name1:
    	while True:
    		inp = input('请输入你喜欢编程的原因:(输入quit退出)')
    		if inp == 'quit':
    			break
    		elif inp == '':
    			print('请不要不写字!会浪费地方的亲!')
    		else:
    			f_name1.write(inp + '\n')
    
    # 10-6 加法运算 : 提示用户提供数值输入时, 常出现的一个问题是, 用户提供的是文本而不是数字。 在这种情况下, 当你尝试将输入转换为整数时, 将引
    # 发TypeError 异常。 编写一个程序, 提示用户输入两个数字, 再将它们相加并打印结果。
    # 在用户输入的任何一个值不是数字时都捕获TypeError 异常, 并打印一条友好的错误消息。 对你编写的程序进行测试: 先输入两个数字, 再输入一些文本而不是数字。
    try:
    	inp_msg = input('请输入数字:')
    	inp_msg_toInt = int(inp_msg)
    except ValueError:
    	print('只能输入整型')
    else:
    	print(inp_msg_toInt)
    
    # 10-7 加法计算器 : 将你为完成练习10-6而编写的代码放在一个while 循环中, 让用户犯错(输入的是文本而不是数字) 后能够继续输入数字。
    while True:
    	try:
    		inp_msg = input('请输入数字:')
    		inp_msg_toInt = int(inp_msg)
    	except ValueError:
    		print('只能输入整型')
    
    	else:
    		print(inp_msg_toInt)
    		break
    
    # 10-8 猫和狗 : 创建两个文件cats.txt和dogs.txt, 在第一个文件中至少存储三只猫的名字, 在第二个文件中至少存储三条狗的名字。 编写一个程序, 尝试读取这些文件,
    # 并将其内容打印到屏幕上。 将这些代码放在一个try-except 代码块中, 以便在文件不存在时捕获FileNotFound 错误, 并打印一条友好的消息。 将其中一个文件
    # 移到另一个地方, 并确认except 代码块中的代码将正确地执行。
    
    
    ##########读、写、清屏函数,不用try,直接造##################
    f_name_a = 'msg/cats.txt'
    f_name_b = 'msg/dogs.txt'
    
    def write(f_name_x,msg):
    	with open(f_name_x,'a') as f:
    		f.write(msg)
    def read(f_name_x):
    	with open(f_name_x) as f:
    		con = f.read()
    		print(con.rstrip())
    def clear(f_name_x):
    	with open(f_name_x,'w') as f:
    		f.truncate()
    clear(f_name_a)
    clear(f_name_b)
    write(f_name_a,'cat1\n')
    write(f_name_a,'cat2\n')
    write(f_name_a,'cat3\n')
    write(f_name_b,'dog1\n')
    write(f_name_b,'dog2\n')
    write(f_name_b,'dog3\n')
    read(f_name_a)
    read(f_name_b)
    
    ##########正确答案############
    def open_file(f_name):
    	try:
    		with open(f_name) as f_n:
    			con = f_n.read()
    	except FileNotFoundError:
    		print('404 not found!')
    	else:
    		print(con.rstrip())
    ur_list = [ 'msg/cats.txt', 'msg/dogs.txt']
    for i in ur_list:
    	open_file(i)
    
    # 10-9 沉默的猫和狗 : 修改你在练习10-8中编写的except 代码块, 让程序在文件不存在时一言不发。
    def open_file(f_name):
    	try:
    		with open(f_name) as f_n:
    			con = f_n.read()
    	except FileNotFoundError:
    		pass
    	else:
    		print(con.rstrip())
    ur_list = [ 'msg/cats.txt', 'msg/dogs.txt']
    for i in ur_list:
    	open_file(i)
    # 10-10 常见单词 : 访问项目Gutenberg(http://gutenberg.org/ ) , 并找一些你想分析的图书。 下载这些作品的文本文件或将浏览器中的原始文本复制到文本文件中。
    # 你可以使用方法count() 来确定特定的单词或短语在字符串中出现了多少次。 例如, 下面的代码计算'row' 在一个字符串中出现了多少次:
    # >>> line = "Row, row, row your boat"
    # >>> line.count('row')
    # 2 >
    # >> line.lower().count('row')
    # 3 请
    # 注意, 通过使用lower() 将字符串转换为小写, 可捕捉要查找的单词出现的所有次数, 而不管其大小写格式如何。
    # 编写一个程序, 它读取你在项目Gutenberg中获取的文件, 并计算单词'the' 在每个文件中分别出现了多少次。
    f_name = 'msg/ruby.txt'
    with open(f_name,encoding='utf-8') as f_n:
    	con = f_n.read()
    	a = con.count('the')
    	print(a)
    
    # 10-11 喜欢的数字 : 编写一个程序, 提示用户输入他喜欢的数字, 并使用json.dump() 将这个数字存储到文件中。 再编写一个程序, 从文件中读取这个值, 并打印
    # 消息“I know your favorite number! It's _____.”。
    import json
    f_name = 'msg/inp_10_11.json'
    msg_inp = input('请输入您喜欢的数字:')
    with open(f_name,'w') as fn:
    	json.dump(msg_inp,f_n)
    with open(f_name) as fn1:
    	c = json.load(f_n)
    	print('I know your favorite number! It\'s '+ c)
    
    # 10-12 记住喜欢的数字 : 将练习10-11中的两个程序合而为一。 如果存储了用户喜欢的数字, 就向用户显示它, 否则提示用户输入他喜欢的数字并将其存储到文件中。
    # 运行这个程序两次, 看看它是否像预期的那样工作。
    import json
    # 如果以前存储了用户名, 就加载它
    # 否则, 就提示用户输入用户名并存储它
    filename = 'msg/fav_numb.json'
    try:
    	with open(filename) as f_obj:
    		fav_num = json.load(f_obj)
    except FileNotFoundError:
    	fav_num = input("请输入你喜欢的数字:")
    	with open(filename, 'a') as f_obj:
    		json.dump(fav_num, f_obj)
    		print("你喜欢的数字:" + fav_num + "!")
    else:
    	print("你喜欢的数字:" + fav_num + "!")
    
    # 10-13 验证用户 : 最后一个remember_me.py版本假设用户要么已输入其用户名, 要么是首次运行该程序。 我们应修改这个程序, 以应对这样的情形: 当前和最后一次
    # 运行该程序的用户并非同一个人。
    # 为此, 在greet_user() 中打印欢迎用户回来的消息前, 先询问他用户名是否是对的。 如果不对, 就调用get_new_username() 让用户输入正确的用户名。
    import json
    
    def get_sorted_username():
    	"""如果存储了用户名,就获取它"""
    	filename = 'username.json'
    	try:
    		with open(filename) as f_obj:
    			username = json.load(f_obj)
    	except FileNotFoundError:
    		return None
    	else:
    		return username
    
    
    def get_new_username():
    	username = input("What is your name?")
    	filename = 'username.json'
    	with open(filename, 'w') as f_obj:
    		json.dump(username, f_obj)
    	return username
    
    
    def greet_user():
    	username = get_sorted_username()
    	if username:
    		result = input(username + "is right?")
    		if result == 'y':
    			print("Welcom back,", username, "!")
    		else:
    			username = get_new_username()
    			print("Welcom back,", username, "!")
    	else:
    		username = get_new_username()
    		print("We'll remember you when you come back,", username, "!")
    
    
    if __name__ == "__main__":
    	greet_user()
    
    

    第十一章

    习题11-1&11-2

    name_function.py

    #!/usr/bin/env	python
    #-*-coding:utf8-*-
    def format_name (first,last,middle=''):
    	""" 格式化一个姓名"""
    	
    	if middle:
    		fullname = first +' '+middle+' '+last
    	else:
    		fullname = first +' '+last
    	return fullname.title()
    def format_city (city,country,population=''):
    	""" 格式化一个国家和城市 """
    	if population:
    		city_country = city +','+country+' - population'+' '+population
    	else:                      
    		city_country = city +','+country
    	return city_country.title()

    test_name_function.py

    #!/usr/bin/env	python
    #-*-condig:utf8-*-
    import unittest
    from name_function import format_name
    from name_function import format_city
    class NameTestCase(unittest.TestCase):
    	""" 测试name_function.py """
    	def test_first_last_name (self):
    		""" 能够正确的处理像james hardon这样的姓名吗? """
    		formattedname = format_name('james','hardon')
    		self.assertEqual(formattedname,'James Hardon')
    	def test_first_middle_last_name (self):
    		""" 能够正确的处理像james hardon ding这样的姓名吗?"""
    		formattedname = format_name('james','hardon','ding')
    		self.assertEqual(formattedname,'James Ding Hardon')
    	def	test_city_country(self):
    		"""能够正确的处理像santiago,chile"""
    		formattedcity = format_city('santiago','chile')
    		self.assertEqual(formattedcity,'Santiago,Chile')
    	def test_city_country_population (self):
    		""" 能够处理带人口的城市吗? """
    		formattedcity = format_city('santiago','chile',population='500000')
    		self.assertEqual(formattedcity,'Santiago,Chile - Population 500000')
    unittest.main()

    习题11-3 

    Employee.py

    #!/usr/bin/env	python
    #-*-coding:utf8-*-
    class Employee:
    	""" 收集雇员信息 """
    	def __init__ (self,first,last,salary):
    		""" 雇员信息 """
    		self.first = first
    		self.last = last
    		self.salary = salary
    	def give_raise (self,addsalary=5000):
    		""" Function doc """
    		self.salary+=addsalary
    		

    test_Employee.py

    #!/usr/bin/env	python
    #-*-coding:utf8-*-
    import unittest
    from Employee import Employee
    class EmployeeTestCase(unittest.TestCase):
    	""" 测试不同的雇员信息 """
    
    	def setUp (self):
    		""" 初始化雇员信息 """
    		self.formatted_default = Employee('ding','yuanxue',1000)
    	def test_give_default_raise (self):
    		""" 默认加薪 """
    		self.formatted_default.give_raise()
    		self.assertEqual(self.formatted_default.salary,6000)
    	def test_give_coustom_raise (self):
    		"""特殊加薪"""
    		self.formatted_default.give_raise(8000)
    		self.assertEqual(self.formatted_default.salary,9000)	
    	
    unittest.main()
    

    第十二章

    番外1-pycharm安装pygame

    如果你是使用cmd-pip安装pygame,在pycharm中运行ver报错:AttributeError

    那么请往下看,本文将讲述如何在pycharm安装扩展包

    【第一步】:

    首先你要知道的是,pycharm是按项目安装扩展包的,即是你所建立的最外层的根目录,所以你在其他目录下添加了pygame,但如果在新建的项目中没有添加的话一样用不了。

    例如:我总共有三个文件夹,python36,t1,以及为十二章新建的alien_invasion,如果我在t1中添加了pygame,但是alien_invasion中没有的话,一样import不成功,所以要看清具体你要用哪个目录,即哪个项目

    第十六章

    番外2-No module named ‘pygal.i18n

    【第一步】:

    下载pygal_maps_world库,方法同番外1:http://blog.csdn.net/qq471011042/article/details/79172064

    【第二步】:

    将原书中使用的【from pygal.i18n import COUNTRIES】 修改成【from pygal_maps_world.i18n import COUNTRIES】

    【原因】:

    pygal.i18n 已经不存在了,现在已经更改成了 pygal_maps_world

    其中Available Package中还有一些其他的maps,比如西班牙、瑞士、法国等,一般也不会用到,下个world的就足够了

    《Python编程:从入门到实践》DEMO实例代码

    前言

    之前,项目后台基本都是使用 Java 的 SpringBoot 框架完成的, 

    而 Python 自去年到现在,一直以来,都是玩着学的,没有想过要应用到项目上。 

    但近来,科技园这边的吴老师,建议项目中使用 Python 的 Django 框架做后台,因其容易拓展、维护等,这是笨重的 Java 难以企及的。

    是时候认真对待 Python ,近来其也火得不行了~ 

    花了一天跳读了一本评价极好的书《Python编程从入门到实战》,以复习一下之前的 Python 基础,同时做了一些小 demo,同时借机对比了 C++、Java、JavaScript 等语言的基础,像读小说般轻松有趣,相当不错的一次体验,分享一下 。

    DEMO代码实例

    1.数据类型

    # 1、全体小写
    print('Itaem'.lower())
    
    # 2、全体大写
    print('Itaem'.upper())
    
    # 3、连接+
    print('Itaem'+'团队')
    
    # 4、转义:和当年 C++ 课设常用的‘UI’符号一样作用
    print('方向:\n\t大数据\n\t云计算\n\t人工智能')
    
    # 5、去空:lstrip 去左空、rstrip 去右空
    print('----'+'  ITAEM  '.strip()+'----')
    
    # 6、乘方:Python 特色
    print(2**3)
    
    # 7、浮点:和 C++ 一致
    print(2*0.3,3/2,3.0/2)
    
    # 8、字符+ 数字:和 Java 不一样,得先转换先
    print('ITAEM有'+str(15)+'个成员')
    
    # 9、求模:可以 %2 根据 1/0  定 奇偶
    print(5%2)

    2.列表

    # 1、列表 CRUD
    lang=['Java','JavaScript','Python']
    # ① 查
    # 第一个元素
    print(lang[0])
    # 最后一个元素,当len=0 时报错,负数即从末尾算起
    print(lang[-1])
    # ② 改
    lang[0]='Go'
    print(lang)
    # ③ 增
    lang.append('php')
    print(lang)
    # ④ 删
    del lang[0]
    print(lang)
    # ⑤ 删末、用之
    print(lang.pop())
    print(lang)
    # ⑥ 删值:只删除第一个指定的值
    lang.remove('JavaScript')
    print(lang)
    
    
    # 2、列表 组织
    lang=['Java','C','Python']
    # ① 永久排序:
    # Ⅰ、正:按字母
    lang.sort()
    print(lang)
    # Ⅱ、反:按字母
    lang.sort(reverse=True)
    print(lang)
    # ② 临时排序:只排序显示本次
    print(sorted(lang))
    # print(sorted(lang,reverse=True)) # 反
    print(lang)
    # ③ 倒排序
    lang.reverse()
    print(lang)
    # ④ 长度
    print(len(lang))
    
    # 3、列表 遍历
    lang=['Java','C','Python']
    # ① for in:和 ES 差不多,就省了( )
    for l in lang:
        print(l)
    # ② 数值
    for v in range(3,9):
        print(v)
    # ③ 数值->列表
    nums=list(range(3,9))
    print(nums)
    # ④ 统计数字列表
    # 最小
    print(min(nums))
    # 最大
    print(max(nums))
    # 平均
    print(sum(nums))
    # ⑤ 列表解析
    squares=[v**2 for v in range(3,9)]
    print(squares)
    # ⑥ 切片
    print(squares[:3])
    print(squares[0:3])
    print(squares[0:])

    3.元组

    ssh=('Spring','Struts2','Hibernate')
    print(ssh)
    print(ssh[0])
    # ① 元组不能修改
    # ssh[0]='xxx' # 报错
    # ② 遍历
    for v in ssh:
        print(v)

    4.字典

    # 1、创建:基本是 JSON 串、可嵌套
    program={
        'C++':'good',
        'Java':'well',
        'Python':['perfect', 'powerful'],
        'other':{
            'php':'easy',
            'C#':'windows'
        }
    }
    print(program)
    # 2、查
    print(program['Java'])
    # 3、增
    program['Go']='excellent'
    print(program)
    # 4、改
    program['C++']='common'
    print(program)
    # 5、删
    del program['C++']
    print(program)
    # 6、遍历key-value
    for k,v in program.items():
        print(k,v)
    # 7、遍历key、排序
    for k in sorted(program.keys()):
        print(k)
    # 8、遍历value:value 嵌套,排不了序
    for v in program.values():
        print(v)

    5.流程控制

    # 1、if-elif-else 判断
    SSM=['Spring','SpringMVC','MyBatis']
    # 列表部位空返回 True,否则 False
    if SSM:
        print('SSM不为空')
    elif 'Hibernate' not in SSM:
        print('Hibernate 不属于SSM系列')
    else:
        print('结束')
    
    # 2、input 输入:默认字符串
    # name=input('your name')
    # print('hello',name)
    # age=int(input('your age')) # 字符转数值
    # if 18==age:
    #     print('perfect!')
    
    # 3、while 循环:break 退出、continue 跳过
    i=0
    total=0
    while i<=100:
        i = i + 1
        if i==5:
            break
        if i==4:
            continue
        total=total+i
    print(total)

    6.函数

    import mymodule  as s
    
    # 1、定义函数:传参
    def sayHello(name,msg='excellent~'):
        print(name,msg)
        return 'that`s all'
    
    # 2、参数顺序
    sayHello('linhongcun!','well done~') # linhongcun! well done~
    sayHello(msg='good~',name='larger5!') # larger5! good~
    
    # 3、默认值:和 C++ 一致
    sayHello(name='ITAEM!') # ITAEM excellent~
    sayHello('ITAEM!') # ITAEM excellent~
    
    # 4、返回值
    print(sayHello('04008'))
    
    # 5、列表参数
    def update(list):
        list.append('55开')
    # ① 原件
    list=['Python','Java']
    update(list)
    print(list)
    # ② 副本:禁止修改列表
    update(list[:])
    print(list)
    
    #  6、不定参数
    def show(*lan):
        print(lan)
    show('Python')
    show('Python','JavaScript')

    7.类

    # 继承 object
    class People():
        def __init__(self,hobby='bb'):
            self.hobby=hobby
    
    class Student(People):
    
        # 初始化
        def __init__(self,hobby='bb',name='lvcha',age=15):
            super().__init__(hobby)
            self.name=name
            self.age=age
    
        # 类似 Java 的 toString
        def __str__(self):
            return str(self.hobby+self.name+str(self.age))
    
        # 定义类 内部函数
        def showMSG(self):
            print('your name:',self.name)
            print('your age',self.age)
    
    s1=Student('progra','linhongcun',21)
    print(s1.hobby)
    print(s1)

    8.文件

    # 1、传统打开、读取、关闭:和 C++ 基本一致
    file1=open('xxx.txt','r') #注意路径
    #全部输入,打成一行
    content=file1.readlines()
    print(len(content))
    print(content)
    file1.close()
    
    # 2、with 在不需要访问文件后将自动关闭 ✔
    with open('xxx.txt','r') as file2:
        print(file2.read())
    
    # 3、新建写入
    with open('zzz.txt','w') as file3:
        file3.write('I like programming\n')
        file3.write('I love you\n')
    
    # 4、追加
    with open('zzz.txt','a') as file4:
        file4.write('I can`t forget you\n')

    9.异常

    # 1、try-except-else
    try:
        # print(1/0)
        print(2/5)
    except ZeroDivisionError:
        print('fail by zero')
    else:
        print('ok')

    10.JSON

    import json
    
    # 列表
    language1=['Python','Java','JavaScript']
    # 字典
    language2={
        'Python':'powerful',
        'Java':'famous',
        'JavaScript':'developing'
    }
    # 元组
    language3=('C++','C','C#','Go')
    
    # 1、JSON 写入文件
    with open('yyy.txt','w') as file1:
        # json.dump(language1,file1)
        json.dump(language2,file1)
        # json.dump(language3,file1)
    
    # 2、读取 JSON 文件
    with open('yyy.txt','r') as file2:
        txt=json.load(file2)
        print(txt)

    11.pygame

    import pygame
    import sys
    
    def run():
    
        # 初始化屏幕
        pygame.init()
        # 窗口大小
        screen = pygame.display.set_mode((900, 600))
        # 窗口标题
        pygame.display.set_caption('吃鸡神坑助手')
        # 浅灰色
        bg_color=(230,230,230)
        image=pygame.image.load('numberOne.png')
        rect=screen.get_rect()
        while True:
            # 监视键盘、鼠标
            for event in pygame.event.get():
                if event.type==pygame.QUIT:
                    sys.exit()
            # 背景颜色
            screen.fill(bg_color)
            # 图片
            screen.blit(image,rect)
            # 显示窗口
            pygame.display.flip()
    
    # 运行
    run()

    12.模块化编程

    1.__init__.py

    def show():
        print('hello')

    2.test.py

    from CrashProject import other
    other.show()

     

    《Python编程:从入门到实践》第一章:起步

    搭建编程环境

    当前,有两个不同的Python版本:Python 2和较新的Python 3。每种编程语言都会随着新概念和新技术的推出而不断发展,Python的开发者也一直致力于丰富和强化其功能。大多数修改都是逐步进行的,你几乎意识不到,但如果你的系统安装的是Python 3,那么有些使用Python 2编写的代码可能无法正确地运行。

    如果你的系统安装了这两个版本,请使用Python 3;如果没有安装Python,请安装Python 3;如果只安装了Python 2,也可直接使用它来编写代码,但还是尽快升级到Python 3为好,因为这样你就能使用最新的Python版本了。

    在不同操作系统中搭建Python编程环境

    在不同操作系统中搭建Python编程环境

    解决安装问题

    如果你按前面的步骤做,应该能够成功地搭建编程环境。但如果你始终无法运行程序hello_world.py,可尝试如下几个解决方案。

    程序存在严重的错误时,Python将显示traceback。Python会仔细研究文件,试图找出其中的问题。trackback可能会提供线索,让你知道是什么问题让程序无法运行。

    离开计算机,先休息一会儿,再尝试。别忘了,在编程中,语法非常重要,即便是少一个冒号、引号不匹配或括号不匹配,都可能导致程序无法正确地运行。请再次阅读本

    章相关的内容,再次审视你所做的工作,看看能否找出错误。

    推倒重来。你也许不需要把一切都推倒重来,但将文件hello_world.py删除并重新创建它也许是合理的选择。

    让别人在你的计算机或其他计算机上按本章的步骤重做一遍,并仔细观察。你可能遗漏了一小步,而别人刚好没有遗漏。

    请懂Python的人帮忙。当你有这样的想法时,可能会发现在你认识的人当中就有人使用Python。

    本章的安装说明在网上也可以找到,其网址为https://www.nostarch.com/pythoncrash-course/ 。对你来说,在线版也许更合适。

    到网上寻求帮助。附录C提供了很多在线资源,如论坛或在线聊天网站,你可以前往这些地方,请求解决过你面临的问题的人提供解决方案。

    起步学习Python体会

    《Python编程:从入门到实践》这本书是由美国人埃里克·马瑟斯(Eric Mathes)所著,袁国忠翻译,出版于2016年,因此采用了Python3。

    我看过一遍,写的很不错,因此打算每天写下我学习这本书的收获和感触,特别是书上要做的习题的代码。

    这本书分成两个部分,第一部分介绍了Python编程的基础概念,包括列表、字典、if语句、类、文件和异常、代码测试等已经熟悉的内容,以及Matplotlib、Numpy和Pygal等强大的Python库和工具介绍。第二部分是三个项目,包含简单的Python2D游戏开发,利用数据生成交互式的信息图,已经创建简单的web应用。

    作者提示,第二部分的项目可以不按顺序,可以只完成某些。

    Python编程第一部分介绍

    序号代表第几章。

    • 1.起步序言
    • 2.介绍在计算机中安装Python,运行”Hello World”!
    • 3.介绍如何在变量中存储信息和使用文本和数字;
    • 4.介绍列表方法; 
    • 5.讲解使用if语句编写条件结构; 
    • 6.演示如何使用Python字典,将不同的信息关联起来; 
    • 7.介绍如何从用户哪里获得输入,让程序变成交互式的,还将学习While循环; 
    • 8.介绍编写函数; 
    • 9.介绍类,它能够让你模拟实物,让你的代码能够表示任何真实的和抽象的; 
    • 10.介绍使用文件,如何处理错误以免程序意外崩溃,以及处理异常,让你未雨绸缪; 
    • 11.为代码编写测试,要想脱离初级程序员,跻身中级程序员的行列,测试代码是我们必须掌握的技能。

    不难发现,很多都是我们在《笨办法学Python》或《简明Python教程》中已经了解的东西。因此值得注意的地方,就是Python3与Python2的不同,而我更新博客的重点就在于习题。

    18天学习《python编程:从入门到实践》心得笔记

    安装、变量和简单数据类型 

    安装以及环境搭建

    python的安装和环境变量的配置通过百度查询即可解决,这里不作赘述。

    IDE的选择:在前几章学习语法这个阶段,我选择使用EditPlus打造一个Python IDE这个。

    PS:如果需要在 Win10下同时安装python3和python2并解决pip共存问题可以参考这个。

    第一次运行hello world!

    首先创建第一个python脚本文件first.py,代码如下:

    #coding=utf8
    print('hello world!')

    EditPlusIDE运行(ctrl+1):

    hello world!

    终端命令行运行:

    >C:\Users\Desktop\学习笔记>python3 first.py
    hello world!

    变量和简单的数据类型

    变量

    和C\C++一样,值可以变化,可以用其存储任何东西。(相当于一个容器) 变量的命名:

    首字符必须是字母(大写或小写)或者一下下划线('_')

    名称的其他部分可以由字母(大写或小写)、下划线(‘ _ ’)或数字(0-9)组成

    对大小写敏感

    有效变量名称的例子有 k、__my_num、name_1 和 a4b5_c6

    无效标识符名称的例子有 2board、this is me和my-num

    变量的赋值: 变量名=值,比如变量名为me,值为god,赋值方法如下:

    me = 'god'
    print(me)
    me = 'home'
    print(me)
    
    运行结果:
    god
    home

    字符串

    其是由数字、字母、下划线组成的一串字符。

    PS:字符串是不可变的,一旦创造了一个字符串,就不能再改变它。

    • 【单引号(')】和【双引号(")】两者使用都是相同的,即'hello' 等同 "hello"
    • 【三引号('''或""")】可以表示一个多行的字符串,在三引号中可以自由的使用单引号和双引号
    • 【转义符】可以用 \' 来指示单引号——注意这个反斜杠,即'What\'s your phone number?'。另一个表示这个特别的字符串的方法是"What's your phone number?",即用双引号。在一个字符串中,行末的单独一个反斜杠表示字符串在下一行继续,而不是开始一个新的行。
    • 【自然字符串】前缀r或R表示“自然字符串”,转义失去意义,所见即所得。
    • 【Unicode字符串】加前缀u或U, 如 u"this is an unicode string"

    字符串的修改 + title() 将字符串的首字母大写 + upper() 将字符串全部大写 + lower() 将字符串全部小写

    me = 'goD'
    print(me.title())
    print(me.upper())
    print(me.lower())
    
    运行结果:
    GoD
    GOD
    god
    • 合并字符串使用加号(+)
    one = 'im'
    two = 'god'
    print(one + ' ' + two)
    
    运行结果:
    im god
    • 使用制表符(\t)或换行符(\n)添加空白
    • 删除字符串右端空白 rstrip() ,删除字符串左端空白 lstrip(),删除字符串两端空白 strip()
    one = ' god '
    one.rstrip()
    one.lstrip()
    one.strip()
    
    运行结果:
    ' god'
    'god '
    'god'

    数字

    4种类型的数:整数、长整数、浮点数和负数。主要运算有加(+)、减(-)、乘(*)、除(/)。另外,乘方使用两个乘号表示,比如 3**2 ,即3的平方。

    • 整数int:6、-1、070、-0520、-0x350、0x59等。
    • 长整数long:5146561L、0132L、-0x19423L。长整型也可以使用小写L,但是还是建议大写L,避免与数字"1"混淆。Python使用"L"来显示长整型。
    • 浮点数float:0.0、14.50、44.8e+12、60.1E-12等。
    • 复数complex:3.5j、4e+5J等。用a + bj,或者complex(a,b)表示, 复数的实部a和虚部b都是浮点型。

    PS:使用 str()可以将非字符串值表示为字符串。

    注释

    注释用井号#。井号后面的都会被python忽略,通常用来标注解释代码。

    列表以及其操作

    列表简介

    列表是是处理一组有序项目的数据结构,即可以在一个列表中存储一个序列的项目。列表中的元素包括在方括号([])中,每个元素之间用逗号分割。列表是可变的数据类型,可以添加、删除或是搜索列表中的元素。

    访问元素

    访问列表元素可以通过索引+方括号的形式,记住,索引从0而不是1开始!。

    shoplist = ['apple', 'mango', 'carrot', 'banana']
    print(shoplist)
    print(shoplist[0].title())
    print('i want a' + ' ' + shoplist[0])
    
    运行结果:
    ['apple', 'mango', 'carrot', 'banana']
    Apple
    i want a apple

    修改或添加元素

    修改元素可以通过直接赋值的方法。

    • append() :将元素附加到列表末尾。
    • insert() :在列表中指定位置添加新元素。
    • del :删除列表中指定位置元素。
    • pop():移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。
    • remove():删除列表中第一个指定值的元素。
    shoplist = ['apple', 'mango', 'carrot', 'banana']
    shoplist.append('duck')
    print(shoplist)
    shoplist.insert(0, 'chick')
    print(shoplist)
    del shoplist[1]
    print(shoplist)
    temp1 = shoplist.pop(0)
    print(temp1)
    print(shoplist)
    shoplist.remove('banana')
    print(shoplist)
    
    运行结果:
    ['apple', 'mango', 'carrot', 'banana', 'duck']
    [‘chick’, 'apple', 'mango', 'carrot', 'banana', 'duck']
    [‘chick’, 'mango', 'carrot', 'banana', 'duck']
    chick
    ['mango', 'carrot', 'banana', 'duck']
    ['mango', 'carrot', 'duck']

    组织列表

    • sort():对列表进行永久性排序。默认按照字母顺序排列,相反顺序的话可以传递参数reverse=True
    • sorted():对列表进行临时排序,不改变原本列表。
    • reverse():反转列表元素排序。
    • len() :获取列表长度。
    shoplist = ['apple', 'mango', 'carrot', 'banana']
    shoplist.sort(reverse=True)
    print(shoplist)
    shoplist = ['apple', 'mango', 'carrot', 'banana']
    print(sorted(shoplist))
    print(shoplist)
    shoplist.reverse()
    print(shoplist)
    len(shoplist)
    
    运行结果:
    ['mango', 'carrot', 'banana', 'apple']
    ['apple', 'banana', 'carrot', 'mango']
    ['apple', 'mango', 'carrot', 'banana']
    ['banana', 'carrot', 'mango', 'apple']
    4

    第四章 操作列表

    遍历列表

    利用for循环可以快速遍历列表,不要忘记它的冒号!

    shoplist = ['apple', 'mango', 'carrot', 'banana']
    for shop in shoplist:
        print('i want a ' + shop.title())
    
    运行结果:
    i want a Apple
    i want a Mango
    i want a Carrot
    i want a Banana

    缩进

    行首的空白(空格和制表符)决定行的缩进层次,同一层次的语句必须有相同的缩进。

    不要混合使用制表符和空格来缩进,在每个缩进层次要么使用单个制表符或 两个或四个空格。

    数值列表

    • range():生成指定步长的左闭右开区间的一系列数字。默认步长为1。
    • list() :将参数转化为列表。
    • min() :找出数字列表最小值。
    • max() :找出数字列表最大值。
    • sum() :求数字列表所有值相加的总和
    nums = list(range(1,5))
    for num in nums:
        print(num)
    print(min(nums))
    print(max(nums))
    print(sum(nums))
    
    运行结果:
    1
    2
    3
    4
    1
    4
    10

    表的一部分——切片

    • 创建切片时,要指定切片的第一个元素和最后一个元素的索引,和range()一样,区间为左闭右开。
    • 如果没有指定第一个索引,切片将从列表开头开始。同理,如果没有指定最后一个索引,切片将直到列表末尾结束。负数索引可以输出离列表末尾相应距离的元素。
    • 切片也可以作为列表遍历。
    • 同时省略起始和终止索引可以穿件包含整个列表的切片,相当于复制列表。
    nums = list(range(0,11))
    print(nums[0:5])
    print(nums[:6])
    Nums = nums[:]
    print(Nums)
    
    运行结果:
    [0, 1, 2, 3, 4]
    [0, 1, 2, 3, 4, 5]
    [2, 3, 4, 5, 6, 7, 8, 9, 10]
    [8, 9, 10]
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    元组

    元组不可以修改,使用圆括号标识。元组也可以用循环进行遍历。我们还能给元组的变量赋值。

    nums = (1, 2)
    print(nums)
    nums = (4, 2)
    for num in nums:
        print(num)
    运行结果:
    (1, 2)
    4
    2

    if 语句

    第五章 if 语句

    if语句用来检验一个条件, 如果条件为真,运行一块语句(if-块),否则处理另外一块语句(else-块)。else从句是可选的。注意这里使用了缩进层次来告诉Python每个语句分别属于哪一个块。if语句判断条件无括号,在结尾处包含一个冒号!

    下面是一个简单的示例

    nums = ['one', 'two', 'three', 'four', 'five']
    for num in nums:
        if num == 'two':
            print('yes')
        else:
            print('no')
    
    运行结果:
    no
    yes
    no
    no
    no

    条件测试

    判断两个值

    python使用两个等号(==)来检查两个变量的值是否相等。注意,检查是否相等时区分大小写。如果相等返回True,否则返回False。

    而惊叹号和等号(!=)用来判断两个值是否不相等(其中惊叹号表示“不”)。如果不相等返回True,否则返回False。

    age = 18
    print(age == 18)
    print(age != 18)
    
    运行结果:
    True
    False

    比较数字

    python还可以用小于<,大于>,小于等于<=,大于等于>=,来进行数学比较。

    age = 18
    print(age < 20)
    print(age > 20)
    print(age >= 18)
    print(age <= 17)
    
    运行结果:
    True
    False
    True
    False

    检查多个条件

    and :只有两边的条件都为真,整个表达式才为真。

    or :至少有一边条件为真,整个表达式才为真。

    age = 18
    print(age < 20 and age > 17)
    print(age < 20 or age > 21)
    
    运行结果:
    True
    True

    在列表检查特定值

    in :判断特定值是否在列表

    not in :判断特定值是否不在列表

    nums = ['one', 'two', 'three', 'four', 'five']
    num1 = 'one'
    num2 = 'six'
    print(num1 in nums)
    print(num2 not in nums)
    
    运行结果:
    True
    True

    布尔表达式

    条件测试的别名,布尔表达式结果要么为True,要么为False。布尔值通常用于记录条件,如游戏是否正在运行或者用户是否为超级用户。

    if 语句

    if语句除了单独一个if语句,if-else语句,还有if-elif-else语句和if-elif语句。下面分别给出例子。

    #单个if语句:
    if num in nums:
        print('yes')
    
    #if-else语句:
    if num in nums:
        print('yes')
    else:
        print('no')
    
    #if-elif-else语句:
    if num in nums:
        print('yes')
    elif num in cars:
        print('???')
    else:
        print('no')

    python还可以根据需要使用任意个elif代码块、测试多个条件。比如:

    money = 20
    if money < 10:
        print('10')
    elif money < 20:
        print('20')
    elif money < 30:
        print('30')
    else:
        print('inf')
    
    money = 20
    if money < 10:
        print('10')
    if money < 20:
        print('20')
    if money < 30:
        print('30')

    使用if语句处理列表,我们可以判断特定值是否在列表中、判断列表是否为空等等,从而做出相应的动作。

    第五章练习答案代码

    习题5-11

    num_list = range(1, 11)
    for i in num_list:
        if i == 1:
            print(str(i) + 'st')
        elif i == 2:
            print(str(i) + 'nd')
        elif i == 3:
            print(str(i) + 'rd')
        else:
            print(str(i) + 'th')

    字典

    第六章 字典

    字典类似于通过联系人名字查找联系人电话号码的电话本,即把键(名字)和值(电话号码)联系在一起。注意,键必须是唯一的。并且python只能使用不可变的对象(比如字符串)来作为字典的键,但是可以将不可变或可变的对象作为字典的值。举一个简单的字典例子。

    alien = {'color': 'green', 'points': 5}

    键值对在字典中的标记为:d = {key1 : value1, key2 : value2 }。注意键/值对用冒号分割,而各个对用逗号分割,所有这些都包括在花括号中。字典中的键/值对是没有顺序的。如果想要一个指定的顺序,那么在使用前自行排序。

    使用字典

    访问字典中的值

    依次指定字典名和放在方括号内的键,如下所示:

    alien = {'color': 'green', 'points': 5}
    print(alien_0['color'])
    
    运行结果:
    green

    创建字典并修改字典中的值

    创建空字典时使用一对空的花括号定义一个字典,再分行添加各个键值对。

    修改字典的值可以指定字典名、键以及新的赋值。

    alien = {}
    alien['x_position'] = 0
    alien['y_position'] = 25
    print(alien)
    alien['x_position'] = 25
    print(alien)
    
    运行结果:
    {'x_position': 0, 'y_position': 25}
    {'x_position': 25, 'y_position': 25}

    添加/删除键值对

    字典是一种动态结构。

    添加键值对时,依次指定字典名、方括号和键、所赋的值。

    删除键值对时,可使用del语句,指定字典名和要删除的键。

    alien = {'color': 'green', 'points': 5}
    print(alien)
    alien['x_position'] = 0
    alien['y_position'] = 25
    print(alien)
    del alien['color']
    print(alien)
    
    运行结果:
    {'color': 'green', 'points': 5}
    {'color': 'green', 'points': 5, 'y_position': 25, 'x_position': 0}
    {'points': 5, 'y_position': 25, 'x_position': 0}

    遍历字典

    遍历所有的键值对

    user = {
        'username': 'efermi',#前面有四个空格的缩进,下同
        'first': 'enrico',
        'last': 'fermi',
        }
    for key, value in user.items()
        print("\nKey: " + key)
        print("Value: " + value)
    
    运行结果:
    Key: last
    Value: fermi
    
    Key: first
    Value: enrico
    
    Key: username
    Value: efermi

    由上可知,在字典的遍历中,可以声明两个变量分别存储键值对中的键和值。字典的方法item()返回一个键值对列表。注意,在遍历字典的时候,键值对的返回顺序与存储顺序不同。python只关系键和值之间的对应关系。

    遍历字典中的所有键/值

    使用方法keys()可以遍历字典中的所有键。或者不使用方法,默认遍历字典中的键。

    使用方法values()可以遍历字典中的所有值。返回一个值列表。

    favorite_languages = {
        'jen': 'python',
        'sarah': 'c',
        'edward': 'ruby',
        'phil': 'python',
        }
    for name in favorite_languages.keys():
        print(name.title())
    for language in favorite_languages.values():
        print(language.title())
    
    运行结果:
    Jen
    Sarah
    Edward
    Phil
    Python
    C
    Ruby
    Python

    或者不使用方法,默认遍历字典中的键。即for name in favorite_languages.keys():效果等同for name in favorite_languages:。

    若需按顺序遍历,只需使用sorted()。

    嵌套

    将一系列字典存储在列表中,或者将列表作为值存储在字典中,称为嵌套。

    字典列表

    将一系列字典存储在列表中。

    alien_0 = {'color': 'green', 'points': 5}
    alien_1 = {'color': 'yellow', 'points': 10}
    alien_2 = {'color': 'red', 'points': 15}
    aliens = [alien_0, alien_1, alien_2]
    for alien in aliens:
        print(alien)
    
    运行结果:
    {'color': 'green', 'points': 5}
    {'color': 'yellow', 'points': 10}
    {'color': 'red', 'points': 15}

    列表字典

    将字典存储在列表中。

    lili = {
        'name': 'lili',
        'phonenum': ['123', '456'],
        }
    print("lili's name is " + lili['name'] + " and her phonenum is ")
    for num in lili['phonenum']:
        print("\t" + num)
    
    运行结果:
    lili's name is lili and her phonenum is 
        123
        456

    字典中嵌套字典

    存储网站用户信息可以在字典中嵌套字典,例如:

    users = {
        'aeinstein': {
            'first': 'albert',
            'last': 'einstein',
            'location': 'princeton',
            },
        'mcurie': {
            'first': 'marie',
            'last': 'curie',
            'location': 'paris',
            },
        }
    for username, user_info in users.items():
        print("\nUsername: " + username)
        full_name = user_info['first'] + " " + user_info['last']
        location = user_info['location']
        print("\tFull name: " + full_name.title())
        print("\tLocation: " + location.title())
    
    运行结果:
    Username: aeinstein
        Full name: Albert Einstein
        Location: Princeton
    
    Username: mcurie
        Full name: Marie Curie
        Location: Paris

    第六章试题以及答案:http://www.xz577.com/j/129.html

    用户输入和while循环

    第七章 用户输入和while循环

    函数input()

    input() :暂停程序,等待用户输入文本并把文本存储在指定变量中。并接受一个参数,即要向用户显示的提示或说明。

    int() :使用input()函数时,输入的文本会被当成字符串,所以可以用这个函数将其化为int型。

    % :求模运算符。讲两个数相除并返回余数。

    下面举个例子:

    message = input("Tell me your name:")
    print(message) 
    message = input("Tell me your years:")
    if int(message) >= 18:
        print('wow')
        print(int(message) % 6)
    
    运行结果:
    Tell me your name:mike
    mike
    Tell me your years:19
    wow
    1

    while循环

    循环简介

    while循环不断运行,直到指定的条件不满足位置。例如:

    current_number = 1
    while current_number <= 5:
        print(current_number)
        current_number += 1 
    
    运行结果:
    1
    2
    3
    4
    5

    还可以让用户选择何时退出,只要把循环的条件由current_number <= 5改为message != 'quit',然后在循环语句里面添加message = input(prompt),即:

    current_number = 1
    while message != 'quit':
        message = input('Enter 'quit' to end the program or go on:')
        print(current_number)
        current_number += 1 
    
    运行结果:
    Enter 'quit' to end the program or go on: 
    1
    Enter 'quit' to end the program or go on: 
    2
    Enter 'quit' to end the program or go on:quit

    这时候我们提示了一条消息:要么输入quit来结束程序,要么继续运行。当然我们还可以设置标志来决定循环的条件,比如利用布尔值True或者False。

    退出循环

    break :不管条件测试结果如何,立即退出循环,不在运行循环中余下代码。

    prompt = "\nPlease enter a city you have visited:"
    prompt += "\n(Enter 'quit' when you are finished.) "
    while True:
        city = input(prompt)
        if city == 'quit':
            break 
    
    运行结果:
    Please enter a city you have visited:
    (Enter 'quit' when you are finished.) China
    I'd love to go to China!
    
    Please enter a city you have visited:
    (Enter 'quit' when you are finished.) San Francisco
    I'd love to go to San Francisco!
    
    Please enter a city you have visited:
    (Enter 'quit' when you are finished.) quit 

    continue :跳出此次循环,即返回到循环开头,并判断循环条件是否满足来决定是否执行循环。

    current_number = 0
    while current_number < 10:
        current_number += 1
        if current_number % 2 == 0:
            continue
        print(current_number) 
    
    运行结果:
    1
    3
    5
    7
    9

    使用循环处理列表和字典

    for循环中不应修改列表,因为for循环中修改列表之后,python的遍历会出现问题。而要想遍历列表并修改,可以用while循环。下面举几个例子。

    在列表之间移动元素

    #创建待验证用户列表和一个已验证用户列表
    unconfirmed_ids = ['mike', 'lili', 'ace']
    confirmed_ids = [] 
    #验证每个用户并把其移动到已验证用户列表
    while unconfirmed_ids:
        current_id = unconfirmed_ids.pop()
        print("Verifying id: " + current_id.title())
        confirmed_ids.append(current_id)
    #显示所有已验证id
    print("\nThe following ids have been confirmed:")
    for confirmed_id in confirmed_ids:
        print(confirmed_id.title()) 
    
    运行结果:
    Ace
    Lili
    Mike

    删除包含特定值的所有列表元素

    nums = ['1', '3', '5', '1', '6', '1', '7']
    print(nums)
    while '1' in nums:
        pets.remove('1')
    print(nums)
    
    运行结果:
    ['3', '5', '6', '7']

    使用用户输入来填充字典

    responses = {}
    #设置一个标志Lj指出调查是否继续
    polling_active = True
    while polling_active:
        #提示输入被调查者的名字和回答
        name = input("\nWhat is your name? ")
        response = input("Which mountain would you like to climb someday? ")
    
        #将答卷存储在字典中
        responses[name] = response
    
        #看看是否有人要参与调查
        repeat = input("Would you like to let another person respond? (yes/ no) ")
        if repeat == 'no':
            polling_active = False
    
    #调查结束显示结果
    print("\n--- Poll Results ---")
    for name, response in responses.items():
        print(name + " would like to climb " + response + ".") 
    
    运行结果:
    What is your name? Eric
    Which mountain would you like to climb someday? Denali
    Would you like to let another person respond? (yes/ no) yes
    
    What is your name? Lynn
    Which mountain would you like to climb someday? Devil's Thumb
    Would you like to let another person respond? (yes/ no) no
    
    --- Poll Results ---
    Lynn would like to climb Devil's Thumb.
    Eric would like to climb Denali. 

    第七章练习答案代码 :http://www.xz577.com/j/129.html

    函数

    第八章 函数

    定义函数

    举个简单的例子

    def greet_user(username):
        """先是简单的问候语"""
        print("Hello! " + username.title() + "!")
    greet_user("mike")
    
    运行结果:
    Hello! Mike!

    由上所示,关键字def定义一个函数,后面跟着函数名以及用来输入参数的括号,定义以冒号结束,而print("Hello!")为其函数体。
    调用函数时,则依次指定函数名以及用括号括起的必要信息,如参数等。

    实参和形参

    在函数greet_user(username)的定义中,变量username是一个形参。形参是一个函数完成其工作所需的一个参数。
    在代码greet_user("mike")中,值"mike"是一个实参。实参是调用函数时传递给函数的参数。

    调用greet_user("mike")函数时,我们将实参"mike"传递给了函数greet_user(),这个值被存储在形参username。

    传递实参

    位置实参:调用函数时,必须将函数调用中的每个实参都采用基于实参顺序的方式关联到函数定义中的一个形参中。
    关键字实参:调用函数时,直接传递给函数名称-值对。此时不用考虑实参顺序。

    def printID(ID, sname):
        print(ID + ":" + sname)
    printID('14', 'mike') #位置实参
    printID(sname='lili', ID='15') #关键字实参
    
    运行结果:
    14:mike
    15:lili

    默认值:给形参指定默认值。在调用函数中给形参提供了实参时,则用指定的实参值。如果没有提供则使用形参默认值。

    PS:使用默认值时,在形参列表中必须Ian列出没有默认值的形参,再列出有默认值的实参。才能让python正确解读位置实参。

    def printID(ID, sname = 'mike'):
        print(ID + ":" + sname)
    printID('14')  #<-here
    printID(sname='lili', ID='15')
    
    运行结果:
    14:mike
    15:lili

    返回值

    返回简单值

    def get_formatted_name(first_name, last_name):
        full_name = first_name + ' ' + last_name
        return full_name.title()
    musician = get_formatted_name('jimi', 'hendrix')
    print(musician)
    
    运行结果:
    Jimi Hendrix

    我们可以使用return语句在函数中返回值。

    让实参可选

    def get_formatted_name(first_name, last_name, middle_name=''):
        if middle_name:
            full_name = first_name + ' ' + middle_name + ' ' + last_name
        else:
            full_name = first_name + ' ' + last_name
        return full_name.title()
    musician = get_formatted_name('jimi', 'hendrix')
    print(musician)
    musician = get_formatted_name('john', 'hooker', 'lee')
    print(musician)
    
    运行结果:
    Jimi Hendrix
    John Lee Hooker

    如上所示,使用if条件语句,并将实参作为判断条件即可让实参可选。

    传递列表

    将列表传递给函数后,不仅可以遍历列表,还能修改列表,并且这种修改时永久性的。

    如果要禁止函数修改列表,可以传递列表的副本,比如:function_name(list_name[:])。

    传递任意数量的实参

    def make_pizza(*toppings):
        print(toppings)
    make_pizza('pepperoni')
    make_pizza('mushrooms', 'green peppers', 'extra cheese')
    
    运行结果:
    ('pepperoni',)
    ('mushrooms', 'green peppers', 'extra cheese')

    形参名*toppings中的星号表示创建一个名为 toppings 的空元组,并把所有收到的值封装在这个元组中。我们还可以使用循环语句将所有值打印出来。

    结合使用位置实参和任意数量实参

    如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量的实参的形参放在最后。这样,python会先匹配位置实参和关键字实参,并把余下的实参都收集到最后一个形参中。

    def make_pizza(size, *toppings):
        print("\nMaking a " + str(size) + "-inch pizza with the following toppings:")
        for topping in toppings:
            print("- " + topping)
    make_pizza(16, 'pepperoni')
    make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
    
    运行结果:
    Making a 16-inch pizza with the following toppings:
    - pepperoni
    
    Making a 12-inch pizza with the following toppings:
    - mushrooms
    - green peppers
    - extra cheese

    使用任意数量的关键字实参

    def build_profile(first, last, **user_info):
        profile = {}
        profile['first_name'] = first
        profile['last_name'] = last
        for key, value in user_info.items():
            profile[key] = value
        return profile
    
    user_profile = build_profile('albert', 'einstein',location='princeton',field='physics')
    print(user_profile)

    形参**user_info中的两个星号表示创建一个名为user_info的空字典,并将收到的所有名称-值对都封装到这个字典中。

    将函数存储在模块中

    导入整个模块

    模块时扩展名为.py的文件,包含要导入到程序中的代码。使用import语句可以将模块导入。

    #pizza.py
    def make_pizza(size, *toppings):
        print("\nMaking a " + str(size) +"-inch pizza with the following toppings:")
        for topping in toppings:
            print("- " + topping)
    
    #making_pizzas.py
    import pizza
    pizza.make_pizza(16, 'pepperoni')
    pizza.make_pizza(12,'mushrooms', 'green peppers', 'extra cheese')
    
    运行结果:
    Making a 16-inch pizza with the following toppings:
    - pepperoni
    Making a 12-inch pizza with the following toppings:
    - mushrooms
    - green peppers
    - extra cheese

    如果导入的是整个模块,调用的时候就要指定模块名:module_name.function_name()。

    导入特定的函数

    导入模块中特定的函数,可以使用以下方法:from module_name import function_name

    用逗号分隔函数名,可导入任意数量函数:from module_name import function_0, function_1, function_2

    这时候调用函数,无需使用句点,直接指定函数名,因为我们在import语句中显示导入了函数。

    使用as给函数指定别名

    为了防止冲突,或者函数名太长,可指定一个独一无二的别名,函数的另外一个名称,通用语法为:from module_name import function_name as fn

    导入模块中的所有函数

    使用星号(*)运算符可以导入模块中的所有函数,此时不用使用句点来调用函数。不过最好不要这样。语法为:from module_name import *。

    第八章练习答案代码:http://www.xz577.com/j/129.html

    第九章

    面向对象编程时,都会遇到一个概念,类,python也有这个概念,下面我们通过代码来深入了解下。

    创建和使用类

    class Dog():
        def __init__(self, name, age):
            self.name = name
            self.age = age
        def sit(self):
            print(self.name.title() + " is now sitting.")
        def roll_over(self):
            print(self.name.title() + " rolled over!")
    
    my_dog = Dog('willie', 6)
    print("My dog's name is " + my_dog.name.title() + ".")
    print("My dog is " + str(my_dog.age) + " years old.")
    
    运行结果:
    My dog's name is Willie.
    My dog is 6 years old.

    class关键字:来定义一个类。类名通常首字母为大写。
    __init__方法:特殊方法,每当实例类的时候都会运行。其中的形参self必不可少,而且必须位于最前面。
    self形参:类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,但是在调用这个方法的时候用不为这个参数赋值,Python会提供这个值。这个特别的变量指对象本身。

    实例的方法是指定类名以及需要传入的实参。
    要访问实例的属性或者调用方法,可使用句点表示法。

    使用类和实例

    class Car():
        def __init__(self, make, model, year):
            self.make = make
            self.model = model
            self.year = year
            self.odometer_reading = 0 #<- here
    
        def get_descriptive_name(self):
            long_name = str(self.year) + ' ' + self.make + ' ' + self.model
            return long_name.title()
    
        def read_odometer(self):
            print("This car has " + str(self.odometer_reading) + " miles on it.")
    
    my_new_car = Car('audi', 'a4', 2016)
    print(my_new_car.get_descriptive_name())
    my_new_car.read_odometer()
    
    运行结果:
    2016 Audi A4

    可以看到,我们给Car类的属性指定了默认值self.odometer_reading = 0。如果要修改它,我们可以通过实例直接访问它并修改,比如:my_new_car.odometer_reading = 23。或者通过方法修改属性的值。或者通过方法对属性的值进行递增。

    class Car():
        --snip--
        #通过方法修改属性的值
        def update_odometer(self, mileage):
            self.odometer_reading = mileage
    
        #通过方法对属性的值进行递增
        def increment_odometer(self, miles):
            self.odometer_reading += miles

    继承

    一个类继承另一个类时,他将自动获得另一个类的所有属性和方法;原有的类称为父类,新类称为子类。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。
    现在我们有一个Car类如下

    class Car():
        def __init__(self, make, model, year):
            self.make = make
            self.model = model
            self.year = year
            self.odometer_reading = 0 #<- here
    
        def get_descriptive_name(self):
            long_name = str(self.year) + ' ' + self.make + ' ' + self.model
            return long_name.title()
    
        def read_odometer(self):
            print("This car has " + str(self.odometer_reading) + " miles on it.")
    
        def update_odometer(self, mileage):
            self.odometer_reading = mileage
    
        def increment_odometer(self, miles):
            self.odometer_reading += miles

    创建子类实例时,python首先给父类所有属性赋值。

    接下来我们创建新类EleCar

    class Car():
        --snip--
    
    class ElectricCar(Car):
        def __init__(self, make, model, year):
            super().__init__(make, model, year)
    
    my_tesla = ElectricCar('tesla', 'model s', 2016)
    print(my_tesla.get_descriptive_name())
    
    运行结果:
    2016 Tesla Model S

    首先父类必须位于子类前面。

    super()是一个特殊函数,将父类和子类关联起来。使得可调用子类的父类的方法__init__(),让子类包父类的所有属性。

    给子类定义属性和方法没有任何限制,比如:

    class Car():
        --snip--
    
    class ElectricCar(Car):
        def __init__(self, make, model, year):
            super().__init__(make, model, year)
            self.battery_size = 70
    
        def describe_battery(self):
            print("This car has a " + str(self.battery_size) + "-kWh battery.")
    
    my_tesla = ElectricCar('tesla', 'model s', 2016)
    print(my_tesla.get_descriptive_name())
    my_tesla.describe_battery()
    
    运行结果:
    2016 Tesla Model S
    This car has a 70-kWh battery.

    如果需要重写父类的方法,只需定义一个与重写的父类方法同名的方法即可。
    python还可以使用其他类的实例作为自己类的属性。

    导入类

    类似函数,类也可以保存为.py文件形成模块从而进行导入。

    导入单个类:

    from model_name import class_name

    导入一个模块的多个类:

    from model_name import class_name1, class_name2

    导入一个模块所有类:

    from model_name import *

    导入整个模块:

    import model_name

    还可以在一个模块中导入另一个模块

    python标准库

    其是一组模块。模块collections中有一个类OrderedDict。字典的键值对没有顺序,但是这个类几乎和字典相同,区别只在于记录了键值对的顺序。

    from collections import OrderedDict
    
    favorite_languages = OrderedDict()
    
    favorite_languages['jen'] = 'python'
    favorite_languages['sarah'] = 'c'
    favorite_languages['edward'] = 'ruby'
    favorite_languages['phil'] = 'python'
    
    for name, language in favorite_languages.items():
        print(name.title() + "'s favorite language is " +
    language.title() + ".")
    
    运行结果:
    Jen's favorite language is Python.
    Sarah's favorite language is C.
    Edward's favorite language is Ruby.
    Phil's favorite language is Python.

    第九章练习答案代码:http://www.xz577.com/j/129.html

    文件和异常

    第十章 文件和异常

    从文件中读取数据

    读取文件、文件路径

    pi_digits.txt
    3.1415926535
       8979323846
       2643383279
    
    file_reader.py
    fillename = 'pi_digits.txt'
    #读取整个文件
    with open(filename) as file_object:
        contents = file_object.read()
        print(contents.rstrip())
    
    #逐行读取
    with open(filename) as file_object:
        for line in file_object:
            print(line.rstrip())
    
    运行结果:
    3.1415926535
       8979323846
       2643383279
    3.1415926535
       8979323846
       2643383279

    函数open():接受要打开文件的文件名作为参数。如果没有指定路径,则在当前执行的文件所在的目录中查找指定的文件。此函数返回一个表示文件的对象。

    关键字with:表示在不需要访问文件之后将其关闭。

    函数read():用于从文件读取指定的字节数,如果未给定或为负则读取所有。到达文件末尾时返回一个空字符串(空行)。打印时可使用函数rstrip()删掉。

    相对文件路径:相对于当前运行的程序所在目录。

    绝对文件路径:完整的文件路径。

    创建包含文件各行内容的列表并使用

    使用关键字with时,open()返回的文件对象只在with代码块内使用。如果要在with代码块外访问文件内容,可在里边将文件各行存储在一个列表中待后续使用。

    filename = 'pi_30_digits.txt'
    with open(filename) as file_object:
        lines = file_object.readlines()
    
    pi_string = ''
    for line in lines:
        pi_string += line.strip()
    
    print(pi_string)
    print(len(pi_string))
    
    运行结果:
    3.141592653589793238462643383279
    32

    注意:读取文本文件时,python将其中所有文本都解读稳字符串。

    写入文件

    将文本写入文件时,调用open()时需要提供另外一个实参。其中,第一个实参时要打开的文件的名称。第二个实参是指定的模式:读取模式('r')、写入模式('w')、附加模式('a')、读取和写入模式('r+')。如果省略将以默认的只读模式打开文件。
    如果写入的文件不存在,则open()会自动创建它。如果以写入模式打开文件且指定文件对象存在,则返回文件对象前会清空改文件。

    filename = 'programming.txt'
    with open(filename, 'w') as file_object:
        file_object.write("I love programming.")
        file_object.write("I love programming.\n")
        file_object.write("I love creating new games.\n")
    
    运行结果:
    programming.txt
    I love programming.I love programming.
    I love creating new games.

    注意:python只能将字符串写入文本文件。函数write()不会在写入的文本末尾添加换行符。

    附加到文件

    如果要写入文件并不覆盖,可以使用附加模式。写入的行都会添加到文件末尾。指定文件不存在时,自动创建。

    filename = 'programming.txt'
    with open(filename, 'a') as file_object:
        file_object.write("I also love finding meaning in large datasets.\n")
        file_object.write("I love creating apps that can run in a browser.\n")
    
    运行结果:
    programming.txt
    I love programming.I love programming.
    I love creating new games.
    I also love finding meaning in large datasets.
    I love creating apps that can run in a browser.

    异常

    异常时python用来管理程序执行期间发生错误的特殊对象。

    异常是使用try-except代码块处理的。如果try代码块中的代码运行无误,则跳过except代码块;如果try代码块中的代码运行出现错误,则运行except代码块。

    print(5/0)
    
    运行结果:
    Traceback (most recent call last):
        File "division.py", line 1, in <module>
            print(5/0)
    ZeroDivisionError: division by zero

    ZeroDivisionError是一个异常对象。

    try:
        print(5/0)
    except ZeroDivisionError:
        print("You can't divide by zero!")
    
    运行结果:
    You can't divide by zero!

    使用try-except代码块也可以隐藏Traceback,防止恶意攻击等等。
    除了try-except代码块还有try-except-else代码块。其中try代码块只包含可能导致错误的代码,而依赖于其成功执行的代码都放在else代码块中。
    如果希望发生错误时继续运行,可以在except代码块中使用pass语句。pass语句还充当了占位符,用来提醒我们在程序的某个地方什么都没有做。

    存储数据

    模块json可以让我们将简单的python数据结构转储到文件中,并在程序再次运行时加载该文件中的数据。并且还可以使用json在python程序中分享数据。

    函数json.dump()接受两个实参:要存储的数据以及可用于存储数据的文件对象。

    import json
    numbers = [2, 3, 5, 7, 11, 13]
    filename = 'numbers.json'
    with open(filename, 'w') as f_obj:
        json.dump(numbers, f_obj)
    
    运行结果:
    numbers.json
    [2, 3, 5, 7, 11, 13]

    函数json.load()加载存储在指定文件对象的信息。

    import json
    filename = 'numbers.json'
    with open(filename) as f_obj:
        numbers = json.load(f_obj)
    print(numbers)
    
    运行结果:
    [2, 3, 5, 7, 11, 13]

    下面将存取数据和异常结合一下程序运行时,从文件获取用户名,若文件不存在,则提示输入用户名并存储:

    import json
    # 如果以前存储了用户名就加载它
    # 否则提示用户输入用户名并存储它
    filename = 'username.json'
    try:
        with open(filename) as f_obj:
            username = json.load(f_obj)
    except FileNotFoundError:
        username = input("What is your name? ")
        with open(filename, 'w') as f_obj:
            json.dump(username, f_obj)
            print("We'll remember you when you come back, " + username + "!")
    else:
        print("Welcome back, " + username + "!")
    
    运行结果:
    #如果文件不存在
    What is your name? Eric
    We'll remember you when you come back, Eric!
    
    #如果文件存在
    Welcome back, Eric!

    第十章练习答案代码:http://www.xz577.com/j/129.html

    测试代码

    第十一章 测试代码

    测试函数

    单元测试和测试用例

    Python标准库中的模块unittest提供了代码测试工具。单元测试用于核实函数的某个方面没有问题;测试用例时一组单元测试,这些单元测试一起核实函数在各种情形下的行为都符合要求。。

    测试示例

    现在有这么一个函数以及其单元测试:

    #name_function.py
    def get_formatted_name(first, last, middle=''):
        if middle:
            full_name = first + ' ' + middle + ' ' + last
        else:
            full_name = first + ' ' + last
        return full_name.title()
    #test_name_ function.py
    import unittest
    from name_function import get_formatted_name
    
    class NamesTestCase(unittest.TestCase):
        def test_first_last_name(self):
            formatted_name = get_formatted_name('janis', 'joplin')
            self.assertEqual(formatted_name, 'Janis Joplin')
    
    unittest.main()
    
    运行结果:
    .
    ----------------------------------------------------------------------
    Ran 1 test in 0.000s
    OK

    首先导入模块unittest和要测试的函数get_formatted_ name()。接着创建一个单元测试类NamesTestCase,记住,类名最好包含Test并且继承unittest.TestCase类,这样python才能识别为测试类。
    接着编写好测试方法之后(在这里我们只写了一个方法:只有名和姓的姓名能否被正确地格式化),当我们运行 test_name_ function.py时,所有以test开头的方法都将自动运行。
    最后,我们使用了unittest类的一个断言方法unittest.assertEqual(),用来核实得到的结果是否与期望的结果一致。代码行unittest.main()让python运行文件中的测试。

    测试类

    各种断言方法

    python的unittest.TestCase类中提供了很多断言方法(检查应该满足的条件是否确实满足,返回布尔值)。
    下面提供了六种常用的断言方法:

    • assertEqual(a, b):核实a == b
    • assertNotEqual(a, b):核实a != b
    • assertTrue(x):核实x为True
    • assertFalse(x):核实x为False
    • assertIn(item, list):核实item在list中
    • assertNotIn(item, list):核实item不在list中

    当测试方法多了起来的时候,每次都要创建一个实例对象很麻烦,而python的unittest.TestCase类中提供了方法setup(),让我们只需创建一次实例对象即可让所有方法使用该对象(运行测试时如果包含这个函数将会首先运行它)。
    注意:测试通过时为一个句点,测试引发错误时为一个E,测试导致断言失败时为一个F。

    第十一章练习答案代码:http://www.xz577.com/j/129.html

    Django入门(一)

    第十八章 Django入门(一)

    Django是一个Web框架——一套用于帮助开发交互式网站的工具,其能够响应网页的请求,还能轻松读写数据库,管理用户等。

    建立项目

    目标:编写一个名为“学习笔记”的Web应用程序,让用户能够记录学习笔记。其主页时对这个网站的描述,可邀请用户注册或登录。用户登录后可以创建新主题、添加新条目以及阅读既有条目。

    建立虚拟环境

    在win10下安装Virtualenv。在cmd中,执行:pip install virtualenv。接着开始创建第一个虚拟环境(参考http://www.jb51.net/article/85527.htm 使用Virtualenv来创建虚拟环境)并安装django。

    在项目文件夹中执行:virtualenv venv

    创建好虚拟环境之后。接着激活环境,执行:venv\Scripts\activate(退出venv环境,运行命令:deactivate)

    如果看到命令行前面有(venv),就代表激活成功,如下图 

    安装Django

    创建并激活虚拟环境后,接着安装django,执行命令pip install django==1.11.7。

    在Django创建项目和数据库

    在处于活动的虚拟环境下,执行命令django-admin.py startproject learning_log .即创建一个名为learning_log的项目,命令末尾的句点让新项目使用合适的目录结构。

    django除了创建一个名为learning_log的目录还创建了一个名为manage.py的文件。

    目录learning_log包含4个文件,其中最重要的是settings.py、urls.py、wsgi.py。

    • settings.py:指定django如何与系统交互以及如何管理项目。
    • urls.py:告诉django应创建哪些网页来响应浏览器请求。
    • wsgi.py:帮助django提供它创建的文件,这个文件名是 web server gateway interface(Web服务器网管接口)的首字母缩写。

    django将大部分与项目相关的信息都存储在数据库中。创建django使用的数据库,执行命令python manage.py migrate。我们把修改数据库称为迁移数据库。

    执行完之后django将创建一个文件db.sqlite3。SQLite是一个使用单个文件的俄数据库。

    运行项目启动服务器,可执行命令runserver。接着在浏览器输入http://127.0.0.1:8000/即可查看运行中的项目。如果要关闭服务器,按ctrl+c。

    Django入门(一)

    第十八章 Django入门(二)

    创建应用程序

    django项目由一系列应用程序组成,他们协同工作,让项目称谓一个整体。首先我们执行命令python manage.py startapp learning_logs。 

    定义模型

    打开刚刚我们创建的文件夹,并修改models.py:

    from django.db import models
    class Topic(models.Model):
        text = models.CharField(max_length=200)
        date_added = models.DateTimeField(auto_now_add=True)
    
        def __str__(self):
            return self.text

    我们为模型创建了一个名为Topic的类,他继承了Model——django中一个定义模型基本功能的类。Topic类只有两个属性:text和date_added。

    text是一个CharField——由字符或文本组成的数据,可存储少量文本。传入参数**max_length**为文本最大长度。

    date_added是一个DateField——记录日期和时间的数据。传入的实参auto_add_now=True告诉django每当用户新建主题时,将这个属性自动设置为当前日期和时间。

    激活模型

    打开learning_log中的setting.py并添加

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
    
        'learning_logs', #<-here
    ]

    这是一个元组,包含了django项目中的所有应用程序。接着执行python manage.py makemigrations learning_logs让django确定如何修改数据库。最后应用迁移,执行python manage.py migrate。 

    Django管理网站

    1.创建超级用户,执行命令python manage.py createsuperuser。 

    2.向管理网站注册模型,打开 learning_logs下的admin.py,并修改为:

    from django.contrib import admin
    from learning_logs.models import Topic
    admin.site.register(Topic)

    这写代码导入了我们要注册的模型Topic,接着使用admin.site.register(Topic)让django通过管理网站管理我们的模型。

    接着运行服务器,访问http://127.0.0.1:8000/admin并使用着急用户帐号密码登录。 

    3.添加主题,点击Topic之后进入主题网页,此时可以通过点击add进行主题的添加,添加完成之后点击save进行保存。

    定义模型Entry

    learning_logs\models.py
    from django.db import models
    
    class Topic(models.Model):
        text = models.CharField(max_length=200)
        date_added = models.DateTimeField(auto_now_add=True)
    
        def __str__(self):
            return self.text
    
    class Entry(models.Model):
        topic = models.ForeignKey(Topic)
        text = models.TextField()
        date_added = models.DateTimeField(auto_now_add=True)
    
        class Meta:
            verbose_name_plural = 'entries'
    
        def __str__(self):
            return self.text[:50] + "..."

    ForeignKey是数据库的外键,引用数据库中的另一个记录。Entry类中的Meta类用于存储管理模型的额外信息,这里设置了一个特殊属性,让django在需要时使用 Entries 来表示多个条目。

    迁移模型Entry

    由于我们添加了一个新模型,因此需要再次迁移数据库。执行命令python manage.py makemigrations learning_logs以及python manage.py migrate. 

    向管理网站注册Entry

    修改如下文件

    learning_logs\admin.py
    from django.contrib import admin
    
    from learning_logs.models import Topic, Entry
    
    admin.site.register(Topic)
    admin.site.register(Entry)

    返回管理网站可以发现多了一个板块

    接着点击新板块的add添加以下主题和讨论,并点击保存给我们之后测试使用。

    国际象棋:The opening is the first part of the game, roughly the first ten moves or so. In the opening, it’s agood idea to do three things— bring out your bishops and knights, try to control the center of theboard, and castle your king.
    攀岩:One of the most important concepts in climbing is to keep your weight on your feet asmuch as possible. There’s a myth that climbers can hang all day on their arms. In reality, goodclimbers have practiced specific ways of keeping their weight over their feet whenever possible

    django shell

    在输入以上数据之后,可以通过交互式终端会话访问这些数据,在测试项目和排除故障的时候会用上。执行命令python manage.py shell可以打开shell会话。

    Django入门(三)

    创建网页:学习笔记主页

    使用django创建网页通常分三个阶段:定义URL、编写视图和编写模板。

    首先必须定义URL模式,其描述了URL是如何设计的,让django知道如何将浏览器请求与网站URL匹配,以确定返回哪个网页。每个URL都被映射到特定的视图——视图函数获取并处理网页所需的数据。视图函数通常调用一个模板,后者生成浏览器能够理解的网页。

    映射URL

    #learning_log/urls.py
    from django.conf.urls import url
    from django.contrib import admin
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'', include('learning_logs.urls', namespace='learning_logs')),
    ]

    我们添加了一行代码来包含模块learning_logs.urls。实参namespace能够将learning_logs的URL同项目中的其他URL区分开来。

    默认的urls.py保存在learning_log文件夹中,我们需要在learning_logs中创建另外一个urls.py如下

    #learning_logs/urls.py
    from django.conf.urls import url
    from . import views
    
    urlpatterns = [
        url(r'^$', views.index, name='index'),
    ]

    此模块中,urlpatterns变量是一个列表,包含可在应用程序learning_logs中请求的网页。

    URL模式是一个对函数url()的调用,其包含三个实参:

    • 第一个是正则表达式,r'^$'中的r让python把单引号对里面的字符串视为原始字符串;脱字符^表示查看字符串的开头;美元符号$表示查看字符串的末尾;整个字符表达式表示查找开头和末尾之间没有任何东西的url。
    • 第二个是指定要调用的视图函数。如果请求的URL与前述正则表达式匹配,django将调用views.index。
    • 第三个是将这个URL模式的名称指定为index,让我们能够在代码的其他地方引用他。当需要提供到这个主页的链接时,我们都将使用这个名称而不编写URL。

    编写视图

    视图函数接受请求中的信息,准备生成网页所需的数据,并将这些数据发送给浏览器。

    修改并添加:

    #learning_logs/views.py
    from django.shortcuts import render
    
    def index(request):
        return render(request, 'learning_logs/index.html')

    函数render()根据视图提供的数据渲染相应。

    当URL请求与我们定义的模式匹配时,django将在文件views.py中查找函数index(),再将请求对象传递给这个视图函数。

    而这里的函数render()提供了两个实参:原始请求对象以及一个可用于创建网页的模板。

    编写模板

    模板定义了网页的结构。模板指定了网页是啥样的。而每当网页被请求时,django将填入相关的数据。

    在文件夹learning_logs中创建文件夹templates,又在这个文件夹中创建文件夹learning_logs。接着在最里面的文件夹learning_logs中新建一个index.html。

    <!-- index.html -->
    <p>Learning Log</p>
    <p>Learning Log helps you keep track of your learning, for any topic you're
    learning about.</p>

    最后在虚拟环境中runserver,并打开http://127.0.0.1:8000/可以看到 

    Django入门(四)

    第十八章 Django入门(四)

    创建其他网页

    我们接下来扩充“学习笔记”项目,创建两个显示数据的网页,其中一个列出所有的主题,另一个显示特定主题的所有条目。

    模板继承

    编写一个包含通用元素的父模板,并让每个网页都继承这个模板,而不必在每个网页中重复定义这些通用元素。这样我们可以专注于开发每个网页的独特部分。

    1.父模板

    创建名为base.html的模板,和index.html放在同一个目录,这个文件包含所有页面都有的元素——顶端的标题。

    <p>
      <a href="{% url 'learning_logs:index' %}">Learning Log</a>
    </p>
    
    {% block content %}{% endblock content %}

    在第二行中使用了一个模板标签,模板标签使用大括号和百分号({% %})表示,其是一小段生成网页中显示信息的代码。

    模板标签{% url 'learning_logs:index' %}生成一个URL,该URL与learning_logs/urls.py中定义的名为index的URL模式匹配。在这个示例中,learning_logs是一个命名空间,而index是该命名空间中的一个名称独特的URL模式。

    在结尾中插入了一对块标签,这个块名为content,是一个占位符,其包含的信息将由子模板指定。

    2.子模板

    重新修改index.html

    {% extends "learning_logs/base.html" %}
    
    {% block content %}
      <p>Learning Log helps you keep track of your learning, for any topic you're learning about.</p>
    {% endblock content %}

    子模板第一行{% extends %}表示继承了指定的父模板。这行代码会导入base.html的所有内容,让index.html的内容能够添加在父模板预留的content块中。

    第二行,我们插入了content的{% content %}标签,以定义content块。不是从父模板继承的内容都包含在里边。

    最后一行,{% endblock content %}表示定义结束。

    显示所有主题的页面

    1.URL模式

    #learning_logs/urls.py
    from django.conf.urls import url
    from . import views
    
    urlpatterns = [
        url(r'^$', views.index, name='index'),
        url(r'^topics/$', views.topics, name='topics'),
    ]

    新添加的正则表达式表示匹配的URL为:基础URL后面跟着topics。接着匹配成功的话将请求都交给views.py中的函数topics()进行处理。

    2.视图

    函数topics()需要从数据库获取数据,发送给模板。

    from django.shortcuts import render
    from .models import Topic
    
    def index(request):
        return render(request, 'learning_logs/index.html')
    
    def topics(request):
        topics = Topic.objects.order_by('date_added')
        context = {'topics': topics}
        return render(request, 'learning_logs/topics.html', context)

    首先导入与所需数据相关联的模型。接着函数topics()包含一个形参:从服务器收到的request对象。

    函数的第二行表示查询数据库,请求Topic对象,并按属性date_added对数据进行排序。最后把返回的查询集春处在topics变量中。

    函数的第三行定义了一个发给模板的上下文:是一个字典,其中的键是模板中用来访问数据的名称,值是发送给模板的数据。

    函数返回的时候,即创建使用数据的网页时,我们把对象request和模板路径,还有变量context传递给render()。

    3.模板

    创建一个文件 topics.html 和 index.html 同一文件夹。

    {% extends "learning_logs/base.html" %}
    
    {% block content %}
    
      <p>Topics</p>
    
      <ul>
        {% for topic in topics %}
           <li>{{ topic }}</li>
        {% empty %}
           <li>No topics have been added yet.</li>
        {% endfor %}
      </ul>
    
    {% endblock content %}

    首先继承父模板,接着定义content块。接着使用for循环的模板标签遍历字典context的列表topics。在模板中,不能使用缩进来表示循环结束,应当使用标签{% endfor %}来指出循环的结束。双花括号({{ topic }})里的模板变量都会被替换为topic的当前值。

    循环中间的模板标签{% empty %}告诉django在列表topics为空时该怎么办:这里是打印一条消息,告诉用户No topics have been added yet.。

    最后修改父模板,使其包含显示所有主题的页面连接:

    <p>
      <a href="{% url 'learning_logs:index' %}">Learning Log</a> - 
      <a href="{% url 'learning_logs:topics' %}">Topics</a>
    </p>
    
    {% block content %}{% endblock content %}

    运行本地服务器可以看到

    成功了!

    显示特定主题的网页

    1.URL模式

    #learning_logs/urls.py
    from django.conf.urls import url
    from . import views
    
    urlpatterns = [
        url(r'^$', views.index, name='index'),
        url(r'^topics/$', views.topics, name='topics'),
        url(r'^topics/(?P<topic_id>\d+)/$', views.topic, name='topic'),
    ]

    显示特定主题的页面的URL模式与前面的不同,因为其将使用主题的id属性来指出请求的是哪个主题。

    + r'^topics/(?P<topic_id>\d+)/$'中的第二部分/(?P<topic_id>\d+)/表示与包含在两个斜杠内的整数匹配,并将这个整数存储在实参topic_id中。这部分表达式两边的括号捕获URL中的值;?P<topic_id>将匹配的值存储到topic_id中;\d+与包含在两个斜杠内的任何数字都匹配,不管其多少位。

    这个模式匹配成功时,将会调用视图函数topic(),并把topic_id的值作为实参传递进去。

    2.视图

    from django.shortcuts import render
    from .models import Topic
    
    def index(request):
        return render(request, 'learning_logs/index.html')
    
    def topics(request):
        topics = Topic.objects.order_by('date_added')
        context = {'topics': topics}
        return render(request, 'learning_logs/topics.html', context)
    
    def topic(request, topic_id):
        topic = Topic.objects.get(id=topic_id)
        entries = topic.entry_set.order_by('-date_added')
        context = {'topic': topic, 'entries': entries}
        return render(request, 'learning_logs/topic.html', context)

    函数get()获取指定的主题。data_added前面的减号指定按降序排列,即先显示最近的条目。

    3.模板

    创建一个文件 topic.html 和 index.html 同一文件夹。

    {% extends 'learning_logs/base.html' %}
    
    {% block content %}
    
      <p>Topic: {{ topic }}</p>
    
      <p>Entries:</p>
      <ul>
      {% for entry in entries %}
        <li>
          <p>{{ entry.date_added|date:'M d, Y H:i' }}</p>
          <p>{{ entry.text|linebreaks }}</p>
        </li>
      {% empty %}
        <li>
          There are no entries for this topic yet.
        </li>
      {% endfor %}
      </ul>
    
    {% endblock content %}

    因为我们变量topic包含在字典context中,所以我们可以使用他。

    每个项目列表项都将列出两项信息:条目的时间戳和完整的文本。列出时间戳date_added的值,我们可以在模板中使用竖线(|)表示模板过滤器——对模板变量的值进行修改的函数。

    过滤器date:'M d, Y H:i'表示以这样的格式显示时间戳:January 1, 2015 23:00。

    过滤器linebreaks表示自动换行。

    4.将显示所有主题的页面中的每个主题都设置为链接

    修改topics.html

    {% extends "learning_logs/base.html" %}
    
    {% block content %}
    
      <p>Topics</p>
    
      <ul>
        {% for topic in topics %}
           <a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a> <!-- here -->
        {% empty %}
           <li>No topics have been added yet.</li>
        {% endfor %}
      </ul>
    
    {% endblock content %}

    运行本地服务器可以看到

    用户账户(一)

    让用户能够输入数据(表单)

    在创建用户账户身份验证系统之前,先添加几个页面,让用户能偶输入数据。添加新主题、添加新条目以及编辑既有条目。

    添加新主题

    1.用于添加主题的表单

    创建一个forms.py文件与models.py放在同一目录下。

    from django import forms
    from .models import Topic
    
    class TopicForm(forms.ModelForm):
        class Meta:
            model = Topic
            fields = ['text']
            labels = {'text': ''}

    TopicForm类继承了forms.ModelForm,其包含一个内嵌的Meta类。Meta类指定了根据哪个模型创建表单,以及在表单中包含哪些字段。

    在这里,我们根据模型Topic创建了一个表单,该表单只包含字段text,且不用为字段text生成标签。

    2.URL模式new_topic

    # learning_logs/urls.py
    from django.conf.urls import url
    from . import views
    
    urlpatterns = [
        url(r'^$', views.index, name='index'),
        url(r'^topics/$', views.topics, name='topics'),
        url(r'^topics/(?P<topic_id>\d+)/$', views.topic, name='topic'),
        url(r'^new_topic/$', views.new_topic, name='new_topic'),
    ]

    3.视图函数new_topic()

    # learning_logs/views.py
    from django.shortcuts import render
    from django.http import HttpResponseRedirect
    from django.core.urlresolvers import reverse
    from .models import Topic
    from .forms import TopicForm
    
    --snip--
    
    def new_topic(request):
        if request.method != 'POST':
            #未提交数据,创建一个新表单
            form = TopicForm()
        else:
            #POST提交的数据,对数据进行处理
            form = TopicForm(request.POST)
            if form.is_valid():
                form.save()
                return HttpResponseRedirect(reverse('learning_logs:topics'))
    
        context = {'form': form}
        return render(request, 'learning_logs/new_topic.html', context)

    用户提交主题后使用HttpResponseRedirect类将用户重定向到网页topics。函数reverse()根据指定的URL模式确定URL,即django将在页面被请求时生成URL。

    4.GET请求和POST请求

    GET请求:从服务器读取数据;

    POST请求:通过表单提交信息。

    在上述代码的else部分中,我们将使用-存储在request.POST的用户输入数据-创建一个TopicForm实例并赋值给对象form。

    将提交的信息保存到数据库之前,得检查其是否有效。函数is_valid()核实用户填写了所有必不可少的字段,且输入的数据与要求的字段类型一致。如果所有字段有效,调用函数save()将表单数据写入数据库。

    最后使用函数reverse()获取页面topics的URL,并将其传递给HttpResponseRedirect(),后者将用户浏览器重定向到页面topics查看用户刚输入的主题。

    5.模版new_topic

    <!-- new_topic.html -->
    {% extends "learning_logs/base.html" %}
    
    {% block content %}
      <p>Add a new topic:</p>
    
      <form action="{% url 'learning_logs:new_topic' %}" method='post'>
        {% csrf_token %}
        {{ form.as_p }}
        <button name="submit">add topic</button>
      </form>
    
    {% endblock content %}

    定义表单使的实参action指定了服务器将提交的表单数据发送的目的地。在这里我们将它发回给视图函数new_topic()。实参method让浏览器以POST请求的方式提交数据。

    模板标签{% csrf_token %}防止攻击者利用表单来获得对服务器未经授权的访问(跨站请求伪造)。

    模板变量{{ form.as_p }}让django自动创建显示表单所需的全部字段。修饰符as_p表示以段落格式渲染所有表单元素。

    6.链接到页面new_topic

    在页面 topics中添加一个到页面new_topic的链接

    {% extends "learning_logs/base.html" %}
    
    {% block content %}
    
      <p>Topics</p>
    
        <ul>
          --snip--
        </ul>
    
      <a href="{% url 'learning_logs:new_topic' %}">Add a new topic:</a>
    
    {% endblock content %}

    运行服务器可以看到

    添加新条目

    1.用于添加新条目放入表单

    定制一个与模型Entry相关联的表单

    from django import forms
    from .models import Topic, Entry
    
    class TopicForm(forms.ModelForm):
        class Meta:
            model = Topic
            fields = ['text']
            labels = {'text': ''}
    
    class EntryForm(forms.ModelForm):
        class Meta:
            model = Entry
            fields = ['text']
            labels = {'text': ''}
            widgets = {'text': forms.Textarea(attrs={'cols': 80})}

    同样导入Entry,新类继承forms.ModelForm,新类包含的Meta类指出表单基于的模型以及表单中包含的字段。

    在Meta类中我们定义了属性widgets。小部件(widget)是一个HTML表单元素,比如单行文本框、多行文本区域或者下拉列表。通过设置这个属性覆盖django默认的小部件,并把文本区域的宽度设置为80列,而不是默认的40列。

    2.URL模式new_entry

    修改urls.py

    #learning_logs/urls.py
    from django.conf.urls import url
    from . import views
    
    urlpatterns = [
        #--snip--
        url(r'^new_entry/(?P<topic_id>\d+)/$', views.new_entry, name='new_entry'),
    ]

    这个URL模式与形式为http://127.0.0.1:8000/new_entry/id/的URL匹配,其中id是一个与主题id匹配的数字。(?P<topic_id>\d+)捕获一个数值存储在变量topic_id中。模式匹配时django把请求和主题id发给函数new_entry()。

    3.视图函数new_topic

    修改views.py

    from django.shortcuts import render
    from django.http import HttpResponseRedirect
    from django.core.urlresolvers import reverse
    from .models import Topic
    from .forms import TopicForm, EntryForm
    #--snip--
    
    def new_entry(request, topic_id):
        topic = Topic.objects.get(id=topic_id)
        if request.method != 'POST':
            #未提交数据,创建一个空表单
            form = EntryForm()
        else:
            #POST提交的数据,对数据进行处理
            form = EntryForm(data=request.POST)
            if form.is_valid():
                new_entry = form.save(commit=False)
                new_entry.topic = topic
                new_entry.save()
                return HttpResponseRedirect(reverse('learning_logs:topic',args=[topic_id]))
    
        context = {'topic': topic, 'form': form}
        return render(request, 'learning_logs/new_entry.html', context)

    new_entry = form.save(commit=False)

    表示创建一个新的条目对象并把它存储到new_entry中,但是不保存到数据库。接着把new_entry的topic设置为此函数开头从数据库中获取的主题,然后调用save()保存到数据库,这样才能确保与正确的主题相关联。

    在调用reserve()时需要提供两个实参。第一个是根据它来生成URL的URL模式的名称。第二个是列表args,其中存储着要包含在URL中的所有实参。

    4.模板new_entry

    类似new_topic.html

    #new_entry.html
    {% extends "learning_logs/base.html" %}
    
    {% block content %}
    
      <p><a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a></p>
    
      <p>Add a new entry:</p>
      <form action="{% url 'learning_logs:new_entry' topic.id %}" method='post'>
        {% csrf_token %}
        {{ form.as_p }}
        <button name='submit'>add entry</button>
      </form>
    
    {% endblock content %}

    表单的实参action包含URL中的topic_id值,让视图函数能够把新条目关联到正确的主题。

    5.链接到页面new_entry

    在显示特定主题的页面中添加到页面new_entry的链接

    #topic.html
    {% extends 'learning_logs/base.html' %}
    
    {% block content %}
    
      <p>Topic: {{ topic }}</p>
    
      <p>Entries:</p>
      <p>
        <a href="{% url 'learning_logs:new_entry' topic.id %}">add new entry</a>
      </p>
      <ul>
      #--snip--
      </ul>
    
    {% endblock content %}

    运行服务器可以看到

    编辑条目

    1.URL模式edit_entry

    此页面的URL需要传递要编辑的条目的ID。

    #learning_logs/urls.py
    from django.conf.urls import url
    from . import views
    
    urlpatterns = [
        #--snip--
        url(r'^edit_entry/(?P<entry_id>\d+)/$', views.edit_entry,name='edit_entry'),
    ]

    在URLhttp://127.0.0.1:8000/edit_entry/id/中传递的id存储在形参entry_id中。模式匹配时把请求发送给视图函数edit_entry()。

    2.视图函数edit_entry

    页面edit_entry收到GET请求时,edit_entry()返回一个表单,让用户对条目进行编辑。该页面收到POST请求(条目文本经过修订)时,把修改后的文本保存到数据库中。

    修改views.py

    from django.shortcuts import render
    from django.http import HttpResponseRedirect
    from django.core.urlresolvers import reverse
    from .models import Topic, Entry
    from .forms import TopicForm, EntryForm
    #--snip--
    
    def edit_entry(request, entry_id):
        entry = Entry.objects.get(id=entry_id)
        topic = entry.topic
        if request.method != 'POST':
            #初次请求,使用当前条目填充表单
            form = EntryForm(instance=entry)
        else:
            # POST提交的数据,对数据进行处理
            form = EntryForm(instance=entry, data=request.POST)
            if form.is_valid():
                form.save()
                return HttpResponseRedirect(reverse('learning_logs:topic',args=[topic.id]))
    
        context = {'entry': entry, 'topic': topic, 'form': form}
        return render(request, 'learning_logs/edit_entry.html', context)

    首先获取需要修改的条目对象以及该条目相关联的主题。当请求方法为GET时执行if代码块,实参instance=entry表示使用既有条目对象中的信息填充创建的表单。

    处理POST请求时,传递实参instance=entry和data=request.POST让django根据既有条目对象创建表单实例并根据request.POST中的相关数据对其进行修改。

    3.模板edit_entry

    类似new_entry.html

    #edit_entry.html
    {% extends "learning_logs/base.html" %}
    
    {% block content %}
    
      <p><a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a></p>
    
      <p>Edit entry:</p>
    
      <form action="{% url 'learning_logs:edit_entry' entry.id %}" method='post'>
        {% csrf_token %}
        {{ form.as_p }}
        <button name="submit">save changes</button>
      </form>
    
    {% endblock content %}

    在标签{% url %}中将条目id作为实参。

    5.链接到页面edit_entry

    在显示特定主题的页面中给每个条目添加到页面edit_entry的链接:

    #topic.html
    #--snip--
      {% for entry in entries %}
        <li>
          <p>{{ entry.date_added|date:'M d, Y H:i' }}</p>
          <p>{{ entry.text|linebreaks }}</p>
          <p>
            <a href="{% url 'learning_logs:edit_entry' entry.id %}">edit entry</a>
          </p>
        </li>
    #--snip--

    运行服务器可以看到

    用户账户(二)

    第十九章 用户账户(二)

    创建用户账户

    这一部分我们来创建用户注册和身份验证系统。

    应用程序users

    首先使用命令python manage.py startapp users创建名为users的应用程序,现在你的目录应该和下面一样。

    1.将应用程序users添加到settings.py

    #--snip--
    INSTALLED_APPS = (
        #--snip--
        'learning_logs',
        'users',
    )
    #--snip--

    2.创建users的URL模式

    from django.conf.urls import url, include
    from django.contrib import admin
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^users/', include('users.urls', namespace='users')),
        url(r'', include('learning_logs.urls', namespace='learning_logs')),
    ]

    添加的代码与任何以单词users大头的URL(如http://localhost:8000/users/login/)都匹配。

    登录页面

    在learning_log/users/中新建一个urls.py。

    from django.conf.urls import url
    from django.contrib.auth.views import login
    
    from . import views
    
    urlpatterns = [
        url(r'^login/$', login, {'template_name': 'users/login.html'},name='login'),
    ]

    首先导入默认视图login,接着登录页面的URL模式与URLhttp://localhost:8000/

    users/login/匹配。实参login(不是views.login)告诉django将请求发送给视图login。接着传递了一个字典指定要查找的模板。

    1.模板login.html

    同样,新建一个路径users/templates/users/,接着在这个路径下新建login.html。

    {% extends "learning_logs/base.html" %}
    
    {% block content %}
    
      {% if form.errors %}
      <p>Your username and password didn't match. Please try again.</p>
      {% endif %}
    
      <form method="post" action="{% url 'users:login' %}">
      {% csrf_token %}
      {{ form.as_p }}
    
      <button name="submit">log in</button>
      <input type="hidden" name="next" value="{% url 'learning_logs:index' %}" />
      </form>
    
    {% endblock content %}

    这个模板同样继承了base.html。一个应用程序中的模板可继承另一个应用程序中的模板。

    表单errors属性可以在输入的用户名-密码错误时显示错误消息。

    将实参action设置为登录页面的URL,让登录视图处理表单。表单元素next告诉django在用户成功登录后将其重定向到主页。

    2.链接到登录页面

    在base.html中添加到登录页面的链接,但当用户已登录时,为了不显示这个链接,我们把它嵌套在{% if %}标签中。

    <p>
      <a href="{% url 'learning_logs:index' %}">Learning Log</a> - 
      <a href="{% url 'learning_logs:topics' %}">Topics</a> - 
      {% if user.is_authenticated %}
        Hello, {{ user.username }}.
      {% else %}
        <a href="{% url 'users:login' %}">log in</a>
      {% endif %}
    </p>
    
    {% block content %}{% endblock content %}

    在django身份验证系统中,每个模板都可以使用变量user,变量的is_authenricated属性:如果用户已登录,该属性值为True,否则为Faule;变量的username属性为用户名。

    3.使用登录页面

    如果你之前登录过管理员,记得先在http://127.0.0.1:8000/admin注销登录。然后重新登录我们的学习笔记网页登录页面http://127.0.0.1:8000/users/login/,并使用管理员的帐号密码登录。 

    注销

    1.注销URL

    #users/urls.py
    from django.conf.urls import url
    from django.contrib.auth.views import login
    
    from . import views
    
    urlpatterns = [
        url(r'^login/$', login, {'template_name': 'users/login.html'},name='login'),
        url(r'^logout/$', views.logout_view, name='logout'),
    ]

    2.视图函数logout_view()

    django自带函数模块logout(),我们只需导入他,并调用他重定向到主页。

    from django.http import HttpResponseRedirect
    from django.core.urlresolvers import reverse
    from django.contrib.auth import logout
    
    def logout_view(request):
        logout(request)
        return HttpResponseRedirect(reverse('learning_logs:index'))

    在这里,request对象作为实参传递给函数logout()。

    3.链接到注销视图

    在base.html中添加注销链接。为了使得仅当用户登录后才能看见他,我们将他放在标签{% if user.is_authenticated %}中。

    #base.html
    <p>
      <a href="{% url 'learning_logs:index' %}">Learning Log</a> - 
      <a href="{% url 'learning_logs:topics' %}">Topics</a> - 
      {% if user.is_authenticated %}
        Hello, {{ user.username }}.
        <a href="{% url 'users:logout' %}">log out</a>
      {% else %}
        <a href="{% url 'users:login' %}">log in</a>
      {% endif %}
    </p>
    
    {% block content %}{% endblock content %}

    运行服务器可以看到

    注册页面

    1.注册页面的URL模式

    from django.conf.urls import url
    from django.contrib.auth.views import login
    
    from . import views
    
    urlpatterns = [
        url(r'^login/$', login, {'template_name': 'users/login.html'},name='login'),
        url(r'^logout/$', views.logout_view, name='logout'),
        url(r'^register/$', views.register, name='register'),
    ]

    2.视图函数reigster()

    当注册页面首次被请求时,视图函数register()显示一个空的注册表单,用户提交后注册成功并自动登录。

    from django.shortcuts import render
    from django.http import HttpResponseRedirect
    from django.core.urlresolvers import reverse
    from django.contrib.auth import login, logout, authenticate
    from django.contrib.auth.forms import UserCreationForm
    
    def logout_view(request):
    --snip--
    
    def register(request):
        if request.method != 'POST':
            #显示空的注册表单
            form = UserCreationForm();
        else:
            #处理填写好的表单
            form = UserCreationForm(data=request.POST)
    
            if form.is_valid():
                new_user = form.save()
                #让用户自动登录并重定向到主页
                authenticate_user = authenticate(username=new_user.username,
                    password=request.POST['password1'])
                login(request, authenticate_user)
                return HttpResponseRedirect(reverse('learning_logs:index'))
    
        context = {'form': form}
        return render(request, 'users/register.html', context)

    函数login()和函数 authenticate()可以让用户注册成功后自动登录。

    在注册的时候,如果用户提交的注册表单数据有效,调用方法save()并返回新创建的用户对象,保存在new_user中。

    自动登录过程中,调用authenticate()并把实参new_user.username和密码(因为表单有效,两个密码相同,所以我们使用第一个密码'password1')传给它。接着我们将authenticate()返回的通过身份验证的用户对象保存在authenticate_user中。最后调用函数login(),并把对象request和authenticate_user传给他。最后完成自动登录。

    3.注册模板

    创建一个register.html,和login.html放在一起。

    {% extends "learning_logs/base.html" %}
    
    {% block content %}
    
      <form method="post" action="{% url 'users:register' %}">
        {% csrf_token %}
        {{ form.as_p }}
    
        <button name="submit">register</button>
        <input type="hidden" name="next" value="{% url 'learning_logs:index' %}" />
      </form>
    
    {% endblock content %}

    4.链接到注册页面

    <p>
      <a href="{% url 'learning_logs:index' %}">Learning Log</a> - 
      <a href="{% url 'learning_logs:topics' %}">Topics</a> - 
      {% if user.is_authenticated %}
        Hello, {{ user.username }}.
        <a href="{% url 'users:logout' %}">log out</a>
      {% else %}
        <a href="{% url 'users:register' %}">register</a> - 
        <a href="{% url 'users:login' %}">log in</a>
      {% endif %}
    </p>
    
    {% block content %}{% endblock content %}

    运行服务器可以看到

    用户账户(三)

    让用户拥有自己的数据

    这部分我们将创建一个系统,确定各项数据所属的用户,再限制对页面的访问,让用户只能使用自己的数据。

    修改模型Topic,让每个主题都归属特定用户。

    使用@login_required限制访问

    装饰器是放在函数定义前面的指令,python在函数运行前,根据它来修改函数代码的行为。

    装饰器@login_required:让特定的页面只允许已登录的用户访问。

    1.限制对topics页面的访问

    修改learning_logs/views.py

    #--snip--
    from django.core.urlresolvers import reverse
    from django.contrib.auth.decorators import login_required
    
    from .models import Topic, Entry
    #--snip--
    
    @login_required
    def topics(request):
        #--snip--

    加上装饰器之后,python会在运行topics()的代码前先运行login_required()的代码。

    login_required()会检查用户是否已登录,仅当用户已登录时,django才运行topics()。如果用户未登录,则重定向到登录页面。

    为实现重定向,修改settings.py,在文件末尾加上 LOGIN_URL = '/users/login/' 。现在未登录的用户会重定向到 LOGIN_URL 指定的URL。

    2.全面限制对项目“学习笔记”的访问

    现在,我们不限制对主页、注册、注销页面的访问,而限制对其他所有页面的访问。

    在learning_logs/views.py中,除了index()意外,每个视图都加上 @login_required。

    --snip--
    @login_required
    def topics(request):
        --snip--
    
    @login_required
    def topic(request, topic_id):
        --snip--
    
    @login_required
    def new_topic(request):
        --snip--
    
    @login_required
    def new_entry(request, topic_id):
        --snip--
    
    @login_required
    def edit_entry(request, entry_id):
        --snip--

    将数据关联到用户

    修改模型Topic,添加一个关联到用户的外键。然后必须对数据库进行迁移。最后对部分视图进行修改,使其只显示与当前用户登录的相关联的数据。

    1.修改模型Topic

    修改learning_logs/models.py

    from django.db import models
    from django.contrib.auth.models import User
    
    class Topic(models.Model):
        text = models.CharField(max_length=200)
        date_added = models.DateTimeField(auto_now_add=True)
        owner = models.ForeignKey(User)
    
        def __str__(self):
            return self.text
    
    class Entry(models.Model):
            --snip--

    2.确定当前有哪些用户

    为了简单,我们将既有主题都关联到超级用户上,先确定超级用户的id,打开shell。 

    确定当前用户只有admin,id为1。(或者还有其他你自己创建的用户)

    3.迁移数据库

    获取id之后,迁移数据库。

    首先执行命令makemigrations后,django指出我们视图给既有模型Topic添加一个必不可少(不可为空)的字段(无默认值),并提供了两种选择:要么现在提供默认值,要么退出并在models.py中添加默认值。在这里我选了第一个选项,输入默认值,接着输入了用户id = 1。最后django使用这个值迁移数据库,在模型Topic中添加字段owner。

    接下来执行迁移,执行命令python manage.py migrate。

    只允许用户访问自己的主题

    当前不管哪个用户登录,都能看到所有主题,现在我们让用户只能看到自己的主题。

    修改learning_logs/views.py

    #--snip--
    @login_required
    def topics(request):
        topics = Topic.objects.filter(owner=request.user).order_by('date_added')
        context = {'topics': topics}
        return render(request, 'learning_logs/topics.html', context)
    #--snip--
    用户登录后,request对象会有一个user属性,其存储了有关该用户的所有信息。`filter()`用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。在这里我们用这个函数从数据库中只获取owner属性为当前用户的Topic对象。

    保护用户的主题

    在此之前,已登录的用户可输入URLhttp://127.0.0.1:8000/topics/1/来访问显示相应主题的页面。

    为修复这种问题,,我们在视图函数topic()获取请求的条目前执行检查。

    from django.shortcuts import render
    from django.http import HttpResponseRedirect, Http404
    from django.core.urlresolvers import reverse
    #--snip--
    
    @login_required
    def topic(request, topic_id):
        topic = Topic.objects.get(id=topic_id)
        if topic.owner != request.user:
            raise Http404
        entries = topic.entry_set.order_by('-date_added')
        context = {'topic': topic, 'entries': entries}
        return render(request, 'learning_logs/topic.html', context)
    #--snip--

    渲染网页前检查该主题是否属于当前登录的用户,如果不是,则404。

    保护页面edit_entry

    接下来保护页面http://127.0.0.1:8000/edit_entry/1/。修改views.py

    #--snip--
    @login_required
    def edit_entry(request, entry_id):
        entry = Entry.objects.get(id=entry_id)
        topic = entry.topic
        if topic.owner != request.user:
            raise Http404
        if request.method != 'POST':
    #--snip--

    将新主题关联到当前用户

    当前,添加新主题的页面没有将新主题关联到特定用户。修改views.py

    #--snip--
    @login_required
    def new_topic(request):
        if request.method != 'POST':
            form = TopicForm()
        else:
            form = TopicForm(request.POST)
            if form.is_valid():
                new_topic = form.save(commit=False)
                new_topic.owner = request.user
                new_topic.save()
                return HttpResponseRedirect(reverse('learning_logs:topics'))
    
        context = {'form': form}
        return render(request, 'learning_logs/new_topic.html', context)
    #--snip--

    首先调用form.save(commit=False)是为了先修改新主题,暂时不提交到数据库中。接下来将新主题的 owner属性设置为当前用户后,最后在保存提交到数据库中。

    现在这个项目允许任何人注册,而且每个用户可以添加任意数量的新主题。每个用户都只能访问自己的数据,无论是查看数据、输入新数据还是修改就数据都是如此。

    设计样式和部署(一)

    第二十章 设计样式和部署(一)

    设置项目“学习笔记”的样式

    应用程序django-bootstrap3

    bootstrap是一组用于为Web应用程序设置样式的工具。

    首先在活动的虚拟环境中执行pip install django-bootstrap3。安装完成之后,我们需要在settings.py的INSTALLED_APPS添加如下代码,在项目中包含应用程序django-bootstrap3

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
    
        'bootstrap3',
        'learning_logs',
        'users',
    ]

    接着让django-bootstrap3包含jQuery,这是一个JavaScript库,让你能够使用bootstrap模板提供的交互元素。在settings.py的末尾添加如下代码。

    BOOTSTRAP3 = {
        'include_jquery': True,
        }

    这些代码让你无需手工下载jQuery并将其放到正确的地方。

    使用Bootstrap来设置项目“学习笔记的样式”

    bootstrap基本上就是一个大型的样式设置工具集,它还提供了大量的模板。如果要查看bootstrap提供的模板,可以访问http://getbootstrap.com/,单击Getting Started,再向下滚动到Examples部分,并找到Navbars in action。我们将使用模板Static top navbar,他提供了简单的顶部导航条、页面标题和同于放置页面内容的容器。

    修改base.html

    这部分我们来修改base.html,先把他分成几部分进行修改。

    1.定义HTML头部

    第一个修改时在这个文件中定义HTML头部,使得显示“学习笔记”的每个页面时,浏览器标题栏都显示这个网站的名称。删除 base.html 的全部代码,并输入下面的代码:

    {% load bootstrap3 %}
    
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset='utf-8'>
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
    
        <title>Learning Log</title>
    
        {% bootstrap_css %}
        {% bootstrap_javascript %}
    
    </head>

    首先加载django-bootstrap3中的模板标签集。接着将这个文件声明为使用英语编写的HTML文档。head部分不包含任何内容,只是将正确显示页面所需的内容告诉浏览器。

    在title标签下面,我们使用了django-bootstrap3的一个自定义模板标签,它让django包含所有的boostsrap样式文件。接下来的标签启用你可能在页面中使用的所有交互式行为,如何折叠的导航栏。

    2.定义导航栏

    定义页面顶部的导航栏

    <!--snip-->
    </head>
    
    <body>
      <!-- Static navbar -->
      <nav class="navbar navbar-default navbar-static-top">
        <div class="container">
    
          <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed"
                data-toggle="collapse" data-target="#navbar"
                aria-expanded="false" aria-controls="navbar">
            </button>
            <a class="navbar-brand" href="{% url 'learning_logs:index' %}">
                Learning Log</a>
          </div>
    
    <!--A处-->
          <div id="navbar" class="navbar-collapse collapse">
            <ul class="nav navbar-nav">
              <li><a href="{% url 'learning_logs:topics' %}">Topics</a></li>
            </ul>
    <!--B处-->
            <ul class="nav navbar-nav navbar-right">
              {% if user.is_authenticated %}
                <li><a>Hello, {{ user.username }}.</a></li>
                <li><a href="{% url 'users:logout' %}">log out</a></li>
              {% else %}
                <li><a href="{% url 'users:register' %}">register</a></li>
                <li><a href="{% url 'users:login' %}">log in</a></li>
              {% endif %}
            </ul>
          </div><!--/.nav-collapse -->
    
        </div>
    </nav>

    首先是<nar>元素,其表示页面的导航链接部分。对于这个元素内的所有内容,都将根据选择器(selector)navbar、navbar-default和navbar-static-top定义的boostsrap样式规则来设置样式。选择器决定了特定样式规则将应用于页面上的哪些元素。

    <button>定义了一个按钮,在浏览器窗口变窄时、无法水平显示完整的导航栏时显示出来。如果单击他将会出现下拉列表,其中包含所有的导航元素。当用户缩小窗口时,"collapse"会使导航栏折叠起来。接着我们在导航栏的最左边显示项目名,并设置了到主页的超链接。

    在A处,我们定义了导航的链接。导航栏其实是一个以<ul>开头的列表,其中每个链接都是一个列表项<li>。

    在B处,我们添加了第二个导航链接列表,这里使用了选择器为navbar-right来设置一组链接的样式,使其出现在导航栏的右边——登录、注册。在这里,已登录就显示问候语和注销;未登录就显示注册和登录。

    3.定义页面的主要部分

    <!--snip-->
        </nav>
    
        <div class="container">
    
          <div class="page-header">
            {% block header %}{% endblock header %}
          </div>
          <div>
            {% block content %}{% endblock content %}
          </div>
    
        </div> <!-- /container -->
    
      </body>
    </html>

    使用jumbotron设置主页的样式

    下面使用新定义的header块和一个名为jumbotron的Boostsrap元素修改主页。jumbotron元素是一个大框,他通常用于在主页中呈现项目的简要描述。修改index.html

    {% extends "learning_logs/base.html" %}
    
    {% block header %}
      <div class='jumbotron'>
        <h1>Track your learning.</h1>
      </div>
    {% endblock header %}
    
    
    {% block content %}
      <h2>
        <a href="{% url 'users:register' %}">Register an account</a> to make
        your own Learning Log, and list the topics you're learning about.
      </h2>
      <h2>
        Whenever you learn something new about a topic, make an entry 
        summarizing what you're learned.
      </h2>
    {% endblock content %}

    设置登录页面的样式

    这里我们改进一下登录的表单,修改login.html

    {% extends "learning_logs/base.html" %}
    
    {% load bootstrap3 %}
    
    {% block header %}
      <h2>Log in to your accout.</h2>
    {% endblock header %}
    
    {% block content %}
    
      <form method="post" action="{% url 'users:login' %}" class="form">
        {% csrf_token %}
        {% bootstrap_form form %}
    
        {% buttons %}
          <button name="submit" class="btn btn-primary">log in</button>
        {% endbuttons %}
    
        <input type="hidden" name="next" value="{% url 'learning_logs:index' %}" />
      </form>
    
    {% endblock content %}

    注意我们从这个模板删除了{% if form.errors %}代码块,因为django-bootstrap3会自动管理表单错误。{% bootstrap_form %}模板标签用来显示表单,其将bootstrap样式规则应用于各个表单元素。接下来的是将bootstrap应用于按钮。

    设置new_topic页面的样式

    修改new_topic.html

    {% extends "learning_logs/base.html" %}
    
    {% load bootstrap3 %}
    
    {% block header %}
      <h2>Add a new topic:</h2>
    {% endblock header %}
    
    {% block content %}
    
      <form action="{% url 'learning_logs:new_topic' %}" method='post' class="form">
    
        {% csrf_token %}
        {% bootstrap_form form %}
    
        {% button %}
          <button name="submit" class="btn btn-primary">add topic</button>
        {% endbutton %}
    
      </form>
    
    {% endblock content %}

    设置topics页面的样式

    修改topics.html

    {% extends "learning_logs/base.html" %}
    
    {% block header %}
      <h1>Topics</h1>
    {% endblock header %}
    
    {% block content %}
    
      <ul>
        {% for topic in topics %}
           <li>
             <h3>
               <a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a></li>
             </h3
           </li>
        {% empty %}
           <li>No topics have been added yet.</li>
        {% endfor %}
      </ul>
    
      <h3><a href="{% url 'learning_logs:new_topic' %}">Add a new topic:</a></h3>
    
    {% endblock content %}

    设置topics页面中条目的样式

    我们将使用bootstrap面板(panel)来突出每个条目。面板是一个带预定义样式的div,适合用于显示主题的条目。修改topic.html

    {% extends 'learning_logs/base.html' %}
    
    {% block header %}
      <h2>{{ topic }}</h2>
    {% endblock header %}
    
    {% block content %}
    
      <p>
        <a href="{% url 'learning_logs:new_entry' topic.id %}">add new entry</a>
      </p>
    
      {% for entry in entries %}
    
        <div class="panel panel-default">
          <div class="panel-heading">
            <h3>
              {{ entry.date_added|date:'M d, Y H:i' }}
              <small>
                <a href="{% url 'learning_logs:edit_entry' entry.id %}">
                  edit entry</a>
              </small>
            </h3>
          </div>
          <div class="panel-body">
            {{ entry.text|linebreaks }}
          </div>
        </div> <!-- panel -->
    
      {% empty %}
        There are no entries for this topic yet.
      {% endfor %}
    
    {% endblock content %}

    其他页面的话可以试着参考以上的学习笔记进行修改。或者等我后续补充哈,点关注会有更新通知哦~

    设计样式和部署(二)

    部署学习笔记

    接下来我们将使用Heroku(基于Web的平台)管理Web应用程序的部署。

    建立Heroku账户

    访问https://signup.heroku.com注册一个帐号。

    安装Heroku Toolbelt

    安装Heroku Toolbelt,对部署到Heroku服务器的项目进行管理。访问https://toolbelt.heroku.com/进行安装。

    安装必要的包

    在虚拟环境中使用pip安装dj-database-url、dj-static、gunicorn,帮助在服务器上支持django项目提供的服务。
    其中dj-database-url帮助django与Heroku使用的数据库进行通信,dj-static帮助django正确的管理静态文件,而gunicorn是一个服务器软件,能够在在线环境中支持应用程序提供的服务。

    创建包含列表的文件requirements.txt

    Heroku需要知道项目依赖那些包,因此我们使用pip来生成一个文件,其中列出依赖包。在虚拟环境中执行pip freeze > requirements.txt.

    #requirements.txt
    dj-database-url==0.5.0
    dj-static==0.0.6
    Django==1.11.7
    django-bootstrap3==9.1.0
    gunicorn==19.7.1
    pytz==2018.3
    static3==0.7.0

    我们部署时,Heroku将会安装以上列出的所有包。接着我们在包列表中添加 psycopg2,它帮助Heroku管理活动数据库。

    #requirements.txt
    dj-database-url==0.5.0
    dj-static==0.0.6
    Django==1.11.7
    django-bootstrap3==9.1.0
    gunicorn==19.7.1
    pytz==2018.3
    static3==0.7.0
    psycopg2>=2.6.1

    指定Python版本

    如果没有指定python的版本,heroku将使用当前默认的版本。在虚拟环境中执行python --version. 

    接着在manage.py所在的文件夹 中仙剑一个名为runtime.txt:

    #runtime.txt
    python-3.6.4

    记住小写和减号!

    为部署到Heroku而修改settings.py

    在settings.py末尾添加

    #settings.py
    #--snip--
    # Heroku设置
    if os.getcwd() == '/app':
        import dj_database_url
        DATABASES = {
            'default': dj_database_url.config(default='postgres://localhost')
        }
    
        # 让request.is_secure()承认X-Forwarded-Proto头
            SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
    
        # 支持所有的主机头(host header) 
        ALLOWED_HOSTS = ['*']
    
        # 静态资产配置
        BASE_DIR = os.path.dirname(os.path.abspath(__file__))
        STATIC_ROOT = 'staticfiles'
        STATICFILES_DIRS = (
            os.path.join(BASE_DIR, 'static'),
        )

    首先我们使用了函数getcwd(),用来获取当前的工作目录。在Heroku部署中,这个目录总是/app。在本地部署中,通常是项目文件夹的名称。

    这个if测试确保仅当项目被部署到Heroku时,才运行这个代码块。这种结构让我们能够将同一个设置文件用于本地开发环境和在线服务器。

    接着我们导入了dj_database_url,用于在Heroku配置服务器。Heroku使用PostgreSQL作为数据库。这些设置对项目进行配置,使其在Heroku上使用PostgreSQL。其他设置思维作用分别是:支持HTTPS请求;让djang能够使用Heroku的URL来提供服务;设置项目,使其能够在Heroku上正确提供静态文件。

    创建启动进程的Procfile

    在manage.py的文件中创建Procfile(无后缀)

    web: gunicorn learning_log.wsgi --log-file -

    这行代码让Heroku将gunicorn用作服务器,并使用learning_log/wsgi.py里的设置来启动应用程序。标志log-file告诉Heroku应将那些类型的事件写入日志。

    为部署到Heroku而修改wsgi.py

    修改wsgi.py

    import os
    
    from django.core.wsgi import get_wsgi_application
    from dj_static import Cling
    
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "learning_log.settings")
    
    application = Cling(get_wsgi_application())

    我们导入了帮助正确地提供静态文件的Cling,并使用他来启动应用程序。

    创建用于存储静态文件的目录

    在目录

    接着在manage.py的同一目录下创建文件夹static,并在static文件夹中新建一个placeholder.txt当作占位文件,因为项目被推送到Heroku时不会包含空文件夹。

    This file ensures that learning_log/static/ will be added to the project.
    Django will collect static files and place them in learning_log/static/.

    使用Git跟踪项目文件

    1.安装Git

    如果你安装了Heroku Toolbelt,则里面已经包含Git了。

    2.配置Git

    执行

    • git config --global user.name "ehmatthes"
    • git config --global user.email "eric@example.com"

    3.忽略文件

    记住不要上传数据库文件!!!在manage.py所在的目录创建一个名为.gitignore的文件。

    venv/
    __pycache__/
    *.sqlite3

    4.提交项目 

    命令git init表示在“学习笔记”所在的目录中初始化一个空仓库。命令git add .表示将未被忽略的文件都添加到这个仓库。命令git status输出表明当前位于分支master中,而工作目录是干净的。

    推送到Heroku

    在虚拟环境中执行

    接着执行命令heroku ps 

    接着执行命令heroku open 

    在Heroku上建立数据库

    为建立在线数据库,我们需要再次执行命令migrate。要对Heroku项目执行django和python命令,可使用heroku run命令 

    现在可以将这个应用程序的URL分享给你的小伙伴了~

    改进Heroku部署

    在这部分,我们将创建超级用户来改进部署。为了项目更安全,将DEBUG设置为False,防止他人看到错误信息。

    1.在Heroku上创建超级用户 

    2.在Heroku上创建对用户友好的URL 

    确保项目的安全

    修改settings.py

    # Heroku设置
    if os.getcwd() == '/app':
        import dj_database_url
        DATABASES = {
            'default': dj_database_url.config(default='postgres://localhost')
        }
    
        # 让request.is_secure()承认X-Forwarded-Proto头
        SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
    
        # 只允许Heroku托管这个项目
        ALLOWED_HOSTS = ['learning-log.herokuapp.com']
    
        DEBUG = False
    
        # 静态资产配置
        BASE_DIR = os.path.dirname(os.path.abspath(__file__))
        STATIC_ROOT = 'staticfiles'
        STATICFILES_DIRS = (
            os.path.join(BASE_DIR, 'static'),
        )

    提交并推送修改

    现在将settings.py的修改提交到Git仓库,在将修改推送到Heroku。 

    Heroku发现仓库发生了变化,因此重建项目,但不会重建数据库,所以不用在迁移数据库。

    创建自定义错误页面

    当用户遇到404或者500的错误时,会返回错误页面。404表示代码没错,但请求的对象不存在。500表示代码有问题。现在我们将自定义错误页面。

    1.创建自定义模板

    在learning_log/learning_log中新建一个 templates文件夹,创建404.html、505.html

    #404.html
    {% extends "learning_logs/base.html" %}
    
    {% block header %}
      <h2>The item you requested is not available. (404)</h2>
    {% endblock header %}
    #500.html
    {% extends "learning_logs/base.html" %}
    
    {% block header %}
      <h2>The item you requested is not available. (404)</h2>
    {% endblock header %}

    这些新文件要求对settings.py做修改。

    #--snip--
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [os.path.join(BASE_DIR, 'learning_log/templates')],
            'APP_DIRS': True,
            #--snip--
        },
    ]
    #--snip--

    2.在本地查看错误页面

    对本地的settings.py进行修改

    #--snip--
    # 安全警告,不要在在线环境中启用调试
    DEBUG = False
    ALLOWED_HOSTS = ['localhost']
    #--snip--

    当DUBUG

    被设置False时,必须在ALLOWED_HOSTS中指定一个主机。

    查看错误页面之后,将DUBUG

    设置True,方便进一步开发。(在settings.py中用于Heroku部署的部分中,确保DEBUG = False)。

    3.将修改推送到Heroku 

    4.使用方法get_object_or_404()

    现在当用户手动请求不存在的主题或条目,将导致500错误。这种情形应该视为404错误合适一点。因此我们使用函数get_object_or_404()。修改views.py

    #--snip--
    from django.shortcuts import render, get_object_or_404
    from django.http import HttpResponseRedirect, Http404
    #--snip--
    @login_required
    def topic(request, topic_id):
        """显示单个主题及其所有的条目"""
        topic = get_object_or_404(Topic, id=topic_id)
        # 确定主题属于当前用户
        #--snip--

    修改之后记得提交。

    继续开发

    首先,对本地项目做必要的修改,如果在修改过程中创建了新文件,使用命令git add .将他们加入到Git仓库中。如果有修改要求迁移数据库,也需要执行这个命令,因为每个迁移都将生成新的迁移文件。
    然后,使用命令git commit -am "commit message"将修改提交到仓库,在使用命令git push
    heroku master将修改推送到Heroku。如果你在本地迁移了数据库,也需要迁移在线数据库。为此,你可以执行一次性命令heroku run python manage.py migrate,也可以使用heroku run bash打开一个远程终端,在其中执行python manage.py migrate。然后访问在线项目,确认修改生效。

    设置SECRET_KEY

    Django根据settings.py中设置SECRET_KEY的值来实现大量的安全协议。

    将项目从Heroku删除

    1.在官网上删除。

    2.执行heroku apps:destroy --app appname

    ---

    修复笔记entry.text文本过长导致的溢出。现已自动换行。

    打开base.html并添加

    <!--snip-->
        <title>Learning Log</title>
    
        {% bootstrap_css %}
        {% bootstrap_javascript %}
    
        <style>
          div.lbreak{word-wrap: break-word;}
        </style>
    
      </head>
    <!--snip-->

    打开topic.html并添加

    <!--snip-->
          <div class="panel-body">
            <div class='lbreak'>{{ entry.text|linebreaks }}</div>
          </div>
        </div> <!-- panel -->
    <!--snip-->

     

    《Python编程:从入门到实践》第二章:变量和简单数据类型

    什么是变量

    举例:

    >>> message = "Hello,Python!"
    >>> print (message)
    Hello,Python!

    这里的message就是变量,可以理解成变量就是一个存储数据的容器。在程序中可随时修改变量的值,而python将始终记录变量的最新值。

    变量命令的规则有哪些呢?

    • 变量只能包含字母数字下划线。
    • 变量名不能包含空格,但可以使用下划线来分割其中的单词
    • 不要将python关键字和函数名作为变量名
    • 变量名应既简单又具有描述性
    • 慎用小写字符l和大写字母O,因为他们可能被人错看成数字1和0

    什么是字符串?

    字符串就是一系列字符,在python中用单引号或者双引号括起来。

    因为拥有两种方式,可以灵活在字符串中包含引号和撇号。

    'I told my friend, "Python is my favorite language!"'
    "The language 'Python' is named after Monty Python, not the snake."
    "One of Python's strengths is its diverse and supportive community."

    一些基本的方法

    1.title()首字符大写

    >>> name = "liu bin"
    >>> print (name.title())
    Liu Bin

    2.upper()全部大写转换

    >>> name = "liu bin"
    >>> print (name.upper())
    LIU BIN

    3.lower()全部小写转换

    >>> name = "Liu Bin"
    >>> print (name.lower())
    liu bin

    怎么将字符串合在一起呢?

    简单的"+"加号既可以实现啦。

    >>> first_name = "Bin"
    >>> last_name = "Liu"
    >>> full_name = last_name + " " + first_name
    >>> print (full_name)
    Liu Bin

    制表符和换行符

    制表符:\t 

    >>> print ("python")
    python
    >>> print ("\tpython")
        python

    换行符:\n

    >>> print ("pythonPHP")
    pythonPHP
    >>> print ("python\nPHP")
    python
    PHP

    怎么删除空白?

    • 删除尾部空白:rstrip()
    • 删除头部空白:lstrip()
    • 删除两端空白:strip()

    运算

    整数加减乘除

    >>> 2 + 3
    5
    >>> 3 - 2
    1
    >>> 2 * 3
    6
    >>> 3 / 2
    1.5

    乘方运算

    >>> 3 ** 2
    9
    >>> 3 ** 3
    27
    >>> 10 ** 6
    1000000

    支持括号优先

    >>> 2 + 3*4
    14
    >>> (2 + 3) * 4
    20

    浮点运算

    >>> 0.1 + 0.1
    0.2
    >>> 0.2 + 0.2
    0.4
    >>> 2 * 0.1
    0.2
    >>> 2 * 0.2
    0.4

    浮点运算结果包含的小数位可能是不确定的,所有语言都会存在这种问题,不用担心,后面有解决方法的

    >>> 0.2 + 0.1
    0.30000000000000004
    >>> 3 * 0.1
    0.30000000000000004

    非字符串转换为字符串? 

    str()

    错误的例子:

    >>> age = 23
    >>> message = "Happy" + age +"rd Birthday!"
    Traceback (most recent call last):
      File "<pyshell#79>", line 1, in <module>
        message = "Happy" + age +"rd Birthday!"
    TypeError: must be str, not int

    所以用str()转换

    >>> message = "Happy " + str(age) + "rd Birthday!"
    >>> print (message)
    Happy 23rd Birthday!

    注释

    Python中使用#注释,换行注释可以使用三引号

    # 向大家问好
    print("Hello Python people!")

    课后习题

    2-1

    message = "Code Geass"
    print(message)

    2-2

    message = "Code Geass"
    print(message)
    message = "Psycho-Pass"
    print(message)

    2-3

    name = "Victorique"
    print("Hello, " + name + "!")

    2-4

    name = "Victorique"
    print(name.lower())
    print(name.upper())
    print(name.title())

    2-5

    print('Lelouch said, "Yes, your mejesty."')

    2-6

    famous_person = "Lelouch"
    message = famous_person + ' said, "Yes, your mejesty."'
    print(message)  

    2-7

    name = "\tLelouch\n"
    print(name.lstrip())
    print(name.rstrip())
    print(name.strip())

    2-8

    print(5 + 3)
    print(10 - 2)
    print(2 * 4)
    print(int(16 / 2))

    2-9

    num = 6
    message = "My favorite nummber is " + str(num) + "."
    print(message)

     

    《Python编程:从入门到实践》第三章:列表简介

    什么是列表呢?

    官方说明就是由一些列按特点顺序排列的元素组成。其实可以看出很多个字符串的有序组合吧,里面的内容可以随时的删除,增加,修改。

    下面这个就是一个列表,python打印列表的时候会将中括号和引号打印出来的

    >>> name = ['liubin','liujian','liuliu']
    >>> print (name)
    ['liubin', 'liujian', 'liuliu']

    有序的列表

    和大多数编程语言一样,列表的第一个元素的索引是0,而不是1。如果要输出最后一个元素可以使用-1,倒数第二个可以使用-2,以此类推。

    >>> language = ['python','C++','Java','PHP','Ruby']
    >>> print (language[0])
    python
    >>> print (language[2])
    Java
    >>> print (language[-1])
    Ruby
    >>> print (language[-2].lower())
    php

    列表的修改、添加和删除元素

    修改:其实就是对元素的重新赋值

    motorcycles = ['honda', 'yamaha', 'suzuki']
    print(motorcycles)
    ['honda', 'yamaha', 'suzuki']
    motorcycles[0] = 'ducati'
    print(motorcycles)
    ['ducati', 'yamaha', 'suzuki']

    在末尾添加:append()

    motorcycles = ['honda', 'yamaha', 'suzuki']
    print(motorcycles)
    ['honda', 'yamaha', 'suzuki']
    motorcycles.append('ducati')
    print(motorcycles)
    ['honda', 'yamaha', 'suzuki', 'ducati']

    在列表中插入:insert(索引,字符串)

    motorcycles = ['honda', 'yamaha', 'suzuki']
    motorcycles.insert(0, 'ducati')
    print(motorcycles)

    del语句删除元素,需要知道元素在列表中索引,删除后,无法再次访问它了

    motorcycles = ['honda', 'yamaha', 'suzuki']
    print(motorcycles)
    ['honda', 'yamaha', 'suzuki']
    del motorcycles[0]
    print(motorcycles)
    ['yamaha', 'suzuki']

    pop()弹出元素,默认是弹出最顶层的元素,就是最后一个,如果知道元素在列表中的位置,可以添加索引弹出

    motorcycles = ['honda', 'yamaha', 'suzuki']
    print(motorcycles)
    ['honda', 'yamaha', 'suzuki']
    popped_motorcycle = motorcycles.pop()
    print(motorcycles)
    ['honda', 'yamaha']
    print(popped_motorcycle)
    suzuki
    motorcycles = ['honda', 'yamaha', 'suzuki'
    first_owned = motorcycles.pop(0)
    print('The first motorcycle I owned was a ' + first_owned.title() + '.')
    The first motorcycle I owned was a Honda.

    有的时候你不知道元素的位置,但是知道元素的内容,可以使用remove('字符串')或者remove(变量)来删除,remove()只能删除第一个指定的值,删除的值可能在列表中出现多次,就需要使用后面学习到的循环了。

    motorcycles = ['honda', 'yamaha', 'suzuki', 'ducati']
    print(motorcycles)
    ['honda', 'yamaha', 'suzuki', 'ducati']
    motorcycles.remove('ducati')
    print(motorcycles)
    ['honda', 'yamaha', 'suzuki']

    永久性排序

    方法sort()对列表进行永久的排序

    >>> car = ['bmw','audi','toyota','subaru']
    >>> print (car)
    ['bmw', 'audi', 'toyota', 'subaru']
    >>> car.sort()
    >>> print (car)
    ['audi', 'bmw', 'subaru', 'toyota']
    >>> car.sort(reverse=True)
    >>> print (car)
    ['toyota', 'subaru', 'bmw', 'audi']

    向方法传递参数reverse=Ture可以倒着排序

    临时性排序

    函数sorted()对列表进行临时的排序

    >>> car = ['bmw','audi','toyota','subaru']
    >>> print (sorted(car))
    ['audi', 'bmw', 'subaru', 'toyota']
    >>> print (car)
    ['bmw', 'audi', 'toyota', 'subaru']

    如果你要按与字母顺序相反的顺序显示列表,也可以向函数sorted()传递参数reverse=Ture

    翻转列表

    方法reverse()反正列表

    >>> car = ['bmw','audi','toyota','subaru']
    >>> car.reverse()
    >>> print (car)
    ['subaru', 'toyota', 'audi', 'bmw']

    求列表的长度

    函数len()可以知道列表的长度,python计算元素个数的时候,是从1开始的。

    >>> car = ['bmw','audi','toyota','subaru']
    >>> len(car)
    4

    课后练习及答案

    #3-1 姓名

    names = ['Qiqi','Danliang','Mingliang','Peng']
    for x in range(0,4):
    print(names[x])

    #3-2 问候语

    names = ['qiqi','qanliang','mingliang','peng']
    for x in range(0,4):
    print("Hello," + names[x].title() + "大吉大利!")

    #3-3 自己的列表

    trip_mode = ['小黄车','摩拜','暴龙兽','大宝剑']
    for x in range(0,4):
    print("我今天想骑" + trip_mode[x] + "去抓皮卡丘!")

    #3-4 嘉宾名单

    names = []
    names.append('新垣结衣')
    names.append('奥黛丽赫本')
    names.append('迪丽热巴')
    for x in range(0,3):
    print('Dear ' + names[x] + ',Can you come to my dinner?')

    #3-5 修改嘉宾名单

    names = []
    names.append('新垣结衣')
    names.append('奥黛丽赫本')
    names.append('迪丽热巴')
    for x in range(0,3):
    print('Dear ' + names[x] + ',Can you come to my dinner?')
    print(names[1] + '无法赴约。')
    names[1] = ('赵丽颖')  #改名单
    for x in range(0,3):
    print('Dear ' + names[x] + ',Can you come to my dinner?')

    #3-6 添加嘉宾

    names = []
    names.append('新垣结衣')
    names.append('奥黛丽赫本')
    names.append('迪丽热巴')
    for x in range(0,3):
    print('Dear ' + names[x] + ',Can you come to my dinner?')
    print('\n' + names[1] + '无法赴约。\n')
    names[1] = ('赵丽颖')  #改名单
    for x in range(0,3):
    print('Dear ' + names[x] + ',Can you come to my dinner?')
    print('\nHaha~,I found a bigger table, I can invite more people!\n')
    names.insert(0,'紫霞')
    names.insert(2,'静香')
    names.append('提莫')
    for x in range(0,len(names)):
    print('Dear ' + names[x] + ',Can you come to my dinner?')

    #3-7 缩减名单

    names = []
    names.append('新垣结衣')
    names.append('奥黛丽赫本')
    names.append('迪丽热巴')
    for x in range(0,3):
        print('Dear ' + names[x] + ',Can you come to my dinner?')
    print('\n' + names[1] + '无法赴约。\n')
    names[1] = ('赵丽颖')  #改名单
    for x in range(0,3):
        print('Dear ' + names[x] + ',Can you come to my dinner?')
    print('\nHaha~,I found a bigger table, I can invite more people!\n')
    names.insert(0,'紫霞')
    names.insert(2,'静香')
    names.append('提莫')
    for x in range(0,len(names)):
        print('Dear ' + names[x] + ',Can you come to my dinner?')
    print('\nOh! GouRiDe快递没给我把桌子送来,我只能邀请两位了(┬_┬)!\n')
    X = len(names)
    for x in range(0,X-2):
        popped_name = names.pop()
        print('实在抱歉,' + popped_name +'我不能与你共进晚餐了!')
    for x in range(0,len(names)):
        print('Dear ' + names[x] + ',我依然邀请你来与我共进晚餐!')
    del names[1]  #del列表应从后往前!
    del names[0]
    print(names)

    #3-8 放眼世界

    cities = ['chongqing','chengdu','xiamen','kuning','shenzhen']
    print(cities)
    print(sorted(cities))
    print(cities)
    print(sorted(cities,reverse=True))
    print(cities)
    cities.reverse()
    print(cities)
    cities.reverse()
    print(cities)
    cities.sort()
    print(cities)
    cities.sort(reverse=True)
    print(cities)

    #3-9 晚餐嘉宾

    names = []
    names.append('新垣结衣')
    names.append('奥黛丽赫本')
    names.append('迪丽热巴')
    for x in range(0,3):
        print('Dear ' + names[x] + ',Can you come to my dinner?')
    print('\n' + names[1] + '无法赴约。\n')
    names[1] = ('赵丽颖')  #改名单
    for x in range(0,3):
        print('Dear ' + names[x] + ',Can you come to my dinner?')
    print('\nHaha~,I found a bigger table, I can invite more people!\n')
    names.insert(0,'紫霞')
    names.insert(2,'静香')
    names.append('提莫')
    for x in range(0,len(names)):
        print('Dear ' + names[x] + ',Can you come to my dinner?')
    print('\nOh! GouRiDe快递没给我把桌子送来,我只能邀请两位了(┬_┬)!\n')
    X = len(names)
    for x in range(0,X-2):
        popped_name = names.pop()
        print('实在抱歉,' + popped_name +'我不能与你共进晚餐了!')
    for x in range(0,len(names)):
        print('Dear ' + names[x] + ',我依然邀请你来与我共进晚餐!')
    print('\n最后,我将邀请' + str(len(names)) + '个人参加晚宴!')
    del names[1]  #del列表应从后往前!
    del names[0]
    print(names)

     

    《Python编程:从入门到实践》第六章:字典

    6-1 人

    使用一个字典来存储一个熟人的信息,包括名、姓、年龄和居住的城市。该字典应包含键first_name 、last_name 、age 和city 。将存储在该字典中 的每项信息都打印出来。

    person = {
    	'first_name':'HandSome',
    	'last_name':'Girl',
    	'age':21,
    	'city':'Zhuhai',
    }
    print(person)

    结果:

    {'first_name': 'HandSome', 'last_name': 'Girl', 'age': 21, 'city': 'Zhuhai'}

    6-2 喜欢的数字

    使用一个字典来存储一些人喜欢的数字。请想出5个人的名字,并将这些名字用作字典中的键;想出每个人喜欢的一个数字,并将这些数字作为值存储在字典中。打印每个人的名字和喜欢的数字。为让这个程序更有趣,通过询问朋友确保数据是真实的。

    perfer_num= {
    	'Nancy':1,
    	'Lucky':2,
    	'Handsome_Girl':3,
    	'Mary':4,
    	'Tony':5,
    }
    print(perfer_num)

    结果:

    {'Handsome_Girl': 3, 'Nancy': 1, 'Tony': 5, 'Lucky': 2, 'Mary': 4}

    6-3 词汇表

    Python字典可用于模拟现实生活中的字典,但为避免混淆,我们将后者称为词汇表。

    想出你在前面学过的5个编程词汇,将它们用作词汇表中的键,并将它们的含义作为值存储在词汇表中。

    以整洁的方式打印每个词汇及其含义。为此,你可以先打印词汇,在它后面加上一个冒号,再打印词汇的含义;也可在一行打印词汇,再使用换行符(\n )插 入一个空行,然后在下一行以缩进的方式打印词汇的含义。

    vocabulary ={
    	'P':'Python',
    	'J':'Java',
    	'C':'C',
    	'V':'Visual Basic',
    }
    for key,value in vocabulary.items():
    	print(key,':',value)

    结果:

    P : Python
    J : Java
    V : Visual Basic
    C : C

    6-4 词汇表2

    既然你知道了如何遍历字典,现在请整理你为完成练习6-3而编写的代码,将其中的一系列print 语句替换为一个遍历字典中的键和值的循环。确定该 循环正确无误后,再在词汇表中添加5个Python术语。当你再次运行这个程序时,这些新术语及其含义将自动包含在输出中。

    vocabulary ={
    	'P':'Python',
    	'J':'Java',
    	'C':'C',
    	'V':'Visual Basic',
    	'R':'Ruby',
    	'P':'111'
    }
    for key,value in vocabulary.items():
    	print(key,':',value)

    结果:

    V : Visual Basic
    C : C
    P : 111
    J : Java
    R : Ruby

    6-5 河流

    创建一个字典,在其中存储三条大河流及其流经的国家。其中一个键—值对可能是'nile': 'egypt' 。

    使用循环为每条河流打印一条消息,如“The Nile runs through Egypt.”。

    使用循环将该字典中每条河流的名字都打印出来。

    使用循环将该字典包含的每个国家的名字都打印出来。

    river = {
    	'nile':'egypt',
    	'yellow river':'lanchow',
    	'Mississippi River':'north America'
    }
    for key,value in river.items():
    	print("The %s runs through %s"%(key.title(),value.title()))

    结果:

    The Nile runs through Egypt
    The Mississippi River runs through North America
    The Yellow River runs through Lanchow

    6-6 调查

    在6.3.1节编写的程序favorite_languages.py中执行以下操作。

    创建一个应该会接受调查的人员名单,其中有些人已包含在字典中,而其他人未包含在字典中。

    遍历这个人员名单,对于已参与调查的人,打印一条消息表示感谢。对于还未参与调查的人,打印一条消息邀请他参与调查。

    favorite_languages = {
    	'jen':'python',
    	'sarah':'c',
    	'edward':'ruby',
    	'phill':'python',
    }
    interviewer = ['jen','sarah','edward','phill','alice','bob']
    for user in interviewer:
    	if user in favorite_languages.items():
    		print('%s thank you for your intend'%user)
    	else:
    		print('welcome to here %s'%user)

    结果:

    welcome to here jen
    welcome to here sarah
    welcome to here edward
    welcome to here phill
    welcome to here alice
    welcome to here bob

    6-7 人 

    在为完成练习6-1而编写的程序中,再创建两个表示人的字典,然后将这三个字典都存储在一个名为people 的列表中。遍历这个列表,将其中每个人的所有 信息都打印出来。

    people = {
    	'person1' : {
    	'first_name':'HandSome',
    	'last_name':'Girl',
    	'age':21,
    	'city':'Zhuhai',
    	},
    	'person2':{
    	'first_name':'albert',
    	'last_name':'einstein',
    	'age':34,
    	'city':'princeton'
    	},
    	'person3':{
    	'first_name':'marie',
    	'last_name':'curie',
    	'age':36,
    	'city':'paris'
    	},
    }
    for key,value in people.items():
    	print(key+":")
    	for key1,value2 in value.items():
    		print("\t %s:%s"%(key1,value))

    结果:

    person3:
    	 first_name:{'first_name': 'marie', 'last_name': 'curie', 'age': 36, 'city': 'paris'}
    	 last_name:{'first_name': 'marie', 'last_name': 'curie', 'age': 36, 'city': 'paris'}
    	 age:{'first_name': 'marie', 'last_name': 'curie', 'age': 36, 'city': 'paris'}
    	 city:{'first_name': 'marie', 'last_name': 'curie', 'age': 36, 'city': 'paris'}
    person1:
    	 first_name:{'first_name': 'HandSome', 'last_name': 'Girl', 'age': 21, 'city': 'Zhuhai'}
    	 last_name:{'first_name': 'HandSome', 'last_name': 'Girl', 'age': 21, 'city': 'Zhuhai'}
    	 age:{'first_name': 'HandSome', 'last_name': 'Girl', 'age': 21, 'city': 'Zhuhai'}
    	 city:{'first_name': 'HandSome', 'last_name': 'Girl', 'age': 21, 'city': 'Zhuhai'}
    person2:
    	 first_name:{'first_name': 'albert', 'last_name': 'einstein', 'age': 34, 'city': 'princeton'}
    	 last_name:{'first_name': 'albert', 'last_name': 'einstein', 'age': 34, 'city': 'princeton'}
    	 age:{'first_name': 'albert', 'last_name': 'einstein', 'age': 34, 'city': 'princeton'}
    	 city:{'first_name': 'albert', 'last_name': 'einstein', 'age': 34, 'city': 'princeton'}

    6-8 宠物

    创建多个字典,对于每个字典,都使用一个宠物的名称来给它命名;在每个字典中,包含宠物的类型及其主人的名字。将这些字典存储在一个名为pets 的列表中,再遍历该列表,并将宠物的所有信息都打印出来。

    cat = {'name':'kitty','owner':'lucy'}
    dog = {'name':'Da Huang','owner':'nancy'}
    rabbit = {'name':'little white','owner':'mary'}
    pets = [cat,dog,rabbit]
    for pet in pets:
    	for key ,value in pet.items():
    		print('%s:%s'%(key,value.title()))

    结果:

    name:Kitty
    owner:Lucy
    name:Da Huang
    owner:Nancy
    name:Little White
    owner:Mary

    6-9 喜欢的地方

    创建一个名为favorite_places 的字典。在这个字典中,将三个人的名字用作键;对于其中的每个人,都存储他喜欢的1~3个地方。为让这个练 习更有趣些,可让一些朋友指出他们喜欢的几个地方。遍历这个字典,并将其中每个人的名字及其喜欢的地方打印出来。

    favorite_palces = {
    	'alice':['shanghai','guangzhou','shenzhen'],
    	'nancy':['zhuhai','xiamen','beijing'],
    	'bob':['ningxia','yunnan']
    }
    for key,value in favorite_palces.items():
    	print(key+":")
    	if len(value) > 0:
    		for place in value:
    			print("\t",place)

    结果:

    alice:
    	 shanghai
    	 guangzhou
    	 shenzhen
    nancy:
    	 zhuhai
    	 xiamen
    	 beijing
    bob:
    	 ningxia
    	 yunnan

    6-10 喜欢的数字

    修改为完成练习6-2而编写的程序,让每个人都可以有多个喜欢的数字,然后将每个人的名字及其喜欢的数字打印出来。

    perfer_num= {
    	'Nancy':[1,2,3],
    	'Lucky':[2,3,4],
    	'Handsome_Girl':[3,4,5],
    	'Mary':[4,5,6],
    	'Tony':[5,6,7],
    }
    for key,value in perfer_num.items():
    	print(key+":")
    	if len(value) > 0:
    		for num in value:
    			print("\t",num)

    结果:

    Handsome_Girl:
    	 3
    	 4
    	 5
    Lucky:
    	 2
    	 3
    	 4
    Nancy:
    	 1
    	 2
    	 3
    Tony:
    	 5
    	 6
    	 7
    Mary:
    	 4
    	 5
    	 6

    6-11 城市

    创建一个名为cities 的字典,其中将三个城市名用作键;对于每座城市,都创建一个字典,并在其中包含该城市所属的国家、人口约数以及一个有关该 城市的事实。在表示每座城市的字典中,应包含country 、population 和fact 等键。将每座城市的名字以及有关它们的信息都打印出来。

    cities = {
    	'A':{
    	'country':'china',
    	'population':32100,
    	'fact':'A'
    	},
    	'B':{
    	'country':'england',
    	'population':36464,
    	'fact':'B'
    	},
    	'C':{
    	'country':'america',
    	'population':465487,
    	'fact':'C'
    	},
    }
    for key,value in cities.items():
    	print(key,":")
    	for key1,value1 in value.items():
    		print("\t",key1,":",value1)

    结果:

    B :
    	 population : 36464
    	 fact : B
    	 country : england
    A :
    	 population : 32100
    	 fact : A
    	 country : china
    C :
    	 population : 465487
    	 fact : C
    	 country : america

     

    《Python编程:入门到实践》第七章:用户输入和while循环

    7-1 汽车租赁

    编写一个程序,询问用户要租赁什么样的汽车,并打印一条消息,如“Let me see if I can find you a Subaru”。

    if __name__ == "__main__":
        car = input("please tell me what car your want")
        print("Let me see if I can find you a %s"%car)

    结果:

    please tell me what car your wantSubaru
    Let me see if I can find you a Subaru

    7-2 餐馆订位

    编写一个程序,询问用户有多少人用餐。如果超过8人,就打印一条消息,指出没有空桌;否则指出有空桌。

    if __name__ == "__main__":
        inp = input("please tell me how many people will have dinner: ")
        num = int(inp)
        if num > 8:
            print("without empty desk")
        else:
            print("have desk")

    结果:

    please tell me how many people will have dinner: 13
    without empty desk
    

    #2

    please tell me how many people will have dinner: 2
    have desk

    7-3 10的整数倍

    让用户输入一个数字,并指出这个数字是否是10的整数倍。

    #-*- coding:utf-8 -*-
    if __name__ == "__main__":
        inp = input("please enter a number: ")
        num = int(inp)
        if (num % 10) == 0:
            print("是十的整数倍")
        else:
            print("不是十的整数倍")

    结果:

    please enter a number: 10
    是十的整数倍

    #2

    please enter a number: 13
    不是十的整数倍

    7-4 比萨配料

    编写一个循环,提示用户输入一系列的比萨配料,并在用户输入'quit' 时结束循环。每当用户输入一种配料后,都打印一条消息,说我们会在比萨 中添加这种配料。

    #-*- coding:utf-8 -*-
    if __name__ == "__main__":
        print("请输入一些了的比赛配料,当输入'quit'时结束")
        peiliao=''
        while peiliao != 'quit':
            peiliao = input()
            if peiliao !=  'quit':
                print(peiliao)

    结果:


     

    7-5 电影票

    有家电影院根据观众的年龄收取不同的票价:不到3岁的观众免费;3~12岁的观众为10美元;超过12岁的观众为15美元。请编写一个循环,在其中询问用 户的年龄,并指出其票价。

    #-*- coding:utf-8 -*-
    if __name__ == "__main__":
        age = input('please enter your age')
        while age != 'quit':
            age1 = int(age)
            if age1 >=3  and age1 <= 12:
                print('%d need 10 dollar'%age1)
            elif age1 >12:
                print('%d age need 15 dollar'%age1)
            age = input('please enter your age')

    结果:

    7-6 三个出口

    以另一种方式完成练习7-4或练习7-5,在程序中采取如下所有做法。

    在while 循环中使用条件测试来结束循环。

    使用变量active 来控制循环结束的时机。

    使用break 语句在用户输入'quit' 时退出循环。

    #-*- coding:utf-8 -*-
    if __name__ == "__main__":
        age = input('please enter your age')
        flag = True
        while flag:
            age1 = int(age)
            if age1 >=3  and age1 <= 12:
                print('%d need 10 dollar'%age1)
            elif age1 >12:
                print('%d age need 15 dollar'%age1)
            age = input('please enter your age')
            if age == 'quit':
                flag = False
                break

    结果:

    7-7 无限循环

    编写一个没完没了的循环,并运行它(要结束该循环,可按Ctrl +C,也可关闭显示输出的窗口)。

    #-*- coding:utf-8 -*-
    if __name__ == "__main__":
        while True:
            print("yes")

    7-8 熟食店

    创建一个名为sandwich_orders 的列表,在其中包含各种三明治的名字;再创建一个名为finished_sandwiches 的空列表。遍历列 表sandwich_orders ,对于其中的每种三明治,都打印一条消息,如I made your tuna sandwich ,并将其移到列表finished_sandwiches 。所有三明

    治都制作好后,打印一条消息,将这些三明治列出来。

    #-*- coding:utf-8 -*-
    if __name__ == "__main__":
        sandwich_orders = ['egg','banana','apple','orange']
        finished_sandwiches  = []
        while sandwich_orders:
            sandwich = sandwich_orders.pop()
            print("I made your %s sandwich"%sandwich)
            finished_sandwiches.append(sandwich)
        print("All sandwiches have been finished")
        for san in finished_sandwiches:
            print(san)

    结果:

    7-9 五香烟熏牛肉(pastrami)卖完了

    使用为完成练习7-8而创建的列表sandwich_orders ,并确保'pastrami' 在其中至少出现了三次。在程序开头附近添加 这样的代码:打印一条消息,指出熟食店的五香烟熏牛肉卖完了;再使用一个while 循环将列表sandwich_orders 中的'pastrami' 都删除。确认最终的列 表finished_sandwiches 中不包含'pastrami'

    #-*- coding:utf-8 -*-
    if __name__ == "__main__":
        sandwich_orders = ['pastrami','egg','pastrami','banana','pastrami','apple','pastrami','orange']
        print("All pastrami sandwiches have been saled")
        while 'pastrami' in sandwich_orders:
            sandwich_orders.remove('pastrami')
        for sandwich in sandwich_orders:
            print(sandwich)

    结果:

    7-10 梦想的度假胜地

    编写一个程序,调查用户梦想的度假胜地。使用类似于“If you could visit one place in the world, where would you go?”的提示,并编写一个打印调查 结果的代码块。

    #-*- coding:utf-8 -*-
    if __name__ == "__main__":
        place = {}
        flag = True
        while flag:
            name = input("what's your name? ")
            places = input("If you could visit one place in the world,where would you go? ")
            place[name] = places
            answer = input("continue?(yes/no)")
            if answer ==  'no':
                flag = False
    
        print("Finish!")
        for name,places in place.items():
            print(name," want to go to ",place)
    
    

    结果:


     

    《Python编程:从入门到实践》第八章:函数

    8-1 消息

    编写一个名为display_message() 的函数,它打印一个句子,指出你在本章学的是什么。调用这个函数,确认显示的消息正确无误。

    # -*- coding : utf-8 -*-
    def display_messages():
        print("本章学习的是函数")
    
    if __name__ == "__main__":
        display_messages()

    结果:


     

    8-2 喜欢的图书

    编写一个名为favorite_book() 的函数,其中包含一个名为title 的形参。这个函数打印一条消息,如One of my favorite books is Alice in Wonderland 。调用这个函数,并将一本图书的名称作为实参传递给它。

    # -*- coding : utf-8 -*-
    def favorite_book(title):
        print("One of my favorite books is %s"%title)
    
    if __name__ == "__main__":
        book = input("what's your favorite book? ")
        favorite_book(book)

    结果:

    8-3 T恤

    编写一个名为make_shirt() 的函数,它接受一个尺码以及要印到T恤上的字样。这个函数应打印一个句子,概要地说明T恤的尺码和字样。 使用位置实参调用这个函数来制作一件T恤;再使用关键字实参来调用这个函数。

    def make_shirt(size,logo):
    	print("size:",size," logo:",logo)
    make_shirt(12,'LOGO')

    结果:

    8-4 大号T恤

    修改函数make_shirt() ,使其在默认情况下制作一件印有字样“I love Python”的大号T恤。调用这个函数来制作如下T恤:一件印有默认字样的大号T 恤、一件印有默认字样的中号T恤和一件印有其他字样的T恤(尺码无关紧要)

    def make_shirt(size,logo="I love Python"):
    	print("size:",size," logo:",logo)
    make_shirt("大号")
    make_shirt("中号")
    make_shirt("小号")

    结果:

    8-5 城市

    编写一个名为describe_city() 的函数,它接受一座城市的名字以及该城市所属的国家。这个函数应打印一个简单的句子,如Reykjavik is in Iceland 。给用于存储国家的形参指定默认值。为三座不同的城市调用这个函数,且其中至少有一座城市不属于默认国家。

    def describe_city(name,country="Iceland"):
    	print(name.title()," is in ",country)
    
    describe_city("Reykjavik")
    describe_city("Mary")
    describe_city("Alice","China")

    结果:

    8-6 城市名

    编写一个名为city_country() 的函数,它接受城市的名称及其所属的国家。这个函数应返回一个格式类似于下面这样的字符串:

    "Santiago, Chile"

    至少使用三个城市-国家对调用这个函数,并打印它返回的值。

    def city_country(city,country):
    	result = city+', '+country
    	return result
    result_list = []
    re = city_country('Zhuhai','China')
    result_list.append(re)
    re = city_country('Tokyo','Japan')
    result_list.append(re)
    re = city_country('Beijin','China')
    result_list.append(re)
    for r in result_list:
    	print(r)
    

    结果:

    8-7 专辑

    编写一个名为make_album() 的函数,它创建一个描述音乐专辑的字典。这个函数应接受歌手的名字和专辑名,并返回一个包含这两项信息的字典。使 用这个函数创建三个表示不同专辑的字典,并打印每个返回的值,以核实字典正确地存储了专辑的信息。

    给函数make_album() 添加一个可选形参,以便能够存储专辑包含的歌曲数。如果调用这个函数时指定了歌曲数,就将这个值添加到表示专辑的字典中。调用这个 函数,并至少在一次调用中指定专辑包含的歌曲数。

    def make_album(name,cd):
    	dvd = {}
    	dvd[name] = cd
    	return dvd
    
    result = []
    r = make_album('Arran','The next of me')
    result.append(r)
    r = make_album('A','B')
    result.append(r)
    r = make_album('C','D')
    result.append(r)
    for r in result:
    	print(r)

    结果:


     

    8-8 用户的专辑

    在为完成练习8-7编写的程序中,编写一个while 循环,让用户输入一个专辑的歌手和名称。获取这些信息后,使用它们来调用函 数make_album() ,并将创建的字典打印出来。在这个while 循环中,务必要提供退出途径。

    def make_album(name,cd):
    	dv = {}
    	dv[name] = cd
    	return dv
    
    if __name__ == "__main__":
        result = []
        while True:
            name = input("name:")
            cd = input("cd:")
            r = make_album(name, cd)
            result.append(r)
            continu = input()
            if continu == 'no':
                break
        for r in result:
            print(r)

    结果:


     

    8-9 魔术师

    创建一个包含魔术师名字的列表,并将其传递给一个名为show_magicians() 的函数,这个函数打印列表中每个魔术师的名字。

    def  show_magicians(name_list):
    	for name in name_list:
    		print(name)
    
    name_list = ['Alice','Tom','Bob','Hence']
    show_magicians(name_list)

    结果:

    8-10 了不起的魔术师

    在你为完成练习8-9而编写的程序中,编写一个名为make_great() 的函数,对魔术师列表进行修改,在每个魔术师的名字中都加入字样“the Great”。调用函数show_magicians() ,确认魔术师列表确实变了。

    def  show_magicians(name_list):
    	for name in name_list:
    		print(name)
    		
    def make_great(name_list,name_change):
    	while name_list:
    		current_name = name_list.pop();
    		current_name = "the Great " + current_name
    		name_change.append(current_name)
    
    name_list = ['Alice','Tom','Bob','Hence']
    name_change = []
    make_great(name_list,name_change)
    show_magicians(name_change)

    结果:

    8-11 不变的魔术师

    修改你为完成练习8-10而编写的程序,在调用函数make_great() 时,向它传递魔术师列表的副本。由于不想修改原始列表,请返回修改后的 列表,并将其存储到另一个列表中。分别使用这两个列表来调用show_magicians() ,确认一个列表包含的是原来的魔术师名字,而另一个列表包含的是添加了字 样“the Great”的魔术师名字。

    def  show_magicians(name_list):
    	for name in name_list:
    		print(name)
    
    def make_great(name_list,name_change):
    	while name_list:
    		current_name = name_list.pop();
    		current_name = "the Great " + current_name
    		name_change.append(current_name)
    
    name_list = ['Alice','Tom','Bob','Hence']
    name_change = []
    make_great(name_list[:],name_change)
    show_magicians(name_list)
    print("----------------------")
    show_magicians(name_change)

    结果:

    8-12 三明治

    编写一个函数,它接受顾客要在三明治中添加的一系列食材。这个函数只有一个形参(它收集函数调用中提供的所有食材),并打印一条消息,对顾客 点的三明治进行概述。调用这个函数三次,每次都提供不同数量的实参。

    def make_pizza(*toppings):
    	print("\nMaking a pizza with the following toppings")
    	for topping in toppings:
    		print(topping)
    make_pizza('pepperoni')
    make_pizza('mushrooms','green peppers','extra cheese')
    make_pizza('A','B','C','D')

    结果:


     

    8-13 用户简介

    复制前面的程序user_profile.py,在其中调用build_profile() 来创建有关你的简介;调用这个函数时,指定你的名和姓,以及三个描述你的键-值 对。

    def build_profile(first_name,last_name,**user_info):
    	profile = {}
    	profile['first_name']  = first_name
    	profile['last_name']  = last_name
    	for key,value in user_info.items():
    		profile[key] = value
    	return profile
    
    user_profile = build_profile('albert','enistein',location = 'princeton',field = 'physics')
    print(user_profile)
    

    结果:

    8-14 汽车

    编写一个函数,将一辆汽车的信息存储在一个字典中。这个函数总是接受制造商和型号,还接受任意数量的关键字实参。这样调用这个函数:提供必不可 少的信息,以及两个名称—值对,如颜色和选装配件。这个函数必须能够像下面这样进行调用:

    car = make_car('subaru','outback',color = 'blue', tow_package = True)

    def make_car(first,last,**info):
    	information = {}
    	information['first'] =  first
    	information['last'] = last
    	for key,value in info.items():
    		information[key] = value
    	return information
    car = make_car('subaru','outback',color = 'blue',tow_package = True)
    print(car)

    结果:

    《Python编程:从入门到实践》第九章:类

    9-1 餐馆

    创建一个名为Restaurant 的类,其方法__init__() 设置两个属性:restaurant_name 和cuisine_type 。创建一个名 为describe_restaurant() 的方法和一个名为open_restaurant() 的方法,其中前者打印前述两项信息,而后者打印一条消息,指出餐馆正在营业。

    class  Restraurant():
    	"""docstring for  Restraurant"""
    	def __init__(self, restaurant_name,cuisine_type):
    		self.restaurant_name = restaurant_name
    		self.cuisine_type = cuisine_type
    	def describe_restaurant(self):
    		print(self.restaurant_name,":",self.cuisine_type)
    	def open_restaurant(self):
    		print("Is opening")
    
    restraurant = Restraurant('A','B')
    print(restraurant.restaurant_name," ",restraurant.cuisine_type)
    restraurant.describe_restaurant()
    restraurant.open_restaurant()		

    结果:


     

    9-2 三家餐馆

    根据你为完成练习9-1而编写的类创建三个实例,并对每个实例调用方法describe_restaurant() 。

    class  Restraurant():
    	"""docstring for  Restraurant"""
    	def __init__(self, restaurant_name,cuisine_type):
    		self.restaurant_name = restaurant_name
    		self.cuisine_type = cuisine_type
    	def describe_restaurant(self):
    		print(self.restaurant_name,":",self.cuisine_type)
    	def open_restaurant(self):
    		print("Is opening")
    
    restraurant1 = Restraurant('A1','B1')
    restraurant1.describe_restaurant()
    restraurant2 = Restraurant('A2','B2')
    restraurant2.describe_restaurant()
    restraurant3 = Restraurant('A3','B3')
    restraurant3.describe_restaurant()
    		

    结果:

    9-3 用户

    创建一个名为User 的类,其中包含属性first_name 和last_name ,还有用户简介通常会存储的其他几个属性。在类User 中定义一个名 为describe_user() 的方法,它打印用户信息摘要;再定义一个名为greet_user() 的方法,它向用户发出个性化的问候。
    创建多个表示不同用户的实例,并对每个实例都调用上述两个方法。

    class User():
    	"""docstring for User"""
    	def __init__(self, first_name,last_name):
    		self.first_name = first_name
    		self.last_name = last_name
    
    	def describe_name(self):
    		print("fitst_name :",self.first_name," last_name: ",self.last_name)
    
    	def greet_user(self):
    		print("hello, ",self.first_name," ",self.last_name)
    
    user1 = User('Alice','Tom')
    user1.describe_name()
    user1.greet_user()
    user2 = User("Mary",'Bob')
    user2.describe_name()
    user2.greet_user()
    user3 = User("Tony",'Belbert')
    user3.describe_name()
    user3.greet_user()
    

    结果:

    9-4 就餐人数

    在为完成练习9-1而编写的程序中,添加一个名为number_served 的属性,并将其默认值设置为0。根据这个类创建一个名为restaurant 的实 例;打印有多少人在这家餐馆就餐过,然后修改这个值并再次打印它。

    添加一个名为set_number_served() 的方法,它让你能够设置就餐人数。调用这个方法并向它传递一个值,然后再次打印这个值。

    添加一个名为increment_number_served() 的方法,它让你能够将就餐人数递增。调用这个方法并向它传递一个这样的值:你认为这家餐馆每天可能接待的就 餐人数。

    class  Restraurant():
    	"""docstring for  Restraurant"""
    	def __init__(self, restaurant_name,cuisine_type):
    		self.restaurant_name = restaurant_name
    		self.cuisine_type = cuisine_type
    		self.number_served = 0
    	def describe_restaurant(self):
    		print(self.restaurant_name,":",self.cuisine_type)
    	def open_restaurant(self):
    		print("Is opening")
    	def set_number_served(self,number):
    		self.number_served = number
    	def get_number_served(self):
    		return self.number_served
    	def increment_number_served(self,number):
    		while self.number_served < number:
    			print(self.number_served)
    			self.number_served +=1
    
    restraurant = Restraurant('A','B')
    print(restraurant.restaurant_name," ",restraurant.cuisine_type)
    restraurant.describe_restaurant()
    restraurant.open_restaurant()
    print(restraurant.get_number_served())
    restraurant.set_number_served(2)
    print(restraurant.get_number_served())
    restraurant.increment_number_served(10)

    结果:


     

    9-5 尝试登录次数

    在为完成练习9-3而编写的User 类中,添加一个名为login_attempts 的属性。编写一个名为increment_login_attempts() 的方法, 它将属性login_attempts 的值加1。再编写一个名为reset_login_attempts() 的方法,它将属性login_attempts 的值重置为0。

    根据User 类创建一个实例,再调用方法increment_login_attempts() 多次。打印属性login_attempts 的值,确认它被正确地递增;然后,调用方 法reset_login_attempts() ,并再次打印属性login_attempts 的值,确认它被重置为0。

    class User():
    	"""docstring for User"""
    	def __init__(self, first_name,last_name):
    		self.first_name = first_name
    		self.last_name = last_name
    		self.login_attempts = 0
    
    	def describe_name(self):
    		print("fitst_name :",self.first_name," last_name: ",self.last_name)
    
    	def greet_user(self):
    		print("hello, ",self.first_name," ",self.last_name)
    
    	def  increment_login_attempts(self):
    		self.login_attempts += 1
    	def reset_login_attempts(self):
    		self.login_attempts = 0
    
    user1 = User('Alice','Tom')
    user1.describe_name()
    print("login_attempts:",user1.login_attempts)
    user1.increment_login_attempts()
    print("login_attempts:",user1.login_attempts)
    user1.increment_login_attempts()
    print("login_attempts:",user1.login_attempts)
    user1.reset_login_attempts()
    print("login_attempts:",user1.login_attempts)

    结果:


     

    9-6 冰淇淋小店

    冰淇淋小店是一种特殊的餐馆。编写一个名为IceCreamStand 的类,让它继承你为完成练习9-1或练习9-4而编写的Restaurant 类。这两个版 本的Restaurant 类都可以,挑选你更喜欢的那个即可。添加一个名为flavors 的属性,用于存储一个由各种口味的冰淇淋组成的列表。编写一个显示这些冰淇淋 的方法。创建一个IceCreamStand 实例,并调用这个方法。

    class  Restraurant():
    	"""docstring for  Restraurant"""
    	def __init__(self, restaurant_name,cuisine_type):
    		self.restaurant_name = restaurant_name
    		self.cuisine_type = cuisine_type
    		self.number_served = 0
    	def describe_restaurant(self):
    		print(self.restaurant_name,":",self.cuisine_type)
    	def open_restaurant(self):
    		print("Is opening")
    	def set_number_served(self,number):
    		self.number_served = number
    	def get_number_served(self):
    		return self.number_served
    	def increment_number_served(self,number):
    		while self.number_served < number:
    			print(self.number_served)
    			self.number_served +=1
    
    class IceCreamStand(Restraurant):
    	def __init__(self, restaurant_name,cuisine_type):
    		super().__init__(restaurant_name,cuisine_type)
    		self.flavors = ['banaa','apple','orange']
    	def show_icecram(self):
    		for s in self.flavors:
    			print(s)
    
    icecream = IceCreamStand('Hang','Big')
    icecream.show_icecram()
    icecream.describe_restaurant()
    
    

    结果:


     

    9-7 管理员

    管理员是一种特殊的用户。编写一个名为Admin 的类,让它继承你为完成练习9-3或练习9-5而编写的User 类。添加一个名为privileges 的属性,用 于存储一个由字符串(如"can add post" 、"can delete post" 、"can ban user" 等)组成的列表。编写一个名为show_privileges() 的方法,它 显示管理员的权限。创建一个Admin 实例,并调用这个方法。

    class User():
    	"""docstring for User"""
    	def __init__(self, first_name,last_name):
    		self.first_name = first_name
    		self.last_name = last_name
    		self.login_attempts = 0
    
    	def describe_name(self):
    		print("fitst_name :",self.first_name," last_name: ",self.last_name)
    
    	def greet_user(self):
    		print("hello, ",self.first_name," ",self.last_name)
    
    	def  increment_login_attempts(self):
    		self.login_attempts += 1
    	def reset_login_attempts(self):
    		self.login_attempts = 0
    
    class Admin(User):
    	"""docstring for Admin"""
    	def __init__(self, first_name,last_name):
    		super().__init__(first_name,last_name)
    		self.privileges = ['can add post','can ban user','can delete post']
    
    	def show_privileges(self):
    		print(self.privileges)
    
    admin = Admin("Alice",'Bob')
    admin.show_privileges()
    		

    结果:


     

    9-8 权限

    编写一个名为Privileges 的类,它只有一个属性——privileges ,其中存储了练习9-7 所说的字符串列表。将方法show_privileges() 移到这 个类中。在Admin 类中,将一个Privileges 实例用作其属性。创建一个Admin 实例,并使用方法show_privileges() 来显示其权限。

    class User():
    	"""docstring for User"""
    	def __init__(self, first_name,last_name):
    		self.first_name = first_name
    		self.last_name = last_name
    		self.login_attempts = 0
    
    	def describe_name(self):
    		print("fitst_name :",self.first_name," last_name: ",self.last_name)
    
    	def greet_user(self):
    		print("hello, ",self.first_name," ",self.last_name)
    
    	def  increment_login_attempts(self):
    		self.login_attempts += 1
    	def reset_login_attempts(self):
    		self.login_attempts = 0
    class Privileges():
    	"""docstring for Privileges"""
    	def __init__(self):
    		self.privileges = ['can add post','can ban user','can delete post']
    	def show_privileges(self):
    		print(self.privileges)
    class Admin(User):
    	"""docstring for Admin"""
    	def __init__(self, first_name,last_name):
    		super().__init__(first_name,last_name)
    		self.privileges = Privileges()
    
    	def show_privileges(self):
    		self.privileges.show_privileges()
    
    admin = Admin("Alice",'Bob')
    admin.show_privileges()
    		

    结果:

    9-9 电瓶升级

    在本节最后一个electric_car.py版本中,给Battery 类添加一个名为upgrade_battery() 的方法。这个方法检查电瓶容量,如果它不是85,就将它 设置为85。创建一辆电瓶容量为默认值的电动汽车,调用方法get_range() ,然后对电瓶进行升级,并再次调用get_range() 。你会看到这辆汽车的续航里程增 加了。

    class Car():
    	"""docstring for Car"""
    	def __init__(self, make,model,year):
    		self.make = make
    		self.model = model
    		self.year = year
    		self.odometer_reading = 0
    
    	def get_descriptive_name(self):
    		long_name = str(self.year) + ' ' + self.make + ' ' + self.model
    		return long_name
    	#打印里程消息
    	def read_odometer(self):
    		print("This car has " + str(self.odometer_reading) + " miles on it.")
    	#更新里程数
    	def update_odometer(self,milegeage):
    		if milegeage >= self.odometer_reading:
    			self.odometer_reading = milegeage
    		else:
    			print("You can't roll back an odometer!")
    
    	def  increment_odometer(self,miles):
    		self.odometer_reading += miles
    class Battery():
    	"""docstring for Battery"""
    	def __init__(self, battery_size=70):
    		self.battery_size = battery_size
    	def describe_battery(self):
    		print("This car has a " + str(self.battery_size) + "-kWh battery")
    	def upgrade_battery(self):
    		if self.battery_size!=85:
    			self.battery_size = 85
    	def get_range(self):
    		if self.battery_size == 70:
    			range = 240
    		elif self.battery_size == 85:
    			range = 270
    		message = "This car can go approximately " + str(range)
    		message += "miles on a full charge."
    		print(message)
    		self.upgrade_battery()
    
    
    class ElectricCar(Car):
    	"""docstring for ElectricCar"""
    	def __init__(self, make,model,year):
    		super().__init__(make,model,year)
    		self.battery_size = Battery()
    	def describe_battery(self):
    		self.battery_size.battery_size()
    	def get_range(self):
    		self.battery_size.get_range()
    
    my_tesla = ElectricCar('tesla','model s',2016)
    my_tesla.get_range()
    my_tesla.get_range()

    结果:

    9-10 导入Restaurant类

    将最新的Restaurant 类存储在一个模块中。在另一个文件中,导入Restaurant 类,创建一个Restaurant 实例,并调 用Restaurant 的一个方法,以确认import 语句正确无误。

    restaurant.py

    class  Restraurant():
    	"""docstring for  Restraurant"""
    	def __init__(self, restaurant_name,cuisine_type):
    		self.restaurant_name = restaurant_name
    		self.cuisine_type = cuisine_type
    		self.number_served = 0
    	def describe_restaurant(self):
    		print(self.restaurant_name,":",self.cuisine_type)
    	def open_restaurant(self):
    		print("Is opening")
    	def set_number_served(self,number):
    		self.number_served = number
    	def get_number_served(self):
    		return self.number_served
    	def increment_number_served(self,number):
    		while self.number_served < number:
    			print(self.number_served)
    			self.number_served +=1

    coding.py

    from restraurant import Restraurant
    restraurant1 = Restraurant('A','B')
    print(restraurant1.restaurant_name," ",restraurant1.cuisine_type)
    restraurant1.describe_restaurant()
    restraurant1.open_restaurant()
    print(restraurant1.get_number_served())
    restraurant1.set_number_served(2)
    print(restraurant1.get_number_served())
    restraurant1.increment_number_served(10)

    结果:


     

    9-11 导入Admin 类

    以为完成练习9-8而做的工作为基础,将User 、Privileges 和Admin 类存储在一个模块中,再创建一个文件,在其中创建一个Admin 实例 并对其调用方法show_privileges() ,以确认一切都能正确地运行。

    user.py

    class User():
    	"""docstring for User"""
    	def __init__(self, first_name,last_name):
    		self.first_name = first_name
    		self.last_name = last_name
    		self.login_attempts = 0
    
    	def describe_name(self):
    		print("fitst_name :",self.first_name," last_name: ",self.last_name)
    
    	def greet_user(self):
    		print("hello, ",self.first_name," ",self.last_name)
    
    	def  increment_login_attempts(self):
    		self.login_attempts += 1
    	def reset_login_attempts(self):
    		self.login_attempts = 0
    class Privileges():
    	"""docstring for Privileges"""
    	def __init__(self):
    		self.privileges = ['can add post','can ban user','can delete post']
    	def show_privileges(self):
    		print(self.privileges)
    class Admin(User):
    	"""docstring for Admin"""
    	def __init__(self, first_name,last_name):
    		super().__init__(first_name,last_name)
    		self.privileges = Privileges()
    
    	def show_privileges(self):
    		self.privileges.show_privileges()

    coding.py

    from user import Admin
    admin = Admin("Alice",'Bob')
    admin.show_privileges()

    结果:

    9-12 多个模块

    将User 类存储在一个模块中,并将Privileges 和Admin 类存储在另一个模块中。再创建一个文件,在其中创建一个Admin 实例,并对其调用方法show_privileges() ,以确认一切都依然能够正确地运行。

    privileges.py

    class Privileges():
    	"""docstring for Privileges"""
    	def __init__(self):
    		self.privileges = ['can add post','can ban user','can delete post']
    	def show_privileges(self):
    		print(self.privileges)

    admin.py

    class Admin(User):
    	"""docstring for Admin"""
    	def __init__(self, first_name,last_name):
    		super().__init__(first_name,last_name)
    		self.privileges = Privileges()
    
    	def show_privileges(self):
    		self.privileges.show_privileges()

    user.py

    class User():
    	"""docstring for User"""
    	def __init__(self, first_name,last_name):
    		self.first_name = first_name
    		self.last_name = last_name
    		self.login_attempts = 0
    
    	def describe_name(self):
    		print("fitst_name :",self.first_name," last_name: ",self.last_name)
    
    	def greet_user(self):
    		print("hello, ",self.first_name," ",self.last_name)
    
    	def  increment_login_attempts(self):
    		self.login_attempts += 1
    	def reset_login_attempts(self):
    		self.login_attempts = 0

    coding.py

    from user import User
    from admin import Admin
    from privilege import Privilege
    admin = Admin("Alice",'Bob')
    admin.show_privileges()

    结果:

    9-13 使用OrderedDict

    在练习6-4中,你使用了一个标准字典来表示词汇表。请使用OrderedDict 类来重写这个程序,并确认输出的顺序与你在字典中添加键 —值对的顺序一致。

    from collections import OrderedDict
    favorite_languages = OrderedDict()
    favorite_languages['jen'] = 'python'
    favorite_languages['sarah'] = 'c'
    favorite_languages['edward'] = 'ruby'
    favorite_languages['phil'] = 'python'
    for key,value in favorite_languages.items():
    	print(key.title() + " 's favorite languages is "+value.title() + ".")

    结果:


     

    9-14 骰子

    模块random 包含以各种方式生成随机数的函数,其中的randint() 返回一个位于指定范围内的整数,例如,下面的代码返回一个1~6内的整数:

    from random import randint

    x = randint(1, 6)

    请创建一个Die 类,它包含一个名为sides 的属性,该属性的默认值为6。编写一个名为roll_die() 的方法,它打印位于1和骰子面数之间的随机数。创建一个6面 的骰子,再掷10次。 创建一个10面的骰子和一个20面的骰子,并将它们都掷10次。

    from random import randint
    class Die():
    	"""docstring for Die"""
    	def __init__(self):
    		self.sides = 6
    	def roll_die(self):
    		x = randint(1,6)
    		self.sides=x
    		print(self.sides)
    	def roll_die10(self):
    		x = randint(1,10)
    		self.sides = x
    		print(self.sides)
    	def  roll_die20(self):
    		self.sides = randint(1,20)
    		print(self.sides)
    die = Die()
    print(die.sides)
    print("6 sides")
    for i in range(0,10):
    	die.roll_die()
    print("10 sides")
    for i in range(0,10):
    	die.roll_die10()
    print("20 sides")
    for i in range(0,10):
    	die.roll_die20()
    		

    结果:

     

    《Python编程:从入门到实践》第十章:文件和异常

    10-2 C语言学习笔记

    可使用replace()将字符串中的特定单词都替换为另一个单词。下面是一个简单的示例,演示了如何将句子中的'dog'替换为'cat':

    >>> message = "I really like dogs."

    >>> message.replace('dog','cat')

    'I really like cats.'

    route = 'learning.txt'
    with open(route) as file_object:
    	message = file_object.read()
    	print(message.rstrip())
    	result = message.replace('dog','cat')
    	print(result.rstrip())

    结果:

    10-3 访客

    编写一个程序,提示用户输入器名字;用户作出响应后,将其名字写入到文件guest.txt中

    if __name__ == "__main__":
        route = 'learning.txt'
        name = input('please input your name')
        with open(route,'w') as file_object:
            file_object.write(name)
        with open(route)  as  file_object:
            print(file_object.read().rstrip())

    结果:


     

    10-4 访客名单

    编写一个while循环,提示用户输入其名字。用户输入其名字后,在屏幕上打印一句问候语,并将一条访问记录添加到文件guest_book.txt中。确保这个文件中的每条记录都独占一行。

    if __name__ == "__main__":
        route = 'guest_book.txt'
        with open(route,'w') as file_object:
            while True:
                name =  input('please input your name:')
                print("Hello, ",name)
                file_object.write(name+"\n")
                conti = input("continute?yes/no")
                if conti == 'no':
                    break;
        with open(route) as  file_object:
            lines = file_object.readlines()
        for line in lines:
            print(line.rstrip())

    结果:

    10-5 关于编程的调查

    编写一个while循环,询问用户为何喜欢编程。每当用户输入一个原因后,都将其添加到一个存储所有原因的文件中。

    if __name__ == "__main__":
        route = 'guest_book.txt'
        with open(route,'w') as file_object:
            while True:
                reason =  input('please tell me why you like programming:')
                print("Hello, ",reason)
                file_object.write(reason+"\n")
                conti = input("continute?yes/no")
                if conti == 'no':
                    break;
        with open(route) as  file_object:
            lines = file_object.readlines()
        for line in lines:
            print(line.rstrip())

    结果:


     

    10-6 加法运算

    提示用户提供数值输入时,常出现的一个问题是,用户提供的是文本而不是数字。在这种情况下,当你尝试将输入转换为整数时,将引 发TypeError 异常。编写一个程序,提示用户输入两个数字,再将它们相加并打印结果。在用户输入的任何一个值不是数字时都捕获TypeError 异常,并打印一
    条友好的错误消息。对你编写的程序进行测试:先输入两个数字,再输入一些文本而不是数字。

    if __name__ == "__main__":
        while True:
            try:
                fist_number = input("please input first number:")
                if fist_number == 'q':
                    break
                fist = int(fist_number)
                second_number = input("please input second number:")
                if second_number == 'q':
                    break
                second = int(second_number)
            except ValueError:
                print("Type Error")
            else:
                print("result:",fist+second)

    结果:


     

    10-7 加法计算器

    将你为完成练习10-6而编写的代码放在一个while 循环中,让用户犯错(输入的是文本而不是数字)后能够继续输入数字。

    同10-6

    10-8 猫和狗

    创建两个文件cats.txt和dogs.txt,在第一个文件中至少存储三只猫的名字,在第二个文件中至少存储三条狗的名字。编写一个程序,尝试读取这些文件, 并将其内容打印到屏幕上。将这些代码放在一个try-except 代码块中,以便在文件不存在时捕获FileNotFound 错误,并打印一条友好的消息。将其中一个文件 移到另一个地方,并确认except 代码块中的代码将正确地执行。

    def openfile(filename):
        try:
            with open(filename) as file_object:
                contents = file_object.read()
        except FileNotFoundError:
            print("Sorry, file was not found")
        else:
            print(contents.rstrip())
    if __name__ == "__main__":
        route = ['cats.txt','alice.txt','dogs.txt']
        for value in route:
            openfile(value)

    结果:


     

    10-9 沉默的猫和狗 沉默的猫和狗

    修改你在练习10-8中编写的except 代码块,让程序在文件不存在时一言不发。

    def openfile(filename):
        try:
            with open(filename) as file_object:
                contents = file_object.read()
        except FileNotFoundError:
            pass
        else:
            print(contents.rstrip())
    if __name__ == "__main__":
        route = ['cats.txt','alice.txt','dogs.txt']
        for value in route:
            openfile(value)

    结果:


     

    10-10 常见单词

    访问项目Gutenberg(http://gutenberg.org/ ),并找一些你想分析的图书。下载这些作品的文本文件或将浏览器中的原始文本复制到文本文件中。 你可以使用方法count() 来确定特定的单词或短语在字符串中出现了多少次。例如,下面的代码计算'row' 在一个字符串中出现了多少次:

    >>> line = "Row, row, row your boat"

    >>> line.count('row')

    2

    >>> line.lower().count('row')

    3

    请注意,通过使用lower() 将字符串转换为小写,可捕捉要查找的单词出现的所有次数,而不管其大小写格式如何。 编写一个程序,它读取你在项目Gutenberg中获取的文件,并计算单词'the' 在每个文件中分别出现了多少次。

    if __name__ == "__main__":
        route = 'EBook.txt'
        try:
            with open(route) as f:
                contents = f.read()
        except FileNotFoundError:
            pass
        else:
            # print(contents)
            numbers = contents.count('the')
            numbers2 = contents.lower().count('the')
            print("numbers:",numbers," numbers2:",numbers2)

    结果:


     

    10-11 喜欢的数字

    编写一个程序,提示用户输入他喜欢的数字,并使用json.dump() 将这个数字存储到文件中。再编写一个程序,从文件中读取这个值,并打印 消息“I know your favorite number! It's _____.”。

    import json
    def jdump(route,number):
        with open(route,'w') as f:
            json.dump(str(number),f)
    def jload(route):
        with open(route) as f:
            num = json.load(f)
        print("I know your favorite number! It's ",num)
    if __name__ == "__main__":
        route ="favorite_number.json"
        number = input("please enter your favorite number:")
        jdump(route,number)
        jload(route)

    结果:

    10-12 记住喜欢的数字

    将练习10-11中的两个程序合而为一。如果存储了用户喜欢的数字,就向用户显示它,否则提示用户输入他喜欢的数字并将其存储到文件中。 运行这个程序两次,看看它是否像预期的那样工作。

    import json
    def jdump(route):
        number = input("please enter your favorite number:")
        with open(route,'w') as f:
            json.dump(str(number),f)
    
    def jload(route):
        with open(route) as f:
            num = json.load(f)
        if num:
            print("I know your favorite number! It's ", num)
        else:
            jdump(route)
    
    if __name__ == "__main__":
        route ="favorite_number.json"
        jload(route)
        jload(route)

    结果:


     

    10-13 验证用户

    最后一个remember_me.py版本假设用户要么已输入其用户名,要么是首次运行该程序。我们应修改这个程序,以应对这样的情形:当前和最后一次 运行该程序的用户并非同一个人。 为此,在greet_user() 中打印欢迎用户回来的消息前,先询问他用户名是否是对的。如果不对,就调用get_new_username() 让用户输入正确的用户名。

    import json
    def get_sorted_username():
        """如果存储了用户名,就获取它"""
        filename = 'username.json'
        try:
            with open(filename) as f_obj:
                username = json.load(f_obj)
        except FileNotFoundError:
            return None
        else:
            return username
    
    def get_new_username():
        username = input("What is your name?")
        filename = 'username.json'
        with open(filename,'w') as f_obj:
            json.dump(username,f_obj)
        return  username
    def greet_user():
        username = get_sorted_username()
        if username:
            result = input(username+"is right?")
            if result == 'y':
                print("Welcom back,",username,"!")
            else:
                username = get_new_username()
                print("Welcom back,",username,"!")
        else:
            username = get_new_username()
            print("We'll remember you when you come back,",username,"!")
    
    if __name__ == "__main__":
        greet_user()

    结果:

    《Python编程:从入门到实践》第十一章:测试代码

    11-1 城市和国家

    编写一个函数,它接受两个形参:一个城市名和一个国家名。这个函数返回一个格式为City, Country 的字符串,如Santiago, Chile 。将 这个函数存储在一个名为city_functions.py的模块中。

    创建一个名为test_cities.py的程序,对刚编写的函数进行测试(别忘了,你需要导入模块unittest 以及要测试的函数)。编写一个名为test_city_country() 的 方法,核实使用类似于'santiago' 和'chile' 这样的值来调用前述函数时,得到的字符串是正确的。运行test_cities.py ,确认测 试test_city_country() 通过了。

    city_functions.py

    def get_city_country(city,country):
        return city+' '+country

    test_cities.py

    import unittest
    from city_functions import get_city_country
    class CityCountryTestCase(unittest.TestCase):
        def test_city_country(self):
            city = 'santuago'
            country = 'chile'
            self.assertEqual(get_city_country(city,country),'santuago chile')
    unittest.main()
    
    

    结果:

    11-2 人口数量

    修改前面的函数,使其包含第三个必不可少的形参population ,并返回一个格式为City, Country - population xxx 的字符串, 如Santiago, Chile - population 5000000 。运行test_cities.py,确认测试test_city_country() 未通过。

    修改上述函数,将形参population 设置为可选的。再次运行test_cities.py,确认测试test_city_country() 又通过了。

    再编写一个名为test_city_country_population() 的测试,核实可以使用类似于'santiago' 、'chile' 和'population=5000000' 这样的值来调用 这个函数。再次运行test_cities.py,确认测试test_city_country_population() 通过了。

    city_functions.py

    def get_city_country(city,country,population):
        return city.title()+', '+country.title()+' - population '+ str(population)

    test_cities.py

    import unittest
    from city_functions import get_city_country
    class CityCountryTestCase(unittest.TestCase):
        def test_city_country(self):
            city = 'santiago'
            country = 'chile'
            population = 5000000
            self.assertEqual(get_city_country(city,country,population),'Santiago, Chile - population 5000000')
    unittest.main()

    结果:

    11-3 雇员

    编写一个名为Employee 的类,其方法__init__() 接受名、姓和年薪,并将它们都存储在属性中。编写一个名为give_raise() 的方法,它默认将 年薪增加5000美元,但也能够接受其他的年薪增加量。

    为Employee 编写一个测试用例,其中包含两个测试方法:test_give_default_raise() 和test_give_custom_raise() 。使用方法setUp() ,以免在 每个测试方法中都创建新的雇员实例。运行这个测试用例,确认两个测试都通过了。

    import  unittest
    class Employee():
        def __init__(self,first_name,last_name,salary):
            self.first_name = first_name
            self.last_name = last_name
            self.salary  = salary
        def give_raise(self):
            self.salary = 5000
            return self.salary
    
    class TestEmployee(unittest.TestCase):
        def setUp(self):
            self.Employee = Employee('Alice','Bob',200)
        def test_give_default_raise(self):
            self.assertEqual(self.Employee.salary,200)
        def test_give_custom_raise(self):
            self.assertEqual(self.Employee.give_raise(),5000)
    unittest.main()

    结果:


     

    上一篇:没有了  下一篇:Java编程的逻辑

    展开 +

    收起 -

    Python3.5编程相关电子书
    学习笔记
    网友NO.35476
    网友NO.35476

    Python编程入门
    我刚开始学习编程,主要是因为自己想动手做个网站,但是由于技术原因,再加上朋友都比较忙,最后抱着“求人不如求己”的想法,干脆自学。
    编程难不难?
    这个问题我觉得所有认真学过的人,都一定会肯定告诉你编程不难,但是精通那是相当困难的。
    如果你还没去学习,就觉得编程一定很难,那么其实你是没有资格说这句话的,任何事情一定是要去尝试后,才能这么说。
    编程其实很像堆积木,然后根据需求,把东西造出来,可以是房子,也可以是桥梁。
    学习编程无非运用这些积木,来创造你要的东西。

    网友NO.34810
    网友NO.34810

    python学习心得体会
    Python是一种面向对象、解释型的脚本语言(一个Shell脚本主要由原本需要在命令行输入的命令组成,使得用键盘进行的交互式操作自动化。),而IDLE就是Python Shell,就是一个通过键入文本与程序交互的途径,我们可以利用IDLE与Python进行交互。
    print()的作用:在输出窗口中显示一些文本。
    >>print("Hello world"*5)可以正常执行,但>>>print("Hello world"+5)却会报错
    在一个字符串中嵌入一个双引号,可以利用反斜杠对双引号转义:\",或者用单引号引起这个字符串,例如:'Hello "W"orld'。这种做法与Linux中的shell如出一辙。
    >>print('hello world')是将结果及类型打印到屏幕上:'hello world';而>>>'hello world'是将结果打印到屏幕上:hello world。
    设置操作系统的环境变量,使得可以通过:开始>运行>python进入Python环境:
    这台电脑>属性>高级系统设置>环境变量>系统变量>path>编辑
    在最后输入; D:\Programs\Python\Python35
    OK
    BIF就是Built-inFunctions,内置函数。为了方便程序员快速编写脚本程序(脚本就是要编程速度快快快!!!),Python提供了非常丰富的内置函数,我们只需要直接调用即可。
    查看Python3提供了多少个BIF,用:dir(__builtins__)
    Python的变量是不用先声明的,只有当标识符已经复制后才能在代码中使用,未赋值的标识符直接使用会导致运行时错误。
    Python中缩进是最重要的,缩进的严格要求使得Python的代码显得非常精简并且有层次。所以在Python里对待缩进代码要十分小心 ,如果没有正确的缩进,代码所做的事情可能和你的期望相去甚远。
    C语言中,如果if(c==1)写成if(c=1),程序就完全不按程序员原本的目的去执行,但在Python这里,不好意思,行不通,语法错误!Python不允许if条件中赋值,所以ifc=1:会报错!

    网友NO.46054
    网友NO.46054

    等学完了《Python编程:从入门到实践》,就可以开始任务型练习。(当然每节后面的练习需要跟着做)。《Python编程:从入门到实践》后面几章本身就是任务型练习,而我为了学爬虫看了《Python编程快速上手 让繁琐工作自动化》。

    接下去第二个重点来了,在这个过程中一定要尝试自己解决问题。《Python编程快速上手 让繁琐工作自动化》的爬虫介绍得很少,无法满足我的项目的需要。但是此时我已经有信心不依赖书本了。

    Copyright 2018-2019 xz577.com 码农之家

    版权责任说明