├── src
└── README.md
├── slides
└── README.md
├── courses
├── images
│ ├── class31.png
│ ├── background.jpg
│ ├── class30-01.png
│ ├── class30-02.png
│ ├── class33-01.png
│ ├── class35-01.png
│ ├── class41-01.png
│ ├── class41-02.png
│ ├── class41-03.png
│ ├── class42-01.png
│ └── class43-01.png
├── python52.md
├── python54.md
├── python44.md
├── python32.md
├── python22.md
├── python12.md
├── python41.md
├── python49.md
├── python31.md
├── python53.md
├── python19.md
├── python43.md
├── python36.md
├── python13.md
├── python51.md
├── python17.md
├── python38.md
├── python03.md
├── python39.md
├── python20.md
├── python48.md
├── python26.md
├── python30.md
├── python04.md
├── python09.md
├── python50.md
├── python02.md
├── python34.md
├── python05.md
├── python45.md
├── python06.md
├── python01.md
├── python47.md
├── python40.md
├── python42.md
├── python25.md
├── python23.md
├── python15.md
├── python07.md
├── python08.md
├── python35.md
├── python24.md
├── python14.md
├── python18.md
├── python10.md
├── python33.md
├── python28.md
├── python11.md
├── python37.md
├── python46.md
├── python29.md
├── python27.md
├── python21.md
└── python16.md
├── .gitignore
└── README.md
/src/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/slides/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/courses/images/class31.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/DevOpsGirls/master/courses/images/class31.png
--------------------------------------------------------------------------------
/courses/images/background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/DevOpsGirls/master/courses/images/background.jpg
--------------------------------------------------------------------------------
/courses/images/class30-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/DevOpsGirls/master/courses/images/class30-01.png
--------------------------------------------------------------------------------
/courses/images/class30-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/DevOpsGirls/master/courses/images/class30-02.png
--------------------------------------------------------------------------------
/courses/images/class33-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/DevOpsGirls/master/courses/images/class33-01.png
--------------------------------------------------------------------------------
/courses/images/class35-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/DevOpsGirls/master/courses/images/class35-01.png
--------------------------------------------------------------------------------
/courses/images/class41-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/DevOpsGirls/master/courses/images/class41-01.png
--------------------------------------------------------------------------------
/courses/images/class41-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/DevOpsGirls/master/courses/images/class41-02.png
--------------------------------------------------------------------------------
/courses/images/class41-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/DevOpsGirls/master/courses/images/class41-03.png
--------------------------------------------------------------------------------
/courses/images/class42-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/DevOpsGirls/master/courses/images/class42-01.png
--------------------------------------------------------------------------------
/courses/images/class43-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/DevOpsGirls/master/courses/images/class43-01.png
--------------------------------------------------------------------------------
/courses/python52.md:
--------------------------------------------------------------------------------
1 | # 第52课:难点强化
2 |
3 | 配图来自Twitter:@tomo_3
4 |
5 | 
--------------------------------------------------------------------------------
/courses/python54.md:
--------------------------------------------------------------------------------
1 | # 第54课:Python面试
2 |
3 | 配图来自Twitter:@atikix
4 |
5 | 
--------------------------------------------------------------------------------
/courses/python44.md:
--------------------------------------------------------------------------------
1 | # 第44课:验证
2 |
3 | 配图来自Twitter:@ukiukisoda
4 |
5 | 
6 |
--------------------------------------------------------------------------------
/courses/python32.md:
--------------------------------------------------------------------------------
1 | # 第32课:入门 - 测试(七)
2 |
3 | 先回顾下前面两节测试课程:
4 | * [第21课:测试(Testing)(一)](python21.md)
5 | * [第22课:测试(Testing)(二)](python22.md)
6 |
7 | 在这里,我们将对投票应用进行测试。
8 |
9 | 配图来自Twitter:@atikix
10 |
11 | 
12 |
--------------------------------------------------------------------------------
/courses/python22.md:
--------------------------------------------------------------------------------
1 | # 第22课:测试(Testing)(二)
2 |
3 | ### 持续集成
4 |
5 | 常用的CI服务器有:Jenkins、Travis CI、GitLab CI、Buildbot等。
6 |
7 | 这里,我们就使用Buildbot来做持续服务器。
8 |
9 | 配图来自Twitter:@neku_draw
10 |
11 | 
12 |
--------------------------------------------------------------------------------
/courses/python12.md:
--------------------------------------------------------------------------------
1 | # 第12课:程序结构(Program structure)
2 |
3 | Python程序由包、模块(即一个Python文件.py)和函数组成,包是由一系列模块组成的集合,模块是处理某一类问题的函数和类的集合。
4 |
5 | 
6 |
7 | (图片来自:w3cschool.cn)
8 |
9 | 包中必须至少含有一个__init__.py文件,该文件的内容可以为空。用于标识当前文件夹是一个包。
10 |
11 | ### 物理设计
12 |
13 | * 组件与类
14 |
15 | * 依赖关系
16 |
17 | * 层次化
18 |
19 | * 包
20 |
21 | ### 逻辑设计
22 |
23 | * 构建一个组件
24 |
25 | * 设计一个函数
26 |
27 | * 实现一个对象
28 |
29 | ### Web项目结构
30 |
31 | ### 网站架构
32 |
33 | ### 脚手架
34 |
35 | 配图来自Twitter
36 |
37 | 
38 |
--------------------------------------------------------------------------------
/courses/python41.md:
--------------------------------------------------------------------------------
1 | # 第41课:认证
2 |
3 | ### 认证中间件
4 | AuthenticationMiddleware
5 |
6 | ### 用户认证
7 | Django 带有用户身份验证系统,包含用户账号、用户组、权限和基于cookie的用户管理。
8 |
9 | 
10 |
11 | 默认用户的主要属性有:
12 | * username
13 | * password
14 | * email
15 | * first_name
16 | * last_name
17 | 
18 |
19 | 
20 |
21 | ### 第三方验证
22 | 支持微博、微信、Twitter、Facebook 等第三方身份验证和账户登录。
23 |
24 | ### 自定义扩展Django验证
25 | Django 自带的验证机制足以应对一般情况,但用户总会有自己的特殊需求,这时就需要自定义和扩展验证机制,你需要了解在已有验证系统中哪些地方是可以扩展的,哪些地方是可以代替的。
26 |
27 |
28 | 配图来自Twitter:@chengr28
29 |
30 | 
31 |
--------------------------------------------------------------------------------
/courses/python49.md:
--------------------------------------------------------------------------------
1 | # 第49课:加密签名
2 |
3 | 背景:Web 应用安全的黄金法则是永远不要信任来自不受信任来源的数据。
4 |
5 | Django 既提供用于签名值的低级 API,也提供用于设置和读取签名cookie的高级 API。
6 |
7 | ### SECRET_KEY
8 | 使用 startproject 创建 Django 项目时,会自动生成 settings.py 文件并获取随机的 SECRET_KEY 值。 此值是保护签名数据的关键,其安全至关重要,因为攻击者可以使用它来生成自己的签名值。
9 |
10 | 类似这样的一个值:SECRET_KEY = 'c=$*+jdept%gz2a+b(dasdfdsczc5&&2q&gasdfeasy#1j='
11 |
12 | ### 使用API
13 | ```
14 | >>> from django.core.signing import Signer
15 | >>> signer = Signer()
16 | >>> value = signer.sign('python')
17 | >>> value
18 | 'python:Gl-at2uNL427Vt2IuODkwD93Tzc'
19 | >>>
20 |
21 | >>> original = signer.unsign(value)
22 | >>> original
23 | 'python'
24 | ```
25 |
26 | 配图来自Twitter:@tomo_3
27 |
28 | 
--------------------------------------------------------------------------------
/courses/python31.md:
--------------------------------------------------------------------------------
1 | # 第31课:入门 - 样式风格(六)
2 |
3 | 一个 Web 应用除了动态语言外,还有图片、样式表等所谓的静态文件,django.contrib.staticfiles 就是干这事的。它将各个应用的静态文件统一收集起来,这样一来,在生产环境中,就会有一个集中便于分发的地方。
4 |
5 | ### 加个样式表
6 | 创建 polls/static/polls/style.css,并添加:
7 | ```
8 | li a {
9 | color: green;
10 | }
11 | ```
12 | 然后,在 polls/templates/polls/index.html 的文件中添加以下内容:
13 | ```
14 | {% load static %}
15 |
16 |
17 | ```
18 |
19 | ### 加个背景
20 | 将图片放在 polls/static/polls/images/ 目录下,
21 |
22 | 然后在样式表 polls/static/polls/style.css 中添加:
23 | ```
24 | body {
25 | background: white url("images/background.jpg") no-repeat;
26 | }
27 | ```
28 | 好了,看下效果。 http://localhost:8000/polls/
29 |
30 | 
31 |
32 | 有背景了,问题的链接变绿了 :)
33 |
34 | 有关样式表的内容比较多,这块你就自己展开学习了。
35 |
36 | 配图来自Twitter:@atikix
37 |
38 | 
39 |
--------------------------------------------------------------------------------
/courses/python53.md:
--------------------------------------------------------------------------------
1 | # 第53课:Python进阶
2 | DevOpsGirls(Python程序媛)也参考和引用了以下资料,大家可进一步深入:
3 |
4 | * [《Python进阶》](https://github.com/eastlakeside/interpy-zh)是《Intermediate Python》的中文译本。
5 | * [《Python Cookbook》 3rd 中文版](https://github.com/yidao620c/python3-cookbook)
6 | * [《Django 中文文档》](https://docs.huihoo.com/django/2.1-zh-cn/index.html)
7 | * [《Python Web开发实践》](https://www.amazon.cn/dp/B01L8NVIC6/)
8 | * [Python 3 教程](http://www.runoob.com/python3/python3-tutorial.html)
9 | * [轻量级Django](https://www.amazon.cn/dp/B01M4S72G0/)
10 | * [Django教程](https://www.w3cschool.cn/django/)
11 | * [Django Girls 教程](https://tutorial.djangogirls.org/zh/)
12 | * [基于 Python3.5 和 Django 1.10 的 Django Blog 项目](https://github.com/zmrenwu/django-blog-tutorial)
13 | * [python-doc中文文档](https://github.com/ictar/python-doc)
14 |
15 | 配图来自Twitter:@tomo_3
16 |
17 | 
18 |
--------------------------------------------------------------------------------
/courses/python19.md:
--------------------------------------------------------------------------------
1 | # 第19课:闭包(Closures)
2 |
3 | ### 什么是闭包
4 | 维基百科介绍
5 |
6 | 在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。
7 |
8 | 闭包,就好比一个封闭的包裹,里面包裹着自由变量,哪里可以访问到这个包裹,哪里就可以访问到这个自由变量。
9 |
10 | ### 为什么要使用闭包
11 | 闭包避免了全局变量的使用,闭包允许将函数与其所操作的相关数据和环境关连起来。
12 |
13 | ### 如何使用闭包
14 | 一个闭包就是你调用了一个函数A,这个函数A返回了一个函数B给你。这个返回的函数B就叫做闭包,你在调用函数A的时候传递的参数就是自由变量。
15 | ```
16 | >>> def func(name):
17 | ... def inner_func(age):
18 | ... print ('name:', name, 'age:', age)
19 | ... return inner_func
20 | ...
21 | >>> hello = func('huihoo')
22 | >>> hello(18)
23 | name: huihoo age: 18
24 | ```
25 |
26 | 调用func的时候就产生了一个闭包inner_func,该闭包也包含name自由变量。当func生命周期结束了,name自由变量依然存在,因为它被闭包引用,所以不会被回收。
27 |
28 | 配图来自Twitter:@MacciattoS2
29 |
30 | 
31 |
--------------------------------------------------------------------------------
/courses/python43.md:
--------------------------------------------------------------------------------
1 | # 第43课:分页
2 |
3 | ### 简介
4 | Django 提供了一些帮助你管理分页数据,这些类在 django/core/paginator.py 中定义
5 |
6 | ### 例子
7 | ```
8 | >>> from django.core.paginator import Paginator
9 | >>> objects = ['Pyton', 'Go', 'C', 'C++', 'C#']
10 | >>> p = Paginator(objects, 2)
11 | >>> p.count
12 | 5
13 | >>> p.num_pages
14 | 3
15 | >>> p.page_range
16 | range(1, 4)
17 | >>> page1 = p.page(1)
18 | >>> page1
19 |
20 | >>> page1.object_list
21 | ['Pyton', 'Go']
22 | >>> page2 = p.page(2)
23 | >>> page2.object_list
24 | ['C', 'C++']
25 | >>> page2.has_next()
26 | True
27 | ```
28 |
29 | ### 在视图中使用Paginator
30 | 先通过Admin后台增加一些问题,
31 |
32 | 
33 |
34 | ### 修改视图
35 | polls/views.py
36 | ```
37 | from django.core.paginator import Paginator
38 |
39 | ```
40 |
41 | ### 修改模版
42 | polls/index.html
43 | ```
44 | ```
45 |
46 | 配图来自Twitter:@ukiukisoda
47 |
48 | 
49 |
--------------------------------------------------------------------------------
/courses/python36.md:
--------------------------------------------------------------------------------
1 | # 第36课:视图(二)
2 |
3 | 这里我们介绍基于类的视图。
4 |
5 | ### 基于类的视图(Class-based views)
6 | 视图不仅仅只有函数(def),而可以是类(class)
7 |
8 | 基于类的视图提供了另一种将视图实现为Python对象而不是函数的方法。
9 |
10 | Django 也提供了一些可用作视图的类的示例,允许你通过继承和复用构建自己的视图并且复用这些代码。
11 |
12 | 将一个函数定义的视图转换成基于类的视图:
13 |
14 | 函数定义的视图
15 | ```
16 | from django.http import HttpResponse
17 |
18 | def my_view(request):
19 | if request.method == 'GET':
20 | #
21 | return HttpResponse('result')
22 | ```
23 | 转换成 -> 基于类的视图:
24 | ```
25 | from django.http import HttpResponse
26 | from django.views import View
27 |
28 | class MyView(View):
29 | def get(self, request):
30 | #
31 | return HttpResponse('result')
32 | ```
33 |
34 | ### 内置基于类的视图
35 | 大致的一个划分:
36 | * Base views
37 | * Generic display views
38 | * Generic editing views
39 | * Generic date views
40 | * Class-based views mixins
41 | * Class-based generic views
42 |
43 | 配图来自Twitter:@chengr28
44 |
45 | 
46 |
--------------------------------------------------------------------------------
/courses/python13.md:
--------------------------------------------------------------------------------
1 | # 第13课:函数(Function)
2 |
3 | ### def
4 | 我们来写一个最简单的函数
5 | ```
6 | >>> def hello():
7 | ... print ("Hello World!")
8 | ...
9 | >>> hello()
10 | Hello World!
11 | ```
12 |
13 | ### lambda
14 | lambda表达式是一行函数,它和普通函数完全一样,它在其它语言中叫匿名函数。
15 |
16 | Python使用lambda来创建匿名函数,匿名就是不用像def那样定义函数。
17 |
18 | lambda是表达式,它不是代码块。
19 |
20 | lambda原型
21 | ```
22 | lambda 参数 : 操作(参数)
23 |
24 | >>> add = lambda x, y : x + y
25 | >>> print(add(1, 2))
26 | ```
27 |
28 | 写一个简单的Lambda表达式
29 | ```
30 | >>> hello = lambda x, y : x*2+y*2
31 | >>> hello(2,3)
32 | 10
33 | ```
34 |
35 | 来一个复杂点的:列表排序
36 | ```
37 | >>> sl = [(2, 3), (4, 2), (11, -2)]
38 | >>> sl.sort(key=lambda x: x[1])
39 | >>> print(sl)
40 | [(11, -2), (4, 2), (2, 3)]
41 |
42 | >>> sl = [(2, 1, 3), (4, 3, 2), (11, 9, -2)]
43 | >>> sl.sort(key=lambda x: x[1])
44 | >>> print(sl)
45 | [(2, 1, 3), (4, 3, 2), (11, 9, -2)]
46 | ```
47 |
48 | 思考下def和lambda有哪些联系和不同?
49 |
50 | 配图来自Twitter:@neku_draw
51 |
52 | 
53 |
--------------------------------------------------------------------------------
/courses/python51.md:
--------------------------------------------------------------------------------
1 | # 第51课:知识回顾
2 |
3 | ### Python知识点
4 | * 数据类型:Number、String、Tuple、List、Dictionary、Set,区分可变、不可变
5 | * 条件 if - elif - else :
6 | * 循环 for、while
7 | * 文件目录:open、write、 close 和 dir、chdir、path
8 | * 错误异常:SyntaxError、try/except、raise、Exception、Finally、traceback
9 | * 语法(Syntax)、语义(Semantics)、词汇(Lexical)
10 | * 操作符:(+、-、*、/),(==、!=、<、>=、<=),(&、|、^、~、<< 、>>),(and、or、not),(in、not in)
11 | * 程序结构:包、模块、函数/类
12 | * 面向对象:属性 + 方法,公有、私有、实例化
13 | * 接口:是定义,不实现
14 | * 闭包:避免了全局变量的使用,包裹里有自由变量
15 | * 元编程:不要重复自己
16 | * 测试:unittest、doctest、py.test、mock、自动化、持续集成
17 | * 设计模式:有很多,记住三大类:创建、结构、行为
18 | * 领域特定语言:内部DSL和外部DSL的使用帮助你应对特定领域问题,如数据库查询、文本处理等
19 |
20 | ### Django知识点
21 | * Django 包含了开发动态 Web 应用的几乎所有相关知识,一站式框架帮助你快速建立完整知识结构
22 | * 核心:模型、模板、视图
23 | * 动态 Web 应用基本功能:认证、会话、验证、分页、序列化、缓存、日志、安全、加密
24 | * 中间件:是可复用的基本功能:安全、缓存、验证、会话、消息 ...
25 | * Django 管理后台帮助更好的管理项目和应用
26 |
27 | ### PostgreSQL知识点
28 | * 使用pgAdmin连接和管理PostgreSQL会带来很多方便
29 | * 使用Psycopgs适配器
30 | * Django 提供 PostgreSQL 的特定功能:django.contrib.postgres
31 |
32 | 配图来自Twitter:@tomo_3
33 |
34 | 
35 |
--------------------------------------------------------------------------------
/courses/python17.md:
--------------------------------------------------------------------------------
1 | # 第17课:模块/库(Module/Library)(二)
2 |
3 | ### 编写自己的模块
4 | 写一个简单的模块文件,包含两个类,每个类有一个函数。
5 |
6 | ```
7 | # mymodule.py
8 | class A:
9 | def python(self):
10 | print('A.python')
11 |
12 | class B(A):
13 | def julia(self):
14 | print('B.julia')
15 | ```
16 |
17 | 运行mymodule
18 |
19 | ```
20 | >>> import mymodule
21 | >>> a = mymodule.A()
22 | >>> a.python()
23 | A.python
24 | >>> b = mymodule.B()
25 | >>> b.julia()
26 | B.julia
27 | ```
28 | ### 对这个模块文件进行分解
29 | 用mymodule目录来替换文件 mymodule.py,创建 a.py、b.py和__init__.py文件。
30 |
31 | ```
32 | mymodule/
33 | __init__.py
34 | a.py
35 | b.py
36 | ```
37 |
38 | a.py文件内容
39 | ```
40 | # a.py
41 | class A:
42 | def python(self):
43 | print('A.python')
44 | ```
45 |
46 | b.py文件内容
47 | ```
48 | # b.py
49 | from .a import A
50 | class B(A):
51 | def julia(self):
52 | print('B.julia')
53 | ```
54 |
55 | __init__.py文件内容
56 | ```
57 | # __init__.py
58 | from .a import A
59 | from .b import B
60 | ```
61 |
62 | 然后你也试试调用模块与函数。
63 |
64 | 真正的模块化设计和开发可没这么简单,这里只是让大家先有一个基本的概念。
65 |
66 | 好吧,今天就先到这,可以放学了 :)
67 |
68 | 配图来自Twitter:@chengr28
69 |
70 | 
71 |
--------------------------------------------------------------------------------
/courses/python38.md:
--------------------------------------------------------------------------------
1 | # 第38课:模板(二)
2 |
3 | ### Django template language(DTL)
4 | 了解一些基本语法,这些标签和过滤器可以是内置的,也可以自定义的:
5 | * 变量(variable):{{ and }}
6 |
7 | My first name is {{ first_name }}. My last name is {{ last_name }}.
8 |
9 | * 标签(Tags):{% and %}
10 |
11 | {% if user.is_authenticated %}Hello, {{ user.username }}.{% endif %}
12 |
13 | * 过滤器(Filters):{{ | }}
14 |
15 | {{ django|title }}
16 |
17 | * 注释(Comments):{# and #}
18 |
19 | {# this won't be rendered #}
20 |
21 | ### 自定义标签
22 | 注册自定义标签:django.template.Library.simple_tag()
23 | ```
24 | import datetime
25 | from django import template
26 | register = template.Library()
27 | @register.simple_tag
28 | def current_time(format_string):
29 | return datetime.datetime.now().strftime(format_string)
30 | ```
31 |
32 | ### 自定义过滤器
33 | 自定义的过滤器就是一些有一到两个参数的Python函数,如:
34 |
35 | 在过滤器``{{ var|foo:"bar" }}``中,变量``var``和参数``bar``会传递给过滤器``foo``
36 |
37 | 注册自定义过滤器:django.template.Library.filter()
38 | ```
39 | >>> from django import template
40 | >>> register = template.Library()
41 | >>> @register.filter
42 | ... def lower(value):
43 | ... return value.lower()
44 | ```
45 |
46 | 配图来自Twitter:@chengr28
47 |
48 | 
49 |
--------------------------------------------------------------------------------
/courses/python03.md:
--------------------------------------------------------------------------------
1 | # 第3课:数据类型(一)
2 |
3 | 将以下内容以Jupyter Notebook的方式做练习和自己总结,可存档附件到作业后面。
4 |
5 | Python3 的六个标准数据类型中:
6 | * 不可变数据(3个):Number(数字)、String(字符串)、Tuple(元组);
7 | * 可变数据(3个):List(列表)、Dictionary(字典)、Set(集合)。
8 |
9 | ps:集合有可变集合(set())和不可变集合(frozenset)两种。
10 |
11 | 接下来我们分两次课介绍列表、元组、集合和字典
12 |
13 | 列表 []、元组 ()、集合 {}、字典 {key: value}
14 |
15 | 首先了解下Number:整数(int)、浮点数(float)、复数(complex)
16 |
17 | 也可以使用十六进制和八进制来代表整数
18 |
19 | ```
20 | >>> number = 0xB0F # 十六进制
21 | >>> number
22 | 2831
23 | >>> number=0o27 # 八进制
24 | >>> number
25 | 23
26 | ```
27 | 类型转换
28 |
29 | 如:浮点数转整数
30 | ```
31 | >>> a = 3.3
32 | >>> int(a)
33 | 3
34 | ```
35 | 内置的数学函数、随机数函数、三角函数、数学常量
36 |
37 | 依此举例:
38 | ```
39 | >>>abs(-3)
40 | >>>import random
41 | >>>random.randint(1,99)
42 | 57
43 |
44 | >>> math.sin(100)
45 | -0.5063656411097588
46 |
47 | >>> math.pi
48 | 3.141592653589793
49 |
50 | >>> math.e
51 | 2.718281828459045
52 | ```
53 |
54 | 大家去去找到这些内容完整介绍,并试试其它一些函数。
55 |
56 | Python3的列表和元组很类似,区别是元组的元素不可变。
57 |
58 | 列表用[],元组用(),如:
59 | ```
60 | >>>list1 = [1, 2, 3, 4, 5]
61 | >>>list1[0] = 10 # 合法
62 | >>>tup1 = (1, 2, 3, 4, 5)
63 | >>>tup1[0] = 10 # 非法
64 | ```
65 |
66 | 配图来自:Twitter
67 |
68 | 
--------------------------------------------------------------------------------
/courses/python39.md:
--------------------------------------------------------------------------------
1 | # 第39课:表单(一)
2 |
3 | ### 表单
4 | 若你的网站需要接收访问者的输入,就需要理解和使用表单。
5 |
6 | 创建 Form 类时,最重要的是定义表单的字段,以及每个字段的验证逻辑。
7 |
8 | Django 提供了一系列的工具和库来帮助您构建表单来接收网站访客的输入,然后处理以及响应这些输入。
9 |
10 | ### 内置字段
11 | 这是一个完整的示例 Form,它为两个字段实现标签,并指定了 auto_id = False 来简化输出:
12 | ```
13 | >>> from django import forms
14 | >>> class CommentForm(forms.Form):
15 | ... name = forms.CharField(initial='Allen')
16 | ... url = forms.URLField(initial='https://huihoo.com')
17 | ... comment = forms.CharField()
18 | ...
19 | >>> f = CommentForm(auto_id=False)
20 | >>> print(f)
21 | | Name: | |
22 | | Url: | |
23 | | Comment: | |
24 | ```
25 |
26 | ### 内置widgets
27 | widget 是 Django 对 HTML 输入元素的表示,widget 处理 HTML 的渲染,以及从与 widget 对应的 GET/POST 字典中提取数据。
28 |
29 | 一个简单的 widget:Textarea
30 | ...
31 | from django import forms
32 |
33 | class CommentForm(forms.Form):
34 | name = forms.CharField()
35 | url = forms.URLField()
36 | comment = forms.CharField(widget=forms.Textarea)
37 | ...
38 |
39 | 配图来自Twitter:@chengr28
40 |
41 | 
--------------------------------------------------------------------------------
/courses/python20.md:
--------------------------------------------------------------------------------
1 | # 第20课:元编程(Metaprogramming)
2 | 软件开发领域中最经典的口头禅就是“don’t repeat yourself”。 也就是说,任何时候当你的程序中存在很多重复的代码时,我们都应该想想是否有更好的解决方案。在Python当中,通常都可以通过元编程来解决这类问题,主要技术是使用装饰器、类装饰器和元类。
3 |
4 | ## 在函数上添加包装器
5 |
6 | 1、定义一个装饰器,增加额外的操作处理(如日志、计时、计数等),也可定义多个装饰器。
7 |
8 | 此装饰器是通过@wraps来实现的。
9 |
10 | ```
11 | import time
12 | from functools import wraps
13 |
14 | def timethis(func):
15 | '''
16 | 装饰器报告执行时间
17 | '''
18 | @wraps(func)
19 | def wrapper(*args, **kwargs):
20 | start = time.time()
21 | result = func(*args, **kwargs)
22 | end = time.time()
23 | print(func.__name__, end-start)
24 | return result
25 | return wrapper
26 | ```
27 |
28 | 2、使用装饰器
29 | ```
30 | >>> @timethis
31 | ... def countdown(n):
32 | ... '''
33 | ... 计数
34 | ... '''
35 | ... while n > 0:
36 | ... n -= 1
37 | ...
38 | >>> countdown(1000)
39 | countdown 5.602836608886719e-05
40 | >>> countdown(10000)
41 | ```
42 | 3、解除装饰器
43 | 使用__wrapped__解除装饰器
44 | ```
45 | >>> countdown.__wrapped__(1000)
46 | >>> countdown.__wrapped__(10000)
47 | ```
48 | 这时就没打印时间信息了
49 |
50 | 注意:并不是所有的装饰器都使用了 @wraps,如内置的装饰器 @staticmethod 和 @classmethod 就没有遵循这个约定 (它们把原始函数存储在属性 __func__ 中)。
51 |
52 | 嗯,有点累了,带狗狗出去散下步。
53 |
54 | 配图来自Twitter:@chengr28
55 |
56 | 
57 |
--------------------------------------------------------------------------------
/courses/python48.md:
--------------------------------------------------------------------------------
1 | # 第48课:安全概览
2 |
3 | 在 Web 应用的发展中,安全是最重要主题,Django 提供了多种保护手段和机制。
4 |
5 | 本节课概述 Django 安全功能,以及 Django 驱动网站的安全建议。
6 |
7 | ### XSS 保护
8 | Cross site scripting (XSS) 攻击允许恶意用户将客户端脚本注入其他用户的浏览器中,这通常通过让用户单击链接来实现,该链接将导致攻击者的JavaScript由用户的浏览器执行。
9 |
10 | 使用 Django 模板可以保护你免受大多数XSS攻击,存在一定局限性。
11 |
12 | ### CSRF 保护
13 | Cross site request forgery (CSRF) 攻击允许恶意用户使用其他用户的证书(credentials)执行操作,而无需用户的知情或同意。
14 |
15 | Django 内置了针对大多数类型的CSRF攻击的保护,只要你在适当的地方启用和使用它,也存在一定局限性。
16 |
17 | CSRF 通过检查每个POST请求中的 secret 来保护工作,用户可使用 csrf_exempt 装饰器标记视图。
18 |
19 | ### SQL 注入保护
20 | SQL 注入(injection)是一种攻击类型,恶意用户可以在数据库上执行任意SQL代码,这可能导致数据库记录被删除或数据泄漏。
21 |
22 | Django 查询集(querysets)受到SQL注入的保护,它们的查询是使用查询参数化构造的,查询的SQL语句与查询的参数分开定义。由于参数可能是用户提供的,因此不安全,所以它们会被底层数据库驱动程序转义(escaped)。
23 |
24 | ### 点击劫持保护
25 | 点击劫持(Clickjacking)也是一种攻击类型,其中恶意网站将另一个站点包装(wraps)在一个帧中,此攻击可能导致不知情的用户被欺骗在目标站点上执行意外操作。
26 |
27 | Django 包含 X-Frame-Options 中间件形式的点击劫持保护,在支持的浏览器中可以防止网站在框架内渲染。
28 |
29 | ### SSL/HTTPS
30 | 支持 HTTPS 的站点拥有更好的安全性,请尽可能使用它。
31 |
32 | ### Header 验证
33 | 这个主要是防虚假主机的,因为即使安全配置了的 Web 服务器也容易受到虚假主机 Headers 的影响,Django 会根据 django.http.HttpRequest.get_host() 方法中的 ALLOWED_HOSTS 设置验证主机 Headers。
34 |
35 | ### Session 安全
36 | 这块是有关 [django.contrib.sessions](python42.md) 的主题。
37 |
38 | 配图来自Twitter:@tomo_3
39 |
40 | 
41 |
--------------------------------------------------------------------------------
/courses/python26.md:
--------------------------------------------------------------------------------
1 | # 第26课:入门 - 请求和响应(一)
2 |
3 | ### 创建第一个Django应用
4 | 注意这里是创建应用而不是创建项目:
5 | * 应用是一个专门做某件事的网络应用程序——比如博客系统,或者简单的投票程序。
6 | * 项目则是一个网站使用的配置和应用的集合。项目可以包含很多个应用。应用可以被很多个项目使用。
7 |
8 | 进入上一节课创建的 mysite 目录,然后运行:
9 |
10 | $ python manage.py startapp polls
11 | ```
12 | polls/
13 | __init__.py
14 | admin.py
15 | apps.py
16 | migrations/
17 | __init__.py
18 | models.py
19 | tests.py
20 | views.py
21 | ```
22 |
23 | ### 编写第一个视图
24 | 打开 polls/views.py,加入以下代码:
25 | ```
26 | from django.http import HttpResponse
27 |
28 | def index(request):
29 | return HttpResponse("Hello Polls")
30 | ```
31 |
32 | ### 创建URLconf
33 | 新建urls.py,加入以下代码:
34 | ```
35 | from django.urls import path
36 |
37 | from . import views
38 |
39 | urlpatterns = [
40 | path('', views.index, name='index'),
41 | ]
42 | ```
43 |
44 | ### 修改根URLconf
45 | 打开 mysite/urls.py,插入一个include():
46 | ```
47 | from django.contrib import admin
48 | from django.urls import path
49 | from django.conf.urls import include
50 |
51 | urlpatterns = [
52 | path('polls/', include('polls.urls')),
53 | path('admin/', admin.site.urls),
54 | ]
55 | ```
56 |
57 | ### 运行应用
58 | $ python manage.py runserver
59 |
60 | http://localhost:8000/polls/
61 |
62 | 浏览器返回:Hello Polls
63 |
64 | 好了,我们完成了第一个应用创建和请求与响应。
65 |
66 | 配图来自Twitter:@DSmile9
67 |
68 | 
69 |
--------------------------------------------------------------------------------
/courses/python30.md:
--------------------------------------------------------------------------------
1 | # 第30课:入门 - 完善管理后台(五)
2 |
3 | ### 增加选项
4 | 在之前的课程中,我们通过管理后台创建了三个问题,但它们都还没有选项,现在我们就把这些选项添加上。
5 |
6 | 通过 admin.site.register(Question) 注册 Question 模型,Django 能够构建一个默认的表单用于展示。
7 |
8 | 编辑 polls/admin.py,提供3个选项(Choice)字段:
9 | ```
10 | from django.contrib import admin
11 | from .models import Choice, Question
12 |
13 | class ChoiceInline(admin.TabularInline):
14 | model = Choice
15 | extra = 3
16 |
17 | class QuestionAdmin(admin.ModelAdmin):
18 | fieldsets = [
19 | (None, {'fields': ['question_text']}),
20 | ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
21 | ]
22 | inlines = [ChoiceInline]
23 |
24 | admin.site.register(Question, QuestionAdmin)
25 | ```
26 |
27 | 编辑 mysite/settings.py,将 templates 加入 DIRS 选项会带来更多便利。
28 | ```
29 | 'DIRS': [os.path.join(BASE_DIR, 'templates')],
30 | ```
31 |
32 | 运行下:$ python manage.py runserver
33 |
34 | 通过管理后台:http://localhost:8000/admin 创建三个问题的选项,每个问题可有三个选项:
35 |
36 | 可以这样创建:
37 | ```
38 | 问题一:
39 | 1A
40 | 1B
41 | 1C
42 | 问题二:
43 | 2A
44 | 2B
45 | 2C
46 | 问题三:
47 | 3A
48 | 3B
49 | 3C
50 | ```
51 | 
52 |
53 | 好了,问题和每个问题的选项都创建好了,现在通过 http://localhost:8000/polls/ 去给每个问题的选项投票。
54 |
55 | 
56 |
57 | 这个例子算是比较完整的跑起来了,管理后台可调整和完善的地方还有很多,你可以一点点去试试。
58 |
59 | 配图来自Twitter:@atikix
60 |
61 | 
62 |
--------------------------------------------------------------------------------
/courses/python04.md:
--------------------------------------------------------------------------------
1 | # 第4课:数据类型(二)
2 |
3 | 将以下内容以Jupyter Notebook的方式做练习和自己总结,可存档附件到作业后面。
4 |
5 | 上节课我们学习了列表[]和元组(),接下来学习集合 {}、字典 {key: value}
6 |
7 | 集合(set)是一个无序不重复元素的序列,如:
8 | ```
9 | >>>set1 = set() # 空集合用set()
10 | >>>set2 = {'a', 'b', 'c', 'd'}
11 | >>>set2.add(“e”)
12 | ```
13 |
14 | 字典可存储任意类型对象,列表是有序的对象集合,字典是无序的对象集合。
15 | ```
16 | >>> dict1 = {'Name': 'Allen', 'Age': 44}
17 | >>> dict1['Age'] = 34
18 | ```
19 |
20 | 接着,我们展开这些内容。
21 |
22 | 集合操作:添加元素、移除元素、集合个数、是否存在、清空集合
23 |
24 | 1、添加元素
25 | ```
26 | >>>set2.add(‘f’) 或 set2.update(‘f’) # 注意:无序
27 | ```
28 |
29 | 2、移除元素
30 | ```
31 | >>>set2.remove(‘f’) 或 set2.discard('f') 或 set2.pop()
32 | ```
33 |
34 | 3、集合个数
35 | ```
36 | >>>len(set2)
37 | ```
38 |
39 | 4、是否存在
40 | ```
41 | >>>'a' in set2
42 | ```
43 |
44 | 5、清空集合
45 | ```
46 | >>>set2.clear()
47 | ```
48 |
49 | 字典操作:访问、修改、个数、删除
50 |
51 | 1、访问
52 | ```
53 | >>> dict1['Name']
54 | ```
55 |
56 | 2、修改
57 | ```
58 | >>> dict1['Name'] = "Python"
59 | ```
60 |
61 | 4、个数
62 | ```
63 | >>> len(dict1)
64 | ```
65 |
66 | 4、删除
67 | ```
68 | >>> del dict1['Name'] # 删除键
69 | >>> dict1.clear() # 清空字典,空字典还在
70 | >>> del dict1 # 删除字典,没了
71 | ```
72 |
73 | 还有些其它字典内置函数&方法,自己可找找学习下。
74 |
75 | 最后,做一个循环输出字典键或字典值的练习,提示:for循环、keys、values。
76 |
77 | ```
78 | >>> dict = {1: "C", 2: "C++", 3: "Java", 4: "Python"}
79 | ```
80 |
81 | 我要交作业啦 奖励自己一根雪糕 :)
82 |
83 | 配图来自Twitter:@makadamixa
84 |
85 | 
--------------------------------------------------------------------------------
/courses/python09.md:
--------------------------------------------------------------------------------
1 | # 第9课:语法(Syntax)、语义(Semantics)、词汇(Lexical)(一)
2 |
3 | 将以下内容以Jupyter Notebook的方式做练习和自己总结,并保存.ipynb。
4 |
5 | 这节课我们从以下几点入手,更多了解Python语言的一些基本原理,它们容易理解和掌握,不会很枯燥。
6 |
7 | * 语法(Syntax)
8 | * 语义(Semantics)
9 | * 词汇(Lexical)
10 |
11 | 这是编程语言都会涉及的几个概念,它们定义了Python语言的规范,大家需了解下。
12 |
13 | 如: AST(Abstract Syntax Trees)抽象语法树,词法分析(标识符、关键字)。在学习时可对应英语的语法、语义、句法想想,能帮助理解它们大致的意思。
14 |
15 | 这里先给大家引出两个概念:编译时(Compile time)和运行时(Runtime)
16 |
17 | 一个现代编译器的主要工作流程如下: 源代码(source code)→ 预处理器(preprocessor)→ 编译器(compiler)→ 汇编程序(assembler)→ 目标代码(object code)→ 链接器(Linker)→ 可执行文件(executables)
18 | 
19 |
20 | 
21 |
22 | 此图是C#的编译过程,其思路也适用于Python语言,Python语法、语义、词汇等概念也贯穿于其中。
23 |
24 | 通过 Python Language Services 和 Python Runtime Services 标准库服务
25 |
26 | Python完成源码的语法解析、抽象语法树处理、访问编译器符号表、编译器编译.py源码成字节码、交由虚拟机运行。和现代编译器的主要工作流程类似。
27 |
28 | 这里:解释器(interpreter)由字节码编译器和虚拟机组成,虚拟机起着类似运行时的作用。
29 |
30 | 简单讲就是:字节码编译器、字节码虚拟机。
31 |
32 | 
33 | 
34 | Python虚拟机是Python的核心,在.py源代码被字节码编译器编译为字节码指令序列后,将由字节码虚拟机接手,依次读入每一条字节码指令,并在当前的上下文环境中执行这条字节码指令。
35 |
36 | 参考资料:
37 | * [Python Language Reference](https://docs.python.org/3/reference/index.html) 描述了Python的语法和核心语义。
38 |
39 | 这节课的主要目的就是大家理解下Python的编译原理和解释过程,下节课我们实际操作下编译过程。
40 |
41 | 配图来自Twitter:@MacciattoS2
42 |
43 | 
--------------------------------------------------------------------------------
/courses/python50.md:
--------------------------------------------------------------------------------
1 | # 第50课:中间件
2 |
3 | 前面的课程中我们都有使用到 Django 中间件,这里我们简单梳理一下。
4 |
5 | 中间件是可调用的,它接受请求并返回响应,就像视图一样。
6 |
7 | 中间件是 Django 请求/响应处理的钩子框架。它是一个轻量级的、低层的插件系统,用于全局改变 Django 的输入或输出。
8 |
9 | 每个中间件组件负责做一些特定的功能。如,AuthenticationMiddleware 中间件 ,它使用会话将用户与请求关联起来。
10 |
11 | 一些常见的功能我们可以采用中间件的方式,当然,我们也可以开发新的中间件。
12 |
13 | 中间件是有顺序的,因为中间件会依赖其他中间件。你可以把它想象成一个洋葱:每个中间件都是一个层,它们覆盖了洋葱的核心。如果请求是通过洋葱的所有层(每一个调用 get_response )以将请求传递到下一层,一直到内核的视图,那么响应将在返回的过程中通过每个层(以相反的顺序)。
14 |
15 | 以下是中间件的顺序(ordering):
16 | * 1、SecurityMiddleware
17 | * 2、UpdateCacheMiddleware
18 | * 3、GZipMiddleware
19 | * 4、SessionMiddleware
20 | * 5、ConditionalGetMiddleware
21 | * 6、LocaleMiddleware
22 | * 7、CommonMiddleware
23 | * 8、CsrfViewMiddleware
24 | * 9、AuthenticationMiddleware
25 | * 10、MessageMiddleware
26 | * 11、FetchFromCacheMiddleware
27 | * 12、FlatpageFallbackMiddleware
28 | * 13、RedirectFallbackMiddleware
29 |
30 | ### SecurityMiddleware
31 | 这里主要介绍 django.middleware.security.SecurityMiddleware 安全中间件
32 |
33 | 它在 settings.py 定义:
34 | ```
35 | MIDDLEWARE = [
36 | 'django.middleware.security.SecurityMiddleware',
37 | ```
38 | SecurityMiddleware 为应用的请求和响应周期提供了若干安全增强功能,每个都可以设置启用或禁用。
39 | * SECURE_BROWSER_XSS_FILTER
40 | * SECURE_CONTENT_TYPE_NOSNIFF
41 | * SECURE_HSTS_INCLUDE_SUBDOMAINS
42 | * SECURE_HSTS_PRELOAD
43 | * SECURE_HSTS_SECONDS
44 | * SECURE_REDIRECT_EXEMPT
45 | * SECURE_SSL_HOST
46 | * SECURE_SSL_REDIRECT
47 |
48 | 配图来自Twitter:@tomo_3
49 |
50 | 
51 |
--------------------------------------------------------------------------------
/courses/python02.md:
--------------------------------------------------------------------------------
1 |
2 | # 第2课:快速熟悉Python
3 |
4 | * 一行Python代码,Hello World
5 | * 了解整数、浮点数、字符串、布尔值
6 | * 了解变量、关键字、变量命名规范
7 |
8 | 运行Anaconda下的Jupyter,完成以下的一些操作:
9 |
10 | ### (1)hello world
11 | `print “Hello World” `
12 |
13 | 能运行吗?若不行,请搜索并完成正确print打印。
14 | 注意:我们现在使用的是Python3。
15 |
16 | ### (2)数据类型
17 | ```
18 | counter = 100 # 整型变量
19 | miles = 100.0 # 浮点型变量
20 | a, b = 1, 2 # 多个变量赋值
21 | name = “Python” # 字符串
22 |
23 | true, false # 布尔值
24 |
25 | print (counter)
26 | print (miles)
27 | print (name)
28 |
29 | print(type(name))
30 | isinstance(name, str)
31 | ```
32 |
33 | ### (3)类型转换
34 | ```
35 | 整数 -> 浮点数
36 | a = 12
37 | b = float(a)
38 | a
39 | b
40 |
41 | 浮点数 -> 整数
42 | c = 12.0
43 | d = int(c)
44 | c
45 | d
46 | ```
47 |
48 | 扩展练习:其它类型的相互转换。
49 |
50 | ### (4)关键字
51 | 关键字即保留字,我们不能把它们用作任何标识符命名。
52 |
53 | Python关键字有哪些?
54 | ```
55 | import keyword
56 | keyword.kwlist
57 | ```
58 | 然后记住它们
59 |
60 | ### (5)一些命名规范:
61 | * a、必须以一个字母或一个下划线字符开头;
62 | * b、字母可以是大小写,但大小写是不同的,如:Ax不同于aX;
63 | * c、数字可以是从0到9的任意数字。
64 |
65 | 合法变量名:
66 | * my_answer
67 | * answer12
68 | * answer_12
69 | * YourAnswer
70 |
71 | 不合法变量名:
72 | * 12answer(不能以数字开头)
73 | * your-answer(不允许连字符)
74 | * my answer (不允许有空格)
75 |
76 | ### (6)
77 | 作业2:type()和isinstance()的区别
78 |
79 | 运行下看系统给出的一些信息:
80 | ```
81 | a = 100
82 | print(type(a)
83 |
84 | b = 101
85 | isinstance(b, int)
86 | ```
87 | 搜索整理出区别点和关系。
88 |
89 | 最后,可小结和总结下(1-5) 知识点和Jupyter操作截图 + (6)的作业一起提交作业。
90 |
91 | 配图来自Twitter:@MacciattoS2
92 |
93 | 
--------------------------------------------------------------------------------
/courses/python34.md:
--------------------------------------------------------------------------------
1 | # 第34课:模型(二)
2 |
3 | ### 管理员
4 | Manager是为Django模型提供的数据库查询接口,Django应用中的每个模型都至少存在一个Manager。
5 |
6 | $ python manage.py shell
7 | ```
8 | >>> from polls.models import Person
9 | >>> Person.objects
10 |
11 | >>> Person.objects.all()
12 | , ]>
13 | ```
14 | 我们使用Person模型上的Manager构造QuerySet从数据库检索对象。
15 |
16 | ### 数据库事务
17 | 事务是指具有原子性的一系列数据库操作。即使是程序崩溃,数据库也会确保这些操作要么全部完成(commit)要么全部都未执行(rollback)。
18 |
19 | Django 默认的事务行为是自动提交。
20 |
21 | 工作原理:将每个HTTP请求封装在一个事务中,配置中的参数 ATOMIC_REQUESTS 设置为 True(默认为 False)。在调用试图方法前,Django 先生成一个事务。如果响应能正常生成,Django 会提交该事务。而如果视图出现异常,Django 则会回滚该事务。
22 |
23 | 你还可以在视图代码中执行子事务,会使用 atomic。
24 |
25 | 先了解这些概念,以后再深入这块。
26 |
27 | ### 迁移
28 | Web应用的开发就是一个持续的过程,其数据库表结构也处于不断增删改的迭代过程中,一套完整的数据库维护机制显得非常重要,Django 为此提供了数据库迁移功能很好的应对这项工作。
29 |
30 | 主要的命令有:
31 | ```
32 | $ python manage.py makemigrations polls # 生成迁移文件,如:0001_initial.py
33 | $ python manage.py sqlmigrate polls 0001 # 生成SQL,可看看是不是自己想要的结果
34 | $ python manage.py migrate # 执行迁移,完成创建新表等任务
35 | ```
36 |
37 | ### 数据库函数
38 | Django提供了以下几类数据库函数:
39 | * 比较和转换函数:如Cast、Coalesce、Greatest、Least
40 | * 日期函数:如Now ...
41 | * 文本函数:如Length、Lower、Upper ...
42 | * Window函数:如Rank ...
43 |
44 | ```
45 | >>> from datetime import datetime
46 | >>> dt = datetime(2019, 2, 10)
47 | >>> (dt.isoweekday() % 7) + 1
48 | 1
49 | ```
50 | 1 for Sunday, 2 for Monday, through 7 for Saturday.
51 |
52 | 配图来自Twitter:@kagachi_SK
53 |
54 | 
55 |
--------------------------------------------------------------------------------
/courses/python05.md:
--------------------------------------------------------------------------------
1 | # 第5课:条件
2 |
3 | 将以下内容以Jupyter Notebook的方式做练习和自己总结,可存档附件到作业后面。
4 |
5 | 条件:if - elif - else,每个后面跟冒号:
6 | 注意:python没有switch – case语句
7 |
8 | 常用的操作符
9 | ```
10 | < 小于
11 | <= 小于或等于
12 | > 大于
13 | >= 大于或等于
14 | == 等于
15 | != 不等于
16 | ```
17 |
18 | 创建 test05.py
19 | ```
20 | #!/anaconda3/bin/python3
21 | import random
22 |
23 | x = random.choice(range(10))
24 | y = random.choice(range(20))
25 |
26 | if x > y:
27 | print('x:', x)
28 | elif x == y:
29 | print('x = y =', x)
30 | else:
31 | print('y:', y)
32 | ```
33 |
34 | python3 test05.py
35 | ```
36 | if - elif - else可嵌套,类似这样:
37 | if 条件1:
38 | 语句
39 | if 条件2:
40 | 语句
41 | elif 条件3:
42 | 语句
43 | else:
44 | 语句
45 | elif 条件4:
46 | 语句
47 | else:
48 | ```
49 | 一组有趣的例子:条件为真或为假
50 |
51 | 1、条件为真:不为0、为True、为”None”
52 | ```
53 | >>> a = 1
54 | >>> if a:
55 | ... print("True")
56 | ... else:
57 | ... print("False")
58 | ...
59 | True
60 |
61 | >>> a = "None"
62 | >>> if a:
63 | ... print("True")
64 | ... else:
65 | ... print("False")
66 | ...
67 | True
68 | ```
69 | 2、条件为假:为0、为False、为None
70 | ```
71 | >>> a = 0
72 | >>> if a:
73 | ... print("True")
74 | ... else:
75 | ... print("False")
76 | ...
77 | False
78 |
79 | >>> a = None
80 | >>> if a:
81 | ... print("True")
82 | ... else:
83 | ... print("False")
84 | ...
85 | False
86 | ```
87 | 你再试试 a = True 或 False的情况。
88 |
89 | 有点困了,该睡觉了。月亮
90 |
91 | 配图来自Twitter:@atikix
92 |
93 | 
--------------------------------------------------------------------------------
/courses/python45.md:
--------------------------------------------------------------------------------
1 | # 第45课:序列化
2 |
3 | ### 简介
4 | Django 序列化框架提供了一种将 Django 模型转换为其他格式的机制。
5 |
6 | Django 支持的序列化格式有:
7 | * XML
8 | * JSON
9 | * YAML
10 |
11 | ### 序列化
12 | ```
13 | >>> from django.core import serializers
14 | >>> with open("person.xml", "w") as out:
15 | ... xml_serializer.serialize(Person.objects.all(), stream=out)
16 | ```
17 | 这时在目录下生成了 person.xml,内容如下:
18 | ```
19 |
20 |
21 |
24 |
27 |
28 | ```
29 | 试试 JSON 格式:
30 | ```
31 | >>> from django.core.serializers import serialize
32 | >>> with open("person.json", "w") as out:
33 | ... serialize('json', Person.objects.all(), stream=out)
34 | ```
35 | 目录下生成了 person.json,内容如下:
36 | ```
37 | [
38 | {
39 | "model": "polls.person",
40 | "pk": 1,
41 | "fields": {
42 | "first_name": "Allen", "last_name": "Long"
43 | }
44 | },
45 | {
46 | "model": "polls.person",
47 | "pk": 2,
48 | "fields": {
49 | "first_name": "Peter", "last_name": "Chen"
50 | }
51 | }
52 | ]
53 | ```
54 |
55 | ### 反序列化
56 |
57 | 配图来自Twitter:@ukiukisoda
58 |
59 | 
60 |
--------------------------------------------------------------------------------
/courses/python06.md:
--------------------------------------------------------------------------------
1 | # 第6课:循环
2 |
3 | 将以下内容以Jupyter Notebook的方式做练习和自己总结,并保存.ipynb。
4 |
5 | 循环:for 和 while
6 |
7 | while循环语句
8 | ```
9 | >>> i = 0
10 | >>> while i < 6:
11 | ... print(i)
12 | ... i = i + 1
13 | ```
14 |
15 | break语句
16 | ```
17 | >>> i = 0
18 | >>> while i < 6:
19 | ... print(i)
20 | ... i = i + 1
21 | ... if i == 5:
22 | ... break
23 | ```
24 |
25 | continue语句
26 | ```
27 | >>> i = 0
28 | >>> while i < 6:
29 | ... print(i)
30 | ... i = i + 1
31 | ... if i < 5:
32 | ... continue
33 | ```
34 |
35 | 无限循环
36 | ```
37 | >>>while True:
38 | print(‘Hello World!’)
39 | ```
40 |
41 | for循环和range()函数
42 |
43 | 可以通过range()函数遍历数字序列
44 | ```
45 | >>> for i in range(6):
46 | ... print(i)
47 | ```
48 |
49 | range()开始、结束、步长
50 | ```
51 | >>> for i in range(0, 10, 2):
52 | ... print(i)
53 |
54 | >>> for i in range(10, -2, -2):
55 | ... print(i)
56 | ```
57 |
58 | 可以有几种方式:
59 |
60 | 方式一:for循环
61 | ```
62 | >>> sum = 0
63 | >>> for num in range(101):
64 | ... sum = sum + num
65 | ...
66 | >>> print(sum)
67 | ```
68 |
69 | 方式二:while循环
70 | ```
71 | >>> sum = 0
72 | >>> n = 1
73 | >>> while n < 101:
74 | ... sum = sum + n
75 | ... n+=1
76 | ...
77 | >>> print(sum)
78 | ```
79 |
80 | 方式三:导入reduce函数
81 | ```
82 | >>> def sum(x, y):
83 | ... return x + y
84 | ...
85 | >>> from functools import reduce
86 | >>> print(reduce(sum ,range(1, 101)))
87 | ```
88 |
89 | 扩展练习:
90 | * 1-100的奇数相加之和
91 | * 1-100的偶数相加之和
92 |
93 | 天气有些热,喝杯冰红茶。
94 |
95 | 配图来自Twitter:@atikix
96 |
97 | 
--------------------------------------------------------------------------------
/courses/python01.md:
--------------------------------------------------------------------------------
1 |
2 | # 第1课:Python历史、版本、安装
3 |
4 | ### 1、了解Python语言和历史
5 | 认识Python之父,Guido von Rossum,荷兰人,数学和计算机双硕士。除了解决常规问题,Python也是处理数学问题的好帮手,在大数据分析、金融数据分析里,都能看到Python在回归、积分、符号计算、统计、随机数、金融衍生品方面的应用,后续课程都会有所涉及。
6 |
7 | 
8 |
9 | Python语言以对象为核心组织代码(Everything is object),支持多种编程范式(multi-paradigm),采用动态类型(dynamic typing),自动进行内存回收(garbage collection)。支持解释运行(interpret),并能调用C库进行拓展,解决性能问题。Python有强大的标准库 (battery included,开箱即用)。由于标准库的体系已经稳定,所以Python开始拓展到第三方包和框架,如Django、Flask、Web.py、WxPython、Numpy、Matplotlib、PIL 和大量人工智能机器学习库,Python已变成极富生命力的生态系统。
10 |
11 | 著名的口号:人生苦短,我用Python。
12 |
13 | 参考读物: [Python简史](http://www.cnblogs.com/vamei/archive/2013/02/06/2892628.html)
14 |
15 | ### 2、Python版本
16 | Python两大版本:Python3和Python2,若没有历史遗留问题就直接使用Python3,有关Python3和Python2的更多细节,请看知乎。
17 |
18 | [应该学习最新版本的 Python 3 还是旧版本的 Python 2?](https://www.zhihu.com/question/24549965)
19 |
20 | 总之,Python3才是Python的未来,大家现在都没有历史包袱,所以Python3。
21 |
22 | ### 3、Python安装
23 | Python的安装有多种方式,这里主要介绍两种:直接安装、Anaconda安装包(建议使用,因升级和安装其它Python包都很方便,我们的课程使用Anaconda)
24 |
25 | [下载Anaconda](https://www.anaconda.com/download/)
26 |
27 | 为了验证Python是否安装正确,我们跑一个简单区块链应用。
28 |
29 | [blockchain-python](https://github.com/Carlos-Zen/blockchain-python)
30 |
31 | 可直接下载压缩包或安装[Git](https://git-scm.com/)
32 |
33 | 
34 |
35 | 
36 |
37 | 完成了以上三个小任务,写点你对Python的认识并截图运行起来的区块链应用的同学就可以提交作业了。
38 |
39 | 在整个学习过程中若有任何疑问都可提出来交流,期待大家的积极参与。
40 |
41 | 
--------------------------------------------------------------------------------
/courses/python47.md:
--------------------------------------------------------------------------------
1 | # 第47课:日志
2 |
3 | Django 使用 Python 内置的 logging 模块处理日志信息。
4 |
5 | ### 日志框架
6 | 一个 Python logging 配置有以下四个部分组成:
7 | * Loggers
8 | * Handlers
9 | * Filters
10 | * Formatters
11 |
12 | #### Loggers
13 | logger 是日志系统的入口。每个 logger 都是命名的 bucket, 消息写入 bucket 以便进一步处理。
14 |
15 | 日志级别
16 | * logger.debug()
17 | * logger.info()
18 | * logger.warning()
19 | * logger.error()
20 | * logger.critical()
21 |
22 | 此外,你还可以:
23 | * logger.log():手动输出一条指定日志级别的日志消息。
24 | * logger.exception():创建一个包含当前异常堆栈帧的 ERROR 级别日志消息。
25 |
26 | #### Handlers
27 | Handler 是决定如何处理 logger 中每一条消息的引擎。它描述特定的日志行为,比如把消息输出到屏幕、文件或网络 socket。
28 |
29 | #### Filters
30 | 在日志记录从 logger 传到 handler 的过程中,使用 Filter 来做过滤操作。
31 |
32 | #### Formatters
33 | 日志记录最终是以文本呈现,Formatter 描述文本的格式。
34 |
35 | ### 配置示例
36 | 一个简单的配置,将来自 Django logger 的所有日志记录写入本地文件:
37 | ```
38 | LOGGING = {
39 | 'version': 1,
40 | 'disable_existing_loggers': False,
41 | 'handlers': {
42 | 'file': {
43 | 'level': 'DEBUG',
44 | 'class': 'logging.FileHandler',
45 | 'filename': '/var/log/django/debug.log',
46 | },
47 | },
48 | 'loggers': {
49 | 'django': {
50 | 'handlers': ['file'],
51 | 'level': 'DEBUG',
52 | 'propagate': True,
53 | },
54 | },
55 | }
56 | ```
57 |
58 | ### 使用Logger
59 | 配置好了 logger,handler,filter 和 formatter 后,就是在代码里调用 logging 模块:
60 | ```
61 | import logging
62 |
63 | logger = logging.getLogger(__name__)
64 |
65 | def my_view(request, arg1, arg):
66 | ...
67 | if bad_mojo:
68 | logger.error('Something went wrong!')
69 | ```
70 | bad_mojo 条件每次满足都会写一条 error 日志。
71 |
72 | 配图来自Twitter:@tomo_3
73 |
74 | 
75 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | MANIFEST
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 | .pytest_cache/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 | db.sqlite3
58 |
59 | # Flask stuff:
60 | instance/
61 | .webassets-cache
62 |
63 | # Scrapy stuff:
64 | .scrapy
65 |
66 | # Sphinx documentation
67 | docs/_build/
68 |
69 | # PyBuilder
70 | target/
71 |
72 | # Jupyter Notebook
73 | .ipynb_checkpoints
74 |
75 | # pyenv
76 | .python-version
77 |
78 | # celery beat schedule file
79 | celerybeat-schedule
80 |
81 | # SageMath parsed files
82 | *.sage.py
83 |
84 | # Environments
85 | .env
86 | .venv
87 | env/
88 | venv/
89 | ENV/
90 | env.bak/
91 | venv.bak/
92 |
93 | # Spyder project settings
94 | .spyderproject
95 | .spyproject
96 |
97 | # Rope project settings
98 | .ropeproject
99 |
100 | # mkdocs documentation
101 | /site
102 |
103 | # mypy
104 | .mypy_cache/
105 |
--------------------------------------------------------------------------------
/courses/python40.md:
--------------------------------------------------------------------------------
1 | # 第40课:表单(二)
2 |
3 | ### 模型表单
4 | 模型中定义了字段,表单中就不需要再定义字段类型了。每个模型字段都有一个对应的默认表单字段。
5 |
6 | Django 提供了一个辅助类让你可以从一个 Django 模型创建一个 Form 类。
7 | ```
8 | >>> from django.forms import ModelForm
9 | >>> from polls.models import Person
10 | >>> class PersonForm(ModelForm):
11 | ... class Meta:
12 | ... model = Person
13 | ... fields = ['first_name', 'last_name']
14 | ...
15 | >>> form = PersonForm('Jeff', 'Zhang')
16 | ```
17 | 思考下,如何把这条记录写入(save)数据库中。
18 |
19 | ### 表单集
20 | formset是一个抽象层,它可以在同一页面上处理多个表单。
21 |
22 | 如一次创建多个Person,需要创建 PersonForm 的 formset,方法如下:
23 | ```
24 | >>> from django.forms import formset_factory
25 | >>> PersonFormSet = formset_factory(PersonForm)
26 | >>> formset = PersonFormSet()
27 | >>> for form in formset:
28 | ... print(form.as_table())
29 | ...
30 | | |
31 | | |
32 | ```
33 | ### 字段验证
34 | Django 表单(和模型)字段支持使用简单的实用函数和称为验证器的类。验证器只是一个可调用的对象或函数,它接受一个值,如果值有效则返回任何内容,否则引发 ValidationError。
35 |
36 | 这些可以通过字段的验证器参数传递给字段的构造函数,或者使用 default_validators 属性定义在 Field 类上。
37 |
38 | SlugField 是一个带有自定义验证器的 CharField,用于验证提交的文本是否符合某些字符规则。
39 | ```
40 | >>> from django.core import validators
41 | >>> from django.forms import CharField
42 | >>>
43 | >>> class SlugField(CharField):
44 | ... default_validators = [validators.validate_slug]
45 | ...
46 | >>> slug = forms.SlugField()
47 | ```
48 |
49 | 配图来自Twitter:@chengr28
50 |
51 | 
52 |
53 |
--------------------------------------------------------------------------------
/courses/python42.md:
--------------------------------------------------------------------------------
1 | # 第42课:会话
2 |
3 | ### 了解会话
4 | 打开浏览器,我们使用 Cookie 包含会话ID,而不是数据本身(除非你使用基于cookie的后端),Django 会话框架基于 cookie,Django 有完整的会话管理解决方案,支持多种后段服务。
5 | * django.contrib.sessions.backends.db (默认)
6 | * django.contrib.sessions.backends.file
7 | * django.contrib.sessions.backends.cache
8 | * django.contrib.sessions.backends.cached_db
9 | * django.contrib.sessions.backends.signed_cookies
10 |
11 | 一旦用户通过身份验证,Django 会将之前用于验证该用户的后端保存在用户的 session 中,以便在将来(session 有效期内)需要访问当前已验证的用户时可以重用该后端。这个优化意味着在 session 中缓存了验证后端的代码,因此,如果你修改了 AUTHENTICATION_BACKENDS 同时希望使用另外的方法重新验证用户,那么需要清除 session 数据,清除 session 数据的一个简单方法是执行 Session.objects.all().delete()。
12 |
13 | 
14 | Django 会话是通过中间件实现的,在 mysite/setting.py 激活:
15 | ```
16 | INSTALLED_APPS = [
17 | 'django.contrib.sessions',
18 |
19 | MIDDLEWARE = [
20 | 'django.contrib.sessions.middleware.SessionMiddleware',
21 | ```
22 | 取某一用户的会话过期时间:
23 | ```
24 | >>> from django.contrib.sessions.models import Session
25 | >>> s = Session.objects.get(pk='ud23ao1l6fwa4ft3ut4ksxcof0mh91g4')
26 | >>> s.expire_date
27 | datetime.datetime(2019, 2, 22, 15, 13, 2, 369009, tzinfo=)
28 | ```
29 | 大家可看到,这个数据就是上图的会话数据。
30 |
31 | 大家也对照自己的数据库数据,重复这个实验过程。
32 |
33 | ### 会话设置
34 | Django 提供了一些设置可帮助你控制会话行为:
35 | * SESSION_CACHE_ALIAS
36 | * SESSION_COOKIE_AGE
37 | * SESSION_COOKIE_DOMAIN
38 | * SESSION_COOKIE_HTTPONLY
39 | * SESSION_COOKIE_NAME
40 | * SESSION_COOKIE_PATH
41 | * SESSION_COOKIE_SAMESITE
42 | * SESSION_COOKIE_SECURE
43 | * SESSION_ENGINE
44 | * SESSION_EXPIRE_AT_BROWSER_CLOSE
45 | * SESSION_FILE_PATH
46 | * SESSION_SAVE_EVERY_REQUEST
47 | * SESSION_SERIALIZER
48 |
49 | 如,SESSION_ENGINE,默认是 django.contrib.sessions.backends.db
50 |
51 |
52 | 配图来自Twitter:@ukiukisoda
53 |
54 | 
55 |
--------------------------------------------------------------------------------
/courses/python25.md:
--------------------------------------------------------------------------------
1 | # 第25课:Django web框架概述
2 |
3 |
4 | ### 简介
5 | 简单讲,Django 是一个模型-模板-视图(model-template-view,MTV)框架。
6 |
7 | $ pip install django
8 |
9 | ```
10 | $ python -m django --version 或
11 | >>> import django
12 | >>> print(django.get_version())
13 | 2.1.5
14 | ```
15 |
16 | ### 运行第一个项目
17 | $ django-admin startproject mysite
18 |
19 | 看看创建了什么
20 | ```
21 | mysite/
22 | manage.py # 一个让你用各种方式管理Django项目的命令行工具
23 | mysite/
24 | __init__.py # 一个空文件,告诉Python这个目录应该被认为是一个Python包
25 | settings.py # Django项目的配置文件
26 | urls.py # URL声明,就是网站的目录
27 | wsgi.py # 运行在WSGI兼容的Web服务器上的入口
28 | ```
29 | $ python manage.py runserver
30 |
31 | http://127.0.0.1:8000
32 |
33 | ### Why Django
34 | 用来构建Web项目的框架很多,为什么选择Django,因为个人觉得Django包含了你构建Web应用需要的所有功能,你不需要太多挑选和各种评估(这个其实是需要很多经验和实践的)而对于大多数开发者,TA们的核心工作就是开发业务和应用系统,快速搭建产品原型和持续迭代。而不用花太多时间去选择,我想这也是我推荐Django的原因。
35 |
36 | [DjangoSites](https://www.djangosites.org/) 提供一个不断增长的使用 Django 搭建的网站的列表,有很多开源的网站可直接拿来用。
37 |
38 | ### PostgreSQL
39 | 先安装并启动PostgreSQL,后面的应用都会使用到它。
40 |
41 | 使用[pgAdmin](https://www.pgadmin.org/)连接和管理PostgreSQL。
42 |
43 | 安装Psycopgs适配器
44 |
45 | $ pip install psycopg2-binary
46 | ```
47 | >>> import psycopg2
48 | >>> conn = psycopg2.connect("dbname=test user=postgres password=postgres")
49 | >>> cur = conn.cursor()
50 | >>> cur.execute("CREATE TABLE test (id serial PRIMARY KEY, num integer, data varchar);")
51 | >>> cur.execute("INSERT INTO test (num, data) VALUES (%s, %s)", (10, "python"))
52 | >>> cur.execute("INSERT INTO test (num, data) VALUES (%s, %s)", (11, "rust"))
53 | >>> cur.execute("SELECT * FROM test;")
54 | >>> cur.fetchall()
55 | [(8, 10, 'python'), (9, 11, 'rust')]
56 | >>> conn.commit() # 写入数据库,打开数据库看插入了两条记录
57 | >>> cur.close()
58 | >>> conn.close()
59 | ```
60 | 配图来自Twitter:@neku_draw
61 |
62 | 
63 |
--------------------------------------------------------------------------------
/courses/python23.md:
--------------------------------------------------------------------------------
1 | # 第23课:设计模式(Design patterns)
2 | 在这里放出设计模式,好像不是特别合适,但直觉是早一点了解些设计模式,对之后的提高是很有帮助的。
3 |
4 | ### 设计模式
5 | 在软件工程中,设计模式(design pattern)是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。设计模式并不直接用来完成代码的编写,而是描述在各种不同情况下,要怎么解决问题的一种方案。
6 |
7 | 
8 | [点击下载大图](https://wiki.huihoo.com/images/a/a2/Design-pattern.png)
9 |
10 | 图片来自[icemoon1987](http://www.cnblogs.com/icemoon1987/p/3349415.html)
11 |
12 | 经典的《设计模式:可复用面向对象软件的基础》包含23个设计模式,这本书是软件工程领域有关软件设计的一本重要的书,提出和总结了对于一些常见软件设计问题的标准解决方案,称为软件设计模式。该书作者为:埃里希·伽玛(Erich Gamma), Richard Helm , Ralph Johnson,John Vlissides,后以“四人帮”(Gang of Four,GoF)著称。
13 |
14 | 先这23个设计模式罗列一下,以后需要的可继续深入下去。
15 |
16 | ### 创建范例
17 | 创建范例全部是关于如何创建实例的。这组范例可以被划分为两组:类创建范例及对象创建范例。类创建实例在实例化过程中有效的使用类之间的继承关系,对象创建范例则使用代理来完成其任务。
18 |
19 | * 抽象工厂 (Abstract Factory pattern)
20 | * 构造器 (Builder pattern)
21 | * 工厂方法 (Factory Method pattern)
22 | * 原型 (Prototype pattern)
23 | * 单例模式 (Singleton pattern)
24 |
25 | ### 结构范例
26 | 这组范例都是关于类及对象复合关系的。
27 |
28 | * 适配器(Adapter pattern)
29 | * 桥接(Bridge pattern)
30 | * 组合(Composite pattern)
31 | * 装饰(Decorator pattern)
32 | * 外观(Façade pattern)
33 | * 享元(Flyweight pattern)
34 | * 代理(Proxy pattern)
35 |
36 | ### 行为范例
37 | 这组范例都是关于对象之间如何通讯的。
38 |
39 | * 职责链(Chain-of-responsibility pattern)
40 | * 命令(Command pattern)
41 | * 解释器(Interpreter pattern)
42 | * 迭代器(Iterator pattern)
43 | * 中介者(Mediator pattern)
44 | * 备忘录(Memento pattern)
45 | * 观察者(Observer pattern)
46 | * 状态机(State pattern)
47 | * 策略(Strategy pattern)
48 | * 模板方法(Template method pattern)
49 | * 访问者(Visitor pattern)
50 |
51 | ### 例子
52 |
53 | ### python-patterns
54 | https://github.com/faif/python-patterns
55 |
56 | 通过这个项目来介绍一下设计模式
57 |
58 | 这块内容有点多,以后单独深入展开。
59 |
60 | ### 参考
61 | * [Design Patterns](https://sourcemaking.com/design_patterns)
62 |
63 | 配图来自Twitter:@chengr28
64 |
65 | 
66 |
--------------------------------------------------------------------------------
/courses/python15.md:
--------------------------------------------------------------------------------
1 | # 第15课:面向对象(Object orientation)(二)
2 |
3 | ### 继承
4 |
5 | ### 方法重载
6 |
7 | ### 运算符重载
8 |
9 | ### 类的专有方法
10 |
11 | ### 自省
12 | 对人来讲,自省(introspection)就是对自身思想、情绪、动机和行为的审视,能帮助我们更好的认识和改善自己。同理,Python自省能帮助开发者更深入了解和洞察Python对象所包含或隐藏的各种细节。
13 |
14 | Python包含了很多内置函数和模块可帮助到我们。
15 |
16 | #### dir函数
17 | dir是用于自省一个重要的函数,它返回一个对象所拥有的属性和方法。
18 | ```
19 | 当前作用域
20 | >>> dir()
21 | ['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'add', 'keyword', 'sl', 'sys']
22 |
23 | 之前第13课定义的sl
24 | >>> dir(sl)
25 | ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
26 | ...
27 | ```
28 |
29 | #### sys模块
30 | sys模块的属性
31 | ```
32 | >>> import sys
33 | >>> dir(sys)
34 | ['__displayhook__', '__doc__', '__excepthook__', '__interactivehook__', '__loader__', '__name__', '__package__', '__spec__', '__stderr__',
35 | ...
36 | ```
37 |
38 | #### keyword模块
39 | keyword模块的关键字列表
40 | ```
41 | >>> import keyword
42 | >>> keyword.kwlist
43 | ['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
44 | ```
45 |
46 | keyword模块的属性
47 | ```
48 | >>> import keyword
49 | >>> dir(keyword)
50 | ['__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'iskeyword', 'kwlist', 'main']
51 | ```
52 |
53 | #### inspect模块
54 | ```
55 | >>> import inspect
56 | >>> print(inspect.getmembers(sl))
57 | >>> print(inspect.getmembers(str))
58 | ```
59 |
60 | #### type和id
61 | type()和id()返回对象类型和对象id
62 | ```
63 | >>> print(type(sl))
64 |
65 | >>> print(type(9))
66 |
67 | >>> name = "python"
68 | >>> print(id(name))
69 | 4552783720
70 | ```
71 |
72 | 配图来自Twitter:@chengr28
73 |
74 | 
75 |
--------------------------------------------------------------------------------
/courses/python07.md:
--------------------------------------------------------------------------------
1 | # 第7课:文件、目录
2 |
3 | 将以下内容以Jupyter Notebook的方式做练习和自己总结,并保存.ipynb。
4 |
5 | touch text.txt
6 | * 列举目录文件
7 | * 写文件
8 | * 读文件
9 |
10 | 本节课主要学习目录操作和文件读写。
11 |
12 | ```
13 | #目录操作
14 | >>> import os
15 | >>> os.getcwd()
16 |
17 | #改变Linux/macOS目录
18 | >>> os.chdir('/Users/huihoo/Software')
19 |
20 | #改变Windows目录
21 | >>> os.chdir('C:\\Windows\System32')
22 |
23 | #继续试试创建目录:makedirs
24 |
25 | #列举目录文件
26 | >>> from pathlib import Path
27 | >>> p = Path('.')
28 | >>> list(p.glob('*.*'))
29 | or
30 | >>> for child in p.iterdir(): child
31 |
32 | #写文件
33 | with open('test.txt', 'w', encoding='utf-8') as f:
34 | f.write('test')
35 | f.close()
36 | ```
37 |
38 | 注意:一定要close()关闭文件,否则你做得修改没有保存到文件里,但写入的内容会覆盖以前的文件内容。
39 |
40 | 所以,我们想追加写入文件,我们使用’a’追加模式
41 | ```
42 | with open('test.txt', 'a', encoding='utf-8') as f:
43 | f.write(‘\n输入中文’)
44 | f.close()
45 |
46 | #读文件
47 | with open('test.txt', 'r', encoding='utf-8') as f:
48 | f.readlines()
49 | ```
50 |
51 | 还有很多文件目录操作的模块和函数,大家都去了解下。
52 |
53 | 扩展学习:文件目录的相关模块和函数,大家可搜索网络完成一些文件目录扩展练习。
54 | ```
55 | >>> help()
56 | help> modules
57 | pathlib, os.path, tempfile, filecmp, fileinput, shutil, zipfile
58 |
59 | #os模块:提供了与系统、目录操作相关的函数
60 | >>>import os
61 | >>>dir(os)
62 |
63 | #pathlib模块:其提供的Path类可以创建path路径对象, 属于比os.path更高抽象级别的对象。
64 | >>> import pathlib
65 | >>> dir(pathlib)
66 | 阅读:Python 3的pathlib模块:驯服文件系统
67 |
68 | #os.path模块:包含许多与文件名和文件路径相关的函数
69 | >>> import os.path
70 | >>> dir(os.path)
71 |
72 | #tempfile模块:临时文件和目录处理
73 | >>> import tempfile
74 | >>> dir(tempfile)
75 |
76 | #filecmp模块:用于比较文件及文件夹的内容
77 | >>> import filecmp
78 | >>> dir(flecmp)
79 |
80 | #fileinput模块:可以对一个或多个文件中的内容进行迭代、遍历等操作,其input()函数有点类似文件
81 | #readlines()方法,区别在于前者是一个迭代对象,需要用for循环迭代,后者是一次性读取所有行。
82 | >>>import fileinput
83 | >>>dir(fileinput)
84 |
85 | #shutil模块:复制、移动、改名和删除文件
86 | >>> import shutil, os
87 | >>> dir(shutil)
88 |
89 | #zipfile模块:压缩文件
90 | >>> import zipfile, os
91 | >>> dir(zipfile)
92 | ```
93 |
94 | 配图来自Twitter:@momoco_haru
95 |
96 | 
--------------------------------------------------------------------------------
/courses/python08.md:
--------------------------------------------------------------------------------
1 | # 第8课:错误、异常
2 |
3 | 将以下内容以Jupyter Notebook的方式做练习和自己总结,并保存.ipynb。
4 |
5 | 本节课涉及一些概念:语法错误、异常、异常处理、抛出异常、自定义异常、Finally始终执行、反向跟踪
6 |
7 | 注意:错误和异常的区别:
8 | 错误(语法错误、解析时)
9 | 异常(运行时)
10 |
11 | 1、语法错误
12 | ```
13 | >>> print (Hello World)
14 | File "", line 1
15 | print (Hello World)
16 | ^
17 | SyntaxError: invalid syntax
18 | ```
19 |
20 | 2、异常(运行时)
21 | 常见的异常类型:ZeroDivisionError,NameError 和 TypeError
22 | ```
23 | >>>1/0
24 | ```
25 |
26 | 3、异常处理(try … except)
27 | ```
28 | >>> def zero_fails():
29 | ... x = 1/0
30 | ...
31 | >>> try:
32 | ... zero_fails()
33 | ... except ZeroDivisionError as err:
34 | ... print('处理运行时错误', err)
35 | ```
36 |
37 | Python抛出异常相当于:“停止运行这个函数中的代码,将程序执行转到except语句。
38 |
39 | raise语句包含以下部分:
40 | * raise关键字;
41 | * 对Exception函数的调用;
42 | * 传递给Exception函数的字符串,包含有用的出错信息。
43 |
44 | 4、抛出异常(raise)
45 | ```
46 | >>> raise Exception('这是一个错误信息')
47 | >>> raise ZeroDivisionError('ZeroFails')
48 | Traceback (most recent call last):
49 | File "", line 1, in
50 | ZeroDivisionError: ZeroFails
51 | ```
52 |
53 | 5、自定义异常,继承自 Exception 类
54 | ```
55 | >>>class MyError(Exception):
56 | def __init__(self, value):
57 | self.value = value
58 |
59 | 类 Exception 默认的 __init__() 被覆盖
60 | ```
61 |
62 | 6、Finally
63 | ```
64 | >>> try:
65 | ... raise ZeroDivisionError
66 | ... finally:
67 | ... print("始终执行")
68 | ```
69 |
70 | 7、traceback
71 |
72 | 只要抛出的异常没有被处理,Python就会显示反向跟踪,你可将反向跟踪信息写入一个日志文件,让程序继续运行,稍后检查日志文件进行分析。
73 | ```
74 | >>> import traceback
75 | >>> try:
76 | ... raise Exception('这是一个错误信息.')
77 | ... except:
78 | ... errorFile = open('errorInfo.txt', 'w')
79 | ... errorFile.write(traceback.format_exc())
80 | ... errorFile.close()
81 | ... print('反向跟踪信息写入errorInfo.txt.')
82 | ```
83 |
84 | 其实本课程也包含调试、调试器、断言、断点、日志等内容,我们会在之后的进阶课程逐步展开。
85 |
86 | 这块有些复杂,多去理解,多看看一些项目里这部分的处理方式。
87 |
88 | 大部分项目对错误和异常处理都格外重视,会有独立的异常处理模块,如:odoo.exceptions
89 | Search · Exception · GitHub
90 |
91 | OK,程序完成调试。
92 |
93 | 配图来自Twitter:@momoco_haru
94 |
95 | 
--------------------------------------------------------------------------------
/courses/python35.md:
--------------------------------------------------------------------------------
1 | # 第35课:视图(一)
2 | 视图简单讲就是负责处理用户的请求并返回响应。
3 |
4 | ### 一个简单视图
5 | ```
6 | from django.http import HttpResponse
7 | import datetime
8 |
9 | def current_datetime(request):
10 | now = datetime.datetime.now()
11 | html = "It is now %s." % now
12 | return HttpResponse(html)
13 | ```
14 |
15 | ### 优雅URL
16 | 回顾一下我们之前在 [polls](python28.md) 应用的URL设计。
17 |
18 | ### 装饰器(decorators
19 | Django 提供了多个可以应用于视图的装饰器,以支持各种HTTP功能,使用 @ 标识符。
20 |
21 | ```
22 | from django.contrib.auth.decorators import login_required
23 |
24 | @login_required(login_url='/accounts/login/')
25 | def my_view(request):
26 | ...
27 | ```
28 | 每次用户试图访问 my_view 时,都会检查用户是否通过身份验证,并将未登录用户重定向到login_url。
29 |
30 | ### 快捷函数
31 | 包 django.shortcuts 收集了“跨越” 多层MVC 的辅助函数和类。 换句话讲,这些函数/类为了方便,引入了可控的耦合。
32 |
33 | * render()
34 | * render_to_response()
35 | * redirect()
36 | * get_object_or_404()
37 | * get_list_or_404()
38 |
39 | 我们常用 render() 替换 HttpResponse()
40 | ```
41 | from django.shortcuts import render
42 |
43 | def my_view(request):
44 | # View code here...
45 | return render(request, 'myapp/index.html', {
46 | 'foo': 'bar',
47 | }, content_type='application/xhtml+xml')
48 | ```
49 | 相当于:
50 | ```
51 | from django.http import HttpResponse
52 | from django.template import loader
53 |
54 | def my_view(request):
55 | # View code here...
56 | t = loader.get_template('myapp/index.html')
57 | c = {'foo': 'bar'}
58 | return HttpResponse(t.render(c, request), content_type='application/xhtml+xml')
59 | ```
60 |
61 | ### 内置视图
62 | Django 提供了内置视图,如 error 视图:
63 | * 404 (page not found)
64 | defaults.page_not_found(request, exception, template_name='404.html')
65 | * 500 (server error)
66 | defaults.server_error(request, template_name='500.html')
67 | * 403 (HTTP Forbidden)
68 | defaults.permission_denied(request, exception, template_name='403.html')
69 | * 400 (bad request)
70 | defaults.bad_request(request, exception, template_name='400.html')
71 |
72 | 
73 |
74 | 配图来自Twitter:@chengr28
75 |
76 | 
77 |
--------------------------------------------------------------------------------
/courses/python24.md:
--------------------------------------------------------------------------------
1 | # 第24课:领域特定语言(Domain-specific language,DSL)
2 |
3 | 领域特定语言(domain-specific language、DSL)指的是专注于某个应用程序领域的计算机语言,如SQL语言,正则表达式。
4 |
5 | DSL分为两类:
6 | * 内部DSL(Internal DSL),DSL和宿主语言是相同的语言。
7 | * 外部DSL(External DSL),DSL和宿主语言不同,需要自己写解释器。
8 |
9 | 抛个问题先:世界上最强大的 DSL 实现语言,不是 Haskell 或者 Scala,而应该是 Scheme?
10 |
11 | 看不懂没关系,留在以后思考。
12 |
13 | ### 为什么有DSL
14 | 通用语言在解决某些特定领域的问题有时会显得有些吃力,这时候DSL似乎就有了用武之地。
15 |
16 | 个人感觉,若能在某些特定领域拥有比其它同学更简单、更高效的解决方法和手段,也是自己的一个加分项和优势。
17 |
18 | ### Python DSL
19 | Python是一门通用、灵活、高效的语言,它在解决某些特定领域问题时会比较擅长。
20 |
21 | 目前,Python是数据科学和机器学习领域的明星语言,这些也都源于它所具有的语言特性和优势。
22 |
23 | ### 参考例子
24 | 一个简单的Internal DSL for SQL DDL。
25 | ```
26 | from contextlib import contextmanager
27 |
28 | class Table(object):
29 | def __init__(self, table_name):
30 | self.table_name = table_name
31 | self.fields = {}
32 |
33 | def __getattr__(self, name):
34 | def f(**kvs):
35 | self.fields[name] = kvs
36 | return f
37 |
38 | def execute(self):
39 | print ("Creating table %s with fields %s"%(self.table_name, self.fields))
40 |
41 | @contextmanager
42 | def create_table(table_name):
43 | table = Table(table_name)
44 | yield table
45 | table.execute()
46 |
47 | with create_table('User') as t:
48 | t.first_name(type='char', length=30)
49 | t.last_name(type='char', length=30)
50 | t.age(type='int')
51 |
52 | 运行结果:
53 | Creating table User with fields {'first_name': {'type': 'char', 'length': 30}, 'last_name': {'type': 'char', 'length': 30}, 'age': {'type': 'int'}}
54 |
55 | ```
56 |
57 | ### 参考
58 | * [王垠《聊聊 DSL》](http://www.yinwang.org/blog-cn/2017/05/25/dsl)
59 | * [Creating Domain Specific Languages in Python](https://www.slideshare.net/Siddhi/creating-domain-specific-languages-in-python)
60 | * [Domain-specific languages to Manycore and GPU: Building High-Performance Tools with Python](https://github.com/inducer/languages-and-codegen-tutorial)
61 | * [Writing a Domain Specific Language (DSL) in Python](https://dbader.org/blog/writing-a-dsl-with-python)
62 |
63 | 配图来自Twitter:@makadamixa
64 |
65 | 
66 |
--------------------------------------------------------------------------------
/courses/python14.md:
--------------------------------------------------------------------------------
1 | # 第14课:面向对象(Object orientation)(一)
2 |
3 | Python设计之初就是一门面向对象编程语言。对象是Python最核心的概念,在Python的世界里,一切都是对象,一个整数是对象,一个字符串是对象,一个字典是对象。
4 |
5 | 在Python中,已预先定义了一些常见类型对象,如:int类型、str类型、list类型等。这些类型对象通过实例化,可以创建相应的实例对象,如:int对象、str对象、list对象等。
6 |
7 | 对象 = 属性(attribute) + 方法(method)
8 |
9 | 如:球(ball)
10 |
11 | 属性有:
12 | * ball.color
13 | * ball.size
14 |
15 | 方法有:
16 | * ball.kick()
17 | * ball.throw()
18 |
19 | ```
20 | >>> help(int)
21 | class int(object)
22 | | int(x=0) -> integer
23 | | int(x, base=10) -> integer
24 | >>> help(str)
25 | class str(object)
26 | | str(object='') -> str
27 | | str(bytes_or_buffer[, encoding[, errors]]) -> str
28 | >>> help(list)
29 | class list(object)
30 | | list() -> new empty list
31 | | list(iterable) -> new list initialized from iterable's items
32 | ```
33 |
34 | 此外,Python也允许通过class a(object)这样的表达式定义自己的类型对象。
35 |
36 | Python的对象系统庞大而复杂,核心使用C语言实现。
37 |
38 | PS:Python语言核心:类型系统、对象系统。这也几乎是所有OO语言的核心,也是构建大规模Python应用的基础,所以掌握类型系统和对象系统是学习掌握一门新语言的关键。
39 |
40 | ### 一些面向对象概念
41 | * 类(class)
42 | 具有相同属性和方法的对象的集合。
43 | * 对象(object)
44 | 对象是类的实例。
45 | * 属性(attribute)
46 | 属性并不属于类,它属于各个实例。属性引用:obj.name
47 | * 方法(method)
48 | 类中定义的函数。
49 | * 实例化(instantiation)
50 | 创建类的具体对象。
51 | * 数据成员(data member)
52 | 类变量或者实例变量。
53 | * 类变量(class variable)
54 | 类变量定义在类中且在函数体之外,在整个实例化的对象中是公用的。
55 | * 实例变量(instance variable)
56 | 定义在方法中的变量,只作用于当前实例的类。
57 | * 继承(inheritance):基类(base class)、派生类(derived class)
58 | * 多态(polymorphism)
59 | 同一个方法,不同的行为。不同的类可以有同名的两个或多个方法。
60 | * 方法重载(override)
61 | 若从父类继承的方法不能满足子类的需求,可以对其进行改写(重写).
62 |
63 | ### 公共私有
64 | * 公共方法
65 | * 私有方法
66 | __private_method:两个下划线开头,只能在类的内部调用。self.__private_methods
67 | * 公共属性
68 | * 私有属性
69 | __private_attrs:两个下划线开头,只能在类内部的方法中使用。self.__private_attrs
70 |
71 | ### 创建类
72 | ```
73 | >>> class Ball:
74 | ... def bounce(self):
75 | ... if self.direction == "down":
76 | ... self.direction = "up"
77 | ...
78 | >>>
79 | ```
80 | ### 实例化
81 | ```
82 | 创建类的一个实例,并设置一些属性
83 | >>> myBall = Ball()
84 | >>> myBall.direction = "down"
85 | >>> myBall.color = "red"
86 | >>> myBall.size = "big"
87 | 使用一个方法
88 | >>> myBall.bounce()
89 | ```
90 |
91 | 配图来自Twitter:@chengr28
92 |
93 | 
94 |
--------------------------------------------------------------------------------
/courses/python18.md:
--------------------------------------------------------------------------------
1 | # 第18课:接口(Interface)
2 |
3 | ### 什么是接口
4 | 接口只是定义了一组方法,而没有具体实现。
5 |
6 | Python的接口由抽象类和抽象方法去实现,接口不能被实例化,只能被别的类继承去实现相应的功能。
7 |
8 | ### 实现方法
9 | Python 使用 abc(Abstract Base Classes)模块可以轻松的定义抽象基类,抽象类的目的就是让别的类继承它并实现特定的抽象方法。
10 |
11 | ### 用抽象类和抽象方法实现接口
12 | 1、定义抽象基类
13 | ```
14 | from abc import ABCMeta,abstractmethod
15 |
16 | class interface(object):
17 | __metaclass__ = ABCMeta #抽象类
18 | @abstractmethod #抽象方法
19 | def python(self):
20 | pass
21 |
22 | def rust(self):
23 | pass
24 | ```
25 | 2、继承基类并实现具体的抽象方法
26 | ```
27 | class ImplementationInterfacePython(interface):
28 | def __init__(self):
29 | print ('这是接口实现')
30 | def python(self):
31 | print ('实现python方法')
32 | def rust(self):
33 | pass
34 |
35 | class ImplementationInterfaceRust(interface):
36 | def __init__(self):
37 | print ('这是接口实现')
38 | def python(self):
39 | pass
40 | def rust(self):
41 | print ("实现rust方法")
42 |
43 | >>> obj = ImplementationInterfacePython()
44 | 这是接口实现
45 | >>> obj.python()
46 | 实现python方法
47 | >>> obj = ImplementationInterfaceRust()
48 | 这是接口实现
49 | >>> obj.rust()
50 | 实现rust方法
51 |
52 | ```
53 | ### 用普通类实现接口
54 | 1、定义接口
55 | ```
56 | class interface(object):
57 | def python(self):
58 | pass
59 |
60 | def rust(self):
61 | pass
62 |
63 | ```
64 |
65 | 2、实现接口
66 | ```
67 | class ImplementationInterfacePython(interface):
68 | def __init__(self):
69 | pass
70 | def python(self):
71 | print ("实现接口中的python方法")
72 |
73 |
74 | class ImplementationInterfaceRust(interface):
75 | def __init__(self):
76 | pass
77 | def rust(self):
78 | print ("实现接口中的rust方法")
79 |
80 |
81 | >>> obj = ImplementationInterfacePython()
82 | >>> obj.python()
83 | 实现接口中的python方法
84 | >>> obj = ImplementationInterfaceRust()
85 | >>> obj.rust()
86 | 实现接口中的rust方法
87 | ```
88 |
89 | ### zope.interface
90 | 此项目提供了Python对象接口的参考实现,大家可通过此项目扩展学习。
91 |
92 | https://pypi.org/project/zope.interface/
93 |
94 | 配图来自Twitter:@chengr28
95 |
96 | 
97 |
--------------------------------------------------------------------------------
/courses/python10.md:
--------------------------------------------------------------------------------
1 | # 第10课:语法(Syntax)、语义(Semantics)、词法(Lexical)(二)
2 |
3 | 将以下内容以Jupyter Notebook的方式做练习和自己总结,并保存.ipynb。
4 |
5 | Python的编译执行过程其实和Java和C#是类似的,也涉及字节码和虚拟机两个主要概念,这个我们在第9课中有描述。
6 |
7 | 这节课我们实践操作下如何把Python源文件.py编译成可执行文件的过程。
8 |
9 | 注意:这里和本系列课程都使用Python3.6进行实验和学习,Python3和Python2两版本有非常大的差异,这里有些环节(pyc和pyo的生成过程)使用了Python2(Python2.7)。
10 |
11 | 创建helloworld.py文件
12 | ```
13 | #!/anaconda3/bin/python
14 | print ("Hello World!")
15 | ```
16 |
17 | ### pyc文件
18 | pyc是由py文件经过编译后生成的二进制文件,是一种跨平台的byte code,再由python虚拟机执行。
19 |
20 | 需要 py_compile 模块
21 |
22 | ```
23 | python2 -m py_compile helloworld.py
24 | 生成了 helloworld.pyc 或
25 | >>> import py_compile
26 | >>> py_compile.compile('helloworld.py')
27 | '__pycache__/helloworld.cpython-36.pyc'
28 | ```
29 |
30 | ### pyo文件
31 | pyo是优化编译后的文件
32 | ```
33 | python2 -O -m py_compile helloworld.py
34 | 注意:这里使用python2生成pyo
35 | helloworld.pyo
36 | ```
37 |
38 | ### so文件
39 | so是python的动态链接库
40 |
41 | 创建setup.py
42 | ```
43 | from distutils.core import setup
44 | from Cython.Build import cythonize
45 |
46 | setup(
47 | ext_modules = cythonize("helloworld.py"),
48 | )
49 | ```
50 | python setup.py build_ext --inplace
51 |
52 | 先将py转换为c代码,然后编译c为so文件。
53 | ```
54 | build/temp.macosx-10.7-x86_64-3.6/helloworld.o
55 | helloworld.c
56 | helloworld.cpython-36m-darwin.so
57 |
58 | ```
59 | ### dis
60 | dis是Python字节码的反汇编程序(Disassembler)
61 |
62 | 我们使用dis对python字节码进行解析
63 |
64 | ```
65 | >>> s = open('helloworld.py').read()
66 | >>> co = compile(s, 'helloworld.py', 'exec')
67 | >>> dis.dis(co)
68 | 1 0 LOAD_NAME 0 (print)
69 | 2 LOAD_CONST 0 ('Hello World!')
70 | 4 CALL_FUNCTION 1
71 | 6 POP_TOP
72 | 8 LOAD_CONST 1 (None)
73 | 10 RETURN_VALUE
74 | ```
75 | 获得dis帮助
76 | ```
77 | >>> help(dis)
78 | ```
79 |
80 | 再完成一个操作
81 | ```
82 | >>> def myfunc(alist):
83 | ... return len(alist)
84 | ...
85 | >>> bytecode = dis.Bytecode(myfunc)
86 | >>> for instr in bytecode:
87 | ... print(instr.opname)
88 | ...
89 | LOAD_GLOBAL
90 | LOAD_FAST
91 | CALL_FUNCTION
92 | RETURN_VALUE
93 | >>>
94 | ```
95 | 配图来自Twitter:@neku_draw
96 |
97 | 
98 |
--------------------------------------------------------------------------------
/courses/python33.md:
--------------------------------------------------------------------------------
1 | # 第33课:模型(一)
2 |
3 | ### 模型定义
4 | 一般来说,每一个模型都映射一个数据库表。
5 | * 每个模型都是一个 Python 类,这些类继承 django.db.models.Model
6 | * 模型类的每个属性都相当于一个数据库的字段
7 | * Django 自动生成访问数据库的 API
8 |
9 | ### 创建模型
10 | 为了方便,我们直接使用之前创建的polls应用。
11 |
12 | 定义了一个 Person 模型, 包含 first_name 和 last_name,将以下内容加入 mysite/polls/models.py:
13 | ```
14 | class Person(models.Model):
15 | first_name = models.CharField(max_length=30)
16 | last_name = models.CharField(max_length=30)
17 | ```
18 | 1、运行:$ python manage.py makemigrations polls
19 | ```
20 | Migrations for 'polls':
21 | polls/migrations/0002_person.py
22 | - Create model Person
23 | ```
24 | 2、检查:$ python manage.py sqlmigrate polls 0002
25 |
26 | 3、迁移:$ python manage.py migrate
27 |
28 | 这时,这个模型会自动在数据库中生成一张新表:
29 | ```
30 | CREATE TABLE polls_person (
31 | "id" serial NOT NULL PRIMARY KEY,
32 | "first_name" varchar(30) NOT NULL,
33 | "last_name" varchar(30) NOT NULL
34 | );
35 | ```
36 |
37 | ### 初始化数据
38 | 数据库表创建好后,可通过 python manage.py loaddata `` 的方式初始化数据库,数据文件格式可以是 JSON 或 YAML。
39 |
40 | 创建 polls-person.json 文件:
41 | ```
42 | [
43 | {
44 | "model": "polls.person",
45 | "pk": 1,
46 | "fields": {
47 | "first_name": "Allen",
48 | "last_name": "Long"
49 | }
50 | },
51 | {
52 | "model": "polls.person",
53 | "pk": 2,
54 | "fields": {
55 | "first_name": "Peter",
56 | "last_name": "Chen"
57 | }
58 | }
59 | ]
60 | ```
61 | 运行 $ python manage.py loaddata polls-person.json
62 |
63 | Installed 2 object(s) from 1 fixture(s)
64 |
65 | 这时 polls_person 新建了两条记录,你可以通过这种方式初始化数据库,或把其它系统的数据导出再导入新系统。
66 |
67 | 
68 |
69 | ### 使用模型
70 | 你可以通过以下的方式使用模型(数据库表),进行增删改查等操作。
71 | ```
72 | >>> import psycopg2
73 | >>> conn = psycopg2.connect("dbname=mysite user=postgres password=postgres")
74 | >>> cur = conn.cursor()
75 | >>> cur.execute("SELECT * FROM polls_person;")
76 | >>> cur.fetchall()
77 | [(1, 'Allen', 'Long'), (2, 'Peter', 'Chen')]
78 | ```
79 |
80 | $ python manage.py shell
81 | ```
82 | >>> from polls.models import Person
83 | >>> Person.objects.count()
84 | 2
85 | >>> Person.objects.all()
86 | , ]>
87 | ```
88 |
89 | 配图来自Twitter:@kagachi_SK
90 |
91 | 
92 |
--------------------------------------------------------------------------------
/courses/python28.md:
--------------------------------------------------------------------------------
1 | # 第28课:入门 - 视图和模板(三)
2 |
3 | ### 视图
4 | Django 中的视图的概念是一类具有相同功能和模板的网页的集合,如大家熟悉的博客会包含以下视图:
5 | * 博客首页:展示最近的几条博客
6 | * 详情页
7 | * 评论
8 | * 归档页:以年、月、日为单位的归档博客
9 |
10 | 在我们的投票(Polls)应用中,需要以下视图:
11 | * 问题索引页:显示最近的几个投票问题。
12 | * 问题详情页:显示某个投票的问题和不带结果的选项列表。
13 | * 问题结果页:显示某个投票的结果。
14 | * 投票处理器:用于响应用户为某个问题的特定选项投票的操作。
15 |
16 | 为了将 URL 和视图关联起来,Django 使用了 'URLconfs' 来配置,URLconf 将 URL模式(urlpatterns)映射到视图。
17 |
18 | 现在我们往 polls/views.py 里添加以下新视图:
19 | ```
20 | def detail(request, question_id):
21 | return HttpResponse("你看到的问题是 %s." % question_id)
22 |
23 | def results(request, question_id):
24 | response = "你看到的问题结果是 %s."
25 | return HttpResponse(response % question_id)
26 |
27 | def vote(request, question_id):
28 | return HttpResponse("你在此问题上的投票 %s." % question_id)
29 | ```
30 |
31 | 编辑 polls/urls.py,添加几个 url() 函数调用:
32 | ```
33 | from django.urls import path
34 |
35 | from . import views
36 |
37 | urlpatterns = [
38 | # ex: /polls/
39 | path('', views.index, name='index'),
40 | # ex: /polls/5/
41 | path('/', views.detail, name='detail'),
42 | # ex: /polls/5/results/
43 | path('/results/', views.results, name='results'),
44 | # ex: /polls/5/vote/
45 | path('/vote/', views.vote, name='vote'),
46 | ]
47 | ```
48 |
49 | ### 模版
50 | 使用模版,我们可以不用把页面的设计写死在视图函数的代码里,而是将页面的设计从代码中分离出来,方便今后的维护。
51 |
52 | 我们创建 polls/templates/polls 目录,然后创建 index.html,因为这样 Django 能找到对应的 app_directories,这样使用 polls/index.html 就可以引用此模版了,把模版放到各自的命名空间下是个好习惯。
53 |
54 | 编辑 polls/templates/polls/index.html
55 | ```
56 | {% if latest_question_list %}
57 |
62 | {% else %}
63 | 没有投票
64 | {% endif %}
65 | ```
66 | 更新一下 polls/views.py 里的 index 视图来使用此模板,使用 render() 重写 index() 视图,而不是使用HttpResponse() :
67 | ```
68 | from django.http import HttpResponse
69 | from django.shortcuts import render
70 | from .models import Question
71 |
72 | def index(request):
73 | latest_question_list = Question.objects.order_by('-pub_date')[:5]
74 | context = {'latest_question_list': latest_question_list}
75 | return render(request, 'polls/index.html', context)
76 | ```
77 |
78 | $ python manage.py runserver
79 |
80 | 打开 http://localhost:8000/admin/ 添加几个问题:
81 | * 问题一
82 | * 问题二
83 | * 问题三
84 |
85 | 再打开 http://localhost:8000/polls/ 你应该可以看见刚创建的三个问题 :)
86 |
87 | 这样,我们就初步学习了视图创建和模版使用的基础知识了。
88 |
89 | 配图来自Twitter:@atikix
90 |
91 | 
92 |
--------------------------------------------------------------------------------
/courses/python11.md:
--------------------------------------------------------------------------------
1 | # 第11课:操作符(Operators)
2 |
3 | 先看看Python有哪些常用操作符:
4 | ```
5 | + - * ** / // % @
6 | << >> & | ^ ~
7 | < > <= >= == !=
8 | ```
9 |
10 | ### 算术操作符
11 | +, -, *, / , %, // , **, _ 分别为加、减、乘、浮点除、取余数(返回除法的余数)、整数除(返回商的整数部分)、幂运算(x的y次幂)、上个表达式结果的值。
12 | ```
13 | >>> a = 2
14 | >>> b = 6
15 | >>> a + b
16 | 8
17 | >>> a - b
18 | -4
19 | >>> a * b
20 | 12
21 | >>> a/b
22 | 0.3333333333333333
23 | >>> a % b
24 | 2
25 | >>> b % a
26 | 0
27 | >>> a ** b
28 | 64
29 | >>> a // b
30 | 0
31 | >>> b // a
32 | 3
33 | >>> _
34 | 3
35 | ```
36 |
37 | ### 比较操作符
38 | ==, !=, <, >=, <= 分别为相等、不等于、大于、小于、大于等于、小于等于。
39 | ```
40 | >>> (a == b)
41 | False
42 | >>> (a != b)
43 | True
44 | >>> (a > b)
45 | False
46 | >>> (a < b)
47 | True
48 | >>> (a >= b)
49 | False
50 | >>> (a <= b)
51 | True
52 | ```
53 |
54 | ### 位操作符
55 | 按位运算符是把数字看作二进制来进行计算,数字加上前缀 '0b' 表示是二进制数字。
56 |
57 | &, |, ^, ~, << , >> 分别为按位与、或、异或、取反、左移、右移。
58 |
59 | 自己用2和4的二进制数做按位运算,并理解其结果。
60 | ```
61 | >>> bin(2);bin(4)
62 | '0b10'
63 | '0b100'
64 | >>> (0b10 & 0b100)
65 | 0
66 | >>> (0b10 | 0b100)
67 | 6
68 | >>> bin(6)
69 | '0b110'
70 | >>> (0b10 ^ 0b100)
71 | 6
72 | >>> (0b10 << 2)
73 | 8
74 | >>> bin(8)
75 | '0b1000'
76 | >>> (0b10 >> 2)
77 | 0
78 | >>> bin(0)
79 | '0b0'
80 | >>>
81 | ```
82 |
83 | ### 逻辑操作符
84 | and, or, not 分别为与、或、非。
85 | ```
86 | >>> (a and b)
87 | 10
88 | >>> (a or b)
89 | 21
90 | >>> not(a and b)
91 | False
92 | ```
93 |
94 | ### 成员操作符
95 | in, not in 分别为是成员、不是成员。
96 | ```
97 | >>> a = 1; b = 2
98 | >>> list = [1, 2, 3, 4, 5]
99 | >>> (a in list)
100 | True
101 | >>> (c not in list)
102 | True
103 | >>> (b not in list)
104 | False
105 | ```
106 |
107 | ### 身份运算符
108 | is, is not 分别为同一对象、不是同一对象。
109 | ```
110 | >>> a = 1; b = 2
111 | >>> (a is b)
112 | False
113 | >>> (a is not b)
114 | True
115 | ```
116 |
117 | ### 赋值操作符
118 | 把算术运算符和=组合起来使用。
119 | ```
120 | >>> c = a + b
121 | >>> c
122 | 8
123 | >>> c += a
124 | >>> c
125 | 10
126 | >>> c -= a
127 | >>> c
128 | 8
129 | >>> c *= a
130 | >>> c
131 | 16
132 | >>> c /= a
133 | >>> c
134 | 8.0
135 | >>> c %= a
136 | >>> c
137 | 0.0
138 | >>> c **= a
139 | >>> c
140 | 0.0
141 | >>> c //= a
142 | >>> c
143 | 0.0
144 | ```
145 |
146 | ### 运算符优先级
147 | ```
148 | >>> a = 10; b = 6; c = 3; d = 0
149 | >>> a = 10; b = 6; c = 3; d = 2
150 | >>> ((a + b) * c) / d
151 | 24.0
152 | >>> a * b ** c
153 | 2160
154 | >>> a * (b ** c)
155 | 2160
156 | ```
157 |
158 | 配图来自Twitter
159 |
160 | 
161 |
--------------------------------------------------------------------------------
/courses/python37.md:
--------------------------------------------------------------------------------
1 | # 第37课:模板(一)
2 | 模板提供了一个对设计师友好的语法用于渲染向用户呈现的信息,这里涉及如何使用语法以及如何扩展的内容。
3 |
4 | Django 项目可以配置一个或多个模板引擎,Django后端内置一个自己的模板系统:Django template language(DTL) `` 。当然,也可以使用第三方模版引擎,如:jinja2
5 |
6 | Django 定义了一个标准的API,用于加载和渲染模板,而不用考虑后端的模板系统。加载包括查找给定标识符的模板并对其进行预处理,通常将其编译的结果保存在内存中。渲染工具将上下文数据插入模板并返回结果字符串。
7 |
8 | ### 概念
9 | * Engine
10 | django.template.Engine 封装了 Django 模板系统的一个实例,实例化引擎的主要原因是在 Django 项目之外直接使用 Django 模板语言。
11 |
12 | django.template.backends.django.DjangoTemplates 是一个包装器(wrapper),它将 django.template.Engine 适配成 Django 的模板后端API。
13 | * Template
14 | django.template.Template 是已编译的模板,使用 Engine.get_template() 或 Engine.from_string() 获取模板
15 |
16 | 同样,django.template.backends.django.Template 是一个包装器(wrapper),它将 django.template.Template 适配成公共模板API。
17 |
18 | * Context
19 | 除了上下文数据外,django.template.Context 还包含一些元数据(metadata), 它被传递给 Template.render() 用于渲染模板。
20 |
21 | django.template.RequestContext 是 Context 的子类,它存储当前 HttpRequest 并运行模板上下文处理器(template context processors)。
22 |
23 | * Loaders
24 | 模板加载器负责定位模板,加载模板和返回模板对象。Django 提供了几个内置模板加载器并支持自定义模板加载器。
25 |
26 | * Context processors
27 | 上下文处理器是接收当前 HttpRequest 作为参数的函数,并返回一个添加数据到渲染上下文的字典。它们的主要用途是将所有模板共享的公共数据添加到上下文中,而不用在每个视图中重复代码。
28 |
29 | Django 提供了许多内置的上下文处理器,实现自定义上下文处理器就像定义函数一样简单。
30 |
31 | ### 配置
32 | mysite/settings.py
33 | ```
34 | TEMPLATES = [
35 | {
36 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
37 | 'DIRS': [os.path.join(BASE_DIR, 'templates')],
38 | 'APP_DIRS': True,
39 | 'OPTIONS': {
40 | 'context_processors': [
41 | 'django.template.context_processors.debug',
42 | 'django.template.context_processors.request',
43 | 'django.contrib.auth.context_processors.auth',
44 | 'django.contrib.messages.context_processors.messages',
45 | ],
46 | },
47 | },
48 | ]
49 | ```
50 | 也可多配置一个模版系统,如:jinja2
51 | ```
52 | {
53 | 'BACKEND': 'django.template.backends.jinja2.Jinja2',
54 | 'DIRS': [
55 | '/home/html/jinja2',
56 | ],
57 | },
58 | ```
59 | ### 简单使用
60 | 为了减少加载和渲染模板的重复性,Django 提供了一个自动处理的快捷函数:render_to_string()
61 | ```
62 | from django.template.loader import render_to_string
63 | rendered = render_to_string('my_template.html', {'foo': 'bar'})
64 | ```
65 |
66 | 此外,你可以在 Django 项目之外直接使用配置好的模版引擎:
67 | ```
68 | from django.template import engines
69 |
70 | django_engine = engines['django']
71 | template = django_engine.from_string("Hello {{ name }}!")
72 | ```
73 |
74 | 配图来自Twitter:@chengr28
75 |
76 | 
77 |
--------------------------------------------------------------------------------
/courses/python46.md:
--------------------------------------------------------------------------------
1 | # 第46课:缓存
2 |
3 | ### 简介
4 | 对于动态 Web 网站,每次用户发起的请求,服务器都会计算,从数据库查询、业务逻辑、页面渲染等,这些都会消费计算资源。而缓存就是保存这些计算结果,不用每一次都重新计算,这样就极大的减少了服务端的开销和压力,也会带来性能和用户体验的提升。
5 |
6 | Web 应用涉及不同层面的缓存:数据库、文件系统、内存等。
7 | * Memcached
8 | * Database caching
9 | * Filesystem caching
10 | * Local-memory caching
11 | * Dummy caching (for development)
12 |
13 | ### 缓存API
14 | 通过 Django 提供的缓存 API,你可以任意粒度缓存各种 Python 对象:字符串、字典、模型对象列表等。
15 |
16 | ```
17 | >>> from django.core.cache import cache
18 | >>> cache.set('my_key', 'hello, world!', 30)
19 | >>> cache.get('my_key')
20 | 'hello, world!'
21 | >>> cache.get('my_key')
22 | >>>
23 | 没有返回值,因为30秒后,cache已过期(expire)。
24 | ```
25 |
26 | ### Memcached
27 | Memcached 是 Django 原生支持的最快,最有效的缓存类型,它是一个完全基于内存的缓存服务器,所有缓存的数据都存储在内存中,Facebook、Wikipedia 等大型网站使用它来减少数据库访问并显着提高网站性能。
28 |
29 | 安装完 Memcached 后,你需要安装两个最常见的 Python 包:[python-memcached](https://pypi.org/project/python-memcached/)、[pylibmc](https://pypi.org/project/pylibmc/)。
30 |
31 | Memcached 有很多的配置方案,这是本地缓存的例子,使用了 python-memcached 绑定。
32 | ```
33 | CACHES = {
34 | 'default': {
35 | 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
36 | 'LOCATION': '127.0.0.1:11211',
37 | }
38 | }
39 | ```
40 | ### 数据库缓存
41 | 需要先在数据库中建立一个用于缓存的数据库表,数据库缓存使用的是你配置文件中的数据库,而不是其他的数据库,本教程指的是 PostgreSQL。
42 |
43 | $ python manage.py createcachetable my_cache_table
44 |
45 | 配置信息
46 | ```
47 | CACHES = {
48 | 'default': {
49 | 'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
50 | 'LOCATION': 'my_cache_table',
51 | }
52 | }
53 | ```
54 | ### 文件系统缓存
55 | 目录使用绝对地址
56 | ```
57 | CACHES = {
58 | 'default': {
59 | 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
60 | 'LOCATION': '/var/tmp/django_cache', # 'LOCATION': 'c:/foo/bar', 这是 Windows 下的目录格式
61 | }
62 | }
63 | ```
64 |
65 | ### 本地内存缓存
66 | 如果未在设置文件中指定其他缓存方案,则它就是默认缓存。若你想运行类似 Memcached 这样速度优势的方案(但没安装 Memcached),可采用此方案用于开发。
67 |
68 | 缓存使用最近最少使用(least-recently-used,LRU)策略。
69 |
70 | ```
71 | CACHES = {
72 | 'default': {
73 | 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
74 | 'LOCATION': 'unique-snowflake',
75 | }
76 | }
77 | ```
78 | ### 虚拟缓存
79 | 虚拟缓存,实际上并不是真实的缓存,它只是实现了缓存接口而不做任何事情,常用于开发/测试中不使用缓存的情况。
80 |
81 | ```
82 | CACHES = {
83 | 'default': {
84 | 'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
85 | }
86 | }
87 | ```
88 |
89 | ### 缓存中间件
90 | 要注意顺序,因为中间件的顺序决定了运行的顺序。UpdateCache一定要放在第一位,Fetch必须放最后。
91 | ```
92 | MIDDLEWARE = [
93 | 'django.middleware.cache.UpdateCacheMiddleware',
94 | 'django.middleware.common.CommonMiddleware',
95 | 'django.middleware.cache.FetchFromCacheMiddleware',
96 | ]
97 | ```
98 |
99 | 配图来自Twitter:@tomo_3
100 |
101 | 
102 |
--------------------------------------------------------------------------------
/courses/python29.md:
--------------------------------------------------------------------------------
1 | # 第29课:入门 - 表单和通用视图(四)
2 |
3 | ### 一个简单的表单
4 | 编写 polls/templates/polls/detail.html,包含一个 HTML `
20 | ```
21 | 编辑 polls/views.py,添加以下代码:
22 | ```
23 | from django.http import HttpResponse, HttpResponseRedirect
24 | from django.shortcuts import get_object_or_404, render
25 | from django.urls import reverse
26 | from .models import Choice, Question
27 |
28 | def vote(request, question_id):
29 | question = get_object_or_404(Question, pk=question_id)
30 | try:
31 | selected_choice = question.choice_set.get(pk=request.POST['choice'])
32 | except (KeyError, Choice.DoesNotExist):
33 | return render(request, 'polls/detail.html', {
34 | 'question': question,
35 | 'error_message': "你没有选择",
36 | })
37 | else:
38 | selected_choice.votes += 1
39 | selected_choice.save()
40 | return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
41 | ```
42 |
43 | 编写 polls/views.py,把 results 修改下:
44 | ```
45 | def results(request, question_id):
46 | question = get_object_or_404(Question, pk=question_id)
47 | return render(request, 'polls/results.html', {'question': question})
48 | ```
49 |
50 | 好了,现在创建 polls/templates/polls/results.html 模版文件,包含以下内容:
51 |
52 | ```
53 | {{ question.question_text }}
54 |
55 |
56 | {% for choice in question.choice_set.all %}
57 | - {{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}
58 | {% endfor %}
59 |
60 |
61 | 重新投票?
62 | ```
63 |
64 | ### 使用通用视图
65 | 使用通用视图系统,这样我们可以删除许多多余的代码。其实,这是代码重构的过程。
66 |
67 | 先修改 polls/urls.py,把 `` 改为 ``:
68 | ```
69 | from django.urls import path
70 |
71 | from . import views
72 |
73 | app_name = 'polls'
74 | urlpatterns = [
75 | path('', views.IndexView.as_view(), name='index'),
76 | path('/', views.DetailView.as_view(), name='detail'),
77 | path('/results/', views.ResultsView.as_view(), name='results'),
78 | path('/vote/', views.vote, name='vote'),
79 | ]
80 | ```
81 |
82 | 再修改 polls/views.py,删除旧的 index, detail, 和 results 视图,并用通用视图代替:
83 |
84 | 两个通用视图: ListView 和 DetailView,vote不变保持原样:
85 | ```
86 | from django.http import HttpResponseRedirect
87 | from django.shortcuts import get_object_or_404, render
88 | from django.urls import reverse
89 | from django.views import generic
90 | from .models import Choice, Question
91 |
92 | class IndexView(generic.ListView):
93 | template_name = 'polls/index.html'
94 | context_object_name = 'latest_question_list'
95 |
96 | def get_queryset(self):
97 | """Return the last five published questions."""
98 | return Question.objects.order_by('-pub_date')[:5]
99 |
100 | class DetailView(generic.DetailView):
101 | model = Question
102 | template_name = 'polls/detail.html'
103 |
104 |
105 | class ResultsView(generic.DetailView):
106 | model = Question
107 | template_name = 'polls/results.html'
108 |
109 | def vote ...保持不变...
110 | ```
111 |
112 | 现在使用新的应用 $ python manage.py runserver
113 |
114 | 配图来自Twitter:@atikix
115 |
116 | 
117 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DevOpsGirls
2 |
3 | 一起设计和完善Python程序媛课程。
4 |
5 | DevOpsGirls(Python程序媛)培养计划 (2019版)
6 |
7 | (ps:本课程内容也适合男同学,男生若有兴趣也可一起参与学习和设计。)
8 |
9 | ### 本课程的初衷和目标
10 |
11 | 帮助更多女性学习编程和IT技能,让她们在技术世界里找到更多自信与尊严!
12 |
13 | ### 网络上对DevOpsGirls程序媛培养计划的声音
14 |
15 | 大家对我们推出的DevOpsGirls程序媛培养计划还是[非常支持和认可的](https://twitter.com/huihoo/status/1000995716053979136),我们会更加努力!
16 |
17 | ### 人生苦短,为什么我要用Python?
18 |
19 | 随着机器学习的兴起,Python逐步成为了最受欢迎的语言。
20 |
21 | ### 2018 人工智能、大数据、Python从业者薪资表
22 |
23 | 了解薪资情况,现在正是进入人工智能领域学习就业/转业和学习Python的最佳时机。
24 |
25 | 
26 |
27 | 课程大纲和简介
28 |
29 | ## 第一阶段:Python入门篇
30 |
31 | [第1课:Python历史、版本、安装](courses/python01.md)
32 |
33 | [第2课:快速熟悉Python](courses/python02.md)
34 |
35 | [第3课:数据类型(一)](courses/python03.md)
36 |
37 | [第4课:数据类型(二)](courses/python04.md)
38 |
39 | [第5课:条件](courses/python05.md)
40 |
41 | [第6课:循环](courses/python06.md)
42 |
43 | [第7课:文件、目录](courses/python07.md)
44 |
45 | [第8课:错误、异常](courses/python08.md)
46 |
47 | ## 第二阶段:Python语言篇
48 |
49 | [第9课:语法(Syntax)、语义(Semantics)、词法(Lexical)(一)](courses/python09.md)
50 |
51 | [第10课:语法(Syntax)、语义(Semantics)、词法(Lexical)(二)](courses/python10.md)
52 |
53 | [第11课:操作符(Operators)](courses/python11.md)
54 |
55 | [第12课:程序结构(Program structure)](courses/python12.md)
56 |
57 | [第13课:函数(Function)](courses/python13.md)
58 |
59 | [第14课:面向对象(Object orientation)(一)](courses/python14.md)
60 |
61 | [第15课:面向对象(Object orientation)(二)](courses/python15.md)
62 |
63 | [第16课:模块/库(Module/Library)(一)](courses/python16.md)
64 |
65 | [第17课:模块/库(Module/Library)(二)](courses/python17.md)
66 |
67 | [第18课:接口(Interface)](courses/python18.md)
68 |
69 | [第19课:闭包(Closures)](courses/python19.md)
70 |
71 | [第20课:元编程(Metaprogramming)](courses/python20.md)
72 |
73 | [第21课:测试(Testing)(一)](courses/python21.md)
74 |
75 | [第22课:测试(Testing)(二)](courses/python22.md)
76 |
77 | [第23课:设计模式(Design patterns)](courses/python23.md)
78 |
79 | [第24课:领域特定语言(Domain-specific language,DSL)](courses/python24.md)
80 |
81 | ## 第三阶段:Django框架篇
82 |
83 | [第25课:Django web框架概述](courses/python25.md)
84 |
85 | [第26课:入门 - 请求和响应(一)](courses/python26.md)
86 |
87 | [第27课:入门 - 模型和管理后台(二)](courses/python27.md)
88 |
89 | [第28课:入门 - 视图和模板(三)](courses/python28.md)
90 |
91 | [第29课:入门 - 表单和通用视图(四)](courses/python29.md)
92 |
93 | [第30课:入门 - 完善管理后台(五)](courses/python30.md)
94 |
95 | [第31课:入门 - 样式风格(六)](courses/python31.md)
96 |
97 | [第32课:入门 - 测试(七)](courses/python32.md)
98 |
99 | [第33课:模型(一)](courses/python33.md)
100 |
101 | [第34课:模型(二)](courses/python34.md)
102 |
103 | [第35课:视图(一)](courses/python35.md)
104 |
105 | [第36课:视图(二)](courses/python36.md)
106 |
107 | [第37课:模板(一)](courses/python37.md)
108 |
109 | [第38课:模板(二)](courses/python38.md)
110 |
111 | [第39课:表单(一)](courses/python39.md)
112 |
113 | [第40课:表单(二)](courses/python40.md)
114 |
115 | ## 第四阶段:Django常用工具和安全篇
116 |
117 | [第41课:认证](courses/python41.md)
118 |
119 | [第42课:会话](courses/python42.md)
120 |
121 | [第43课:分页](courses/python43.md)
122 |
123 | [第44课:验证](courses/python44.md)
124 |
125 | [第45课:序列化](courses/python45.md)
126 |
127 | [第46课:缓存](courses/python46.md)
128 |
129 | [第47课:日志](courses/python47.md)
130 |
131 | [第48课:安全概览](courses/python48.md)
132 |
133 | [第49课:加密签名](courses/python49.md)
134 |
135 | [第50课:中间件](courses/python50.md)
136 |
137 |
138 | ## 第五阶段:Python小结
139 |
140 | [第51课:知识回顾](courses/python51.md)
141 |
142 | [第52课:难点强化](courses/python52.md)
143 |
144 | [第53课:Python进阶](courses/python53.md)
145 |
146 | [第54课:Python面试](courses/python54.md)
147 |
148 | ## 许可方式 License
149 |
150 | courses和slides采用CC
151 |
152 | [](http://wiki.huihoo.com/wiki/CC-BY-SA_3.0)
153 |
154 | src采用Apache v2
155 |
156 |
157 | ## 赞助与支持
158 | 本教程为免费教程,若需要得到更多技术支持,可通过赞助我们的方式获得。
159 |
160 | 
161 |
162 | [灰狐的朋友们更多权益](https://wiki.huihoo.com/wiki/%E7%81%B0%E7%8B%90%E4%BC%9A%E5%91%98)
163 |
--------------------------------------------------------------------------------
/courses/python27.md:
--------------------------------------------------------------------------------
1 | # 第27课:入门 - 模型和管理后台(二)
2 |
3 | 涉及到模型,就要使用到数据库。
4 |
5 | ### 配置数据库
6 | 打开 mysite/settings.py
7 |
8 | 先创建数据库:mysite
9 | ```
10 | DATABASES = {
11 | 'default': {
12 | 'ENGINE': 'django.db.backends.postgresql_psycopg2',
13 | 'NAME': 'mysite',
14 | 'USER': 'postgres',
15 | 'PASSWORD': 'postgres',
16 | 'HOST': 'localhost',
17 | 'PORT': '5432',
18 | }
19 | }
20 | ```
21 | $ python manage.py migrate
22 | ```
23 | Operations to perform:
24 | Apply all migrations: admin, auth, contenttypes, sessions
25 | Running migrations:
26 | Applying contenttypes.0001_initial... OK
27 | Applying auth.0001_initial... OK
28 | Applying admin.0001_initial... OK
29 | Applying admin.0002_logentry_remove_auto_add... OK
30 | Applying admin.0003_logentry_add_action_flag_choices... OK
31 | Applying contenttypes.0002_remove_content_type_name... OK
32 | Applying auth.0002_alter_permission_name_max_length... OK
33 | Applying auth.0003_alter_user_email_max_length... OK
34 | Applying auth.0004_alter_user_username_opts... OK
35 | Applying auth.0005_alter_user_last_login_null... OK
36 | Applying auth.0006_require_contenttypes_0002... OK
37 | Applying auth.0007_alter_validators_add_error_messages... OK
38 | Applying auth.0008_alter_user_username_max_length... OK
39 | Applying auth.0009_alter_user_last_name_max_length... OK
40 | Applying sessions.0001_initial... OK
41 | ```
42 |
43 | 默认启用以下应用并创建相关数据库表,这些应用给常规项目提供方便:
44 |
45 | * django.contrib.admin -- 管理员站点, 你很快就会使用它。
46 | * django.contrib.auth -- 认证授权系统。
47 | * django.contrib.contenttypes -- 内容类型框架。
48 | * django.contrib.sessions -- 会话框架。
49 | * django.contrib.messages -- 消息框架。
50 | * django.contrib.staticfiles -- 管理静态文件的框架。
51 |
52 | ### 创建模型
53 | 定义模型也就是数据库结构设计,数据库和表会从从模型自动生成。Django的迁移代码是由你的模型文件自动生成,它本质上是个历史记录,Django可以用它来进行数据库的滚动更新,通过这种方式使其能够和当前的模型匹配。
54 |
55 | 编辑 polls/models.py
56 | ```
57 | from django.db import models
58 |
59 | class Question(models.Model):
60 | question_text = models.CharField(max_length=200)
61 | pub_date = models.DateTimeField('date published')
62 |
63 | class Choice(models.Model):
64 | question = models.ForeignKey(Question, on_delete=models.CASCADE)
65 | choice_text = models.CharField(max_length=200)
66 | votes = models.IntegerField(default=0)
67 | ```
68 | 新增Question和Choice两个模型,每个模型被表示为 django.db.models.Model 类的子类。每个模型有一些类变量,它们都表示模型里的一个数据库字段。
69 |
70 | 使用 ForeignKey 定义了一个关系,每个 Choice 对象都关联到一个 Question 对象。
71 |
72 |
73 | ### 激活模型
74 | 修改 mysite/settings.py,增加polls.apps.PollsConfig
75 | ```
76 | INSTALLED_APPS = [
77 | 'polls.apps.PollsConfig',
78 | ...
79 | ]
80 | ```
81 | $ python manage.py makemigrations polls
82 | ```
83 | Migrations for 'polls':
84 | polls/migrations/0001_initial.py
85 | - Create model Choice
86 | - Create model Question
87 | - Add field question to choice
88 | ```
89 | 然后执行migrate自动执行数据库迁移并同步管理你的数据库结构。
90 |
91 | $ python manage.py sqlmigrate polls 0001
92 | ```
93 | BEGIN;
94 | --
95 | -- Create model Choice
96 | --
97 | CREATE TABLE "polls_choice" ("id" serial NOT NULL PRIMARY KEY, "choice_text" varchar(200) NOT NULL, "votes" integer NOT NULL);
98 | --
99 | -- Create model Question
100 | --
101 | CREATE TABLE "polls_question" ("id" serial NOT NULL PRIMARY KEY, "question_text" varchar(200) NOT NULL, "pub_date" timestamp with time zone NOT NULL);
102 | --
103 | -- Add field question to choice
104 | --
105 | ALTER TABLE "polls_choice" ADD COLUMN "question_id" integer NOT NULL;
106 | CREATE INDEX "polls_choice_question_id_c5b4b260" ON "polls_choice" ("question_id");
107 | ALTER TABLE "polls_choice" ADD CONSTRAINT "polls_choice_question_id_c5b4b260_fk_polls_question_id" FOREIGN KEY ("question_id") REFERENCES "polls_question" ("id") DEFERRABLE INITIALLY DEFERRED;
108 | COMMIT;
109 | ```
110 | 最后,再次运行 migrate 命令,在数据库里创建新定义的模型的数据表,这时就新建了这两张表。
111 |
112 | $ python manage.py migrate
113 | ```
114 | Operations to perform:
115 | Apply all migrations: admin, auth, contenttypes, polls, sessions
116 | Running migrations:
117 | Applying polls.0001_initial... OK
118 | ```
119 | 所以,改变模型需要这三步:
120 | * 编辑 models.py 文件,改变模型。
121 | * 运行 python manage.py makemigrations 为模型的改变生成迁移文件。
122 | * 运行 python manage.py migrate 来应用数据库迁移。
123 |
124 | ### Django管理后台
125 | Django会根据模型自动地创建后台界面。
126 |
127 | 创建一个管理员账号:
128 | ```
129 | $ python manage.py createsuperuser
130 | $ python manage.py runserver
131 | http://127.0.0.1:8000/admin/
132 | admin/adminadmin
133 | ```
134 |
135 | ### 将polls应用加入管理
136 | 编辑 polls/admin.py
137 | ```
138 | from django.contrib import admin
139 | from .models import Question
140 |
141 | admin.site.register(Question)
142 | ```
143 | 以后其它应用加入管理也采用类似方法,这样就可以在后台统一管理这些应用了。
144 |
145 | 配图来自Twitter:@atikix
146 |
147 | 
148 |
--------------------------------------------------------------------------------
/courses/python21.md:
--------------------------------------------------------------------------------
1 | # 第21课:测试(Testing)(一)
2 |
3 | 其实,这块包含软件测试、自动化、软件质量等内容,但这里我们主要学习讨论Python测试的一些入门知识。
4 |
5 | 先回顾一下[第8课:错误、异常](python08.md)的内容
6 |
7 | ### unittest
8 | unittest是Python用于单元测试的标准模块。
9 |
10 | 先运行一个简单的单元测试,感受下:
11 | ```
12 | >>> import unittest
13 | >>>
14 | >>> class MyTest(unittest.TestCase):
15 | ... pass
16 | ...
17 | >>> if __name__ == '__main__':
18 | ... unittest.main()
19 | ...
20 |
21 | ----------------------------------------------------------------------
22 | Ran 0 tests in 0.000s
23 | ```
24 | 再来一个复杂点的单元测试,运行5个小测试:可忽略、标记、或按照预期运行失败。
25 |
26 | unittest模块中的装饰器可用来控制对指定测试方法的处理,如:skip、skipIf、skipUnless、expectedFailure等。
27 |
28 | 如在macOS上运行以下测试,touch unittestsample.py
29 | ```
30 | import unittest
31 | import os
32 | import platform
33 |
34 | class Tests(unittest.TestCase):
35 | def test_0(self):
36 | self.assertTrue(True)
37 |
38 | @unittest.skip('skipped test')
39 | def test_1(self):
40 | self.fail('should have failed!')
41 |
42 | @unittest.skipIf(os.name=='posix', 'Not supported on Unix')
43 | def test_2(self):
44 | import winreg
45 |
46 | @unittest.skipUnless(platform.system() == 'Darwin', 'Mac specific test')
47 | def test_3(self):
48 | self.assertTrue(True)
49 |
50 | @unittest.expectedFailure
51 | def test_4(self):
52 | self.assertEqual(2+2, 5)
53 |
54 | if __name__ == '__main__':
55 | unittest.main()
56 | ```
57 |
58 | 运行这个例子:
59 | ```
60 | (venv2) gougou:python huihoo$ python unittestsample.py -v
61 | test_0 (__main__.Tests) ... ok
62 | test_1 (__main__.Tests) ... skipped 'skipped test'
63 | test_2 (__main__.Tests) ... skipped 'Not supported on Unix'
64 | test_3 (__main__.Tests) ... ok
65 | test_4 (__main__.Tests) ... expected failure
66 |
67 | ----------------------------------------------------------------------
68 | Ran 5 tests in 0.001s
69 |
70 | OK (skipped=2, expected failures=1)
71 | ```
72 | ### doctest
73 | doctest模块会搜索那些看起来像是python交互式会话中的代码片段,然后尝试执行并验证结果。
74 |
75 | 运行一个简单的doctext,先感受下:
76 | ```
77 | >>> if __name__ == "__main__":
78 | ... import doctest
79 | ... doctest.testmod()
80 | ...
81 | TestResults(failed=0, attempted=0)
82 | ```
83 | 再来一个稍微复杂点的例子,创建一个doctestsample.py文件,有两个测试用例,包含以下内容:
84 | ```
85 | def add(a, b):
86 | """
87 | >>> add(1, 2)
88 | 3
89 | >>> add('python ', 'rust')
90 | 'python rust'
91 | """
92 | return a + b
93 | if __name__=='__main__':
94 | import doctest
95 | doctest.testmod()
96 | ```
97 |
98 | 运行这个例子:
99 | ```
100 | python -m doctest -v doctestsample.py # -m 表示引用一个模块,-v 等价于 verbose=True
101 | python doctestsample.py -v
102 |
103 | 运行结果:
104 | Trying:
105 | add(1, 2)
106 | Expecting:
107 | 3
108 | ok
109 | Trying:
110 | add('python ', 'rust')
111 | Expecting:
112 | 'python rust'
113 | ok
114 | 1 items had no tests:
115 | __main__
116 | 1 items passed all tests:
117 | 2 tests in __main__.add
118 | 2 tests in 2 items.
119 | 2 passed and 0 failed.
120 | Test passed.
121 |
122 | ```
123 |
124 | ### py.test
125 | 安装 pip install pytest
126 |
127 | 创建pytestsample.py文件,包含:
128 | ```
129 | def inc(x):
130 | return x + 1
131 |
132 | def test_answer():
133 | assert inc(3) == 5
134 | ```
135 |
136 | 运行测试:
137 | ```
138 | $ pytest pytestsample.py
139 | ================================= test session starts ======================================
140 | platform darwin -- Python 3.7.1, pytest-4.2.0, py-1.7.0, pluggy-0.8.1
141 | rootdir: /private/tmp/python, inifile:
142 | collected 1 item
143 | pytestsample.py F [100%]
144 |
145 | ================================= FAILURES ===================================
146 | _________________________________ test_answer ___________________________________
147 |
148 | def test_answer():
149 | > assert inc(3) == 5
150 | E assert 4 == 5
151 | E + where 4 = inc(3)
152 |
153 | pytestsample.py:5: AssertionError
154 | ================================ 1 failed in 0.45 seconds ========================================
155 |
156 | ```
157 | ### mock
158 | 在单元测试中,模拟对象可以模拟复杂的、真实的(非模拟)对象的行为, 如果真实的对象无法放入单元测试中,使用模拟对象就很有帮助。
159 |
160 | 为什么要用mock?
161 |
162 | 在下面的情形,可能需要使用模拟对象来代替真实对象:
163 |
164 | * 真实对象的行为是不确定的(例如,当前的时间或当前的温度);
165 | * 真实对象很难搭建起来;
166 | * 真实对象的行为很难触发(例如,网络错误);
167 | * 真实对象速度很慢(例如,一个完整的数据库,在测试之前可能需要初始化);
168 | * 真实的对象是用户界面,或包括用户界面在内;
169 | * 真实的对象使用了回调机制;
170 | * 真实对象可能还不存在;
171 | * 真实对象可能包含不能用作测试(而不是为实际工作)的信息和方法。
172 |
173 | 从Python 3.3开始,mock模块已经被合并到标准库中,被命名为unittest.mock
174 |
175 | from unittest import mock
176 |
177 | 在Python 3.3以前版本,需要安装,pip install mock
178 |
179 | import mock
180 |
181 | 先感受下mock
182 | ```
183 | >>> from unittest.mock import MagicMock
184 | >>> mock = MagicMock(side_effect=[1, 2, 3])
185 | >>> mock()
186 | 1
187 | >>> mock()
188 | 2
189 | >>> mock()
190 | 3
191 | ```
192 |
193 | Mock这块内容会比较多,以后再深入展开。
194 |
195 | 今天是大年初三,顺祝大家2019,新年快乐!
196 |
197 | 配图来自Twitter:@chengr28
198 |
199 | 
200 |
--------------------------------------------------------------------------------
/courses/python16.md:
--------------------------------------------------------------------------------
1 | # 第16课:模块/库(Module/Library)(一)
2 |
3 | 先抛出一个简单python web应用的例子的目录结构:
4 |
5 | ```
6 | mysite/
7 | manage.py
8 | mysite/
9 | __init__.py
10 | settings.py
11 | urls.py
12 | wsgi.py
13 | polls/
14 | __init__.py
15 | admin.py
16 | migrations/
17 | __init__.py
18 | 0001_initial.py
19 | models.py
20 | static/
21 | polls/
22 | images/
23 | background.gif
24 | style.css
25 | templates/
26 | polls/
27 | detail.html
28 | index.html
29 | results.html
30 | tests.py
31 | urls.py
32 | views.py
33 | templates/
34 | admin/
35 | base_site.html
36 | ```
37 | 你可以执行以下import语句引入
38 | * import mysite.polls.tests
39 | * from mysite.polls import urls
40 | * import mysite.pools.views as views
41 |
42 | ### 命名空间(namespace)和作用域(scope)
43 | python最大特点也是最核心思想就是: 一切皆对象。
44 |
45 | 命名空间是名字和对象的映射,可以把一个namespace理解为一个字典。
46 |
47 | 命名空间的作用:程序在直接访问变量时,会在当前的命名空间内查找,并会从内到外依次访问所有的作用域直到找到。
48 |
49 | 命名空间可以分为三类:
50 | * 函数的局部命名空间
51 | * 模块的全局命名空间
52 | * 内置命名空间
53 |
54 | 作用域就是一个Python程序可以直接访问命名空间的区域,可以具体分为以下四个作用域:
55 | * Local(innermost) 最里面的局部作用域
56 | * Enclosing 外层函数的局部作用域
57 | * Global(next-to-last) 模块的全局作用域
58 | * Built-in(outtermost) 包含Python内置对象的最外层作用域
59 |
60 | ```
61 | def scope_test():
62 | def do_local():
63 | variable = "local variable"
64 |
65 | def do_nonlocal():
66 | nonlocal variable
67 | variable = "nonlocal variable"
68 |
69 | def do_global():
70 | global variable
71 | variable = "global variable"
72 |
73 | variable = "test variable"
74 | do_local()
75 | print("After local assignment:", variable)
76 | do_nonlocal()
77 | print("After nonlocal assignment:", variable)
78 | do_global()
79 | print("After global assignment:", variable)
80 |
81 | scope_test()
82 | print("In global scope:", variable)
83 | ```
84 |
85 | ### 模块
86 | 模块即一个Python文件.py
87 |
88 | ### 包
89 | 包是由一系列模块组成的集合,包中必须至少含有一个__init__.py文件,该文件的内容可以为空,用于标识当前文件夹是一个包。
90 |
91 | 上面例子包含了三个包:mysite、polls、migrations
92 |
93 | ### 标准模块
94 | Python内置了非常多的模块,大部分是纯Python的,也有一些用C编写的模块。熟练使用这些模块,能帮助你解决日常编程中出现的许多问题,所以大家很有必要熟悉这些标准库模块。
95 |
96 | 这里简单介绍下以下常用模块的使用方法:
97 | #### error
98 | 捕获各种异常,并做特殊处理。
99 |
100 | ```
101 | >>>import os
102 | >>>os.kill(123, 0)
103 | >>>os.strerror(3)
104 | ```
105 | #### subprocess
106 | subprocess模块允许你生成新进程,连接到它们的input/output/error管道,并获取它们的返回代码, 该模块旨在替换几个较旧的模块和功能:os.system、os.spawn*、os.popen*等
107 | ```
108 | >>> import subprocess
109 | >>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
110 | CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0, stdout=b'crw-rw-rw- 1 root wheel 3, 2 2 5 17:52 /dev/null\n')
111 | ```
112 |
113 | #### contextlib
114 | Python程序通过上下文管理能让代码的可读性更强并且错误更少。
115 | ```
116 | from contextlib import contextmanager
117 |
118 | @contextmanager
119 | def tag(name):
120 | print("<%s>" % name)
121 | yield
122 | print("%s>" % name)
123 |
124 | with tag("h1"):
125 | print("python")
126 | ```
127 |
128 | #### glob
129 | glob是用来匹配UNIX风格路径名的模块,支持 '*'、'?'、'[]'三种通配符。
130 | ```
131 | $ ls
132 | 1.txt 2.txt a1.txt a2.txt b1.txt b2.txt
133 |
134 | >>> import glob
135 | >>> glob.glob('./*.txt')
136 | ['./a1.txt', './a2.txt', './b2.txt', './2.txt', './b1.txt', './1.txt']
137 | >>> glob.glob('./a?.txt')
138 | ['./a1.txt', './a2.txt']
139 | >>> glob.glob('./b?.txt')
140 | ['./b2.txt', './b1.txt']
141 | >>> glob.glob('./[0-9].*')
142 | ['./2.txt', './1.txt']
143 | >>> glob.glob('./a[0-9].*')
144 | ['./a1.txt', './a2.txt']
145 | >>> glob.glob('./b[0-9].*')
146 | ['./b2.txt', './b1.txt']
147 | ```
148 |
149 | #### operator
150 | 标准运算符作为函数,如求和我们可以使用sum,乘积可结合operator和reduce模块来实现。
151 |
152 | ```
153 | >>> import operator
154 | >>> from functools import reduce
155 | >>> reduce(operator.mul, (5, 4, 3, 2, 1))
156 | 120
157 | ```
158 |
159 | #### functools
160 | functools模块用于高阶函数,包含了一系列操作其它函数的工具。
161 | ```
162 | >>> from functools import partial
163 | >>> basetwo = partial(int, base=2)
164 | >>> basetwo.__doc__ = '将base 2字符串转换为整数'
165 | >>> basetwo('10010')
166 | 18
167 | >>> basetwo('11111')
168 | 31
169 | ```
170 |
171 | #### collections
172 | 回忆一下之前提到的标准数据类型中包含的:dict, list, set, tuple。
173 |
174 | collections模块实现了专门的容器数据类型:
175 | * namedtuple:能创建可以通过属性访问元素内容的扩展元祖。
176 | * deque:一个双端队列,能够在队列两端添加或删除队列元素。
177 | * ChainMap:
178 | * Counter:一个方便、快速计算的计时器工具。
179 | * OrderedDict:Python的dict是无序的,而OrderedDict保证字典健值对的顺序。
180 | * defaultdict:简化了处理不存在键的场景。
181 | * UserDict:
182 | * UserList:
183 | * UserString:
184 |
185 | 举一个Counter的例子
186 | ```
187 | >>> import collections
188 | >>> words = ['a', 'b', 'a', 'c', 'd', 'c', 'e', 'b']
189 | >>> cnt = collections.Counter(words)
190 | >>> cnt.most_common(5)
191 | [('a', 2), ('b', 2), ('c', 2), ('d', 1), ('e', 1)]
192 | ```
193 |
194 | ### 标准库思维导图
195 | 7张Python[常见标准库思维导图](https://woaielf.github.io/2018/04/15/python2/):
196 | * 1、标准库概述
197 | 
198 | * 2、正则表达式
199 | 
200 | * 3、日期 & 时间
201 | 
202 | * 4、系统 & 文件
203 | 
204 | * 5、进程 & 线程
205 | 
206 | * 6、数据库操作
207 | 
208 | * 7、数学运算 & 数据结构
209 | 
210 |
211 | 配图来自Twitter:@chengr28
212 |
213 | 
214 |
--------------------------------------------------------------------------------