Full Code of ZiniuLu/Python-100-Days for AI

master d4d159d1d6a7 cached
308 files
1.5 MB
555.9k tokens
471 symbols
1 requests
Download .txt
Showing preview only (1,574K chars total). Download the full file or copy to clipboard to get everything.
Repository: ZiniuLu/Python-100-Days
Branch: master
Commit: d4d159d1d6a7
Files: 308
Total size: 1.5 MB

Directory structure:
gitextract_l08lgnd9/

├── .gitignore
├── Day01-15/
│   ├── Day01/
│   │   ├── hello.py
│   │   ├── peppa_pig.py
│   │   └── 初识Python.md
│   ├── Day02/
│   │   ├── centigrade.py
│   │   ├── circle.py
│   │   ├── leap.py
│   │   ├── operator.py
│   │   ├── string.py
│   │   ├── variable1.py
│   │   ├── variable2.py
│   │   ├── variable3.py
│   │   ├── variable4.py
│   │   ├── variable5.py
│   │   └── 语言元素.md
│   ├── Day03/
│   │   ├── .py
│   │   ├── convert.py
│   │   ├── grade.py
│   │   ├── piecewise.py
│   │   ├── rolldice.py
│   │   ├── tax.py
│   │   ├── triangle.py
│   │   ├── verify.py
│   │   └── 分支结构.md
│   ├── Day04/
│   │   ├── for1.py
│   │   ├── for2.py
│   │   ├── for3.py
│   │   ├── for4.py
│   │   ├── for5.py
│   │   ├── for6.py
│   │   ├── while1.py
│   │   ├── while2.py
│   │   └── 循环结构.md
│   ├── Day05/
│   │   ├── chicken.py
│   │   ├── craps.py
│   │   ├── fibonacci.py
│   │   ├── guess.py
│   │   ├── lily.py
│   │   ├── palindrome.py
│   │   ├── perfect.py
│   │   ├── prime.py
│   │   ├── table.py
│   │   └── 总结和练习.md
│   ├── Day06/
│   │   ├── function1.py
│   │   ├── function2.py
│   │   ├── function3.py
│   │   ├── function4.py
│   │   ├── function5.py
│   │   ├── function6.py
│   │   └── 函数和模块的使用.md
│   ├── Day07/
│   │   ├── avgscore.py
│   │   ├── dict1.py
│   │   ├── dict2.py
│   │   ├── fibonacci.py
│   │   ├── findmax.py
│   │   ├── list1.py
│   │   ├── list2.py
│   │   ├── list3.py
│   │   ├── lottery.py
│   │   ├── marquee.py
│   │   ├── scoretable.py
│   │   ├── set1.py
│   │   ├── set2.py
│   │   ├── tic-tac-toe.py
│   │   ├── tuple.py
│   │   ├── yanghui.py
│   │   └── 字符串和常用数据结构.md
│   ├── Day08/
│   │   ├── access.py
│   │   ├── circle.py
│   │   ├── clock.py
│   │   ├── guess.py
│   │   ├── hack.py
│   │   ├── rect.py
│   │   ├── student.py
│   │   ├── test.py
│   │   └── 面向对象编程基础.md
│   ├── Day09/
│   │   ├── association.py
│   │   ├── car1.py
│   │   ├── car2.py
│   │   ├── clock.py
│   │   ├── dependency.py
│   │   ├── diamond.py
│   │   ├── employee.py
│   │   ├── multi.py
│   │   ├── pet.py
│   │   ├── rational.py
│   │   ├── res/
│   │   │   └── uml-example.gliffy
│   │   ├── shape.py
│   │   ├── triangle.py
│   │   └── 面向对象进阶.md
│   ├── Day10/
│   │   ├── ball.py
│   │   ├── gui1.py
│   │   ├── gui2.py
│   │   ├── gui3.py
│   │   ├── turtle1.py
│   │   └── 图形用户界面和游戏开发.md
│   ├── Day11/
│   │   ├── .py
│   │   ├── csv1.py
│   │   ├── csv2.py
│   │   ├── ex1.py
│   │   ├── ex2.py
│   │   ├── ex3.py
│   │   ├── ex4.py
│   │   ├── example.csv
│   │   ├── file1.py
│   │   ├── file2.py
│   │   ├── file3.py
│   │   ├── file4.py
│   │   ├── json1.py
│   │   ├── json2.py
│   │   ├── pi_million_digits.txt
│   │   ├── teacher.csv
│   │   ├── 文件和异常.md
│   │   └── 致橡树.txt
│   ├── Day12/
│   │   ├── str1.py
│   │   ├── str2.py
│   │   ├── test3.py
│   │   ├── test4.py
│   │   ├── test5.py
│   │   └── 字符串和正则表达式.md
│   ├── Day13/
│   │   ├── asyncio1.py
│   │   ├── asyncio2.py
│   │   ├── asyncio3.py
│   │   ├── coroutine1.py
│   │   ├── coroutine2.py
│   │   ├── generator1.py
│   │   ├── generator2.py
│   │   ├── multiprocess1.py
│   │   ├── multiprocess2.py
│   │   ├── multiprocess3.py
│   │   ├── multiprocess4.py
│   │   ├── multithread1.py
│   │   ├── multithread2.py
│   │   ├── multithread3.py
│   │   ├── multithread4.py
│   │   ├── multithread5.py
│   │   ├── multithread6.py
│   │   ├── singlethread1.py
│   │   ├── singlethread2.py
│   │   ├── test2.py
│   │   ├── test3.py
│   │   └── 进程和线程.md
│   ├── Day14/
│   │   ├── chatclient.py
│   │   ├── chatserver.py
│   │   ├── fileclient.py
│   │   ├── fileserver.py
│   │   ├── mmdownloader.py
│   │   ├── socket1.py
│   │   ├── socket2.py
│   │   ├── socket3.py
│   │   ├── socket4.py
│   │   ├── socket5.py
│   │   ├── timeclient.py
│   │   ├── timeserver.py
│   │   └── 网络编程入门.md
│   └── Day15/
│       └── 网络应用开发.md
├── Day16-20/
│   └── Python语言进阶.md
├── Day21-30/
│   ├── Web前端概述.md
│   ├── classical_layout.html
│   ├── example.html
│   ├── form.html
│   ├── form_and_table.html
│   ├── jquery3.html
│   └── qq_link.html
├── Day31-35/
│   └── 玩转Linux.md
├── Day36-40/
│   ├── NoSQL入门.md
│   └── 关系型数据库MySQL.md
├── Day41-55/
│   ├── Django2实战01.md
│   ├── Django2实战02.md
│   ├── Django2实战03.md
│   ├── Django2实战04.md
│   ├── Django2实战05.md
│   ├── Django2实战06.md
│   ├── Django2实战07.md
│   ├── Django2实战08.md
│   ├── Django2实战09.md
│   ├── Django2实战10.md
│   ├── Django2项目实战.md
│   ├── car/
│   │   ├── car/
│   │   │   ├── __init__.py
│   │   │   ├── settings.py
│   │   │   ├── urls.py
│   │   │   └── wsgi.py
│   │   ├── manage.py
│   │   ├── search/
│   │   │   ├── __init__.py
│   │   │   ├── admin.py
│   │   │   ├── apps.py
│   │   │   ├── migrations/
│   │   │   │   ├── 0001_initial.py
│   │   │   │   ├── 0002_auto_20180524_1420.py
│   │   │   │   └── __init__.py
│   │   │   ├── models.py
│   │   │   ├── tests.py
│   │   │   └── views.py
│   │   └── templates/
│   │       ├── add.html
│   │       ├── search.html
│   │       └── search2.html
│   ├── oa/
│   │   ├── hrs/
│   │   │   ├── __init__.py
│   │   │   ├── admin.py
│   │   │   ├── apps.py
│   │   │   ├── migrations/
│   │   │   │   ├── 0001_initial.py
│   │   │   │   ├── 0002_auto_20180523_0923.py
│   │   │   │   ├── 0003_auto_20180524_1646.py
│   │   │   │   └── __init__.py
│   │   │   ├── models.py
│   │   │   ├── tests.py
│   │   │   ├── urls.py
│   │   │   └── views.py
│   │   ├── manage.py
│   │   ├── oa/
│   │   │   ├── __init__.py
│   │   │   ├── settings.py
│   │   │   ├── urls.py
│   │   │   └── wsgi.py
│   │   └── templates/
│   │       ├── dept.html
│   │       ├── emp.html
│   │       └── index.html
│   ├── shop/
│   │   ├── cart/
│   │   │   ├── __init__.py
│   │   │   ├── admin.py
│   │   │   ├── apps.py
│   │   │   ├── migrations/
│   │   │   │   ├── 0001_initial.py
│   │   │   │   └── __init__.py
│   │   │   ├── models.py
│   │   │   ├── tests.py
│   │   │   └── views.py
│   │   ├── manage.py
│   │   ├── shop/
│   │   │   ├── __init__.py
│   │   │   ├── settings.py
│   │   │   ├── urls.py
│   │   │   └── wsgi.py
│   │   └── templates/
│   │       ├── cart.html
│   │       └── goods.html
│   └── shop_origin/
│       ├── cart/
│       │   ├── __init__.py
│       │   ├── admin.py
│       │   ├── apps.py
│       │   ├── migrations/
│       │   │   ├── 0001_initial.py
│       │   │   └── __init__.py
│       │   ├── models.py
│       │   ├── tests.py
│       │   └── views.py
│       ├── manage.py
│       ├── shop/
│       │   ├── __init__.py
│       │   ├── settings.py
│       │   ├── urls.py
│       │   └── wsgi.py
│       ├── shop_create_sql.sql
│       └── templates/
│           ├── cart.html
│           └── goods.html
├── Day56-65/
│   ├── Flask安装和入门.md
│   ├── Flask项目实战.md
│   ├── 使用Flask进行项目开发.md
│   ├── 数据库操作.md
│   ├── 模板的使用.md
│   └── 表单的处理.md
├── Day66-75/
│   ├── 01.网络爬虫和相关工具.md
│   ├── 02.数据采集和解析.md
│   ├── 03.存储数据.md
│   ├── 04.并发下载.md
│   ├── 05.解析动态内容.md
│   ├── 06.表单交互和验证码处理.md
│   ├── Scrapy爬虫框架入门.md
│   ├── Scrapy爬虫框架分布式实现.md
│   ├── Scrapy爬虫框架高级应用.md
│   └── code/
│       ├── asyncio01.py
│       ├── asyncio02.py
│       ├── coroutine01.py
│       ├── coroutine02.py
│       ├── douban/
│       │   ├── douban/
│       │   │   ├── __init__.py
│       │   │   ├── items.py
│       │   │   ├── middlewares.py
│       │   │   ├── pipelines.py
│       │   │   ├── settings.py
│       │   │   └── spiders/
│       │   │       ├── __init__.py
│       │   │       └── movie.py
│       │   └── scrapy.cfg
│       ├── example01.py
│       ├── example02.py
│       ├── example03.py
│       ├── example04.py
│       ├── example05.py
│       ├── example06.py
│       ├── example07.py
│       ├── example08.py
│       ├── example09.py
│       ├── example10.py
│       ├── example11.py
│       ├── example12.py
│       ├── generator01.py
│       ├── generator02.py
│       ├── image360/
│       │   ├── image360/
│       │   │   ├── __init__.py
│       │   │   ├── items.py
│       │   │   ├── middlewares.py
│       │   │   ├── pipelines.py
│       │   │   ├── settings.py
│       │   │   └── spiders/
│       │   │       ├── __init__.py
│       │   │       ├── image.py
│       │   │       └── taobao.py
│       │   └── scrapy.cfg
│       ├── main.py
│       ├── main_redis.py
│       └── myutils.py
├── Day76-90/
│   ├── 数据处理和可视化.md
│   └── 机器学习.md
├── Day91-100/
│   └── 团队项目开发.md
├── PEP 8风格指南.md
├── Python参考书籍.md
├── Python惯例.md
├── README.md
├── 玩转PyCharm(上).md
├── 用函数还是用复杂的表达式.md
└── 那些年我们踩过的那些坑.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
venv
.idea
*.pyc
__pycache__



================================================
FILE: Day01-15/Day01/hello.py
================================================
"""

第一个Python程序 - hello, world!
向伟大的Dennis M. Ritchie先生致敬

Version: 0.1
Author: 骆昊
Date: 2018-02-26

请将该文件命名为hello.py并在终端中通过下面的命令运行它
python hello.py

"""

print('hello, world!')
# print("你好,世界!")
print('你好', '世界')
print('hello', 'world', sep=', ', end='!')
print('goodbye, world', end='!\n')


================================================
FILE: Day01-15/Day01/peppa_pig.py
================================================
from turtle import*


def nose(x,y):#鼻子
    penup()#提起笔
    goto(x,y)#定位
    pendown()#落笔,开始画
    setheading(-30)#将乌龟的方向设置为to_angle/为数字(0-东、90-北、180-西、270-南)
    begin_fill()#准备开始填充图形
    a=0.4
    for i in range(120):
        if 0<=i<30 or 60<=i<90:
            a=a+0.08
            left(3) #向左转3度
            forward(a) #向前走a的步长
        else:
            a=a-0.08
            left(3)
            forward(a)
    end_fill()#填充完成

    penup()
    setheading(90)
    forward(25)
    setheading(0)
    forward(10)
    pendown()
    pencolor(255,155,192)#画笔颜色
    setheading(10)
    begin_fill()
    circle(5)
    color(160,82,45)#返回或设置pencolor和fillcolor
    end_fill()

    penup()
    setheading(0)
    forward(20)
    pendown()
    pencolor(255,155,192)
    setheading(10)
    begin_fill()
    circle(5)
    color(160,82,45)
    end_fill()


def head(x,y):#头
    color((255,155,192),"pink")
    penup()
    goto(x,y)
    setheading(0)
    pendown()
    begin_fill()
    setheading(180)
    circle(300,-30)
    circle(100,-60)
    circle(80,-100)
    circle(150,-20)
    circle(60,-95)
    setheading(161)
    circle(-300,15)
    penup()
    goto(-100,100)
    pendown()
    setheading(-30)
    a=0.4
    for i in range(60):
        if 0<=i<30 or 60<=i<90:
            a=a+0.08
            lt(3) #向左转3度
            fd(a) #向前走a的步长
        else:
            a=a-0.08
            lt(3)
            fd(a)
    end_fill()


def ears(x,y): #耳朵
    color((255,155,192),"pink")
    penup()
    goto(x,y)
    pendown()
    begin_fill()
    setheading(100)
    circle(-50,50)
    circle(-10,120)
    circle(-50,54)
    end_fill()

    penup()
    setheading(90)
    forward(-12)
    setheading(0)
    forward(30)
    pendown()
    begin_fill()
    setheading(100)
    circle(-50,50)
    circle(-10,120)
    circle(-50,56)
    end_fill()


def eyes(x,y):#眼睛
    color((255,155,192),"white")
    penup()
    setheading(90)
    forward(-20)
    setheading(0)
    forward(-95)
    pendown()
    begin_fill()
    circle(15)
    end_fill()

    color("black")
    penup()
    setheading(90)
    forward(12)
    setheading(0)
    forward(-3)
    pendown()
    begin_fill()
    circle(3)
    end_fill()

    color((255,155,192),"white")
    penup()
    seth(90)
    forward(-25)
    seth(0)
    forward(40)
    pendown()
    begin_fill()
    circle(15)
    end_fill()

    color("black")
    penup()
    setheading(90)
    forward(12)
    setheading(0)
    forward(-3)
    pendown()
    begin_fill()
    circle(3)
    end_fill()


def cheek(x,y):#腮
    color((255,155,192))
    penup()
    goto(x,y)
    pendown()
    setheading(0)
    begin_fill()
    circle(30)
    end_fill()


def mouth(x,y): #嘴
    color(239,69,19)
    penup()
    goto(x,y)
    pendown()
    setheading(-80)
    circle(30,40)
    circle(40,80)


def setting():          #参数设置
    pensize(4)
    hideturtle()        #使乌龟无形(隐藏)
    colormode(255)      #将其设置为1.0或255.随后 颜色三元组的r,g,b值必须在0 .. cmode范围内
    color((255,155,192),"pink")
    setup(840,500)
    speed(10)


def main():
    setting()           #画布、画笔设置
    nose(-100,100)      #鼻子
    head(-69,167)       #头
    ears(0,160)         #耳朵
    eyes(0,140)         #眼睛
    cheek(80,10)        #腮
    mouth(-20,30)       #嘴
    done()


if __name__ == '__main__':
	main()


================================================
FILE: Day01-15/Day01/初识Python.md
================================================
## Day01 - 初识Python

### Python简介

#### Python的历史

1. 1989年圣诞节:Guido von Rossum开始写Python语言的编译器。
2. 1991年2月:第一个Python编译器(同时也是解释器)诞生,它是用C语言实现的(后面又出现了Java和C#实现的版本Jython和IronPython,以及PyPy、Brython、Pyston等其他实现),可以调用C语言的库函数。在最早的版本中,Python已经提供了对“类”,“函数”,“异常处理”等构造块的支持,同时提供了“列表”和“字典”等核心数据类型,同时支持以模块为基础的拓展系统。
3. 1994年1月:Python 1.0正式发布。
4. 2000年10月16日:Python 2.0发布,增加了实现完整的[垃圾回收](https://zh.wikipedia.org/wiki/%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6_(%E8%A8%88%E7%AE%97%E6%A9%9F%E7%A7%91%E5%AD%B8)),并且支持[Unicode](https://zh.wikipedia.org/wiki/Unicode)。与此同时,Python的整个开发过程更加透明,社区对开发进度的影响逐渐扩大,生态圈开始慢慢形成。
5. 2008年12月3日:Python 3.0发布,此版不完全兼容之前的Python代码,不过很多新特性后来也被移植到旧的Python 2.6/2.7版本,因为目前还有公司在项目和运维中使用Python 2.x版本的代码。

目前我们使用的Python 3.6.x的版本是在2016年的12月23日发布的,Python的版本号分为三段,形如A.B.C。其中A表示大版本号,一般当整体重写,或出现不向后兼容的改变时,增加A;B表示功能更新,出现新功能时增加B;C表示小的改动(如修复了某个Bug),只要有修改就增加C。如果对Python的历史感兴趣,可以查看一篇名为[《Python简史》](http://www.cnblogs.com/vamei/archive/2013/02/06/2892628.html)的博文。

#### Python的优缺点

Python的优点很多,简单的可以总结为以下几点。

1. 简单和明确,做一件事只有一种方法。
2. 学习曲线低,与其他很多语言比上手更容易。
3. 开放源代码,拥有强大的社区和生态圈。
4. 解释型语言,完美的平台可移植性。
5. 支持两种主流的编程范式,可以使用面向对象和函数式编程。
6. 可扩展性和可嵌入性,可以调用C/C++代码也可以在C/C++中调用。
7. 代码规范程度高,可读性强,适合有代码洁癖和强迫症的人群。

Python的缺点主要集中在以下几点。

1. 执行效率低下,因此计算密集型任务可以由C/C++编写。
2. 代码无法加密,但是现在的公司很多都不是卖软件而是卖服务,这个问题慢慢会淡化。
3. 在开发时可以选择的框架太多,有选择的地方就有错误。

#### Python的应用领域

目前Python在云基础设施、DevOps、网络爬虫开发、数据分析挖掘、机器学习等领域都有着广泛的应用,因此也产生了服务器开发、数据接口开发、自动化运维、科学计算和数据可视化、聊天机器人开发、图像识别和处理等一系列的职位。

### 搭建编程环境

#### Windows环境

可以在[Python的官方网站](https://www.python.org)下载到Python的Windows安装程序(exe文件),需要注意的是如果在Windows 7环境下安装需要先安装Service Pack 1补丁包(可以通过一些工具软件自动安装系统补丁的功能来安装),安装过程建议勾选“Add Python 3.6 to PATH”(将Python 3.6添加到PATH环境变量)并选择自定义安装,在设置“Optional Features”界面最好将“pip”、“tcl/tk”、“Python test suite”等项全部勾选上。强烈建议使用自定义的安装路径并保证路径中没有中文。安装完成会看到“Setup was successful”的提示,但是在启动Python环境时可能会因为缺失一些动态链接库文件而导致Python解释器无法运行,常见的问题主要是api-ms-win-crt\*.dll缺失以及更新DirectX之后导致某些动态链接库文件缺失,前者可以参照[《api-ms-win-crt\*.dll缺失原因分析和解决方法》]()一文讲解的方法进行处理或者直接在[微软官网](https://www.microsoft.com/zh-cn/download/details.aspx?id=48145)下载Visual C++ Redistributable for Visual Studio 2015文件进行修复,后者可以下载一个DirectX修复工具进行修复。

#### Linux环境

Linux环境自带了Python 2.x版本,但是如果要更新到3.x的版本,可以在[Python的官方网站](https://www.python.org)下载Python的源代码并通过源代码构建安装的方式进行安装,具体的步骤如下所示。

安装依赖库(因为没有这些依赖库可能在源代码构件安装时因为缺失底层依赖库而失败)。

```Shell
yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel
```

下载Python源代码并解压缩到指定目录。

```Shell
wget https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tar.xz
xz -d Python-3.6.1.tar.xz
tar -xvf Python-3.6.1.tar
```

切换至Python源代码目录并执行下面的命令进行配置和安装。

```Shell
cd Python-3.6.1
./configure --prefix=/usr/local/python3.6 --enable-optimizations
make && make install
```

创建软链接,这样就可以直接通过python3直接启动Python解释器。

```Shell
ln -s /usr/local/python3.6/bin/python3 /usr/bin/python3
```


#### MacOS环境

MacOS也是自带了Python 2.x版本的,可以通过[Python的官方网站](https://www.python.org)提供的安装文件(pkg文件)安装3.x的版本。默认安装完成后,可以通过在终端执行python命令来启动2.x版本的Python解释器,可以通过执行python3命令来启动3.x版本的Python解释器,当然也可以通过重新设置软链接来修改启动Python解释器的命令。

### 从终端运行Python程序

#### 确认Python的版本

在终端或命令行提示符中键入下面的命令。

```Shell
python --version
```
当然也可以先输入python进入交互式环境,再执行以下的代码检查Python的版本。

```Python
import sys

print(sys.version_info)
print(sys.version)
```

#### 编写Python源代码

可以用文本编辑工具(推荐使用Sublime、Atom、TextMate、VSCode等高级文本编辑工具)编写Python源代码并将其命名为hello.py保存起来,代码内容如下所示。

```Python
print('hello, world!')
```

#### 运行程序

切换到源代码所在的目录并执行下面的命令,看看屏幕上是否输出了"hello, world!"。

```Shell
python hello.py
```

### 代码中的注释

注释是编程语言的一个重要组成部分,用于在源代码中解释代码的作用从而增强程序的可读性和可维护性,当然也可以将源代码中不需要参与运行的代码段通过注释来去掉,这一点在调试程序的时候经常用到。注释在随源代码进入预处理器或编译时会被移除,不会在目标代码中保留也不会影响程序的执行结果。

1. 单行注释 - 以#和空格开头的部分
2. 多行注释 - 三个引号开头,三个引号结尾

```Python
"""

第一个Python程序 - hello, world!
向伟大的Dennis M. Ritchie先生致敬

Version: 0.1
Author: 骆昊
Date: 2018-02-26

"""

print('hello, world!')
# print("你好,世界!")
print('你好', '世界')
print('hello', 'world', sep=', ', end='!')
print('goodbye, world', end='!\n')
```

### 其他工具介绍

#### IDLE - 自带的集成开发工具

IDLE是安装Python环境时自带的集成开发工具,如下图所示。但是由于IDLE的用户体验并不是那么好所以很少在实际开发中被采用。

![](./res/python-idle.png)

#### IPython - 更好的交互式编程工具

IPython是一种基于Python的交互式解释器。相较于原生的Python Shell,IPython提供了更为强大的编辑和交互功能。可以通过Python的包管理工具pip安装IPython和Jupyter,具体的操作如下所示。

```Shell
pip install ipython jupyter
```

或者

```Shell
python -m pip install ipython jupyter
```

安装成功后,可以通过下面的ipython命令启动IPython,如下图所示。

![](./res/python-ipython.png)

当然我们也可以通过Jupyter运行名为notebook的项目在浏览器窗口中进行交互式操作。

```Shell
jupyter notebook
```

![](./res/python-jupyter-1.png)

![](./res/python-jupyter-2.png)

#### Sublime - 文本编辑神器

![](./res/python-sublime.png)

- 首先可以通过[官方网站](https://www.sublimetext.com/)下载安装程序安装Sublime 3或Sublime 2。

- 安装包管理工具。通过快捷键Ctrl+`或者在View菜单中选择Show Console打开控制台,输入下面的代码。

  - Sublime 3

  ```Python
  import  urllib.request,os;pf='Package Control.sublime-package';ipp=sublime.installed_packages_path();urllib.request.install_opener(urllib.request.build_opener(urllib.request.ProxyHandler()));open(os.path.join(ipp,pf),'wb').write(urllib.request.urlopen('http://sublime.wbond.net/'+pf.replace(' ','%20')).read())
  ```

  - Sublime 2

  ```Python
  import  urllib2,os;pf='Package Control.sublime-package';ipp=sublime.installed_packages_path();os.makedirs(ipp)ifnotos.path.exists(ipp)elseNone;urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler()));open(os.path.join(ipp,pf),'wb').write(urllib2.urlopen('http://sublime.wbond.net/'+pf.replace(' ','%20')).read());print('Please restart Sublime Text to finish installation')
  ```

- 安装插件。通过Preference菜单的Package Control或快捷键Ctrl+Shift+P打开命令面板,在面板中输入Install Package就可以找到安装插件的工具,然后再查找需要的插件。我们推荐大家安装以下几个插件。

  - SublimeCodeIntel - 代码自动补全工具插件
  - Emmet - 前端开发代码模板插件
  - Git - 版本控制工具插件
  - Python PEP8 Autoformat - PEP8规范自动格式化插件
  - ConvertToUTF8 - 将本地编码转换为UTF-8

#### PyCharm - Python开发神器

PyCharm的安装、配置和使用我们在后面会进行介绍。

![](./res/python-pycharm.png)

### 练习

1. 在Python交互环境中下面的代码查看结果并将内容翻译成中文。

    ```Python
    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!
    ```

2. 学习使用turtle在屏幕上绘制图形。

    ```Python
    import turtle

    turtle.pensize(4)
    turtle.pencolor('red')
    turtle.forward(100)
    turtle.right(90)
    turtle.forward(100)
    turtle.right(90)
    turtle.forward(100)
    turtle.right(90)
    turtle.forward(100)
    turtle.mainloop()
    ```


================================================
FILE: Day01-15/Day02/centigrade.py
================================================
"""

将华氏温度转换为摄氏温度
F = 1.8C + 32

Version: 0.1
Author: 骆昊
Date: 2018-02-27

"""

f = float(input('请输入华氏温度: '))
c = (f - 32) / 1.8
print('%.1f华氏度 = %.1f摄氏度' % (f, c))


================================================
FILE: Day01-15/Day02/circle.py
================================================
"""

输入半径计算圆的周长和面积

Version: 0.1
Author: 骆昊
Date: 2018-02-27

"""

import math

radius = float(input('请输入圆的半径: '))
perimeter = 2 * math.pi * radius
area = math.pi * radius * radius
print('周长: %.2f' % perimeter)
print('面积: %.2f' % area)


================================================
FILE: Day01-15/Day02/leap.py
================================================
"""

输入年份 如果是闰年输出True 否则输出False

Version: 0.1
Author: 骆昊
Date: 2018-02-27

"""

year = int(input('请输入年份: '))
# 如果代码太长写成一行不便于阅读 可以使用\或()折行
is_leap = (year % 4 == 0 and year % 100 != 0 or
           year % 400 == 0)
print(is_leap)


================================================
FILE: Day01-15/Day02/operator.py
================================================
"""

运算符的使用

Version: 0.1
Author: 骆昊
Date: 2018-02-27

"""

a = 5
b = 10
c = 3
d = 4
e = 5
a += b
a -= c
a *= d
a /= e
print("a = ", a)

flag1 = 3 > 2
flag2 = 2 < 1
flag3 = flag1 and flag2
flag4 = flag1 or flag2
flag5 = not flag1
print("flag1 = ", flag1)
print("flag2 = ", flag2)
print("flag3 = ", flag3)
print("flag4 = ", flag4)
print("flag5 = ", flag5)
print(flag1 is True)
print(flag2 is not False)


================================================
FILE: Day01-15/Day02/string.py
================================================
"""

字符串常用操作

Version: 0.1
Author: 骆昊
Date: 2018-02-27

"""

str1 = 'hello, world!'
print('字符串的长度是:', len(str1))
print('单词首字母大写: ', str1.title())
print('字符串变大写: ', str1.upper())
# str1 = str1.upper()
print('字符串是不是大写: ', str1.isupper())
print('字符串是不是以hello开头: ', str1.startswith('hello'))
print('字符串是不是以hello结尾: ', str1.endswith('hello'))
print('字符串是不是以感叹号开头: ', str1.startswith('!'))
print('字符串是不是一感叹号结尾: ', str1.endswith('!'))
str2 = '- \u9a86\u660a'
str3 = str1.title() + ' ' + str2.lower()
print(str3)


================================================
FILE: Day01-15/Day02/variable1.py
================================================
"""

使用变量保存数据并进行操作

Version: 0.1
Author: 骆昊
Date: 2018-02-27

"""

a = 321
b = 123
print(a + b)
print(a - b)
print(a * b)
print(a / b)
print(a // b)
print(a % b)
print(a ** b)


================================================
FILE: Day01-15/Day02/variable2.py
================================================
"""

将input函数输入的数据保存在变量中并进行操作

Version: 0.1
Author: 骆昊
Date: 2018-02-27

"""

a = int(input('a = '))
b = int(input('b = '))
print(a + b)
print(a - b)
print(a * b)
print(a / b)
print(a // b)
print(a % b)
print(a ** b)


================================================
FILE: Day01-15/Day02/variable3.py
================================================
"""

格式化输出

Version: 0.1
Author: 骆昊
Date: 2018-02-27

"""

a = int(input('a = '))
b = int(input('b = '))
print('%d + %d = %d' % (a, b, a + b))
print('%d - %d = %d' % (a, b, a - b))
print('%d * %d = %d' % (a, b, a * b))
print('%d / %d = %f' % (a, b, a / b))
print('%d // %d = %d' % (a, b, a // b))
print('%d %% %d = %d' % (a, b, a % b))
print('%d ** %d = %d' % (a, b, a ** b))


================================================
FILE: Day01-15/Day02/variable4.py
================================================
"""

检查变量的类型

Version: 0.1
Author: 骆昊
Date: 2018-02-27

"""

a = 100
b = 1000000000000000000
c = 12.345
d = 1 + 5j
e = 'A'
f = 'hello, world'
g = True
print(type(a))
print(type(b))
print(type(c))
print(type(d))
print(type(e))
print(type(f))
print(type(g))


================================================
FILE: Day01-15/Day02/variable5.py
================================================
"""

类型转换

Version: 0.1
Author: 骆昊
Date: 2018-02-27

"""

a = 100
b = str(a)
c = 12.345
d = str(c)
e = '123'
f = int(e)
g = '123.456'
h = float(g)
i = False
j = str(i)
k = 'hello'
m = bool(k)
print(a)
print(type(a))
print(b)
print(type(b))
print(c)
print(type(c))
print(d)
print(type(d))
print(e)
print(type(e))
print(f)
print(type(f))
print(g)
print(type(g))
print(h)
print(type(h))
print(i)
print(type(i))
print(j)
print(type(j))
print(k)
print(type(k))
print(m)
print(type(m))


================================================
FILE: Day01-15/Day02/语言元素.md
================================================
## Day02 - 语言元素

#### 指令和程序

计算机的硬件系统通常由五大部件构成,包括:运算器、控制器、存储器、输入设备和输出设备。其中,运算器和控制器放在一起就是我们通常所说的中央处理器,它的功能是执行各种运算和控制指令以及处理计算机软件中的数据。我们通常所说的程序实际上就是指令的集合,我们程序就是将一系列的指令按照某种方式组织到一起,然后通过这些指令去控制计算机做我们想让它做的事情。今天我们使用的计算机虽然器件做工越来越精密,处理能力越来越强大,但究其本质来说仍然属于[“冯·诺依曼结构”](https://zh.wikipedia.org/wiki/%E5%86%AF%C2%B7%E8%AF%BA%E4%BC%8A%E6%9B%BC%E7%BB%93%E6%9E%84)的计算机。“冯·诺依曼结构”有两个关键点,一是提出了将存储设备与中央处理器分开,二是提出了将数据以二进制方式编码。二进制是一种“逢二进一”的计数法,跟我们人类使用的“逢十进一”的计数法没有实质性的区别,人类因为有十根手指所以使用了十进制(因为在数数时十根手指用完之后就只能进位了,当然凡事都有例外,玛雅人可能是因为长年光着脚的原因把脚趾头也算上了,于是他们使用了二十进制的计数法,在这种计数法的指导下玛雅人的历法就与我们的不太一致,而按照玛雅人的历法,2012年是上一个所谓的“太阳纪”的最后一年,而2013年则是新的“太阳纪”的开始,后来这件事情被以讹传讹的方式误传为2012年就是玛雅人预言的世界末日这种荒诞的说法,今天我们可以大胆的猜测,玛雅文明之所以发展缓慢估计也与使用了二十进制有关),对于计算机来说,二进制在物理器件上来说是最容易实现的(高电压表示1,低电压表示0),于是在“冯·诺依曼结构”的计算机都使用了二进制。虽然我们并不需要每个程序员都能够使用二进制的思维方式来工作,但是了解二进制以及它与我们生活中的十进制之间的转换关系,以及二进制与八进制和十六进制的转换关系还是有必要的。如果你对这一点不熟悉,可以自行使用[维基百科](https://zh.wikipedia.org/wiki/%E4%BA%8C%E8%BF%9B%E5%88%B6)或者[度娘](https://www.baidu.com)科普一下。

### 变量和类型

在程序设计中,变量是一种存储数据的载体。计算机中的变量是实际存在的数据或者说是存储器中存储数据的一块内存空间,变量的值可以被读取和修改,这是所有计算和控制的基础。计算机能处理的数据有很多中类型,除了数值之外还可以处理文本、图形、音频、视频等各种各样的数据,那么不同的数据就需要定义不同的存储类型。Python中的数据类型很多,而且也允许我们自定义新的数据类型(这一点在后面会讲到),我们先介绍几种常用的数据类型。

- 整型:Python中可以处理任意大小的整数(Python 2.x中有int和long两种类型的整数,但这种区分对Python来说意义不大,因此在Python 3.x中整数只有int这一种了),而且支持二进制(如`0b100`,换算成十进制是4)、八进制(如`0o100`,换算成十进制是64)、十进制(`100`)和十六进制(`0x100`,换算成十进制是256)的表示法。
- 浮点型:浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,浮点数除了数学写法(如`123.456`)之外还支持科学计数法(如`1.23456e2`)。
- 字符串型:字符串是以单引号或双引号括起来的任意文本,比如`'hello'`和`"hello"`,字符串还有原始字符串表示法、字节字符串表示法、Unicode字符串表示法,而且可以书写成多行的形式(用三个单引号或三个双引号开头,三个单引号或三个双引号结尾)。
- 布尔型:布尔值只有`True`、`False`两种值,要么是`True`,要么是`False`,在Python中,可以直接用`True`、`False`表示布尔值(请注意大小写),也可以通过布尔运算计算出来(例如`3 < 5`会产生布尔值`True`,而`2 == 1`会产生布尔值`False`)。
- 复数型:形如`3+5j`,跟数学上的复数表示一样,唯一不同的是虚部的i换成了j。

#### 变量命名

对于每个变量我们需要给它取一个名字,就如同我们每个人都有属于自己的响亮的名字一样。在Python中,变量命名需要遵循以下这些必须遵守硬性规则和强烈建议遵守的非硬性规则。

- 硬性规则:
  - 变量名由字母(广义的Unicode字符,不包括特殊字符)、数字和下划线构成,数字不能开头。
  - 大小写敏感(大写的`a`和小写的`A`是两个不同的变量)。
  - 不要跟关键字(有特殊含义的单词,后面会讲到)和系统保留字(如函数、模块等的名字)冲突。
- PEP 8要求:
  - 用小写字母拼写,多个单词用下划线连接。
  - 受保护的实例属性用单个下划线开头(后面会讲到)。
  - 私有的实例属性用两个下划线开头(后面会讲到)。

当然,作为一个专业的程序员,给变量(事实上应该是所有的标识符)命名做到见名知意也是非常重要的。

#### 变量的使用

下面通过几个例子来说明变量的类型和变量使用。

```Python
"""

使用变量保存数据并进行算术运算

Version: 0.1
Author: 骆昊
Date: 2018-02-27

"""

a = 321
b = 123
print(a + b)
print(a - b)
print(a * b)
print(a / b)
print(a // b)
print(a % b)
print(a ** b)

```

```Python
"""

使用input函数输入
使用int()进行类型转换
用占位符格式化输出的字符串

Version: 0.1
Author: 骆昊
Date: 2018-02-27

"""

a = int(input('a = '))
b = int(input('b = '))
print('%d + %d = %d' % (a, b, a + b))
print('%d - %d = %d' % (a, b, a - b))
print('%d * %d = %d' % (a, b, a * b))
print('%d / %d = %f' % (a, b, a / b))
print('%d // %d = %d' % (a, b, a // b))
print('%d %% %d = %d' % (a, b, a % b))
print('%d ** %d = %d' % (a, b, a ** b))

```

```Python
"""

使用type()检查变量的类型

Version: 0.1
Author: 骆昊
Date: 2018-02-27

"""

a = 100
b = 12.345
c = 1 + 5j
d = 'hello, world'
e = True
print(type(a))
print(type(b))
print(type(c))
print(type(d))
print(type(e))

```

在对变量类型进行转换时可以使用Python的内置函数(准确的说下面列出的并不是真正意义上的函数,而是后面我们要讲到的创建对象的构造方法)。

- int():将一个数值或字符串转换成整数,可以指定进制。
- float():将一个字符串转换成浮点数。
- str():将指定的对象转换成字符串形式,可以指定编码。
- chr():将整数转换成该编码对应的字符串(一个字符)。
- ord():将字符串(一个字符)转换成对应的编码(整数)。

### 运算符

Python支持多种运算符,下表大致按照优先级从高到低的顺序列出了所有的运算符,我们会陆续使用到它们。

| 运算符                                                       | 描述                           |
| ------------------------------------------------------------ | ------------------------------ |
| `[]` `[:]`                                                   | 下标,切片                     |
| `**`                                                         | 指数                           |
| `~` `+` `-`                                                  | 按位取反, 正负号               |
| `*` `/` `%` `//`                                             | 乘,除,模,整除               |
| `+` `-`                                                      | 加,减                         |
| `>>` `<<`                                                    | 右移,左移                     |
| `&`                                                          | 按位与                         |
| `^` `|`                                                      | 按位异或,按位或               |
| `<=` `<` `>` `>=`                                            | 小于等于,小于,大于,大于等于 |
| `==` `!=`                                                    | 等于,不等于                   |
| `is`  `is not`                                               | 身份运算符                     |
| `in` `not in`                                                | 成员运算符                     |
| `not` `or` `and`                                             | 逻辑运算符                     |
| `=` `+=` `-=` `*=` `/=` `%=` `//=` `**=` `&=` `|=` `^=` `>>=` `<<=` | (复合)赋值运算符             |

>**说明:**在实际开发中,如果搞不清楚优先级可以使用括号来确保运算的执行顺序。

下面的例子演示了运算符的使用。

```Python
"""

运算符的使用

Version: 0.1
Author: 骆昊
Date: 2018-02-27

"""

a = 5
b = 10
c = 3
d = 4
e = 5
a += b
a -= c
a *= d
a /= e
print("a = ", a)

flag1 = 3 > 2
flag2 = 2 < 1
flag3 = flag1 and flag2
flag4 = flag1 or flag2
flag5 = not flag1
print("flag1 = ", flag1)
print("flag2 = ", flag2)
print("flag3 = ", flag3)
print("flag4 = ", flag4)
print("flag5 = ", flag5)
print(flag1 is True)
print(flag2 is not False)

```

### 练习

#### 练习1:华氏温度转摄氏温度。

```Python
"""

将华氏温度转换为摄氏温度
F = 1.8C + 32

Version: 0.1
Author: 骆昊
Date: 2018-02-27

"""

f = float(input('请输入华氏温度: '))
c = (f - 32) / 1.8
print('%.1f华氏度 = %.1f摄氏度' % (f, c))

```

#### 练习2:输入圆的半径计算计算周长和面积。

```Python
"""

输入半径计算圆的周长和面积

Version: 0.1
Author: 骆昊
Date: 2018-02-27

"""

import math

radius = float(input('请输入圆的半径: '))
perimeter = 2 * math.pi * radius
area = math.pi * radius * radius
print('周长: %.2f' % perimeter)
print('面积: %.2f' % area)

```

#### 练习3:输入年份判断是不是闰年。

```Python
"""

输入年份 如果是闰年输出True 否则输出False

Version: 0.1
Author: 骆昊
Date: 2018-02-27

"""

year = int(input('请输入年份: '))
# 如果代码太长写成一行不便于阅读 可以使用\或()折行
is_leap = (year % 4 == 0 and year % 100 != 0 or
           year % 400 == 0)
print(is_leap)
```



================================================
FILE: Day01-15/Day03/.py
================================================


================================================
FILE: Day01-15/Day03/convert.py
================================================
"""

英制单位英寸和公制单位厘米互换

Version: 0.1
Author: 骆昊
Date: 2018-02-28

"""

value = float(input('请输入长度: '))
unit = input('请输入单位: ')
if unit == 'in' or unit == '英寸':
	print('%f英寸 = %f厘米' % (value, value * 2.54))
elif unit == 'cm' or unit == '厘米':
	print('%f厘米 = %f英寸' % (value, value / 2.54))
else:
	print('请输入有效的单位')


================================================
FILE: Day01-15/Day03/grade.py
================================================
"""

百分制成绩转等级制成绩
90分以上 	 	--> A
80分~89分 	--> B
70分~79分	--> C
60分~69分	--> D
60分以下		--> E

Version: 0.1
Author: 骆昊
Date: 2018-02-28

"""

score = float(input('请输入成绩: '))
if score >= 90:
	grade = 'A'
elif score >= 80:
	grade = 'B'
elif score >= 70:
	grade = 'C'
elif score >= 60:
	grade = 'D'
else:
	grade = 'E'
print('对应的等级是:', grade)


================================================
FILE: Day01-15/Day03/piecewise.py
================================================
"""

分段函数求值
		3x - 5	(x > 1)
f(x) =	x + 2	(-1 <= x <= 1)
		5x + 3	(x < -1)

Version: 0.1
Author: 骆昊
Date: 2018-02-28

"""

x = float(input('x = '))
if x > 1:
	y = 3 * x - 5
elif x >= -1:
	y = x + 2
else:
	y = 5 * x + 3
print('f(%.2f) = %.2f' % (x, y))


================================================
FILE: Day01-15/Day03/rolldice.py
================================================
"""

掷骰子决定做什么事情

Version: 0.1
Author: 骆昊
Date: 2018-02-28

"""

from random import randint

face = randint(1, 6)
if face == 1:
	result = '唱首歌'
elif face == 2:
	result = '跳个舞'
elif face == 3:
	result = '学狗叫'
elif face == 4:
	result = '做俯卧撑'
elif face == 5:
	result = '念绕口令'
else:
	result = '讲冷笑话'
print(result)


================================================
FILE: Day01-15/Day03/tax.py
================================================
"""

输入月收入和五险一金计算个人所得税

Version: 0.1
Author: 骆昊
Date: 2018-02-28

"""

salary = float(input('本月收入: '))
insurance = float(input('五险一金: '))
diff = salary - insurance - 3500
if diff <= 0:
	rate = 0
	deduction = 0
elif diff < 1500:
	rate = 0.03
	deduction = 0
elif diff < 4500:
	rate = 0.1
	deduction = 105
elif diff < 9000:
	rate = 0.2
	deduction = 555
elif diff < 35000:
	rate = 0.25
	deduction = 1005
elif diff < 55000:
	rate = 0.3
	deduction = 2755
elif diff < 80000:
	rate = 0.35
	deduction = 5505
else:
	rate = 0.45
	deduction = 13505
tax = abs(diff * rate - deduction)
print('个人所得税: ¥%.2f元' % tax)
print('实际到手收入: ¥%.2f元' % (diff + 3500 - tax))


================================================
FILE: Day01-15/Day03/triangle.py
================================================
"""

判断输入的边长能否构成三角形
如果能则计算出三角形的周长和面积

Version: 0.1
Author: 骆昊
Date: 2018-02-28

"""

import math

a = float(input('a = '))
b = float(input('b = '))
c = float(input('c = '))
if a + b > c and a + c > b and b + c > a:
	print('周长: %f' % (a + b + c))
	p = (a + b + c) / 2
	area = math.sqrt(p * (p - a) * (p - b) * (p - c))
	print('面积: %f' % (area))
else:
	print('不能构成三角形')


================================================
FILE: Day01-15/Day03/verify.py
================================================
"""

用户身份验证

Version: 0.1
Author: 骆昊
Date: 2018-02-28

"""

# import getpass
# from getpass import getpass
# from getpass import *

username = input('请输入用户名: ')
password = input('请输入口令: ')
# 输入口令的时候终端中没有回显
# password = getpass.getpass('请输入口令: ')
if username == 'admin' and password == '123456':
	print('身份验证成功!')
else:
	print('身份验证失败!')


================================================
FILE: Day01-15/Day03/分支结构.md
================================================
## Day03 - 分支结构

### 分支结构的应用场景

迄今为止,我们写的Python代码都是一条一条语句顺序执行,这种结构的代码我们称之为顺序结构。然而仅有顺序结构并不能解决所有的问题,比如我们设计一个游戏,游戏第一关的通关条件是玩家获得1000分,那么在完成本局游戏后我们要根据玩家得到分数来决定究竟是进入第二关还是告诉玩家“Game Over”,这里就会产生两个分支,而且这两个分支只有一个会被执行,这就是程序中分支结构。类似的场景还有很多,给大家一分钟的时间,你应该可以想到至少5个以上这样的例子,赶紧试一试。

### if语句的使用

在Python中,要构造分支结构可以使用`if`、`elif`和`else`关键字。所谓关键字就是有特殊含义的单词,像`if`和`else`就是专门用于构造分支结构的关键字,很显然你不能够使用它作为变量名(事实上,用作其他的标识符也是不可以)。下面的例子中演示了如何构造一个分支结构。

```Python
"""

用户身份验证

Version: 0.1
Author: 骆昊
Date: 2018-02-28

"""

username = input('请输入用户名: ')
password = input('请输入口令: ')
# 如果希望输入口令时 终端中没有回显 可以使用getpass模块的getpass函数
# import getpass
# password = getpass.getpass('请输入口令: ')
if username == 'admin' and password == '123456':
	print('身份验证成功!')
else:
	print('身份验证失败!')

```

唯一需要说明的是和C/C++、Java等语言不同,Python中没有用花括号来构造代码块而是使用了缩进的方式来设置代码的层次结构,如果`if`条件成立的情况下需要执行多条语句,只要保持多条语句具有相同的缩进就可以了,换句话说连续的代码如果又保持了相同的缩进那么它们属于同一个代码块,相当于是一个执行的整体。

当然如果要构造出更多的分支,可以使用`if…elif…else…`结构,例如下面的分段函数求值。

$$f(x)=\begin{cases} 3x-5&\text{(x>1)}\\x+2&\text{(-1}\leq\text{x}\leq\text{1)}\\5x+3&\text {(x<-1)}\end{cases}$$

```Python
"""

分段函数求值

        3x - 5  (x > 1)
f(x) =  x + 2   (-1 <= x <= 1)
        5x + 3  (x < -1)

Version: 0.1
Author: 骆昊
Date: 2018-02-28

"""

x = float(input('x = '))
if x > 1:
	y = 3 * x - 5
elif x >= -1:
	y = x + 2
else:
	y = 5 * x + 3
print('f(%.2f) = %.2f' % (x, y))

```

当然根据实际开发的需要,分支结构是可以嵌套的,例如判断是否通关以后还要根据你获得的宝物或者道具的数量对你的表现给出等级(比如点亮两颗或三颗星星),那么我们就需要在`if`的内部构造出一个新的分支结构,同理`elif`和`else`中也可以再构造新的分支,我们称之为嵌套的分支结构,也就是说上面的代码也可以写成下面的样子。

```Python
"""

分段函数求值
		3x - 5	(x > 1)
f(x) =	x + 2	(-1 <= x <= 1)
		5x + 3	(x < -1)

Version: 0.1
Author: 骆昊
Date: 2018-02-28

"""

x = float(input('x = '))
if x > 1:
	y = 3 * x - 5
else:
	if x >= -1:
		y = x + 2
	else:
		y = 5 * x + 3
print('f(%.2f) = %.2f' % (x, y))
```

> **说明:**大家可以自己感受一下这两种写法到底是哪一种更好。在之前我们提到的Python之禅中有这么一句话“Flat is bettern than nested.”,之所以提出这个观点是因为嵌套结构的嵌套层次多了之后会严重的影响代码的可读性,如果可以使用扁平化的结构就不要去用嵌套,因此之前的写法是更好的做法。

### 练习

#### 练习1:英制单位与公制单位互换

```Python
"""

英制单位英寸和公制单位厘米互换

Version: 0.1
Author: 骆昊
Date: 2018-02-28

"""

value = float(input('请输入长度: '))
unit = input('请输入单位: ')
if unit == 'in' or unit == '英寸':
	print('%f英寸 = %f厘米' % (value, value * 2.54))
elif unit == 'cm' or unit == '厘米':
	print('%f厘米 = %f英寸' % (value, value / 2.54))
else:
	print('请输入有效的单位')

```

#### 练习2:掷骰子决定做什么

```Python
"""

掷骰子决定做什么事情

Version: 0.1
Author: 骆昊
Date: 2018-02-28

"""

from random import randint

face = randint(1, 6)
if face == 1:
	result = '唱首歌'
elif face == 2:
	result = '跳个舞'
elif face == 3:
	result = '学狗叫'
elif face == 4:
	result = '做俯卧撑'
elif face == 5:
	result = '念绕口令'
else:
	result = '讲冷笑话'
print(result)

```
> **说明:**上面的代码中使用了random模块的randint函数生成指定范围的随机数来模拟掷骰子。

#### 练习3:百分制成绩转等级制

```Python
"""

百分制成绩转等级制成绩
90分以上    --> A
80分~89分    --> B
70分~79分	   --> C
60分~69分    --> D
60分以下    --> E

Version: 0.1
Author: 骆昊
Date: 2018-02-28

"""

score = float(input('请输入成绩: '))
if score >= 90:
	grade = 'A'
elif score >= 80:
	grade = 'B'
elif score >= 70:
	grade = 'C'
elif score >= 60:
	grade = 'D'
else:
	grade = 'E'
print('对应的等级是:', grade)

```
#### 练习4:输入三条边长如果能构成三角形就计算周长和面积

```Python
"""

判断输入的边长能否构成三角形
如果能则计算出三角形的周长和面积

Version: 0.1
Author: 骆昊
Date: 2018-02-28

"""

import math

a = float(input('a = '))
b = float(input('b = '))
c = float(input('c = '))
if a + b > c and a + c > b and b + c > a:
	print('周长: %f' % (a + b + c))
	p = (a + b + c) / 2
	area = math.sqrt(p * (p - a) * (p - b) * (p - c))
	print('面积: %f' % (area))
else:
	print('不能构成三角形')

```
> **说明:**上面的代码中使用了`math`模块的`sqrt`函数来计算平方根。用边长计算三角形面积的公式叫做[海伦公式](https://zh.wikipedia.org/zh-hans/海伦公式)。

#### 练习5:实现一个个人所得税计算器。

```Python
"""

输入月收入和五险一金计算个人所得税

Version: 0.1
Author: 骆昊
Date: 2018-02-28

"""

salary = float(input('本月收入: '))
insurance = float(input('五险一金: '))
diff = salary - insurance - 3500
if diff <= 0:
	rate = 0
	deduction = 0
elif diff < 1500:
	rate = 0.03
	deduction = 0
elif diff < 4500:
	rate = 0.1
	deduction = 105
elif diff < 9000:
	rate = 0.2
	deduction = 555
elif diff < 35000:
	rate = 0.25
	deduction = 1005
elif diff < 55000:
	rate = 0.3
	deduction = 2755
elif diff < 80000:
	rate = 0.35
	deduction = 5505
else:
	rate = 0.45
	deduction = 13505
tax = abs(diff * rate - deduction)
print('个人所得税: ¥%.2f元' % tax)
print('实际到手收入: ¥%.2f元' % (diff + 3500 - tax))

```
>**说明:**上面的代码中使用了Python内置的`abs()`函数取绝对值来处理`-0`的问题。



================================================
FILE: Day01-15/Day04/for1.py
================================================
"""

用for循环实现1~100求和

Version: 0.1
Author: 骆昊
Date: 2018-03-01

"""

sum = 0
for x in range(1, 101):
	if x % 2 == 0:
		sum += x
print(sum)


================================================
FILE: Day01-15/Day04/for2.py
================================================
"""

用for循环实现1~100之间的偶数求和

Version: 0.1
Author: 骆昊
Date: 2018-03-01

"""

sum = 0
for x in range(2, 101, 2):
	sum += x
print(sum)


================================================
FILE: Day01-15/Day04/for3.py
================================================
"""

输入非负整数n计算n!

Version: 0.1
Author: 骆昊
Date: 2018-03-01

"""

n = int(input('n = '))
result = 1
for x in range(1, n + 1):
	result *= x
print('%d! = %d' % (n, result))


================================================
FILE: Day01-15/Day04/for4.py
================================================
"""

输入一个正整数判断它是不是素数

Version: 0.1
Author: 骆昊
Date: 2018-03-01

"""

from math import sqrt

num = int(input('请输入一个正整数: '))
end = int(sqrt(num))
is_prime = True
for x in range(2, end + 1):
	if num % x == 0:
		is_prime = False
		break
if is_prime and num != 1:
	print('%d是素数' % num)
else:
	print('%d不是素数' % num)


================================================
FILE: Day01-15/Day04/for5.py
================================================
"""

输入两个正整数计算最大公约数和最小公倍数

Version: 0.1
Author: 骆昊
Date: 2018-03-01

"""

x = int(input('x = '))
y = int(input('y = '))
if x > y:
	(x, y) = (y, x)
for factor in range(x, 0, -1):
	if x % factor == 0 and y % factor == 0:
		print('%d和%d的最大公约数是%d' % (x, y, factor))
		print('%d和%d的最小公倍数是%d' % (x, y, x * y // factor))
		break


================================================
FILE: Day01-15/Day04/for6.py
================================================
"""

打印各种三角形图案

*
**
***
****
*****

    *
   **
  ***
 ****
*****

    *
   ***
  *****
 *******
*********

Version: 0.1
Author: 骆昊
Date: 2018-03-01

"""

row = int(input('请输入行数: '))
for i in range(row):
    for _ in range(i + 1):
        print('*', end='')
    print()

for i in range(row):
    for j in range(row):
        if j < row - i - 1:
            print(' ', end='')
        else:
            print('*', end='')
    print()

for i in range(row):
    for _ in range(row - i - 1):
        print(' ', end='')
    for _ in range(2 * i + 1):
        print('*', end='')
    print()


================================================
FILE: Day01-15/Day04/while1.py
================================================
"""

用while循环实现1~100求和

Version: 0.1
Author: 骆昊
Date: 2018-03-01

"""

sum = 0
num = 1
while num <= 100:
	sum += num
	num += 1
print(sum)


================================================
FILE: Day01-15/Day04/while2.py
================================================
"""

用while循环实现1~100之间的偶数求和

Version: 0.1
Author: 骆昊
Date: 2018-03-01

"""

sum = 0
num = 2
while num <= 100:
	sum += num
	num += 2
print(sum)


================================================
FILE: Day01-15/Day04/循环结构.md
================================================
## Day04 - 循环结构

### 循环结构的应用场景

如果在程序中我们需要重复的执行某条或某些指令,例如用程序控制机器人踢足球,如果机器人持球而且还没有进入射门范围,那么我们就要一直发出让机器人向球门方向奔跑的指令。当然你可能已经注意到了,刚才的描述中其实不仅仅有需要重复的动作,还有我们上一个章节讲到的分支结构。再举一个简单的例子,比如在我们的程序中要实现每隔1秒中在屏幕上打印一个&quot;hello, world&quot;这样的字符串并持续一个小时,我们肯定不能够将`print('hello, world')`这句代码写上3600遍,如果真的需要这样做那么我们的工作就太无聊了。因此,我们需要循环结构,使用循环结构我们就可以轻松的控制某件事或者某些事重复、重复、再重复的发生。在Python中构造循环结构有两种做法,一种是`for-in`循环,一种是`while`循环。

### for-in循环

如果明确的知道循环执行的次数或者是要对一个容器进行迭代(后面会讲到),那么我们推荐使用`for-in`循环,例如下面代码中计算$\sum_{n=1}^{100}n$。

```Python
"""

用for循环实现1~100求和

Version: 0.1
Author: 骆昊
Date: 2018-03-01

"""

sum = 0
for x in range(101):
	sum += x
print(sum)
```

需要说明的是上面代码中的`range`类型,`range`可以用来产生一个不变的数值序列,而且这个序列通常都是用在循环中的,例如:

- `range(101)`可以产生一个0到100的整数序列。
- `range(1, 100)`可以产生一个1到99的整数序列。
- `range(1, 100, 2)`可以产生一个1到99的奇数序列,其中的2是步长,即数值序列的增量。

知道了这一点,我们可以用下面的代码来实现1~100之间的偶数求和。

```Python
"""

用for循环实现1~100之间的偶数求和

Version: 0.1
Author: 骆昊
Date: 2018-03-01

"""

sum = 0
for x in range(2, 101, 2):
	sum += x
print(sum)
```

也可以通过在循环中使用分支结构的方式来实现相同的功能,代码如下所示。

```Python
"""

用for循环实现1~100之间的偶数求和

Version: 0.1
Author: 骆昊
Date: 2018-03-01

"""

sum = 0
for x in range(1, 101):
	if x % 2 == 0:
		sum += x
print(sum)

```

### while循环

如果要构造不知道具体循环次数的循环结构,我们推荐使用`while`循环,`while`循环通过一个能够产生或转换出`bool`值的表达式来控制循环,表达式的值为`True`循环继续,表达式的值为`False`循环结束。下面我们通过一个“猜数字”的小游戏(计算机出一个1~100之间的随机数,人输入自己猜的数字,计算机给出对应的提示信息,直到人猜出计算机出的数字)来看看如何使用`while`循环。

```Python
"""

猜数字游戏
计算机出一个1~100之间的随机数由人来猜
计算机根据人猜的数字分别给出提示大一点/小一点/猜对了

Version: 0.1
Author: 骆昊
Date: 2018-03-01

"""

import random

answer = random.randint(1, 100)
counter = 0
while True:
	counter += 1
	number = int(input('请输入: '))
	if number < answer:
		print('大一点')
	elif number > answer:
		print('小一点')
	else:
		print('恭喜你猜对了!')
		break
print('你总共猜了%d次' % counter)
if counter > 7:
	print('你的智商余额明显不足')

```

> **说明:**上面的代码中使用了`break`关键字来提前终止循环,需要注意的是`break`只能终止它所在的那个循环,这一点在使用嵌套的循环结构(下面会讲到)需要引起注意。除了`break`之外,还有另一个关键字是`continue`,它可以用来放弃本次循环后续的代码直接让循环进入下一轮。

和分支结构一样,循环结构也是可以嵌套的,也就是说在循环中还可以构造循环结构。下面的例子演示了如何通过嵌套的循环来输出一个九九乘法表。

```Python
"""

输出乘法口诀表(九九表)

Version: 0.1
Author: 骆昊
Date: 2018-03-01

"""

for i in range(1, 10):
	for j in range(1, i + 1):
		print('%d*%d=%d' % (i, j, i * j), end='\t')
	print()

```

### 练习

#### 练习1:输入一个数判断是不是素数。

```Python
"""

输入一个正整数判断它是不是素数

Version: 0.1
Author: 骆昊
Date: 2018-03-01

"""

from math import sqrt

num = int(input('请输入一个正整数: '))
end = int(sqrt(num))
is_prime = True
for x in range(2, end + 1):
	if num % x == 0:
		is_prime = False
		break
if is_prime and num != 1:
	print('%d是素数' % num)
else:
	print('%d不是素数' % num)

```

#### 练习2:输入两个正整数,计算最大公约数和最小公倍数。

```Python
"""

输入两个正整数计算最大公约数和最小公倍数

Version: 0.1
Author: 骆昊
Date: 2018-03-01

"""

x = int(input('x = '))
y = int(input('y = '))
if x > y:
	(x, y) = (y, x)
for factor in range(x, 0, -1):
	if x % factor == 0 and y % factor == 0:
		print('%d和%d的最大公约数是%d' % (x, y, factor))
		print('%d和%d的最小公倍数是%d' % (x, y, x * y // factor))
		break

```

#### 练习3:打印三角形图案。

```Python
"""

打印各种三角形图案

*
**
***
****
*****

    *
   **
  ***
 ****
*****

    *
   ***
  *****
 *******
*********

Version: 0.1
Author: 骆昊
Date: 2018-03-01

"""

row = int(input('请输入行数: '))
for i in range(row):
    for _ in range(i + 1):
        print('*', end='')
    print()


for i in range(row):
    for j in range(row):
        if j < row - i - 1:
            print(' ', end='')
        else:
            print('*', end='')
    print()

for i in range(row):
    for _ in range(row - i - 1):
        print(' ', end='')
    for _ in range(2 * i + 1):
        print('*', end='')
    print()

```



================================================
FILE: Day01-15/Day05/chicken.py
================================================
"""

求解《百钱百鸡》问题
1只公鸡5元 1只母鸡3元 3只小鸡1元 用100元买100只鸡
问公鸡 母鸡 小鸡各有多少只

Version: 0.1
Author: 骆昊
Date: 2018-03-02

"""

for x in range(0, 20):
	for y in range(0, 33):
		z = 100 - x - y
		if 5 * x + 3 * y + z / 3 == 100:
			print('公鸡: %d只, 母鸡: %d只, 小鸡: %d只' % (x, y, z))

# 要理解程序背后的算法 - 穷举法


================================================
FILE: Day01-15/Day05/craps.py
================================================
"""

Craps赌博游戏
玩家摇两颗色子 如果第一次摇出7点或11点 玩家胜
如果摇出2点 3点 12点 庄家胜 其他情况游戏继续
玩家再次要色子 如果摇出7点 庄家胜
如果摇出第一次摇的点数 玩家胜
否则游戏继续 玩家继续摇色子
玩家进入游戏时有1000元的赌注 全部输光游戏结束

Version: 0.1
Author: 骆昊
Date: 2018-03-02

"""

from random import randint

money = 1000
while money > 0:
	print('你的总资产为:', money)
	needs_go_on = False
	while True:
		debt = int(input('请下注: '))
		if debt > 0 and debt <= money:
			break
	first = randint(1, 6) + randint(1, 6)
	print('玩家摇出了%d点' % first)
	if first == 7 or first == 11:
		print('玩家胜!')
		money += debt
	elif first == 2 or first == 3 or first == 12:
		print('庄家胜!')
		money -= debt
	else:
		needs_go_on = True

	while needs_go_on:
		current = randint(1, 6) + randint(1, 6)
		print('玩家摇出了%d点' % current)
		if current == 7:
			print('庄家胜')
			money -= debt
			needs_go_on = False
		elif current == first:
			print('玩家胜')
			money += debt
			needs_go_on = False

print('你破产了, 游戏结束!')


================================================
FILE: Day01-15/Day05/fibonacci.py
================================================
"""

输出斐波那契数列的前20个数
1 1 2 3 5 8 13 21 ...

Version: 0.1
Author: 骆昊
Date: 2018-03-02

"""

a = 0
b = 1
for _ in range(20):
	(a, b) = (b, a + b)
	print(a, end=' ')


================================================
FILE: Day01-15/Day05/guess.py
================================================
"""

猜数字游戏
计算机出一个1~100之间的随机数由人来猜
计算机根据人猜的数字分别给出提示大一点/小一点/猜对了

Version: 0.1
Author: 骆昊
Date: 2018-03-02

"""

import random

answer = random.randint(1, 100)
counter = 0
while True:
	counter += 1
	number = int(input('请输入: '))
	if number < answer:
		print('大一点')
	elif number > answer:
		print('小一点')
	else:
		print('恭喜你猜对了!')
		break
print('你总共猜了%d次' % counter)
if counter > 7:
	print('你的智商余额明显不足')


================================================
FILE: Day01-15/Day05/lily.py
================================================
"""

找出100~999之间的所有水仙花数
水仙花数是各位立方和等于这个数本身的数
如: 153 = 1**3 + 5**3 + 3**3

Version: 0.1
Author: 骆昊
Date: 2018-03-02

"""

for num in range(100, 1000):
	low = num % 10
	mid = num // 10 % 10
	high = num // 100
	if num == low ** 3 + mid ** 3 + high ** 3:
		print(num)


================================================
FILE: Day01-15/Day05/palindrome.py
================================================
"""

判断输入的正整数是不是回文数
回文数是指将一个正整数从左往右排列和从右往左排列值一样的数

Version: 0.1
Author: 骆昊
Date: 2018-03-02

"""

num = int(input('请输入一个正整数: '))
temp = num
num2 = 0
while temp > 0:
	num2 *= 10
	num2 += temp % 10
	temp //= 10
if num == num2:
	print('%d是回文数' % num)
else:
	print('%d不是回文数' % num)


================================================
FILE: Day01-15/Day05/perfect.py
================================================
"""

找出1~9999之间的所有完美数
完美数是除自身外其他所有因子的和正好等于这个数本身的数
例如: 6 = 1 + 2 + 3, 28 = 1 + 2 + 4 + 7 + 14

Version: 0.1
Author: 骆昊
Date: 2018-03-02

"""
import time
import math

start = time.clock()
for num in range(1, 10000):
	sum = 0
	for factor in range(1, int(math.sqrt(num)) + 1):
		if num % factor == 0:
			sum += factor
			if factor > 1 and num / factor != factor:
				sum += num / factor
	if sum == num:
		print(num)
end = time.clock()
print("执行时间:", (end - start), "秒")

# 通过比较上面两种不同的解决方案的执行时间 意识到优化程序的重要性


================================================
FILE: Day01-15/Day05/prime.py
================================================
"""

输出2~99之间的素数

Version: 0.1
Author: 骆昊
Date: 2018-03-02

"""

import math

for num in range(2, 100):
	is_prime = True
	for factor in range(2, int(math.sqrt(num)) + 1):
		if num % factor == 0:
			is_prime = False
			break
	if is_prime:
		print(num, end=' ')


================================================
FILE: Day01-15/Day05/table.py
================================================
"""

输出乘法口诀表(九九表)

Version: 0.1
Author: 骆昊
Date: 2018-03-02

"""

for i in range(1, 10):
	for j in range(1, i + 1):
		print('%d*%d=%d' % (i, j, i * j), end='\t')
	print()


================================================
FILE: Day01-15/Day05/总结和练习.md
================================================
## 总结和练习


================================================
FILE: Day01-15/Day06/function1.py
================================================
"""

函数的定义和使用 - 计算组合数C(7,3)

Version: 0.1
Author: 骆昊
Date: 2018-03-05

"""


# 将求阶乘的功能封装成一个函数
def factorial(n):
	result = 1
	for num in range(1, n + 1):
		result *= num
	return result


print(factorial(7) // factorial(3) // factorial(4))


================================================
FILE: Day01-15/Day06/function2.py
================================================
"""

函数的定义和使用 - 求最大公约数和最小公倍数

Version: 0.1
Author: 骆昊
Date: 2018-03-05

"""


def gcd(x, y):
	if x > y:
		(x, y) = (y, x)
	for factor in range(x, 1, -1):
		if x % factor == 0 and y % factor == 0:
			return factor
	return 1


def lcm(x, y):
	return x * y // gcd(x, y)


print(gcd(15, 27))
print(lcm(15, 27))


================================================
FILE: Day01-15/Day06/function3.py
================================================
"""

Python的内置函数
	- 数学相关: abs / divmod / pow / round / min / max / sum
	- 序列相关: len / range / next / filter / map / sorted / slice / reversed
	- 类型转换: chr / ord / str / bool / int / float / complex / bin / oct / hex
	- 数据结构: dict / list / set / tuple
	- 其他函数: all / any / id / input / open / print / type

Version: 0.1
Author: 骆昊
Date: 2018-03-05

"""


def myfilter(mystr):
	return len(mystr) == 6


# help()
print(chr(0x9a86))
print(hex(ord('骆')))
print(abs(-1.2345))
print(round(-1.2345))
print(pow(1.2345, 5))
fruits = ['orange', 'peach', 'durian', 'watermelon']
print(fruits[slice(1, 3)])
fruits2 = list(filter(myfilter, fruits))
print(fruits)
print(fruits2)


================================================
FILE: Day01-15/Day06/function4.py
================================================
"""

Python常用模块
	- 运行时服务相关模块: copy / pickle / sys / ...
	- 数学相关模块: decimal / math / random / ...
	- 字符串处理模块: codecs / re / ...
	- 文件处理相关模块: shutil / gzip / ...
	- 操作系统服务相关模块: datetime / os / time / logging / io / ...
	- 进程和线程相关模块: multiprocessing / threading / queue
	- 网络应用相关模块: ftplib / http / smtplib / urllib / ...
	- Web编程相关模块: cgi / webbrowser
	- 数据处理和编码模块: base64 / csv / html.parser / json / xml / ...

Version: 0.1
Author: 骆昊
Date: 2018-03-05

"""

import time
import shutil
import os

seconds = time.time()
print(seconds)
localtime = time.localtime(seconds)
print(localtime)
print(localtime.tm_year)
print(localtime.tm_mon)
print(localtime.tm_mday)
asctime = time.asctime(localtime)
print(asctime)
strtime = time.strftime('%Y-%m-%d %H:%M:%S', localtime)
print(strtime)
mydate = time.strptime('2018-1-1', '%Y-%m-%d')
print(mydate)

shutil.copy('/Users/Hao/hello.py', '/Users/Hao/Desktop/first.py')
os.system('ls -l')
os.chdir('/Users/Hao')
os.system('ls -l')
os.mkdir('test')


================================================
FILE: Day01-15/Day06/function5.py
================================================
"""

函数的参数
	- 默认参数
	- 可变参数
	- 关键字参数
	- 命名关键字参数

Version: 0.1
Author: 骆昊
Date: 2018-03-05

"""


# 参数默认值
def f1(a, b=5, c=10):
	return a + b * 2 + c * 3


print(f1(1, 2, 3))
print(f1(100, 200))
print(f1(100))
print(f1(c=2, b=3, a=1))


# 可变参数
def f2(*args):
	sum = 0
	for num in args:
		sum += num
	return sum


print(f2(1, 2, 3))
print(f2(1, 2, 3, 4, 5))
print(f2())


# 关键字参数
def f3(**kw):
	if 'name' in kw:
		print('欢迎你%s!' % kw['name'])
	elif 'tel' in kw:
		print('你的联系电话是: %s!' % kw['tel'])
	else:
		print('没找到你的个人信息!')


param = {'name': '骆昊', 'age': 38}
f3(**param)
f3(name='骆昊', age=38, tel='13866778899')
f3(user='骆昊', age=38, tel='13866778899')
f3(user='骆昊', age=38, mobile='13866778899')


================================================
FILE: Day01-15/Day06/function6.py
================================================
"""

作用域问题

Version: 0.1
Author: 骆昊
Date: 2018-03-05

"""


# 局部作用域
def foo1():
	a = 5


foo1()
# print(a)	# NameError

# 全局作用域
b = 10


def foo2():
	print(b)


foo2()


def foo3():
	b = 100		# 局部变量
	print(b)


foo3()
print(b)


def foo4():
	global b
	b = 200		# 全局变量
	print(b)


foo4()
print(b)


================================================
FILE: Day01-15/Day06/函数和模块的使用.md
================================================
## 函数和模块的使用

在讲解本章节的内容之前,我们先来研究一道数学题,请说出下面的方程有多少组正整数解。

$$x_1 + x_2 + x_3 + x_4 = 8$$

事实上,上面的问题等同于将8个苹果分成四组每组至少一个苹果有多少种方案。想到这一点问题的答案就呼之欲出了。

$$C_M^N =\frac{M!}{N!(M-N)!}, \text{(M=7, N=3)} $$

可以用Python的程序来计算出这个值,代码如下所示。

```Python
"""

输入M和N计算C(M,N)

"""

m = int(input('m = '))
n = int(input('n = '))
fm = 1
for num in range(1, m + 1):
    fm *= num
fn = 1
for num in range(1, n + 1):
    fn *= num
fmn = 1
for num in range(1, m - n + 1):
    fmn *= num
print(fm // fn // fmn)

```

### 函数的作用

不知道大家是否注意到,在上面的代码中,我们做了3次求阶乘,这样的代码实际上就是重复代码。编程大师Martin Fowler先生曾经说过:“代码有很多种坏味道,重复是最坏的一种!”,要写出高质量的代码首先要解决的就是重复代码的问题。对于上面的代码来说,我们可以将计算阶乘的功能封装到一个称之为“函数”的功能模块中,在需要计算阶乘的地方,我们只需要“调用”这个“函数”就可以了。

### 定义函数

在Python中可以使用`def`关键字来定义函数,和变量一样每个函数也有一个响亮的名字,而且命名规则跟变量的命名规则是一致的。在函数名后面的圆括号中可以放置传递给函数的参数,这一点和数学上的函数非常相似,程序中函数的参数就相当于是数学上说的函数的自变量,而函数执行完成后我们可以通过`return`关键字来返回一个值,这相当于数学上说的函数的因变量。

在了解了如何定义函数后,我们可以对上面的代码进行重构,所谓重构就是在不影响代码执行结果的前提下对代码的结构进行调整,重构之后的代码如下所示。

```Python
def factorial(num):
    """
    求阶乘
    
    :param num: 非负整数
    
    :return: num的阶乘
    """
    result = 1
    for n in range(1, num + 1):
        result *= n
    return result


m = int(input('m = '))
n = int(input('n = '))
# 当需要计算阶乘的时候不用再写循环求阶乘而是直接调用已经定义好的函数
print(factorial(m) // factorial(n) // factorial(m - n))

```

> **说明:**Python的math模块中其实已经有一个factorial函数了,事实上要计算阶乘可以直接使用这个现成的函数而不用自己定义。下面例子中的某些函数其实Python中也是内置了,我们这里是为了讲解函数的定义和使用才把它们又实现了一遍,实际开发中不建议做这种低级的重复性的工作。


### 函数的参数

函数是绝大多数编程语言中都支持的一个代码的“构建块”,但是Python中的函数与其他语言中的函数还是有很多不太相同的地方,其中一个显著的区别就是Python对函数参数的处理。在Python中,函数的参数可以有默认值,也支持使用可变参数,所以Python并不需要像其他语言一样支持[函数的重载](https://zh.wikipedia.org/wiki/%E5%87%BD%E6%95%B0%E9%87%8D%E8%BD%BD),因为我们在定义一个函数的时候可以让它有多种不同的使用方式,下面是两个小例子。

```Python
from random import randint


def roll_dice(n=2):
    """
    摇色子
    
    :param n: 色子的个数
    
    :return: n颗色子点数之和
    """
	total = 0
	for _ in range(n):
		total += randint(1, 6)
	return total


def add(a=0, b=0, c=0):
	return a + b + c


# 如果没有指定参数那么使用默认值摇两颗色子
print(roll_dice())
# 摇三颗色子
print(roll_dice(3))
print(add())
print(add(1))
print(add(1, 2))
print(add(1, 2, 3))
# 传递参数时可以不按照设定的顺序进行传递
print(add(c=50, a=100, b=200))

```

我们给上面两个函数的参数都设定了默认值,这也就意味着如果在调用函数的时候如果没有传入对应参数的值时将使用该参数的默认值,所以在上面的代码中我们可以用各种不同的方式去调用`add`函数,这跟其他很多语言中函数重载的效果是一致的。

其实上面的`add`函数还有更好的实现方案,因为我们可能会对0个或多个参数进行加法运算,而具体有多少个参数是由调用者来决定,我们作为函数的设计者对这一点是一无所知的,因此在不确定参数个数的时候,我们可以使用可变参数,代码如下所示。

```Python
# 在参数前使用*表示args是可变参数
# 也就是说调用add函数时传入的参数个数可以是0个或多个
def add(*args):
	total = 0
	for val in args:
		total += val
	return total


print(add())
print(add(1))
print(add(1, 2))
print(add(1, 2, 3))
print(add(1, 3, 5, 7, 9))

```

### 用模块管理函数

对于任何一种编程语言来说,给变量、函数这样的标识符起名字都是一个让人头疼的问题,因为我们会遇到命名冲突这种尴尬的情况。最简单的场景就是在同一个.py文件中定义了两个同名函数,由于Python没有函数重载的概念,那么后面的定义会覆盖之前的定义,也就意味着两个函数同名函数实际上只有一个是存在的。

```Python
def foo():
	print('hello, world!')


def foo():
	print('goodbye, world!')


foo()	# 输出goodbye, world!

```

当然上面的这种情况我们很容易就能避免,但是如果项目是由多人协作进行团队开发的时候,团队中可能有多个程序员都定义了名为`foo`的函数,那么怎么解决这种命名冲突呢?答案其实很简单,Python中每个文件就代表了一个模块(module),我们在不同的模块中可以有同名的函数,在使用函数的时候我们通过`import`关键字导入指定的模块就可以区分到底要使用的是哪个模块中的`foo`函数,代码如下所示。

module1.py

```Python
def foo():
    print('hello, world!')
```

module2.py

```Python
def foo():
    print('goodbye, world!')
```

test.py

```Python
from module1 import foo

foo()	# 输出hello, world!

from module2 import foo

foo()	# 输出goodbye, world!

```

也可以按照如下所示的方式来区分到底要使用哪一个`foo`函数。

test.py

```Python
import module1 as m1
import module2 as m2

m1.foo()
m2.foo()

```

但是如果将代码写成了下面的样子,那么程序中调用的是最后导入的那个`foo`,因为后导入的foo覆盖了之前导入的`foo`。

test.py

```Python
from module1 import foo
from module2 import foo

foo()	# 输出goodbye, world!

```

test.py

```Python
from module2 import foo
from module1 import foo

foo()	# 输出hello, world!

```

需要说明的是,如果我们导入的模块除了定义函数之外还中有可以执行代码,那么Python解释器在导入这个模块时就会执行这些代码,事实上我们可能并不希望如此,因此如果我们在模块中编写了执行代码,最好是将这些执行代码放入如下所示的条件中,这样的话除非直接运行该模块,if条件下的这些代码是不会执行的,因为只有直接执行的模块的名字才是“\_\_main\_\_”。

module3.py

```Python
def foo():
    pass


def bar():
    pass


# __name__是Python中一个隐含的变量它代表了模块的名字
# 只有被Python解释器直接执行的模块的名字才是__main__
if __name__ == '__main__':
    print('call foo()')
    foo()
    print('call bar()')
    bar()

```

test.py

```Python
import module3

# 导入module3时 不会执行模块中if条件成立时的代码 因为模块的名字是module3而不是__main__

```

### 练习

#### 练习1:实现计算求最大公约数和最小公倍数的函数。

```Python
def gcd(x, y):
	(x, y) = (y, x) if x > y else (x, y)
	for factor in range(x, 0, -1):
		if x % factor == 0 and y % factor == 0:
			return factor


def lcm(x, y):
	return x * y // gcd(x, y)
```

#### 练习2:实现判断一个数是不是回文数的函数。

```Python
def is_palindrome(num):
	temp = num
	total = 0
	while temp > 0:
		total = total * 10 + temp % 10
		temp //= 10
	return total == num
```

#### 练习3:实现判断一个数是不是素数的函数。

```Python
def is_prime(num):
	for factor in range(2, num):
		if num % factor == 0:
			return False
	return True if num != 1 else False
```

#### 练习4:写一个程序判断输入的正整数是不是回文素数。

```Python
if __name__ == '__main__':
	num = int(input('请输入正整数: '))
	if is_palindrome(num) and is_prime(num):
		print('%d是回文素数' % num)

```

通过上面的程序可以看出,当我们将代码中重复出现的和相对独立的功能抽取成函数后,我们可以组合使用这些函数来解决更为复杂的问题,这也是我们为什么要定义和使用函数的一个非常重要的原因。

最后,我们来讨论一下Python中有关变量作用域的问题。

```Python
def foo():
	b = 'hello'

	def bar():  # Python中可以在函数内部再定义函数
        c = True
		print(a)
		print(b)
        print(c)

	bar()
    # print(c)  # NameError: name 'c' is not defined


if __name__ == '__main__':
	a = 100
    # print(b)  # NameError: name 'b' is not defined
	foo()

```

上面的代码能够顺利的执行并且打印出100和“hello”,但我们注意到了,在`bar`函数的内部并没有定义`a`和`b`两个变量,那么`a`和`b`是从哪里来的。我们在上面代码的`if`分支中定义了一个变量`a`,这是一个全局变量(global variable),属于全局作用域,因为它没有定义在任何一个函数中。在上面的`foo`函数中我们定义了变量`b`,这是一个定义在函数中的局部变量(local variable),属于局部作用域,在`foo`函数的外部并不能访问到它;但对于`foo`函数内部的`bar`函数来说,变量`b`属于嵌套作用域,在`bar`函数中我们是可以访问到它的。`bar`函数中的变量`c`属于局部作用域,在`bar`函数之外是无法访问的。事实上,Python查找一个变量时会按照“局部作用域”、“嵌套作用域”、“全局作用域”和“内置作用域”的顺序进行搜索,前三者我们在上面的代码中已经看到了,所谓的“内置作用域”就是Python内置的那些隐含标识符`min`、`len`等都属于内置作用域)。

再看看下面这段代码,我们希望通过函数调用修改全局变量`a`的值,但实际上下面的代码是做不到的。

```Python
def foo():
	a = 200
	print(a)  # 200


if __name__ == '__main__':
	a = 100
	foo()
	print(a)  # 100

```

在调用`foo`函数后,我们发现`a`的值仍然是100,这是因为当我们在函数`foo`中写`a = 200`的时候,是重新定义了一个名字为`a`的局部变量,它跟全局作用域的`a`并不是同一个变量,因为局部作用域中有了自己的变量`a`,因此`foo`函数不再搜索全局作用域中的`a`。如果我们希望在`foo`函数中修改全局作用域中的`a`,代码如下所示。

```Python
def foo():
	global a
	a = 200
	print(a)  # 200


if __name__ == '__main__':
	a = 100
	foo()
	print(a)  # 200

```

我们可以使用`global`关键字来指示`foo`函数中的变量`a`来自于全局作用域,如果全局作用域中没有`a`,那么下面一行的代码就会定义变量`a`并将其置于全局作用域。同理,如果我们希望函数内部的函数能够修改嵌套作用域中的变量,可以使用`nonlocal`关键字来指示变量来自于嵌套作用域,请大家自行试验。

在实际开发中,我们应该尽量减少对全局变量的使用,因为全局变量的作用域和影响过于广泛,可能会发生意料之外的修改和使用,除此之外全局变量比局部变量拥有更长的生命周期,可能导致对象占用的内存长时间无法被[垃圾回收](https://zh.wikipedia.org/wiki/%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6_(%E8%A8%88%E7%AE%97%E6%A9%9F%E7%A7%91%E5%AD%B8))。事实上,减少对全局变量的使用,也是降低代码之间耦合度的一个重要举措,同时也是对[迪米特法则](https://zh.wikipedia.org/zh-hans/%E5%BE%97%E5%A2%A8%E5%BF%92%E8%80%B3%E5%AE%9A%E5%BE%8B)的践行。减少全局变量的使用就意味着我们应该尽量让变量的作用域在函数的内部,但是如果我们希望将一个局部变量的生命周期延长,使其在函数调用结束后依然可以访问,这时候就需要使用[闭包](https://zh.wikipedia.org/wiki/%E9%97%AD%E5%8C%85_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6)),这个我们在后续的内容中进行讲解。

> **说明**:很多人经常会将“闭包”一词和[“匿名函数”](https://zh.wikipedia.org/wiki/%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0)混为一谈,但实际上它们是不同的概念,如果想提前了解这个概念,推荐看看[维基百科](https://zh.wikipedia.org/wiki/)或者[知乎](https://www.zhihu.com/)上对这个概念的讨论。

说了那么多,其实结论很简单,从现在开始我们可以将Python代码按照下面的格式进行书写,这一点点的改进其实就是在我们理解了函数和作用域的基础上跨出的巨大的一步。

```Python
def main():
    # Todo: Add your code here
    pass


if __name__ == '__main__':
    main()

```



================================================
FILE: Day01-15/Day07/avgscore.py
================================================
"""

输入学生考试成绩计算平均分

Version: 0.1
Author: 骆昊
Date: 2018-03-06

"""


def main():
	number = int(input('请输入学生人数: '))
	names = [None] * number
	scores = [None] * number
	for index in range(len(names)):
		names[index] = input('请输入第%d个学生的名字: ' % (index + 1))
		scores[index] = float(input('请输入第%d个学生的成绩: ' % (index + 1)))
	total = 0
	for index in range(len(names)):
		print('%s: %.1f分' % (names[index], scores[index]))
		total += scores[index]
	print('平均成绩是: %.1f分' % (total / number))


if __name__ == '__main__':
	main()


================================================
FILE: Day01-15/Day07/dict1.py
================================================
"""

定义和使用字典

Version: 0.1
Author: 骆昊
Date: 2018-03-06

"""


def main():
	scores = {'骆昊': 95, '白元芳': 78, '狄仁杰': 82}
	print(scores['骆昊'])
	print(scores['狄仁杰'])
	for elem in scores:
		print('%s\t--->\t%d' % (elem, scores[elem]))
	scores['白元芳'] = 65
	scores['诸葛王朗'] = 71
	scores.update(冷面=67, 方启鹤=85)
	print(scores)
	if '武则天' in scores:
		print(scores['武则天'])
	print(scores.get('武则天'))
	print(scores.get('武则天', 60))
	print(scores.popitem())
	print(scores.popitem())
	print(scores.pop('骆昊', 100))
	scores.clear()
	print(scores)


if __name__ == '__main__':
	main()


================================================
FILE: Day01-15/Day07/dict2.py
================================================
"""

字典的常用操作

Version: 0.1
Author: 骆昊
Date: 2018-03-06

"""


def main():
	stu = {'name': '骆昊', 'age': 38, 'gender': True}
	print(stu)
	print(stu.keys())
	print(stu.values())
	print(stu.items())
	for elem in stu.items():
		print(elem)
		print(elem[0], elem[1])
	if 'age' in stu:
		stu['age'] = 20
	print(stu)
	stu.setdefault('score', 60)
	print(stu)
	stu.setdefault('score', 100)
	print(stu)
	stu['score'] = 100
	print(stu)


if __name__ == '__main__':
	main()


================================================
FILE: Day01-15/Day07/fibonacci.py
================================================
"""

生成斐波拉切数列

Version: 0.1
Author: 骆昊
Date: 2018-03-06

"""


def main():
	f = [1 , 1]
	for i in range(2, 20):
		f += [f[i - 1] + f[i - 2]]
		# f.append(f[i - 1] + f[i - 2])
	for val in f:
		print(val, end=' ')


if __name__ == '__main__':
	main()


================================================
FILE: Day01-15/Day07/findmax.py
================================================
"""

找出列表中最大或最小的元素

Version: 0.1
Author: 骆昊
Date: 2018-03-06

"""


def main():
	fruits = ['grape', 'apple', 'strawberry', 'waxberry', 'pitaya']
	# 直接使用内置的max和min函数找出列表中最大和最小元素
	# print(max(fruits))
	# print(min(fruits))
	max_value = min_value = fruits[0]
	for index in range(1, len(fruits)):
		if fruits[index] > max_value:
			max_value = fruits[index]
		elif fruits[index] < min_value:
			min_value = fruits[index]
	print('Max:', max_value)
	print('Min:', min_value)


if __name__ == '__main__':
	main()
# 想一想如果最大的元素有两个要找出第二大的又该怎么做 


================================================
FILE: Day01-15/Day07/list1.py
================================================
"""

定义和使用列表
	- 用下标访问元素
	- 添加元素
	- 删除元素

Version: 0.1
Author: 骆昊
Date: 2018-03-06

"""


def main():
	fruits = ['grape', '@pple', 'strawberry', 'waxberry']
	print(fruits)
	# 通过下标访问元素
	print(fruits[0])
	print(fruits[1])
	print(fruits[-1])
	print(fruits[-2])
	# print(fruits[-5]) # IndexError
	# print(fruits[4])	# IndexError
	fruits[1] = 'apple'
	print(fruits)
	# 添加元素
	fruits.append('pitaya')
	fruits.insert(0, 'banana')
	print(fruits)
	# 删除元素
	del fruits[1]
	fruits.pop()
	fruits.pop(0)
	fruits.remove('apple')
	print(fruits)


if __name__ == '__main__':
	main()


================================================
FILE: Day01-15/Day07/list2.py
================================================
"""

列表常用操作
	- 列表连接
	- 获取长度
	- 遍历列表
	- 列表切片
	- 列表排序
	- 列表反转
	- 查找元素

Version: 0.1
Author: 骆昊
Date: 2018-03-06

"""


def main():
	fruits = ['grape', 'apple', 'strawberry', 'waxberry']
	fruits += ['pitaya', 'pear', 'mango']
	# 循环遍历列表元素
	for fruit in fruits:
		print(fruit.title(), end=' ')
	print()
	# 列表切片
	fruits2 = fruits[1:4]
	print(fruits2)
	# fruit3 = fruits  # 没有复制列表只创建了新的引用
	fruits3 = fruits[:]
	print(fruits3)
	fruits4 = fruits[-3:-1]
	print(fruits4)
	fruits5 = fruits[::-1]
	print(fruits5)


if __name__ == '__main__':
	main()


================================================
FILE: Day01-15/Day07/list3.py
================================================
"""

生成列表
	- 用range创建数字列表
	- 生成表达式
	- 生成器

Version: 0.1
Author: 骆昊
Date: 2018-03-06

"""


# 生成Fibonacci序列的生成器
def fib(n):
	a, b = 0, 1
	for _ in range(n):
		a, b = b, a + b
		yield a


def main():
	# 用range创建数值列表
	list1 = list(range(1, 11))
	print(list1)
	# 生成表达式
	list2 = [x * x for x in range(1, 11)]
	print(list2)
	list3 = [m + n for m in 'ABCDEFG' for n in '12345']
	print(list3)
	print(len(list3))
	# 生成器(节省空间但生成下一个元素时需要花费时间)
	gen = (m + n for m in 'ABCDEFG' for n in '12345')
	print(gen)
	for elem in gen:
		print(elem, end=' ')
	print()
	gen = fib(20)
	print(gen)
	for elem in gen:
		print(elem, end=' ')
	print()


if __name__ == '__main__':
	main()


================================================
FILE: Day01-15/Day07/lottery.py
================================================
"""

双色球随机选号程序

Version: 0.1
Author: 骆昊
Date: 2018-03-06

"""

from random import randrange, randint, sample


def display(balls):
	"""
	输出列表中的双色球号码
	"""
	for index, ball in enumerate(balls):
		if index == len(balls) - 1:
			print('|', end=' ')
		print('%02d' % ball, end=' ')
	print()


def random_select():
	"""
	随机选择一组号码
	"""
	red_balls = [x for x in range(1, 34)]
	selected_balls = []
	for _ in range(6):
		index = randrange(len(red_balls))
		selected_balls.append(red_balls[index])
		del red_balls[index]
	# 上面的for循环也可以写成下面这行代码
	# sample函数是random模块下的函数
	# selected_balls = sample(red_balls, 6)
	selected_balls.sort()
	selected_balls.append(randint(1, 16))
	return selected_balls


def main():
	n = int(input('机选几注: '))
	for _ in range(n):
		display(random_select())


if __name__ == '__main__':
	main()


================================================
FILE: Day01-15/Day07/marquee.py
================================================
"""

输入学生考试成绩计算平均分

Version: 0.1
Author: 骆昊
Date: 2018-03-06

"""

import os
import time


def main():
	str = 'Welcome to 1000 Phone Chengdu Campus      '
	while True:
		print(str)
		time.sleep(0.2)
		str = str[1:] + str[0:1]
		# for Windows use os.system('cls') instead
		os.system('clear')


if __name__ == '__main__':
	main()


================================================
FILE: Day01-15/Day07/scoretable.py
================================================
"""

学生考试成绩表

Version: 0.1
Author: 骆昊
Date: 2018-03-06

"""


def main():
	names = ['关羽', '张飞', '赵云', '马超', '黄忠']
	subjs = ['语文', '数学', '英语']
	scores = [[0] * 3] * 5
	for row, name in enumerate(names):
		print('请输入%s的成绩' % name)
		for col, subj in enumerate(subjs):
			scores[row][col] = float(input(subj + ': '))
	print(scores)
#	for row, name in enumerate(names):
#		print('请输入%s的成绩' % name)
#		scores[row] = [None] * len(subjs)
#		for col, subj in enumerate(subjs):
#			score = float(input(subj + ': '))
#			scores[row][col] = score
#	print(scores)

if __name__ == '__main__':
	main()


================================================
FILE: Day01-15/Day07/set1.py
================================================
"""

定义和使用集合

Version: 0.1
Author: 骆昊
Date: 2018-03-06

"""


def main():
    set1 = {1, 2, 3, 3, 3, 2}
    print(set1)
    print('Length =', len(set1))
    set2 = set(range(1, 10))
    print(set2)
    set1.add(4)
    set1.add(5)
    set2.update([11, 12])
    print(set1)
    print(set2)
    set2.discard(5)
    # remove的元素如果不存在会引发KeyError
    if 4 in set2:
        set2.remove(4)
    print(set2)
    # 遍历集合容器
    for elem in set2:
        print(elem ** 2, end=' ')
    print()
    # 将元组转换成集合
    set3 = set((1, 2, 3, 3, 2, 1))
    print(set3.pop())
    print(set3)


if __name__ == '__main__':
    main()


================================================
FILE: Day01-15/Day07/set2.py
================================================
"""

集合的常用操作
	- 交集
	- 并集
	- 差集
	- 子集
	- 超集

Version: 0.1
Author: 骆昊
Date: 2018-03-06

"""


def main():
	set1 = set(range(1, 7))
	print(set1)
	set2 = set(range(2, 11, 2))
	print(set2)
	set3 = set(range(1, 5))
	print(set1 & set2)
	# print(set1.intersection(set2))
	print(set1 | set2)
	# print(set1.union(set2))
	print(set1 - set2)
	# print(set1.difference(set2))
	print(set1 ^ set2)
	# print(set1.symmetric_difference(set2))
	print(set2 <= set1)
	# print(set2.issubset(set1))
	print(set3 <= set1)
	# print(set3.issubset(set1))
	print(set1 >= set2)
	# print(set1.issuperset(set2))
	print(set1 >= set3)
	# print(set1.issuperset(set3))


if __name__ == '__main__':
	main()


================================================
FILE: Day01-15/Day07/tic-tac-toe.py
================================================
"""

井字棋游戏

Version: 0.1
Author: 骆昊
Date: 2018-03-06

"""

import os



def print_board(board):
	print(board['TL'] + '|' + board['TM'] + '|' + board['TR'])
	print('-+-+-')
	print(board['ML'] + '|' + board['MM'] + '|' + board['MR'])
	print('-+-+-')
	print(board['BL'] + '|' + board['BM'] + '|' + board['BR'])


def main():
	init_board = {
		'TL': ' ', 'TM': ' ', 'TR': ' ',
		'ML': ' ', 'MM': ' ', 'MR': ' ',
		'BL': ' ', 'BM': ' ', 'BR': ' '
	}
	begin = True
	while begin:
		curr_board = init_board.copy()
		begin = False
		turn = 'x'
		counter = 0
		os.system('clear')
		print_board(curr_board)
		while counter < 9:
			move = input('轮到%s走棋, 请输入位置: ' % turn)
			if curr_board[move] == ' ':
				counter += 1
				curr_board[move] = turn
				if turn == 'x':
					turn = 'o'
				else:
					turn = 'x'
			os.system('clear')
			print_board(curr_board)
		choice = input('再玩一局?(yes|no)')
		begin = choice == 'yes'


if __name__ == '__main__':
	main()


================================================
FILE: Day01-15/Day07/tuple.py
================================================
"""

元组的定义和使用

Version: 0.1
Author: 骆昊
Date: 2018-03-06

"""


def main():
	# 定义元组
	t = ('骆昊', 38, True, '四川成都')
	print(t)
	# 获取元组中的元素
	print(t[0])
	print(t[1])
	print(t[2])
	print(t[3])
	# 遍历元组中的值
	for member in t:
		print(member)
	# 重新给元组赋值
	# t[0] = '王大锤'		# TypeError
	# 变量t重新引用了新的元组 原来的元组被垃圾回收
	t = ('王大锤', 20, True, '云南昆明')
	print(t)
	# 元组和列表的转换
	person = list(t)
	print(person)
	person[0] = '李小龙'
	person[1] = 25
	print(person)
	fruits_list = ['apple', 'banana', 'orange']
	fruits_tuple = tuple(fruits_list)
	print(fruits_tuple)
	print(fruits_tuple[1])


if __name__ == '__main__':
	main()

================================================
FILE: Day01-15/Day07/yanghui.py
================================================
"""

输出10行的杨辉三角 - 二项式的n次方展开系数
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
... ... ...


Version: 0.1
Author: 骆昊
Date: 2018-03-06

"""


def main():
    num = int(input('Number of rows: '))
    yh = [[]] * num
    for row in range(len(yh)):
        yh[row] = [None] * (row + 1)
        for col in range(len(yh[row])):
            if col == 0 or col == row:
                yh[row][col] = 1
            else:
                yh[row][col] = yh[row - 1][col] + yh[row - 1][col - 1]
            print(yh[row][col], end='\t')
        print()


if __name__ == '__main__':
    main()


================================================
FILE: Day01-15/Day07/字符串和常用数据结构.md
================================================
## 字符串和常用数据结构

### 使用字符串

第二次世界大战促使了现代电子计算机的诞生,当初的想法很简单,就是用计算机来计算导弹的弹道,因此在计算机刚刚诞生的那个年代,计算机处理的信息主要是数值,而世界上的第一台电子计算机ENIAC每秒钟能够完成约5000次浮点运算。随着时间的推移,虽然对数值运算仍然是计算机日常工作中最为重要的事情之一,但是今天的计算机处理得更多的数据都是以文本信息的方式存在的,而Python表示文本信息的方式我们在很早以前就说过了,那就是字符串类型。所谓**字符串**,就是由零个或多个字符组成的有限序列,一般记为[$${\displaystyle s=a_{1}a_{2}\dots a_{n}(0\leq n \leq \infty)}$$](https://wikimedia.org/api/rest_v1/media/math/render/svg/e29bf631b090323edd6889f810e6cff29538b161)。

我们可以通过下面的代码来了解字符串的使用。

```Python
def main():
    str1 = 'hello, world!'
    # 通过len函数计算字符串的长度
    print(len(str1))  # 13
    # 获得字符串首字母大写的拷贝
    print(str1.capitalize())  # Hello, world!
    # 获得字符串变大写后的拷贝
    print(str1.upper())  # HELLO, WORLD!
    # 从字符串中查找子串所在位置
    print(str1.find('or'))  # 8
    print(str1.find('shit'))  # -1
    # 与find类似但找不到子串时会引发异常
    # print(str1.index('or'))
    # print(str1.index('shit'))
    # 检查字符串是否以指定的字符串开头
    print(str1.startswith('He'))  # False
    print(str1.startswith('hel'))  # True
    # 检查字符串是否以指定的字符串结尾
    print(str1.endswith('!'))  # True
    # 将字符串以指定的宽度居中并在两侧填充指定的字符
    print(str1.center(50, '*'))
    # 将字符串以指定的宽度靠右放置左侧填充指定的字符
    print(str1.rjust(50, ' '))
    str2 = 'abc123456'
    # 从字符串中取出指定位置的字符(下标运算)
    print(str2[2])  # c
    # 字符串切片(从指定的开始索引到指定的结束索引)
    print(str2[2:5])  # c12
    print(str2[2:])  # c123456
    print(str2[2::2])  # c246
    print(str2[::2])  # ac246
    print(str2[::-1])  # 654321cba
    print(str2[-3:-1])  # 45
    # 检查字符串是否由数字构成
    print(str2.isdigit())  # False
    # 检查字符串是否以字母构成
    print(str2.isalpha())  # False
    # 检查字符串是否以数字和字母构成
    print(str2.isalnum())  # True
    str3 = '  jackfrued@126.com '
    print(str3)
    # 获得字符串修剪左右两侧空格的拷贝
    print(str3.strip())


if __name__ == '__main__':
    main()

```

除了字符串,Python还内置了多种类型的数据结构,如果要在程序中保存和操作数据,绝大多数时候可以利用现有的数据结构来实现,最常用的包括列表、元组、集合和字典。

### 使用列表

下面的代码演示了如何定义列表、使用下标访问列表元素以及添加和删除元素的操作。

```Python
def main():
	list1 = [1, 3, 5, 7, 100]
    print(list1)
    list2 = ['hello'] * 5
    print(list2)
	# 计算列表长度(元素个数)
	print(len(list1))
	# 下标(索引)运算
	print(list1[0])
	print(list1[4])
	# print(list1[5])  # IndexError: list index out of range
	print(list1[-1])
	print(list1[-3])
	list1[2] = 300
	print(list1)
	# 添加元素
	list1.append(200)
	list1.insert(1, 400)
	list1 += [1000, 2000]
	print(list1)
	print(len(list1))
	# 删除元素
	list1.remove(3)
	if 1234 in list1:
		list1.remove(1234)
	del list1[0]
	print(list1)
	# 清空列表元素
	list1.clear()
	print(list1)
	

if __name__ == '__main__':
	main()

```

和字符串一样,列表也可以做切片操作,通过切片操作我们可以实现对列表的复制或者将列表中的一部分取出来创建出新的列表,代码如下所示。

```Python
def main():
	fruits = ['grape', 'apple', 'strawberry', 'waxberry']
	fruits += ['pitaya', 'pear', 'mango']
	# 循环遍历列表元素
	for fruit in fruits:
		print(fruit.title(), end=' ')
	print()
	# 列表切片
	fruits2 = fruits[1:4]
	print(fruits2)
	# fruit3 = fruits  # 没有复制列表只创建了新的引用
    # 可以通过完整切片操作来复制列表
	fruits3 = fruits[:]
	print(fruits3)
	fruits4 = fruits[-3:-1]
	print(fruits4)
    # 可以通过反向切片操作来获得倒转后的列表的拷贝
	fruits5 = fruits[::-1]
	print(fruits5)


if __name__ == '__main__':
	main()

```

下面的代码实现了对列表的排序操作。

```Python
def main():
    list1 = ['orange', 'apple', 'zoo', 'internationalization', 'blueberry']
    list2 = sorted(list1)
    # sorted函数返回列表排序后的拷贝不会修改传入的列表
    # 函数的设计就应该像sorted函数一样尽可能不产生副作用
    list3 = sorted(list1, reverse=True)
    # 通过key关键字参数指定根据字符串长度进行排序而不是默认的字母表顺序
    list4 = sorted(list1, key=len)
    print(list1)
    print(list2)
    print(list3)
    print(list4)
    # 给列表对象发出排序消息直接在列表对象上进行排序
    list1.sort(reverse=True)
    print(list1)


if __name__ == '__main__':
    main()

```

我们还可以使用列表的生成式语法来创建列表,代码如下所示。

```Python
import sys


def main():
    f = [x for x in range(1, 10)]
    print(f)
    f = [x + y for x in 'ABCDE' for y in '1234567']
    print(f)
    # 用列表的生成表达式语法创建列表容器
    # 用这种语法创建列表之后元素已经准备就绪所以需要耗费较多的内存空间
    f = [x ** 2 for x in range(1, 1000)]
    print(sys.getsizeof(f))  # 查看对象占用内存的字节数
    print(f)
    # 请注意下面的代码创建的不是一个列表而是一个生成器对象
    # 通过生成器可以获取到数据但它不占用额外的空间存储数据
    # 每次需要数据的时候就通过内部的运算得到数据(需要花费额外的时间)
    f = (x ** 2 for x in range(1, 1000))
    print(sys.getsizeof(f))  # 相比生成式生成器不占用存储数据的空间
    print(f)
    for val in f:
        print(val)


if __name__ == '__main__':
    main()

```

除了上面提到的生成器语法,Python中还有另外一种定义生成器的方式,就是通过`yield`关键字将一个普通函数改造成生成器函数。下面的代码演示了如何实现一个生成[斐波拉切数列](https://zh.wikipedia.org/wiki/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97)的生成器。所谓斐波拉切数列可以通过下面[递归](https://zh.wikipedia.org/wiki/%E9%80%92%E5%BD%92)的方法来进行定义:

$${\displaystyle F_{0}=0}$$

$${\displaystyle F_{1}=1}$$

$${\displaystyle F_{n}=F_{n-1}+F_{n-2}}({n}\geq{2})$$

![](./res/fibonacci-blocks.png)

```Python
def fib(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
        yield a


def main():
	for val in fib(20):
	    print(val)


if __name__ == '__main__':
	main()

```

### 使用元组

Python 的元组与列表类似,不同之处在于元组的元素不能修改,在前面的代码中我们已经不止一次使用过元组了。顾名思义,我们把多个元素组合到一起就形成了一个元组,所以它和列表一样可以保存多条数据。下面的代码演示了如何定义和使用元组。

```Python
def main():
	# 定义元组
	t = ('骆昊', 38, True, '四川成都')
	print(t)
	# 获取元组中的元素
	print(t[0])
	print(t[3])
	# 遍历元组中的值
	for member in t:
		print(member)
	# 重新给元组赋值
	# t[0] = '王大锤'  # TypeError
	# 变量t重新引用了新的元组原来的元组将被垃圾回收
	t = ('王大锤', 20, True, '云南昆明')
	print(t)
	# 将元组转换成列表
	person = list(t)
	print(person)
    # 列表是可以修改它的元素的
	person[0] = '李小龙'
	person[1] = 25
	print(person)
    # 将列表转换成元组
	fruits_list = ['apple', 'banana', 'orange']
	fruits_tuple = tuple(fruits_list)
	print(fruits_tuple)


if __name__ == '__main__':
	main()
```

这里有一个非常值得探讨的问题,我们已经有了列表这种数据结构,为什么还需要元组这样的类型呢?

1. 元组中的元素是无法修改的,事实上我们在项目中尤其是[多线程](https://zh.wikipedia.org/zh-hans/%E5%A4%9A%E7%BA%BF%E7%A8%8B)环境(后面会讲到)中可能更喜欢使用的是那些不变对象(一方面因为对象状态不能修改,所以可以避免由此引起的不必要的程序错误,简单的说就是一个不变的对象要比可变的对象更加容易维护;另一方面因为没有任何一个线程能够修改不变对象的内部状态,一个不变对象自动就是线程安全的,这样就可以省掉处理同步化的开销。一个不变对象可以方便的被共享访问)。所以结论就是:如果不需要对元素进行添加、删除、修改的时候,可以考虑使用元组,当然如果一个方法要返回多个值,使用元组也是不错的选择。
2. 元组在创建时间和占用的空间上面都优于列表。我们可以使用sys模块的getsizeof函数来检查存储同样的元素的元组和列表各自占用了多少内存空间,这个很容易做到。我们也可以在ipython中使用魔法指令%timeit来分析创建同样内容的元组和列表所花费的时间,下图是我的macOS系统上测试的结果。

![](./res/ipython-timeit.png)

### 使用集合

Python中的集合跟数学上的集合是一致的,不允许有重复元素,而且可以进行交集、并集、差集等运算。

![](./res/python-set.png)

```Python
def main():
    set1 = {1, 2, 3, 3, 3, 2}
    print(set1)
    print('Length =', len(set1))
    set2 = set(range(1, 10))
    print(set2)
    set1.add(4)
    set1.add(5)
    set2.update([11, 12])
    print(set1)
    print(set2)
    set2.discard(5)
    # remove的元素如果不存在会引发KeyError
    if 4 in set2:
        set2.remove(4)
    print(set2)
    # 遍历集合容器
    for elem in set2:
        print(elem ** 2, end=' ')
    print()
    # 将元组转换成集合
    set3 = set((1, 2, 3, 3, 2, 1))
    print(set3.pop())
    print(set3)
    # 集合的交集、并集、差集、对称差运算
    print(set1 & set2)
    # print(set1.intersection(set2))
    print(set1 | set2)
    # print(set1.union(set2))
    print(set1 - set2)
    # print(set1.difference(set2))
    print(set1 ^ set2)
    # print(set1.symmetric_difference(set2))
    # 判断子集和超集
    print(set2 <= set1)
    # print(set2.issubset(set1))
    print(set3 <= set1)
    # print(set3.issubset(set1))
    print(set1 >= set2)
    # print(set1.issuperset(set2))
    print(set1 >= set3)
    # print(set1.issuperset(set3))


if __name__ == '__main__':
    main()

```

> **说明**:Python中允许通过一些特殊的方法来为某种类型或数据结构自定义运算符(后面的章节中会讲到),上面的代码中我们对集合进行运算的时候可以调用集合对象的方法,也可以直接使用对应的运算符,例如`&`运算符跟intersection方法的作用就是一样的,但是使用运算符让代码更加直观。

### 使用字典

字典是另一种可变容器模型,类似于我们生活中使用的字典,它可以存储任意类型对象,与列表、集合不同的是,字典的每个元素都是由一个键和一个值组成的“键值对”,键和值通过冒号分开。下面的代码演示了如何定义和使用字典。

```Python
def main():
	scores = {'骆昊': 95, '白元芳': 78, '狄仁杰': 82}
    # 通过键可以获取字典中对应的值
	print(scores['骆昊'])
	print(scores['狄仁杰'])
    # 对字典进行遍历(遍历的其实是键再通过键取对应的值)
	for elem in scores:
		print('%s\t--->\t%d' % (elem, scores[elem]))
    # 更新字典中的元素
	scores['白元芳'] = 65
	scores['诸葛王朗'] = 71
	scores.update(冷面=67, 方启鹤=85)
	print(scores)
	if '武则天' in scores:
		print(scores['武则天'])
	print(scores.get('武则天'))
    # get方法也是通过键获取对应的值但是可以设置默认值
	print(scores.get('武则天', 60))
    # 删除字典中的元素
	print(scores.popitem())
	print(scores.popitem())
	print(scores.pop('骆昊', 100))
    # 清空字典
	scores.clear()
	print(scores)


if __name__ == '__main__':
	main()

```

### 练习

#### 练习1:在屏幕上显示跑马灯文字

```Python
import os
import time


def main():
    content = '北京欢迎你为你开天辟地…………'
    while True:
        # 清理屏幕上的输出
        os.system('cls')  # os.system('clear')
        print(content)
        # 休眠200毫秒
        time.sleep(0.2)
        content = content[1:] + content[0]


if __name__ == '__main__':
    main()

```

#### 练习2:设计一个函数产生指定长度的验证码,验证码由大小写字母和数字构成。

```Python
import random


def generate_code(code_len=4):
    """
    生成指定长度的验证码

    :param code_len: 验证码的长度(默认4个字符)

    :return: 由大小写英文字母和数字构成的随机验证码
    """
    all_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    last_pos = len(all_chars) - 1
    code = ''
    for _ in range(code_len):
        index = random.randint(0, last_pos)
        code += all_chars[index]
    return code
```

#### 练习3:设计一个函数返回给定文件名的后缀名。

```Python
def get_suffix(filename, has_dot=False):
    """
    获取文件名的后缀名

    :param filename: 文件名
    :param has_dot: 返回的后缀名是否需要带点

    :return: 文件的后缀名
    """
    pos = filename.rfind('.')
    if 0 < pos < len(filename) - 1:
        index = pos if has_dot else pos + 1
        return filename[index:]
    else:
        return ''
    
```

#### 练习4:设计一个函数返回传入的列表中最大和第二大的元素的值。

```Python
def max2(x):
    m1, m2 = (x[0], x[1]) if x[0] > x[1] else (x[1], x[0])
    for index in range(2, len(x)):
        if x[index] > m1:
            m2 = m1
            m1 = x[index]
        elif x[index] > m2:
            m2 = x[index]
    return m1, m2
```

#### 练习5:计算指定的年月日是这一年的第几天

```Python
def is_leap_year(year):
    """
    判断指定的年份是不是闰年

    :param year: 年份

    :return: 闰年返回True平年返回False
    """
    return year % 4 == 0 and year % 100 != 0 or year % 400 == 0


def which_day(year, month, date):
    """
    计算传入的日期是这一年的第几天

    :param year: 年
    :param month: 月
    :param date: 日

    :return: 第几天
    """
    days_of_month = [
        [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
        [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    ][is_leap_year(year)]
    total = 0
    for index in range(month - 1):
        total += days_of_month[index]
    return total + date


def main():
    print(which_day(1980, 11, 28))
    print(which_day(1981, 12, 31))
    print(which_day(2018, 1, 1))
    print(which_day(2016, 3, 1))


if __name__ == '__main__':
    main()

```

#### 练习6:打印[杨辉三角](https://zh.wikipedia.org/wiki/%E6%9D%A8%E8%BE%89%E4%B8%89%E8%A7%92%E5%BD%A2)。

```Python
def main():
    num = int(input('Number of rows: '))
    yh = [[]] * num
    for row in range(len(yh)):
        yh[row] = [None] * (row + 1)
        for col in range(len(yh[row])):
            if col == 0 or col == row:
                yh[row][col] = 1
            else:
                yh[row][col] = yh[row - 1][col] + yh[row - 1][col - 1]
            print(yh[row][col], end='\t')
        print()


if __name__ == '__main__':
    main()

```

### 综合案例

#### 案例1:双色球选号

```Python
from random import randrange, randint, sample


def display(balls):
    """
    输出列表中的双色球号码
    """
    for index, ball in enumerate(balls):
        if index == len(balls) - 1:
            print('|', end=' ')
        print('%02d' % ball, end=' ')
    print()


def random_select():
    """
    随机选择一组号码
    """
    red_balls = [x for x in range(1, 34)]
    selected_balls = []
    for _ in range(6):
        index = randrange(len(red_balls))
        selected_balls.append(red_balls[index])
        del red_balls[index]
    # 上面的for循环也可以写成下面这行代码
    # sample函数是random模块下的函数
    # selected_balls = sample(red_balls, 6)
    selected_balls.sort()
    selected_balls.append(randint(1, 16))
    return selected_balls


def main():
    n = int(input('机选几注: '))
    for _ in range(n):
        display(random_select())


if __name__ == '__main__':
    main()

```

> **说明**:可以使用random模块的sample函数来实现从列表中选择不重复的n个元素。

#### 综合案例2:[约瑟夫环问题](https://zh.wikipedia.org/wiki/%E7%BA%A6%E7%91%9F%E5%A4%AB%E6%96%AF%E9%97%AE%E9%A2%98)

```Python
"""

《幸运的基督徒》
有15个基督徒和15个非基督徒在海上遇险,为了能让一部分人活下来不得不将其中15个人扔到海里面去,有个人想了个办法就是大家围成一个圈,由某个人开始从1报数,报到9的人就扔到海里面,他后面的人接着从1开始报数,报到9的人继续扔到海里面,直到扔掉15个人。由于上帝的保佑,15个基督徒都幸免于难,问这些人最开始是怎么站的,哪些位置是基督徒哪些位置是非基督徒。

"""


def main():
    persons = [True] * 30
    counter, index, number = 0, 0, 0
    while counter < 15:
        if persons[index]:
            number += 1
            if number == 9:
                persons[index] = False
                counter += 1
                number = 0
        index += 1
        index %= 30
    for person in persons:
        print('基' if person else '非', end='')


if __name__ == '__main__':
    main()

```

#### 综合案例3:[井字棋](https://zh.wikipedia.org/wiki/%E4%BA%95%E5%AD%97%E6%A3%8B)游戏

```Python
import os


def print_board(board):
	print(board['TL'] + '|' + board['TM'] + '|' + board['TR'])
	print('-+-+-')
	print(board['ML'] + '|' + board['MM'] + '|' + board['MR'])
	print('-+-+-')
	print(board['BL'] + '|' + board['BM'] + '|' + board['BR'])


def main():
	init_board = {
		'TL': ' ', 'TM': ' ', 'TR': ' ',
		'ML': ' ', 'MM': ' ', 'MR': ' ',
		'BL': ' ', 'BM': ' ', 'BR': ' '
	}
	begin = True
	while begin:
		curr_board = init_board.copy()
		begin = False
		turn = 'x'
		counter = 0
		os.system('clear')
		print_board(curr_board)
		while counter < 9:
			move = input('轮到%s走棋, 请输入位置: ' % turn)
			if curr_board[move] == ' ':
				counter += 1
				curr_board[move] = turn
				if turn == 'x':
					turn = 'o'
				else:
					turn = 'x'
			os.system('clear')
			print_board(curr_board)
		choice = input('再玩一局?(yes|no)')
		begin = choice == 'yes'


if __name__ == '__main__':
	main()

```

>**说明**:最后这个案例来自[《Python编程快速上手:让繁琐工作自动化》](https://item.jd.com/11943853.html)一书(这本书对有编程基础想迅速使用Python将日常工作自动化的人来说还是不错的教材),对代码做了一点点的调整。

================================================
FILE: Day01-15/Day08/access.py
================================================
class Test:

	def __init__(self, foo):
		self.__foo = foo

	def __bar(self):
		print(self.__foo)
		print('__bar')


def main():
	test = Test('hello')
	test._Test__bar()
	print(test._Test__foo)


if __name__ == "__main__":
	main()


================================================
FILE: Day01-15/Day08/circle.py
================================================
"""

练习
修一个游泳池 半径(以米为单位)在程序运行时输入 游泳池外修一条3米宽的过道
过道的外侧修一圈围墙 已知过道的造价为25元每平米 围墙的造价为32.5元每米
输出围墙和过道的总造价分别是多少钱(精确到小数点后2位)

Version: 0.1
Author: 骆昊
Date: 2018-03-08

"""

import math


class Circle(object):

	def __init__(self, radius):
		self._radius = radius

	@property
	def radius(self):
		return self._radius

	@radius.setter
	def radius(self, radius):
		self._radius = radius if radius > 0 else 0

	@property
	def perimeter(self):
		return 2 * math.pi * self._radius

	@property
	def area(self):
		return math.pi * self._radius * self._radius


if __name__ == '__main__':	
	radius = float(input('请输入游泳池的半径: '))
	small = Circle(radius)
	big = Circle(radius + 3)
	print('围墙的造价为: ¥%.1f元' % (big.perimeter * 115))
	print('过道的造价为: ¥%.1f元' % ((big.area - small.area) * 65))


================================================
FILE: Day01-15/Day08/clock.py
================================================
"""

定义和使用时钟类

Version: 0.1
Author: 骆昊
Date: 2018-03-08

"""

import time
import os


class Clock(object):

	# Python中的函数是没有重载的概念的
	# 因为Python中函数的参数没有类型而且支持缺省参数和可变参数
	# 用关键字参数让构造器可以传入任意多个参数来实现其他语言中的构造器重载
	def __init__(self, **kw):
		if 'hour' in kw and 'minute' in kw and 'second' in kw:
			self._hour = kw['hour']
			self._minute = kw['minute']
			self._second = kw['second']
		else:
			tm = time.localtime(time.time())
			self._hour = tm.tm_hour
			self._minute = tm.tm_min
			self._second = tm.tm_sec

	def run(self):
		self._second += 1
		if self._second == 60:
			self._second = 0
			self._minute += 1
			if self._minute == 60:
				self._minute = 0
				self._hour += 1
				if self._hour == 24:
					self._hour = 0

	def show(self):
		return '%02d:%02d:%02d' % (self._hour, self._minute, self._second)


if __name__ == '__main__':
	# clock = Clock(hour=10, minute=5, second=58)
	clock = Clock()
	while True:
		os.system('clear')
		print(clock.show())
		time.sleep(1)
		clock.run()


================================================
FILE: Day01-15/Day08/guess.py
================================================
"""

面向对象版本的猜数字游戏

Version: 0.1
Author: 骆昊
Date: 2018-03-08

"""

from random import randint


class GuessMachine(object):

	def __init__(self):
		self._answer = None
		self._counter = None
		self._hint = None

	def reset(self):
		self._answer = randint(1, 100)
		self._counter = 0
		self._hint = None

	def guess(self, your_answer):
		self._counter += 1
		if your_answer > self._answer:
			self._hint = '小一点'
		elif your_answer < self._answer:
			self._hint = '大一点'
		else:
			self._hint = '恭喜你猜对了'
			return True
		return False

	@property
	def counter(self):
		return self._counter

	@property
	def hint(self):
		return self._hint


if __name__ == '__main__':
	gm = GuessMachine()
	play_again = True
	while play_again:
		game_over = False
		gm.reset()
		while not game_over:
			your_answer = int(input('请输入: '))
			game_over = gm.guess(your_answer)
			print(gm.hint)
		if gm.counter > 7:
			print('智商余额不足!')
		play_again = input('再玩一次?(yes|no)') == 'yes'


================================================
FILE: Day01-15/Day08/hack.py
================================================
"""

另一种创建类的方式

Version: 0.1
Author: 骆昊
Date: 2018-03-08

"""


def bar(self, name):
	self._name = name


def foo(self, course_name):
	print('%s正在学习%s.' % (self._name, course_name))


def main():
	Student = type('Student', (object,), dict(__init__=bar, study=foo))
	stu1 = Student('骆昊')
	stu1.study('Python程序设计')


if __name__ == '__main__':
	main()	


================================================
FILE: Day01-15/Day08/rect.py
================================================
"""

定义和使用矩形类

Version: 0.1
Author: 骆昊
Date: 2018-03-08

"""


class Rect(object):
	"""矩形类"""

	def __init__(self, width=0, height=0):
		"""构造器"""
		self.__width = width
		self.__height = height

	def perimeter(self):
		"""计算周长"""
		return (self.__width + self.__height) * 2

	def area(self):
		"""计算面积"""
		return self.__width * self.__height

	def __str__(self):
		"""矩形对象的字符串表达式"""
		return '矩形[%f,%f]' % (self.__width, self.__height)

	def __del__(self):
		"""析构器"""
		print('销毁矩形对象')


if __name__ == '__main__':
	rect1 = Rect()
	print(rect1)
	print(rect1.perimeter())
	print(rect1.area())
	rect2 = Rect(3.5, 4.5)
	print(rect2)
	print(rect2.perimeter())
	print(rect2.area())


================================================
FILE: Day01-15/Day08/student.py
================================================
"""

定义和使用学生类

Version: 0.1
Author: 骆昊
Date: 2018-03-08

"""


def _foo():
	print('test')


class Student(object):

	# __init__是一个特殊方法用于在创建对象时进行初始化操作
	# 通过这个方法我们可以为学生对象绑定name和age两个属性
	def __init__(self, name, age):
		self.name = name
		self.age = age

	def study(self, course_name):
		print('%s正在学习%s.' % (self.name, course_name))

	# PEP 8要求标识符的名字用全小写多个单词用下划线连接
	# 但是很多程序员和公司更倾向于使用驼峰命名法(驼峰标识)
	def watch_av(self):
		if self.age < 18:
			print('%s只能观看《熊出没》.' % self.name)
		else:
			print('%s正在观看岛国爱情动作片.' % self.name)


def main():
	stu1 = Student('骆昊', 38)
	stu1.study('Python程序设计')
	stu1.watch_av()
	stu2 = Student('王大锤', 15)
	stu2.study('思想品德')
	stu2.watch_av()


if __name__ == '__main__':
	main()

================================================
FILE: Day01-15/Day08/test.py
================================================


================================================
FILE: Day01-15/Day08/面向对象编程基础.md
================================================
## 面向对象编程基础

活在当下的程序员应该都听过“面向对象编程”一词,也经常有人问能不能用一句话解释下什么是“面向对象编程”,我们先来看看比较正式的说法。

> 把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封装(encapsulation)隐藏内部细节,通过继承(inheritance)实现类的特化(specialization)和泛化(generalization),通过多态(polymorphism)实现基于对象类型的动态分派。

这样一说是不是更不明白了。所以我们还是看看更通俗易懂的说法,下面这段内容来自于[知乎](https://www.zhihu.com/)。

![](./res/oop-zhihu.png)

> **说明**:以上的内容来自于网络,不代表作者本人的观点和看法,与作者本人立场无关,相关责任不由作者承担。(终于有机会享受一下把这段话反过来说的乐趣了,乐得牙都快碎了。)

之前我们说过“程序是指令的集合”,我们在程序中书写的语句在执行时会变成一条或多条指令然后由CPU去执行。当然为了简化程序的设计,我们引入了函数的概念,把相对独立且经常重复使用的代码放置到函数中,在需要使用这些功能的时候只要调用函数即可;如果一个函数的功能过于复杂和臃肿,我们又可以进一步将函数继续切分为子函数来降低系统的复杂性。但是说了这么多,不知道大家是否发现,所谓编程就是程序员按照计算机的工作方式控制计算机完成各种任务。但是,计算机的工作方式与正常人类的思维模式是不同的,如果编程就必须得抛弃人类正常的思维方式去迎合计算机,编程的乐趣就少了很多,“每个人都应该学习编程”这样的豪言壮语就只能说说而已。当然,这些还不是最重要的,最重要的是当我们需要开发一个复杂的系统时,代码的复杂性会让开发和维护工作都变得举步维艰,所以在上世纪60年代末期,“[软件危机](https://zh.wikipedia.org/wiki/%E8%BD%AF%E4%BB%B6%E5%8D%B1%E6%9C%BA)”、“[软件工程](https://zh.wikipedia.org/wiki/%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B)”等一系列的概念开始在行业中出现。

当然,程序员圈子内的人都知道,现实中并没有解决上面所说的这些问题的“[银弹](https://zh.wikipedia.org/wiki/%E6%B2%A1%E6%9C%89%E9%93%B6%E5%BC%B9)”,真正让软件开发者看到希望的是上世纪70年代诞生的[Smalltalk](https://zh.wikipedia.org/wiki/Smalltalk)编程语言中引入的面向对象的编程思想(面向对象编程的雏形可以追溯到更早期的[Simula](https://zh.wikipedia.org/wiki/Simula)语言)。按照这种编程理念,程序中的数据和操作数据的函数是一个逻辑上的整体,我们称之为“对象”,而我们解决问题的方式就是创建出需要的对象并向对象发出各种各样的消息,多个对象的协同工作最终可以让我们构造出复杂的系统来解决现实中的问题。

> **说明**:当然面向对象也不是解决软件开发中所有问题的最后的“银弹”,所以今天的高级程序设计语言几乎都提供了对多种编程范式的支持,Python也不例外。

### 类和对象

简单的说,类是对象的蓝图和模板,而对象是类的实例。这个解释虽然有点像用概念在解释概念,但是从这句话我们至少可以看出,类是抽象的概念,而对象是具体的东西。在面向对象编程的世界中,一切皆为对象,对象都有属性和行为,每个对象都是独一无二的,而且对象一定属于某个类(型)。当我们把一大堆拥有共同特征的对象的静态特征(属性)和动态特征(行为)都抽取出来后,就可以定义出一个叫做“类”的东西。

![](./res/object-feature.png)

### 定义类

在Python中可以使用`class`关键字定义类,然后在类中通过之前学习过的函数来定义方法,这样就可以将对象的动态特征描述出来,代码如下所示。

```Python
class Student(object):

	# __init__是一个特殊方法用于在创建对象时进行初始化操作
	# 通过这个方法我们可以为学生对象绑定name和age两个属性
	def __init__(self, name, age):
		self.name = name
		self.age = age

	def study(self, course_name):
		print('%s正在学习%s.' % (self.name, course_name))

	# PEP 8要求标识符的名字用全小写多个单词用下划线连接
	# 但是很多程序员和公司更倾向于使用驼峰命名法(驼峰标识)
	def watch_av(self):
		if self.age < 18:
			print('%s只能观看《熊出没》.' % self.name)
		else:
			print('%s正在观看岛国爱情动作片.' % self.name)
```

> **说明**:写在类中的函数,我们通常称之为(对象的)方法,这些方法就是对象可以接收的消息。

### 创建和使用对象

当我们定义好一个类之后,可以通过下面的方式来创建对象并给对象发消息。

```Python
def main():
    # 创建学生对象并指定姓名和年龄
	stu1 = Student('骆昊', 38)
    # 给对象发study消息
	stu1.study('Python程序设计')
    # 给对象发watch_av消息
	stu1.watch_av()
	stu2 = Student('王大锤', 15)
	stu2.study('思想品德')
	stu2.watch_av()


if __name__ == '__main__':
	main()

```

### 访问可见性问题

对于上面的代码,有C++、Java、C#等编程经验的程序员可能会问,我们给`Student`对象绑定的`name`和`age`属性到底具有怎样的访问权限(也称为可见性)。因为在很多面向对象编程语言中,我们通常会将对象的属性设置为私有的(private)或受保护的(protected),简单的说就是不允许外界访问,而对象的方法通常都是公开的(public),因为公开的方法就是对象能够接受的消息。在Python中,属性和方法的访问权限只有两种,也就是公开的和私有的,如果希望属性是私有的,在给属性命名时可以用两个下划线作为开头,下面的代码可以验证这一点。

```Python
class Test:

	def __init__(self, foo):
		self.__foo = foo

	def __bar(self):
		print(self.__foo)
		print('__bar')


def main():
	test = Test('hello')
	# AttributeError: 'Test' object has no attribute '__bar'
	test.__bar()
	# AttributeError: 'Test' object has no attribute '__foo'
	print(test.__foo)


if __name__ == "__main__":
	main()

```

但是,Python并没有从语法上严格保证私有属性或方法的私密性,它只是给私有的属性和方法换了一个名字来“妨碍”对它们的访问,事实上如果你知道更换名字的规则仍然可以访问到它们,下面的代码就可以验证这一点。之所以这样设定,可以用这样一句名言加以解释,就是“We are all consenting adults here”。因为绝大多数程序员都认为开放比封闭要好,而且程序员要自己为自己的行为负责。

```Python
class Test:

	def __init__(self, foo):
		self.__foo = foo

	def __bar(self):
		print(self.__foo)
		print('__bar')


def main():
	test = Test('hello')
	test._Test__bar()
	print(test._Test__foo)


if __name__ == "__main__":
	main()

```

在实际开发中,我们并不建议将属性设置为私有的,因为这会导致子类无法访问(后面会讲到)。所以大多数Python程序员会遵循一种命名惯例就是让属性名以单下划线开头来表示属性是受保护的,本类之外的代码在访问这样的属性时应该要保持慎重。这种做法并不是语法上的规则,单下划线开头的属性和方法外界仍然是可以访问的,所以更多的时候它是一种暗示或隐喻,关于这一点可以看看我的[《Python - 那些年我们踩过的那些坑》](http://blog.csdn.net/jackfrued/article/details/79521404)文章中的讲解。

### 面向对象的支柱

面向对象有三大支柱:封装、继承和多态。后面两个概念在下一个章节中进行详细的说明,这里我们先说一下什么是封装。我自己对封装的理解是“隐藏一切可以隐藏的实现细节,只向外界暴露(提供)简单的编程接口”。我们在类中定义的方法其实就是把数据和对数据的操作封装起来了,在我们创建了对象之后,只需要给对象发送一个消息(调用方法)就可以执行方法中的代码,也就是说我们只需要知道方法的名字和传入的参数(方法的外部视图),而不需要知道方法内部的实现细节(方法的内部视图)。

### 练习

#### 练习1:定义一个类描述数字时钟

```Python
class Clock(object):
    """
    数字时钟
    """

    def __init__(self, hour=0, minute=0, second=0):
        """
        构造器

        :param hour: 时
        :param minute: 分
        :param second: 秒
        """
        self._hour = hour
        self._minute = minute
        self._second = second

    def run(self):
        """走字"""
        self._second += 1
        if self._second == 60:
            self._second = 0
            self._minute += 1
            if self._minute == 60:
                self._minute = 0
                self._hour += 1
                if self._hour == 24:
                    self._hour = 0

    def __str__(self):
        """显示时间"""
        return '%02d:%02d:%02d' % \
               (self._hour, self._minute, self._second)


def main():
    clock = Clock(23, 59, 58)
    while True:
        print(clock)
        sleep(1)
        clock.run()


if __name__ == '__main__':
    main()

```

#### 练习2:定义一个类描述平面上的点并提供移动点和计算到另一个点距离的方法。

```Python
from math import sqrt


class Point(object):

    def __init__(self, x=0, y=0):
        """
        构造器
        
        :param x: 横坐标
        :param y: 纵坐标
        """
        self.x = x
        self.y = y

    def move_to(self, x, y):
        """
        移动到指定位置
        
        :param x: 新的横坐标
        "param y: 新的纵坐标
        """
        self.x = x
        self.y = y

    def move_by(self, dx, dy):
        """
        移动指定的增量
        
        :param dx: 横坐标的增量
        "param dy: 纵坐标的增量
        """
        self.x += dx
        self.y += dy

    def distance_to(self, other):
        """
        计算与另一个点的距离
        
        :param other: 另一个点
        """
        dx = self.x - other.x
        dy = self.y - other.y
        return sqrt(dx ** 2 + dy ** 2)

    def __str__(self):
        return '(%s, %s)' % (str(self.x), str(self.y))


def main():
    p1 = Point(3, 5)
    p2 = Point()
    print(p1)
    print(p2)
    p2.move_by(-1, 2)
    print(p2)
    print(p1.distance_to(p2))


if __name__ == '__main__':
    main()

```

> **说明**:本章中的插图来自于Grady Booch等著作的[《面向对象分析与设计》](https://item.jd.com/20476561918.html)一书,该书是讲解面向对象编程的经典著作,有兴趣的读者可以购买和阅读这本书来了解更多的面向对象的相关知识。

================================================
FILE: Day01-15/Day09/association.py
================================================
"""

对象之间的关联关系

Version: 0.1
Author: 骆昊
Date: 2018-03-12

"""

from math import sqrt


class Point(object):

	def __init__(self, x=0, y=0):
		self._x = x
		self._y = y

	def move_to(self, x, y):
		self._x = x
		self._y = y

	def move_by(self, dx, dy):
		self._x += dx
		self._y += dy

	def distance_to(self, other):
		dx = self._x - other._x
		dy = self._y - other._y
		return sqrt(dx ** 2 + dy ** 2)

	def __str__(self):
		return '(%s, %s)' % (str(self._x), str(self._y))


class Line(object):

	def __init__(self, start=Point(0, 0), end=Point(0, 0)):
		self._start = start
		self._end = end

	@property
	def start(self):
		return self._start

	@start.setter
	def start(self, start):
		self._start = start

	@property
	def end(self):
		return self.end

	@end.setter
	def end(self, end):
		self._end = end

	@property
	def length(self):
		return self._start.distance_to(self._end)


if __name__ == '__main__':
	p1 = Point(3, 5)
	print(p1)
	p2 = Point(-2, -1.5)
	print(p2)
	line = Line(p1, p2)
	print(line.length)
	line.start.move_to(2, 1)
	line.end = Point(1, 2)
	print(line.length)


================================================
FILE: Day01-15/Day09/car1.py
================================================
"""

属性的使用
	- 访问器/修改器/删除器
	- 使用__slots__对属性加以限制

Version: 0.1
Author: 骆昊
Date: 2018-03-12

"""


class Car(object):

	__slots__ = ('_brand', '_max_speed')

	def __init__(self, brand, max_speed):
		self._brand = brand
		self._max_speed = max_speed

	@property
	def brand(self):
		return self._brand

	@brand.setter
	def brand(self, brand):
		self._brand = brand

	@brand.deleter
	def brand(self):
		del self._brand

	@property
	def max_speed(self):
		return self._max_speed

	@max_speed.setter
	def max_speed(self, max_speed):
		if max_speed < 0:
			raise ValueError('Invalid max speed for car')
		self._max_speed = max_speed

	def __str__(self):
		return 'Car: [品牌=%s, 最高时速=%d]' % (self._brand, self._max_speed)


car = Car('QQ', 120)
print(car)
# ValueError
# car.max_speed = -100
car.max_speed = 320
car.brand = "Benz"
# 使用__slots__属性限制后下面的代码将产生异常
# car.current_speed = 80
print(car)
# 如果提供了删除器可以执行下面的代码
# del car.brand
# 属性的实现
print(Car.brand)
print(Car.brand.fget)
print(Car.brand.fset)
print(Car.brand.fdel)
# 通过上面的代码帮助学生理解之前提到的包装器的概念
# Python中有很多类似的语法糖后面还会出现这样的东西


================================================
FILE: Day01-15/Day09/car2.py
================================================
"""

属性的使用
	- 使用已有方法定义访问器/修改器/删除器

Version: 0.1
Author: 骆昊
Date: 2018-03-12

"""


class Car(object):

	def __init__(self, brand, max_speed):
		self.set_brand(brand)
		self.set_max_speed(max_speed)

	def get_brand(self):
		return self._brand

	def set_brand(self, brand):
		self._brand = brand

	def get_max_speed(self):
		return self._max_speed

	def set_max_speed(self, max_speed):
		if max_speed < 0:
			raise ValueError('Invalid max speed for car')
		self._max_speed = max_speed

	def __str__(self):
		return 'Car: [品牌=%s, 最高时速=%d]' % (self._brand, self._max_speed)

	# 用已有的修改器和访问器定义属性
	brand = property(get_brand, set_brand)
	max_speed = property(get_max_speed, set_max_speed)


car = Car('QQ', 120)
print(car)
# ValueError
# car.max_speed = -100
car.max_speed = 320
car.brand = "Benz"
print(car)
print(Car.brand)
print(Car.brand.fget)
print(Car.brand.fset)


================================================
FILE: Day01-15/Day09/clock.py
================================================
from time import time, localtime, sleep


class Clock(object):
    """数字时钟"""

    def __init__(self, hour=0, minute=0, second=0):
        self._hour = hour
        self._minute = minute
        self._second = second

    @classmethod
    def now(cls):
        ctime = localtime(time())
        return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)

    def run(self):
        """走字"""
        self._second += 1
        if self._second == 60:
            self._second = 0
            self._minute += 1
            if self._minute == 60:
                self._minute = 0
                self._hour += 1
                if self._hour == 24:
                    self._hour = 0

    def show(self):
        """显示时间"""
        return '%02d:%02d:%02d' % \
               (self._hour, self._minute, self._second)


def main():
    clock = Clock.now()
    while True:
        print(clock.show())
        sleep(1)
        clock.run()


if __name__ == '__main__':
    main()


================================================
FILE: Day01-15/Day09/dependency.py
================================================
"""

对象之间的依赖关系和运算符重载

Version: 0.1
Author: 骆昊
Date: 2018-03-12

"""


class Car(object):

	def __init__(self, brand, max_speed):
		self._brand = brand
		self._max_speed = max_speed
		self._current_speed = 0

	@property
	def brand(self):
		return self._brand

	def accelerate(self, delta):
		self._current_speed += delta
		if self._current_speed > self._max_speed:
			self._current_speed = self._max_speed

	def brake(self):
		self._current_speed = 0

	def __str__(self):
		return '%s当前时速%d' % (self._brand, self._current_speed)


class Student(object):

	def __init__(self, name, age):
		self._name = name
		self._age = age

	@property
	def name(self):
		return self._name

	# 学生和车之间存在依赖关系 - 学生使用了汽车
	def drive(self, car):
		print('%s驾驶着%s欢快的行驶在去西天的路上' % (self._name, car._brand))
		car.accelerate(30)
		print(car)
		car.accelerate(50)
		print(car)
		car.accelerate(50)
		print(car)

	def study(self, course_name):
		print('%s正在学习%s.' % (self._name, course_name))

	def watch_av(self):
		if self._age < 18:
			print('%s只能观看《熊出没》.' % self._name)
		else:
			print('%s正在观看岛国爱情动作片.' % self._name)

	# 重载大于(>)运算符
	def __gt__(self, other):
		return self._age > other._age

	# 重载小于(<)运算符
	def __lt__(self, other):
		return self._age < other._age


if __name__ == '__main__':
	stu1 = Student('骆昊', 38)
	stu1.study('Python程序设计')
	stu1.watch_av()
	stu2 = Student('王大锤', 15)
	stu2.study('思想品德')
	stu2.watch_av()
	car = Car('QQ', 120)
	stu2.drive(car)
	print(stu1 > stu2)
	print(stu1 < stu2)


================================================
FILE: Day01-15/Day09/diamond.py
================================================
"""

多重继承
	- 菱形继承(钻石继承)
	- C3算法(替代DFS的算法)

Version: 0.1
Author: 骆昊
Date: 2018-03-12

"""


class A(object):

	def foo(self):
		print('foo of A')


class B(A):
	pass


class C(A):

	def foo(self):
		print('foo fo C')


class D(B, C):
	pass


class E(D):

	def foo(self):
		print('foo in E')
		super().foo()
		super(B, self).foo()
		super(C, self).foo()


if __name__ == '__main__':
	d = D()
	d.foo()
	e = E()
	e.foo()


================================================
FILE: Day01-15/Day09/employee.py
================================================
"""

抽象类 / 方法重写 / 多态
实现一个工资结算系统 公司有三种类型的员工
	- 部门经理固定月薪12000元/月
	- 程序员按本月工作小时数每小时100元
	- 销售员1500元/月的底薪加上本月销售额5%的提成
输入员工的信息 输出每位员工的月薪信息

Version: 0.1
Author: 骆昊
Date: 2018-03-12

"""

from abc import ABCMeta, abstractmethod


class Employee(object, metaclass=ABCMeta):

	def __init__(self, name):
		self._name = name

	@property
	def name(self):
		return self._name

	@abstractmethod
	def get_salary(self):
		pass


class Manager(Employee):

	# 想一想: 如果不定义构造方法会怎么样
	def __init__(self, name):
		# 想一想: 如果不调用父类构造器会怎么样
		super().__init__(name)

	def get_salary(self):
		return 12000


class Programmer(Employee):

	def __init__(self, name):
		super().__init__(name)

	def set_working_hour(self, working_hour):
		self._working_hour = working_hour

	def get_salary(self):
		return 100 * self._working_hour


class Salesman(Employee):

	def __init__(self, name):
		super().__init__(name)

	def set_sales(self, sales):
		self._sales = sales

	def get_salary(self):
		return 1500 + self._sales * 0.05


if __name__ == '__main__':
	emps = [Manager('武则天'), Programmer('狄仁杰'), Salesman('白元芳')]
	for emp in emps:
		if isinstance(emp, Programmer):
			working_hour = int(input('请输入%s本月工作时间: ' % emp.name))
			emp.set_working_hour(working_hour)
		elif isinstance(emp, Salesman):
			sales = float(input('请输入%s本月销售额: ' % emp.name))
			emp.set_sales(sales)
		print('%s本月月薪为: ¥%.2f元' % (emp.name, emp.get_salary()))


================================================
FILE: Day01-15/Day09/multi.py
================================================
"""

多重继承
	- 通过多重继承可以给一个类的对象具备多方面的能力
	- 这样在设计类的时候可以避免设计太多层次的复杂的继承关系

Version: 0.1
Author: 骆昊
Date: 2018-03-12

"""


class Father(object):

	def __init__(self, name):
		self._name = name

	def gamble(self):
		print('%s在打麻将.' % self._name)

	def eat(self):
		print('%s在大吃大喝.' % self._name)


class Monk(object):

	def __init__(self, name):
		self._name = name

	def eat(self):
		print('%s在吃斋.' % self._name)

	def chant(self):
		print('%s在念经.' % self._name)


class Musician(object):

	def __init__(self, name):
		self._name = name

	def eat(self):
		print('%s在细嚼慢咽.' % self._name)

	def play_piano(self):
		print('%s在弹钢琴.' % self._name)


# 试一试下面的代码看看有什么区别
# class Son(Monk, Father, Musician):
# class Son(Musician, Father, Monk):


class Son(Father, Monk, Musician):

	def __init__(self, name):
		Father.__init__(self, name)
		Monk.__init__(self, name)
		Musician.__init__(self, name)


son = Son('王大锤')
son.gamble()
# 调用继承自Father的eat方法
son.eat()
son.chant()
son.play_piano()


================================================
FILE: Day01-15/Day09/pet.py
================================================
from abc import ABCMeta, abstractmethod


class Pet(object, metaclass=ABCMeta):

    def __init__(self, nickname):
        self._nickname = nickname

    @abstractmethod
    def make_voice(self):
        pass


class Dog(Pet):

    def make_voice(self):
        print('%s: 汪汪汪...' % self._nickname)


class Cat(Pet):

    def make_voice(self):
        print('%s: 喵...喵...' % self._nickname)


def main():
    pets = [Dog('旺财'), Cat('凯蒂'), Dog('大黄')]
    for pet in pets:
        pet.make_voice()


if __name__ == '__main__':
    main()


================================================
FILE: Day01-15/Day09/rational.py
================================================
"""

运算符重载 - 自定义分数类

Version: 0.1
Author: 骆昊
Date: 2018-03-12

"""

from math import gcd


class Rational(object):

	def __init__(self, num, den=1):
		if den == 0:
			raise ValueError('分母不能为0')
		self._num = num
		self._den = den
		self.normalize()

	def simplify(self):
		x = abs(self._num)
		y = abs(self._den)
		factor = gcd(x, y)
		if factor > 1:
			self._num //= factor
			self._den //= factor
		return self

	def normalize(self):
		if self._den < 0:
			self._den = -self._den
			self._num = -self._num
		return self

	def __add__(self, other):
		new_num = self._num * other._den + other._num * self._den
		new_den = self._den * other._den
		return Rational(new_num, new_den).simplify().normalize()

	def __sub__(self, other):
		new_num = self._num * other._den - other._num * self._den
		new_den = self._den * other._den
		return Rational(new_num, new_den).simplify().normalize()

	def __mul__(self, other):
		new_num = self._num * other._num
		new_den = self._den * other._den
		return Rational(new_num, new_den).simplify().normalize()

	def __truediv__(self, other):
		new_num = self._num * other._den
		new_den = self._den * other._num
		return Rational(new_num, new_den).simplify().normalize()

	def __str__(self):
		if self._num == 0:
			return '0'
		elif self._den == 1:
			return str(self._num)
		else:
			return '(%d/%d)' % (self._num, self._den)


if __name__ == '__main__':
	r1 = Rational(2, 3)
	print(r1)
	r2 = Rational(6, -8)
	print(r2)
	print(r2.simplify())
	print('%s + %s = %s' % (r1, r2, r1 + r2))
	print('%s - %s = %s' % (r1, r2, r1 - r2))
	print('%s * %s = %s' % (r1, r2, r1 * r2))
	print('%s / %s = %s' % (r1, r2, r1 / r2))


================================================
FILE: Day01-15/Day09/res/uml-example.gliffy
================================================
{"contentType":"application/gliffy+json","version":"1.1","metadata":{"title":"untitled","revision":0,"exportBorder":false},"embeddedResources":{"index":0,"resources":[]},"stage":{"objects":[{"x":211,"y":179.5,"rotation":0,"id":79,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":60,"height":28,"lockAspectRatio":false,"lockShape":false,"order":71,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">继承关系</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]},{"x":702,"y":249,"rotation":0,"id":78,"uid":"com.gliffy.shape.uml.uml_v1.default.generalization","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":70,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":4,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[82,-4],[50,-4],[50,-69.32485578727801],[18,-69.32485578727801]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":70,"px":0,"py":0.5}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":32,"px":0.9999999999999998,"py":0.7071067811865475}}},"linkMap":[]},{"x":615,"y":70,"rotation":0,"id":77,"uid":"com.gliffy.shape.uml.uml_v1.default.generalization","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":69,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":4,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[169,6.75],[137,6.75],[137,70.32485578727798],[105,70.32485578727798]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":63,"px":0,"py":0.5}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":32,"px":1,"py":0.29289321881345237}}},"linkMap":[]},{"x":228,"y":356,"rotation":0,"id":55,"uid":"com.gliffy.shape.uml.uml_v1.default.association","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":0,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":0,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[202,-46],[202,-22.666666666666686],[202,0.6666666666666856],[202,24]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":24,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":48,"px":0.5,"py":0}}},"linkMap":[]},{"x":667,"y":225,"rotation":0,"id":47,"uid":"com.gliffy.shape.uml.uml_v1.default.aggregation","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":40,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":5,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[-17,-17.5],[-17,8.333333333333343],[-17,34.166666666666686],[-17,60]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":32,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":56,"px":0.5,"py":0}}},"linkMap":[]},{"x":403,"y":390,"rotation":0,"id":39,"uid":"com.gliffy.shape.uml.uml_v1.default.dependency","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":39,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":"8.0,2.0","startArrow":0,"endArrow":6,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[97,-125],[137,-125],[137,-230],[177,-230]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":24,"px":1,"py":0.5}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":32,"px":0,"py":0.5}}},"linkMap":[]},{"x":289,"y":219,"rotation":0,"id":31,"uid":"com.gliffy.shape.uml.uml_v1.default.generalization","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":31,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":4,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[141,1],[141,-124],[51,-124]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":24,"px":0.5,"py":0}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":0,"px":1,"py":0.5}}},"linkMap":[]},{"x":325,"y":185,"rotation":0,"id":22,"uid":"com.gliffy.shape.uml.uml_v1.default.generalization","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":23,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":4,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[-55,35],[-55,11.666666666666657],[-55,-11.666666666666657],[-55,-35]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":14,"px":0.5,"py":0}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":0,"px":0.5,"py":1}}},"linkMap":[]},{"x":98,"y":173,"rotation":0,"id":21,"uid":"com.gliffy.shape.uml.uml_v1.default.generalization","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":22,"graphic":{"type":"Line","Line":{"strokeWidth":1,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":4,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":null,"controlPath":[[12,47],[12,-78],[102,-78]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":7,"px":0.5,"py":0}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":0,"px":0,"py":0.5}}},"linkMap":[]},{"x":200,"y":220,"rotation":0,"id":14,"uid":"com.gliffy.shape.uml.uml_v1.default.class","width":140,"height":75,"lockAspectRatio":false,"lockShape":false,"order":15,"graphic":null,"children":[{"x":0,"y":0,"rotation":0,"id":15,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":16,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">Teacher</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":16,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":18,"rotation":0,"id":17,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":18,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">title</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"PositionConstraint","PositionConstraint":{"nodeId":15,"px":0,"py":1}},{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":18,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":36,"rotation":0,"id":19,"uid":null,"width":140,"height":39,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":20,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">teach</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":14,"magnitude":1},{"id":15,"magnitude":-1},{"id":17,"magnitude":-1}],"growParent":false,"padding":0}},{"type":"PositionConstraint","PositionConstraint":{"nodeId":17,"px":0,"py":1}}]}}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":true,"heightInfo":[{"id":15,"magnitude":1},{"id":17,"magnitude":1},{"id":20,"magnitude":1}],"growParent":false,"padding":0}}]},"linkMap":[]},{"x":40,"y":220,"rotation":0,"id":7,"uid":"com.gliffy.shape.uml.uml_v1.default.class","width":140,"height":75,"lockAspectRatio":false,"lockShape":false,"order":8,"graphic":null,"children":[{"x":0,"y":0,"rotation":0,"id":8,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":9,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">Student</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":9,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":18,"rotation":0,"id":10,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":11,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">grade</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"PositionConstraint","PositionConstraint":{"nodeId":8,"px":0,"py":1}},{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":11,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":36,"rotation":0,"id":12,"uid":null,"width":140,"height":39,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":13,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">study</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":7,"magnitude":1},{"id":8,"magnitude":-1},{"id":10,"magnitude":-1}],"growParent":false,"padding":0}},{"type":"PositionConstraint","PositionConstraint":{"nodeId":10,"px":0,"py":1}}]}}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":true,"heightInfo":[{"id":8,"magnitude":1},{"id":10,"magnitude":1},{"id":13,"magnitude":1}],"growParent":false,"padding":0}}]},"linkMap":[]},{"x":200,"y":40,"rotation":0,"id":0,"uid":"com.gliffy.shape.uml.uml_v1.default.class","width":140,"height":110,"lockAspectRatio":false,"lockShape":false,"order":1,"graphic":null,"children":[{"x":0,"y":0,"rotation":0,"id":1,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":2,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">Person</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":2,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":18,"rotation":0,"id":3,"uid":null,"width":140,"height":32,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":4,"uid":null,"width":140,"height":32,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">name\n</span></p><p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">age</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"PositionConstraint","PositionConstraint":{"nodeId":1,"px":0,"py":1}},{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":4,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":50,"rotation":0,"id":5,"uid":null,"width":140,"height":60,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":6,"uid":null,"width":140,"height":32,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">eat\n</span></p><p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">play</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":0,"magnitude":1},{"id":1,"magnitude":-1},{"id":3,"magnitude":-1}],"growParent":false,"padding":0}},{"type":"PositionConstraint","PositionConstraint":{"nodeId":3,"px":0,"py":1}}]}}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":true,"heightInfo":[{"id":1,"magnitude":1},{"id":3,"magnitude":1},{"id":6,"magnitude":1}],"growParent":false,"padding":0}}]},"linkMap":[]},{"x":360,"y":220,"rotation":0,"id":24,"uid":"com.gliffy.shape.uml.uml_v1.default.class","width":140,"height":90,"lockAspectRatio":false,"lockShape":false,"order":24,"graphic":null,"children":[{"x":0,"y":0,"rotation":0,"id":25,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":26,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">Driver</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":26,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":18,"rotation":0,"id":27,"uid":null,"width":140,"height":32,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":28,"uid":null,"width":140,"height":32,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">work_experience\n</span></p><p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">license</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"PositionConstraint","PositionConstraint":{"nodeId":25,"px":0,"py":1}},{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":28,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":50,"rotation":0,"id":29,"uid":null,"width":140,"height":40,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":30,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">drive</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":24,"magnitude":1},{"id":25,"magnitude":-1},{"id":27,"magnitude":-1}],"growParent":false,"padding":0}},{"type":"PositionConstraint","PositionConstraint":{"nodeId":27,"px":0,"py":1}}]}}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":true,"heightInfo":[{"id":25,"magnitude":1},{"id":27,"magnitude":1},{"id":30,"magnitude":1}],"growParent":false,"padding":0}}]},"linkMap":[]},{"x":580,"y":112.5,"rotation":0,"id":32,"uid":"com.gliffy.shape.uml.uml_v1.default.class","width":140,"height":95,"lockAspectRatio":false,"lockShape":false,"order":32,"graphic":null,"children":[{"x":0,"y":0,"rotation":0,"id":33,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":34,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">Vehicle</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":34,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":18,"rotation":0,"id":35,"uid":null,"width":140,"height":32,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":36,"uid":null,"width":140,"height":32,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">brand\n</span></p><p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">engine</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"PositionConstraint","PositionConstraint":{"nodeId":33,"px":0,"py":1}},{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":36,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":50,"rotation":0,"id":37,"uid":null,"width":140,"height":45,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":38,"uid":null,"width":140,"height":32,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">accelerate\n</span></p><p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">slow_down</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":32,"magnitude":1},{"id":33,"magnitude":-1},{"id":35,"magnitude":-1}],"growParent":false,"padding":0}},{"type":"PositionConstraint","PositionConstraint":{"nodeId":35,"px":0,"py":1}}]}}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":true,"heightInfo":[{"id":33,"magnitude":1},{"id":35,"magnitude":1},{"id":38,"magnitude":1}],"growParent":false,"padding":0}}]},"linkMap":[]},{"x":360,"y":380,"rotation":0,"id":48,"uid":"com.gliffy.shape.uml.uml_v1.default.class","width":140,"height":75,"lockAspectRatio":false,"lockShape":false,"order":41,"graphic":null,"children":[{"x":0,"y":0,"rotation":0,"id":49,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":50,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">License</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":50,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":18,"rotation":0,"id":51,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":52,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align: left;\"><span class=\"gliffy-placeholder-text\" style=\"font-family: Arial; font-size: 12px; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">Attribute</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"PositionConstraint","PositionConstraint":{"nodeId":49,"px":0,"py":1}},{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":52,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":36,"rotation":0,"id":53,"uid":null,"width":140,"height":39,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":54,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align: left;\"><span class=\"gliffy-placeholder-text\" style=\"font-family: Arial; font-size: 12px; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">Method</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":48,"magnitude":1},{"id":49,"magnitude":-1},{"id":51,"magnitude":-1}],"growParent":false,"padding":0}},{"type":"PositionConstraint","PositionConstraint":{"nodeId":51,"px":0,"py":1}}]}}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":true,"heightInfo":[{"id":49,"magnitude":1},{"id":51,"magnitude":1},{"id":54,"magnitude":1}],"growParent":false,"padding":0}}]},"linkMap":[]},{"x":580,"y":285,"rotation":0,"id":56,"uid":"com.gliffy.shape.uml.uml_v1.default.class","width":140,"height":75,"lockAspectRatio":false,"lockShape":false,"order":48,"graphic":null,"children":[{"x":0,"y":0,"rotation":0,"id":57,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":58,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">Engine</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":58,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":18,"rotation":0,"id":59,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":60,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">number</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"PositionConstraint","PositionConstraint":{"nodeId":57,"px":0,"py":1}},{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":60,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":36,"rotation":0,"id":61,"uid":null,"width":140,"height":39,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":62,"uid":null,"width":140,"height":4,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\"></span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":56,"magnitude":1},{"id":57,"magnitude":-1},{"id":59,"magnitude":-1}],"growParent":false,"padding":0}},{"type":"PositionConstraint","PositionConstraint":{"nodeId":59,"px":0,"py":1}}]}}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":true,"heightInfo":[{"id":57,"magnitude":1},{"id":59,"magnitude":1},{"id":62,"magnitude":1}],"growParent":false,"padding":0}}]},"linkMap":[]},{"x":784,"y":41,"rotation":0,"id":63,"uid":"com.gliffy.shape.uml.uml_v1.default.class","width":140,"height":71.5,"lockAspectRatio":false,"lockShape":false,"order":55,"graphic":null,"children":[{"x":0,"y":0,"rotation":0,"id":64,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":65,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">Car</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":65,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":18,"rotation":0,"id":66,"uid":null,"width":140,"height":32,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":67,"uid":null,"width":140,"height":32,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">seats\n</span></p><p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">displacement</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"PositionConstraint","PositionConstraint":{"nodeId":64,"px":0,"py":1}},{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":67,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":50,"rotation":0,"id":68,"uid":null,"width":140,"height":21.5,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":69,"uid":null,"width":140,"height":4,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\"></span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":63,"magnitude":1},{"id":64,"magnitude":-1},{"id":66,"magnitude":-1}],"growParent":false,"padding":0}},{"type":"PositionConstraint","PositionConstraint":{"nodeId":66,"px":0,"py":1}}]}}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":true,"heightInfo":[{"id":64,"magnitude":1},{"id":66,"magnitude":1},{"id":69,"magnitude":1}],"growParent":false,"padding":0}}]},"linkMap":[]},{"x":784,"y":207.5,"rotation":0,"id":70,"uid":"com.gliffy.shape.uml.uml_v1.default.class","width":140,"height":75,"lockAspectRatio":false,"lockShape":false,"order":62,"graphic":null,"children":[{"x":0,"y":0,"rotation":0,"id":71,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":72,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:center;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: bold; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">Truck</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":72,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":18,"rotation":0,"id":73,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":74,"uid":null,"width":140,"height":18,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">capacity</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"PositionConstraint","PositionConstraint":{"nodeId":71,"px":0,"py":1}},{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":74,"magnitude":1}],"growParent":true,"padding":0}}]}},{"x":0,"y":36,"rotation":0,"id":75,"uid":null,"width":140,"height":39,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":0,"y":0,"rotation":0,"id":76,"uid":null,"width":140,"height":4,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\"></span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":false,"heightInfo":[{"id":70,"magnitude":1},{"id":71,"magnitude":-1},{"id":73,"magnitude":-1}],"growParent":false,"padding":0}},{"type":"PositionConstraint","PositionConstraint":{"nodeId":73,"px":0,"py":1}}]}}],"constraints":{"constraints":[{"type":"HeightConstraint","HeightConstraint":{"isMin":true,"heightInfo":[{"id":71,"magnitude":1},{"id":73,"magnitude":1},{"id":76,"magnitude":1}],"growParent":false,"padding":0}}]},"linkMap":[]},{"x":371,"y":346,"rotation":0,"id":81,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":60,"height":14,"lockAspectRatio":false,"lockShape":false,"order":72,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">关联关系</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]},{"x":490,"y":186.5,"rotation":0,"id":82,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":60,"height":14,"lockAspectRatio":false,"lockShape":false,"order":73,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">依赖关系</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]},{"x":591,"y":238,"rotation":0,"id":83,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":60,"height":14,"lockAspectRatio":false,"lockShape":false,"order":74,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"<p style=\"text-align:left;\"><span style=\"font-size: 12px; font-family: Arial; white-space: pre-wrap; font-weight: normal; text-decoration: none; line-height: 14px; color: rgb(0, 0, 0);\">聚合关系</span></p>","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]}],"background":"#FFFFFF","width":926,"height":455,"maxWidth":5000,"maxHeight":5000,"nodeIndex":84,"autoFit":true,"exportBorder":false,"gridOn":true,"snapToGrid":true,"drawingGuidesOn":true,"pageBreaksOn":false,"printGridOn":false,"printPaper":"LETTER","printShrinkToFit":false,"printPortrait":true,"shapeStyles":{},"lineStyles":{},"textStyles":{},"themeData":null}}

================================================
FILE: Day01-15/Day09/shape.py
================================================
"""

继承的应用
	- 抽象类
	- 抽象方法
	- 方法重写
	- 多态

Version: 0.1
Author: 骆昊
Date: 2018-03-12

"""

from abc import ABCMeta, abstractmethod
from math import pi


class Shape(object, metaclass=ABCMeta):

	@abstractmethod
	def perimeter(self):
		pass

	@abstractmethod
	def area(self):
		pass


class Circle(Shape):

	def __init__(self, radius):
		self._radius = radius

	def perimeter(self):
		return 2 * pi * self._radius

	def area(self):
		return pi * self._radius ** 2

	def __str__(self):
		return '我是一个圆'


class Rect(Shape):

	def __init__(self, width, height):
		self._width = width
		self._height = height

	def perimeter(self):
		return 2 * (self._width + self._height)

	def area(self):
		return self._width * self._height

	def __str__(self):
		return '我是一个矩形'


if __name__ == '__main__':
	shapes = [Circle(5), Circle(3.2), Rect(3.2, 6.3)]
	for shape in shapes:
		print(shape)
		print('周长:', shape.perimeter())
		print('面积:', shape.area())


================================================
FILE: Day01-15/Day09/triangle.py
================================================
"""

实例方法和类方法的应用

Version: 0.1
Author: 骆昊
Date: 2018-03-12

"""

from math import sqrt


class Triangle(object):

	def __init__(self, a, b, c):
		self._a = a
		self._b = b
		self._c = c

	# 静态方法
	@staticmethod
	def is_valid(a, b, c):
		return a + b > c and b + c > a and c + a > b

	# 实例方法
	def perimeter(self):
		return self._a + self._b + self._c

	# 实例方法
	def area(self):
		p = self.perimeter() / 2
		return sqrt(p * (p - self._a) * (p - self._b) * (p - self._c))


if __name__ == '__main__':
	# 用字符串的split方法将字符串拆分成一个列表
	# 再通过map函数对列表中的每个字符串进行映射处理成小数
	a, b, c = map(float, input('请输入三条边: ').split())
	# 先判断给定长度的三条边能否构成三角形
	# 如果能才创建三角形对象
	if Triangle.is_valid(a, b, c):
		tri = Triangle(a, b, c)
		print('周长:', tri.perimeter())
		print('面积:', tri.area())
		# 如果传入对象作为方法参数也可以通过类调用实例方法
		# print('周长:', Triangle.perimeter(tri))
		# print('面积:', Triangle.area(tri))
		# 看看下面的代码就知道其实二者本质上是一致的
		# print(type(tri.perimeter))
		# print(type(Triangle.perimeter))
	else:
		print('不能构成三角形.')


================================================
FILE: Day01-15/Day09/面向对象进阶.md
================================================
## 面向对象进阶

在前面的章节我们已经了解了面向对象的入门知识,知道了如何定义类,如何创建对象以及如何给对象发消息。为了能够更好的使用面向对象编程思想进行程序开发,我们还需要对Python中的面向对象编程进行更为深入的了解。

### @property装饰器

之前我们讨论过Python中属性和方法访问权限的问题,虽然我们不建议将属性设置为私有的,但是如果直接将属性暴露给外界也是有问题的,比如我们没有办法检查赋给属性的值是否有效。我们之前的建议是将属性命名以单下划线开头,通过这种方式来暗示属性是受保护的,不建议外界直接访问,那么如果想访问属性可以通过属性的getter(访问器)和setter(修改器)方法进行对应的操作。如果要做到这点,就可以考虑使用@property包装器来包装getter和setter方法,使得对属性的访问既安全又方便,代码如下所示。

```Python
class Person(object):

    def __init__(self, name, age):
        self._name = name
        self._age = age

    # 访问器 - getter方法
    @property
    def name(self):
        return self._name

    # 访问器 - getter方法
    @property
    def age(self):
        return self._age

    # 修改器 - setter方法
    @age.setter
    def age(self, age):
        self._age = age

    def play(self):
        if self._age <= 16:
            print('%s正在玩飞行棋.' % self._name)
        else:
            print('%s正在玩斗地主.' % self._name)


def main():
    person = Person('王大锤', 12)
    person.play()
    person.age = 22
    person.play()
    # person.name = '白元芳'  # AttributeError: can't set attribute


if __name__ == '__main__':
    main()

```

### \_\_slots\_\_魔法

我们讲到这里,不知道大家是否已经意识到,Python是一门[动态语言](https://zh.wikipedia.org/wiki/%E5%8A%A8%E6%80%81%E8%AF%AD%E8%A8%80)。通常,动态语言允许我们在程序运行时给对象绑定新的属性或方法,当然也可以对已经绑定的属性和方法进行解绑定。但是如果我们需要限定自定义类型的对象只能绑定某些属性,可以通过在类中定义\_\_slots\_\_变量来进行限定。需要注意的是\_\_slots\_\_的限定只对当前类的对象生效,对子类并不起任何作用。

```Python
class Person(object):

    # 限定Person对象只能绑定_name, _age和_gender属性
    __slots__ = ('_name', '_age', '_gender')

    def __init__(self, name, age):
        self._name = name
        self._age = age

    @property
    def name(self):
        return self._name

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, age):
        self._age = age

    def play(self):
        if self._age <= 16:
            print('%s正在玩飞行棋.' % self._name)
        else:
            print('%s正在玩斗地主.' % self._name)


def main():
    person = Person('王大锤', 22)
    person.play()
    person._gender = '男'
    # AttributeError: 'Person' object has no attribute '_is_gay'
    # person._is_gay = True

```

### 静态方法和类方法

之前,我们在类中定义的方法都是对象方法,也就是说这些方法都是发送给对象的消息。实际上,我们写在类中的方法并不需要都是对象方法,例如我们定义一个“三角形”类,通过传入三条边长来构造三角形,并提供计算周长和面积的方法,但是传入的三条边长未必能构造出三角形对象,因此我们可以先写一个方法来验证三条边长是否可以构成三角形,这个方法很显然就不是对象方法,因为在调用这个方法时三角形对象尚未创建出来(因为都不知道三条边能不能构成三角形),所以这个方法是属于三角形类而并不属于三角形对象的。我们可以使用静态方法来解决这类问题,代码如下所示。

```Python
from math import sqrt


class Triangle(object):

    def __init__(self, a, b, c):
        self._a = a
        self._b = b
        self._c = c

    @staticmethod
    def is_valid(a, b, c):
        return a + b > c and b + c > a and a + c > b

    def perimeter(self):
        return self._a + self._b + self._c

    def area(self):
        half = self.perimeter() / 2
        return sqrt(half * (half - self._a) *
                    (half - self._b) * (half - self._c))


def main():
    a, b, c = 3, 4, 5
    # 静态方法和类方法都是通过给类发消息来调用的
    if Triangle.is_valid(a, b, c):
        t = Triangle(a, b, c)
        print(t.perimeter())
        # 也可以通过给类发消息来调用对象方法但是要传入接收消息的对象作为参数
        # print(Triangle.perimeter(t))
        print(t.area())
        # print(Triangle.area(t))
    else:
        print('无法构成三角形.')


if __name__ == '__main__':
    main()

```

和静态方法比较类似,Python还可以在类中定义类方法,类方法的第一个参数约定名为cls,它代表的是当前类相关的信息的对象(类本身也是一个对象,有的地方也称之为类的元数据对象),通过这个参数我们可以获取和类相关的信息并且可以创建出类的对象,代码如下所示。

```Python
from time import time, localtime, sleep


class Clock(object):
    """数字时钟"""

    def __init__(self, hour=0, minute=0, second=0):
        self._hour = hour
        self._minute = minute
        self._second = second

    @classmethod
    def now(cls):
        ctime = localtime(time())
        return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)

    def run(self):
        """走字"""
        self._second += 1
        if self._second == 60:
            self._second = 0
            self._minute += 1
            if self._minute == 60:
                self._minute = 0
                self._hour += 1
                if self._hour == 24:
                    self._hour = 0

    def show(self):
        """显示时间"""
        return '%02d:%02d:%02d' % \
               (self._hour, self._minute, self._second)


def main():
    # 通过类方法创建对象并获取系统时间
    clock = Clock.now()
    while True:
        print(clock.show())
        sleep(1)
        clock.run()


if __name__ == '__main__':
    main()

```

### 类之间的关系

简单的说,类和类之间的关系有三种:is-a、has-a和use-a关系。

- is-a关系也叫继承或泛化,比如学生和人的关系、手机和电子产品的关系都属于继承关系。
- has-a关系通常称之为关联,比如部门和员工的关系,汽车和引擎的关系都属于关联关系;关联关系如果是整体和部分的关联,那么我们称之为聚合关系;如果整体进一步负责了部分的生命周期(整体和部分是不可分割的,同时同在也同时消亡),那么这种就是最强的关联关系,我们称之为合成关系。
- use-a关系通常称之为依赖,比如司机有一个驾驶的行为(方法),其中(的参数)使用到了汽车,那么司机和汽车的关系就是依赖关系。

我们可以使用一种叫做[UML](https://zh.wikipedia.org/wiki/%E7%BB%9F%E4%B8%80%E5%BB%BA%E6%A8%A1%E8%AF%AD%E8%A8%80)(统一建模语言)的东西来进行面向对象建模,其中一项重要的工作就是把类和类之间的关系用标准化的图形符号描述出来。关于UML我们在这里不做详细的介绍,有兴趣的读者可以自行阅读[《UML面向对象设计基础》](https://e.jd.com/30392949.html)一书。

![](./res/uml-components.png)

![](./res/uml-example.png)

利用类之间的这些关系,我们可以在已有类的基础上来完成某些操作,也可以在已有类的基础上创建新的类,这些都是实现代码复用的重要手段。复用现有的代码不仅可以减少开发的工作量,也有利于代码的管理和维护,这是我们在日常工作中都会使用到的技术手段。

### 继承和多态

刚才我们提到了,可以在已有类的基础上创建新类,这其中的一种做法就是让一个类从另一个类那里将属性和方法直接继承下来,从而减少重复代码的编写。提供继承信息的我们称之为父类,也叫超类或基类;得到继承信息的我们称之为子类,也叫派生类或衍生类。子类除了继承父类提供的属性和方法,还可以定义自己特有的属性和方法,所以子类比父类拥有的更多的能力,在实际开发中,我们经常会用子类对象去替换掉一个父类对象,这是面向对象编程中一个常见的行为,对应的原则称之为[里氏替换原则](https://zh.wikipedia.org/wiki/%E9%87%8C%E6%B0%8F%E6%9B%BF%E6%8D%A2%E5%8E%9F%E5%88%99)。下面我们先看一个继承的例子。

```Python
class Person(object):
    """人"""

    def __init__(self, name, age):
        self._name = name
        self._age = age

    @property
    def name(self):
        return self._name

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, age):
        self._age = age

    def play(self):
        print('%s正在愉快的玩耍.' % self._name)

    def watch_av(self):
        if self._age >= 18:
            print('%s正在观看爱情动作片.' % self._name)
        else:
            print('%s只能观看《熊出没》.' % self._name)


class Student(Person):
    """学生"""

    def __init__(self, name, age, grade):
        super().__init__(name, age)
        self._grade = grade

    @property
    def grade(self):
        return self._grade

    @grade.setter
    def grade(self, grade):
        self._grade = grade

    def study(self, course):
        print('%s的%s正在学习%s.' % (self._grade, self._name, course))


class Teacher(Person):
    """老师"""

    def __init__(self, name, age, title):
        super().__init__(name, age)
        self._title = title

    @property
    def title(self):
        return self._title

    @title.setter
    def title(self, title):
        self._title = title

    def teach(self, course):
        print('%s%s正在讲%s.' % (self._name, self._title, course))


def main():
    stu = Student('王大锤', 15, '初三')
    stu.study('数学')
    stu.watch_av()
    t = Teacher('骆昊', 38, '老叫兽')
    t.teach('Python程序设计')
    t.watch_av()


if __name__ == '__main__':
    main()

```

子类在继承了父类的方法后,可以对父类已有的方法给出新的实现版本,这个动作称之为方法重写(override)。通过方法重写我们可以让父类的同一个行为在子类中拥有不同的实现版本,当我们调用这个经过子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态(poly-morphism)。

```Python
from abc import ABCMeta, abstractmethod


class Pet(object, metaclass=ABCMeta):
    """宠物"""

    def __init__(self, nickname):
        self._nickname = nickname

    @abstractmethod
    def make_voice(self):
        """发出声音"""
        pass


class Dog(Pet):
    """狗"""

    def make_voice(self):
        print('%s: 汪汪汪...' % self._nickname)


class Cat(Pet):
    """猫"""

    def make_voice(self):
        print('%s: 喵...喵...' % self._nickname)


def main():
    pets = [Dog('旺财'), Cat('凯蒂'), Dog('大黄')]
    for pet in pets:
        pet.make_voice()


if __name__ == '__main__':
    main()

```

在上面的代码中,我们将`Pet`类处理成了一个抽象类,所谓抽象类就是不能够创建对象的类,这种类的存在就是专门为了让其他类去继承它。Python从语法层面并没有像Java或C#那样提供对抽象类的支持,但是我们可以通过`abc`模块的`ABCMeta`元类和`abstractmethod`包装器来达到抽象类的效果,如果一个类中存在抽象方法那么这个类就不能够实例化(创建对象)。上面的代码中,`Dog`和`Cat`两个子类分别对`Pet`类中的`make_voice`抽象方法进行了重写并给出了不同的实现版本,当我们在`main`函数中调用该方法时,这个方法就表现出了多态行为(同样的方法做了不同的事情)。

### 综合案例

#### 案例1:奥特曼打小怪兽

```Python
from abc import ABCMeta, abstractmethod
from random import randint, randrange


class Fighter(object, metaclass=ABCMeta):
    """战斗者"""

    # 通过__slots__魔法限定对象可以绑定的成员变量
    __slots__ = ('_name', '_hp')

    def __init__(self, name, hp):
        """
        初始化方法

        :param name: 名字
        :param hp: 生命值
        """
        self._name = name
        self._hp = hp

    @property
    def name(self):
        return self._name

    @property
    def hp(self):
        return self._hp

    @hp.setter
    def hp(self, hp):
        self._hp = hp if hp >= 0 else 0

    @property
    def alive(self):
        return self._hp > 0

    @abstractmethod
    def attack(self, other):
        """
        攻击

        :param other: 被攻击的对象
        """
        pass


class Ultraman(Fighter):
    """奥特曼"""

    __slots__ = ('_name', '_hp', '_mp')

    def __init__(self, name, hp, mp):
        """
        初始化方法

        :param name: 名字
        :param hp: 生命值
        :param mp: 魔法值
        """
        super().__init__(name, hp)
        self._mp = mp

    def attack(self, other):
        other.hp -= randint(15, 25)

    def huge_attack(self, other):
        """
        究极必杀技(打掉对方至少50点或四分之三的血)

        :param other: 被攻击的对象

        :return: 使用成功返回True否则返回False
        """
        if self._mp >= 50:
            self._mp -= 50
            injury = other.hp * 3 // 4
            injury = injury if injury >= 50 else 50
            other.hp -= injury
            return True
        else:
            self.attack(other)
            return False

    def magic_attack(self, others):
        """
        魔法攻击

        :param others: 被攻击的群体

        :return: 使用魔法成功返回True否则返回False
        """
        if self._mp >= 20:
            self._mp -= 20
            for temp in others:
                if temp.alive:
                    temp.hp -= randint(10, 15)
            return True
        else:
            return False

    def resume(self):
        """恢复魔法值"""
        incr_point = randint(1, 10)
        self._mp += incr_point
        return incr_point

    def __str__(self):
        return '~~~%s奥特曼~~~\n' % self._name + \
            '生命值: %d\n' % self._hp + \
            '魔法值: %d\n' % self._mp


class Monster(Fighter):
    """小怪兽"""

    __slots__ = ('_name', '_hp')

    def attack(self, other):
        other.hp -= randint(10, 20)

    def __str__(self):
        return '~~~%s小怪兽~~~\n' % self._name + \
            '生命值: %d\n' % self._hp


def is_any_alive(monsters):
    """判断有没有小怪兽是活着的"""
    for monster in monsters:
        if monster.alive > 0:
            return True
    return False


def select_alive_one(monsters):
    """选中一只活着的小怪兽"""
    monsters_len = len(monsters)
    while True:
        index = randrange(monsters_len)
        monster = monsters[index]
        if monster.alive > 0:
            return monster


def display_info(ultraman, monsters):
    """显示奥特曼和小怪兽的信息"""
    print(ultraman)
    for monster in monsters:
        print(monster, end='')


def main():
    u = Ultraman('骆昊', 1000, 120)
    m1 = Monster('舒小玲', 250)
    m2 = Monster('白元芳', 500)
    m3 = Monster('王大锤', 750)
    ms = [m1, m2, m3]
    fight_round = 1
    while u.alive and is_any_alive(ms):
        print('========第%02d回合========' % fight_round)
        m = select_alive_one(ms)  # 选中一只小怪兽
        skill = randint(1, 10)   # 通过随机数选择使用哪种技能
        if skill <= 6:  # 60%的概率使用普通攻击
            print('%s使用普通攻击打了%s.' % (u.name, m.name))
            u.attack(m)
            print('%s的魔法值恢复了%d点.' % (u.name, u.resume()))
        elif skill <= 9:  # 30%的概率使用魔法攻击(可能因魔法值不足而失败)
            if u.magic_attack(ms):
                print('%s使用了魔法攻击.' % u.name)
            else:
                print('%s使用魔法失败.' % u.name)
        else:  # 10%的概率使用究极必杀技(如果魔法值不足则使用普通攻击)
            if u.huge_attack(m):
                print('%s使用究极必杀技虐了%s.' % (u.name, m.name))
            else:
                print('%s使用普通攻击打了%s.' % (u.name, m.name))
                print('%s的魔法值恢复了%d点.' % (u.name, u.resume()))
        if m.alive > 0:  # 如果选中的小怪兽没有死就回击奥特曼
            print('%s回击了%s.' % (m.name, u.name))
            m.attack(u)
        display_info(u, ms)  # 每个回合结束后显示奥特曼和小怪兽的信息
        fight_round += 1
    print('\n========战斗结束!========\n')
    if u.alive > 0:
        print('%s奥特曼胜利!' % u.name)
    else:
        print('小怪兽胜利!')


if __name__ == '__main__':
    main()

```

#### 案例2:扑克游戏

```Python
from random import randrange


class Card(object):
    """一张牌"""

    def __init__(self, suite, face):
        self._suite = suite
        self._face = face

    @property
    def face(self):
        return self._face

    @property
    def suite(self):
        return self._suite

    def __str__(self):
        all_suites = ('♠', '♥', '♣', '♦')
        if self._face == 1:
            face_str = 'A'
        elif self._face == 11:
            face_str = 'J'
        elif self._face == 12:
            face_str = 'Q'
        elif self._face == 13:
            face_str = 'K'
        else:
            face_str = str(self._face)
        return '%s%s' % (all_suites[self._suite], face_str)


class Poker(object):
    """一副牌"""

    def __init__(self):
        self._cards = []
        self._current = 0
        for suite in range(4):
            for face in range(1, 14):
                card = Card(suite, face)
                self._cards.append(card)

    @property
    def cards(self):
        return self._cards

    def shuffle(self):
        """洗牌(随机乱序)"""
        self._current = 0
        cards_len = len(self._cards)
        for index in range(cards_len):
            pos = randrange(cards_len)
            self._cards[index], self._cards[pos] = \
                self._cards[pos], self._cards[index]

    @property
    def next(self):
        """发牌"""
        card = self._cards[self._current]
        self._current += 1
        return card

    @property
    def has_next(self):
        """还有没有牌"""
        return self._current < len(self._cards)


class Player(object):
    """玩家"""

    def __init__(self, name):
        self._name = name
        self._cards_on_hand = []

    @property
    def name(self):
        return self._name

    @property
    def cards_on_hand(self):
        return self._cards_on_hand

    def get(self, card):
        """摸牌"""
        self._cards_on_hand.append(card)

    def arrange(self, card_key):
        """玩家整理手上的牌"""
        self._cards_on_hand.sort(key=card_key)


# 排序规则-先根据花色再根据点数排序
def get_key(card):
    return (card.suite, card.face)


def main():
    p = Poker()
    p.shuffle()
    players = [Player('东邪'), Player('西毒'), Player('南帝'), Player('北丐')]
    for _ in range(13):
        for player in players:
            player.get(p.next)
    for player in players:
        print(player.name + ':', end=' ')
        player.arrange(get_key)
        for card in player.cards_on_hand:
            print(card, end=' ')
        print()


if __name__ == '__main__':
    main()

```

>**说明**:大家可以自己尝试在上面代码的基础上写一个简单的扑克游戏,例如21点(Black Jack),游戏的规则可以自己在网上找一找。

#### 案例3:工资结算系统

```Python
"""

某公司有三种类型的员工 分别是部门经理、程序员和销售员
需要设计一个工资结算系统 根据提供的员工信息来计算月薪
部门经理的月薪是每月固定15000元
程序员的月薪按本月工作时间计算 每小时150元
销售员的月薪是1200元的底薪加上销售额5%的提成

"""
from abc import ABCMeta, abstractmethod


class Employee(object, metaclass=ABCMeta):
    """员工"""

    def __init__(self, name):
        """
        初始化方法

        :param name: 姓名
        """
        self._name = name

    @property
    def name(self):
        return self._name

    @abstractmethod
    def get_salary(self):
        """
        获得月薪

        :return: 月薪
        """
        pass


class Manager(Employee):
    """部门经理"""

    def get_salary(self):
        return 15000.0


class Programmer(Employee):
    """程序员"""

    def __init__(self, name, working_hour=0):
        super().__init__(name)
        self._working_hour = working_hour

    @property
    def working_hour(self):
        return self._working_hour

    @working_hour.setter
    def working_hour(self, working_hour):
        self._working_hour = working_hour if working_hour > 0 else 0

    def get_salary(self):
        return 150.0 * self._working_hour


class Salesman(Employee):
    """销售员"""

    def __init__(self, name, sales=0):
        super().__init__(name)
        self._sales = sales

    @property
    def sales(self):
        return self._sales

    @sales.setter
    def sales(self, sales):
        self._sales = sales if sales > 0 else 0

    def get_salary(self):
        return 1200.0 + self._sales * 0.05


def main():
    emps = [
        Manager('刘备'), Programmer('诸葛亮'),
        Manager('曹操'), Salesman('荀彧'),
        Salesman('吕布'), Programmer('张辽'),
        Programmer('赵云')
    ]
    for emp in emps:
        if isinstance(emp, Programmer):
            emp.working_hour = int(input('请输入%s本月工作时间: ' % emp.name))
        elif isinstance(emp, Salesman):
            emp.sales = float(input('请输入%s本月销售额: ' % emp.name))
        # 同样是接收get_salary这个消息但是不同的员工表现出了不同的行为(多态)
        print('%s本月工资为: ¥%s元' %
              (emp.name, emp.get_salary()))


if __name__ == '__main__':
    main()

```



================================================
FILE: Day01-15/Day10/ball.py
================================================
from enum import Enum, unique
from math import sqrt
from random import randint

import pygame


@unique
class Color(Enum):
    """颜色"""

    RED = (255, 0, 0)
    GREEN = (0, 255, 0)
    BLUE = (0, 0, 255)
    BLACK = (0, 0, 0)
    WHITE = (255, 255, 255)
    GRAY = (242, 242, 242)

    @staticmethod
    def random_color():
        """获得随机颜色"""
        r = randint(0, 255)
        g = randint(0, 255)
        b = randint(0, 255)
        return (r, g, b)


class Ball(object):
    """球"""

    def __init__(self, x, y, radius, sx, sy, color=Color.RED):
        """初始化方法"""
        self.x = x
        self.y = y
        self.radius = radius
        self.sx = sx
        self.sy = sy
        self.color = color
        self.alive = True

    def move(self, screen):
        """移动"""
        self.x += self.sx
        self.y += self.sy
        if self.x - self.radius <= 0 or self.x + self.radius >= screen.get_width():
            self.sx = -self.sx
        if self.y - self.radius <= 0 or self.y + self.radius >= screen.get_height():
            self.sy = -self.sy

    def eat(self, other):
        """吃其他球"""
        if self.alive and other.alive and self != other:
            dx, dy = self.x - other.x, self.y - other.y
            distance = sqrt(dx ** 2 + dy ** 2)
            if distance < self.radius + other.radius \
                    and self.radius > other.radius:
                other.alive = False
               	self.radius = self.radius + int(other.radius * 0.146)

    def draw(self, screen):
        """在窗口上绘制球"""
        pygame.draw.circle(screen, self.color,
                           (self.x, self.y), self.radius, 0)


def main():
    # 定义用来装所有球的容器
    balls = []
    # 初始化导入的pygame中的模块
    pygame.init()
    # 初始化用于显示的窗口并设置窗口尺寸
    screen = pygame.display.set_mode((800, 600))
    print(screen.get_width())
    print(screen.get_height())
    # 设置当前窗口的标题
    pygame.display.set_caption('大球吃小球')
    # 定义变量来表示小球在屏幕上的位置
    x, y = 50, 50
    running = True
    # 开启一个事件循环处理发生的事件
    while running:
        # 从消息队列中获取事件并对事件进行处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                x, y = event.pos
                radius = randint(10, 100)
                sx, sy = randint(-10, 10), randint(-10, 10)
                color = Color.random_color()
                ball = Ball(x, y, radius, sx, sy, color)
                balls.append(ball)
        screen.fill((255, 255, 255))
        for ball in balls:
            if ball.alive:
                ball.draw(screen)
            else:
                balls.remove(ball)
        pygame.display.flip()
        # 每隔50毫秒就改变小球的位置再刷新窗口
        pygame.time.delay(50)
        for ball in balls:
            ball.move(screen)
            for other in balls:
                ball.eat(other)


if __name__ == '__main__':
    main()


================================================
FILE: Day01-15/Day10/gui1.py
================================================
"""

使用tkinter创建GUI
	- 顶层窗口
	- 控件
	- 布局
	- 事件回调

Version: 0.1
Author: 骆昊
Date: 2018-03-14

"""

import tkinter
import tkinter.messagebox


def main():
	flag = True

	# 修改标签上的文字
	def change_label_text():
		nonlocal flag
		flag = not flag
		color, msg = ('red', 'Hello, world!')\
			if flag else ('blue', 'Goodbye, world!')
		label.config(text=msg, fg=color)

	# 确认退出
	def confirm_to_quit():
		if tkinter.messagebox.askokcancel('温馨提示', '确定要退出吗?'):
			top.quit()

	# 创建顶层窗口
	top = tkinter.Tk()
	# 设置窗口大小
	top.geometry('240x160')
	# 设置窗口标题
	top.title('小游戏')
	# 创建标签对象
	label = tkinter.Label(top, text='Hello, world!', font='Arial -32', fg='red')
	label.pack(expand=1)
	# 创建一个装按钮的容器
	panel = tkinter.Frame(top)
	# 创建按钮对象
	button1 = tkinter.Button(panel, text='修改', command=change_label_text)
	button1.pack(side='left')
	button2 = tkinter.Button(panel, text='退出', command=confirm_to_quit)
	button2.pack(side='right')
	panel.pack(side='bottom')
	# 开启主事件循环
	tkinter.mainloop()


if __name__ == '__main__':
	main()


================================================
FILE: Day01-15/Day10/gui2.py
================================================
"""

使用tkinter创建GUI
	- 使用画布绘图
	- 处理鼠标事件

Version: 0.1
Author: 骆昊
Date: 2018-03-14

"""

import tkinter


def mouse_evt_handler(evt=None):
	row = round((evt.y - 20) / 40)
	col = round((evt.x - 20) / 40)
	pos_x = 40 * col
	pos_y = 40 * row
	canvas.create_oval(pos_x, pos_y, 40 + pos_x, 40 + pos_y, fill='black')


top = tkinter.Tk()
# 设置窗口尺寸
top.geometry('620x620')
# 设置窗口标题
top.title('五子棋')
# 设置窗口大小不可改变
top.resizable(False, False)
# 设置窗口置顶
top.wm_attributes('-topmost', 1)
canvas = tkinter.Canvas(top, width=600, height=600, bd=0, highlightthickness=0)
canvas.bind('<Button-1>', mouse_evt_handler)
canvas.create_rectangle(0, 0, 600, 600, fill='yellow', outline='white')
for index in range(15):
	canvas.create_line(20, 20 + 40 * index, 580, 20 + 40 * index, fill='black')
	canvas.create_line(20 + 40 * index, 20, 20 + 40 * index, 580, fill='black')
canvas.create_rectangle(15, 15, 585, 585, outline='black', width=4)
canvas.pack()
tkinter.mainloop()

# 请思考如何用面向对象的编程思想对上面的代码进行封装


================================================
FILE: Day01-15/Day10/gui3.py
================================================
"""

使用tkinter创建GUI
	- 在窗口上制作动画

Version: 0.1
Author: 骆昊
Date: 2018-03-14

"""

import tkinter
import time


# 播放动画效果的函数
def play_animation():
	canvas.move(oval, 2, 2)
	canvas.update()
	top.after(50, play_animation)


x = 10
y = 10
top = tkinter.Tk()
top.geometry('600x600')
top.title('动画效果')
top.resizable(False, False)
top.wm_attributes('-topmost', 1)
canvas = tkinter.Canvas(top, width=600, height=600, bd=0, highlightthickness=0)
canvas.create_rectangle(0, 0, 600, 600, fill='gray')
oval = canvas.create_oval(10, 10, 60, 60, fill='red')
canvas.pack()
top.update()
play_animation()
tkinter.mainloop()

# 请思考如何让小球碰到屏幕的边界就弹回
# 请思考如何用面向对象的编程思想对上面的代码进行封装


================================================
FILE: Day01-15/Day10/turtle1.py
================================================
"""

用turtle模块绘图
这是一个非常有趣的模块 它模拟一只乌龟在窗口上爬行的方式来进行绘图

Version: 0.1
Author: 骆昊
Date: 2018-03-14

"""

import turtle

turtle.pensize(3)
turtle.penup()
turtle.goto(-180, 150)
turtle.pencolor('red')
turtle.fillcolor('yellow')
turtle.pendown()
turtle.begin_fill()
for _ in range(36):
	turtle.forward(200)
	turtle.right(170)
turtle.end_fill()
turtle.mainloop()


================================================
FILE: Day01-15/Day10/图形用户界面和游戏开发.md
================================================
## 图形用户界面和游戏开发

### 基于tkinter模块的GUI

GUI是图形用户界面的缩写,图形化的用户界面对使用过计算机的人来说应该都不陌生,在此也无需进行赘述。Python默认的GUI开发模块是tkinter(在Python 3以前的版本中名为Tkinter),从这个名字就可以看出它是基于Tk的,Tk是一个工具包,最初是为Tcl设计的,后来被移植到很多其他的脚本语言中,它提供了跨平台的GUI控件。当然Tk并不是最新和最好的选择,也没有功能特别强大的GUI控件,事实上,开发GUI应用并不是Python最擅长的工作,如果真的需要使用Python开发GUI应用,wxPython、PyQt、PyGTK等模块都是不错的选择。

基本上使用tkinter来开发GUI应用需要以下5个步骤:

1. 导入tkinter模块中我们需要的东西。
2. 创建一个顶层窗口对象并用它来承载整个GUI应用。
3. 在顶层窗口对象上添加GUI组件。
4. 通过代码将这些GUI组件的功能组织起来。
5. 进入主事件循环(main loop)。

下面的代码演示了如何使用tkinter做一个简单的GUI应用。

```Python
import tkinter
import tkinter.messagebox


def main():
	flag = True

	# 修改标签上的文字
	def change_label_text():
		nonlocal flag
		flag = not flag
		color, msg = ('red', 'Hello, world!')\
			if flag else ('blue', 'Goodbye, world!')
		label.config(text=msg, fg=color)

	# 确认退出
	def confirm_to_quit():
		if tkinter.messagebox.askokcancel('温馨提示', '确定要退出吗?'):
			top.quit()

	# 创建顶层窗口
	top = tkinter.Tk()
	# 设置窗口大小
	top.geometry('240x160')
	# 设置窗口标题
	top.title('小游戏')
	# 创建标签对象并添加到顶层窗口
	label = tkinter.Label(top, text='Hello, world!', font='Arial -32', fg='red')
	label.pack(expand=1)
	# 创建一个装按钮的容器
	panel = tkinter.Frame(top)
	# 创建按钮对象 指定添加到哪个容器中 通过command参数绑定事件回调函数
	button1 = tkinter.Button(panel, text='修改', command=change_label_text)
	button1.pack(side='left')
	button2 = tkinter.Button(panel, text='退出', command=confirm_to_quit)
	button2.pack(side='right')
	panel.pack(side='bottom')
	# 开启主事件循环
	tkinter.mainloop()


if __name__ == '__main__':
	main()

```

需要说明的是,GUI应用通常是事件驱动式的,之所以要进入主事件循环就是要监听鼠标、键盘等各种事件的发生并执行对应的代码对事件进行处理,因为事件会持续的发生,所以需要这样的一个循环一直运行着等待下一个事件的发生。另一方面,Tk为控件的摆放提供了三种布局管理器,通过布局管理器可以对控件进行定位,这三种布局管理器分别是:Placer(开发者提供控件的大小和摆放位置)、Packer(自动将控件填充到合适的位置)和Grid(基于网格坐标来摆放控件),此处不进行赘述。

### 使用Pygame进行游戏开发

Pygame是一个开源的Python模块,专门用于多媒体应用(如电子游戏)的开发,其中包含对图像、声音、视频、事件、碰撞等的支持。Pygame建立在[SDL](https://zh.wikipedia.org/wiki/SDL)的基础上,SDL是一套跨平台的多媒体开发库,用C语言实现,被广泛的应用于游戏、模拟器、播放器等的开发。而Pygame让游戏开发者不再被底层语言束缚,可以更多的关注游戏的功能和逻辑。

下面我们来完成一个简单的小游戏,游戏的名字叫“大球吃小球”,当然完成这个游戏并不是重点,学会使用Pygame也不是重点,最重要的我们要在这个过程中体会如何使用前面讲解的面向对象程序设计,学会用这种编程思想去解决现实中的问题。

#### 制作游戏窗口

```Python
import pygame


def main():
	# 初始化导入的pygame中的模块
    pygame.init()
    # 初始化用于显示的窗口并设置窗口尺寸
    screen = pygame.display.set_mode((800, 600))
    # 设置当前窗口的标题
    pygame.display.set_caption('大球吃小球')
    running = True
    # 开启一个事件循环处理发生的事件
    while running:
    	# 从消息队列中获取事件并对事件进行处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False


if __name__ == '__main__':
    main()

```

#### 在窗口中绘图

可以通过pygame中draw模块的函数在窗口上绘图,可以绘制的图形包括:线条、矩形、多边形、圆、椭圆、圆弧等。需要说明的是,屏幕坐标系是将屏幕左上角设置为坐标原点`(0, 0)`,向右是x轴的正向,向下是y轴的正向,在表示位置或者设置尺寸的时候,我们默认的单位都是[像素](https://zh.wikipedia.org/wiki/%E5%83%8F%E7%B4%A0)。所谓像素就是屏幕上的一个点,你可以用浏览图片的软件试着将一张图片放大若干倍,就可以看到这些点。pygame中表示颜色用的是色光[三原色](https://zh.wikipedia.org/wiki/%E5%8E%9F%E8%89%B2)表示法,即通过一个元组或列表来指定颜色的RGB值,每个值都在0~255之间,因为是每种原色都用一个8位(bit)的值来表示,三种颜色相当于一共由24位构成,这也就是常说的“24位颜色表示法”。

```Python
import pygame


def main():
	# 初始化导入的pygame中的模块
    pygame.init()
    # 初始化用于显示的窗口并设置窗口尺寸
    screen = pygame.display.set_mode((800, 600))
    # 设置当前窗口的标题
    pygame.display.set_caption('大球吃小球')
    # 设置窗口的背景色(颜色是由红绿蓝三原色构成的元组)
    screen.fill((242, 242, 242))
    # 绘制一个圆(参数分别是: 屏幕, 颜色, 圆心位置, 半径, 0表示填充圆)
    pygame.draw.circle(screen, (255, 0, 0,), (100, 100), 30, 0)
    # 刷新当前窗口(渲染窗口将绘制的图像呈现出来)
    pygame.display.flip()
    running = True
    # 开启一个事件循环处理发生的事件
    while running:
    	# 从消息队列中获取事件并对事件进行处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False


if __name__ == '__main__':
    main()

```

####加载图像

如果需要直接加载图像到窗口上,可以使用pygame中image模块的函数来加载图像,再通过之前获得的窗口对象的`blit`方法渲染图像,代码如下所示。

```Python
import pygame


def main():
    # 初始化导入的pygame中的模块
    pygame.init()
    # 初始化用于显示的窗口并设置窗口尺寸
    screen = pygame.display.set_mode((800, 600))
    # 设置当前窗口的标题
    pygame.display.set_caption('大球吃小球')
    # 设置窗口的背景色(颜色是由红绿蓝三原色构成的元组)
    screen.fill((255, 255, 255))
    # 通过指定的文件名加载图像
    ball_image = pygame.image.load('./res/ball.png')
    # 在窗口上渲染图像
    screen.blit(ball_image, (50, 50))
    # 刷新当前窗口(渲染窗口将绘制的图像呈现出来)
    pygame.display.flip()
    running = True
    # 开启一个事件循环处理发生的事件
    while running:
        # 从消息队列中获取事件并对事件进行处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False


if __name__ == '__main__':
    main()

```

####实现动画效果 

说到[动画](https://zh.wikipedia.org/wiki/%E5%8A%A8%E7%94%BB)这个词大家都不会陌生,事实上要实现动画效果,本身的原理也非常简单,就是将不连续的图片连续的播放,只要每秒钟达到了一定的帧数,那么就可以做出比较流畅的动画效果。如果要让上面代码中的小球动起来,可以将小球的位置用变量来表示,并在循环中修改小球的位置再刷新整个窗口即可。

```Python
import pygame


def main():
    # 初始化导入的pygame中的模块
    pygame.init()
    # 初始化用于显示的窗口并设置窗口尺寸
    screen = pygame.display.set_mode((800, 600))
    # 设置当前窗口的标题
    pygame.display.set_caption('大球吃小球')
    # 定义变量来表示小球在屏幕上的位置
    x, y = 50, 50
    running = True
    # 开启一个事件循环处理发生的事件
    while running:
        # 从消息队列中获取事件并对事件进行处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
        screen.fill((255, 255, 255))
        pygame.draw.circle(screen, (255, 0, 0,), (x, y), 30, 0)
        pygame.display.flip()
        # 每隔50毫秒就改变小球的位置再刷新窗口
        pygame.time.delay(50)
        x, y = x + 5, y + 5


if __name__ == '__main__':
    main()

```

#### 碰撞检测

通常一个游戏中会有很多对象出现,而这些对象之间的“碰撞”在所难免,比如炮弹击中了飞机、箱子撞到了地面等。碰撞检测在绝大多数的游戏中都是一个必须得处理的至关重要的问题,pygame的sprite(动画精灵)模块就提供了对碰撞检测的支持,这里我们暂时不介绍sprite模块提供的功能,因为要检测两个小球有没有碰撞其实非常简单,只需要检查球心的距离有没有小于两个球的半径之和。为了制造出更多的小球,我们可以通过对鼠标事件的处理,在点击鼠标的位置创建颜色、大小和移动速度都随机的小球,当然要做到这一点,我们可以把之前学习到的面向对象的知识应用起来。

```Python
from enum import Enum, unique
from math import sqrt
from random import randint

import pygame


@unique
class Color(Enum):
    """颜色"""

    RED = (255, 0, 0)
    GREEN = (0, 255, 0)
    BLUE = (0, 0, 255)
    BLACK = (0, 0, 0)
    WHITE = (255, 255, 255)
    GRAY = (242, 242, 242)

    @staticmethod
    def random_color():
        """获得随机颜色"""
        r = randint(0, 255)
        g = randint(0, 255)
        b = randint(0, 255)
        return (r, g, b)


class Ball(object):
    """球"""

    def __init__(self, x, y, radius, sx, sy, color=Color.RED):
        """初始化方法"""
        self.x = x
        self.y = y
        self.radius = radius
        self.sx = sx
        self.sy = sy
        self.color = color
        self.alive = True

    def move(self, screen):
        """移动"""
        self.x += self.sx
        self.y += self.sy
        if self.x - self.radius <= 0 or \
                self.x + self.radius >= screen.get_width():
            self.sx = -self.sx
        if self.y - self.radius <= 0 or \
                self.y + self.radius >= screen.get_height():
            self.sy = -self.sy

    def eat(self, other):
        """吃其他球"""
        if self.alive and other.alive and self != other:
            dx, dy = self.x - other.x, self.y - other.y
            distance = sqrt(dx ** 2 + dy ** 2)
            if distance < self.radius + other.radius \
                    and self.radius > other.radius:
                other.alive = False
               a self.radius = self.radius + int(other.radius * 0.146)

    def draw(self, screen):
        """在窗口上绘制球"""
        pygame.draw.circle(screen, self.color,
                           (self.x, self.y), self.radius, 0)

```

#### 事件处理

可以在事件循环中对鼠标事件进行处理,通过事件对象的`type`属性可以判定事件类型,再通过`pos`属性就可以获得鼠标点击的位置。如果要处理键盘事件也是在这个地方,做法与处理鼠标事件类似。

```Python
def main():
    # 定义用来装所有球的容器
    balls = []
    # 初始化导入的pygame中的模块
    pygame.init()
    # 初始化用于显示的窗口并设置窗口尺寸
    screen = pygame.display.set_mode((800, 600))
    # 设置当前窗口的标题
    pygame.display.set_caption('大球吃小球')
    running = True
    # 开启一个事件循环处理发生的事件
    while running:
        # 从消息队列中获取事件并对事件进行处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            # 处理鼠标事件的代码
            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                # 获得点击鼠标的位置
                x, y = event.pos
                radius = randint(10, 100)
                sx, sy = randint(-10, 10), randint(-10, 10)
                color = Color.random_color()
                # 在点击鼠标的位置创建一个球(大小、速度和颜色随机)
                ball = Ball(x, y, radius, sx, sy, color)
                # 将球添加到列表容器中
                balls.append(ball)
        screen.fill((255, 255, 255))
        # 取出容器中的球 如果没被吃掉就绘制 被吃掉了就移除
        for ball in balls:
            if ball.alive:
                ball.draw(screen)
            else:
                balls.remove(ball)
        pygame.display.flip()
        # 每隔50毫秒就改变球的位置再刷新窗口
        pygame.time.delay(50)
        for ball in balls:
            ball.move(screen)
            # 检查球有没有吃到其他的球
            for other in balls:
                ball.eat(other)


if __name__ == '__main__':
    main()

```

上面的两段代码合在一起,我们就完成了“大球吃小球”的游戏(如下图所示),准确的说它算不上一个游戏,但是做一个小游戏的基本知识我们已经通过这个例子告诉大家了,有了这些知识已经可以开始你的小游戏开发之旅了。其实上面的代码中还有很多值得改进的地方,比如刷新窗口以及让球移动起来的代码并不应该放在事件循环中,等学习了多线程的知识后,用一个后台线程来处理这些事可能是更好的选择。如果希望获得更好的用户体验,我们还可以在游戏中加入背景音乐以及在球与球发生碰撞时播放音效,利用pygame的mixer和music模块,我们可以很容易的做到这一点,大家可以自行了解这方面的知识。事实上,想了解更多的关于pygame的知识,最好的教程是[pygame的官方网站](https://www.pygame.org/news),如果英语没毛病就可以赶紧去看看啦。 如果想开发[3D游戏](https://zh.wikipedia.org/wiki/3D%E6%B8%B8%E6%88%8F),pygame就显得力不从心了,对3D游戏开发如果有兴趣的读者不妨看看[Panda3D](https://www.panda3d.org/)。





================================================
FILE: Day01-15/Day11/.py
================================================


================================================
FILE: Day01-15/Day11/csv1.py
================================================
"""

读取CSV文件

Version: 0.1
Author: 骆昊
Date: 2018-03-13

"""

import csv

filename = 'example.csv'

try:
	with open(filename) as f:
		reader = csv.reader(f)
		data = list(reader)
except FileNotFoundError:
	print('无法打开文件:', filename)
else:
	for item in data:
		print('%-30s%-20s%-10s' % (item[0], item[1], item[2]))


================================================
FILE: Day01-15/Day11/csv2.py
================================================
"""

写入CSV文件

Version: 0.1
Author: 骆昊
Date: 2018-03-13

"""

import csv


class Teacher(object):

	def __init__(self, name, age, title):
		self.__name = name
		self.__age = age
		self.__title = title
		self.__index = -1

	@property
	def name(self):
		return self.__name

	@property
	def age(self):
		return self.__age

	@property
	def title(self):
		return self.__title


filename = 'teacher.csv'
teachers = [Teacher('骆昊', 38, '叫兽'), Teacher('狄仁杰', 25, '砖家')]

try:
	with open(filename, 'w') as f:
		writer = csv.writer(f)
		for teacher in teachers:
			writer.writerow([teacher.name, teacher.age, teacher.title])
except BaseException as e:
	print('无法写入文件:', filename)
else:
	print('保存数据完成!')


================================================
FILE: Day01-15/Day11/ex1.py
================================================
"""

异常机制 - 处理程序在运行时可能发生的状态

Version: 0.1
Author: 骆昊
Date: 2018-03-13

"""

input_again = True
while input_again:
	try:
		a = int(input('a = '))
		b = int(input('b = '))
		print('%d / %d = %f' % (a, b, a / b))
		input_again = False
	except ValueError:
		print('请输入整数')
	except ZeroDivisionError:
		print('除数不能为0')
# 处理异常让代码不因异常而崩溃是一方面
# 更重要的是可以通过对异常的处理让代码从异常中恢复过来


================================================
FILE: Day01-15/Day11/ex2.py
================================================
"""

异常机制 - 处理程序在运行时可能发生的状态

Version: 0.1
Author: 骆昊
Date: 2018-03-13

"""

input_again = True
while input_again:
	try:
		a = int(input('a = '))
		b = int(input('b = '))
		print('%d / %d = %f' % (a, b, a / b))
		input_again = False
	except (ValueError, ZeroDivisionError) as msg:
		print(msg)


================================================
FILE: Day01-15/Day11/ex3.py
================================================
"""

异常机制 - 处理程序在运行时可能发生的状态

Version: 0.1
Author: 骆昊
Date: 2018-03-13

"""

import time
import sys

filename = input('请输入文件名: ')
try:
	with open(filename) as f:
		lines = f.readlines()
except FileNotFoundError as msg:
	print('无法打开文件:', filename)
	print(msg)
except UnicodeDecodeError as msg:
	print('非文本文件无法解码')
	sys.exit()
else:
	for line in lines:
		print(line.rstrip())
		time.sleep(0.5)
finally:
	# 此处最适合做善后工作
	print('不管发生什么我都会执行')


================================================
FILE: Day01-15/Day11/ex4.py
================================================
"""

引发异常和异常栈

Version: 0.1
Author: 骆昊
Date: 2018-03-13

"""


def f1():
	raise AssertionError('发生异常')


def f2():
	f1()


def f3():
	f2()


f3()


================================================
FILE: Day01-15/Day11/example.csv
================================================
4/5/2014 13:34,Apples,73
4/5/2014 3:41,Cherries,85
4/6/2014 12:46,Pears,14
4/8/2014 8:59,Oranges,52
4/10/2014 2:07,Apples,152
4/10/2014 18:10,Bananas,23
4/10/2014 2:40,Strawberries,98


================================================
FILE: Day01-15/Day11/file1.py
================================================
"""

从文本文件中读取数据

Version: 0.1
Author: 骆昊
Date: 2018-03-13

"""

import time


def main():
	# 一次性读取整个文件内容
	with open('致橡树.txt', 'r', encoding='utf-8') as f:
		print(f.read())

	# 通过for-in循环逐行读取
	with open('致橡树.txt', mode='r') as f:
		for line in f:
			print(line, end='')
			time.sleep(0.5)
	print()

	# 读取文件按行读取到列表中
	with open('致橡树.txt') as f:
		lines = f.readlines()
	print(lines)
	

if __name__ == '__main__':
	main()


================================================
FILE: Day01-15/Day11/file2.py
================================================
"""

读取圆周率文件判断其中是否包含自己的生日

Version: 0.1
Author: 骆昊
Date: 2018-03-13

"""

birth = input('请输入你的生日: ')
with open('pi_million_digits.txt') as f:
	lines = f.readlines()
	pi_string = ''
	for line in lines:
		pi_string += line.strip()
	if birth in pi_string:
		print('Bingo!!!')


================================================
FILE: Day01-15/Day11/file3.py
================================================
"""

写文本文件
将100以内的素数写入到文件中

Version: 0.1
Author: 骆昊
Date: 2018-03-13

"""

from math import sqrt


def is_prime(n):
	for factor in range(2, int(sqrt(n)) + 1):
		if n % factor == 0:
			return False
	return True


# 试一试有什么不一样
# with open('prime.txt', 'a') as f:
with open('prime.txt', 'w') as f:
	for num in range(2, 100):
		if is_prime(num):
			f.write(str(num) + '\n')
print('写入完成!')


================================================
FILE: Day01-15/Day11/file4.py
================================================
"""

读写二进制文件

Version: 0.1
Author: 骆昊
Date: 2018-03-13

"""

import base64

with open('mm.jpg', 'rb') as f:
	data = f.read()
	# print(type(data))
	# print(data)
	print('字节数:', len(data))
	# 将图片处理成BASE-64编码
	print(base64.b64encode(data))

with open('girl.jpg', 'wb') as f:
	f.write(data)
print('写入完成!')


================================================
FILE: Day01-15/Day11/json1.py
================================================
"""

读取JSON数据

Version: 0.1
Author: 骆昊
Date: 2018-03-13

"""

import json
import csv2

json_str = '{"name": "骆昊", "age": 38, "title": "叫兽"}'
result = json.loads(json_str)
print(result)
print(type(result))
print(result['name'])
print(result['age'])

# 把转换得到的字典作为关键字参数传入Teacher的构造器
teacher = csv2.Teacher(**result)
print(teacher)
print(teacher.name)
print(teacher.age)
print(teacher.title)

# 请思考如何将下面JSON格式的天气数据转换成对象并获取我们需要的信息
# 稍后我们会讲解如何通过网络API获取我们需要的JSON格式的数据
"""
	{
		"wendu": "29",
		"ganmao": "各项气象条件适宜,发生感冒机率较低。但请避免长期处于空调房间中,以防感冒。",
		"forecast": [
			{
				"fengxiang": "南风",
				"fengli": "3-4级",
				"high": "高温 32℃",
				"type": "多云",
				"low": "低温 17℃",
				"date": "16日星期二"
			},
			{
				"fengxiang": "南风",
				"fengli": "微风级",
				"high": "高温 34℃",
				"type": "晴",
				"low": "低温 19℃",
				"date": "17日星期三"
			},
			{
				"fengxiang": "南风",
				"fengli": "微风级",
				"high": "高温 35℃",
				"type": "晴",
				"low": "低温 22℃",
				"date": "18日星期四"
			},
			{
				"fengxiang": "南风",
				"fengli": "微风级",
				"high": "高温 35℃",
				"type": "多云",
				"low": "低温 22℃",
				"date": "19日星期五"
			},
			{
				"fengxiang": "南风",
				"fengli": "3-4级",
				"high": "高温 34℃",
				"type": "晴",
				"low": "低温 21℃",
				"date": "20日星期六"
			}
		],
		"yesterday": {
			"fl": "微风",
			"fx": "南风",
			"high": "高温 28℃",
			"type": "晴",
			"low": "低温 15℃",
			"date": "15日星期一"
		},
		"aqi": "72",
		"city": "北京"
	}
"""


================================================
FILE: Day01-15/Day11/json2.py
================================================
"""

写入JSON文件

Version: 0.1
Author: 骆昊
Date: 2018-03-13

"""

import json

teacher_dict = {'name': '白元芳', 'age': 25, 'title': '讲师'}
json_str = json.dumps(teacher_dict)
print(json_str)
print(type(json_str))
fruits_list = ['apple', 'orange', 'strawberry', 'banana', 'pitaya']
json_str = json.dumps(fruits_list)
print(json_str)
print(type(json_str))


================================================
FILE: Day01-15/Day11/pi_million_digits.txt
================================================
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
  8214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196
  4428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273
  7245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094
  3305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912
  9833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132
  0005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235
  4201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859
  5024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303
  5982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989
  3809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151
  5574857242454150695950829533116861727855889075098381754637464939319255060400927701671139009848824012
  8583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912
  9331367702898915210475216205696602405803815019351125338243003558764024749647326391419927260426992279
  6782354781636009341721641219924586315030286182974555706749838505494588586926995690927210797509302955
  3211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000
  8164706001614524919217321721477235014144197356854816136115735255213347574184946843852332390739414333
  4547762416862518983569485562099219222184272550254256887671790494601653466804988627232791786085784383
  8279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863
  0674427862203919494504712371378696095636437191728746776465757396241389086583264599581339047802759009
  9465764078951269468398352595709825822620522489407726719478268482601476990902640136394437455305068203
  4962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382
  6868386894277415599185592524595395943104997252468084598727364469584865383673622262609912460805124388
  4390451244136549762780797715691435997700129616089441694868555848406353422072225828488648158456028506
  0168427394522674676788952521385225499546667278239864565961163548862305774564980355936345681743241125
  1507606947945109659609402522887971089314566913686722874894056010150330861792868092087476091782493858
  9009714909675985261365549781893129784821682998948722658804857564014270477555132379641451523746234364
  5428584447952658678210511413547357395231134271661021359695362314429524849371871101457654035902799344
  0374200731057853906219838744780847848968332144571386875194350643021845319104848100537061468067491927
  8191197939952061419663428754440643745123718192179998391015919561814675142691239748940907186494231961
  5679452080951465502252316038819301420937621378559566389377870830390697920773467221825625996615014215
  0306803844773454920260541466592520149744285073251866600213243408819071048633173464965145390579626856
  1005508106658796998163574736384052571459102897064140110971206280439039759515677157700420337869936007
  2305587631763594218731251471205329281918261861258673215791984148488291644706095752706957220917567116
  7229109816909152801735067127485832228718352093539657251210835791513698820914442100675103346711031412
  6711136990865851639831501970165151168517143765761835155650884909989859982387345528331635507647918535
  8932261854896321329330898570642046752590709154814165498594616371802709819943099244889575712828905923
  2332609729971208443357326548938239119325974636673058360414281388303203824903758985243744170291327656
  1809377344403070746921120191302033038019762110110044929321516084244485963766983895228684783123552658
  2131449576857262433441893039686426243410773226978028073189154411010446823252716201052652272111660396
  6655730925471105578537634668206531098965269186205647693125705863566201855810072936065987648611791045
  3348850346113657686753249441668039626579787718556084552965412665408530614344431858676975145661406800
  7002378776591344017127494704205622305389945613140711270004078547332699390814546646458807972708266830
  6343285878569830523580893306575740679545716377525420211495576158140025012622859413021647155097925923
  0990796547376125517656751357517829666454779174501129961489030463994713296210734043751895735961458901
  9389713111790429782856475032031986915140287080859904801094121472213179476477726224142548545403321571
  8530614228813758504306332175182979866223717215916077166925474873898665494945011465406284336639379003
  9769265672146385306736096571209180763832716641627488880078692560290228472104031721186082041900042296
  6171196377921337575114959501566049631862947265473642523081770367515906735023507283540567040386743513
  6222247715891504953098444893330963408780769325993978054193414473774418426312986080998886874132604721
  5695162396586457302163159819319516735381297416772947867242292465436680098067692823828068996400482435
  4037014163149658979409243237896907069779422362508221688957383798623001593776471651228935786015881617
  5578297352334460428151262720373431465319777741603199066554187639792933441952154134189948544473456738
  3162499341913181480927777103863877343177207545654532207770921201905166096280490926360197598828161332
  3166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267
  9456127531813407833033625423278394497538243720583531147711992606381334677687969597030983391307710987
  0408591337464144282277263465947047458784778720192771528073176790770715721344473060570073349243693113
  8350493163128404251219256517980694113528013147013047816437885185290928545201165839341965621349143415
  9562586586557055269049652098580338507224264829397285847831630577775606888764462482468579260395352773
  4803048029005876075825104747091643961362676044925627420420832085661190625454337213153595845068772460
  2901618766795240616342522577195429162991930645537799140373404328752628889639958794757291746426357455
  2540790914513571113694109119393251910760208252026187985318877058429725916778131496990090192116971737
  2784768472686084900337702424291651300500516832336435038951702989392233451722013812806965011784408745
  1960121228599371623130171144484640903890644954440061986907548516026327505298349187407866808818338510
  2283345085048608250393021332197155184306354550076682829493041377655279397517546139539846833936383047
  4611996653858153842056853386218672523340283087112328278921250771262946322956398989893582116745627010
  2183564622013496715188190973038119800497340723961036854066431939509790190699639552453005450580685501
  9567302292191393391856803449039820595510022635353619204199474553859381023439554495977837790237421617
  2711172364343543947822181852862408514006660443325888569867054315470696574745855033232334210730154594
  0516553790686627333799585115625784322988273723198987571415957811196358330059408730681216028764962867
  4460477464915995054973742562690104903778198683593814657412680492564879855614537234786733039046883834
  3634655379498641927056387293174872332083760112302991136793862708943879936201629515413371424892830722
  0126901475466847653576164773794675200490757155527819653621323926406160136358155907422020203187277605
  2772190055614842555187925303435139844253223415762336106425063904975008656271095359194658975141310348
  2276930624743536325691607815478181152843667957061108615331504452127473924544945423682886061340841486
  3776700961207151249140430272538607648236341433462351897576645216413767969031495019108575984423919862
  9164219399490723623464684411739403265918404437805133389452574239950829659122850855582157250310712570
  1266830240292952522011872676756220415420516184163484756516999811614101002996078386909291603028840026
  9104140792886215078424516709087000699282120660418371806535567252532567532861291042487761825829765157
  9598470356222629348600341587229805349896502262917487882027342092222453398562647669149055628425039127
  5771028402799806636582548892648802545661017296702664076559042909945681506526530537182941270336931378
  5178609040708667114965583434347693385781711386455873678123014587687126603489139095620099393610310291
  6161528813843790990423174733639480457593149314052976347574811935670911013775172100803155902485309066
  9203767192203322909433467685142214477379393751703443661991040337511173547191855046449026365512816228
  8244625759163330391072253837421821408835086573917715096828874782656995995744906617583441375223970968
  3408005355984917541738188399944697486762655165827658483588453142775687900290951702835297163445621296
  4043523117600665101241200659755851276178583829204197484423608007193045761893234922927965019875187212
  7267507981255470958904556357921221033346697499235630254947802490114195212382815309114079073860251522
  7429958180724716259166854513331239480494707911915326734302824418604142636395480004480026704962482017
  9289647669758318327131425170296923488962766844032326092752496035799646925650493681836090032380929345
  9588970695365349406034021665443755890045632882250545255640564482465151875471196218443965825337543885
  6909411303150952617937800297412076651479394259029896959469955657612186561967337862362561252163208628
  6922210327488921865436480229678070576561514463204692790682120738837781423356282360896320806822246801
  2248261177185896381409183903673672220888321513755600372798394004152970028783076670944474560134556417
  2543709069793961225714298946715435784687886144458123145935719849225284716050492212424701412147805734
  5510500801908699603302763478708108175450119307141223390866393833952942578690507643100638351983438934
  1596131854347546495569781038293
Download .txt
gitextract_l08lgnd9/

├── .gitignore
├── Day01-15/
│   ├── Day01/
│   │   ├── hello.py
│   │   ├── peppa_pig.py
│   │   └── 初识Python.md
│   ├── Day02/
│   │   ├── centigrade.py
│   │   ├── circle.py
│   │   ├── leap.py
│   │   ├── operator.py
│   │   ├── string.py
│   │   ├── variable1.py
│   │   ├── variable2.py
│   │   ├── variable3.py
│   │   ├── variable4.py
│   │   ├── variable5.py
│   │   └── 语言元素.md
│   ├── Day03/
│   │   ├── .py
│   │   ├── convert.py
│   │   ├── grade.py
│   │   ├── piecewise.py
│   │   ├── rolldice.py
│   │   ├── tax.py
│   │   ├── triangle.py
│   │   ├── verify.py
│   │   └── 分支结构.md
│   ├── Day04/
│   │   ├── for1.py
│   │   ├── for2.py
│   │   ├── for3.py
│   │   ├── for4.py
│   │   ├── for5.py
│   │   ├── for6.py
│   │   ├── while1.py
│   │   ├── while2.py
│   │   └── 循环结构.md
│   ├── Day05/
│   │   ├── chicken.py
│   │   ├── craps.py
│   │   ├── fibonacci.py
│   │   ├── guess.py
│   │   ├── lily.py
│   │   ├── palindrome.py
│   │   ├── perfect.py
│   │   ├── prime.py
│   │   ├── table.py
│   │   └── 总结和练习.md
│   ├── Day06/
│   │   ├── function1.py
│   │   ├── function2.py
│   │   ├── function3.py
│   │   ├── function4.py
│   │   ├── function5.py
│   │   ├── function6.py
│   │   └── 函数和模块的使用.md
│   ├── Day07/
│   │   ├── avgscore.py
│   │   ├── dict1.py
│   │   ├── dict2.py
│   │   ├── fibonacci.py
│   │   ├── findmax.py
│   │   ├── list1.py
│   │   ├── list2.py
│   │   ├── list3.py
│   │   ├── lottery.py
│   │   ├── marquee.py
│   │   ├── scoretable.py
│   │   ├── set1.py
│   │   ├── set2.py
│   │   ├── tic-tac-toe.py
│   │   ├── tuple.py
│   │   ├── yanghui.py
│   │   └── 字符串和常用数据结构.md
│   ├── Day08/
│   │   ├── access.py
│   │   ├── circle.py
│   │   ├── clock.py
│   │   ├── guess.py
│   │   ├── hack.py
│   │   ├── rect.py
│   │   ├── student.py
│   │   ├── test.py
│   │   └── 面向对象编程基础.md
│   ├── Day09/
│   │   ├── association.py
│   │   ├── car1.py
│   │   ├── car2.py
│   │   ├── clock.py
│   │   ├── dependency.py
│   │   ├── diamond.py
│   │   ├── employee.py
│   │   ├── multi.py
│   │   ├── pet.py
│   │   ├── rational.py
│   │   ├── res/
│   │   │   └── uml-example.gliffy
│   │   ├── shape.py
│   │   ├── triangle.py
│   │   └── 面向对象进阶.md
│   ├── Day10/
│   │   ├── ball.py
│   │   ├── gui1.py
│   │   ├── gui2.py
│   │   ├── gui3.py
│   │   ├── turtle1.py
│   │   └── 图形用户界面和游戏开发.md
│   ├── Day11/
│   │   ├── .py
│   │   ├── csv1.py
│   │   ├── csv2.py
│   │   ├── ex1.py
│   │   ├── ex2.py
│   │   ├── ex3.py
│   │   ├── ex4.py
│   │   ├── example.csv
│   │   ├── file1.py
│   │   ├── file2.py
│   │   ├── file3.py
│   │   ├── file4.py
│   │   ├── json1.py
│   │   ├── json2.py
│   │   ├── pi_million_digits.txt
│   │   ├── teacher.csv
│   │   ├── 文件和异常.md
│   │   └── 致橡树.txt
│   ├── Day12/
│   │   ├── str1.py
│   │   ├── str2.py
│   │   ├── test3.py
│   │   ├── test4.py
│   │   ├── test5.py
│   │   └── 字符串和正则表达式.md
│   ├── Day13/
│   │   ├── asyncio1.py
│   │   ├── asyncio2.py
│   │   ├── asyncio3.py
│   │   ├── coroutine1.py
│   │   ├── coroutine2.py
│   │   ├── generator1.py
│   │   ├── generator2.py
│   │   ├── multiprocess1.py
│   │   ├── multiprocess2.py
│   │   ├── multiprocess3.py
│   │   ├── multiprocess4.py
│   │   ├── multithread1.py
│   │   ├── multithread2.py
│   │   ├── multithread3.py
│   │   ├── multithread4.py
│   │   ├── multithread5.py
│   │   ├── multithread6.py
│   │   ├── singlethread1.py
│   │   ├── singlethread2.py
│   │   ├── test2.py
│   │   ├── test3.py
│   │   └── 进程和线程.md
│   ├── Day14/
│   │   ├── chatclient.py
│   │   ├── chatserver.py
│   │   ├── fileclient.py
│   │   ├── fileserver.py
│   │   ├── mmdownloader.py
│   │   ├── socket1.py
│   │   ├── socket2.py
│   │   ├── socket3.py
│   │   ├── socket4.py
│   │   ├── socket5.py
│   │   ├── timeclient.py
│   │   ├── timeserver.py
│   │   └── 网络编程入门.md
│   └── Day15/
│       └── 网络应用开发.md
├── Day16-20/
│   └── Python语言进阶.md
├── Day21-30/
│   ├── Web前端概述.md
│   ├── classical_layout.html
│   ├── example.html
│   ├── form.html
│   ├── form_and_table.html
│   ├── jquery3.html
│   └── qq_link.html
├── Day31-35/
│   └── 玩转Linux.md
├── Day36-40/
│   ├── NoSQL入门.md
│   └── 关系型数据库MySQL.md
├── Day41-55/
│   ├── Django2实战01.md
│   ├── Django2实战02.md
│   ├── Django2实战03.md
│   ├── Django2实战04.md
│   ├── Django2实战05.md
│   ├── Django2实战06.md
│   ├── Django2实战07.md
│   ├── Django2实战08.md
│   ├── Django2实战09.md
│   ├── Django2实战10.md
│   ├── Django2项目实战.md
│   ├── car/
│   │   ├── car/
│   │   │   ├── __init__.py
│   │   │   ├── settings.py
│   │   │   ├── urls.py
│   │   │   └── wsgi.py
│   │   ├── manage.py
│   │   ├── search/
│   │   │   ├── __init__.py
│   │   │   ├── admin.py
│   │   │   ├── apps.py
│   │   │   ├── migrations/
│   │   │   │   ├── 0001_initial.py
│   │   │   │   ├── 0002_auto_20180524_1420.py
│   │   │   │   └── __init__.py
│   │   │   ├── models.py
│   │   │   ├── tests.py
│   │   │   └── views.py
│   │   └── templates/
│   │       ├── add.html
│   │       ├── search.html
│   │       └── search2.html
│   ├── oa/
│   │   ├── hrs/
│   │   │   ├── __init__.py
│   │   │   ├── admin.py
│   │   │   ├── apps.py
│   │   │   ├── migrations/
│   │   │   │   ├── 0001_initial.py
│   │   │   │   ├── 0002_auto_20180523_0923.py
│   │   │   │   ├── 0003_auto_20180524_1646.py
│   │   │   │   └── __init__.py
│   │   │   ├── models.py
│   │   │   ├── tests.py
│   │   │   ├── urls.py
│   │   │   └── views.py
│   │   ├── manage.py
│   │   ├── oa/
│   │   │   ├── __init__.py
│   │   │   ├── settings.py
│   │   │   ├── urls.py
│   │   │   └── wsgi.py
│   │   └── templates/
│   │       ├── dept.html
│   │       ├── emp.html
│   │       └── index.html
│   ├── shop/
│   │   ├── cart/
│   │   │   ├── __init__.py
│   │   │   ├── admin.py
│   │   │   ├── apps.py
│   │   │   ├── migrations/
│   │   │   │   ├── 0001_initial.py
│   │   │   │   └── __init__.py
│   │   │   ├── models.py
│   │   │   ├── tests.py
│   │   │   └── views.py
│   │   ├── manage.py
│   │   ├── shop/
│   │   │   ├── __init__.py
│   │   │   ├── settings.py
│   │   │   ├── urls.py
│   │   │   └── wsgi.py
│   │   └── templates/
│   │       ├── cart.html
│   │       └── goods.html
│   └── shop_origin/
│       ├── cart/
│       │   ├── __init__.py
│       │   ├── admin.py
│       │   ├── apps.py
│       │   ├── migrations/
│       │   │   ├── 0001_initial.py
│       │   │   └── __init__.py
│       │   ├── models.py
│       │   ├── tests.py
│       │   └── views.py
│       ├── manage.py
│       ├── shop/
│       │   ├── __init__.py
│       │   ├── settings.py
│       │   ├── urls.py
│       │   └── wsgi.py
│       ├── shop_create_sql.sql
│       └── templates/
│           ├── cart.html
│           └── goods.html
├── Day56-65/
│   ├── Flask安装和入门.md
│   ├── Flask项目实战.md
│   ├── 使用Flask进行项目开发.md
│   ├── 数据库操作.md
│   ├── 模板的使用.md
│   └── 表单的处理.md
├── Day66-75/
│   ├── 01.网络爬虫和相关工具.md
│   ├── 02.数据采集和解析.md
│   ├── 03.存储数据.md
│   ├── 04.并发下载.md
│   ├── 05.解析动态内容.md
│   ├── 06.表单交互和验证码处理.md
│   ├── Scrapy爬虫框架入门.md
│   ├── Scrapy爬虫框架分布式实现.md
│   ├── Scrapy爬虫框架高级应用.md
│   └── code/
│       ├── asyncio01.py
│       ├── asyncio02.py
│       ├── coroutine01.py
│       ├── coroutine02.py
│       ├── douban/
│       │   ├── douban/
│       │   │   ├── __init__.py
│       │   │   ├── items.py
│       │   │   ├── middlewares.py
│       │   │   ├── pipelines.py
│       │   │   ├── settings.py
│       │   │   └── spiders/
│       │   │       ├── __init__.py
│       │   │       └── movie.py
│       │   └── scrapy.cfg
│       ├── example01.py
│       ├── example02.py
│       ├── example03.py
│       ├── example04.py
│       ├── example05.py
│       ├── example06.py
│       ├── example07.py
│       ├── example08.py
│       ├── example09.py
│       ├── example10.py
│       ├── example11.py
│       ├── example12.py
│       ├── generator01.py
│       ├── generator02.py
│       ├── image360/
│       │   ├── image360/
│       │   │   ├── __init__.py
│       │   │   ├── items.py
│       │   │   ├── middlewares.py
│       │   │   ├── pipelines.py
│       │   │   ├── settings.py
│       │   │   └── spiders/
│       │   │       ├── __init__.py
│       │   │       ├── image.py
│       │   │       └── taobao.py
│       │   └── scrapy.cfg
│       ├── main.py
│       ├── main_redis.py
│       └── myutils.py
├── Day76-90/
│   ├── 数据处理和可视化.md
│   └── 机器学习.md
├── Day91-100/
│   └── 团队项目开发.md
├── PEP 8风格指南.md
├── Python参考书籍.md
├── Python惯例.md
├── README.md
├── 玩转PyCharm(上).md
├── 用函数还是用复杂的表达式.md
└── 那些年我们踩过的那些坑.md
Download .txt
SYMBOL INDEX (471 symbols across 134 files)

FILE: Day01-15/Day01/peppa_pig.py
  function nose (line 4) | def nose(x,y):#鼻子
  function head (line 47) | def head(x,y):#头
  function ears (line 79) | def ears(x,y): #耳朵
  function eyes (line 105) | def eyes(x,y):#眼睛
  function cheek (line 151) | def cheek(x,y):#腮
  function mouth (line 162) | def mouth(x,y): #嘴
  function setting (line 172) | def setting():          #参数设置
  function main (line 181) | def main():

FILE: Day01-15/Day06/function1.py
  function factorial (line 13) | def factorial(n):

FILE: Day01-15/Day06/function2.py
  function gcd (line 12) | def gcd(x, y):
  function lcm (line 21) | def lcm(x, y):

FILE: Day01-15/Day06/function3.py
  function myfilter (line 17) | def myfilter(mystr):

FILE: Day01-15/Day06/function5.py
  function f1 (line 17) | def f1(a, b=5, c=10):
  function f2 (line 28) | def f2(*args):
  function f3 (line 41) | def f3(**kw):

FILE: Day01-15/Day06/function6.py
  function foo1 (line 13) | def foo1():
  function foo2 (line 24) | def foo2():
  function foo3 (line 31) | def foo3():
  function foo4 (line 40) | def foo4():

FILE: Day01-15/Day07/avgscore.py
  function main (line 12) | def main():

FILE: Day01-15/Day07/dict1.py
  function main (line 12) | def main():

FILE: Day01-15/Day07/dict2.py
  function main (line 12) | def main():

FILE: Day01-15/Day07/fibonacci.py
  function main (line 12) | def main():

FILE: Day01-15/Day07/findmax.py
  function main (line 12) | def main():

FILE: Day01-15/Day07/list1.py
  function main (line 15) | def main():

FILE: Day01-15/Day07/list2.py
  function main (line 19) | def main():

FILE: Day01-15/Day07/list3.py
  function fib (line 16) | def fib(n):
  function main (line 23) | def main():

FILE: Day01-15/Day07/lottery.py
  function display (line 14) | def display(balls):
  function random_select (line 25) | def random_select():
  function main (line 43) | def main():

FILE: Day01-15/Day07/marquee.py
  function main (line 15) | def main():

FILE: Day01-15/Day07/scoretable.py
  function main (line 12) | def main():

FILE: Day01-15/Day07/set1.py
  function main (line 12) | def main():

FILE: Day01-15/Day07/set2.py
  function main (line 17) | def main():

FILE: Day01-15/Day07/tic-tac-toe.py
  function print_board (line 15) | def print_board(board):
  function main (line 23) | def main():

FILE: Day01-15/Day07/tuple.py
  function main (line 12) | def main():

FILE: Day01-15/Day07/yanghui.py
  function main (line 19) | def main():

FILE: Day01-15/Day08/access.py
  class Test (line 1) | class Test:
    method __init__ (line 3) | def __init__(self, foo):
    method __bar (line 6) | def __bar(self):
  function main (line 11) | def main():

FILE: Day01-15/Day08/circle.py
  class Circle (line 17) | class Circle(object):
    method __init__ (line 19) | def __init__(self, radius):
    method radius (line 23) | def radius(self):
    method radius (line 27) | def radius(self, radius):
    method perimeter (line 31) | def perimeter(self):
    method area (line 35) | def area(self):

FILE: Day01-15/Day08/clock.py
  class Clock (line 15) | class Clock(object):
    method __init__ (line 20) | def __init__(self, **kw):
    method run (line 31) | def run(self):
    method show (line 42) | def show(self):

FILE: Day01-15/Day08/guess.py
  class GuessMachine (line 14) | class GuessMachine(object):
    method __init__ (line 16) | def __init__(self):
    method reset (line 21) | def reset(self):
    method guess (line 26) | def guess(self, your_answer):
    method counter (line 38) | def counter(self):
    method hint (line 42) | def hint(self):

FILE: Day01-15/Day08/hack.py
  function bar (line 12) | def bar(self, name):
  function foo (line 16) | def foo(self, course_name):
  function main (line 20) | def main():

FILE: Day01-15/Day08/rect.py
  class Rect (line 12) | class Rect(object):
    method __init__ (line 15) | def __init__(self, width=0, height=0):
    method perimeter (line 20) | def perimeter(self):
    method area (line 24) | def area(self):
    method __str__ (line 28) | def __str__(self):
    method __del__ (line 32) | def __del__(self):

FILE: Day01-15/Day08/student.py
  function _foo (line 12) | def _foo():
  class Student (line 16) | class Student(object):
    method __init__ (line 20) | def __init__(self, name, age):
    method study (line 24) | def study(self, course_name):
    method watch_av (line 29) | def watch_av(self):
  function main (line 36) | def main():

FILE: Day01-15/Day09/association.py
  class Point (line 14) | class Point(object):
    method __init__ (line 16) | def __init__(self, x=0, y=0):
    method move_to (line 20) | def move_to(self, x, y):
    method move_by (line 24) | def move_by(self, dx, dy):
    method distance_to (line 28) | def distance_to(self, other):
    method __str__ (line 33) | def __str__(self):
  class Line (line 37) | class Line(object):
    method __init__ (line 39) | def __init__(self, start=Point(0, 0), end=Point(0, 0)):
    method start (line 44) | def start(self):
    method start (line 48) | def start(self, start):
    method end (line 52) | def end(self):
    method end (line 56) | def end(self, end):
    method length (line 60) | def length(self):

FILE: Day01-15/Day09/car1.py
  class Car (line 14) | class Car(object):
    method __init__ (line 18) | def __init__(self, brand, max_speed):
    method brand (line 23) | def brand(self):
    method brand (line 27) | def brand(self, brand):
    method brand (line 31) | def brand(self):
    method max_speed (line 35) | def max_speed(self):
    method max_speed (line 39) | def max_speed(self, max_speed):
    method __str__ (line 44) | def __str__(self):

FILE: Day01-15/Day09/car2.py
  class Car (line 13) | class Car(object):
    method __init__ (line 15) | def __init__(self, brand, max_speed):
    method get_brand (line 19) | def get_brand(self):
    method set_brand (line 22) | def set_brand(self, brand):
    method get_max_speed (line 25) | def get_max_speed(self):
    method set_max_speed (line 28) | def set_max_speed(self, max_speed):
    method __str__ (line 33) | def __str__(self):

FILE: Day01-15/Day09/clock.py
  class Clock (line 4) | class Clock(object):
    method __init__ (line 7) | def __init__(self, hour=0, minute=0, second=0):
    method now (line 13) | def now(cls):
    method run (line 17) | def run(self):
    method show (line 29) | def show(self):
  function main (line 35) | def main():

FILE: Day01-15/Day09/dependency.py
  class Car (line 12) | class Car(object):
    method __init__ (line 14) | def __init__(self, brand, max_speed):
    method brand (line 20) | def brand(self):
    method accelerate (line 23) | def accelerate(self, delta):
    method brake (line 28) | def brake(self):
    method __str__ (line 31) | def __str__(self):
  class Student (line 35) | class Student(object):
    method __init__ (line 37) | def __init__(self, name, age):
    method name (line 42) | def name(self):
    method drive (line 46) | def drive(self, car):
    method study (line 55) | def study(self, course_name):
    method watch_av (line 58) | def watch_av(self):
    method __gt__ (line 65) | def __gt__(self, other):
    method __lt__ (line 69) | def __lt__(self, other):

FILE: Day01-15/Day09/diamond.py
  class A (line 14) | class A(object):
    method foo (line 16) | def foo(self):
  class B (line 20) | class B(A):
  class C (line 24) | class C(A):
    method foo (line 26) | def foo(self):
  class D (line 30) | class D(B, C):
  class E (line 34) | class E(D):
    method foo (line 36) | def foo(self):

FILE: Day01-15/Day09/employee.py
  class Employee (line 19) | class Employee(object, metaclass=ABCMeta):
    method __init__ (line 21) | def __init__(self, name):
    method name (line 25) | def name(self):
    method get_salary (line 29) | def get_salary(self):
  class Manager (line 33) | class Manager(Employee):
    method __init__ (line 36) | def __init__(self, name):
    method get_salary (line 40) | def get_salary(self):
  class Programmer (line 44) | class Programmer(Employee):
    method __init__ (line 46) | def __init__(self, name):
    method set_working_hour (line 49) | def set_working_hour(self, working_hour):
    method get_salary (line 52) | def get_salary(self):
  class Salesman (line 56) | class Salesman(Employee):
    method __init__ (line 58) | def __init__(self, name):
    method set_sales (line 61) | def set_sales(self, sales):
    method get_salary (line 64) | def get_salary(self):

FILE: Day01-15/Day09/multi.py
  class Father (line 14) | class Father(object):
    method __init__ (line 16) | def __init__(self, name):
    method gamble (line 19) | def gamble(self):
    method eat (line 22) | def eat(self):
  class Monk (line 26) | class Monk(object):
    method __init__ (line 28) | def __init__(self, name):
    method eat (line 31) | def eat(self):
    method chant (line 34) | def chant(self):
  class Musician (line 38) | class Musician(object):
    method __init__ (line 40) | def __init__(self, name):
    method eat (line 43) | def eat(self):
    method play_piano (line 46) | def play_piano(self):
  class Son (line 55) | class Son(Father, Monk, Musician):
    method __init__ (line 57) | def __init__(self, name):

FILE: Day01-15/Day09/pet.py
  class Pet (line 4) | class Pet(object, metaclass=ABCMeta):
    method __init__ (line 6) | def __init__(self, nickname):
    method make_voice (line 10) | def make_voice(self):
  class Dog (line 14) | class Dog(Pet):
    method make_voice (line 16) | def make_voice(self):
  class Cat (line 20) | class Cat(Pet):
    method make_voice (line 22) | def make_voice(self):
  function main (line 26) | def main():

FILE: Day01-15/Day09/rational.py
  class Rational (line 14) | class Rational(object):
    method __init__ (line 16) | def __init__(self, num, den=1):
    method simplify (line 23) | def simplify(self):
    method normalize (line 32) | def normalize(self):
    method __add__ (line 38) | def __add__(self, other):
    method __sub__ (line 43) | def __sub__(self, other):
    method __mul__ (line 48) | def __mul__(self, other):
    method __truediv__ (line 53) | def __truediv__(self, other):
    method __str__ (line 58) | def __str__(self):

FILE: Day01-15/Day09/shape.py
  class Shape (line 19) | class Shape(object, metaclass=ABCMeta):
    method perimeter (line 22) | def perimeter(self):
    method area (line 26) | def area(self):
  class Circle (line 30) | class Circle(Shape):
    method __init__ (line 32) | def __init__(self, radius):
    method perimeter (line 35) | def perimeter(self):
    method area (line 38) | def area(self):
    method __str__ (line 41) | def __str__(self):
  class Rect (line 45) | class Rect(Shape):
    method __init__ (line 47) | def __init__(self, width, height):
    method perimeter (line 51) | def perimeter(self):
    method area (line 54) | def area(self):
    method __str__ (line 57) | def __str__(self):

FILE: Day01-15/Day09/triangle.py
  class Triangle (line 14) | class Triangle(object):
    method __init__ (line 16) | def __init__(self, a, b, c):
    method is_valid (line 23) | def is_valid(a, b, c):
    method perimeter (line 27) | def perimeter(self):
    method area (line 31) | def area(self):

FILE: Day01-15/Day10/ball.py
  class Color (line 9) | class Color(Enum):
    method random_color (line 20) | def random_color():
  class Ball (line 28) | class Ball(object):
    method __init__ (line 31) | def __init__(self, x, y, radius, sx, sy, color=Color.RED):
    method move (line 41) | def move(self, screen):
    method eat (line 50) | def eat(self, other):
    method draw (line 60) | def draw(self, screen):
  function main (line 66) | def main():

FILE: Day01-15/Day10/gui1.py
  function main (line 19) | def main():

FILE: Day01-15/Day10/gui2.py
  function mouse_evt_handler (line 16) | def mouse_evt_handler(evt=None):

FILE: Day01-15/Day10/gui3.py
  function play_animation (line 17) | def play_animation():

FILE: Day01-15/Day11/csv2.py
  class Teacher (line 14) | class Teacher(object):
    method __init__ (line 16) | def __init__(self, name, age, title):
    method name (line 23) | def name(self):
    method age (line 27) | def age(self):
    method title (line 31) | def title(self):

FILE: Day01-15/Day11/ex4.py
  function f1 (line 12) | def f1():
  function f2 (line 16) | def f2():
  function f3 (line 20) | def f3():

FILE: Day01-15/Day11/file1.py
  function main (line 14) | def main():

FILE: Day01-15/Day11/file3.py
  function is_prime (line 15) | def is_prime(n):

FILE: Day01-15/Day12/str2.py
  function reverse_str1 (line 14) | def reverse_str1(str):
  function reverse_str2 (line 18) | def reverse_str2(str):
  function reverse_str3 (line 24) | def reverse_str3(str):
  function reverse_str4 (line 34) | def reverse_str4(str):
  function reverse_str5 (line 38) | def reverse_str5(str):

FILE: Day01-15/Day12/test3.py
  function main (line 14) | def main():

FILE: Day01-15/Day12/test4.py
  function main (line 4) | def main():

FILE: Day01-15/Day12/test5.py
  function main (line 4) | def main():

FILE: Day01-15/Day13/asyncio1.py
  function hello (line 17) | def hello():

FILE: Day01-15/Day13/asyncio2.py
  function hello (line 17) | async def hello():

FILE: Day01-15/Day13/asyncio3.py
  function wget (line 14) | async def wget(host):

FILE: Day01-15/Day13/coroutine1.py
  function build_deliver_man (line 15) | def build_deliver_man(man_id):
  function package_center (line 25) | def package_center(deliver_man, max_per_day):

FILE: Day01-15/Day13/coroutine2.py
  function build_deliver_man (line 15) | def build_deliver_man(man_id):
  function package_center (line 25) | def package_center(deliver_man, max_per_day):

FILE: Day01-15/Day13/generator2.py
  function fib (line 12) | def fib(num):

FILE: Day01-15/Day13/multiprocess1.py
  function sub_task (line 19) | def sub_task(string, q):
  function main (line 27) | def main():

FILE: Day01-15/Day13/multiprocess2.py
  function sub_task (line 15) | def sub_task(queue):

FILE: Day01-15/Day13/multiprocess3.py
  function main (line 14) | def main():

FILE: Day01-15/Day13/multiprocess4.py
  function main (line 4) | def main():

FILE: Day01-15/Day13/multithread1.py
  function download_task (line 17) | def download_task(filename):
  function shutdown_hook (line 25) | def shutdown_hook(start):
  function main (line 30) | def main():

FILE: Day01-15/Day13/multithread2.py
  function download_task (line 16) | def download_task(filename):
  function main (line 23) | def main():

FILE: Day01-15/Day13/multithread3.py
  class DownloadTask (line 16) | class DownloadTask(threading.Thread):
    method __init__ (line 18) | def __init__(self, filename):
    method run (line 22) | def run(self):
  function main (line 30) | def main():

FILE: Day01-15/Day13/multithread4.py
  function main (line 17) | def main():

FILE: Day01-15/Day13/multithread5.py
  class Account (line 15) | class Account(object):
    method __init__ (line 17) | def __init__(self):
    method deposit (line 21) | def deposit(self, money):
    method balance (line 33) | def balance(self):
  class AddMoneyThread (line 37) | class AddMoneyThread(Thread):
    method __init__ (line 39) | def __init__(self, account, money):
    method run (line 44) | def run(self):
  function main (line 48) | def main():

FILE: Day01-15/Day13/multithread6.py
  class Account (line 15) | class Account(object):
    method __init__ (line 17) | def __init__(self):
    method deposit (line 21) | def deposit(self, money):
    method balance (line 33) | def balance(self):

FILE: Day01-15/Day13/singlethread1.py
  function download_task (line 15) | def download_task(filename):
  function main (line 22) | def main():

FILE: Day01-15/Day13/singlethread2.py
  function download (line 16) | def download():
  function show_about (line 22) | def show_about():
  function main (line 26) | def main():

FILE: Day01-15/Day13/test2.py
  class Account (line 5) | class Account(object):
    method __init__ (line 7) | def __init__(self, balance=0):
    method balance (line 12) | def balance(self):
    method deposit (line 15) | def deposit(self, money):
  class AddMoneyThread (line 28) | class AddMoneyThread(Thread):
    method __init__ (line 30) | def __init__(self, account):
    method run (line 34) | def run(self):
  function main (line 38) | def main():

FILE: Day01-15/Day13/test3.py
  class Color (line 8) | class Color(object):
    method random_color (line 14) | def random_color():
  class Car (line 21) | class Car(object):
    method __init__ (line 23) | def __init__(self, x, y, color):
    method move (line 28) | def move(self):
    method draw (line 32) | def draw(self, screen):
  function main (line 37) | def main():

FILE: Day01-15/Day14/chatclient.py
  function main (line 5) | def main():

FILE: Day01-15/Day14/chatserver.py
  function main (line 5) | def main():

FILE: Day01-15/Day14/fileclient.py
  function main (line 6) | def main():

FILE: Day01-15/Day14/fileserver.py
  function main (line 7) | def main():

FILE: Day01-15/Day14/mmdownloader.py
  class DownloadHanlder (line 7) | class DownloadHanlder(Thread):
    method __init__ (line 9) | def __init__(self, url):
    method run (line 13) | def run(self):
  function main (line 20) | def main():

FILE: Day01-15/Day14/socket5.py
  class EchoRequestHandler (line 15) | class EchoRequestHandler(StreamRequestHandler):
    method handle (line 17) | def handle(self):

FILE: Day01-15/Day14/timeclient.py
  function main (line 4) | def main():

FILE: Day01-15/Day14/timeserver.py
  function main (line 5) | def main():

FILE: Day41-55/car/search/admin.py
  class CarRecordAdmin (line 6) | class CarRecordAdmin(admin.ModelAdmin):

FILE: Day41-55/car/search/apps.py
  class SearchConfig (line 4) | class SearchConfig(AppConfig):

FILE: Day41-55/car/search/migrations/0001_initial.py
  class Migration (line 8) | class Migration(migrations.Migration):

FILE: Day41-55/car/search/migrations/0002_auto_20180524_1420.py
  class Migration (line 8) | class Migration(migrations.Migration):

FILE: Day41-55/car/search/models.py
  class CarRecord (line 4) | class CarRecord(models.Model):
    method happen_date (line 12) | def happen_date(self):
    class Meta (line 20) | class Meta:

FILE: Day41-55/car/search/views.py
  class CarRecordEncoder (line 20) | class CarRecordEncoder(JSONEncoder):
    method default (line 22) | def default(self, o):
  function ajax_search (line 28) | def ajax_search(request):
  function search (line 56) | def search(request):
  class CarRecordForm (line 77) | class CarRecordForm(forms.ModelForm):
    class Meta (line 91) | class Meta:
  function add (line 96) | def add(request):

FILE: Day41-55/oa/hrs/admin.py
  class DeptAdmin (line 6) | class DeptAdmin(admin.ModelAdmin):
  class EmpAdmin (line 12) | class EmpAdmin(admin.ModelAdmin):

FILE: Day41-55/oa/hrs/apps.py
  class HrsConfig (line 4) | class HrsConfig(AppConfig):

FILE: Day41-55/oa/hrs/migrations/0001_initial.py
  class Migration (line 7) | class Migration(migrations.Migration):

FILE: Day41-55/oa/hrs/migrations/0002_auto_20180523_0923.py
  class Migration (line 6) | class Migration(migrations.Migration):

FILE: Day41-55/oa/hrs/migrations/0003_auto_20180524_1646.py
  class Migration (line 7) | class Migration(migrations.Migration):

FILE: Day41-55/oa/hrs/models.py
  class Dept (line 10) | class Dept(models.Model):
    method __str__ (line 16) | def __str__(self):
    class Meta (line 19) | class Meta:
  class Emp (line 23) | class Emp(models.Model):
    class Meta (line 33) | class Meta:

FILE: Day41-55/oa/hrs/views.py
  function index (line 10) | def index(request):
  function del_dept (line 17) | def del_dept(request, no='0'):
  function emps (line 30) | def emps(request, no='0'):
  function depts (line 45) | def depts(request):

FILE: Day41-55/shop/cart/admin.py
  class GoodsAdmin (line 6) | class GoodsAdmin(admin.ModelAdmin):

FILE: Day41-55/shop/cart/apps.py
  class CartConfig (line 4) | class CartConfig(AppConfig):

FILE: Day41-55/shop/cart/migrations/0001_initial.py
  class Migration (line 6) | class Migration(migrations.Migration):

FILE: Day41-55/shop/cart/models.py
  class Goods (line 4) | class Goods(models.Model):
    class Meta (line 12) | class Meta:

FILE: Day41-55/shop/cart/views.py
  function index (line 6) | def index(request):
  class CartItem (line 11) | class CartItem(object):
    method __init__ (line 14) | def __init__(self, goods, amount=1):
    method total (line 19) | def total(self):
  class ShoppingCart (line 23) | class ShoppingCart(object):
    method __init__ (line 26) | def __init__(self):
    method add_item (line 29) | def add_item(self, item):
    method remove_item (line 35) | def remove_item(self, id):
    method clear_all_items (line 39) | def clear_all_items(self):
    method cart_items (line 43) | def cart_items(self):
    method total (line 47) | def total(self):
  function add_to_cart (line 54) | def add_to_cart(request, id):
  function show_cart (line 73) | def show_cart(request):

FILE: Day41-55/shop_origin/cart/admin.py
  class GoodsAdmin (line 6) | class GoodsAdmin(admin.ModelAdmin):

FILE: Day41-55/shop_origin/cart/apps.py
  class CartConfig (line 4) | class CartConfig(AppConfig):

FILE: Day41-55/shop_origin/cart/migrations/0001_initial.py
  class Migration (line 6) | class Migration(migrations.Migration):

FILE: Day41-55/shop_origin/cart/models.py
  class Goods (line 4) | class Goods(models.Model):
    class Meta (line 11) | class Meta:

FILE: Day41-55/shop_origin/cart/views.py
  function index (line 6) | def index(request):
  function show_cart (line 11) | def show_cart(request):
  function add_to_cart (line 15) | def add_to_cart(request, no):

FILE: Day66-75/code/asyncio01.py
  function countdown (line 5) | def countdown(name, num):
  function main (line 12) | def main():

FILE: Day66-75/code/asyncio02.py
  function download (line 5) | async def download(url):
  function main (line 14) | def main():

FILE: Day66-75/code/coroutine01.py
  function countdown_gen (line 4) | def countdown_gen(n, consumer):
  function countdown_con (line 12) | def countdown_con():
  function main (line 22) | def main():

FILE: Day66-75/code/coroutine02.py
  function create_delivery_man (line 7) | def create_delivery_man(name, capacity=1):
  function create_package_center (line 24) | def create_package_center(consumer, max_packages):
  function main (line 35) | def main():

FILE: Day66-75/code/douban/douban/items.py
  class DoubanItem (line 11) | class DoubanItem(scrapy.Item):

FILE: Day66-75/code/douban/douban/middlewares.py
  class DoubanSpiderMiddleware (line 11) | class DoubanSpiderMiddleware(object):
    method from_crawler (line 17) | def from_crawler(cls, crawler):
    method process_spider_input (line 23) | def process_spider_input(self, response, spider):
    method process_spider_output (line 30) | def process_spider_output(self, response, result, spider):
    method process_spider_exception (line 38) | def process_spider_exception(self, response, exception, spider):
    method process_start_requests (line 46) | def process_start_requests(self, start_requests, spider):
    method spider_opened (line 55) | def spider_opened(self, spider):
  class DoubanDownloaderMiddleware (line 59) | class DoubanDownloaderMiddleware(object):
    method from_crawler (line 65) | def from_crawler(cls, crawler):
    method process_request (line 71) | def process_request(self, request, spider):
    method process_response (line 83) | def process_response(self, request, response, spider):
    method process_exception (line 92) | def process_exception(self, request, exception, spider):
    method spider_opened (line 102) | def spider_opened(self, spider):

FILE: Day66-75/code/douban/douban/pipelines.py
  class DoubanPipeline (line 14) | class DoubanPipeline(object):
    method __init__ (line 16) | def __init__(self):
    method process_item (line 21) | def process_item(self, item, spider):

FILE: Day66-75/code/douban/douban/spiders/movie.py
  class MovieSpider (line 10) | class MovieSpider(CrawlSpider):
    method parse_item (line 19) | def parse_item(self, response):

FILE: Day66-75/code/example01.py
  function decode_page (line 12) | def decode_page(page_bytes, charsets=('utf-8',)):
  function get_page_html (line 25) | def get_page_html(seed_url, *, retry_times=3, charsets=('utf-8',)):
  function get_matched_parts (line 38) | def get_matched_parts(page_html, pattern_str, pattern_ignore_case=re.I):
  function start_crawl (line 44) | def start_crawl(seed_url, match_pattern, *, max_depth=-1):
  function main (line 76) | def main():

FILE: Day66-75/code/example02.py
  function main (line 6) | def main():
  function foo (line 66) | def foo(elem):

FILE: Day66-75/code/example03.py
  function main (line 8) | def main():

FILE: Day66-75/code/example04.py
  function main (line 9) | def main():

FILE: Day66-75/code/example05.py
  function decode_page (line 18) | def decode_page(page_bytes, charsets=('utf-8',)):
  function get_page_html (line 31) | def get_page_html(seed_url, *, retry_times=3, charsets=('utf-8',)):
  function get_matched_parts (line 46) | def get_matched_parts(page_html, pattern_str, pattern_ignore_case=re.I):
  function start_crawl (line 52) | def start_crawl(seed_url, match_pattern, *, max_depth=-1):
  function main (line 75) | def main():

FILE: Day66-75/code/example06.py
  function main (line 14) | def main():

FILE: Day66-75/code/example07.py
  function main (line 5) | def main():

FILE: Day66-75/code/example08.py
  function main (line 5) | def main():

FILE: Day66-75/code/example09.py
  function main (line 4) | def main():

FILE: Day66-75/code/example10.py
  function main (line 4) | def main():

FILE: Day66-75/code/example11.py
  function main (line 6) | def main():

FILE: Day66-75/code/example12.py
  function main (line 10) | def main():

FILE: Day66-75/code/generator01.py
  function fib (line 1) | def fib():
  function even (line 8) | def even(gen):
  function main (line 14) | def main():

FILE: Day66-75/code/generator02.py
  function countdown (line 4) | def countdown(n):
  function main (line 10) | def main():

FILE: Day66-75/code/image360/image360/items.py
  class GoodsItem (line 11) | class GoodsItem(scrapy.Item):
  class BeautyItem (line 18) | class BeautyItem(scrapy.Item):

FILE: Day66-75/code/image360/image360/middlewares.py
  class Image360SpiderMiddleware (line 15) | class Image360SpiderMiddleware(object):
    method from_crawler (line 21) | def from_crawler(cls, crawler):
    method process_spider_input (line 27) | def process_spider_input(self, response, spider):
    method process_spider_output (line 34) | def process_spider_output(self, response, result, spider):
    method process_spider_exception (line 42) | def process_spider_exception(self, response, exception, spider):
    method process_start_requests (line 50) | def process_start_requests(self, start_requests, spider):
    method spider_opened (line 59) | def spider_opened(self, spider):
  class Image360DownloaderMiddleware (line 63) | class Image360DownloaderMiddleware(object):
    method from_crawler (line 69) | def from_crawler(cls, crawler):
    method process_request (line 75) | def process_request(self, request, spider):
    method process_response (line 87) | def process_response(self, request, response, spider):
    method process_exception (line 96) | def process_exception(self, request, exception, spider):
    method spider_opened (line 106) | def spider_opened(self, spider):
  class TaobaoDownloaderMiddleWare (line 110) | class TaobaoDownloaderMiddleWare(object):
    method __init__ (line 112) | def __init__(self, timeout=None):
    method __del__ (line 118) | def __del__(self):
    method process_request (line 121) | def process_request(self, request, spider):
    method process_response (line 129) | def process_response(self, request, response, spider):
    method process_exception (line 132) | def process_exception(self, request, exception, spider):
    method from_crawler (line 136) | def from_crawler(cls, crawler):

FILE: Day66-75/code/image360/image360/pipelines.py
  class SaveImagePipeline (line 18) | class SaveImagePipeline(ImagesPipeline):
    method get_media_requests (line 20) | def get_media_requests(self, item, info):
    method item_completed (line 23) | def item_completed(self, results, item, info):
    method file_path (line 29) | def file_path(self, request, response=None, info=None):
  class SaveToMongoPipeline (line 33) | class SaveToMongoPipeline(object):
    method __init__ (line 35) | def __init__(self, mongo_url, db_name):
    method process_item (line 41) | def process_item(self, item, spider):
    method open_spider (line 44) | def open_spider(self, spider):
    method close_spider (line 48) | def close_spider(self, spider):
    method from_crawler (line 52) | def from_crawler(cls, crawler):

FILE: Day66-75/code/image360/image360/spiders/image.py
  class ImageSpider (line 10) | class ImageSpider(scrapy.Spider):
    method start_requests (line 14) | def start_requests(self):
    method parse (line 22) | def parse(self, response):

FILE: Day66-75/code/image360/image360/spiders/taobao.py
  class TaobaoSpider (line 11) | class TaobaoSpider(scrapy.Spider):
    method start_requests (line 15) | def start_requests(self):
    method parse (line 25) | def parse(self, response):

FILE: Day66-75/code/main.py
  class SpiderStatus (line 13) | class SpiderStatus(Enum):
  function decode_page (line 18) | def decode_page(page_bytes, charsets=('utf-8',)):
  class Retry (line 29) | class Retry(object):
    method __init__ (line 31) | def __init__(self, *, retry_times=3,
    method __call__ (line 37) | def __call__(self, fn):
  class Spider (line 51) | class Spider(object):
    method __init__ (line 53) | def __init__(self):
    method fetch (line 57) | def fetch(self, current_url, *, charsets=('utf-8', ),
    method parse (line 67) | def parse(self, html_page, *, domain='m.sohu.com'):
    method extract (line 82) | def extract(self, html_page):
    method store (line 85) | def store(self, data_dict):
  class SpiderThread (line 89) | class SpiderThread(Thread):
    method __init__ (line 91) | def __init__(self, name, spider, tasks_queue):
    method run (line 96) | def run(self):
  function is_any_alive (line 109) | def is_any_alive(spider_threads):
  function main (line 117) | def main():

FILE: Day66-75/code/main_redis.py
  class SpiderStatus (line 18) | class SpiderStatus(Enum):
  function decode_page (line 23) | def decode_page(page_bytes, charsets=('utf-8',)):
  class Retry (line 34) | class Retry(object):
    method __init__ (line 36) | def __init__(self, *, retry_times=3,
    method __call__ (line 42) | def __call__(self, fn):
  class Spider (line 56) | class Spider(object):
    method __init__ (line 58) | def __init__(self):
    method fetch (line 62) | def fetch(self, current_url, *, charsets=('utf-8', ),
    method parse (line 72) | def parse(self, html_page, *, domain='m.sohu.com'):
    method extract (line 86) | def extract(self, html_page):
    method store (line 89) | def store(self, data_dict):
  class SpiderThread (line 95) | class SpiderThread(Thread):
    method __init__ (line 97) | def __init__(self, name, spider):
    method run (line 101) | def run(self):
  function is_any_alive (line 130) | def is_any_alive(spider_threads):
  function main (line 139) | def main():

FILE: Day66-75/code/myutils.py
  function coroutine (line 4) | def coroutine(fn):
Condensed preview — 308 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,585K chars).
[
  {
    "path": ".gitignore",
    "chars": 30,
    "preview": "venv\n.idea\n*.pyc\n__pycache__\n\n"
  },
  {
    "path": "Day01-15/Day01/hello.py",
    "chars": 293,
    "preview": "\"\"\"\n\n第一个Python程序 - hello, world!\n向伟大的Dennis M. Ritchie先生致敬\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-02-26\n\n请将该文件命名为hello.py并在"
  },
  {
    "path": "Day01-15/Day01/peppa_pig.py",
    "chars": 3273,
    "preview": "from turtle import*\n\n\ndef nose(x,y):#鼻子\n    penup()#提起笔\n    goto(x,y)#定位\n    pendown()#落笔,开始画\n    setheading(-30)#将乌龟的方向"
  },
  {
    "path": "Day01-15/Day01/初识Python.md",
    "chars": 7160,
    "preview": "## Day01 - 初识Python\n\n### Python简介\n\n#### Python的历史\n\n1. 1989年圣诞节:Guido von Rossum开始写Python语言的编译器。\n2. 1991年2月:第一个Python编译器("
  },
  {
    "path": "Day01-15/Day02/centigrade.py",
    "chars": 165,
    "preview": "\"\"\"\n\n将华氏温度转换为摄氏温度\nF = 1.8C + 32\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-02-27\n\n\"\"\"\n\nf = float(input('请输入华氏温度: '))\nc = (f - 3"
  },
  {
    "path": "Day01-15/Day02/circle.py",
    "chars": 236,
    "preview": "\"\"\"\n\n输入半径计算圆的周长和面积\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-02-27\n\n\"\"\"\n\nimport math\n\nradius = float(input('请输入圆的半径: '))\nperim"
  },
  {
    "path": "Day01-15/Day02/leap.py",
    "chars": 229,
    "preview": "\"\"\"\n\n输入年份 如果是闰年输出True 否则输出False\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-02-27\n\n\"\"\"\n\nyear = int(input('请输入年份: '))\n# 如果代码太长写成一"
  },
  {
    "path": "Day01-15/Day02/operator.py",
    "chars": 402,
    "preview": "\"\"\"\n\n运算符的使用\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-02-27\n\n\"\"\"\n\na = 5\nb = 10\nc = 3\nd = 4\ne = 5\na += b\na -= c\na *= d\na /= e\np"
  },
  {
    "path": "Day01-15/Day02/string.py",
    "chars": 505,
    "preview": "\"\"\"\n\n字符串常用操作\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-02-27\n\n\"\"\"\n\nstr1 = 'hello, world!'\nprint('字符串的长度是:', len(str1))\nprint('"
  },
  {
    "path": "Day01-15/Day02/variable1.py",
    "chars": 176,
    "preview": "\"\"\"\n\n使用变量保存数据并进行操作\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-02-27\n\n\"\"\"\n\na = 321\nb = 123\nprint(a + b)\nprint(a - b)\nprint(a * b"
  },
  {
    "path": "Day01-15/Day02/variable2.py",
    "chars": 217,
    "preview": "\"\"\"\n\n将input函数输入的数据保存在变量中并进行操作\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-02-27\n\n\"\"\"\n\na = int(input('a = '))\nb = int(input('b = "
  },
  {
    "path": "Day01-15/Day02/variable3.py",
    "chars": 376,
    "preview": "\"\"\"\n\n格式化输出\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-02-27\n\n\"\"\"\n\na = int(input('a = '))\nb = int(input('b = '))\nprint('%d + %d "
  },
  {
    "path": "Day01-15/Day02/variable4.py",
    "chars": 256,
    "preview": "\"\"\"\n\n检查变量的类型\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-02-27\n\n\"\"\"\n\na = 100\nb = 1000000000000000000\nc = 12.345\nd = 1 + 5j\ne = '"
  },
  {
    "path": "Day01-15/Day02/variable5.py",
    "chars": 480,
    "preview": "\"\"\"\n\n类型转换\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-02-27\n\n\"\"\"\n\na = 100\nb = str(a)\nc = 12.345\nd = str(c)\ne = '123'\nf = int(e)\n"
  },
  {
    "path": "Day01-15/Day02/语言元素.md",
    "chars": 6056,
    "preview": "## Day02 - 语言元素\n\n#### 指令和程序\n\n计算机的硬件系统通常由五大部件构成,包括:运算器、控制器、存储器、输入设备和输出设备。其中,运算器和控制器放在一起就是我们通常所说的中央处理器,它的功能是执行各种运算和控制指令以及处"
  },
  {
    "path": "Day01-15/Day03/.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "Day01-15/Day03/convert.py",
    "chars": 310,
    "preview": "\"\"\"\n\n英制单位英寸和公制单位厘米互换\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-02-28\n\n\"\"\"\n\nvalue = float(input('请输入长度: '))\nunit = input('请输入单位"
  },
  {
    "path": "Day01-15/Day03/grade.py",
    "chars": 333,
    "preview": "\"\"\"\n\n百分制成绩转等级制成绩\n90分以上 \t \t--> A\n80分~89分 \t--> B\n70分~79分\t--> C\n60分~69分\t--> D\n60分以下\t\t--> E\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2"
  },
  {
    "path": "Day01-15/Day03/piecewise.py",
    "chars": 252,
    "preview": "\"\"\"\n\n分段函数求值\n\t\t3x - 5\t(x > 1)\nf(x) =\tx + 2\t(-1 <= x <= 1)\n\t\t5x + 3\t(x < -1)\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-02-28\n\n\"\""
  },
  {
    "path": "Day01-15/Day03/rolldice.py",
    "chars": 310,
    "preview": "\"\"\"\n\n掷骰子决定做什么事情\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-02-28\n\n\"\"\"\n\nfrom random import randint\n\nface = randint(1, 6)\nif face"
  },
  {
    "path": "Day01-15/Day03/tax.py",
    "chars": 647,
    "preview": "\"\"\"\n\n输入月收入和五险一金计算个人所得税\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-02-28\n\n\"\"\"\n\nsalary = float(input('本月收入: '))\ninsurance = float"
  },
  {
    "path": "Day01-15/Day03/triangle.py",
    "chars": 368,
    "preview": "\"\"\"\n\n判断输入的边长能否构成三角形\n如果能则计算出三角形的周长和面积\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-02-28\n\n\"\"\"\n\nimport math\n\na = float(input('a = '"
  },
  {
    "path": "Day01-15/Day03/verify.py",
    "chars": 337,
    "preview": "\"\"\"\n\n用户身份验证\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-02-28\n\n\"\"\"\n\n# import getpass\n# from getpass import getpass\n# from getpas"
  },
  {
    "path": "Day01-15/Day03/分支结构.md",
    "chars": 4343,
    "preview": "## Day03 - 分支结构\n\n### 分支结构的应用场景\n\n迄今为止,我们写的Python代码都是一条一条语句顺序执行,这种结构的代码我们称之为顺序结构。然而仅有顺序结构并不能解决所有的问题,比如我们设计一个游戏,游戏第一关的通关条件是"
  },
  {
    "path": "Day01-15/Day04/for1.py",
    "chars": 139,
    "preview": "\"\"\"\n\n用for循环实现1~100求和\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-01\n\n\"\"\"\n\nsum = 0\nfor x in range(1, 101):\n\tif x % 2 == 0:\n\t\ts"
  },
  {
    "path": "Day01-15/Day04/for2.py",
    "chars": 130,
    "preview": "\"\"\"\n\n用for循环实现1~100之间的偶数求和\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-01\n\n\"\"\"\n\nsum = 0\nfor x in range(2, 101, 2):\n\tsum += x\np"
  },
  {
    "path": "Day01-15/Day04/for3.py",
    "chars": 170,
    "preview": "\"\"\"\n\n输入非负整数n计算n!\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-01\n\n\"\"\"\n\nn = int(input('n = '))\nresult = 1\nfor x in range(1, n +"
  },
  {
    "path": "Day01-15/Day04/for4.py",
    "chars": 310,
    "preview": "\"\"\"\n\n输入一个正整数判断它是不是素数\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-01\n\n\"\"\"\n\nfrom math import sqrt\n\nnum = int(input('请输入一个正整数: '"
  },
  {
    "path": "Day01-15/Day04/for5.py",
    "chars": 322,
    "preview": "\"\"\"\n\n输入两个正整数计算最大公约数和最小公倍数\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-01\n\n\"\"\"\n\nx = int(input('x = '))\ny = int(input('y = '))\n"
  },
  {
    "path": "Day01-15/Day04/for6.py",
    "chars": 586,
    "preview": "\"\"\"\n\n打印各种三角形图案\n\n*\n**\n***\n****\n*****\n\n    *\n   **\n  ***\n ****\n*****\n\n    *\n   ***\n  *****\n *******\n*********\n\nVersion: 0."
  },
  {
    "path": "Day01-15/Day04/while1.py",
    "chars": 138,
    "preview": "\"\"\"\n\n用while循环实现1~100求和\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-01\n\n\"\"\"\n\nsum = 0\nnum = 1\nwhile num <= 100:\n\tsum += num\n\tnu"
  },
  {
    "path": "Day01-15/Day04/while2.py",
    "chars": 143,
    "preview": "\"\"\"\n\n用while循环实现1~100之间的偶数求和\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-01\n\n\"\"\"\n\nsum = 0\nnum = 2\nwhile num <= 100:\n\tsum += nu"
  },
  {
    "path": "Day01-15/Day04/循环结构.md",
    "chars": 3577,
    "preview": "## Day04 - 循环结构\n\n### 循环结构的应用场景\n\n如果在程序中我们需要重复的执行某条或某些指令,例如用程序控制机器人踢足球,如果机器人持球而且还没有进入射门范围,那么我们就要一直发出让机器人向球门方向奔跑的指令。当然你可能已经"
  },
  {
    "path": "Day01-15/Day05/chicken.py",
    "chars": 282,
    "preview": "\"\"\"\n\n求解《百钱百鸡》问题\n1只公鸡5元 1只母鸡3元 3只小鸡1元 用100元买100只鸡\n问公鸡 母鸡 小鸡各有多少只\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-02\n\n\"\"\"\n\nfor x in"
  },
  {
    "path": "Day01-15/Day05/craps.py",
    "chars": 887,
    "preview": "\"\"\"\n\nCraps赌博游戏\n玩家摇两颗色子 如果第一次摇出7点或11点 玩家胜\n如果摇出2点 3点 12点 庄家胜 其他情况游戏继续\n玩家再次要色子 如果摇出7点 庄家胜\n如果摇出第一次摇的点数 玩家胜\n否则游戏继续 玩家继续摇色子\n玩家"
  },
  {
    "path": "Day01-15/Day05/fibonacci.py",
    "chars": 162,
    "preview": "\"\"\"\n\n输出斐波那契数列的前20个数\n1 1 2 3 5 8 13 21 ...\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-02\n\n\"\"\"\n\na = 0\nb = 1\nfor _ in range(20)"
  },
  {
    "path": "Day01-15/Day05/guess.py",
    "chars": 397,
    "preview": "\"\"\"\n\n猜数字游戏\n计算机出一个1~100之间的随机数由人来猜\n计算机根据人猜的数字分别给出提示大一点/小一点/猜对了\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-02\n\n\"\"\"\n\nimport rand"
  },
  {
    "path": "Day01-15/Day05/lily.py",
    "chars": 263,
    "preview": "\"\"\"\n\n找出100~999之间的所有水仙花数\n水仙花数是各位立方和等于这个数本身的数\n如: 153 = 1**3 + 5**3 + 3**3\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-02\n\n\"\"\"\n\n"
  },
  {
    "path": "Day01-15/Day05/palindrome.py",
    "chars": 278,
    "preview": "\"\"\"\n\n判断输入的正整数是不是回文数\n回文数是指将一个正整数从左往右排列和从右往左排列值一样的数\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-02\n\n\"\"\"\n\nnum = int(input('请输入一个"
  },
  {
    "path": "Day01-15/Day05/perfect.py",
    "chars": 502,
    "preview": "\"\"\"\n\n找出1~9999之间的所有完美数\n完美数是除自身外其他所有因子的和正好等于这个数本身的数\n例如: 6 = 1 + 2 + 3, 28 = 1 + 2 + 4 + 7 + 14\n\nVersion: 0.1\nAuthor: 骆昊\nDa"
  },
  {
    "path": "Day01-15/Day05/prime.py",
    "chars": 260,
    "preview": "\"\"\"\n\n输出2~99之间的素数\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-02\n\n\"\"\"\n\nimport math\n\nfor num in range(2, 100):\n\tis_prime = True"
  },
  {
    "path": "Day01-15/Day05/table.py",
    "chars": 171,
    "preview": "\"\"\"\n\n输出乘法口诀表(九九表)\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-02\n\n\"\"\"\n\nfor i in range(1, 10):\n\tfor j in range(1, i + 1):\n\t\tpr"
  },
  {
    "path": "Day01-15/Day05/总结和练习.md",
    "chars": 9,
    "preview": "## 总结和练习\n"
  },
  {
    "path": "Day01-15/Day06/function1.py",
    "chars": 238,
    "preview": "\"\"\"\n\n函数的定义和使用 - 计算组合数C(7,3)\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-05\n\n\"\"\"\n\n\n# 将求阶乘的功能封装成一个函数\ndef factorial(n):\n\tresult "
  },
  {
    "path": "Day01-15/Day06/function2.py",
    "chars": 307,
    "preview": "\"\"\"\n\n函数的定义和使用 - 求最大公约数和最小公倍数\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-05\n\n\"\"\"\n\n\ndef gcd(x, y):\n\tif x > y:\n\t\t(x, y) = (y, x"
  },
  {
    "path": "Day01-15/Day06/function3.py",
    "chars": 664,
    "preview": "\"\"\"\n\nPython的内置函数\n\t- 数学相关: abs / divmod / pow / round / min / max / sum\n\t- 序列相关: len / range / next / filter / map / sort"
  },
  {
    "path": "Day01-15/Day06/function4.py",
    "chars": 985,
    "preview": "\"\"\"\n\nPython常用模块\n\t- 运行时服务相关模块: copy / pickle / sys / ...\n\t- 数学相关模块: decimal / math / random / ...\n\t- 字符串处理模块: codecs / re"
  },
  {
    "path": "Day01-15/Day06/function5.py",
    "chars": 698,
    "preview": "\"\"\"\n\n函数的参数\n\t- 默认参数\n\t- 可变参数\n\t- 关键字参数\n\t- 命名关键字参数\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-05\n\n\"\"\"\n\n\n# 参数默认值\ndef f1(a, b=5, c"
  },
  {
    "path": "Day01-15/Day06/function6.py",
    "chars": 296,
    "preview": "\"\"\"\n\n作用域问题\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-05\n\n\"\"\"\n\n\n# 局部作用域\ndef foo1():\n\ta = 5\n\n\nfoo1()\n# print(a)\t# NameError\n\n"
  },
  {
    "path": "Day01-15/Day06/函数和模块的使用.md",
    "chars": 7458,
    "preview": "## 函数和模块的使用\n\n在讲解本章节的内容之前,我们先来研究一道数学题,请说出下面的方程有多少组正整数解。\n\n$$x_1 + x_2 + x_3 + x_4 = 8$$\n\n事实上,上面的问题等同于将8个苹果分成四组每组至少一个苹果有多少种"
  },
  {
    "path": "Day01-15/Day07/avgscore.py",
    "chars": 517,
    "preview": "\"\"\"\n\n输入学生考试成绩计算平均分\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-06\n\n\"\"\"\n\n\ndef main():\n\tnumber = int(input('请输入学生人数: '))\n\tnames"
  },
  {
    "path": "Day01-15/Day07/dict1.py",
    "chars": 562,
    "preview": "\"\"\"\n\n定义和使用字典\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-06\n\n\"\"\"\n\n\ndef main():\n\tscores = {'骆昊': 95, '白元芳': 78, '狄仁杰': 82}\n\tpr"
  },
  {
    "path": "Day01-15/Day07/dict2.py",
    "chars": 461,
    "preview": "\"\"\"\n\n字典的常用操作\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-06\n\n\"\"\"\n\n\ndef main():\n\tstu = {'name': '骆昊', 'age': 38, 'gender': Tru"
  },
  {
    "path": "Day01-15/Day07/fibonacci.py",
    "chars": 249,
    "preview": "\"\"\"\n\n生成斐波拉切数列\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-06\n\n\"\"\"\n\n\ndef main():\n\tf = [1 , 1]\n\tfor i in range(2, 20):\n\t\tf += ["
  },
  {
    "path": "Day01-15/Day07/findmax.py",
    "chars": 535,
    "preview": "\"\"\"\n\n找出列表中最大或最小的元素\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-06\n\n\"\"\"\n\n\ndef main():\n\tfruits = ['grape', 'apple', 'strawberry"
  },
  {
    "path": "Day01-15/Day07/list1.py",
    "chars": 564,
    "preview": "\"\"\"\n\n定义和使用列表\n\t- 用下标访问元素\n\t- 添加元素\n\t- 删除元素\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-06\n\n\"\"\"\n\n\ndef main():\n\tfruits = ['grape',"
  },
  {
    "path": "Day01-15/Day07/list2.py",
    "chars": 537,
    "preview": "\"\"\"\n\n列表常用操作\n\t- 列表连接\n\t- 获取长度\n\t- 遍历列表\n\t- 列表切片\n\t- 列表排序\n\t- 列表反转\n\t- 查找元素\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-06\n\n\"\"\"\n\n\ndef"
  },
  {
    "path": "Day01-15/Day07/list3.py",
    "chars": 659,
    "preview": "\"\"\"\n\n生成列表\n\t- 用range创建数字列表\n\t- 生成表达式\n\t- 生成器\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-06\n\n\"\"\"\n\n\n# 生成Fibonacci序列的生成器\ndef fib(n"
  },
  {
    "path": "Day01-15/Day07/lottery.py",
    "chars": 808,
    "preview": "\"\"\"\n\n双色球随机选号程序\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-06\n\n\"\"\"\n\nfrom random import randrange, randint, sample\n\n\ndef displ"
  },
  {
    "path": "Day01-15/Day07/marquee.py",
    "chars": 329,
    "preview": "\"\"\"\n\n输入学生考试成绩计算平均分\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-06\n\n\"\"\"\n\nimport os\nimport time\n\n\ndef main():\n\tstr = 'Welcome t"
  },
  {
    "path": "Day01-15/Day07/scoretable.py",
    "chars": 588,
    "preview": "\"\"\"\n\n学生考试成绩表\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-06\n\n\"\"\"\n\n\ndef main():\n\tnames = ['关羽', '张飞', '赵云', '马超', '黄忠']\n\tsubjs"
  },
  {
    "path": "Day01-15/Day07/set1.py",
    "chars": 606,
    "preview": "\"\"\"\n\n定义和使用集合\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-06\n\n\"\"\"\n\n\ndef main():\n    set1 = {1, 2, 3, 3, 3, 2}\n    print(set1)\n"
  },
  {
    "path": "Day01-15/Day07/set2.py",
    "chars": 669,
    "preview": "\"\"\"\n\n集合的常用操作\n\t- 交集\n\t- 并集\n\t- 差集\n\t- 子集\n\t- 超集\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-06\n\n\"\"\"\n\n\ndef main():\n\tset1 = set(rang"
  },
  {
    "path": "Day01-15/Day07/tic-tac-toe.py",
    "chars": 943,
    "preview": "\"\"\"\n\n井字棋游戏\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-06\n\n\"\"\"\n\nimport os\n\n\n\ndef print_board(board):\n\tprint(board['TL'] + '|'"
  },
  {
    "path": "Day01-15/Day07/tuple.py",
    "chars": 596,
    "preview": "\"\"\"\n\n元组的定义和使用\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-06\n\n\"\"\"\n\n\ndef main():\n\t# 定义元组\n\tt = ('骆昊', 38, True, '四川成都')\n\tprint("
  },
  {
    "path": "Day01-15/Day07/yanghui.py",
    "chars": 562,
    "preview": "\"\"\"\n\n输出10行的杨辉三角 - 二项式的n次方展开系数\n1\n1 1\n1 2 1\n1 3 3 1\n1 4 6 4 1\n... ... ...\n\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-06\n\n\"\"\"\n"
  },
  {
    "path": "Day01-15/Day07/字符串和常用数据结构.md",
    "chars": 13713,
    "preview": "## 字符串和常用数据结构\n\n### 使用字符串\n\n第二次世界大战促使了现代电子计算机的诞生,当初的想法很简单,就是用计算机来计算导弹的弹道,因此在计算机刚刚诞生的那个年代,计算机处理的信息主要是数值,而世界上的第一台电子计算机ENIAC每"
  },
  {
    "path": "Day01-15/Day08/access.py",
    "chars": 230,
    "preview": "class Test:\n\n\tdef __init__(self, foo):\n\t\tself.__foo = foo\n\n\tdef __bar(self):\n\t\tprint(self.__foo)\n\t\tprint('__bar')\n\n\ndef "
  },
  {
    "path": "Day01-15/Day08/circle.py",
    "chars": 767,
    "preview": "\"\"\"\n\n练习\n修一个游泳池 半径(以米为单位)在程序运行时输入 游泳池外修一条3米宽的过道\n过道的外侧修一圈围墙 已知过道的造价为25元每平米 围墙的造价为32.5元每米\n输出围墙和过道的总造价分别是多少钱(精确到小数点后2位)\n\nVer"
  },
  {
    "path": "Day01-15/Day08/clock.py",
    "chars": 985,
    "preview": "\"\"\"\n\n定义和使用时钟类\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-08\n\n\"\"\"\n\nimport time\nimport os\n\n\nclass Clock(object):\n\n\t# Python中的函"
  },
  {
    "path": "Day01-15/Day08/guess.py",
    "chars": 958,
    "preview": "\"\"\"\n\n面向对象版本的猜数字游戏\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-08\n\n\"\"\"\n\nfrom random import randint\n\n\nclass GuessMachine(object"
  },
  {
    "path": "Day01-15/Day08/hack.py",
    "chars": 351,
    "preview": "\"\"\"\n\n另一种创建类的方式\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-08\n\n\"\"\"\n\n\ndef bar(self, name):\n\tself._name = name\n\n\ndef foo(self, "
  },
  {
    "path": "Day01-15/Day08/rect.py",
    "chars": 680,
    "preview": "\"\"\"\n\n定义和使用矩形类\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-08\n\n\"\"\"\n\n\nclass Rect(object):\n\t\"\"\"矩形类\"\"\"\n\n\tdef __init__(self, width"
  },
  {
    "path": "Day01-15/Day08/student.py",
    "chars": 702,
    "preview": "\"\"\"\n\n定义和使用学生类\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-08\n\n\"\"\"\n\n\ndef _foo():\n\tprint('test')\n\n\nclass Student(object):\n\n\t# _"
  },
  {
    "path": "Day01-15/Day08/test.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "Day01-15/Day08/面向对象编程基础.md",
    "chars": 6339,
    "preview": "## 面向对象编程基础\n\n活在当下的程序员应该都听过“面向对象编程”一词,也经常有人问能不能用一句话解释下什么是“面向对象编程”,我们先来看看比较正式的说法。\n\n> 把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归"
  },
  {
    "path": "Day01-15/Day09/association.py",
    "chars": 1083,
    "preview": "\"\"\"\n\n对象之间的关联关系\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-12\n\n\"\"\"\n\nfrom math import sqrt\n\n\nclass Point(object):\n\n\tdef __init"
  },
  {
    "path": "Day01-15/Day09/car1.py",
    "chars": 1070,
    "preview": "\"\"\"\n\n属性的使用\n\t- 访问器/修改器/删除器\n\t- 使用__slots__对属性加以限制\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-12\n\n\"\"\"\n\n\nclass Car(object):\n\n\t__"
  },
  {
    "path": "Day01-15/Day09/car2.py",
    "chars": 863,
    "preview": "\"\"\"\n\n属性的使用\n\t- 使用已有方法定义访问器/修改器/删除器\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-12\n\n\"\"\"\n\n\nclass Car(object):\n\n\tdef __init__(sel"
  },
  {
    "path": "Day01-15/Day09/clock.py",
    "chars": 965,
    "preview": "from time import time, localtime, sleep\n\n\nclass Clock(object):\n    \"\"\"数字时钟\"\"\"\n\n    def __init__(self, hour=0, minute=0, "
  },
  {
    "path": "Day01-15/Day09/dependency.py",
    "chars": 1480,
    "preview": "\"\"\"\n\n对象之间的依赖关系和运算符重载\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-12\n\n\"\"\"\n\n\nclass Car(object):\n\n\tdef __init__(self, brand, max"
  },
  {
    "path": "Day01-15/Day09/diamond.py",
    "chars": 417,
    "preview": "\"\"\"\n\n多重继承\n\t- 菱形继承(钻石继承)\n\t- C3算法(替代DFS的算法)\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-12\n\n\"\"\"\n\n\nclass A(object):\n\n\tdef foo(se"
  },
  {
    "path": "Day01-15/Day09/employee.py",
    "chars": 1394,
    "preview": "\"\"\"\n\n抽象类 / 方法重写 / 多态\n实现一个工资结算系统 公司有三种类型的员工\n\t- 部门经理固定月薪12000元/月\n\t- 程序员按本月工作小时数每小时100元\n\t- 销售员1500元/月的底薪加上本月销售额5%的提成\n输入员工的信"
  },
  {
    "path": "Day01-15/Day09/multi.py",
    "chars": 977,
    "preview": "\"\"\"\n\n多重继承\n\t- 通过多重继承可以给一个类的对象具备多方面的能力\n\t- 这样在设计类的时候可以避免设计太多层次的复杂的继承关系\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-12\n\n\"\"\"\n\n\ncla"
  },
  {
    "path": "Day01-15/Day09/pet.py",
    "chars": 536,
    "preview": "from abc import ABCMeta, abstractmethod\n\n\nclass Pet(object, metaclass=ABCMeta):\n\n    def __init__(self, nickname):\n     "
  },
  {
    "path": "Day01-15/Day09/rational.py",
    "chars": 1649,
    "preview": "\"\"\"\n\n运算符重载 - 自定义分数类\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-12\n\n\"\"\"\n\nfrom math import gcd\n\n\nclass Rational(object):\n\n\tdef"
  },
  {
    "path": "Day01-15/Day09/res/uml-example.gliffy",
    "chars": 45229,
    "preview": "{\"contentType\":\"application/gliffy+json\",\"version\":\"1.1\",\"metadata\":{\"title\":\"untitled\",\"revision\":0,\"exportBorder\":fals"
  },
  {
    "path": "Day01-15/Day09/shape.py",
    "chars": 940,
    "preview": "\"\"\"\n\n继承的应用\n\t- 抽象类\n\t- 抽象方法\n\t- 方法重写\n\t- 多态\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-12\n\n\"\"\"\n\nfrom abc import ABCMeta, abstrac"
  },
  {
    "path": "Day01-15/Day09/triangle.py",
    "chars": 985,
    "preview": "\"\"\"\n\n实例方法和类方法的应用\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-12\n\n\"\"\"\n\nfrom math import sqrt\n\n\nclass Triangle(object):\n\n\tdef _"
  },
  {
    "path": "Day01-15/Day09/面向对象进阶.md",
    "chars": 17092,
    "preview": "## 面向对象进阶\n\n在前面的章节我们已经了解了面向对象的入门知识,知道了如何定义类,如何创建对象以及如何给对象发消息。为了能够更好的使用面向对象编程思想进行程序开发,我们还需要对Python中的面向对象编程进行更为深入的了解。\n\n### "
  },
  {
    "path": "Day01-15/Day10/ball.py",
    "chars": 2942,
    "preview": "from enum import Enum, unique\nfrom math import sqrt\nfrom random import randint\n\nimport pygame\n\n\n@unique\nclass Color(Enum"
  },
  {
    "path": "Day01-15/Day10/gui1.py",
    "chars": 1006,
    "preview": "\"\"\"\n\n使用tkinter创建GUI\n\t- 顶层窗口\n\t- 控件\n\t- 布局\n\t- 事件回调\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-14\n\n\"\"\"\n\nimport tkinter\nimport tk"
  },
  {
    "path": "Day01-15/Day10/gui2.py",
    "chars": 978,
    "preview": "\"\"\"\n\n使用tkinter创建GUI\n\t- 使用画布绘图\n\t- 处理鼠标事件\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-14\n\n\"\"\"\n\nimport tkinter\n\n\ndef mouse_evt_h"
  },
  {
    "path": "Day01-15/Day10/gui3.py",
    "chars": 654,
    "preview": "\"\"\"\n\n使用tkinter创建GUI\n\t- 在窗口上制作动画\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-14\n\n\"\"\"\n\nimport tkinter\nimport time\n\n\n# 播放动画效果的函数"
  },
  {
    "path": "Day01-15/Day10/turtle1.py",
    "chars": 353,
    "preview": "\"\"\"\n\n用turtle模块绘图\n这是一个非常有趣的模块 它模拟一只乌龟在窗口上爬行的方式来进行绘图\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-14\n\n\"\"\"\n\nimport turtle\n\nturtle"
  },
  {
    "path": "Day01-15/Day10/图形用户界面和游戏开发.md",
    "chars": 9307,
    "preview": "## 图形用户界面和游戏开发\n\n### 基于tkinter模块的GUI\n\nGUI是图形用户界面的缩写,图形化的用户界面对使用过计算机的人来说应该都不陌生,在此也无需进行赘述。Python默认的GUI开发模块是tkinter(在Python "
  },
  {
    "path": "Day01-15/Day11/.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "Day01-15/Day11/csv1.py",
    "chars": 314,
    "preview": "\"\"\"\n\n读取CSV文件\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-13\n\n\"\"\"\n\nimport csv\n\nfilename = 'example.csv'\n\ntry:\n\twith open(filen"
  },
  {
    "path": "Day01-15/Day11/csv2.py",
    "chars": 692,
    "preview": "\"\"\"\n\n写入CSV文件\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-13\n\n\"\"\"\n\nimport csv\n\n\nclass Teacher(object):\n\n\tdef __init__(self, na"
  },
  {
    "path": "Day01-15/Day11/ex1.py",
    "chars": 364,
    "preview": "\"\"\"\n\n异常机制 - 处理程序在运行时可能发生的状态\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-13\n\n\"\"\"\n\ninput_again = True\nwhile input_again:\n\ttry:\n"
  },
  {
    "path": "Day01-15/Day11/ex2.py",
    "chars": 293,
    "preview": "\"\"\"\n\n异常机制 - 处理程序在运行时可能发生的状态\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-13\n\n\"\"\"\n\ninput_again = True\nwhile input_again:\n\ttry:\n"
  },
  {
    "path": "Day01-15/Day11/ex3.py",
    "chars": 436,
    "preview": "\"\"\"\n\n异常机制 - 处理程序在运行时可能发生的状态\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-13\n\n\"\"\"\n\nimport time\nimport sys\n\nfilename = input('请输"
  },
  {
    "path": "Day01-15/Day11/ex4.py",
    "chars": 146,
    "preview": "\"\"\"\n\n引发异常和异常栈\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-13\n\n\"\"\"\n\n\ndef f1():\n\traise AssertionError('发生异常')\n\n\ndef f2():\n\tf1()"
  },
  {
    "path": "Day01-15/Day11/example.csv",
    "chars": 184,
    "preview": "4/5/2014 13:34,Apples,73\n4/5/2014 3:41,Cherries,85\n4/6/2014 12:46,Pears,14\n4/8/2014 8:59,Oranges,52\n4/10/2014 2:07,Apple"
  },
  {
    "path": "Day01-15/Day11/file1.py",
    "chars": 420,
    "preview": "\"\"\"\n\n从文本文件中读取数据\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-13\n\n\"\"\"\n\nimport time\n\n\ndef main():\n\t# 一次性读取整个文件内容\n\twith open('致橡树"
  },
  {
    "path": "Day01-15/Day11/file2.py",
    "chars": 273,
    "preview": "\"\"\"\n\n读取圆周率文件判断其中是否包含自己的生日\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-13\n\n\"\"\"\n\nbirth = input('请输入你的生日: ')\nwith open('pi_milli"
  },
  {
    "path": "Day01-15/Day11/file3.py",
    "chars": 384,
    "preview": "\"\"\"\n\n写文本文件\n将100以内的素数写入到文件中\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-13\n\n\"\"\"\n\nfrom math import sqrt\n\n\ndef is_prime(n):\n\tfor"
  },
  {
    "path": "Day01-15/Day11/file4.py",
    "chars": 302,
    "preview": "\"\"\"\n\n读写二进制文件\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-13\n\n\"\"\"\n\nimport base64\n\nwith open('mm.jpg', 'rb') as f:\n\tdata = f.re"
  },
  {
    "path": "Day01-15/Day11/json1.py",
    "chars": 1408,
    "preview": "\"\"\"\n\n读取JSON数据\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-13\n\n\"\"\"\n\nimport json\nimport csv2\n\njson_str = '{\"name\": \"骆昊\", \"age\":"
  },
  {
    "path": "Day01-15/Day11/json2.py",
    "chars": 347,
    "preview": "\"\"\"\n\n写入JSON文件\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-13\n\n\"\"\"\n\nimport json\n\nteacher_dict = {'name': '白元芳', 'age': 25, 'ti"
  },
  {
    "path": "Day01-15/Day11/pi_million_digits.txt",
    "chars": 1030000,
    "preview": "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679\n  821480865132823"
  },
  {
    "path": "Day01-15/Day11/teacher.csv",
    "chars": 19,
    "preview": "骆昊,38,叫兽\n狄仁杰,25,砖家\n"
  },
  {
    "path": "Day01-15/Day11/文件和异常.md",
    "chars": 8223,
    "preview": "## 文件和异常\n\n在实际开发中,常常需要对程序中的数据进行[持久化](https://baike.baidu.com/item/%E6%95%B0%E6%8D%AE%E6%8C%81%E4%B9%85%E5%8C%96)操作,而实现数据持"
  },
  {
    "path": "Day01-15/Day11/致橡树.txt",
    "chars": 53,
    "preview": "我如果爱你\n绝不学攀援的凌霄花\n借你的高枝炫耀自己\n\n我如果爱你\n绝不学痴情的鸟儿\n为绿荫重复单调的歌曲\n"
  },
  {
    "path": "Day01-15/Day12/str1.py",
    "chars": 740,
    "preview": "\"\"\"\n\n字符串常用操作\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-19\n\n\"\"\"\n\nimport pyperclip\n\n# 转义字符\nprint('My brother\\'s name is \\'007"
  },
  {
    "path": "Day01-15/Day12/str2.py",
    "chars": 1139,
    "preview": "\"\"\"\n\n字符串常用操作 - 实现字符串倒转的方法\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-19\n\n\"\"\"\n\nfrom io import StringIO\n\n\ndef reverse_str1(str"
  },
  {
    "path": "Day01-15/Day12/test3.py",
    "chars": 445,
    "preview": "\"\"\"\n\n验证输入用户名和QQ号是否有效并给出对应的提示信息\n\n要求:\n用户名必须由字母、数字或下划线构成且长度在6~20个字符之间\nQQ号是5~12的数字且首位不能为0\n\n\"\"\"\n\nimport re\n\n\ndef main():\n    "
  },
  {
    "path": "Day01-15/Day12/test4.py",
    "chars": 724,
    "preview": "import re\n\n\ndef main():\n    # 创建正则表达式对象 使用了前瞻和回顾来保证手机号前后不应该出现数字\n    pattern = re.compile(r'(?<=\\D)(1[38]\\d{9}|14[57]\\d{8"
  },
  {
    "path": "Day01-15/Day12/test5.py",
    "chars": 242,
    "preview": "import re\n\n\ndef main():\n    sentence = '你丫是傻叉吗? 我操你大爷的. Fuck you.'\n    purified = re.sub('[操肏艹草曹]|fuck|shit|傻[比屄逼叉缺吊屌]|煞"
  },
  {
    "path": "Day01-15/Day12/字符串和正则表达式.md",
    "chars": 9772,
    "preview": "## 使用正则表达式\n\n### 正则表达式相关知识\n\n在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要,正则表达式就是用于描述这些规则的工具,换句话说正则表达式是一种工具,它定义了字符串的匹配模式(如何检查一个字符"
  },
  {
    "path": "Day01-15/Day13/asyncio1.py",
    "chars": 546,
    "preview": "\"\"\"\n\n异步I/O操作 - asyncio模块\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-21\n\n\"\"\"\n\nimport asyncio\nimport threading\n# import time\n\n"
  },
  {
    "path": "Day01-15/Day13/asyncio2.py",
    "chars": 469,
    "preview": "\"\"\"\n\n异步I/O操作 - async和await\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-21\n\n\"\"\"\n\nimport asyncio\nimport threading\n\n\n# 通过async修饰"
  },
  {
    "path": "Day01-15/Day13/asyncio3.py",
    "chars": 793,
    "preview": "\"\"\"\n\n异步I/O操作 - asyncio模块\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-21\n\n\"\"\"\n\nimport asyncio\n\n\nasync def wget(host):\n\tprint('"
  },
  {
    "path": "Day01-15/Day13/coroutine1.py",
    "chars": 693,
    "preview": "\"\"\"\n\n使用协程 - 模拟快递中心派发快递\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-21\n\n\"\"\"\n\nfrom time import sleep\nfrom random import random\n"
  },
  {
    "path": "Day01-15/Day13/coroutine2.py",
    "chars": 824,
    "preview": "\"\"\"\n\n使用协程 - 查看协程的状态\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-21\n\n\"\"\"\n\nfrom time import sleep\nfrom inspect import getgenera"
  },
  {
    "path": "Day01-15/Day13/generator1.py",
    "chars": 315,
    "preview": "\"\"\"\n\n生成器 - 生成器语法\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-21\n\n\"\"\"\n\nseq = [x * x for x in range(10)]\nprint(seq)\n\ngen = (x *"
  },
  {
    "path": "Day01-15/Day13/generator2.py",
    "chars": 187,
    "preview": "\"\"\"\n\n生成器 - 使用yield关键字\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-21\n\n\"\"\"\n\n\ndef fib(num):\n\tn, a, b = 0, 0, 1\n\twhile n < num:\n"
  },
  {
    "path": "Day01-15/Day13/multiprocess1.py",
    "chars": 608,
    "preview": "\"\"\"\n\n使用Process类创建多个进程\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-20\n\n\"\"\"\n\n# 通过下面程序的执行结果可以证实 父进程在创建子进程时复制了进程及其数据结构\n# 每个进程都有自己"
  },
  {
    "path": "Day01-15/Day13/multiprocess2.py",
    "chars": 536,
    "preview": "\"\"\"\n\n实现进程间的通信\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-20\n\n\"\"\"\n\nimport multiprocessing\nimport os\n\n\ndef sub_task(queue):\n\tp"
  },
  {
    "path": "Day01-15/Day13/multiprocess3.py",
    "chars": 445,
    "preview": "\"\"\"\n\n创建进程调用其他程序\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-20\n\n\"\"\"\n\nimport subprocess\nimport sys\n\ndef main():\n\t# 通过sys.argv获"
  },
  {
    "path": "Day01-15/Day13/multiprocess4.py",
    "chars": 299,
    "preview": "from time import time\n\n\ndef main():\n    total = 0\n    number_list = [x for x in range(1, 100000001)]\n    start = time()\n"
  },
  {
    "path": "Day01-15/Day13/multithread1.py",
    "chars": 866,
    "preview": "\"\"\"\n\n使用多线程的情况 - 模拟多个下载任务\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-20\n\n\"\"\"\n\nfrom random import randint\nfrom time import tim"
  },
  {
    "path": "Day01-15/Day13/multithread2.py",
    "chars": 654,
    "preview": "\"\"\"\n\n使用多线程的情况 - 模拟多个下载任务\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-20\n\n\"\"\"\n\nfrom random import randint\nfrom threading impor"
  },
  {
    "path": "Day01-15/Day13/multithread3.py",
    "chars": 822,
    "preview": "\"\"\"\n\n使用多线程的情况 - 模拟多个下载任务\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-20\n\n\"\"\"\n\nfrom random import randint\nfrom time import tim"
  },
  {
    "path": "Day01-15/Day13/multithread4.py",
    "chars": 1112,
    "preview": "\"\"\"\n\n使用多线程的情况 - 耗时间的任务在独立的线程中执行\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-20\n\n\"\"\"\n\nimport time\nimport tkinter\nimport tkinte"
  },
  {
    "path": "Day01-15/Day13/multithread5.py",
    "chars": 1157,
    "preview": "\"\"\"\n\n多个线程共享数据 - 没有锁的情况\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-20\n\n\"\"\"\n\nfrom time import sleep\nfrom threading import Thre"
  },
  {
    "path": "Day01-15/Day13/multithread6.py",
    "chars": 725,
    "preview": "\"\"\"\n\n多个线程共享数据 - 有锁的情况\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-20\n\n\"\"\"\n\nimport time\nimport threading\n\n\nclass Account(objec"
  },
  {
    "path": "Day01-15/Day13/singlethread1.py",
    "chars": 511,
    "preview": "\"\"\"\n\n不使用多线程的情况 - 模拟多个下载任务\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-20\n\n\"\"\"\n\nfrom random import randint\nfrom time import ti"
  },
  {
    "path": "Day01-15/Day13/singlethread2.py",
    "chars": 861,
    "preview": "\"\"\"\n\n不使用多线程的情况 - 耗时间的任务阻塞主事件循环\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-20\n\n\"\"\"\n\nimport time\nimport tkinter\nimport tkinter"
  },
  {
    "path": "Day01-15/Day13/test2.py",
    "chars": 1075,
    "preview": "import time\nfrom threading import Thread, Lock\n\n\nclass Account(object):\n\n    def __init__(self, balance=0):\n        self"
  },
  {
    "path": "Day01-15/Day13/test3.py",
    "chars": 1637,
    "preview": "from random import randint\nfrom threading import Thread\nfrom time import sleep\n\nimport pygame\n\n\nclass Color(object):\n   "
  },
  {
    "path": "Day01-15/Day13/进程和线程.md",
    "chars": 13854,
    "preview": "## 进程和线程\n\n今天我们使用的计算机早已进入多CPU或多核时代,而我们使用的操作系统都是支持“多任务”的操作系统,这使得我们可以同时运行多个程序,也可以将一个程序分解为若干个相对独立的子任务,让多个子任务并发的执行,从而缩短程序的执行时"
  },
  {
    "path": "Day01-15/Day14/chatclient.py",
    "chars": 827,
    "preview": "from socket import socket\nfrom threading import Thread\n\n\ndef main():\n\n    class RefreshScreenThread(Thread):\n\n        de"
  },
  {
    "path": "Day01-15/Day14/chatserver.py",
    "chars": 1222,
    "preview": "from socket import socket\nfrom threading import Thread\n\n\ndef main():\n\n    class ClientHandler(Thread):\n\n        def __in"
  },
  {
    "path": "Day01-15/Day14/fileclient.py",
    "chars": 736,
    "preview": "from socket import socket\nfrom json import loads\nfrom base64 import b64decode\n\n\ndef main():\n    client = socket()\n    cl"
  },
  {
    "path": "Day01-15/Day14/fileserver.py",
    "chars": 1210,
    "preview": "from socket import socket, SOCK_STREAM, AF_INET\nfrom base64 import b64encode\nfrom json import dumps\nfrom threading impor"
  },
  {
    "path": "Day01-15/Day14/mmdownloader.py",
    "chars": 782,
    "preview": "from time import time\nfrom threading import Thread\n\nimport requests\n\n\nclass DownloadHanlder(Thread):\n\n    def __init__(s"
  },
  {
    "path": "Day01-15/Day14/socket1.py",
    "chars": 468,
    "preview": "\"\"\"\n\n套接字 - 基于TCP协议创建时间服务器\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-22\n\n\"\"\"\n\nfrom socket import *\nfrom time import *\n\nserve"
  },
  {
    "path": "Day01-15/Day14/socket2.py",
    "chars": 274,
    "preview": "\"\"\"\n\n套接字 - 基于TCP协议创建时间客户端\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-22\n\n\"\"\"\n\nfrom socket import *\n\nclient = socket(AF_INET,"
  },
  {
    "path": "Day01-15/Day14/socket3.py",
    "chars": 275,
    "preview": "\"\"\"\n\n套接字 - 基于UDP协议Echo服务器\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-22\n\n\"\"\"\n\nfrom socket import *\nfrom time import *\n\nserve"
  },
  {
    "path": "Day01-15/Day14/socket4.py",
    "chars": 378,
    "preview": "\"\"\"\n\n套接字 - 基于UDP协议创建Echo客户端\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-22\n\n\"\"\"\n\nfrom socket import *\n\nclient = socket(AF_INE"
  },
  {
    "path": "Day01-15/Day14/socket5.py",
    "chars": 435,
    "preview": "\"\"\"\n\n使用socketserver模块创建时间服务器\n\nVersion: 0.1\nAuthor: 骆昊\nDate: 2018-03-22\n\n\"\"\"\n\nfrom socketserver import TCPServer, StreamR"
  },
  {
    "path": "Day01-15/Day14/timeclient.py",
    "chars": 208,
    "preview": "from socket import socket\n\n\ndef main():\n    client = socket()\n    client.connect(('10.7.152.69', 6789))\n    print(client"
  },
  {
    "path": "Day01-15/Day14/timeserver.py",
    "chars": 888,
    "preview": "from socket import socket, SOCK_STREAM, AF_INET\nfrom datetime import datetime\n\n\ndef main():\n    # 1.创建套接字对象并指定使用哪种传输服务\n "
  },
  {
    "path": "Day01-15/Day14/网络编程入门.md",
    "chars": 9722,
    "preview": "## 网络编程入门\n\n### 计算机网络基础\n\n计算机网络是独立自主的计算机互联而成的系统的总称,组建计算机网络最主要的目的是实现多台计算机之间的通信和资源共享。今天计算机网络中的设备和计算机网络的用户已经多得不可计数,而计算机网络也可以称"
  },
  {
    "path": "Day01-15/Day15/网络应用开发.md",
    "chars": 3510,
    "preview": "## 网络应用开发\n\n### 发送电子邮件\n\n在即时通信软件如此发达的今天,电子邮件仍然是互联网上使用最为广泛的应用之一,公司向应聘者发出录用通知、网站向用户发送一个激活账号的链接、银行向客户推广它们的理财产品等几乎都是通过电子邮件来完成的"
  },
  {
    "path": "Day16-20/Python语言进阶.md",
    "chars": 15,
    "preview": "## Python进阶知识\n\n"
  },
  {
    "path": "Day21-30/Web前端概述.md",
    "chars": 7584,
    "preview": "## Web前端概述\n\n### HTML简史\n\n1. 1991年10月:一个非正式CERN([欧洲核子研究中心](https://zh.wikipedia.org/wiki/%E6%AD%90%E6%B4%B2%E6%A0%B8%E5%AD"
  },
  {
    "path": "Day21-30/classical_layout.html",
    "chars": 1823,
    "preview": "<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<meta charset=\"UTF-8\">\n\t\t<title></title>\n\t\t<style>\n\t\t\t* {\n\t\t\t\tmargin: 0;\n\t\t\t\tpadding: 0"
  },
  {
    "path": "Day21-30/example.html",
    "chars": 1202,
    "preview": "<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<meta charset=\"UTF-8\">\n\t\t<title></title>\n\t\t<style>\n\t\t\t* {\n\t\t\t\tmargin: 0;\n\t\t\t\tpadding: 0"
  },
  {
    "path": "Day21-30/form.html",
    "chars": 4631,
    "preview": "<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<meta charset=\"UTF-8\">\n\t\t<title></title>\n\t\t<style>\n\t\t\t* {\n\t\t\t\tmargin: 0;\n\t\t\t\tpadding: 0"
  },
  {
    "path": "Day21-30/form_and_table.html",
    "chars": 3132,
    "preview": "<!DOCTYPE html>\n<html lang=\"zh\">\n\t<head>\n\t\t<meta charset=\"UTF-8\" />\n\t\t<meta name=\"description\" content=\"\" />\n\t\t<title>用户"
  },
  {
    "path": "Day21-30/jquery3.html",
    "chars": 8304,
    "preview": "<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title></title>\n\t\t<style>\n\t\t\t* { \n\t\t\t\tmargin: 0;\n\t\t\t\tpadding: "
  },
  {
    "path": "Day21-30/qq_link.html",
    "chars": 280,
    "preview": "<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<meta charset=\"UTF-8\">\n\t\t<title></title>\n\t</head>\n\t<body>\n\t\t<a target=\"_blank\" href=\"ht"
  },
  {
    "path": "Day31-35/玩转Linux.md",
    "chars": 7270,
    "preview": "## 玩转Linux操作系统\n\n### 操作系统发展史\n\n![](./res/history-of-os.png)\n\n### Linux概述\n\nLinux是一个通用操作系统。一个操作系统要负责任务调度、内存分配、处理外围设备I/O等操作。操"
  },
  {
    "path": "Day36-40/NoSQL入门.md",
    "chars": 83,
    "preview": "## NoSQL入门\n\n### NoSQL概述\n\n\n\n### 主流NoSQL数据库\n\n\n\n### Redis概述\n\n\n\n### MongoDB概述\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "Day36-40/关系型数据库MySQL.md",
    "chars": 200,
    "preview": "## 关系型数据入门\n\n### 关系型数据概述\n\n1. 数据持久化。\n2. 数据库发展史。\n3. 关系型数据库特点。\n4. E-R图。\n5. 关系型数据库产品。\n\n### MySQL简介\n\n1. 安装和配置。\n2. 常用命令。\n\n### S"
  },
  {
    "path": "Day41-55/Django2实战01.md",
    "chars": 11257,
    "preview": "## Django 2.x实战(01) - 快速上手\n\nWeb开发的早期阶段,开发者需要手动编写每个页面,例如一个新闻门户网站,每天都要修改它的HTML页面,这样随着网站规模和体量的增大,这种方式就变得极度糟糕。为了解决这个问题,开发人员想"
  },
  {
    "path": "Day41-55/Django2实战02.md",
    "chars": 16383,
    "preview": "## Django 2.x实战(02) - 深入模型\n\n在上一个章节中,我们提到了Django是一个基于MVC架构的Web框架,MVC架构要追求的是模型和视图的解耦合,而其中的模型说得更直白一些就是数据,所以通常也被称作数据模型。在实际的项"
  },
  {
    "path": "Day41-55/Django2实战03.md",
    "chars": 33,
    "preview": "## Django 2.x实战(03) - 视图、模板和URL\n\n"
  },
  {
    "path": "Day41-55/Django2实战04.md",
    "chars": 29,
    "preview": "## Django 2.x实战(04) - 表单的应用\n\n"
  },
  {
    "path": "Day41-55/Django2实战05.md",
    "chars": 35,
    "preview": "## Django 2.x实战(05) - Cookie和会话\n\n\n\n"
  },
  {
    "path": "Day41-55/Django2实战06.md",
    "chars": 31,
    "preview": "## Django 2.x实战(06) - 日志和缓存\n\n\n\n"
  },
  {
    "path": "Day41-55/Django2实战07.md",
    "chars": 35,
    "preview": "## Django 2.x实战(07) - 文件上传和通用视图\n\n\n\n"
  },
  {
    "path": "Day41-55/Django2实战08.md",
    "chars": 38,
    "preview": "## Django 2.x实战(08) - 用户/角色/权限和中间件\n\n\n\n"
  },
  {
    "path": "Day41-55/Django2实战09.md",
    "chars": 41,
    "preview": "## Django 2.x实战(09) - RESTful架构和应用(上)\n\n\n\n"
  },
  {
    "path": "Day41-55/Django2实战10.md",
    "chars": 41,
    "preview": "## Django 2.x实战(10) - RESTful架构和应用(下)\n\n\n\n"
  },
  {
    "path": "Day41-55/Django2项目实战.md",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "Day41-55/car/car/__init__.py",
    "chars": 44,
    "preview": "import pymysql\n\npymysql.install_as_MySQLdb()"
  },
  {
    "path": "Day41-55/car/car/settings.py",
    "chars": 3263,
    "preview": "\"\"\"\nDjango settings for car project.\n\nGenerated by 'django-admin startproject' using Django 2.0.5.\n\nFor more information"
  },
  {
    "path": "Day41-55/car/car/urls.py",
    "chars": 883,
    "preview": "\"\"\"car URL Configuration\n\nThe `urlpatterns` list routes URLs to views. For more information please see:\n    https://docs"
  },
  {
    "path": "Day41-55/car/car/wsgi.py",
    "chars": 383,
    "preview": "\"\"\"\nWSGI config for car project.\n\nIt exposes the WSGI callable as a module-level variable named ``application``.\n\nFor mo"
  },
  {
    "path": "Day41-55/car/manage.py",
    "chars": 535,
    "preview": "#!/usr/bin/env python\nimport os\nimport sys\n\nif __name__ == \"__main__\":\n    os.environ.setdefault(\"DJANGO_SETTINGS_MODULE"
  },
  {
    "path": "Day41-55/car/search/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "Day41-55/car/search/admin.py",
    "chars": 261,
    "preview": "from django.contrib import admin\n\nfrom search.models import CarRecord\n\n\nclass CarRecordAdmin(admin.ModelAdmin):\n\n    lis"
  },
  {
    "path": "Day41-55/car/search/apps.py",
    "chars": 87,
    "preview": "from django.apps import AppConfig\n\n\nclass SearchConfig(AppConfig):\n    name = 'search'\n"
  },
  {
    "path": "Day41-55/car/search/migrations/0001_initial.py",
    "chars": 893,
    "preview": "# -*- coding: utf-8 -*-\n# Generated by Django 1.11 on 2018-05-24 01:16\nfrom __future__ import unicode_literals\n\nfrom dja"
  },
  {
    "path": "Day41-55/car/search/migrations/0002_auto_20180524_1420.py",
    "chars": 543,
    "preview": "# -*- coding: utf-8 -*-\n# Generated by Django 1.11 on 2018-05-24 06:20\nfrom __future__ import unicode_literals\n\nfrom dja"
  },
  {
    "path": "Day41-55/car/search/migrations/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "Day41-55/car/search/models.py",
    "chars": 705,
    "preview": "from django.db import models\n\n\nclass CarRecord(models.Model):\n    carno = models.CharField(max_length=7)\n    reason = mo"
  },
  {
    "path": "Day41-55/car/search/tests.py",
    "chars": 60,
    "preview": "from django.test import TestCase\n\n# Create your tests here.\n"
  },
  {
    "path": "Day41-55/car/search/views.py",
    "chars": 3551,
    "preview": "from datetime import datetime\nfrom json import JSONEncoder\n\nfrom django import forms\nfrom django.http import JsonRespons"
  },
  {
    "path": "Day41-55/car/templates/add.html",
    "chars": 758,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>添加</title>\n    <style>\n        .err {\n    "
  },
  {
    "path": "Day41-55/car/templates/search.html",
    "chars": 2527,
    "preview": "<!DOCTYPE html>\n{% load staticfiles %}\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>车辆违章查询</title>\n    "
  },
  {
    "path": "Day41-55/car/templates/search2.html",
    "chars": 3535,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>车辆违章查询</title>\n    <style>\n        * {\n   "
  },
  {
    "path": "Day41-55/oa/hrs/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "Day41-55/oa/hrs/admin.py",
    "chars": 404,
    "preview": "from django.contrib import admin\n\nfrom hrs.models import Dept, Emp\n\n\nclass DeptAdmin(admin.ModelAdmin):\n\n    list_displa"
  },
  {
    "path": "Day41-55/oa/hrs/apps.py",
    "chars": 81,
    "preview": "from django.apps import AppConfig\n\n\nclass HrsConfig(AppConfig):\n    name = 'hrs'\n"
  },
  {
    "path": "Day41-55/oa/hrs/migrations/0001_initial.py",
    "chars": 1325,
    "preview": "# Generated by Django 2.0.5 on 2018-05-22 03:07\n\nfrom django.db import migrations, models\nimport django.db.models.deleti"
  },
  {
    "path": "Day41-55/oa/hrs/migrations/0002_auto_20180523_0923.py",
    "chars": 1275,
    "preview": "# Generated by Django 2.0.5 on 2018-05-23 01:23\n\nfrom django.db import migrations, models\n\n\nclass Migration(migrations.M"
  }
]

// ... and 108 more files (download for full content)

About this extraction

This page contains the full source code of the ZiniuLu/Python-100-Days GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 308 files (1.5 MB), approximately 555.9k tokens, and a symbol index with 471 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!