From 20ba69a60097c5052a212a281f0b3e2d4ec8a5ff Mon Sep 17 00:00:00 2001 From: 1337428173 <1337428173@qq.com> Date: Wed, 3 Apr 2024 08:41:04 +0000 Subject: [PATCH 1/3] GitBook: No commit message --- SUMMARY.md | 222 ++++++++++++++++++ day01-15-1/README.md | 2 + day01-15-10/README.md | 2 + day01-15-11/README.md | 2 + day01-15-12/README.md | 2 + day01-15-13/README.md | 2 + day01-15-14/README.md | 2 + day01-15-2/README.md | 2 + day01-15-3/README.md | 2 + day01-15-4/README.md | 2 + day01-15-5/README.md | 2 + day01-15-6/README.md | 2 + day01-15-7/README.md | 2 + day01-15-8/README.md | 2 + day01-15-9/README.md | 2 + day01-15/README.md | 2 + day16-20/README.md | 2 + day21-30/README.md | 2 + day31-35/README.md | 2 + day36-40-1/README.md | 2 + day36-40-2/README.md | 2 + day36-40-3/README.md | 2 + day36-40-4/README.md | 2 + day36-40-5/README.md | 2 + day36-40/README.md | 2 + day41-55-1/README.md | 2 + day41-55-10/README.md | 2 + day41-55-11/README.md | 2 + day41-55-12/README.md | 2 + day41-55-13/README.md | 2 + day41-55-14/README.md | 2 + day41-55-2/README.md | 2 + day41-55-3/README.md | 2 + day41-55-4/README.md | 2 + day41-55-5/README.md | 2 + day41-55-6/README.md | 2 + day41-55-7/README.md | 2 + day41-55-8/README.md | 2 + day41-55-9/README.md | 2 + day41-55/README.md | 2 + day56-60/README.md | 2 + day61-65-1/README.md | 2 + day61-65-2/README.md | 2 + day61-65-3/README.md | 2 + day61-65-4/README.md | 2 + day61-65-5/README.md | 2 + day61-65-6/README.md | 2 + day61-65-7/README.md | 2 + day61-65-8/README.md | 2 + day61-65/README.md | 2 + day66-80-1/README.md | 2 + day66-80-10/README.md | 2 + day66-80-11/README.md | 2 + day66-80-12/README.md | 2 + day66-80-13/README.md | 2 + day66-80-14/README.md | 2 + day66-80-2/README.md | 2 + day66-80-3/README.md | 2 + day66-80-4/README.md | 2 + day66-80-5/README.md | 2 + day66-80-6/README.md | 2 + day66-80-7/README.md | 2 + day66-80-8/README.md | 2 + day66-80-9/README.md | 2 + day66-80/README.md | 2 + day81-90-1/README.md | 2 + day81-90-10/README.md | 2 + day81-90-2/README.md | 2 + day81-90-3/README.md | 2 + day81-90-4/README.md | 2 + day81-90-5/README.md | 2 + day81-90-6/README.md | 2 + day81-90-7/README.md | 2 + day81-90-8/README.md | 2 + day81-90-9/README.md | 2 + day81-90/README.md | 2 + day91-100-1/README.md | 2 + day91-100-2/README.md | 2 + day91-100-3/README.md | 2 + day91-100-4/README.md | 2 + day91-100-5/README.md | 2 + day91-100-6/README.md | 2 + day91-100-7/README.md | 2 + day91-100-8/README.md | 2 + day91-100-9/README.md | 2 + day91-100/README.md | 2 + fan-wai-pian-1/README.md | 2 + fan-wai-pian-10/README.md | 2 + fan-wai-pian-11/README.md | 2 + fan-wai-pian-12/README.md | 2 + fan-wai-pian-13/README.md | 2 + fan-wai-pian-14/README.md | 2 + fan-wai-pian-15/README.md | 2 + fan-wai-pian-2/README.md | 2 + fan-wai-pian-3/README.md | 2 + fan-wai-pian-4/README.md | 2 + fan-wai-pian-5/README.md | 2 + fan-wai-pian-6/README.md | 2 + fan-wai-pian-7/README.md | 2 + fan-wai-pian-8/README.md | 2 + fan-wai-pian-9/README.md | 2 + fan-wai-pian/README.md | 2 + gong-kai-ke-1/README.md | 2 + gong-kai-ke-1/wen-dang/README.md | 2 + .../README.md | 2 + gong-kai-ke-2/README.md | 2 + gong-kai-ke-2/wen-dang/README.md | 2 + .../README.md | 2 + gong-kai-ke-3/README.md | 2 + gong-kai-ke-3/wen-dang/README.md | 2 + .../README.md | 2 + gong-kai-ke/README.md | 2 + gong-kai-ke/wen-dang/README.md | 2 + .../README.md | 2 + 114 files changed, 448 insertions(+) create mode 100644 SUMMARY.md create mode 100644 day01-15-1/README.md create mode 100644 day01-15-10/README.md create mode 100644 day01-15-11/README.md create mode 100644 day01-15-12/README.md create mode 100644 day01-15-13/README.md create mode 100644 day01-15-14/README.md create mode 100644 day01-15-2/README.md create mode 100644 day01-15-3/README.md create mode 100644 day01-15-4/README.md create mode 100644 day01-15-5/README.md create mode 100644 day01-15-6/README.md create mode 100644 day01-15-7/README.md create mode 100644 day01-15-8/README.md create mode 100644 day01-15-9/README.md create mode 100644 day01-15/README.md create mode 100644 day16-20/README.md create mode 100644 day21-30/README.md create mode 100644 day31-35/README.md create mode 100644 day36-40-1/README.md create mode 100644 day36-40-2/README.md create mode 100644 day36-40-3/README.md create mode 100644 day36-40-4/README.md create mode 100644 day36-40-5/README.md create mode 100644 day36-40/README.md create mode 100644 day41-55-1/README.md create mode 100644 day41-55-10/README.md create mode 100644 day41-55-11/README.md create mode 100644 day41-55-12/README.md create mode 100644 day41-55-13/README.md create mode 100644 day41-55-14/README.md create mode 100644 day41-55-2/README.md create mode 100644 day41-55-3/README.md create mode 100644 day41-55-4/README.md create mode 100644 day41-55-5/README.md create mode 100644 day41-55-6/README.md create mode 100644 day41-55-7/README.md create mode 100644 day41-55-8/README.md create mode 100644 day41-55-9/README.md create mode 100644 day41-55/README.md create mode 100644 day56-60/README.md create mode 100644 day61-65-1/README.md create mode 100644 day61-65-2/README.md create mode 100644 day61-65-3/README.md create mode 100644 day61-65-4/README.md create mode 100644 day61-65-5/README.md create mode 100644 day61-65-6/README.md create mode 100644 day61-65-7/README.md create mode 100644 day61-65-8/README.md create mode 100644 day61-65/README.md create mode 100644 day66-80-1/README.md create mode 100644 day66-80-10/README.md create mode 100644 day66-80-11/README.md create mode 100644 day66-80-12/README.md create mode 100644 day66-80-13/README.md create mode 100644 day66-80-14/README.md create mode 100644 day66-80-2/README.md create mode 100644 day66-80-3/README.md create mode 100644 day66-80-4/README.md create mode 100644 day66-80-5/README.md create mode 100644 day66-80-6/README.md create mode 100644 day66-80-7/README.md create mode 100644 day66-80-8/README.md create mode 100644 day66-80-9/README.md create mode 100644 day66-80/README.md create mode 100644 day81-90-1/README.md create mode 100644 day81-90-10/README.md create mode 100644 day81-90-2/README.md create mode 100644 day81-90-3/README.md create mode 100644 day81-90-4/README.md create mode 100644 day81-90-5/README.md create mode 100644 day81-90-6/README.md create mode 100644 day81-90-7/README.md create mode 100644 day81-90-8/README.md create mode 100644 day81-90-9/README.md create mode 100644 day81-90/README.md create mode 100644 day91-100-1/README.md create mode 100644 day91-100-2/README.md create mode 100644 day91-100-3/README.md create mode 100644 day91-100-4/README.md create mode 100644 day91-100-5/README.md create mode 100644 day91-100-6/README.md create mode 100644 day91-100-7/README.md create mode 100644 day91-100-8/README.md create mode 100644 day91-100-9/README.md create mode 100644 day91-100/README.md create mode 100644 fan-wai-pian-1/README.md create mode 100644 fan-wai-pian-10/README.md create mode 100644 fan-wai-pian-11/README.md create mode 100644 fan-wai-pian-12/README.md create mode 100644 fan-wai-pian-13/README.md create mode 100644 fan-wai-pian-14/README.md create mode 100644 fan-wai-pian-15/README.md create mode 100644 fan-wai-pian-2/README.md create mode 100644 fan-wai-pian-3/README.md create mode 100644 fan-wai-pian-4/README.md create mode 100644 fan-wai-pian-5/README.md create mode 100644 fan-wai-pian-6/README.md create mode 100644 fan-wai-pian-7/README.md create mode 100644 fan-wai-pian-8/README.md create mode 100644 fan-wai-pian-9/README.md create mode 100644 fan-wai-pian/README.md create mode 100644 gong-kai-ke-1/README.md create mode 100644 gong-kai-ke-1/wen-dang/README.md create mode 100644 gong-kai-ke-1/wen-dang/di-04-ci-gong-kai-ke-hao-wan-de-python/README.md create mode 100644 gong-kai-ke-2/README.md create mode 100644 gong-kai-ke-2/wen-dang/README.md create mode 100644 gong-kai-ke-2/wen-dang/di-05-ci-gong-kai-ke-suan-fa-ru-men-xi-lie-1-zhou-er-fu-shi/README.md create mode 100644 gong-kai-ke-3/README.md create mode 100644 gong-kai-ke-3/wen-dang/README.md create mode 100644 gong-kai-ke-3/wen-dang/di-06-ci-gong-kai-ke-suan-fa-ru-men-xi-lie-2-zai-shui-yi-fang/README.md create mode 100644 gong-kai-ke/README.md create mode 100644 gong-kai-ke/wen-dang/README.md create mode 100644 gong-kai-ke/wen-dang/nian-xin-50w+-de-python-cheng-xu-yuan-ru-he-xie-dai-ma/README.md diff --git a/SUMMARY.md b/SUMMARY.md new file mode 100644 index 0000000000..5305ad7c64 --- /dev/null +++ b/SUMMARY.md @@ -0,0 +1,222 @@ +# Table of contents + +* [Python - 100天从新手到大师](README.md) +* [更新日志](更新日志.md) +* [Day01-15](day01-15/README.md) + * [初识Python](Day01-15/01.初识Python.md) +* [Day01-15](day01-15-1/README.md) + * [语言元素](Day01-15/02.语言元素.md) +* [Day01-15](day01-15-2/README.md) + * [分支结构](Day01-15/03.分支结构.md) +* [Day01-15](day01-15-3/README.md) + * [循环结构](Day01-15/04.循环结构.md) +* [Day01-15](day01-15-4/README.md) + * [构造程序逻辑](Day01-15/05.构造程序逻辑.md) +* [Day01-15](day01-15-5/README.md) + * [函数和模块的使用](Day01-15/06.函数和模块的使用.md) +* [Day01-15](day01-15-6/README.md) + * [字符串和常用数据结构](Day01-15/07.字符串和常用数据结构.md) +* [Day01-15](day01-15-7/README.md) + * [面向对象编程基础](Day01-15/08.面向对象编程基础.md) +* [Day01-15](day01-15-8/README.md) + * [面向对象进阶](Day01-15/09.面向对象进阶.md) +* [Day01-15](day01-15-9/README.md) + * [图形用户界面和游戏开发](Day01-15/10.图形用户界面和游戏开发.md) +* [Day01-15](day01-15-10/README.md) + * [文件和异常](Day01-15/11.文件和异常.md) +* [Day01-15](day01-15-11/README.md) + * [使用正则表达式](Day01-15/12.字符串和正则表达式.md) +* [Day01-15](day01-15-12/README.md) + * [进程和线程](Day01-15/13.进程和线程.md) +* [Day01-15](day01-15-13/README.md) + * [网络编程入门](Day01-15/14.网络编程入门和网络应用开发.md) +* [Day01-15](day01-15-14/README.md) + * [图像和办公文档处理](Day01-15/15.图像和办公文档处理.md) +* [Day16-20](day16-20/README.md) + * [Python语言进阶](Day16-20/16-20.Python语言进阶.md) +* [Day21-30](day21-30/README.md) + * [Web前端概述](Day21-30/21-30.Web前端概述.md) +* [Day31-35](day31-35/README.md) + * [31-35.玩转Linux操作系统](Day31-35/31-35.玩转Linux操作系统.md) +* [Day36-40](day36-40/README.md) + * [关系型数据库和MySQL概述](Day36-40/36.关系型数据库和MySQL概述.md) +* [Day36-40](day36-40-1/README.md) + * [SQL 和 MySQL 详解](Day36-40/37.SQL详解.md) +* [Day36-40](day36-40-2/README.md) + * [深入MySQL](Day36-40/38.深入MySQL.md) +* [Day36-40](day36-40-3/README.md) + * [Python程序接入MySQL数据库](Day36-40/39.Python程序接入MySQL数据库.md) +* [Day36-40](day36-40-4/README.md) + * [Hive简介](Day36-40/40.大数据平台和HiveSQL.md) +* [Day36-40](day36-40-5/README.md) + * [NoSQL入门](Day36-40/NoSQL数据库入门.md) +* [Day41-55](day41-55/README.md) + * [Django快速上手](Day41-55/41.Django快速上手.md) +* [Day41-55](day41-55-1/README.md) + * [深入模型](Day41-55/42.深入模型.md) +* [Day41-55](day41-55-2/README.md) + * [静态资源和Ajax请求](Day41-55/43.静态资源和Ajax请求.md) +* [Day41-55](day41-55-3/README.md) + * [Cookie和Session](Day41-55/44.Cookie和Session.md) +* [Day41-55](day41-55-4/README.md) + * [制作报表](Day41-55/45.制作报表.md) +* [Day41-55](day41-55-5/README.md) + * [日志和调试工具栏](Day41-55/46.日志和调试工具栏.md) +* [Day41-55](day41-55-6/README.md) + * [中间件的应用](Day41-55/47.中间件的应用.md) +* [Day41-55](day41-55-7/README.md) + * [前后端分离开发入门](Day41-55/48.前后端分离开发入门.md) +* [Day41-55](day41-55-8/README.md) + * [RESTful架构和DRF入门](Day41-55/49.RESTful架构和DRF入门.md) +* [Day41-55](day41-55-9/README.md) + * [RESTful架构和DRF进阶](Day41-55/50.RESTful架构和DRF进阶.md) +* [Day41-55](day41-55-10/README.md) + * [使用缓存](Day41-55/51.使用缓存.md) +* [Day41-55](day41-55-11/README.md) + * [接入三方平台](Day41-55/52.接入三方平台.md) +* [Day41-55](day41-55-12/README.md) + * [异步任务和定时任务](Day41-55/53.异步任务和定时任务.md) +* [Day41-55](day41-55-13/README.md) + * [单元测试](Day41-55/54.单元测试.md) +* [Day41-55](day41-55-14/README.md) + * [项目上线](Day41-55/55.项目上线.md) +* [Day56-60](day56-60/README.md) + * [用FastAPI开发网络数据接口](Day56-60/56-60.用FastAPI开发数据接口.md) +* [Day61-65](day61-65/README.md) + * [网络数据采集概述](Day61-65/61.网络数据采集概述.md) +* [Day61-65](day61-65-1/README.md) + * [用Python获取网络数据](Day61-65/62.用Python获取网络资源-1.md) +* [Day61-65](day61-65-2/README.md) + * [用Python解析HTML页面](Day61-65/62.用Python解析HTML页面-2.md) +* [Day61-65](day61-65-3/README.md) + * [Python中的并发编程-1](Day61-65/63.Python中的并发编程-1.md) +* [Day61-65](day61-65-4/README.md) + * [Python中的并发编程-2](Day61-65/63.Python中的并发编程-2.md) +* [Day61-65](day61-65-5/README.md) + * [Python中的并发编程-3](Day61-65/63.Python中的并发编程-3.md) +* [Day61-65](day61-65-6/README.md) + * [并发编程在爬虫中的应用](Day61-65/63.并发编程在爬虫中的应用.md) +* [Day61-65](day61-65-7/README.md) + * [使用Selenium抓取网页动态内容](Day61-65/64.使用Selenium抓取网页动态内容.md) +* [Day61-65](day61-65-8/README.md) + * [爬虫框架Scrapy简介](Day61-65/65.爬虫框架Scrapy简介.md) +* [Day66-80](day66-80/README.md) + * [数据分析概述](Day66-80/66.数据分析概述.md) +* [Day66-80](day66-80-1/README.md) + * [环境准备](Day66-80/67.环境准备.md) +* [Day66-80](day66-80-2/README.md) + * [NumPy的应用-1](Day66-80/68.NumPy的应用-1.md) +* [Day66-80](day66-80-3/README.md) + * [NumPy的应用-2](Day66-80/69.NumPy的应用-2.md) +* [Day66-80](day66-80-4/README.md) + * [NumPy的应用-3](Day66-80/70.NumPy的应用-3.md) +* [Day66-80](day66-80-5/README.md) + * [NumPy的应用-4](Day66-80/71.NumPy的应用-4.md) +* [Day66-80](day66-80-6/README.md) + * [深入浅出pandas-1](Day66-80/72.深入浅出pandas-1.md) +* [Day66-80](day66-80-7/README.md) + * [深入浅出pandas-2](Day66-80/73.深入浅出pandas-2.md) +* [Day66-80](day66-80-8/README.md) + * [深入浅出pandas-3](Day66-80/74.深入浅出pandas-3.md) +* [Day66-80](day66-80-9/README.md) + * [深入浅出pandas-4](Day66-80/75.深入浅出pandas-4.md) +* [Day66-80](day66-80-10/README.md) + * [深入浅出pandas-5](Day66-80/76.深入浅出pandas-5.md) +* [Day66-80](day66-80-11/README.md) + * [深入浅出pandas-6](Day66-80/77.深入浅出pandas-6.md) +* [Day66-80](day66-80-12/README.md) + * [数据可视化-1](Day66-80/78.数据可视化-1.md) +* [Day66-80](day66-80-13/README.md) + * [数据可视化-2](Day66-80/79.数据可视化-2.md) +* [Day66-80](day66-80-14/README.md) + * [数据可视化-3](Day66-80/80.数据可视化-3.md) +* [Day81-90](day81-90/README.md) + * [人工智能和机器学习概述](Day81-90/81.人工智能和机器学习概述.md) +* [Day81-90](day81-90-1/README.md) + * [k最近邻分类](Day81-90/82.k最近邻分类.md) +* [Day81-90](day81-90-2/README.md) + * [决策树](Day81-90/83.决策树.md) +* [Day81-90](day81-90-3/README.md) + * [推荐系统实战(1)](Day81-90/83.推荐系统实战-1.md) +* [Day81-90](day81-90-4/README.md) + * [贝叶斯分类](Day81-90/84.贝叶斯分类.md) +* [Day81-90](day81-90-5/README.md) + * [支持向量机](Day81-90/85.支持向量机.md) +* [Day81-90](day81-90-6/README.md) + * [K-均值聚类](Day81-90/86.K-均值聚类.md) +* [Day81-90](day81-90-7/README.md) + * [回归分析](Day81-90/87.回归分析.md) +* [Day81-90](day81-90-8/README.md) + * [Tensorflow入门](Day81-90/88.深度学习入门.md) +* [Day81-90](day81-90-9/README.md) + * [PyTorch入门](Day81-90/89.PyTorch概述.md) +* [Day81-90](day81-90-10/README.md) + * [PyTorch实战](Day81-90/90.PyTorch实战.md) +* [Day91-100](day91-100/README.md) + * [Python面试题实录](Day91-100/100.Python面试题实录.md) +* [Day91-100](day91-100-1/README.md) + * [团队项目开发的问题和解决方案](Day91-100/91.团队项目开发的问题和解决方案.md) +* [Day91-100](day91-100-2/README.md) + * [Docker容器技术详解](Day91-100/92.Docker容器技术详解.md) +* [Day91-100](day91-100-3/README.md) + * [MySQL性能优化](Day91-100/93.MySQL性能优化.md) +* [Day91-100](day91-100-4/README.md) + * [网络API接口设计](Day91-100/94.网络API接口设计.md) +* [Day91-100](day91-100-5/README.md) + * [使用Django开发商业项目](Day91-100/95.使用Django开发商业项目.md) +* [Day91-100](day91-100-6/README.md) + * [软件测试和自动化测试](Day91-100/96.软件测试和自动化测试.md) +* [Day91-100](day91-100-7/README.md) + * [电商网站技术要点剖析](Day91-100/97.电商网站技术要点剖析.md) +* [Day91-100](day91-100-8/README.md) + * [项目部署上线指南](Day91-100/98.项目部署上线和性能调优.md) +* [Day91-100](day91-100-9/README.md) + * [面试中的公共问题](Day91-100/99.面试中的公共问题.md) +* [番外篇](fan-wai-pian/README.md) + * [PEP 8风格指南](番外篇/PEP8风格指南.md) +* [番外篇](fan-wai-pian-1/README.md) + * [Zen of Python(Python之禅)](番外篇/Python之禅的最佳翻译.md) +* [番外篇](fan-wai-pian-2/README.md) + * [Python参考书籍](番外篇/Python参考书籍.md) +* [番外篇](fan-wai-pian-3/README.md) + * [Python容器类型使用小技巧](番外篇/Python容器使用小技巧.md) +* [番外篇](fan-wai-pian-4/README.md) + * [Python数据分析师面试题](番外篇/Python数据分析师面试题.md) +* [番外篇](fan-wai-pian-5/README.md) + * [Python编程惯例](番外篇/Python编程惯例.md) +* [番外篇](fan-wai-pian-6/README.md) + * [一个小例子助你彻底理解协程](番外篇/一个小例子助你彻底理解协程.md) +* [番外篇](fan-wai-pian-7/README.md) + * [使用Hexo搭建自己的博客](番外篇/使用Hexo搭建自己的博客.md) +* [番外篇](fan-wai-pian-8/README.md) + * [常见反爬策略及应对方案](番外篇/常见反爬策略及应对方案.md) +* [番外篇](fan-wai-pian-9/README.md) + * [我为什么选择了Python](番外篇/我为什么选择了Python.md) +* [番外篇](fan-wai-pian-10/README.md) + * [接口文档参考示例](番外篇/接口文档参考示例.md) +* [番外篇](fan-wai-pian-11/README.md) + * [玩转PyCharm](番外篇/玩转PyCharm.md) +* [番外篇](fan-wai-pian-12/README.md) + * [用函数还是用复杂的表达式](番外篇/用函数还是用复杂的表达式.md) +* [番外篇](fan-wai-pian-13/README.md) + * [知乎问题回答](番外篇/知乎问题回答.md) +* [番外篇](fan-wai-pian-14/README.md) + * [英语面试](番外篇/英语面试.md) +* [番外篇](fan-wai-pian-15/README.md) + * [那些年我们踩过的那些坑](番外篇/那些年我们踩过的那些坑.md) +* [公开课](gong-kai-ke/README.md) + * [文档](gong-kai-ke/wen-dang/README.md) + * [年薪50W+的Python程序员如何写代码](gong-kai-ke/wen-dang/nian-xin-50w+-de-python-cheng-xu-yuan-ru-he-xie-dai-ma/README.md) + * [年薪50W+的Python程序员如何写代码](公开课/文档/年薪50W+的Python程序员如何写代码/年薪50W+的Python程序员如何写代码.md) +* [公开课](gong-kai-ke-1/README.md) + * [文档](gong-kai-ke-1/wen-dang/README.md) + * [第04次公开课-好玩的Python](gong-kai-ke-1/wen-dang/di-04-ci-gong-kai-ke-hao-wan-de-python/README.md) + * [好玩的Python](公开课/文档/第04次公开课-好玩的Python/好玩的Python.md) +* [公开课](gong-kai-ke-2/README.md) + * [文档](gong-kai-ke-2/wen-dang/README.md) + * [第05次公开课-算法入门系列1-周而复始](gong-kai-ke-2/wen-dang/di-05-ci-gong-kai-ke-suan-fa-ru-men-xi-lie-1-zhou-er-fu-shi/README.md) + * [算法入门系列课程1 - 周而复始](公开课/文档/第05次公开课-算法入门系列1-周而复始/算法入门系列1-周而复始.md) +* [公开课](gong-kai-ke-3/README.md) + * [文档](gong-kai-ke-3/wen-dang/README.md) + * [第06次公开课-算法入门系列2-在水一方](gong-kai-ke-3/wen-dang/di-06-ci-gong-kai-ke-suan-fa-ru-men-xi-lie-2-zai-shui-yi-fang/README.md) + * [算法入门系列2 - 在水一方](<公开课/文档/第06次公开课-算法入门系列2-在水一方/算法入门系列2 - 在水一方.md>) diff --git a/day01-15-1/README.md b/day01-15-1/README.md new file mode 100644 index 0000000000..74af26405c --- /dev/null +++ b/day01-15-1/README.md @@ -0,0 +1,2 @@ +# Day01-15 + diff --git a/day01-15-10/README.md b/day01-15-10/README.md new file mode 100644 index 0000000000..74af26405c --- /dev/null +++ b/day01-15-10/README.md @@ -0,0 +1,2 @@ +# Day01-15 + diff --git a/day01-15-11/README.md b/day01-15-11/README.md new file mode 100644 index 0000000000..74af26405c --- /dev/null +++ b/day01-15-11/README.md @@ -0,0 +1,2 @@ +# Day01-15 + diff --git a/day01-15-12/README.md b/day01-15-12/README.md new file mode 100644 index 0000000000..74af26405c --- /dev/null +++ b/day01-15-12/README.md @@ -0,0 +1,2 @@ +# Day01-15 + diff --git a/day01-15-13/README.md b/day01-15-13/README.md new file mode 100644 index 0000000000..74af26405c --- /dev/null +++ b/day01-15-13/README.md @@ -0,0 +1,2 @@ +# Day01-15 + diff --git a/day01-15-14/README.md b/day01-15-14/README.md new file mode 100644 index 0000000000..74af26405c --- /dev/null +++ b/day01-15-14/README.md @@ -0,0 +1,2 @@ +# Day01-15 + diff --git a/day01-15-2/README.md b/day01-15-2/README.md new file mode 100644 index 0000000000..74af26405c --- /dev/null +++ b/day01-15-2/README.md @@ -0,0 +1,2 @@ +# Day01-15 + diff --git a/day01-15-3/README.md b/day01-15-3/README.md new file mode 100644 index 0000000000..74af26405c --- /dev/null +++ b/day01-15-3/README.md @@ -0,0 +1,2 @@ +# Day01-15 + diff --git a/day01-15-4/README.md b/day01-15-4/README.md new file mode 100644 index 0000000000..74af26405c --- /dev/null +++ b/day01-15-4/README.md @@ -0,0 +1,2 @@ +# Day01-15 + diff --git a/day01-15-5/README.md b/day01-15-5/README.md new file mode 100644 index 0000000000..74af26405c --- /dev/null +++ b/day01-15-5/README.md @@ -0,0 +1,2 @@ +# Day01-15 + diff --git a/day01-15-6/README.md b/day01-15-6/README.md new file mode 100644 index 0000000000..74af26405c --- /dev/null +++ b/day01-15-6/README.md @@ -0,0 +1,2 @@ +# Day01-15 + diff --git a/day01-15-7/README.md b/day01-15-7/README.md new file mode 100644 index 0000000000..74af26405c --- /dev/null +++ b/day01-15-7/README.md @@ -0,0 +1,2 @@ +# Day01-15 + diff --git a/day01-15-8/README.md b/day01-15-8/README.md new file mode 100644 index 0000000000..74af26405c --- /dev/null +++ b/day01-15-8/README.md @@ -0,0 +1,2 @@ +# Day01-15 + diff --git a/day01-15-9/README.md b/day01-15-9/README.md new file mode 100644 index 0000000000..74af26405c --- /dev/null +++ b/day01-15-9/README.md @@ -0,0 +1,2 @@ +# Day01-15 + diff --git a/day01-15/README.md b/day01-15/README.md new file mode 100644 index 0000000000..74af26405c --- /dev/null +++ b/day01-15/README.md @@ -0,0 +1,2 @@ +# Day01-15 + diff --git a/day16-20/README.md b/day16-20/README.md new file mode 100644 index 0000000000..900442a379 --- /dev/null +++ b/day16-20/README.md @@ -0,0 +1,2 @@ +# Day16-20 + diff --git a/day21-30/README.md b/day21-30/README.md new file mode 100644 index 0000000000..3426d2b5ef --- /dev/null +++ b/day21-30/README.md @@ -0,0 +1,2 @@ +# Day21-30 + diff --git a/day31-35/README.md b/day31-35/README.md new file mode 100644 index 0000000000..26ebd7b7ff --- /dev/null +++ b/day31-35/README.md @@ -0,0 +1,2 @@ +# Day31-35 + diff --git a/day36-40-1/README.md b/day36-40-1/README.md new file mode 100644 index 0000000000..98a0819def --- /dev/null +++ b/day36-40-1/README.md @@ -0,0 +1,2 @@ +# Day36-40 + diff --git a/day36-40-2/README.md b/day36-40-2/README.md new file mode 100644 index 0000000000..98a0819def --- /dev/null +++ b/day36-40-2/README.md @@ -0,0 +1,2 @@ +# Day36-40 + diff --git a/day36-40-3/README.md b/day36-40-3/README.md new file mode 100644 index 0000000000..98a0819def --- /dev/null +++ b/day36-40-3/README.md @@ -0,0 +1,2 @@ +# Day36-40 + diff --git a/day36-40-4/README.md b/day36-40-4/README.md new file mode 100644 index 0000000000..98a0819def --- /dev/null +++ b/day36-40-4/README.md @@ -0,0 +1,2 @@ +# Day36-40 + diff --git a/day36-40-5/README.md b/day36-40-5/README.md new file mode 100644 index 0000000000..98a0819def --- /dev/null +++ b/day36-40-5/README.md @@ -0,0 +1,2 @@ +# Day36-40 + diff --git a/day36-40/README.md b/day36-40/README.md new file mode 100644 index 0000000000..98a0819def --- /dev/null +++ b/day36-40/README.md @@ -0,0 +1,2 @@ +# Day36-40 + diff --git a/day41-55-1/README.md b/day41-55-1/README.md new file mode 100644 index 0000000000..40de9e0134 --- /dev/null +++ b/day41-55-1/README.md @@ -0,0 +1,2 @@ +# Day41-55 + diff --git a/day41-55-10/README.md b/day41-55-10/README.md new file mode 100644 index 0000000000..40de9e0134 --- /dev/null +++ b/day41-55-10/README.md @@ -0,0 +1,2 @@ +# Day41-55 + diff --git a/day41-55-11/README.md b/day41-55-11/README.md new file mode 100644 index 0000000000..40de9e0134 --- /dev/null +++ b/day41-55-11/README.md @@ -0,0 +1,2 @@ +# Day41-55 + diff --git a/day41-55-12/README.md b/day41-55-12/README.md new file mode 100644 index 0000000000..40de9e0134 --- /dev/null +++ b/day41-55-12/README.md @@ -0,0 +1,2 @@ +# Day41-55 + diff --git a/day41-55-13/README.md b/day41-55-13/README.md new file mode 100644 index 0000000000..40de9e0134 --- /dev/null +++ b/day41-55-13/README.md @@ -0,0 +1,2 @@ +# Day41-55 + diff --git a/day41-55-14/README.md b/day41-55-14/README.md new file mode 100644 index 0000000000..40de9e0134 --- /dev/null +++ b/day41-55-14/README.md @@ -0,0 +1,2 @@ +# Day41-55 + diff --git a/day41-55-2/README.md b/day41-55-2/README.md new file mode 100644 index 0000000000..40de9e0134 --- /dev/null +++ b/day41-55-2/README.md @@ -0,0 +1,2 @@ +# Day41-55 + diff --git a/day41-55-3/README.md b/day41-55-3/README.md new file mode 100644 index 0000000000..40de9e0134 --- /dev/null +++ b/day41-55-3/README.md @@ -0,0 +1,2 @@ +# Day41-55 + diff --git a/day41-55-4/README.md b/day41-55-4/README.md new file mode 100644 index 0000000000..40de9e0134 --- /dev/null +++ b/day41-55-4/README.md @@ -0,0 +1,2 @@ +# Day41-55 + diff --git a/day41-55-5/README.md b/day41-55-5/README.md new file mode 100644 index 0000000000..40de9e0134 --- /dev/null +++ b/day41-55-5/README.md @@ -0,0 +1,2 @@ +# Day41-55 + diff --git a/day41-55-6/README.md b/day41-55-6/README.md new file mode 100644 index 0000000000..40de9e0134 --- /dev/null +++ b/day41-55-6/README.md @@ -0,0 +1,2 @@ +# Day41-55 + diff --git a/day41-55-7/README.md b/day41-55-7/README.md new file mode 100644 index 0000000000..40de9e0134 --- /dev/null +++ b/day41-55-7/README.md @@ -0,0 +1,2 @@ +# Day41-55 + diff --git a/day41-55-8/README.md b/day41-55-8/README.md new file mode 100644 index 0000000000..40de9e0134 --- /dev/null +++ b/day41-55-8/README.md @@ -0,0 +1,2 @@ +# Day41-55 + diff --git a/day41-55-9/README.md b/day41-55-9/README.md new file mode 100644 index 0000000000..40de9e0134 --- /dev/null +++ b/day41-55-9/README.md @@ -0,0 +1,2 @@ +# Day41-55 + diff --git a/day41-55/README.md b/day41-55/README.md new file mode 100644 index 0000000000..40de9e0134 --- /dev/null +++ b/day41-55/README.md @@ -0,0 +1,2 @@ +# Day41-55 + diff --git a/day56-60/README.md b/day56-60/README.md new file mode 100644 index 0000000000..020f75fdbd --- /dev/null +++ b/day56-60/README.md @@ -0,0 +1,2 @@ +# Day56-60 + diff --git a/day61-65-1/README.md b/day61-65-1/README.md new file mode 100644 index 0000000000..ef96c6b53d --- /dev/null +++ b/day61-65-1/README.md @@ -0,0 +1,2 @@ +# Day61-65 + diff --git a/day61-65-2/README.md b/day61-65-2/README.md new file mode 100644 index 0000000000..ef96c6b53d --- /dev/null +++ b/day61-65-2/README.md @@ -0,0 +1,2 @@ +# Day61-65 + diff --git a/day61-65-3/README.md b/day61-65-3/README.md new file mode 100644 index 0000000000..ef96c6b53d --- /dev/null +++ b/day61-65-3/README.md @@ -0,0 +1,2 @@ +# Day61-65 + diff --git a/day61-65-4/README.md b/day61-65-4/README.md new file mode 100644 index 0000000000..ef96c6b53d --- /dev/null +++ b/day61-65-4/README.md @@ -0,0 +1,2 @@ +# Day61-65 + diff --git a/day61-65-5/README.md b/day61-65-5/README.md new file mode 100644 index 0000000000..ef96c6b53d --- /dev/null +++ b/day61-65-5/README.md @@ -0,0 +1,2 @@ +# Day61-65 + diff --git a/day61-65-6/README.md b/day61-65-6/README.md new file mode 100644 index 0000000000..ef96c6b53d --- /dev/null +++ b/day61-65-6/README.md @@ -0,0 +1,2 @@ +# Day61-65 + diff --git a/day61-65-7/README.md b/day61-65-7/README.md new file mode 100644 index 0000000000..ef96c6b53d --- /dev/null +++ b/day61-65-7/README.md @@ -0,0 +1,2 @@ +# Day61-65 + diff --git a/day61-65-8/README.md b/day61-65-8/README.md new file mode 100644 index 0000000000..ef96c6b53d --- /dev/null +++ b/day61-65-8/README.md @@ -0,0 +1,2 @@ +# Day61-65 + diff --git a/day61-65/README.md b/day61-65/README.md new file mode 100644 index 0000000000..ef96c6b53d --- /dev/null +++ b/day61-65/README.md @@ -0,0 +1,2 @@ +# Day61-65 + diff --git a/day66-80-1/README.md b/day66-80-1/README.md new file mode 100644 index 0000000000..e6a5758faa --- /dev/null +++ b/day66-80-1/README.md @@ -0,0 +1,2 @@ +# Day66-80 + diff --git a/day66-80-10/README.md b/day66-80-10/README.md new file mode 100644 index 0000000000..e6a5758faa --- /dev/null +++ b/day66-80-10/README.md @@ -0,0 +1,2 @@ +# Day66-80 + diff --git a/day66-80-11/README.md b/day66-80-11/README.md new file mode 100644 index 0000000000..e6a5758faa --- /dev/null +++ b/day66-80-11/README.md @@ -0,0 +1,2 @@ +# Day66-80 + diff --git a/day66-80-12/README.md b/day66-80-12/README.md new file mode 100644 index 0000000000..e6a5758faa --- /dev/null +++ b/day66-80-12/README.md @@ -0,0 +1,2 @@ +# Day66-80 + diff --git a/day66-80-13/README.md b/day66-80-13/README.md new file mode 100644 index 0000000000..e6a5758faa --- /dev/null +++ b/day66-80-13/README.md @@ -0,0 +1,2 @@ +# Day66-80 + diff --git a/day66-80-14/README.md b/day66-80-14/README.md new file mode 100644 index 0000000000..e6a5758faa --- /dev/null +++ b/day66-80-14/README.md @@ -0,0 +1,2 @@ +# Day66-80 + diff --git a/day66-80-2/README.md b/day66-80-2/README.md new file mode 100644 index 0000000000..e6a5758faa --- /dev/null +++ b/day66-80-2/README.md @@ -0,0 +1,2 @@ +# Day66-80 + diff --git a/day66-80-3/README.md b/day66-80-3/README.md new file mode 100644 index 0000000000..e6a5758faa --- /dev/null +++ b/day66-80-3/README.md @@ -0,0 +1,2 @@ +# Day66-80 + diff --git a/day66-80-4/README.md b/day66-80-4/README.md new file mode 100644 index 0000000000..e6a5758faa --- /dev/null +++ b/day66-80-4/README.md @@ -0,0 +1,2 @@ +# Day66-80 + diff --git a/day66-80-5/README.md b/day66-80-5/README.md new file mode 100644 index 0000000000..e6a5758faa --- /dev/null +++ b/day66-80-5/README.md @@ -0,0 +1,2 @@ +# Day66-80 + diff --git a/day66-80-6/README.md b/day66-80-6/README.md new file mode 100644 index 0000000000..e6a5758faa --- /dev/null +++ b/day66-80-6/README.md @@ -0,0 +1,2 @@ +# Day66-80 + diff --git a/day66-80-7/README.md b/day66-80-7/README.md new file mode 100644 index 0000000000..e6a5758faa --- /dev/null +++ b/day66-80-7/README.md @@ -0,0 +1,2 @@ +# Day66-80 + diff --git a/day66-80-8/README.md b/day66-80-8/README.md new file mode 100644 index 0000000000..e6a5758faa --- /dev/null +++ b/day66-80-8/README.md @@ -0,0 +1,2 @@ +# Day66-80 + diff --git a/day66-80-9/README.md b/day66-80-9/README.md new file mode 100644 index 0000000000..e6a5758faa --- /dev/null +++ b/day66-80-9/README.md @@ -0,0 +1,2 @@ +# Day66-80 + diff --git a/day66-80/README.md b/day66-80/README.md new file mode 100644 index 0000000000..e6a5758faa --- /dev/null +++ b/day66-80/README.md @@ -0,0 +1,2 @@ +# Day66-80 + diff --git a/day81-90-1/README.md b/day81-90-1/README.md new file mode 100644 index 0000000000..9830dd998e --- /dev/null +++ b/day81-90-1/README.md @@ -0,0 +1,2 @@ +# Day81-90 + diff --git a/day81-90-10/README.md b/day81-90-10/README.md new file mode 100644 index 0000000000..9830dd998e --- /dev/null +++ b/day81-90-10/README.md @@ -0,0 +1,2 @@ +# Day81-90 + diff --git a/day81-90-2/README.md b/day81-90-2/README.md new file mode 100644 index 0000000000..9830dd998e --- /dev/null +++ b/day81-90-2/README.md @@ -0,0 +1,2 @@ +# Day81-90 + diff --git a/day81-90-3/README.md b/day81-90-3/README.md new file mode 100644 index 0000000000..9830dd998e --- /dev/null +++ b/day81-90-3/README.md @@ -0,0 +1,2 @@ +# Day81-90 + diff --git a/day81-90-4/README.md b/day81-90-4/README.md new file mode 100644 index 0000000000..9830dd998e --- /dev/null +++ b/day81-90-4/README.md @@ -0,0 +1,2 @@ +# Day81-90 + diff --git a/day81-90-5/README.md b/day81-90-5/README.md new file mode 100644 index 0000000000..9830dd998e --- /dev/null +++ b/day81-90-5/README.md @@ -0,0 +1,2 @@ +# Day81-90 + diff --git a/day81-90-6/README.md b/day81-90-6/README.md new file mode 100644 index 0000000000..9830dd998e --- /dev/null +++ b/day81-90-6/README.md @@ -0,0 +1,2 @@ +# Day81-90 + diff --git a/day81-90-7/README.md b/day81-90-7/README.md new file mode 100644 index 0000000000..9830dd998e --- /dev/null +++ b/day81-90-7/README.md @@ -0,0 +1,2 @@ +# Day81-90 + diff --git a/day81-90-8/README.md b/day81-90-8/README.md new file mode 100644 index 0000000000..9830dd998e --- /dev/null +++ b/day81-90-8/README.md @@ -0,0 +1,2 @@ +# Day81-90 + diff --git a/day81-90-9/README.md b/day81-90-9/README.md new file mode 100644 index 0000000000..9830dd998e --- /dev/null +++ b/day81-90-9/README.md @@ -0,0 +1,2 @@ +# Day81-90 + diff --git a/day81-90/README.md b/day81-90/README.md new file mode 100644 index 0000000000..9830dd998e --- /dev/null +++ b/day81-90/README.md @@ -0,0 +1,2 @@ +# Day81-90 + diff --git a/day91-100-1/README.md b/day91-100-1/README.md new file mode 100644 index 0000000000..07d5ec8322 --- /dev/null +++ b/day91-100-1/README.md @@ -0,0 +1,2 @@ +# Day91-100 + diff --git a/day91-100-2/README.md b/day91-100-2/README.md new file mode 100644 index 0000000000..07d5ec8322 --- /dev/null +++ b/day91-100-2/README.md @@ -0,0 +1,2 @@ +# Day91-100 + diff --git a/day91-100-3/README.md b/day91-100-3/README.md new file mode 100644 index 0000000000..07d5ec8322 --- /dev/null +++ b/day91-100-3/README.md @@ -0,0 +1,2 @@ +# Day91-100 + diff --git a/day91-100-4/README.md b/day91-100-4/README.md new file mode 100644 index 0000000000..07d5ec8322 --- /dev/null +++ b/day91-100-4/README.md @@ -0,0 +1,2 @@ +# Day91-100 + diff --git a/day91-100-5/README.md b/day91-100-5/README.md new file mode 100644 index 0000000000..07d5ec8322 --- /dev/null +++ b/day91-100-5/README.md @@ -0,0 +1,2 @@ +# Day91-100 + diff --git a/day91-100-6/README.md b/day91-100-6/README.md new file mode 100644 index 0000000000..07d5ec8322 --- /dev/null +++ b/day91-100-6/README.md @@ -0,0 +1,2 @@ +# Day91-100 + diff --git a/day91-100-7/README.md b/day91-100-7/README.md new file mode 100644 index 0000000000..07d5ec8322 --- /dev/null +++ b/day91-100-7/README.md @@ -0,0 +1,2 @@ +# Day91-100 + diff --git a/day91-100-8/README.md b/day91-100-8/README.md new file mode 100644 index 0000000000..07d5ec8322 --- /dev/null +++ b/day91-100-8/README.md @@ -0,0 +1,2 @@ +# Day91-100 + diff --git a/day91-100-9/README.md b/day91-100-9/README.md new file mode 100644 index 0000000000..07d5ec8322 --- /dev/null +++ b/day91-100-9/README.md @@ -0,0 +1,2 @@ +# Day91-100 + diff --git a/day91-100/README.md b/day91-100/README.md new file mode 100644 index 0000000000..07d5ec8322 --- /dev/null +++ b/day91-100/README.md @@ -0,0 +1,2 @@ +# Day91-100 + diff --git a/fan-wai-pian-1/README.md b/fan-wai-pian-1/README.md new file mode 100644 index 0000000000..c4ca50cb2e --- /dev/null +++ b/fan-wai-pian-1/README.md @@ -0,0 +1,2 @@ +# 番外篇 + diff --git a/fan-wai-pian-10/README.md b/fan-wai-pian-10/README.md new file mode 100644 index 0000000000..c4ca50cb2e --- /dev/null +++ b/fan-wai-pian-10/README.md @@ -0,0 +1,2 @@ +# 番外篇 + diff --git a/fan-wai-pian-11/README.md b/fan-wai-pian-11/README.md new file mode 100644 index 0000000000..c4ca50cb2e --- /dev/null +++ b/fan-wai-pian-11/README.md @@ -0,0 +1,2 @@ +# 番外篇 + diff --git a/fan-wai-pian-12/README.md b/fan-wai-pian-12/README.md new file mode 100644 index 0000000000..c4ca50cb2e --- /dev/null +++ b/fan-wai-pian-12/README.md @@ -0,0 +1,2 @@ +# 番外篇 + diff --git a/fan-wai-pian-13/README.md b/fan-wai-pian-13/README.md new file mode 100644 index 0000000000..c4ca50cb2e --- /dev/null +++ b/fan-wai-pian-13/README.md @@ -0,0 +1,2 @@ +# 番外篇 + diff --git a/fan-wai-pian-14/README.md b/fan-wai-pian-14/README.md new file mode 100644 index 0000000000..c4ca50cb2e --- /dev/null +++ b/fan-wai-pian-14/README.md @@ -0,0 +1,2 @@ +# 番外篇 + diff --git a/fan-wai-pian-15/README.md b/fan-wai-pian-15/README.md new file mode 100644 index 0000000000..c4ca50cb2e --- /dev/null +++ b/fan-wai-pian-15/README.md @@ -0,0 +1,2 @@ +# 番外篇 + diff --git a/fan-wai-pian-2/README.md b/fan-wai-pian-2/README.md new file mode 100644 index 0000000000..c4ca50cb2e --- /dev/null +++ b/fan-wai-pian-2/README.md @@ -0,0 +1,2 @@ +# 番外篇 + diff --git a/fan-wai-pian-3/README.md b/fan-wai-pian-3/README.md new file mode 100644 index 0000000000..c4ca50cb2e --- /dev/null +++ b/fan-wai-pian-3/README.md @@ -0,0 +1,2 @@ +# 番外篇 + diff --git a/fan-wai-pian-4/README.md b/fan-wai-pian-4/README.md new file mode 100644 index 0000000000..c4ca50cb2e --- /dev/null +++ b/fan-wai-pian-4/README.md @@ -0,0 +1,2 @@ +# 番外篇 + diff --git a/fan-wai-pian-5/README.md b/fan-wai-pian-5/README.md new file mode 100644 index 0000000000..c4ca50cb2e --- /dev/null +++ b/fan-wai-pian-5/README.md @@ -0,0 +1,2 @@ +# 番外篇 + diff --git a/fan-wai-pian-6/README.md b/fan-wai-pian-6/README.md new file mode 100644 index 0000000000..c4ca50cb2e --- /dev/null +++ b/fan-wai-pian-6/README.md @@ -0,0 +1,2 @@ +# 番外篇 + diff --git a/fan-wai-pian-7/README.md b/fan-wai-pian-7/README.md new file mode 100644 index 0000000000..c4ca50cb2e --- /dev/null +++ b/fan-wai-pian-7/README.md @@ -0,0 +1,2 @@ +# 番外篇 + diff --git a/fan-wai-pian-8/README.md b/fan-wai-pian-8/README.md new file mode 100644 index 0000000000..c4ca50cb2e --- /dev/null +++ b/fan-wai-pian-8/README.md @@ -0,0 +1,2 @@ +# 番外篇 + diff --git a/fan-wai-pian-9/README.md b/fan-wai-pian-9/README.md new file mode 100644 index 0000000000..c4ca50cb2e --- /dev/null +++ b/fan-wai-pian-9/README.md @@ -0,0 +1,2 @@ +# 番外篇 + diff --git a/fan-wai-pian/README.md b/fan-wai-pian/README.md new file mode 100644 index 0000000000..c4ca50cb2e --- /dev/null +++ b/fan-wai-pian/README.md @@ -0,0 +1,2 @@ +# 番外篇 + diff --git a/gong-kai-ke-1/README.md b/gong-kai-ke-1/README.md new file mode 100644 index 0000000000..16d470f983 --- /dev/null +++ b/gong-kai-ke-1/README.md @@ -0,0 +1,2 @@ +# 公开课 + diff --git a/gong-kai-ke-1/wen-dang/README.md b/gong-kai-ke-1/wen-dang/README.md new file mode 100644 index 0000000000..4f03d405a9 --- /dev/null +++ b/gong-kai-ke-1/wen-dang/README.md @@ -0,0 +1,2 @@ +# 文档 + diff --git a/gong-kai-ke-1/wen-dang/di-04-ci-gong-kai-ke-hao-wan-de-python/README.md b/gong-kai-ke-1/wen-dang/di-04-ci-gong-kai-ke-hao-wan-de-python/README.md new file mode 100644 index 0000000000..c42e63375d --- /dev/null +++ b/gong-kai-ke-1/wen-dang/di-04-ci-gong-kai-ke-hao-wan-de-python/README.md @@ -0,0 +1,2 @@ +# 第04次公开课-好玩的Python + diff --git a/gong-kai-ke-2/README.md b/gong-kai-ke-2/README.md new file mode 100644 index 0000000000..16d470f983 --- /dev/null +++ b/gong-kai-ke-2/README.md @@ -0,0 +1,2 @@ +# 公开课 + diff --git a/gong-kai-ke-2/wen-dang/README.md b/gong-kai-ke-2/wen-dang/README.md new file mode 100644 index 0000000000..4f03d405a9 --- /dev/null +++ b/gong-kai-ke-2/wen-dang/README.md @@ -0,0 +1,2 @@ +# 文档 + diff --git a/gong-kai-ke-2/wen-dang/di-05-ci-gong-kai-ke-suan-fa-ru-men-xi-lie-1-zhou-er-fu-shi/README.md b/gong-kai-ke-2/wen-dang/di-05-ci-gong-kai-ke-suan-fa-ru-men-xi-lie-1-zhou-er-fu-shi/README.md new file mode 100644 index 0000000000..7fcd814bc4 --- /dev/null +++ b/gong-kai-ke-2/wen-dang/di-05-ci-gong-kai-ke-suan-fa-ru-men-xi-lie-1-zhou-er-fu-shi/README.md @@ -0,0 +1,2 @@ +# 第05次公开课-算法入门系列1-周而复始 + diff --git a/gong-kai-ke-3/README.md b/gong-kai-ke-3/README.md new file mode 100644 index 0000000000..16d470f983 --- /dev/null +++ b/gong-kai-ke-3/README.md @@ -0,0 +1,2 @@ +# 公开课 + diff --git a/gong-kai-ke-3/wen-dang/README.md b/gong-kai-ke-3/wen-dang/README.md new file mode 100644 index 0000000000..4f03d405a9 --- /dev/null +++ b/gong-kai-ke-3/wen-dang/README.md @@ -0,0 +1,2 @@ +# 文档 + diff --git a/gong-kai-ke-3/wen-dang/di-06-ci-gong-kai-ke-suan-fa-ru-men-xi-lie-2-zai-shui-yi-fang/README.md b/gong-kai-ke-3/wen-dang/di-06-ci-gong-kai-ke-suan-fa-ru-men-xi-lie-2-zai-shui-yi-fang/README.md new file mode 100644 index 0000000000..64968d20f6 --- /dev/null +++ b/gong-kai-ke-3/wen-dang/di-06-ci-gong-kai-ke-suan-fa-ru-men-xi-lie-2-zai-shui-yi-fang/README.md @@ -0,0 +1,2 @@ +# 第06次公开课-算法入门系列2-在水一方 + diff --git a/gong-kai-ke/README.md b/gong-kai-ke/README.md new file mode 100644 index 0000000000..16d470f983 --- /dev/null +++ b/gong-kai-ke/README.md @@ -0,0 +1,2 @@ +# 公开课 + diff --git a/gong-kai-ke/wen-dang/README.md b/gong-kai-ke/wen-dang/README.md new file mode 100644 index 0000000000..4f03d405a9 --- /dev/null +++ b/gong-kai-ke/wen-dang/README.md @@ -0,0 +1,2 @@ +# 文档 + diff --git a/gong-kai-ke/wen-dang/nian-xin-50w+-de-python-cheng-xu-yuan-ru-he-xie-dai-ma/README.md b/gong-kai-ke/wen-dang/nian-xin-50w+-de-python-cheng-xu-yuan-ru-he-xie-dai-ma/README.md new file mode 100644 index 0000000000..0ad721ed80 --- /dev/null +++ b/gong-kai-ke/wen-dang/nian-xin-50w+-de-python-cheng-xu-yuan-ru-he-xie-dai-ma/README.md @@ -0,0 +1,2 @@ +# 年薪50W+的Python程序员如何写代码 + From cd93eedfa8b96b771c2898b462811dbaee5812df Mon Sep 17 00:00:00 2001 From: 1337428173 <1337428173@qq.com> Date: Wed, 3 Apr 2024 09:25:13 +0000 Subject: [PATCH 2/3] GITBOOK-1: No subject --- ...55\350\250\200\350\277\233\351\230\266.md" | 1376 ---------- ...15\347\253\257\346\246\202\350\277\260.md" | 912 ------- ...5\222\214MySQL\346\246\202\350\277\260.md" | 402 ++- ...53\351\200\237\344\270\212\346\211\213.md" | 339 --- ...61\345\205\245\346\250\241\345\236\213.md" | 681 ----- ...25\345\205\203\346\265\213\350\257\225.md" | 4 - ...71\347\233\256\344\270\212\347\272\277.md" | 4 - ...47\350\203\275\344\274\230\345\214\226.md" | 312 --- ...47\350\203\275\350\260\203\344\274\230.md" | 883 ------- README.md | 815 +++--- SUMMARY.md | 246 +- day01-15-1/README.md | 2 - day01-15-10/README.md | 2 - day01-15-11/README.md | 2 - day01-15-12/README.md | 2 - day01-15-13/README.md | 2 - day01-15-14/README.md | 2 - day01-15-2/README.md | 2 - day01-15-3/README.md | 2 - day01-15-4/README.md | 2 - day01-15-5/README.md | 2 - day01-15-6/README.md | 2 - day01-15-7/README.md | 2 - day01-15-8/README.md | 2 - day01-15-9/README.md | 2 - .../02.-yu-yan-yuan-su.md | 0 .../03.-fen-zhi-jie-gou.md | 19 +- .../04.-xun-huan-jie-gou.md | 0 .../05.-gou-zao-cheng-xu-luo-ji.md | 0 .../06.-han-shu-he-mo-kuai-de-shi-yong.md | 35 +- ...i-fu-chuan-he-chang-yong-shu-ju-jie-gou.md | 54 +- ...-mian-xiang-dui-xiang-bian-cheng-ji-chu.md | 36 +- .../09.-mian-xiang-dui-xiang-jin-jie.md | 33 +- ...-xing-yong-hu-jie-mian-he-you-xi-kai-fa.md | 0 .../11.-wen-jian-he-yi-chang.md | 40 +- ...12.-zi-fu-chuan-he-zheng-ze-biao-da-shi.md | 122 +- .../13.-jin-cheng-he-xian-cheng.md | 28 +- ...eng-ru-men-he-wang-luo-ying-yong-kai-fa.md | 62 +- ...5.-tu-xiang-he-ban-gong-wen-dang-chu-li.md | 136 +- day16-20/README.md | 2 - day21-30/README.md | 2 - day36-40-1/README.md | 2 - day36-40-2/README.md | 2 - day36-40-3/README.md | 2 - day36-40-4/README.md | 2 - day36-40-5/README.md | 2 - .../37.sql-xiang-jie.md | 0 .../38.-shen-ru-mysql.md | 0 ....python-cheng-xu-jie-ru-mysql-shu-ju-ku.md | 0 .../40.-da-shu-ju-ping-tai-he-hivesql.md | 0 .../nosql-shu-ju-ku-ru-men.md | 368 ++- day41-55-1/2130.web-qian-duan-gai-shu.md | 875 +++++++ day41-55-10/README.md | 2 - day41-55-11/README.md | 2 - day41-55-12/README.md | 2 - day41-55-13/README.md | 2 - day41-55-14/README.md | 2 - day41-55-2/41.django-kuai-su-shang-shou.md | 333 +++ day41-55-2/42.-shen-ru-mo-xing.md | 647 +++++ .../44.cookie-he-session.md | 79 +- .../45.-zhi-zuo-bao-biao.md | 14 +- .../46.-ri-zhi-he-tiao-shi-gong-ju-lan.md | 113 +- .../47.-zhong-jian-jian-de-ying-yong.md | 29 +- .../48.-qian-hou-duan-fen-li-kai-fa-ru-men.md | 0 .../49.restful-jia-gou-he-drf-ru-men.md | 70 +- .../50.restful-jia-gou-he-drf-jin-jie.md | 0 .../51.-shi-yong-huan-cun.md | 26 +- .../52.-jie-ru-san-fang-ping-tai.md | 54 +- .../53.-yi-bu-ren-wu-he-ding-shi-ren-wu.md | 0 day41-55-2/54.-dan-yuan-ce-shi.md | 3 + day41-55-2/55.-xiang-mu-shang-xian.md | 3 + day41-55-3/README.md | 2 - day41-55-4/README.md | 2 - day41-55-5/README.md | 2 - day41-55-6/README.md | 2 - day41-55-7/README.md | 2 - day41-55-8/README.md | 2 - day41-55-9/README.md | 2 - day41-55/1620.python-yu-yan-jin-jie.md | 1348 ++++++++++ day61-65-1/README.md | 2 - day61-65-2/README.md | 2 - day61-65-3/README.md | 2 - day61-65-4/README.md | 2 - day61-65-5/README.md | 2 - day61-65-6/README.md | 2 - day61-65-7/README.md | 2 - day61-65-8/README.md | 2 - ....-yong-python-huo-qu-wang-luo-zi-yuan-1.md | 0 .../62.-yong-python-jie-xi-html-ye-mian-2.md | 0 ...n-cheng-zai-pa-chong-zhong-de-ying-yong.md | 0 ...63.python-zhong-de-bing-fa-bian-cheng-1.md | 0 ...63.python-zhong-de-bing-fa-bian-cheng-2.md | 0 ...63.python-zhong-de-bing-fa-bian-cheng-3.md | 0 ...enium-zhua-qu-wang-ye-dong-tai-nei-rong.md | 0 .../65.-pa-chong-kuang-jia-scrapy-jian-jie.md | 0 day66-80-1/README.md | 2 - day66-80-10/README.md | 2 - day66-80-11/README.md | 2 - day66-80-12/README.md | 2 - day66-80-13/README.md | 2 - day66-80-14/README.md | 2 - day66-80-2/README.md | 2 - day66-80-3/README.md | 2 - day66-80-4/README.md | 2 - day66-80-5/README.md | 2 - day66-80-6/README.md | 2 - day66-80-7/README.md | 2 - day66-80-8/README.md | 2 - day66-80-9/README.md | 2 - .../67.-huan-jing-zhun-bei.md | 149 +- .../68.numpy-de-ying-yong-1.md | 50 +- .../69.numpy-de-ying-yong-2.md | 37 +- .../70.numpy-de-ying-yong-3.md | 116 +- .../71.numpy-de-ying-yong-4.md | 246 +- .../72.-shen-ru-qian-chu-pandas1.md | 60 +- .../73.-shen-ru-qian-chu-pandas2.md | 0 .../74.-shen-ru-qian-chu-pandas3.md | 0 .../75.-shen-ru-qian-chu-pandas4.md | 27 +- .../76.-shen-ru-qian-chu-pandas5.md | 49 +- .../77.-shen-ru-qian-chu-pandas6.md | 25 +- .../78.-shu-ju-ke-shi-hua-1.md | 54 +- .../79.-shu-ju-ke-shi-hua-2.md | 24 +- .../80.-shu-ju-ke-shi-hua-3.md | 46 +- day81-90-1/README.md | 2 - day81-90-10/README.md | 2 - day81-90-2/README.md | 2 - day81-90-3/README.md | 2 - day81-90-4/README.md | 2 - day81-90-5/README.md | 2 - day81-90-6/README.md | 2 - day81-90-7/README.md | 2 - day81-90-8/README.md | 2 - day81-90-9/README.md | 2 - .../82.k-zui-jin-lin-fen-lei.md | 0 .../83.-jue-ce-shu.md | 0 .../83.-tui-jian-xi-tong-shi-zhan-1.md | 0 .../84.-bei-ye-si-fen-lei.md | 0 .../85.-zhi-chi-xiang-liang-ji.md | 0 .../86.k-jun-zhi-ju-lei.md | 0 .../87.-hui-gui-fen-xi.md | 0 .../88.-shen-du-xue-xi-ru-men.md | 0 .../89.pytorch-gai-shu.md | 0 .../90.pytorch-shi-zhan.md | 0 day91-100-1/README.md | 2 - day91-100-2/README.md | 2 - day91-100-3/README.md | 2 - day91-100-4/README.md | 2 - day91-100-5/README.md | 2 - day91-100-6/README.md | 2 - day91-100-7/README.md | 2 - day91-100-8/README.md | 2 - day91-100-9/README.md | 2 - ...-mu-kai-fa-de-wen-ti-he-jie-jue-fang-an.md | 524 ++-- .../92.docker-rong-qi-ji-shu-xiang-jie.md | 543 ++-- day91-100/93.mysql-xing-neng-you-hua.md | 287 +++ .../94.-wang-luo-api-jie-kou-she-ji.md | 0 ...hi-yong-django-kai-fa-shang-ye-xiang-mu.md | 2222 ++++++++--------- ...-ruan-jian-ce-shi-he-zi-dong-hua-ce-shi.md | 95 +- ...-shang-wang-zhan-ji-shu-yao-dian-pou-xi.md | 987 ++++---- ...bu-shu-shang-xian-he-xing-neng-tiao-you.md | 852 +++++++ .../99.-mian-shi-zhong-de-gong-gong-wen-ti.md | 0 ...50\350\200\214\345\244\215\345\247\213.md" | 248 +- ...50\346\260\264\344\270\200\346\226\271.md" | 26 +- ...64\346\226\260\346\227\245\345\277\227.md" | 73 +- ...00\344\275\263\347\277\273\350\257\221.md" | 62 +- ...04\350\241\250\350\276\276\345\274\217.md" | 5 +- 166 files changed, 8385 insertions(+), 9071 deletions(-) delete mode 100755 "Day16-20/16-20.Python\350\257\255\350\250\200\350\277\233\351\230\266.md" delete mode 100755 "Day21-30/21-30.Web\345\211\215\347\253\257\346\246\202\350\277\260.md" delete mode 100755 "Day41-55/41.Django\345\277\253\351\200\237\344\270\212\346\211\213.md" delete mode 100755 "Day41-55/42.\346\267\261\345\205\245\346\250\241\345\236\213.md" delete mode 100755 "Day41-55/54.\345\215\225\345\205\203\346\265\213\350\257\225.md" delete mode 100755 "Day41-55/55.\351\241\271\347\233\256\344\270\212\347\272\277.md" delete mode 100755 "Day91-100/93.MySQL\346\200\247\350\203\275\344\274\230\345\214\226.md" delete mode 100755 "Day91-100/98.\351\241\271\347\233\256\351\203\250\347\275\262\344\270\212\347\272\277\345\222\214\346\200\247\350\203\275\350\260\203\344\274\230.md" delete mode 100644 day01-15-1/README.md delete mode 100644 day01-15-10/README.md delete mode 100644 day01-15-11/README.md delete mode 100644 day01-15-12/README.md delete mode 100644 day01-15-13/README.md delete mode 100644 day01-15-14/README.md delete mode 100644 day01-15-2/README.md delete mode 100644 day01-15-3/README.md delete mode 100644 day01-15-4/README.md delete mode 100644 day01-15-5/README.md delete mode 100644 day01-15-6/README.md delete mode 100644 day01-15-7/README.md delete mode 100644 day01-15-8/README.md delete mode 100644 day01-15-9/README.md rename "Day01-15/02.\350\257\255\350\250\200\345\205\203\347\264\240.md" => day01-15/02.-yu-yan-yuan-su.md (100%) mode change 100755 => 100644 rename "Day01-15/03.\345\210\206\346\224\257\347\273\223\346\236\204.md" => day01-15/03.-fen-zhi-jie-gou.md (90%) mode change 100755 => 100644 rename "Day01-15/04.\345\276\252\347\216\257\347\273\223\346\236\204.md" => day01-15/04.-xun-huan-jie-gou.md (100%) mode change 100755 => 100644 rename "Day01-15/05.\346\236\204\351\200\240\347\250\213\345\272\217\351\200\273\350\276\221.md" => day01-15/05.-gou-zao-cheng-xu-luo-ji.md (100%) mode change 100755 => 100644 rename "Day01-15/06.\345\207\275\346\225\260\345\222\214\346\250\241\345\235\227\347\232\204\344\275\277\347\224\250.md" => day01-15/06.-han-shu-he-mo-kuai-de-shi-yong.md (85%) mode change 100755 => 100644 rename "Day01-15/07.\345\255\227\347\254\246\344\270\262\345\222\214\345\270\270\347\224\250\346\225\260\346\215\256\347\273\223\346\236\204.md" => day01-15/07.-zi-fu-chuan-he-chang-yong-shu-ju-jie-gou.md (91%) mode change 100755 => 100644 rename "Day01-15/08.\351\235\242\345\220\221\345\257\271\350\261\241\347\274\226\347\250\213\345\237\272\347\241\200.md" => day01-15/08.-mian-xiang-dui-xiang-bian-cheng-ji-chu.md (66%) mode change 100755 => 100644 rename "Day01-15/09.\351\235\242\345\220\221\345\257\271\350\261\241\350\277\233\351\230\266.md" => day01-15/09.-mian-xiang-dui-xiang-jin-jie.md (96%) mode change 100755 => 100644 rename "Day01-15/10.\345\233\276\345\275\242\347\224\250\346\210\267\347\225\214\351\235\242\345\222\214\346\270\270\346\210\217\345\274\200\345\217\221.md" => day01-15/10.-tu-xing-yong-hu-jie-mian-he-you-xi-kai-fa.md (100%) mode change 100755 => 100644 rename "Day01-15/11.\346\226\207\344\273\266\345\222\214\345\274\202\345\270\270.md" => day01-15/11.-wen-jian-he-yi-chang.md (90%) mode change 100755 => 100644 rename "Day01-15/12.\345\255\227\347\254\246\344\270\262\345\222\214\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" => day01-15/12.-zi-fu-chuan-he-zheng-ze-biao-da-shi.md (58%) mode change 100755 => 100644 rename "Day01-15/13.\350\277\233\347\250\213\345\222\214\347\272\277\347\250\213.md" => day01-15/13.-jin-cheng-he-xian-cheng.md (96%) mode change 100755 => 100644 rename "Day01-15/14.\347\275\221\347\273\234\347\274\226\347\250\213\345\205\245\351\227\250\345\222\214\347\275\221\347\273\234\345\272\224\347\224\250\345\274\200\345\217\221.md" => day01-15/14.-wang-luo-bian-cheng-ru-men-he-wang-luo-ying-yong-kai-fa.md (86%) mode change 100755 => 100644 rename "Day01-15/15.\345\233\276\345\203\217\345\222\214\345\212\236\345\205\254\346\226\207\346\241\243\345\244\204\347\220\206.md" => day01-15/15.-tu-xiang-he-ban-gong-wen-dang-chu-li.md (52%) mode change 100755 => 100644 delete mode 100644 day16-20/README.md delete mode 100644 day21-30/README.md delete mode 100644 day36-40-1/README.md delete mode 100644 day36-40-2/README.md delete mode 100644 day36-40-3/README.md delete mode 100644 day36-40-4/README.md delete mode 100644 day36-40-5/README.md rename "Day36-40/37.SQL\350\257\246\350\247\243.md" => day36-40/37.sql-xiang-jie.md (100%) mode change 100755 => 100644 rename "Day36-40/38.\346\267\261\345\205\245MySQL.md" => day36-40/38.-shen-ru-mysql.md (100%) mode change 100755 => 100644 rename "Day36-40/39.Python\347\250\213\345\272\217\346\216\245\345\205\245MySQL\346\225\260\346\215\256\345\272\223.md" => day36-40/39.python-cheng-xu-jie-ru-mysql-shu-ju-ku.md (100%) mode change 100755 => 100644 rename "Day36-40/40.\345\244\247\346\225\260\346\215\256\345\271\263\345\217\260\345\222\214HiveSQL.md" => day36-40/40.-da-shu-ju-ping-tai-he-hivesql.md (100%) mode change 100755 => 100644 rename "Day36-40/NoSQL\346\225\260\346\215\256\345\272\223\345\205\245\351\227\250.md" => day36-40/nosql-shu-ju-ku-ru-men.md (62%) mode change 100755 => 100644 create mode 100644 day41-55-1/2130.web-qian-duan-gai-shu.md delete mode 100644 day41-55-10/README.md delete mode 100644 day41-55-11/README.md delete mode 100644 day41-55-12/README.md delete mode 100644 day41-55-13/README.md delete mode 100644 day41-55-14/README.md create mode 100644 day41-55-2/41.django-kuai-su-shang-shou.md create mode 100644 day41-55-2/42.-shen-ru-mo-xing.md rename "Day41-55/44.Cookie\345\222\214Session.md" => day41-55-2/44.cookie-he-session.md (85%) mode change 100755 => 100644 rename "Day41-55/45.\345\210\266\344\275\234\346\212\245\350\241\250.md" => day41-55-2/45.-zhi-zuo-bao-biao.md (83%) mode change 100755 => 100644 rename "Day41-55/46.\346\227\245\345\277\227\345\222\214\350\260\203\350\257\225\345\267\245\345\205\267\346\240\217.md" => day41-55-2/46.-ri-zhi-he-tiao-shi-gong-ju-lan.md (85%) mode change 100755 => 100644 rename "Day41-55/47.\344\270\255\351\227\264\344\273\266\347\232\204\345\272\224\347\224\250.md" => day41-55-2/47.-zhong-jian-jian-de-ying-yong.md (91%) mode change 100755 => 100644 rename "Day41-55/48.\345\211\215\345\220\216\347\253\257\345\210\206\347\246\273\345\274\200\345\217\221\345\205\245\351\227\250.md" => day41-55-2/48.-qian-hou-duan-fen-li-kai-fa-ru-men.md (100%) mode change 100755 => 100644 rename "Day41-55/49.RESTful\346\236\266\346\236\204\345\222\214DRF\345\205\245\351\227\250.md" => day41-55-2/49.restful-jia-gou-he-drf-ru-men.md (91%) mode change 100755 => 100644 rename "Day41-55/50.RESTful\346\236\266\346\236\204\345\222\214DRF\350\277\233\351\230\266.md" => day41-55-2/50.restful-jia-gou-he-drf-jin-jie.md (100%) mode change 100755 => 100644 rename "Day41-55/51.\344\275\277\347\224\250\347\274\223\345\255\230.md" => day41-55-2/51.-shi-yong-huan-cun.md (96%) mode change 100755 => 100644 rename "Day41-55/52.\346\216\245\345\205\245\344\270\211\346\226\271\345\271\263\345\217\260.md" => day41-55-2/52.-jie-ru-san-fang-ping-tai.md (82%) mode change 100755 => 100644 rename "Day41-55/53.\345\274\202\346\255\245\344\273\273\345\212\241\345\222\214\345\256\232\346\227\266\344\273\273\345\212\241.md" => day41-55-2/53.-yi-bu-ren-wu-he-ding-shi-ren-wu.md (100%) mode change 100755 => 100644 create mode 100644 day41-55-2/54.-dan-yuan-ce-shi.md create mode 100644 day41-55-2/55.-xiang-mu-shang-xian.md delete mode 100644 day41-55-3/README.md delete mode 100644 day41-55-4/README.md delete mode 100644 day41-55-5/README.md delete mode 100644 day41-55-6/README.md delete mode 100644 day41-55-7/README.md delete mode 100644 day41-55-8/README.md delete mode 100644 day41-55-9/README.md create mode 100644 day41-55/1620.python-yu-yan-jin-jie.md delete mode 100644 day61-65-1/README.md delete mode 100644 day61-65-2/README.md delete mode 100644 day61-65-3/README.md delete mode 100644 day61-65-4/README.md delete mode 100644 day61-65-5/README.md delete mode 100644 day61-65-6/README.md delete mode 100644 day61-65-7/README.md delete mode 100644 day61-65-8/README.md rename "Day61-65/62.\347\224\250Python\350\216\267\345\217\226\347\275\221\347\273\234\350\265\204\346\272\220-1.md" => day61-65/62.-yong-python-huo-qu-wang-luo-zi-yuan-1.md (100%) mode change 100755 => 100644 rename "Day61-65/62.\347\224\250Python\350\247\243\346\236\220HTML\351\241\265\351\235\242-2.md" => day61-65/62.-yong-python-jie-xi-html-ye-mian-2.md (100%) mode change 100755 => 100644 rename "Day61-65/63.\345\271\266\345\217\221\347\274\226\347\250\213\345\234\250\347\210\254\350\231\253\344\270\255\347\232\204\345\272\224\347\224\250.md" => day61-65/63.-bing-fa-bian-cheng-zai-pa-chong-zhong-de-ying-yong.md (100%) mode change 100755 => 100644 rename "Day61-65/63.Python\344\270\255\347\232\204\345\271\266\345\217\221\347\274\226\347\250\213-1.md" => day61-65/63.python-zhong-de-bing-fa-bian-cheng-1.md (100%) mode change 100755 => 100644 rename "Day61-65/63.Python\344\270\255\347\232\204\345\271\266\345\217\221\347\274\226\347\250\213-2.md" => day61-65/63.python-zhong-de-bing-fa-bian-cheng-2.md (100%) mode change 100755 => 100644 rename "Day61-65/63.Python\344\270\255\347\232\204\345\271\266\345\217\221\347\274\226\347\250\213-3.md" => day61-65/63.python-zhong-de-bing-fa-bian-cheng-3.md (100%) mode change 100755 => 100644 rename "Day61-65/64.\344\275\277\347\224\250Selenium\346\212\223\345\217\226\347\275\221\351\241\265\345\212\250\346\200\201\345\206\205\345\256\271.md" => day61-65/64.-shi-yong-selenium-zhua-qu-wang-ye-dong-tai-nei-rong.md (100%) mode change 100755 => 100644 rename "Day61-65/65.\347\210\254\350\231\253\346\241\206\346\236\266Scrapy\347\256\200\344\273\213.md" => day61-65/65.-pa-chong-kuang-jia-scrapy-jian-jie.md (100%) mode change 100755 => 100644 delete mode 100644 day66-80-1/README.md delete mode 100644 day66-80-10/README.md delete mode 100644 day66-80-11/README.md delete mode 100644 day66-80-12/README.md delete mode 100644 day66-80-13/README.md delete mode 100644 day66-80-14/README.md delete mode 100644 day66-80-2/README.md delete mode 100644 day66-80-3/README.md delete mode 100644 day66-80-4/README.md delete mode 100644 day66-80-5/README.md delete mode 100644 day66-80-6/README.md delete mode 100644 day66-80-7/README.md delete mode 100644 day66-80-8/README.md delete mode 100644 day66-80-9/README.md rename "Day66-80/67.\347\216\257\345\242\203\345\207\206\345\244\207.md" => day66-80/67.-huan-jing-zhun-bei.md (64%) mode change 100755 => 100644 rename "Day66-80/68.NumPy\347\232\204\345\272\224\347\224\250-1.md" => day66-80/68.numpy-de-ying-yong-1.md (94%) mode change 100755 => 100644 rename "Day66-80/69.NumPy\347\232\204\345\272\224\347\224\250-2.md" => day66-80/69.numpy-de-ying-yong-2.md (87%) mode change 100755 => 100644 rename "Day66-80/70.NumPy\347\232\204\345\272\224\347\224\250-3.md" => day66-80/70.numpy-de-ying-yong-3.md (82%) rename "Day66-80/71.NumPy\347\232\204\345\272\224\347\224\250-4.md" => day66-80/71.numpy-de-ying-yong-4.md (77%) rename "Day66-80/72.\346\267\261\345\205\245\346\265\205\345\207\272pandas-1.md" => day66-80/72.-shen-ru-qian-chu-pandas1.md (94%) mode change 100755 => 100644 rename "Day66-80/73.\346\267\261\345\205\245\346\265\205\345\207\272pandas-2.md" => day66-80/73.-shen-ru-qian-chu-pandas2.md (100%) mode change 100755 => 100644 rename "Day66-80/74.\346\267\261\345\205\245\346\265\205\345\207\272pandas-3.md" => day66-80/74.-shen-ru-qian-chu-pandas3.md (100%) mode change 100755 => 100644 rename "Day66-80/75.\346\267\261\345\205\245\346\265\205\345\207\272pandas-4.md" => day66-80/75.-shen-ru-qian-chu-pandas4.md (96%) mode change 100755 => 100644 rename "Day66-80/76.\346\267\261\345\205\245\346\265\205\345\207\272pandas-5.md" => day66-80/76.-shen-ru-qian-chu-pandas5.md (86%) mode change 100755 => 100644 rename "Day66-80/77.\346\267\261\345\205\245\346\265\205\345\207\272pandas-6.md" => day66-80/77.-shen-ru-qian-chu-pandas6.md (96%) rename "Day66-80/78.\346\225\260\346\215\256\345\217\257\350\247\206\345\214\226-1.md" => day66-80/78.-shu-ju-ke-shi-hua-1.md (86%) mode change 100755 => 100644 rename "Day66-80/79.\346\225\260\346\215\256\345\217\257\350\247\206\345\214\226-2.md" => day66-80/79.-shu-ju-ke-shi-hua-2.md (94%) rename "Day66-80/80.\346\225\260\346\215\256\345\217\257\350\247\206\345\214\226-3.md" => day66-80/80.-shu-ju-ke-shi-hua-3.md (86%) mode change 100755 => 100644 delete mode 100644 day81-90-1/README.md delete mode 100644 day81-90-10/README.md delete mode 100644 day81-90-2/README.md delete mode 100644 day81-90-3/README.md delete mode 100644 day81-90-4/README.md delete mode 100644 day81-90-5/README.md delete mode 100644 day81-90-6/README.md delete mode 100644 day81-90-7/README.md delete mode 100644 day81-90-8/README.md delete mode 100644 day81-90-9/README.md rename "Day81-90/82.k\346\234\200\350\277\221\351\202\273\345\210\206\347\261\273.md" => day81-90/82.k-zui-jin-lin-fen-lei.md (100%) mode change 100755 => 100644 rename "Day81-90/83.\345\206\263\347\255\226\346\240\221.md" => day81-90/83.-jue-ce-shu.md (100%) mode change 100755 => 100644 rename "Day81-90/83.\346\216\250\350\215\220\347\263\273\347\273\237\345\256\236\346\210\230-1.md" => day81-90/83.-tui-jian-xi-tong-shi-zhan-1.md (100%) mode change 100755 => 100644 rename "Day81-90/84.\350\264\235\345\217\266\346\226\257\345\210\206\347\261\273.md" => day81-90/84.-bei-ye-si-fen-lei.md (100%) mode change 100755 => 100644 rename "Day81-90/85.\346\224\257\346\214\201\345\220\221\351\207\217\346\234\272.md" => day81-90/85.-zhi-chi-xiang-liang-ji.md (100%) mode change 100755 => 100644 rename "Day81-90/86.K-\345\235\207\345\200\274\350\201\232\347\261\273.md" => day81-90/86.k-jun-zhi-ju-lei.md (100%) mode change 100755 => 100644 rename "Day81-90/87.\345\233\236\345\275\222\345\210\206\346\236\220.md" => day81-90/87.-hui-gui-fen-xi.md (100%) mode change 100755 => 100644 rename "Day81-90/88.\346\267\261\345\272\246\345\255\246\344\271\240\345\205\245\351\227\250.md" => day81-90/88.-shen-du-xue-xi-ru-men.md (100%) mode change 100755 => 100644 rename "Day81-90/89.PyTorch\346\246\202\350\277\260.md" => day81-90/89.pytorch-gai-shu.md (100%) mode change 100755 => 100644 rename "Day81-90/90.PyTorch\345\256\236\346\210\230.md" => day81-90/90.pytorch-shi-zhan.md (100%) mode change 100755 => 100644 delete mode 100644 day91-100-1/README.md delete mode 100644 day91-100-2/README.md delete mode 100644 day91-100-3/README.md delete mode 100644 day91-100-4/README.md delete mode 100644 day91-100-5/README.md delete mode 100644 day91-100-6/README.md delete mode 100644 day91-100-7/README.md delete mode 100644 day91-100-8/README.md delete mode 100644 day91-100-9/README.md rename "Day91-100/91.\345\233\242\351\230\237\351\241\271\347\233\256\345\274\200\345\217\221\347\232\204\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263\346\226\271\346\241\210.md" => day91-100/91.-tuan-dui-xiang-mu-kai-fa-de-wen-ti-he-jie-jue-fang-an.md (55%) mode change 100755 => 100644 rename "Day91-100/92.Docker\345\256\271\345\231\250\346\212\200\346\234\257\350\257\246\350\247\243.md" => day91-100/92.docker-rong-qi-ji-shu-xiang-jie.md (67%) mode change 100755 => 100644 create mode 100644 day91-100/93.mysql-xing-neng-you-hua.md rename "Day91-100/94.\347\275\221\347\273\234API\346\216\245\345\217\243\350\256\276\350\256\241.md" => day91-100/94.-wang-luo-api-jie-kou-she-ji.md (100%) mode change 100755 => 100644 rename "Day91-100/95.\344\275\277\347\224\250Django\345\274\200\345\217\221\345\225\206\344\270\232\351\241\271\347\233\256.md" => day91-100/95.-shi-yong-django-kai-fa-shang-ye-xiang-mu.md (50%) mode change 100755 => 100644 rename "Day91-100/96.\350\275\257\344\273\266\346\265\213\350\257\225\345\222\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225.md" => day91-100/96.-ruan-jian-ce-shi-he-zi-dong-hua-ce-shi.md (58%) mode change 100755 => 100644 rename "Day91-100/97.\347\224\265\345\225\206\347\275\221\347\253\231\346\212\200\346\234\257\350\246\201\347\202\271\345\211\226\346\236\220.md" => day91-100/97.-dian-shang-wang-zhan-ji-shu-yao-dian-pou-xi.md (51%) mode change 100755 => 100644 create mode 100644 day91-100/98.-xiang-mu-bu-shu-shang-xian-he-xing-neng-tiao-you.md rename "Day91-100/99.\351\235\242\350\257\225\344\270\255\347\232\204\345\205\254\345\205\261\351\227\256\351\242\230.md" => day91-100/99.-mian-shi-zhong-de-gong-gong-wen-ti.md (100%) mode change 100755 => 100644 diff --git "a/Day16-20/16-20.Python\350\257\255\350\250\200\350\277\233\351\230\266.md" "b/Day16-20/16-20.Python\350\257\255\350\250\200\350\277\233\351\230\266.md" deleted file mode 100755 index 4f1c607873..0000000000 --- "a/Day16-20/16-20.Python\350\257\255\350\250\200\350\277\233\351\230\266.md" +++ /dev/null @@ -1,1376 +0,0 @@ -## Python语言进阶 - -### 重要知识点 - -- 生成式(推导式)的用法 - - ```Python - prices = { - 'AAPL': 191.88, - 'GOOG': 1186.96, - 'IBM': 149.24, - 'ORCL': 48.44, - 'ACN': 166.89, - 'FB': 208.09, - 'SYMC': 21.29 - } - # 用股票价格大于100元的股票构造一个新的字典 - prices2 = {key: value for key, value in prices.items() if value > 100} - print(prices2) - ``` - - > 说明:生成式(推导式)可以用来生成列表、集合和字典。 - -- 嵌套的列表的坑 - - ```Python - names = ['关羽', '张飞', '赵云', '马超', '黄忠'] - courses = ['语文', '数学', '英语'] - # 录入五个学生三门课程的成绩 - # 错误 - 参考http://pythontutor.com/visualize.html#mode=edit - # scores = [[None] * len(courses)] * len(names) - scores = [[None] * len(courses) for _ in range(len(names))] - for row, name in enumerate(names): - for col, course in enumerate(courses): - scores[row][col] = float(input(f'请输入{name}的{course}成绩: ')) - print(scores) - ``` - - [Python Tutor](http://pythontutor.com/) - VISUALIZE CODE AND GET LIVE HELP - -- `heapq`模块(堆排序) - - ```Python - """ - 从列表中找出最大的或最小的N个元素 - 堆结构(大根堆/小根堆) - """ - import heapq - - list1 = [34, 25, 12, 99, 87, 63, 58, 78, 88, 92] - list2 = [ - {'name': 'IBM', 'shares': 100, 'price': 91.1}, - {'name': 'AAPL', 'shares': 50, 'price': 543.22}, - {'name': 'FB', 'shares': 200, 'price': 21.09}, - {'name': 'HPQ', 'shares': 35, 'price': 31.75}, - {'name': 'YHOO', 'shares': 45, 'price': 16.35}, - {'name': 'ACME', 'shares': 75, 'price': 115.65} - ] - print(heapq.nlargest(3, list1)) - print(heapq.nsmallest(3, list1)) - print(heapq.nlargest(2, list2, key=lambda x: x['price'])) - print(heapq.nlargest(2, list2, key=lambda x: x['shares'])) - ``` - -- `itertools`模块 - - ```Python - """ - 迭代工具模块 - """ - import itertools - - # 产生ABCD的全排列 - itertools.permutations('ABCD') - # 产生ABCDE的五选三组合 - itertools.combinations('ABCDE', 3) - # 产生ABCD和123的笛卡尔积 - itertools.product('ABCD', '123') - # 产生ABC的无限循环序列 - itertools.cycle(('A', 'B', 'C')) - ``` - -- `collections`模块 - - 常用的工具类: - - - `namedtuple`:命令元组,它是一个类工厂,接受类型的名称和属性列表来创建一个类。 - - `deque`:双端队列,是列表的替代实现。Python中的列表底层是基于数组来实现的,而deque底层是双向链表,因此当你需要在头尾添加和删除元素时,deque会表现出更好的性能,渐近时间复杂度为$O(1)$。 - - `Counter`:`dict`的子类,键是元素,值是元素的计数,它的`most_common()`方法可以帮助我们获取出现频率最高的元素。`Counter`和`dict`的继承关系我认为是值得商榷的,按照CARP原则,`Counter`跟`dict`的关系应该设计为关联关系更为合理。 - - `OrderedDict`:`dict`的子类,它记录了键值对插入的顺序,看起来既有字典的行为,也有链表的行为。 - - `defaultdict`:类似于字典类型,但是可以通过默认的工厂函数来获得键对应的默认值,相比字典中的`setdefault()`方法,这种做法更加高效。 - - ```Python - """ - 找出序列中出现次数最多的元素 - """ - from collections import Counter - - words = [ - 'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes', - 'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', - 'the', 'eyes', "don't", 'look', 'around', 'the', 'eyes', - 'look', 'into', 'my', 'eyes', "you're", 'under' - ] - counter = Counter(words) - print(counter.most_common(3)) - ``` - -### 数据结构和算法 - -- 算法:解决问题的方法和步骤 - -- 评价算法的好坏:渐近时间复杂度和渐近空间复杂度。 - -- 渐近时间复杂度的大O标记: - - - 常量时间复杂度 - 布隆过滤器 / 哈希存储 - - - 对数时间复杂度 - 折半查找(二分查找) - - - 线性时间复杂度 - 顺序查找 / 计数排序 - - - 对数线性时间复杂度 - 高级排序算法(归并排序、快速排序) - - - 平方时间复杂度 - 简单排序算法(选择排序、插入排序、冒泡排序) - - - 立方时间复杂度 - Floyd算法 / 矩阵乘法运算 - - - 几何级数时间复杂度 - 汉诺塔 - - - 阶乘时间复杂度 - 旅行经销商问题 - NPC - - ![](./res/algorithm_complexity_1.png) - - ![](./res/algorithm_complexity_2.png) - -- 排序算法(选择、冒泡和归并)和查找算法(顺序和折半) - - ```Python - def select_sort(items, comp=lambda x, y: x < y): - """简单选择排序""" - items = items[:] - for i in range(len(items) - 1): - min_index = i - for j in range(i + 1, len(items)): - if comp(items[j], items[min_index]): - min_index = j - items[i], items[min_index] = items[min_index], items[i] - return items - ``` - - ```Python - def bubble_sort(items, comp=lambda x, y: x > y): - """冒泡排序""" - items = items[:] - for i in range(len(items) - 1): - swapped = False - for j in range(len(items) - 1 - i): - if comp(items[j], items[j + 1]): - items[j], items[j + 1] = items[j + 1], items[j] - swapped = True - if not swapped: - break - return items - ``` - - ```Python - def bubble_sort(items, comp=lambda x, y: x > y): - """搅拌排序(冒泡排序升级版)""" - items = items[:] - for i in range(len(items) - 1): - swapped = False - for j in range(len(items) - 1 - i): - if comp(items[j], items[j + 1]): - items[j], items[j + 1] = items[j + 1], items[j] - swapped = True - if swapped: - swapped = False - for j in range(len(items) - 2 - i, i, -1): - if comp(items[j - 1], items[j]): - items[j], items[j - 1] = items[j - 1], items[j] - swapped = True - if not swapped: - break - return items - ``` - - ```Python - def merge(items1, items2, comp=lambda x, y: x < y): - """合并(将两个有序的列表合并成一个有序的列表)""" - items = [] - index1, index2 = 0, 0 - while index1 < len(items1) and index2 < len(items2): - if comp(items1[index1], items2[index2]): - items.append(items1[index1]) - index1 += 1 - else: - items.append(items2[index2]) - index2 += 1 - items += items1[index1:] - items += items2[index2:] - return items - - - def merge_sort(items, comp=lambda x, y: x < y): - return _merge_sort(list(items), comp) - - - def _merge_sort(items, comp): - """归并排序""" - if len(items) < 2: - return items - mid = len(items) // 2 - left = _merge_sort(items[:mid], comp) - right = _merge_sort(items[mid:], comp) - return merge(left, right, comp) - ``` - - ```Python - def seq_search(items, key): - """顺序查找""" - for index, item in enumerate(items): - if item == key: - return index - return -1 - ``` - - ```Python - def bin_search(items, key): - """折半查找""" - start, end = 0, len(items) - 1 - while start <= end: - mid = (start + end) // 2 - if key > items[mid]: - start = mid + 1 - elif key < items[mid]: - end = mid - 1 - else: - return mid - return -1 - ``` - -- 常用算法: - - - 穷举法 - 又称为暴力破解法,对所有的可能性进行验证,直到找到正确答案。 - - 贪婪法 - 在对问题求解时,总是做出在当前看来 - - 最好的选择,不追求最优解,快速找到满意解。 - - 分治法 - 把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题,直到可以直接求解的程度,最后将子问题的解进行合并得到原问题的解。 - - 回溯法 - 回溯法又称为试探法,按选优条件向前搜索,当搜索到某一步发现原先选择并不优或达不到目标时,就退回一步重新选择。 - - 动态规划 - 基本思想也是将待求解问题分解成若干个子问题,先求解并保存这些子问题的解,避免产生大量的重复运算。 - - 穷举法例子:百钱百鸡和五人分鱼。 - - ```Python - # 公鸡5元一只 母鸡3元一只 小鸡1元三只 - # 用100元买100只鸡 问公鸡/母鸡/小鸡各多少只 - for x in range(20): - for y in range(33): - z = 100 - x - y - if 5 * x + 3 * y + z // 3 == 100 and z % 3 == 0: - print(x, y, z) - - # A、B、C、D、E五人在某天夜里合伙捕鱼 最后疲惫不堪各自睡觉 - # 第二天A第一个醒来 他将鱼分为5份 扔掉多余的1条 拿走自己的一份 - # B第二个醒来 也将鱼分为5份 扔掉多余的1条 拿走自己的一份 - # 然后C、D、E依次醒来也按同样的方式分鱼 问他们至少捕了多少条鱼 - fish = 6 - while True: - total = fish - enough = True - for _ in range(5): - if (total - 1) % 5 == 0: - total = (total - 1) // 5 * 4 - else: - enough = False - break - if enough: - print(fish) - break - fish += 5 - ``` - - 贪婪法例子:假设小偷有一个背包,最多能装20公斤赃物,他闯入一户人家,发现如下表所示的物品。很显然,他不能把所有物品都装进背包,所以必须确定拿走哪些物品,留下哪些物品。 - - | 名称 | 价格(美元) | 重量(kg) | - | :----: | :----------: | :--------: | - | 电脑 | 200 | 20 | - | 收音机 | 20 | 4 | - | 钟 | 175 | 10 | - | 花瓶 | 50 | 2 | - | 书 | 10 | 1 | - | 油画 | 90 | 9 | - - ```Python - """ - 贪婪法:在对问题求解时,总是做出在当前看来是最好的选择,不追求最优解,快速找到满意解。 - 输入: - 20 6 - 电脑 200 20 - 收音机 20 4 - 钟 175 10 - 花瓶 50 2 - 书 10 1 - 油画 90 9 - """ - class Thing(object): - """物品""" - - def __init__(self, name, price, weight): - self.name = name - self.price = price - self.weight = weight - - @property - def value(self): - """价格重量比""" - return self.price / self.weight - - - def input_thing(): - """输入物品信息""" - name_str, price_str, weight_str = input().split() - return name_str, int(price_str), int(weight_str) - - - def main(): - """主函数""" - max_weight, num_of_things = map(int, input().split()) - all_things = [] - for _ in range(num_of_things): - all_things.append(Thing(*input_thing())) - all_things.sort(key=lambda x: x.value, reverse=True) - total_weight = 0 - total_price = 0 - for thing in all_things: - if total_weight + thing.weight <= max_weight: - print(f'小偷拿走了{thing.name}') - total_weight += thing.weight - total_price += thing.price - print(f'总价值: {total_price}美元') - - - if __name__ == '__main__': - main() - ``` - - 分治法例子:[快速排序](https://zh.wikipedia.org/zh/%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F)。 - - ```Python - """ - 快速排序 - 选择枢轴对元素进行划分,左边都比枢轴小右边都比枢轴大 - """ - def quick_sort(items, comp=lambda x, y: x <= y): - items = list(items)[:] - _quick_sort(items, 0, len(items) - 1, comp) - return items - - - def _quick_sort(items, start, end, comp): - if start < end: - pos = _partition(items, start, end, comp) - _quick_sort(items, start, pos - 1, comp) - _quick_sort(items, pos + 1, end, comp) - - - def _partition(items, start, end, comp): - pivot = items[end] - i = start - 1 - for j in range(start, end): - if comp(items[j], pivot): - i += 1 - items[i], items[j] = items[j], items[i] - items[i + 1], items[end] = items[end], items[i + 1] - return i + 1 - ``` - - 回溯法例子:[骑士巡逻](https://zh.wikipedia.org/zh/%E9%AA%91%E5%A3%AB%E5%B7%A1%E9%80%BB)。 - - ```Python - """ - 递归回溯法:叫称为试探法,按选优条件向前搜索,当搜索到某一步,发现原先选择并不优或达不到目标时,就退回一步重新选择,比较经典的问题包括骑士巡逻、八皇后和迷宫寻路等。 - """ - import sys - import time - - SIZE = 5 - total = 0 - - - def print_board(board): - for row in board: - for col in row: - print(str(col).center(4), end='') - print() - - - def patrol(board, row, col, step=1): - if row >= 0 and row < SIZE and \ - col >= 0 and col < SIZE and \ - board[row][col] == 0: - board[row][col] = step - if step == SIZE * SIZE: - global total - total += 1 - print(f'第{total}种走法: ') - print_board(board) - patrol(board, row - 2, col - 1, step + 1) - patrol(board, row - 1, col - 2, step + 1) - patrol(board, row + 1, col - 2, step + 1) - patrol(board, row + 2, col - 1, step + 1) - patrol(board, row + 2, col + 1, step + 1) - patrol(board, row + 1, col + 2, step + 1) - patrol(board, row - 1, col + 2, step + 1) - patrol(board, row - 2, col + 1, step + 1) - board[row][col] = 0 - - - def main(): - board = [[0] * SIZE for _ in range(SIZE)] - patrol(board, SIZE - 1, SIZE - 1) - - - if __name__ == '__main__': - main() - ``` - - 动态规划例子:子列表元素之和的最大值。 - - > 说明:子列表指的是列表中索引(下标)连续的元素构成的列表;列表中的元素是int类型,可能包含正整数、0、负整数;程序输入列表中的元素,输出子列表元素求和的最大值,例如: - > - > 输入:1 -2 3 5 -3 2 - > - > 输出:8 - > - > 输入:0 -2 3 5 -1 2 - > - > 输出:9 - > - > 输入:-9 -2 -3 -5 -3 - > - > 输出:-2 - - ```Python - def main(): - items = list(map(int, input().split())) - overall = partial = items[0] - for i in range(1, len(items)): - partial = max(items[i], partial + items[i]) - overall = max(partial, overall) - print(overall) - - - if __name__ == '__main__': - main() - ``` - - > **说明**:这个题目最容易想到的解法是使用二重循环,但是代码的时间性能将会变得非常的糟糕。使用动态规划的思想,仅仅是多用了两个变量,就将原来$O(N^2)$复杂度的问题变成了$O(N)$。 - -### 函数的使用方式 - -- 将函数视为“一等公民” - - - 函数可以赋值给变量 - - 函数可以作为函数的参数 - - 函数可以作为函数的返回值 - -- 高阶函数的用法(`filter`、`map`以及它们的替代品) - - ```Python - items1 = list(map(lambda x: x ** 2, filter(lambda x: x % 2, range(1, 10)))) - items2 = [x ** 2 for x in range(1, 10) if x % 2] - ``` - -- 位置参数、可变参数、关键字参数、命名关键字参数 - -- 参数的元信息(代码可读性问题) - -- 匿名函数和内联函数的用法(`lambda`函数) - -- 闭包和作用域问题 - - - Python搜索变量的LEGB顺序(Local >>> Embedded >>> Global >>> Built-in) - - - `global`和`nonlocal`关键字的作用 - - `global`:声明或定义全局变量(要么直接使用现有的全局作用域的变量,要么定义一个变量放到全局作用域)。 - - `nonlocal`:声明使用嵌套作用域的变量(嵌套作用域必须存在该变量,否则报错)。 - -- 装饰器函数(使用装饰器和取消装饰器) - - 例子:输出函数执行时间的装饰器。 - - ```Python - def record_time(func): - """自定义装饰函数的装饰器""" - - @wraps(func) - def wrapper(*args, **kwargs): - start = time() - result = func(*args, **kwargs) - print(f'{func.__name__}: {time() - start}秒') - return result - - return wrapper - ``` - - 如果装饰器不希望跟`print`函数耦合,可以编写可以参数化的装饰器。 - - ```Python - from functools import wraps - from time import time - - - def record(output): - """可以参数化的装饰器""" - - def decorate(func): - - @wraps(func) - def wrapper(*args, **kwargs): - start = time() - result = func(*args, **kwargs) - output(func.__name__, time() - start) - return result - - return wrapper - - return decorate - ``` - - ```Python - from functools import wraps - from time import time - - - class Record(): - """通过定义类的方式定义装饰器""" - - def __init__(self, output): - self.output = output - - def __call__(self, func): - - @wraps(func) - def wrapper(*args, **kwargs): - start = time() - result = func(*args, **kwargs) - self.output(func.__name__, time() - start) - return result - - return wrapper - ``` - - > **说明**:由于对带装饰功能的函数添加了@wraps装饰器,可以通过`func.__wrapped__`方式获得被装饰之前的函数或类来取消装饰器的作用。 - - 例子:用装饰器来实现单例模式。 - - ```Python - from functools import wraps - - - def singleton(cls): - """装饰类的装饰器""" - instances = {} - - @wraps(cls) - def wrapper(*args, **kwargs): - if cls not in instances: - instances[cls] = cls(*args, **kwargs) - return instances[cls] - - return wrapper - - - @singleton - class President: - """总统(单例类)""" - pass - ``` - - > **提示**:上面的代码中用到了闭包(closure),不知道你是否已经意识到了。还没有一个小问题就是,上面的代码并没有实现线程安全的单例,如果要实现线程安全的单例应该怎么做呢? - - 线程安全的单例装饰器。 - - ```Python - from functools import wraps - from threading import RLock - - - def singleton(cls): - """线程安全的单例装饰器""" - instances = {} - locker = RLock() - - @wraps(cls) - def wrapper(*args, **kwargs): - if cls not in instances: - with locker: - if cls not in instances: - instances[cls] = cls(*args, **kwargs) - return instances[cls] - - return wrapper - ``` - - > **提示**:上面的代码用到了`with`上下文语法来进行锁操作,因为锁对象本身就是上下文管理器对象(支持`__enter__`和`__exit__`魔术方法)。在`wrapper`函数中,我们先做了一次不带锁的检查,然后再做带锁的检查,这样做比直接加锁检查性能要更好,如果对象已经创建就没有必须再去加锁而是直接返回该对象就可以了。 - -### 面向对象相关知识 - -- 三大支柱:封装、继承、多态 - - 例子:工资结算系统。 - - ```Python - """ - 月薪结算系统 - 部门经理每月15000 程序员每小时200 销售员1800底薪加销售额5%提成 - """ - from abc import ABCMeta, abstractmethod - - - class Employee(metaclass=ABCMeta): - """员工(抽象类)""" - - def __init__(self, name): - self.name = name - - @abstractmethod - def get_salary(self): - """结算月薪(抽象方法)""" - pass - - - class Manager(Employee): - """部门经理""" - - def get_salary(self): - return 15000.0 - - - class Programmer(Employee): - """程序员""" - - def __init__(self, name, working_hour=0): - self.working_hour = working_hour - super().__init__(name) - - def get_salary(self): - return 200.0 * self.working_hour - - - class Salesman(Employee): - """销售员""" - - def __init__(self, name, sales=0.0): - self.sales = sales - super().__init__(name) - - def get_salary(self): - return 1800.0 + self.sales * 0.05 - - - class EmployeeFactory: - """创建员工的工厂(工厂模式 - 通过工厂实现对象使用者和对象之间的解耦合)""" - - @staticmethod - def create(emp_type, *args, **kwargs): - """创建员工""" - all_emp_types = {'M': Manager, 'P': Programmer, 'S': Salesman} - cls = all_emp_types[emp_type.upper()] - return cls(*args, **kwargs) if cls else None - - - def main(): - """主函数""" - emps = [ - EmployeeFactory.create('M', '曹操'), - EmployeeFactory.create('P', '荀彧', 120), - EmployeeFactory.create('P', '郭嘉', 85), - EmployeeFactory.create('S', '典韦', 123000), - ] - for emp in emps: - print(f'{emp.name}: {emp.get_salary():.2f}元') - - - if __name__ == '__main__': - main() - ``` - -- 类与类之间的关系 - - - is-a关系:继承 - - has-a关系:关联 / 聚合 / 合成 - - use-a关系:依赖 - - 例子:扑克游戏。 - - ```Python - """ - 经验:符号常量总是优于字面常量,枚举类型是定义符号常量的最佳选择 - """ - from enum import Enum, unique - - import random - - - @unique - class Suite(Enum): - """花色""" - - SPADE, HEART, CLUB, DIAMOND = range(4) - - def __lt__(self, other): - return self.value < other.value - - - class Card: - """牌""" - - def __init__(self, suite, face): - """初始化方法""" - self.suite = suite - self.face = face - - def show(self): - """显示牌面""" - suites = ['♠︎', '♥︎', '♣︎', '♦︎'] - faces = ['', 'A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'] - return f'{suites[self.suite.value]}{faces[self.face]}' - - def __repr__(self): - return self.show() - - - class Poker: - """扑克""" - - def __init__(self): - self.index = 0 - self.cards = [Card(suite, face) - for suite in Suite - for face in range(1, 14)] - - def shuffle(self): - """洗牌(随机乱序)""" - random.shuffle(self.cards) - self.index = 0 - - def deal(self): - """发牌""" - card = self.cards[self.index] - self.index += 1 - return card - - @property - def has_more(self): - return self.index < len(self.cards) - - - class Player: - """玩家""" - - def __init__(self, name): - self.name = name - self.cards = [] - - def get_one(self, card): - """摸一张牌""" - self.cards.append(card) - - def sort(self, comp=lambda card: (card.suite, card.face)): - """整理手上的牌""" - self.cards.sort(key=comp) - - - def main(): - """主函数""" - poker = Poker() - poker.shuffle() - players = [Player('东邪'), Player('西毒'), Player('南帝'), Player('北丐')] - while poker.has_more: - for player in players: - player.get_one(poker.deal()) - for player in players: - player.sort() - print(player.name, end=': ') - print(player.cards) - - - if __name__ == '__main__': - main() - ``` - - > **说明**:上面的代码中使用了Emoji字符来表示扑克牌的四种花色,在某些不支持Emoji字符的系统上可能无法显示。 - -- 对象的复制(深复制/深拷贝/深度克隆和浅复制/浅拷贝/影子克隆) - -- 垃圾回收、循环引用和弱引用 - - Python使用了自动化内存管理,这种管理机制以**引用计数**为基础,同时也引入了**标记-清除**和**分代收集**两种机制为辅的策略。 - - ```C - typedef struct _object { - /* 引用计数 */ - int ob_refcnt; - /* 对象指针 */ - struct _typeobject *ob_type; - } PyObject; - ``` - - ```C - /* 增加引用计数的宏定义 */ - #define Py_INCREF(op) ((op)->ob_refcnt++) - /* 减少引用计数的宏定义 */ - #define Py_DECREF(op) \ //减少计数 - if (--(op)->ob_refcnt != 0) \ - ; \ - else \ - __Py_Dealloc((PyObject *)(op)) - ``` - - 导致引用计数+1的情况: - - - 对象被创建,例如`a = 23` - - 对象被引用,例如`b = a` - - 对象被作为参数,传入到一个函数中,例如`f(a)` - - 对象作为一个元素,存储在容器中,例如`list1 = [a, a]` - - 导致引用计数-1的情况: - - - 对象的别名被显式销毁,例如`del a` - - 对象的别名被赋予新的对象,例如`a = 24` - - 一个对象离开它的作用域,例如f函数执行完毕时,f函数中的局部变量(全局变量不会) - - 对象所在的容器被销毁,或从容器中删除对象 - - 引用计数可能会导致循环引用问题,而循环引用会导致内存泄露,如下面的代码所示。为了解决这个问题,Python中引入了“标记-清除”和“分代收集”。在创建一个对象的时候,对象被放在第一代中,如果在第一代的垃圾检查中对象存活了下来,该对象就会被放到第二代中,同理在第二代的垃圾检查中对象存活下来,该对象就会被放到第三代中。 - - ```Python - # 循环引用会导致内存泄露 - Python除了引用技术还引入了标记清理和分代回收 - # 在Python 3.6以前如果重写__del__魔术方法会导致循环引用处理失效 - # 如果不想造成循环引用可以使用弱引用 - list1 = [] - list2 = [] - list1.append(list2) - list2.append(list1) - ``` - - 以下情况会导致垃圾回收: - - - 调用`gc.collect()` - - `gc`模块的计数器达到阀值 - - 程序退出 - - 如果循环引用中两个对象都定义了`__del__`方法,`gc`模块不会销毁这些不可达对象,因为gc模块不知道应该先调用哪个对象的`__del__`方法,这个问题在Python 3.6中得到了解决。 - - 也可以通过`weakref`模块构造弱引用的方式来解决循环引用的问题。 - -- 魔法属性和方法(请参考《Python魔法方法指南》) - - 有几个小问题请大家思考: - - - 自定义的对象能不能使用运算符做运算? - - 自定义的对象能不能放到`set`中?能去重吗? - - 自定义的对象能不能作为`dict`的键? - - 自定义的对象能不能使用上下文语法? - -- 混入(Mixin) - - 例子:自定义字典限制只有在指定的key不存在时才能在字典中设置键值对。 - - ```Python - class SetOnceMappingMixin: - """自定义混入类""" - __slots__ = () - - def __setitem__(self, key, value): - if key in self: - raise KeyError(str(key) + ' already set') - return super().__setitem__(key, value) - - - class SetOnceDict(SetOnceMappingMixin, dict): - """自定义字典""" - pass - - - my_dict= SetOnceDict() - try: - my_dict['username'] = 'jackfrued' - my_dict['username'] = 'hellokitty' - except KeyError: - pass - print(my_dict) - ``` - -- 元编程和元类 - - 对象是通过类创建的,类是通过元类创建的,元类提供了创建类的元信息。所有的类都直接或间接的继承自`object`,所有的元类都直接或间接的继承自`type`。 - - 例子:用元类实现单例模式。 - - ```Python - import threading - - - class SingletonMeta(type): - """自定义元类""" - - def __init__(cls, *args, **kwargs): - cls.__instance = None - cls.__lock = threading.RLock() - super().__init__(*args, **kwargs) - - def __call__(cls, *args, **kwargs): - if cls.__instance is None: - with cls.__lock: - if cls.__instance is None: - cls.__instance = super().__call__(*args, **kwargs) - return cls.__instance - - - class President(metaclass=SingletonMeta): - """总统(单例类)""" - - pass - ``` - -- 面向对象设计原则 - - - 单一职责原则 (**S**RP)- 一个类只做该做的事情(类的设计要高内聚) - - 开闭原则 (**O**CP)- 软件实体应该对扩展开发对修改关闭 - - 依赖倒转原则(DIP)- 面向抽象编程(在弱类型语言中已经被弱化) - - 里氏替换原则(**L**SP) - 任何时候可以用子类对象替换掉父类对象 - - 接口隔离原则(**I**SP)- 接口要小而专不要大而全(Python中没有接口的概念) - - 合成聚合复用原则(CARP) - 优先使用强关联关系而不是继承关系复用代码 - - 最少知识原则(迪米特法则,Lo**D**)- 不要给没有必然联系的对象发消息 - - > **说明**:上面加粗的字母放在一起称为面向对象的**SOLID**原则。 - -- GoF设计模式 - - - 创建型模式:单例、工厂、建造者、原型 - - 结构型模式:适配器、门面(外观)、代理 - - 行为型模式:迭代器、观察者、状态、策略 - - 例子:可插拔的哈希算法(策略模式)。 - - ```Python - class StreamHasher(): - """哈希摘要生成器""" - - def __init__(self, alg='md5', size=4096): - self.size = size - alg = alg.lower() - self.hasher = getattr(__import__('hashlib'), alg.lower())() - - def __call__(self, stream): - return self.to_digest(stream) - - def to_digest(self, stream): - """生成十六进制形式的摘要""" - for buf in iter(lambda: stream.read(self.size), b''): - self.hasher.update(buf) - return self.hasher.hexdigest() - - def main(): - """主函数""" - hasher1 = StreamHasher() - with open('Python-3.7.6.tgz', 'rb') as stream: - print(hasher1.to_digest(stream)) - hasher2 = StreamHasher('sha1') - with open('Python-3.7.6.tgz', 'rb') as stream: - print(hasher2(stream)) - - - if __name__ == '__main__': - main() - ``` - -### 迭代器和生成器 - -- 迭代器是实现了迭代器协议的对象。 - - - Python中没有像`protocol`或`interface`这样的定义协议的关键字。 - - Python中用魔术方法表示协议。 - - `__iter__`和`__next__`魔术方法就是迭代器协议。 - - ```Python - class Fib(object): - """迭代器""" - - def __init__(self, num): - self.num = num - self.a, self.b = 0, 1 - self.idx = 0 - - def __iter__(self): - return self - - def __next__(self): - if self.idx < self.num: - self.a, self.b = self.b, self.a + self.b - self.idx += 1 - return self.a - raise StopIteration() - ``` - -- 生成器是语法简化版的迭代器。 - - ```Python - def fib(num): - """生成器""" - a, b = 0, 1 - for _ in range(num): - a, b = b, a + b - yield a - ``` - -- 生成器进化为协程。 - - 生成器对象可以使用`send()`方法发送数据,发送的数据会成为生成器函数中通过`yield`表达式获得的值。这样,生成器就可以作为协程使用,协程简单的说就是可以相互协作的子程序。 - - ```Python - def calc_avg(): - """流式计算平均值""" - total, counter = 0, 0 - avg_value = None - while True: - value = yield avg_value - total, counter = total + value, counter + 1 - avg_value = total / counter - - - gen = calc_avg() - next(gen) - print(gen.send(10)) - print(gen.send(20)) - print(gen.send(30)) - ``` - -### 并发编程 - -Python中实现并发编程的三种方案:多线程、多进程和异步I/O。并发编程的好处在于可以提升程序的执行效率以及改善用户体验;坏处在于并发的程序不容易开发和调试,同时对其他程序来说它并不友好。 - -- 多线程:Python中提供了`Thread`类并辅以`Lock`、`Condition`、`Event`、`Semaphore`和`Barrier`。Python中有GIL来防止多个线程同时执行本地字节码,这个锁对于CPython是必须的,因为CPython的内存管理并不是线程安全的,因为GIL的存在多线程并不能发挥CPU的多核特性。 - - ```Python - """ - 面试题:进程和线程的区别和联系? - 进程 - 操作系统分配内存的基本单位 - 一个进程可以包含一个或多个线程 - 线程 - 操作系统分配CPU的基本单位 - 并发编程(concurrent programming) - 1. 提升执行性能 - 让程序中没有因果关系的部分可以并发的执行 - 2. 改善用户体验 - 让耗时间的操作不会造成程序的假死 - """ - import glob - import os - import threading - - from PIL import Image - - PREFIX = 'thumbnails' - - - def generate_thumbnail(infile, size, format='PNG'): - """生成指定图片文件的缩略图""" - file, ext = os.path.splitext(infile) - file = file[file.rfind('/') + 1:] - outfile = f'{PREFIX}/{file}_{size[0]}_{size[1]}.{ext}' - img = Image.open(infile) - img.thumbnail(size, Image.ANTIALIAS) - img.save(outfile, format) - - - def main(): - """主函数""" - if not os.path.exists(PREFIX): - os.mkdir(PREFIX) - for infile in glob.glob('images/*.png'): - for size in (32, 64, 128): - # 创建并启动线程 - threading.Thread( - target=generate_thumbnail, - args=(infile, (size, size)) - ).start() - - - if __name__ == '__main__': - main() - ``` - - 多个线程竞争资源的情况。 - - ```Python - """ - 多线程程序如果没有竞争资源处理起来通常也比较简单 - 当多个线程竞争临界资源的时候如果缺乏必要的保护措施就会导致数据错乱 - 说明:临界资源就是被多个线程竞争的资源 - """ - import time - import threading - - from concurrent.futures import ThreadPoolExecutor - - - class Account(object): - """银行账户""" - - def __init__(self): - self.balance = 0.0 - self.lock = threading.Lock() - - def deposit(self, money): - # 通过锁保护临界资源 - with self.lock: - new_balance = self.balance + money - time.sleep(0.001) - self.balance = new_balance - - - def main(): - """主函数""" - account = Account() - # 创建线程池 - pool = ThreadPoolExecutor(max_workers=10) - futures = [] - for _ in range(100): - future = pool.submit(account.deposit, 1) - futures.append(future) - # 关闭线程池 - pool.shutdown() - for future in futures: - future.result() - print(account.balance) - - - if __name__ == '__main__': - main() - ``` - - 修改上面的程序,启动5个线程向账户中存钱,5个线程从账户中取钱,取钱时如果余额不足就暂停线程进行等待。为了达到上述目标,需要对存钱和取钱的线程进行调度,在余额不足时取钱的线程暂停并释放锁,而存钱的线程将钱存入后要通知取钱的线程,使其从暂停状态被唤醒。可以使用`threading`模块的`Condition`来实现线程调度,该对象也是基于锁来创建的,代码如下所示: - - ```Python - """ - 多个线程竞争一个资源 - 保护临界资源 - 锁(Lock/RLock) - 多个线程竞争多个资源(线程数>资源数) - 信号量(Semaphore) - 多个线程的调度 - 暂停线程执行/唤醒等待中的线程 - Condition - """ - from concurrent.futures import ThreadPoolExecutor - from random import randint - from time import sleep - - import threading - - - class Account: - """银行账户""" - - def __init__(self, balance=0): - self.balance = balance - lock = threading.RLock() - self.condition = threading.Condition(lock) - - def withdraw(self, money): - """取钱""" - with self.condition: - while money > self.balance: - self.condition.wait() - new_balance = self.balance - money - sleep(0.001) - self.balance = new_balance - - def deposit(self, money): - """存钱""" - with self.condition: - new_balance = self.balance + money - sleep(0.001) - self.balance = new_balance - self.condition.notify_all() - - - def add_money(account): - while True: - money = randint(5, 10) - account.deposit(money) - print(threading.current_thread().name, - ':', money, '====>', account.balance) - sleep(0.5) - - - def sub_money(account): - while True: - money = randint(10, 30) - account.withdraw(money) - print(threading.current_thread().name, - ':', money, '<====', account.balance) - sleep(1) - - - def main(): - account = Account() - with ThreadPoolExecutor(max_workers=15) as pool: - for _ in range(5): - pool.submit(add_money, account) - for _ in range(10): - pool.submit(sub_money, account) - - - if __name__ == '__main__': - main() - ``` - -- 多进程:多进程可以有效的解决GIL的问题,实现多进程主要的类是`Process`,其他辅助的类跟`threading`模块中的类似,进程间共享数据可以使用管道、套接字等,在`multiprocessing`模块中有一个`Queue`类,它基于管道和锁机制提供了多个进程共享的队列。下面是官方文档上关于多进程和进程池的一个示例。 - - ```Python - """ - 多进程和进程池的使用 - 多线程因为GIL的存在不能够发挥CPU的多核特性 - 对于计算密集型任务应该考虑使用多进程 - time python3 example22.py - real 0m11.512s - user 0m39.319s - sys 0m0.169s - 使用多进程后实际执行时间为11.512秒,而用户时间39.319秒约为实际执行时间的4倍 - 这就证明我们的程序通过多进程使用了CPU的多核特性,而且这台计算机配置了4核的CPU - """ - import concurrent.futures - import math - - PRIMES = [ - 1116281, - 1297337, - 104395303, - 472882027, - 533000389, - 817504243, - 982451653, - 112272535095293, - 112582705942171, - 112272535095293, - 115280095190773, - 115797848077099, - 1099726899285419 - ] * 5 - - - def is_prime(n): - """判断素数""" - if n % 2 == 0: - return False - - sqrt_n = int(math.floor(math.sqrt(n))) - for i in range(3, sqrt_n + 1, 2): - if n % i == 0: - return False - return True - - - def main(): - """主函数""" - with concurrent.futures.ProcessPoolExecutor() as executor: - for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)): - print('%d is prime: %s' % (number, prime)) - - - if __name__ == '__main__': - main() - ``` - - > **重点**:**多线程和多进程的比较**。 - > - > 以下情况需要使用多线程: - > - > 1. 程序需要维护许多共享的状态(尤其是可变状态),Python中的列表、字典、集合都是线程安全的,所以使用线程而不是进程维护共享状态的代价相对较小。 - > 2. 程序会花费大量时间在I/O操作上,没有太多并行计算的需求且不需占用太多的内存。 - > - > 以下情况需要使用多进程: - > - > 1. 程序执行计算密集型任务(如:字节码操作、数据处理、科学计算)。 - > 2. 程序的输入可以并行的分成块,并且可以将运算结果合并。 - > 3. 程序在内存使用方面没有任何限制且不强依赖于I/O操作(如:读写文件、套接字等)。 - -- 异步处理:从调度程序的任务队列中挑选任务,该调度程序以交叉的形式执行这些任务,我们并不能保证任务将以某种顺序去执行,因为执行顺序取决于队列中的一项任务是否愿意将CPU处理时间让位给另一项任务。异步任务通常通过多任务协作处理的方式来实现,由于执行时间和顺序的不确定,因此需要通过回调式编程或者`future`对象来获取任务执行的结果。Python 3通过`asyncio`模块和`await`和`async`关键字(在Python 3.7中正式被列为关键字)来支持异步处理。 - - ```Python - """ - 异步I/O - async / await - """ - import asyncio - - - def num_generator(m, n): - """指定范围的数字生成器""" - yield from range(m, n + 1) - - - async def prime_filter(m, n): - """素数过滤器""" - primes = [] - for i in num_generator(m, n): - flag = True - for j in range(2, int(i ** 0.5 + 1)): - if i % j == 0: - flag = False - break - if flag: - print('Prime =>', i) - primes.append(i) - - await asyncio.sleep(0.001) - return tuple(primes) - - - async def square_mapper(m, n): - """平方映射器""" - squares = [] - for i in num_generator(m, n): - print('Square =>', i * i) - squares.append(i * i) - - await asyncio.sleep(0.001) - return squares - - - def main(): - """主函数""" - loop = asyncio.get_event_loop() - future = asyncio.gather(prime_filter(2, 100), square_mapper(1, 100)) - future.add_done_callback(lambda x: print(x.result())) - loop.run_until_complete(future) - loop.close() - - - if __name__ == '__main__': - main() - ``` - - > **说明**:上面的代码使用`get_event_loop`函数获得系统默认的事件循环,通过`gather`函数可以获得一个`future`对象,`future`对象的`add_done_callback`可以添加执行完成时的回调函数,`loop`对象的`run_until_complete`方法可以等待通过`future`对象获得协程执行结果。 - - Python中有一个名为`aiohttp`的三方库,它提供了异步的HTTP客户端和服务器,这个三方库可以跟`asyncio`模块一起工作,并提供了对`Future`对象的支持。Python 3.6中引入了`async`和`await`来定义异步执行的函数以及创建异步上下文,在Python 3.7中它们正式成为了关键字。下面的代码异步的从5个URL中获取页面并通过正则表达式的命名捕获组提取了网站的标题。 - - ```Python - import asyncio - import re - - import aiohttp - - PATTERN = re.compile(r'\(?P.*)\<\/title\>') - - - async def fetch_page(session, url): - async with session.get(url, ssl=False) as resp: - return await resp.text() - - - async def show_title(url): - async with aiohttp.ClientSession() as session: - html = await fetch_page(session, url) - print(PATTERN.search(html).group('title')) - - - def main(): - urls = ('https://www.python.org/', - 'https://git-scm.com/', - 'https://www.jd.com/', - 'https://www.taobao.com/', - 'https://www.douban.com/') - loop = asyncio.get_event_loop() - cos = [show_title(url) for url in urls] - loop.run_until_complete(asyncio.wait(cos)) - loop.close() - - - if __name__ == '__main__': - main() - ``` - - > **重点**:**异步I/O与多进程的比较**。 - > - > 当程序不需要真正的并发性或并行性,而是更多的依赖于异步处理和回调时,`asyncio`就是一种很好的选择。如果程序中有大量的等待与休眠时,也应该考虑`asyncio`,它很适合编写没有实时数据处理需求的Web应用服务器。 - - Python还有很多用于处理并行任务的三方库,例如:`joblib`、`PyMP`等。实际开发中,要提升系统的可扩展性和并发性通常有垂直扩展(增加单个节点的处理能力)和水平扩展(将单个节点变成多个节点)两种做法。可以通过消息队列来实现应用程序的解耦合,消息队列相当于是多线程同步队列的扩展版本,不同机器上的应用程序相当于就是线程,而共享的分布式消息队列就是原来程序中的Queue。消息队列(面向消息的中间件)的最流行和最标准化的实现是AMQP(高级消息队列协议),AMQP源于金融行业,提供了排队、路由、可靠传输、安全等功能,最著名的实现包括:Apache的ActiveMQ、RabbitMQ等。 - - 要实现任务的异步化,可以使用名为`Celery`的三方库。`Celery`是Python编写的分布式任务队列,它使用分布式消息进行工作,可以基于RabbitMQ或Redis来作为后端的消息代理。 \ No newline at end of file diff --git "a/Day21-30/21-30.Web\345\211\215\347\253\257\346\246\202\350\277\260.md" "b/Day21-30/21-30.Web\345\211\215\347\253\257\346\246\202\350\277\260.md" deleted file mode 100755 index 6d6fa23ce5..0000000000 --- "a/Day21-30/21-30.Web\345\211\215\347\253\257\346\246\202\350\277\260.md" +++ /dev/null @@ -1,912 +0,0 @@ -## Web前端概述 - -> **说明**:本文使用的部分插图来自*Jon Duckett*先生的*[HTML and CSS: Design and Build Websites](https://www.amazon.cn/dp/1118008189/ref=sr_1_5?__mk_zh_CN=%E4%BA%9A%E9%A9%AC%E9%80%8A%E7%BD%91%E7%AB%99&keywords=html+%26+css&qid=1554609325&s=gateway&sr=8-5)*一书,这是一本非常棒的前端入门书,有兴趣的读者可以在亚马逊或者其他网站上找到该书的购买链接。 - -HTML 是用来描述网页的一种语言,全称是 Hyper-Text Markup Language,即超文本标记语言。我们浏览网页时看到的文字、按钮、图片、视频等元素,它们都是通过 HTML 书写并通过浏览器来呈现的。 - -### HTML简史 - -1. 1991年10月:一个非正式CERN([欧洲核子研究中心](https://zh.wikipedia.org/wiki/%E6%AD%90%E6%B4%B2%E6%A0%B8%E5%AD%90%E7%A0%94%E7%A9%B6%E7%B5%84%E7%B9%94))文件首次公开18个HTML标签,这个文件的作者是物理学家[蒂姆·伯纳斯-李](https://zh.wikipedia.org/wiki/%E8%92%82%E5%A7%86%C2%B7%E4%BC%AF%E7%BA%B3%E6%96%AF-%E6%9D%8E),因此他是[万维网](https://zh.wikipedia.org/wiki/%E4%B8%87%E7%BB%B4%E7%BD%91)的发明者,也是[万维网联盟](https://zh.wikipedia.org/wiki/%E4%B8%87%E7%BB%B4%E7%BD%91%E8%81%94%E7%9B%9F)的主席。 -2. 1995年11月:HTML 2.0标准发布(RFC 1866)。 -3. 1997年1月:HTML 3.2作为[W3C](https://zh.wikipedia.org/wiki/W3C)推荐标准发布。 -4. 1997年12月:HTML 4.0作为W3C推荐标准发布。 -5. 1999年12月:HTML4.01作为W3C推荐标准发布。 -6. 2008年1月:HTML5由W3C作为工作草案发布。 -7. 2011年5月:W3C将HTML5推进至“最终征求”(Last Call)阶段。 -8. 2012年12月:W3C指定HTML5作为“候选推荐”阶段。 -9. 2014年10月:HTML5作为稳定W3C推荐标准发布,这意味着HTML5的标准化已经完成。 - -#### HTML5新特性 - -1. 引入原生多媒体支持(audio和video标签) -2. 引入可编程内容(canvas标签) -3. 引入语义Web(article、aside、details、figure、footer、header、nav、section、summary等标签) -4. 引入新的表单控件(日历、邮箱、搜索、滑条等) -5. 引入对离线存储更好的支持(localStorage和sessionStorage) -6. 引入对定位、拖放、WebSocket、后台任务等的支持 - -### 使用标签承载内容 - -<img src="https://gitee.com/jackfrued/mypic/raw/master/20211107163448.png" style="zoom:35%"> - -<img src="https://gitee.com/jackfrued/mypic/raw/master/20211107163741.png" style="zoom:75%"> - -#### 结构 - -- html - - head - - title - - meta - - body - -#### 文本 - -- 标题(heading)和段落(paragraph) - - h1 ~ h6 - - p -- 上标(superscript)和下标(subscript) - - sup - - sub -- 空白(白色空间折叠) -- 折行(break)和水平标尺(horizontal ruler) - - br - - hr -- 语义化标签 - - 加粗和强调 - strong - - 引用 - blockquote - - 缩写词和首字母缩写词 - abbr / acronym - - 引文 - cite - - 所有者联系信息 - address - - 内容的修改 - ins / del - -#### 列表(list) - - - 有序列表(ordered list)- ol / li - - 无序列表(unordered list)- ul / li - - 定义列表(definition list)- dl / dt / dd - -#### 链接(anchor) - -- 页面链接 -- 锚链接 -- 功能链接 - -#### 图像(image) - -- 图像存储位置 - - ![](./res/相对路径.png) - -- 图像及其宽高 - -- 选择正确的图像格式 - - JPEG - - GIF - - PNG - -- 矢量图 - -- 语义化标签 - figure / figcaption - -#### 表格(table) - -- 基本的表格结构 - table / tr / td / th -- 表格的标题 - caption -- 跨行和跨列 - rowspan属性 / colspan属性 -- 长表格 - thead / tbody / tfoot - -#### 表单(form) - -- 重要属性 - action / method / enctype -- 表单控件(input)- type属性 - - 文本框 - `text` / 密码框 - `password` / 数字框 - `number` - - 邮箱 - `email` / 电话 - `tel` / 日期 - `date` / 滑条 - `range` / URL - `url` / 搜索 - `search` - - 单选按钮 - `radio` / 复选按钮 - `checkbox` - - 文件上传 - `file` / 隐藏域 - `hidden` - - 提交按钮 - `submit` / 图像按钮 - `image` / 重置按钮 - `reset` -- 下拉列表 - select / option -- 文本域(多行文本)- textarea -- 组合表单元素 - fieldset / legend - -#### 音视频(audio / video) - -- 视频格式和播放器 -- 视频托管服务 -- 添加视频的准备工作 -- video标签和属性 - autoplay / controls / loop / muted / preload / src -- audio标签和属性 - autoplay / controls / loop / muted / preload / src / width / height / poster - -#### 窗口(frame) - -- 框架集(过时,不建议使用) - frameset / frame - -- 内嵌窗口 - iframe - -#### 其他 - -- 文档类型 - - ```HTML - <!doctype html> - ``` - - ```HTML - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> - ``` - - ```HTML - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> - ``` - -- 注释 - - ```HTML - <!-- 这是一段注释,注释不能够嵌套 --> - ``` - -- 属性 - - id:唯一标识 - - class:元素所属的类,用于区分不同的元素 - - title:元素的额外信息(鼠标悬浮时会显示工具提示文本) - - tabindex:Tab键切换顺序 - - contenteditable:元素是否可编辑 - - draggable:元素是否可拖拽 - -- 块级元素 / 行级元素 - -- 字符实体(实体替换符) - - ![](./res/字符实体.png) - -### 使用CSS渲染页面 - -#### 简介 - -- CSS的作用 - -- CSS的工作原理 - -- 规则、属性和值 - - ![](./res/选择器语法.png) - -- 常用选择器 - - ![](./res/常用选择器.png) - -#### 颜色(color) - -- 如何指定颜色 -- 颜色术语和颜色对比 -- 背景色 - -#### 文本(text / font) - -- 文本的大小和字型(font-size / font-family) - - ![](./res/尺寸单位.png) - - ![](./res/衬线字体+非衬线字体+等宽字体.png) - -- 粗细、样式、拉伸和装饰(font-weight / font-style / font-stretch / text-decoration) - - ![](./res/字体样式.png) - -- 行间距(line-height)、字母间距(letter-spacing)和单词间距(word-spacing) - -- 对齐(text-align)方式和缩进(text-ident) - -- 链接样式(:link / :visited / :active / :hover) - -- CSS3新属性 - - 阴影效果 - text-shadow - - 首字母和首行文本(:first-letter / :first-line) - - 响应用户 - -#### 盒子(box model) - -- 盒子大小的控制(width / height) - - ![](./res/尺寸单位.png) - -- 盒子的边框、外边距和内边距(border / margin / padding) - - ![](./res/盒子模型.png) - -- 盒子的显示和隐藏(display / visibility) - -- CSS3新属性 - - 边框图像(border-image) - - 投影(border-shadow) - - 圆角(border-radius) - -#### 列表、表格和表单 - -- 列表的项目符号(list-style) -- 表格的边框和背景(border-collapse) -- 表单控件的外观 -- 表单控件的对齐 -- 浏览器的开发者工具 - -#### 图像 - -- 控制图像的大小(display: inline-block) -- 对齐图像 -- 背景图像(background / background-image / background-repeat / background-position) - -#### 布局 - -- 控制元素的位置(position / z-index) - - 普通流 - - 相对定位 - - 绝对定位 - - 固定定位 - - 浮动元素(float / clear) -- 网站布局 - - - HTML5布局 - - ![](./res/经典布局-2.png) -- 适配屏幕尺寸 - - 固定宽度布局 - - 流体布局 - - 布局网格 - -### 使用JavaScript控制行为 - -#### JavaScript基本语法 - -- 语句和注释 -- 变量和数据类型 - - 声明和赋值 - - 简单数据类型和复杂数据类型 - - 变量的命名规则 -- 表达式和运算符 - - 赋值运算符 - - 算术运算符 - - 比较运算符 - - 逻辑运算符:`&&`、`||`、`!` -- 分支结构 - - `if...else...` - - `switch...cas...default...` -- 循环结构 - - `for`循环 - - `while`循环 - - `do...while`循环 -- 数组 - - 创建数组 - - 操作数组中的元素 -- 函数 - - 声明函数 - - 调用函数 - - 参数和返回值 - - 匿名函数 - - 立即调用函数 - -#### 面向对象 - - - 对象的概念 - - 创建对象的字面量语法 - - 访问成员运算符 - - 创建对象的构造函数语法 - - `this`关键字 - - 添加和删除属性 - - `delete`关键字 - - 标准对象 - - `Number` / `String` / `Boolean` / `Symbol` / `Array` / `Function` - - `Date` / `Error` / `Math` / `RegExp` / `Object` / `Map` / `Set` - - `JSON` / `Promise` / `Generator` / `Reflect` / `Proxy` - -#### BOM - - - `window`对象的属性和方法 - - `history`对象 - - `forward()` / `back()` / `go()` - - `location`对象 - - `navigator`对象 - - `screen`对象 - -#### DOM - - - DOM树 - - 访问元素 - - `getElementById()` / `querySelector()` - - `getElementsByClassName()` / `getElementsByTagName()` / `querySelectorAll()` - - `parentNode` / `previousSibling` / `nextSibling` / `children` / `firstChild` / `lastChild` -- 操作元素 - - `nodeValue` - - `innerHTML` / `textContent` / `createElement()` / `createTextNode()` / `appendChild()` / `insertBefore()` / `removeChild()` - - `className` / `id` / `hasAttribute()` / `getAttribute()` / `setAttribute()` / `removeAttribute()` -- 事件处理 - - 事件类型 - - UI事件:`load` / `unload` / `error` / `resize` / `scroll` - - 键盘事件:`keydown` / `keyup` / `keypress` - - 鼠标事件:`click` / `dbclick` / `mousedown` / `mouseup` / `mousemove` / `mouseover` / `mouseout` - - 焦点事件:`focus` / `blur` - - 表单事件:`input` / `change` / `submit` / `reset` / `cut` / `copy` / `paste` / `select` - - 事件绑定 - - HTML事件处理程序(不推荐使用,因为要做到标签与代码分离) - - 传统的DOM事件处理程序(只能附加一个回调函数) - - 事件监听器(旧的浏览器中不被支持) - - 事件流:事件捕获 / 事件冒泡 - - 事件对象(低版本IE中的window.event) - - `target`(有些浏览器使用srcElement) - - `type` - - `cancelable` - - `preventDefault()` - - `stopPropagation()`(低版本IE中的cancelBubble) - - 鼠标事件 - 事件发生的位置 - - 屏幕位置:`screenX`和`screenY` - - 页面位置:`pageX`和`pageY` - - 客户端位置:`clientX`和`clientY` - - 键盘事件 - 哪个键被按下了 - - `keyCode`属性(有些浏览器使用`which`) - - `String.fromCharCode(event.keyCode)` - - HTML5事件 - - `DOMContentLoaded` - - `hashchange` - - `beforeunload` - -#### JavaScript API - -- 客户端存储 - `localStorage`和`sessionStorage` - - ```JavaScript - localStorage.colorSetting = '#a4509b'; - localStorage['colorSetting'] = '#a4509b'; - localStorage.setItem('colorSetting', '#a4509b'); - ``` - -- 获取位置信息 - `geolocation` - - ```JavaScript - navigator.geolocation.getCurrentPosition(function(pos) { - console.log(pos.coords.latitude) - console.log(pos.coords.longitude) - }) - ``` - -- 从服务器获取数据 - Fetch API -- 绘制图形 - `<canvas>`的API -- 音视频 - `<audio>`和`<video>`的API - -### 使用jQuery - -#### jQuery概述 - -1. Write Less Do More(用更少的代码来完成更多的工作) -2. 使用CSS选择器来查找元素(更简单更方便) -3. 使用jQuery方法来操作元素(解决浏览器兼容性问题、应用于所有元素并施加多个方法) - -#### 引入jQuery - -- 下载jQuery的开发版和压缩版 -- 从CDN加载jQuery - -```HTML -<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> -<script> - window.jQuery || - document.write('<script src="js/jquery-3.3.1.min.js"></script>') -</script> -``` - -#### 查找元素 - -- 选择器 - - \* / element / #id / .class / selector1, selector2 - - ancestor descendant / parent>child / previous+next / previous~siblings -- 筛选器 - - 基本筛选器::not(selector) / :first / :last / :even / :odd / :eq(index) / :gt(index) / :lt(index) / :animated / :focus - - 内容筛选器::contains('…') / :empty / :parent / :has(selector) - - 可见性筛选器::hidden / :visible - - 子节点筛选器::nth-child(expr) / :first-child / :last-child / :only-child - - 属性筛选器:[attribute] / [attribute='value'] / [attribute!='value'] / [attribute^='value'] / [attribute$='value'] / [attribute|='value'] / [attribute~='value'] -- 表单::input / :text / :password / :radio / :checkbox / :submit / :image / :reset / :button / :file / :selected / :enabled / :disabled / :checked - -#### 执行操作 - -- 内容操作 - - 获取/修改内容:`html()` / `text()` / `replaceWith()` / `remove()` - - 获取/设置元素:`before()` / `after()` / `prepend()` / `append()` / `remove()` / `clone()` / `unwrap()` / `detach()` / `empty()` / `add()` - - 获取/修改属性:`attr()` / `removeAttr()` / `addClass()` / `removeClass()` / `css()` - - 获取/设置表单值:`val()` -- 查找操作 - - 查找方法:`find()` / `parent()` / `children()` / `siblings()` / `next()` / `nextAll()` / `prev()` / `prevAll()` - - 筛选器:`filter()` / `not()` / `has()` / `is()` / `contains()` - - 索引编号:`eq()` -- 尺寸和位置 - - 尺寸相关:`height()` / `width()` / `innerHeight()` / `innerWidth()` / `outerWidth()` / `outerHeight()` - - 位置相关:`offset()` / `position()` / `scrollLeft()` / `scrollTop()` -- 特效和动画 - - 基本动画:`show()` / `hide()` / `toggle()` - - 消失出现:`fadeIn()` / `fadeOut()` / `fadeTo()` / `fadeToggle()` - - 滑动效果:`slideDown()` / `slideUp()` / `slideToggle()` - - 自定义:`delay()` / `stop()` / `animate()` -- 事件 - - 文档加载:`ready()` / `load()` - - 用户交互:`on()` / `off()` - -#### 链式操作 - -#### 检测页面是否可用 - -```HTML -<script> - $(document).ready(function() { - - }); -</script> -``` - -```HTML -<script> - $(function() { - - }); -</script> -``` - -#### jQuery插件 - -- jQuery Validation -- jQuery Treeview -- jQuery Autocomplete -- jQuery UI - -#### 避免和其他库的冲突 - -先引入其他库再引入jQuery的情况。 - -```HTML -<script src="other.js"></script> -<script src="jquery.js"></script> -<script> - jQuery.noConflict(); - jQuery(function() { - jQuery('div').hide(); - }); -</script> -``` - -先引入jQuery再引入其他库的情况。 - -```HTML - -<script src="jquery.js"></script> -<script src="other.js"></script> -<script> - jQuery(function() { - jQuery('div').hide(); - }); -</script> -``` - -#### 使用Ajax - -Ajax是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。 - -- 原生的Ajax -- 基于jQuery的Ajax - - 加载内容 - - 提交表单 - -### 前端框架 - -#### 渐进式框架 - [Vue.js](<https://cn.vuejs.org/>) - -前后端分离开发(前端渲染)必选框架。 - -##### 快速上手 - -1. 引入Vue的JavaScript文件,我们仍然推荐从CDN服务器加载它。 - - ```HTML - <script src="https://cdn.jsdelivr.net/npm/vue"></script> - ``` - -2. 数据绑定(声明式渲染 )。 - - ```HTML - <div id="app"> - <h1>{{ product }}库存信息</h1> - </div> - - <script src="https://cdn.jsdelivr.net/npm/vue"></script> - <script> - const app = new Vue({ - el: '#app', - data: { - product: 'iPhone X' - } - }); - </script> - ``` - -3. 条件与循环。 - - ```HTML - <div id="app"> - <h1>库存信息</h1> - <hr> - <ul> - <li v-for="product in products"> - {{ product.name }} - {{ product.quantity }} - <span v-if="product.quantity === 0"> - 已经售罄 - </span> - </li> - </ul> - </div> - - <script src="https://cdn.jsdelivr.net/npm/vue"></script> - <script> - const app = new Vue({ - el: '#app', - data: { - products: [ - {"id": 1, "name": "iPhone X", "quantity": 20}, - {"id": 2, "name": "华为 Mate20", "quantity": 0}, - {"id": 3, "name": "小米 Mix3", "quantity": 50} - ] - } - }); - </script> - ``` - -4. 计算属性。 - - ```HTML - <div id="app"> - <h1>库存信息</h1> - <hr> - <ul> - <li v-for="product in products"> - {{ product.name }} - {{ product.quantity }} - <span v-if="product.quantity === 0"> - 已经售罄 - </span> - </li> - </ul> - <h2>库存总量:{{ totalQuantity }}台</h2> - </div> - - <script src="https://cdn.jsdelivr.net/npm/vue"></script> - <script> - const app = new Vue({ - el: '#app', - data: { - products: [ - {"id": 1, "name": "iPhone X", "quantity": 20}, - {"id": 2, "name": "华为 Mate20", "quantity": 0}, - {"id": 3, "name": "小米 Mix3", "quantity": 50} - ] - }, - computed: { - totalQuantity() { - return this.products.reduce((sum, product) => { - return sum + product.quantity - }, 0); - } - } - }); - </script> - ``` - -5. 处理事件。 - - ```HTML - <div id="app"> - <h1>库存信息</h1> - <hr> - <ul> - <li v-for="product in products"> - {{ product.name }} - {{ product.quantity }} - <span v-if="product.quantity === 0"> - 已经售罄 - </span> - <button @click="product.quantity += 1"> - 增加库存 - </button> - </li> - </ul> - <h2>库存总量:{{ totalQuantity }}台</h2> - </div> - - <script src="https://cdn.jsdelivr.net/npm/vue"></script> - <script> - const app = new Vue({ - el: '#app', - data: { - products: [ - {"id": 1, "name": "iPhone X", "quantity": 20}, - {"id": 2, "name": "华为 Mate20", "quantity": 0}, - {"id": 3, "name": "小米 Mix3", "quantity": 50} - ] - }, - computed: { - totalQuantity() { - return this.products.reduce((sum, product) => { - return sum + product.quantity - }, 0); - } - } - }); - </script> - ``` - -6. 用户输入。 - - ```HTML - <div id="app"> - <h1>库存信息</h1> - <hr> - <ul> - <li v-for="product in products"> - {{ product.name }} - - <input type="number" v-model.number="product.quantity" min="0"> - <span v-if="product.quantity === 0"> - 已经售罄 - </span> - <button @click="product.quantity += 1"> - 增加库存 - </button> - </li> - </ul> - <h2>库存总量:{{ totalQuantity }}台</h2> - </div> - - <script src="https://cdn.jsdelivr.net/npm/vue"></script> - <script> - const app = new Vue({ - el: '#app', - data: { - products: [ - {"id": 1, "name": "iPhone X", "quantity": 20}, - {"id": 2, "name": "华为 Mate20", "quantity": 0}, - {"id": 3, "name": "小米 Mix3", "quantity": 50} - ] - }, - computed: { - totalQuantity() { - return this.products.reduce((sum, product) => { - return sum + product.quantity - }, 0); - } - } - }); - </script> - ``` - -7. 通过网络加载JSON数据。 - - ```HTML - <div id="app"> - <h2>库存信息</h2> - <ul> - <li v-for="product in products"> - {{ product.name }} - {{ product.quantity }} - <span v-if="product.quantity === 0"> - 已经售罄 - </span> - </li> - </ul> - </div> - - <script src="https://cdn.jsdelivr.net/npm/vue"></script> - <script> - const app = new Vue({ - el: '#app', - data: { - products: [] - }, - created() { - fetch('https://jackfrued.top/api/products') - .then(response => response.json()) - .then(json => { - this.products = json - }); - } - }); - </script> - ``` - -##### 使用脚手架 - vue-cli - -Vue为商业项目开发提供了非常便捷的脚手架工具vue-cli,通过工具可以省去手工配置开发环境、测试环境和运行环境的步骤,让开发者只需要关注要解决的问题。 - -1. 安装脚手架。 -2. 创建项目。 -3. 安装依赖包。 -4. 运行项目。 - - -#### UI框架 - [Element](<http://element-cn.eleme.io/#/zh-CN>) - -基于Vue 2.0的桌面端组件库,用于构造用户界面,支持响应式布局。 - -1. 引入Element的CSS和JavaScript文件。 - - ```HTML - <!-- 引入样式 --> - <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> - <!-- 引入组件库 --> - <script src="https://unpkg.com/element-ui/lib/index.js"></script> - ``` - -2. 一个简单的例子。 - - ```HTML - <!DOCTYPE html> - <html> - <head> - <meta charset="UTF-8"> - <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> - </head> - <body> - <div id="app"> - <el-button @click="visible = true">点我</el-button> - <el-dialog :visible.sync="visible" title="Hello world"> - <p>开始使用Element吧</p> - </el-dialog> - </div> - </body> - <script src="https://unpkg.com/vue/dist/vue.js"></script> - <script src="https://unpkg.com/element-ui/lib/index.js"></script> - <script> - new Vue({ - el: '#app', - data: { - visible: false, - } - }) - </script> - </html> - ``` - -3. 使用组件。 - - ```HTML - <!DOCTYPE html> - <html> - <head> - <meta charset="UTF-8"> - <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> - </head> - <body> - <div id="app"> - <el-table :data="tableData" stripe style="width: 100%"> - <el-table-column prop="date" label="日期" width="180"> - </el-table-column> - <el-table-column prop="name" label="姓名" width="180"> - </el-table-column> - <el-table-column prop="address" label="地址"> - </el-table-column> - </el-table> - </div> - </body> - <script src="https://unpkg.com/vue/dist/vue.js"></script> - <script src="https://unpkg.com/element-ui/lib/index.js"></script> - <script> - new Vue({ - el: '#app', - data: { - tableData: [ - { - date: '2016-05-02', - name: '王一霸', - address: '上海市普陀区金沙江路 1518 弄' - }, - { - date: '2016-05-04', - name: '刘二狗', - address: '上海市普陀区金沙江路 1517 弄' - }, - { - date: '2016-05-01', - name: '杨三萌', - address: '上海市普陀区金沙江路 1519 弄' - }, - { - date: '2016-05-03', - name: '陈四吹', - address: '上海市普陀区金沙江路 1516 弄' - } - ] - } - }) - </script> - </html> - ``` - - -#### 报表框架 - [ECharts](<https://echarts.baidu.com>) - -百度出品的开源可视化库,常用于生成各种类型的报表。 - -![](./res/baidu_echarts.png) - -#### 基于弹性盒子的CSS框架 - [Bulma](<https://bulma.io/>) - -Bulma是一个基于Flexbox的现代化的CSS框架,其初衷就是移动优先(Mobile First),模块化设计,可以轻松用来实现各种简单或者复杂的内容布局,即使不懂CSS的开发者也能够使用它定制出漂亮的页面。 - -```HTML -<!DOCTYPE html> -<html lang="en"> -<head> - <meta charset="UTF-8"> - <title>Bulma - - - - -
-
1
-
2
-
3
-
4
-
-
- Primary - Link - Info - Success - Warning - Danger -
-
- 60% -
-
- - - - - - - - - - - - - - - - - - - - - - - - - -
OneTwo
ThreeFour
FiveSix
SevenEight
NineTen
ElevenTwelve
-
- - -``` - -#### 响应式布局框架 - [Bootstrap]() - -用于快速开发Web应用程序的前端框架,支持响应式布局。 - -1. 特点 - - 支持主流的浏览器和移动设备 - - 容易上手 - - 响应式设计 - -2. 内容 - - 网格系统 - - 封装的CSS - - 现成的组件 - - JavaScript插件 - -3. 可视化 - - ![](./res/bootstrap-layoutit.png) \ No newline at end of file diff --git "a/Day36-40/36.\345\205\263\347\263\273\345\236\213\346\225\260\346\215\256\345\272\223\345\222\214MySQL\346\246\202\350\277\260.md" "b/Day36-40/36.\345\205\263\347\263\273\345\236\213\346\225\260\346\215\256\345\272\223\345\222\214MySQL\346\246\202\350\277\260.md" index 5bb33a1094..c35dfdce15 100755 --- "a/Day36-40/36.\345\205\263\347\263\273\345\236\213\346\225\260\346\215\256\345\272\223\345\222\214MySQL\346\246\202\350\277\260.md" +++ "b/Day36-40/36.\345\205\263\347\263\273\345\236\213\346\225\260\346\215\256\345\272\223\345\222\214MySQL\346\246\202\350\277\260.md" @@ -1,298 +1,273 @@ -## 关系型数据库和MySQL概述 +# 关系型数据库和MySQL概述 -### 关系型数据库概述 +## 关系型数据库概述 1. 数据持久化 - 将数据保存到能够长久保存数据的存储介质中,在掉电的情况下数据也不会丢失。 +2. 数据库发展史 - 网状数据库、层次数据库、关系数据库、NoSQL 数据库、NewSQL 数据库。 -2. 数据库发展史 - 网状数据库、层次数据库、关系数据库、NoSQL 数据库、NewSQL 数据库。 - - > 1970年,IBM的研究员E.F.Codd在*Communication of the ACM*上发表了名为*A Relational Model of Data for Large Shared Data Banks*的论文,提出了**关系模型**的概念,奠定了关系模型的理论基础。后来Codd又陆续发表多篇文章,论述了范式理论和衡量关系系统的12条标准,用数学理论奠定了关系数据库的基础。 - + > 1970年,IBM的研究员E.F.Codd在_Communication of the ACM_上发表了名为_A Relational Model of Data for Large Shared Data Banks_的论文,提出了**关系模型**的概念,奠定了关系模型的理论基础。后来Codd又陆续发表多篇文章,论述了范式理论和衡量关系系统的12条标准,用数学理论奠定了关系数据库的基础。 3. 关系数据库特点。 + * 理论基础:**关系代数**(关系运算、集合论、一阶谓词逻辑)。 + * 具体表象:用**二维表**(有行和列)组织数据。 + * 编程语言:**结构化查询语言**(SQL)。 +4. ER模型(实体关系模型)和概念模型图。 - - 理论基础:**关系代数**(关系运算、集合论、一阶谓词逻辑)。 - - - 具体表象:用**二维表**(有行和列)组织数据。 - - - 编程语言:**结构化查询语言**(SQL)。 - -4. ER模型(实体关系模型)和概念模型图。 - - **ER模型**,全称为**实体关系模型**(Entity-Relationship Model),由美籍华裔计算机科学家陈品山先生提出,是概念数据模型的高层描述方式,如下图所示。 - - + **ER模型**,全称为**实体关系模型**(Entity-Relationship Model),由美籍华裔计算机科学家陈品山先生提出,是概念数据模型的高层描述方式,如下图所示。 - - 实体 - 矩形框 - - 属性 - 椭圆框 - - 关系 - 菱形框 - - 重数 - 1:1(一对一) / 1:N(一对多) / M:N(多对多) + ![](https://gitee.com/jackfrued/mypic/raw/master/20210826003119.png) - 实际项目开发中,我们可以利用数据库建模工具(如:PowerDesigner)来绘制概念数据模型(其本质就是 ER 模型),然后再设置好目标数据库系统,将概念模型转换成物理模型,最终生成创建二维表的 SQL(很多工具都可以根据我们设计的物理模型图以及设定的目标数据库来导出 SQL 或直接生成数据表)。 + * 实体 - 矩形框 + * 属性 - 椭圆框 + * 关系 - 菱形框 + * 重数 - 1:1(一对一) / 1:N(一对多) / M:N(多对多) - ![](https://gitee.com/jackfrued/mypic/raw/master/20210826003212.png) + 实际项目开发中,我们可以利用数据库建模工具(如:PowerDesigner)来绘制概念数据模型(其本质就是 ER 模型),然后再设置好目标数据库系统,将概念模型转换成物理模型,最终生成创建二维表的 SQL(很多工具都可以根据我们设计的物理模型图以及设定的目标数据库来导出 SQL 或直接生成数据表)。 + ![](https://gitee.com/jackfrued/mypic/raw/master/20210826003212.png) 5. 关系数据库产品。 - - [Oracle](https://www.oracle.com/index.html) - 目前世界上使用最为广泛的数据库管理系统,作为一个通用的数据库系统,它具有完整的数据管理功能;作为一个关系数据库,它是一个完备关系的产品;作为分布式数据库,它实现了分布式处理的功能。在 Oracle 最新的 12c 版本中,还引入了多承租方架构,使用该架构可轻松部署和管理数据库云。 - - [DB2](https://www.ibm.com/analytics/us/en/db2/) - IBM 公司开发的、主要运行于 Unix(包括 IBM 自家的 [AIX](https://zh.wikipedia.org/wiki/AIX))、Linux、以及 Windows 服务器版等系统的关系数据库产品。DB2 历史悠久且被认为是最早使用 SQL 的数据库产品,它拥有较为强大的商业智能功能。 - - [SQL Server](https://www.microsoft.com/en-us/sql-server/) - 由 Microsoft 开发和推广的关系型数据库产品,最初适用于中小企业的数据管理,但是近年来它的应用范围有所扩展,部分大企业甚至是跨国公司也开始基于它来构建自己的数据管理系统。 - - [MySQL](https://www.mysql.com/) - MySQL 是开放源代码的,任何人都可以在 GPL(General Public License)的许可下下载并根据个性化的需要对其进行修改。MySQL 因为其速度、可靠性和适应性而备受关注。 - - [PostgreSQL]() - 在 BSD 许可证下发行的开放源代码的关系数据库产品。 + * [Oracle](https://www.oracle.com/index.html) - 目前世界上使用最为广泛的数据库管理系统,作为一个通用的数据库系统,它具有完整的数据管理功能;作为一个关系数据库,它是一个完备关系的产品;作为分布式数据库,它实现了分布式处理的功能。在 Oracle 最新的 12c 版本中,还引入了多承租方架构,使用该架构可轻松部署和管理数据库云。 + * [DB2](https://www.ibm.com/analytics/us/en/db2/) - IBM 公司开发的、主要运行于 Unix(包括 IBM 自家的 [AIX](https://zh.wikipedia.org/wiki/AIX))、Linux、以及 Windows 服务器版等系统的关系数据库产品。DB2 历史悠久且被认为是最早使用 SQL 的数据库产品,它拥有较为强大的商业智能功能。 + * [SQL Server](https://www.microsoft.com/en-us/sql-server/) - 由 Microsoft 开发和推广的关系型数据库产品,最初适用于中小企业的数据管理,但是近年来它的应用范围有所扩展,部分大企业甚至是跨国公司也开始基于它来构建自己的数据管理系统。 + * [MySQL](https://www.mysql.com/) - MySQL 是开放源代码的,任何人都可以在 GPL(General Public License)的许可下下载并根据个性化的需要对其进行修改。MySQL 因为其速度、可靠性和适应性而备受关注。 + * [PostgreSQL](36.关系型数据库和MySQL概述.md) - 在 BSD 许可证下发行的开放源代码的关系数据库产品。 -### MySQL 简介 +## MySQL 简介 MySQL 最早是由瑞典的 MySQL AB 公司开发的一个开放源码的关系数据库管理系统,该公司于2008年被昇阳微系统公司(Sun Microsystems)收购。在2009年,甲骨文公司(Oracle)收购昇阳微系统公司,因此 MySQL 目前也是 Oracle 旗下产品。 MySQL 在过去由于性能高、成本低、可靠性好,已经成为最流行的开源数据库,因此被广泛地应用于中小型网站开发。随着 MySQL 的不断成熟,它也逐渐被应用于更多大规模网站和应用,比如维基百科、谷歌(Google)、脸书(Facebook)、淘宝网等网站都使用了 MySQL 来提供数据持久化服务。 -甲骨文公司收购后昇阳微系统公司,大幅调涨 MySQL 商业版的售价,且甲骨文公司不再支持另一个自由软件项目 [OpenSolaris ](https://zh.wikipedia.org/wiki/OpenSolaris) 的发展,因此导致自由软件社区对于 Oracle 是否还会持续支持 MySQL 社区版(MySQL 的各个发行版本中唯一免费的版本)有所担忧,MySQL 的创始人麦克尔·维德纽斯以 MySQL 为基础,创建了 [MariaDB](https://zh.wikipedia.org/wiki/MariaDB)(以他女儿的名字命名的数据库)分支。有许多原来使用 MySQL 数据库的公司(例如:维基百科)已经陆续完成了从 MySQL 数据库到 MariaDB 数据库的迁移。 - -### 安装 MySQL - -#### Windows 环境 - -1. 通过[官方网站](https://www.mysql.com/)提供的[下载链接](https://dev.mysql.com/downloads/windows/installer/8.0.html)下载“MySQL社区版服务器”安装程序,如下图所示,建议大家下载离线安装版的MySQL Installer。 - - - -2. 运行 Installer,按照下面的步骤进行安装。 - - - 选择自定义安装。 - - +甲骨文公司收购后昇阳微系统公司,大幅调涨 MySQL 商业版的售价,且甲骨文公司不再支持另一个自由软件项目 [OpenSolaris ](https://zh.wikipedia.org/wiki/OpenSolaris)的发展,因此导致自由软件社区对于 Oracle 是否还会持续支持 MySQL 社区版(MySQL 的各个发行版本中唯一免费的版本)有所担忧,MySQL 的创始人麦克尔·维德纽斯以 MySQL 为基础,创建了 [MariaDB](https://zh.wikipedia.org/wiki/MariaDB)(以他女儿的名字命名的数据库)分支。有许多原来使用 MySQL 数据库的公司(例如:维基百科)已经陆续完成了从 MySQL 数据库到 MariaDB 数据库的迁移。 - - 选择需要安装的组件。 +## 安装 MySQL - +### Windows 环境 - - 如果缺少依赖项,需要先安装依赖项。 +1. 通过[官方网站](https://www.mysql.com/)提供的[下载链接](https://dev.mysql.com/downloads/windows/installer/8.0.html)下载“MySQL社区版服务器”安装程序,如下图所示,建议大家下载离线安装版的MySQL Installer。 - + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105230905.png) +2. 运行 Installer,按照下面的步骤进行安装。 - - 准备开始安装。 + * 选择自定义安装。 - + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105231152.jpg) - - 安装完成。 + * 选择需要安装的组件。 - + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105231255.jpg) - - 准备执行配置向导。 + * 如果缺少依赖项,需要先安装依赖项。 - + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105231620.png) -3. 执行安装后的配置向导。 + * 准备开始安装。 - - 配置服务器类型和网络。 + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105231719.jpg) - + * 安装完成。 - - 配置认证方法(保护密码的方式)。 + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105232024.jpg) - + * 准备执行配置向导。 - - 配置用户和角色。 + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105231815.jpg) +3. 执行安装后的配置向导。 - + * 配置服务器类型和网络。 - - 配置Windows服务名以及是否开机自启。 + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105232109.jpg) - + * 配置认证方法(保护密码的方式)。 - - 配置日志。 + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105232408.jpg) + * 配置用户和角色。 - + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105232521.jpg) + * 配置Windows服务名以及是否开机自启。 - - 配置高级选项。 + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105232608.jpg) + * 配置日志。 - ACAC15B8633133B65476286A49BFBD7E + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105232641.jpg) + * 配置高级选项。 - - 应用配置。 + ![ACAC15B8633133B65476286A49BFBD7E](https://gitee.com/jackfrued/mypic/raw/master/20211105232724.jpg) + * 应用配置。 - - -4. 可以在 Windows 系统的“服务”窗口中启动或停止 MySQL。 - - + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105232800.jpg) +4. 可以在 Windows 系统的“服务”窗口中启动或停止 MySQL。 + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105232926.jpg) 5. 配置 PATH 环境变量,以便在命令行提示符窗口使用 MySQL 客户端工具。 + * 打开 Windows 的“系统”窗口并点击“高级系统设置”。 - - 打开 Windows 的“系统”窗口并点击“高级系统设置”。 - - - - - 在“系统属性”的“高级”窗口,点击“环境变量”按钮。 + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105233054.jpg) + * 在“系统属性”的“高级”窗口,点击“环境变量”按钮。 - + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105233312.jpg) + * 修改PATH环境变量,将MySQL安装路径下的`bin`文件夹的路径配置到PATH环境变量中。 - - 修改PATH环境变量,将MySQL安装路径下的`bin`文件夹的路径配置到PATH环境变量中。 + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105233359.jpg) + * 配置完成后,可以尝试在“命令提示符”下使用 MySQL 的命令行工具。 - + ![](https://gitee.com/jackfrued/mypic/raw/master/20211105233643.jpg) - - 配置完成后,可以尝试在“命令提示符”下使用 MySQL 的命令行工具。 - - - -#### Linux 环境 +### Linux 环境 下面以 CentOS 7.x 环境为例,演示如何安装 MySQL 5.7.x,如果需要在其他 Linux 系统下安装其他版本的 MySQL,请读者自行在网络上查找对应的安装教程。 -1. 安装 MySQL。 - - 可以在 [MySQL 官方网站]()下载安装文件。首先在下载页面中选择平台和版本,然后找到对应的下载链接,直接下载包含所有安装文件的归档文件,解归档之后通过包管理工具进行安装。 - - ```Shell - wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.26-1.el7.x86_64.rpm-bundle.tar - tar -xvf mysql-5.7.26-1.el7.x86_64.rpm-bundle.tar - ``` +1. 安装 MySQL。 - 如果系统上有 MariaDB 相关的文件,需要先移除 MariaDB 相关的文件。 + 可以在 [MySQL 官方网站](https://www.mysql.com/)下载安装文件。首先在下载页面中选择平台和版本,然后找到对应的下载链接,直接下载包含所有安装文件的归档文件,解归档之后通过包管理工具进行安装。 - ```Shell - yum list installed | grep mariadb | awk '{print $1}' | xargs yum erase -y - ``` - - 更新和安装可能用到的底层依赖库。 - - ```Bash - yum update - yum install -y libaio libaio-devel - ``` + ```Shell + wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.26-1.el7.x86_64.rpm-bundle.tar + tar -xvf mysql-5.7.26-1.el7.x86_64.rpm-bundle.tar + ``` - 接下来可以按照如下所示的顺序用 RPM(Redhat Package Manager)工具安装 MySQL。 + 如果系统上有 MariaDB 相关的文件,需要先移除 MariaDB 相关的文件。 - ```Shell - rpm -ivh mysql-community-common-5.7.26-1.el7.x86_64.rpm - rpm -ivh mysql-community-libs-5.7.26-1.el7.x86_64.rpm - rpm -ivh mysql-community-libs-compat-5.7.26-1.el7.x86_64.rpm - rpm -ivh mysql-community-devel-5.7.26-1.el7.x86_64.rpm - rpm -ivh mysql-community-client-5.7.26-1.el7.x86_64.rpm - rpm -ivh mysql-community-server-5.7.26-1.el7.x86_64.rpm - ``` + ```Shell + yum list installed | grep mariadb | awk '{print $1}' | xargs yum erase -y + ``` - 可以使用下面的命令查看已经安装的 MySQL 相关的包。 + 更新和安装可能用到的底层依赖库。 - ```Shell - rpm -qa | grep mysql - ``` + ```Bash + yum update + yum install -y libaio libaio-devel + ``` -2. 配置 MySQL。 + 接下来可以按照如下所示的顺序用 RPM(Redhat Package Manager)工具安装 MySQL。 - MySQL 的配置文件在`/etc`目录下,名为`my.cnf`,默认的配置文件内容如下所示。 + ```Shell + rpm -ivh mysql-community-common-5.7.26-1.el7.x86_64.rpm + rpm -ivh mysql-community-libs-5.7.26-1.el7.x86_64.rpm + rpm -ivh mysql-community-libs-compat-5.7.26-1.el7.x86_64.rpm + rpm -ivh mysql-community-devel-5.7.26-1.el7.x86_64.rpm + rpm -ivh mysql-community-client-5.7.26-1.el7.x86_64.rpm + rpm -ivh mysql-community-server-5.7.26-1.el7.x86_64.rpm + ``` - ```Shell - cat /etc/my.cnf - ``` + 可以使用下面的命令查看已经安装的 MySQL 相关的包。 - ```INI - # For advice on how to change settings please see - # http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html - - [mysqld] - # - # Remove leading # and set to the amount of RAM for the most important data - # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%. - # innodb_buffer_pool_size = 128M - # - # Remove leading # to turn on a very important data integrity option: logging - # changes to the binary log between backups. - # log_bin - # - # Remove leading # to set options mainly useful for reporting servers. - # The server defaults are faster for transactions and fast SELECTs. - # Adjust sizes as needed, experiment to find the optimal values. - # join_buffer_size = 128M - # sort_buffer_size = 2M - # read_rnd_buffer_size = 2M - datadir=/var/lib/mysql - socket=/var/lib/mysql/mysql.sock - - # Disabling symbolic-links is recommended to prevent assorted security risks - symbolic-links=0 - - log-error=/var/log/mysqld.log - pid-file=/var/run/mysqld/mysqld.pid - ``` + ```Shell + rpm -qa | grep mysql + ``` +2. 配置 MySQL。 - 通过配置文件,我们可以修改 MySQL 服务使用的端口、字符集、最大连接数、套接字队列大小、最大数据包大小、日志文件的位置、日志过期时间等配置。当然,我们还可以通过修改配置文件来对 MySQL 服务器进行性能调优和安全管控。 + MySQL 的配置文件在`/etc`目录下,名为`my.cnf`,默认的配置文件内容如下所示。 -3. 启动 MySQL 服务。 + ```Shell + cat /etc/my.cnf + ``` - 可以使用下面的命令来启动 MySQL。 + ```INI + # For advice on how to change settings please see + # http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html + + [mysqld] + # + # Remove leading # and set to the amount of RAM for the most important data + # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%. + # innodb_buffer_pool_size = 128M + # + # Remove leading # to turn on a very important data integrity option: logging + # changes to the binary log between backups. + # log_bin + # + # Remove leading # to set options mainly useful for reporting servers. + # The server defaults are faster for transactions and fast SELECTs. + # Adjust sizes as needed, experiment to find the optimal values. + # join_buffer_size = 128M + # sort_buffer_size = 2M + # read_rnd_buffer_size = 2M + datadir=/var/lib/mysql + socket=/var/lib/mysql/mysql.sock + + # Disabling symbolic-links is recommended to prevent assorted security risks + symbolic-links=0 + + log-error=/var/log/mysqld.log + pid-file=/var/run/mysqld/mysqld.pid + ``` - ```Shell - service mysqld start - ``` + 通过配置文件,我们可以修改 MySQL 服务使用的端口、字符集、最大连接数、套接字队列大小、最大数据包大小、日志文件的位置、日志过期时间等配置。当然,我们还可以通过修改配置文件来对 MySQL 服务器进行性能调优和安全管控。 +3. 启动 MySQL 服务。 - 在 CentOS 7 中,更推荐使用下面的命令来启动 MySQL。 + 可以使用下面的命令来启动 MySQL。 - ```Shell - systemctl start mysqld - ``` + ```Shell + service mysqld start + ``` - 启动 MySQL 成功后,可以通过下面的命令来检查网络端口使用情况,MySQL 默认使用`3306`端口。 + 在 CentOS 7 中,更推荐使用下面的命令来启动 MySQL。 - ```Shell - netstat -ntlp | grep mysql - ``` + ```Shell + systemctl start mysqld + ``` - 也可以使用下面的命令查找是否有名为`mysqld`的进程。 + 启动 MySQL 成功后,可以通过下面的命令来检查网络端口使用情况,MySQL 默认使用`3306`端口。 - ```Shell - pgrep mysqld - ``` + ```Shell + netstat -ntlp | grep mysql + ``` -4. 使用 MySQL 客户端工具连接服务器。 + 也可以使用下面的命令查找是否有名为`mysqld`的进程。 - 命令行工具: + ```Shell + pgrep mysqld + ``` +4. 使用 MySQL 客户端工具连接服务器。 - ```Shell - mysql -u root -p - ``` + 命令行工具: - > 说明:启动客户端时,`-u`参数用来指定用户名,MySQL 默认的超级管理账号为`root`;`-p`表示要输入密码(用户口令);如果连接的是其他主机而非本机,可以用`-h`来指定连接主机的主机名或IP地址。 + ```Shell + mysql -u root -p + ``` - 如果是首次安装 MySQL,可以使用下面的命令来找到默认的初始密码。 + > 说明:启动客户端时,`-u`参数用来指定用户名,MySQL 默认的超级管理账号为`root`;`-p`表示要输入密码(用户口令);如果连接的是其他主机而非本机,可以用`-h`来指定连接主机的主机名或IP地址。 - ```Shell - cat /var/log/mysqld.log | grep password - ``` + 如果是首次安装 MySQL,可以使用下面的命令来找到默认的初始密码。 - 上面的命令会查看 MySQL 的日志带有`password`的行,在显示的结果中`root@localhost:`后面的部分就是默认设置的初始密码。 + ```Shell + cat /var/log/mysqld.log | grep password + ``` - 进入客户端工具后,可以通过下面的指令来修改超级管理员(root)的访问口令为`123456`。 + 上面的命令会查看 MySQL 的日志带有`password`的行,在显示的结果中`root@localhost:`后面的部分就是默认设置的初始密码。 - ```SQL - set global validate_password_policy=0; - set global validate_password_length=6; - alter user 'root'@'localhost' identified by '123456'; - ``` + 进入客户端工具后,可以通过下面的指令来修改超级管理员(root)的访问口令为`123456`。 - > **说明**:MySQL 较新的版本默认不允许使用弱口令作为用户口令,所以上面的代码修改了验证用户口令的策略和口令的长度。事实上我们不应该使用弱口令,因为存在用户口令被暴力破解的风险。近年来,**攻击数据库窃取数据和劫持数据库勒索比特币**的事件屡见不鲜,要避免这些潜在的风险,最为重要的一点是**不要让数据库服务器暴露在公网上**(最好的做法是将数据库置于内网,至少要做到不向公网开放数据库服务器的访问端口),另外要保管好`root`账号的口令,应用系统需要访问数据库时,通常不使用`root`账号进行访问,而是**创建其他拥有适当权限的账号来访问**。 + ```SQL + set global validate_password_policy=0; + set global validate_password_length=6; + alter user 'root'@'localhost' identified by '123456'; + ``` - 再次使用客户端工具连接 MySQL 服务器时,就可以使用新设置的口令了。在实际开发中,为了方便用户操作,可以选择图形化的客户端工具来连接 MySQL 服务器,包括: + > **说明**:MySQL 较新的版本默认不允许使用弱口令作为用户口令,所以上面的代码修改了验证用户口令的策略和口令的长度。事实上我们不应该使用弱口令,因为存在用户口令被暴力破解的风险。近年来,**攻击数据库窃取数据和劫持数据库勒索比特币**的事件屡见不鲜,要避免这些潜在的风险,最为重要的一点是**不要让数据库服务器暴露在公网上**(最好的做法是将数据库置于内网,至少要做到不向公网开放数据库服务器的访问端口),另外要保管好`root`账号的口令,应用系统需要访问数据库时,通常不使用`root`账号进行访问,而是**创建其他拥有适当权限的账号来访问**。 - - MySQL Workbench(官方工具) + 再次使用客户端工具连接 MySQL 服务器时,就可以使用新设置的口令了。在实际开发中,为了方便用户操作,可以选择图形化的客户端工具来连接 MySQL 服务器,包括: - + * MySQL Workbench(官方工具) - - Navicat for MySQL(界面简单友好) + ![](https://gitee.com/jackfrued/mypic/raw/master/20211106063939.png) + * Navicat for MySQL(界面简单友好) - - + ![](https://gitee.com/jackfrued/mypic/raw/master/20210521152457.png) -#### macOS环境 +### macOS环境 macOS 系统安装 MySQL 是比较简单的,只需要从刚才说到的官方网站下载 DMG 安装文件并运行就可以了,下载的时候需要根据自己使用的是 Intel 的芯片还是苹果的 M1 芯片选择下载链接,如下图所示。 - +![](https://gitee.com/jackfrued/mypic/raw/master/20211121215901.png) 安装成功后,可以在“系统偏好设置”中找到“MySQL”,在如下所示的画面中,可以启动和停止 MySQL 服务器,也可以对 MySQL 核心文件的路径进行配置。 - +![](https://gitee.com/jackfrued/mypic/raw/master/20211121215153.png) -### MySQL 基本命令 +## MySQL 基本命令 -#### 查看命令 +### 查看命令 1. 查看所有数据库 @@ -330,59 +305,42 @@ show binary logs; show tables; ``` -#### 获取帮助 +### 获取帮助 在 MySQL 命令行工具中,可以使用`help`命令或`?`来获取帮助,如下所示。 -1. 查看`show`命令的帮助。 +1. 查看`show`命令的帮助。 ```MySQL ? show ``` - -2. 查看有哪些帮助内容。 +2. 查看有哪些帮助内容。 ```MySQL ? contents ``` - -3. 获取函数的帮助。 +3. 获取函数的帮助。 ```MySQL ? functions ``` - -4. 获取数据类型的帮助。 +4. 获取数据类型的帮助。 ```MySQL ? data types ``` -#### 其他命令 +### 其他命令 1. 新建/重建服务器连接 - `connect` / `resetconnection`。 - 2. 清空当前输入 - `\c`。在输入错误时,可以及时使用`\c`清空当前输入并重新开始。 - 3. 修改终止符(定界符)- `delimiter`。默认的终止符是`;`,可以使用该命令修改成其他的字符,例如修改为`$`符号,可以用`delimiter $`命令。 - 4. 打开系统默认编辑器 - `edit`。编辑完成保存关闭之后,命令行会自动执行编辑的内容。 - 5. 查看服务器状态 - `status`。 - 6. 修改默认提示符 - `prompt`。 - 7. 执行系统命令 - `system`。可以将系统命令跟在`system`命令的后面执行,`system`命令也可以缩写为`\!`。 - 8. 执行 SQL 文件 - `source`。`source`命令后面跟 SQL 文件路径。 - 9. 重定向输出 - `tee` / `notee`。可以将命令的输出重定向到指定的文件中。 - 10. 切换数据库 - `use`。 - 11. 显示警告信息 - `warnings`。 - 12. 退出命令行 - `quit`或`exit`。 - - - diff --git "a/Day41-55/41.Django\345\277\253\351\200\237\344\270\212\346\211\213.md" "b/Day41-55/41.Django\345\277\253\351\200\237\344\270\212\346\211\213.md" deleted file mode 100755 index ff50eb70ca..0000000000 --- "a/Day41-55/41.Django\345\277\253\351\200\237\344\270\212\346\211\213.md" +++ /dev/null @@ -1,339 +0,0 @@ -## Django快速上手 - -Web开发的早期阶段,开发者需要手动编写每个页面,例如一个新闻门户网站,每天都要修改它的HTML页面,随着网站规模和体量的增大,这种做法一定是非常糟糕的。为了解决这个问题,开发人员想到了用程序来为Web服务器生成动态内容,也就是说网页中的动态内容不再通过手动编写而是通过程序自动生成。最早的时候,这项技术被称为CGI(公共网关接口),当然随着时间的推移,CGI暴露出的问题也越来越多,例如大量重复的样板代码,总体性能较为低下等。在时代呼唤新英雄的背景下,PHP、ASP、JSP这类Web应用开发技术在上世纪90年代中后期如雨后春笋般涌现。通常我们说的Web应用是指通过浏览器来访问网络资源的应用程序,因为浏览器的普及性以及易用性,Web应用使用起来方便简单,免除了安装和更新应用程序带来的麻烦;站在开发者的角度,也不用关心用户使用什么样的操作系统,甚至不用区分是PC端还是移动端。 - -### Web应用机制和术语 - -下图向我们展示了Web应用的工作流程,其中涉及到的术语如下表所示。 - -![](./res/web-application.png) - -> 说明:相信有经验的读者会发现,这张图中其实还少了很多东西,例如反向代理服务器、数据库服务器、防火墙等,而且图中的每个节点在实际项目部署时可能是一组节点组成的集群。当然,如果你对这些没有什么概念也不要紧,继续下去就行了,后面会给大家一一讲解的。 - -| 术语 | 解释 | -| ------------- | ------------------------------------------------------------ | -| **URL/URI** | 统一资源定位符/统一资源标识符,网络资源的唯一标识 | -| **域名** | 与Web服务器地址对应的一个易于记忆的字符串名字 | -| **DNS** | 域名解析服务,可以将域名转换成对应的IP地址 | -| **IP地址** | 网络上的主机的身份标识,通过IP地址可以区分不同的主机 | -| **HTTP** | 超文本传输协议,构建在TCP之上的应用级协议,万维网数据通信的基础 | -| **反向代理** | 代理客户端向服务器发出请求,然后将服务器返回的资源返回给客户端 | -| **Web服务器** | 接受HTTP请求,然后返回HTML文件、纯文本文件、图像等资源给请求者 | -| **Nginx** | 高性能的Web服务器,也可以用作[反向代理](https://zh.wikipedia.org/wiki/%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86),[负载均衡](https://zh.wikipedia.org/wiki/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1) 和 [HTTP缓存](https://zh.wikipedia.org/wiki/HTTP%E7%BC%93%E5%AD%98) | - -#### HTTP协议 - -这里我们先费一些笔墨来说说HTTP这个协议。HTTP(超文本传输协议)是构建于TCP(传输控制协议)之上应用级协议,它利用了TCP提供的可靠的传输服务实现了Web应用中的数据交换。按照维基百科上的介绍,设计HTTP最初的目的是为了提供一种发布和接收[HTML](https://zh.wikipedia.org/wiki/HTML)页面的方法,也就是说这个协议是浏览器和Web服务器之间传输的数据的载体。关于这个协议的详细信息以及目前的发展状况,大家可以阅读[《HTTP 协议入门》](http://www.ruanyifeng.com/blog/2016/08/http.html)、[《互联网协议入门》](http://www.ruanyifeng.com/blog/2012/05/internet_protocol_suite_part_i.html)系列以及[《图解HTTPS协议》](http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html)这几篇文章进行了解。下图是我在四川省网络通信技术重点实验室学习和工作期间使用开源协议分析工具Ethereal(抓包工具WireShark的前身)截取的访问百度首页时的HTTP请求和响应的报文(协议数据),由于Ethereal截取的是经过网络适配器的数据,因此可以清晰的看到从物理链路层到应用层的协议数据。 - -HTTP请求(请求行+请求头+空行+[消息体]): - -![](./res/http-request.png) - -HTTP响应(响应行+响应头+空行+消息体): - -![](./res/http-response.png) - -> **说明**:这两张图是在2009年9月10日凌晨获得的,但愿这两张如同泛黄的照片般的截图能帮助你了解HTTP到底是什么样子的。当然,如果没有专业的抓包工具,也可以通过浏览器提供的“开发者工具”来查看HTTP请求和响应的数据格式。 - -### Django概述 - -Python的Web框架有上百个,比它的关键字还要多。所谓Web框架,就是用于开发Web服务器端应用的基础设施,说得通俗一点就是一系列封装好的模块和工具。事实上,即便没有Web框架,我们仍然可以通过socket或[CGI](https://zh.wikipedia.org/wiki/%E9%80%9A%E7%94%A8%E7%BD%91%E5%85%B3%E6%8E%A5%E5%8F%A3)来开发Web服务器端应用,但是这样做的成本和代价在商业项目中通常是不能接受的。通过Web框架,我们可以化繁为简,降低创建、更新、扩展应用程序的工作量。刚才我们说到Python有上百个Web框架,这些框架包括Django、Flask、Tornado、Sanic、Pyramid、Bottle、Web2py、web.py等。 - -在上述Python的Web框架中,Django无疑是最有代表性的重量级选手,开发者可以基于Django快速的开发可靠的Web应用程序,因为它减少了Web开发中不必要的开销,对常用的设计和开发模式进行了封装,并对MVC架构提供了支持(Django中称之为MTV架构)。MVC是软件系统开发领域中一种放之四海而皆准的架构,它将系统中的组件分为模型(Model)、视图(View)和控制器(Controller)三个部分并借此实现模型(数据)和视图(显示)的解耦合。由于模型和视图进行了分离,所以需要一个中间人将解耦合的模型和视图联系起来,扮演这个角色的就是控制器。稍具规模的软件系统都会使用MVC架构(或者是从MVC演进出的其他架构),Django项目中我们称之为MTV,MTV中的M跟MVC中的M没有区别,就是代表数据的模型,T代表了网页模板(显示数据的视图),而V代表了视图函数,在Django框架中,视图函数和Django框架本身一起扮演了MVC中C的角色。 - -![](./res/mvc.png) - -Django框架诞生于2003年,它是一个在真正的应用中成长起来的项目,由劳伦斯出版集团旗下在线新闻网站的内容管理系统(CMS)研发团队(主要是Adrian Holovaty和Simon Willison)开发,以比利时的吉普赛爵士吉他手Django Reinhardt来命名。Django框架在2005年夏天作为开源框架发布,使用Django框架能用很短的时间构建出功能完备的网站,因为它代替程序员完成了那些重复乏味的劳动,剩下真正有意义的核心业务给程序员来开发,这一点就是对DRY(Don't Repeat Yourself)理念的最好践行。许多成功的网站和应用都是基于Python语言进行开发的,国内比较有代表性的网站包括:知乎、豆瓣网、果壳网、搜狐闪电邮箱、101围棋网、海报时尚网、背书吧、堆糖、手机搜狐网、咕咚、爱福窝、果库等,其中不乏使用了Django框架的产品。 - -### 快速上手 - -#### 第一个Django项目 - -1. 检查Python环境:Django 1.11需要Python 2.7或Python 3.4以上的版本;Django 2.0需要Python 3.4以上的版本;Django 2.1和2.2需要Python 3.5以上的版本;Django 3.0需要Python 3.6以上版本。 - - > **说明**:Django框架不同版本所需的Python解释器环境,可以在Django官方文档的[FAQ](https://docs.djangoproject.com/zh-hans/3.0/faq/install/#faq-python-version-support)中找到。 - - 可以在macOS的终端中输入下面的命令检查Python解释器版本,Windows系统可以在命令行提示符中输入`python --version`。 - - ```Bash -python3 --version - ``` - - 也可以在Python的交互式环境中执行下面的代码来查看Python解释器的版本。 - - ```Shell - import sys - sys.version - sys.version_info - ``` - -2. 更新包管理工具并安装Django环境(用于创建Django项目)。 - - > **说明**:在更新这个文档时,Django最新的正式版本是3.0.7,Django 3.0提供了对ASGI的支持,可以实现全双工的异步通信,但是目前的使用体验一般,所以暂时不推荐大家使用Django 3.0,下面我们安装的是Django 2.2.13版本。使用`pip`安装三方库和工具时,可以通过`==`来指定安装的版本。 - - ```Bash - pip3 install -U pip - pip3 install django==2.2.13 - ``` - -3. 检查Django环境并使用`django-admin`命令创建Django项目(项目名称为hellodjango)。 - - ```Shell - django-admin --version - django-admin startproject hellodjango - ``` - -4. 用PyCharm打开创建好的Djang项目,并为其添加虚拟环境。 - - ![](res/pycharm-django-project.png) - - 如上图所示,PyCharm的项目浏览器中,最顶层的文件夹`hellodjango`是Python项目文件夹,这个文件夹的名字并不重要,Django项目也不关心这个文件夹叫什么名字。该文件夹下有一个同名的文件夹,它是Django项目文件夹,其中包含了`__init__.py`、`settings.py`、`urls.py`、`wsgi.py`四个文件,与名为`hellodjango`的Django项目文件夹同级的还有一个名为`manage.py` 的文件,这些文件的作用如下所示: - - - `hellodjango/__init__.py`:空文件,告诉Python解释器这个目录应该被视为一个Python的包。 - - `hellodjango/settings.py`:Django项目的配置文件。 - - `hellodjango/urls.py`:Django项目的URL映射声明,就像是网站的“目录”。 - - `hellodjango/wsgi.py`:项目运行在WSGI兼容Web服务器上的入口文件。 - - `manage.py`: 管理Django项目的脚本程序。 - - > 说明:WSGI全称是Web服务器网关接口,维基百科上给出的解释是“为Python语言定义的[Web服务器](https://zh.wikipedia.org/wiki/%E7%B6%B2%E9%A0%81%E4%BC%BA%E6%9C%8D%E5%99%A8)和[Web应用程序](https://zh.wikipedia.org/wiki/%E7%BD%91%E7%BB%9C%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F)或框架之间的一种简单而通用的接口”。 - - 创建虚拟环境的界面如下图所示。 - - ![pycharm-django-virtual-environment](res/pycharm-django-virtual-environment.png) - -5. 安装项目依赖项。 - - 方法一:打开PyCharm的终端,在终端中通过`pip`命令安装Django项目的依赖项。 - - > **说明**:由于已经基于Python 3解释器环境为项目创建了虚拟环境,所以虚拟环境中的`python`命令对应的是Python 3的解释器,而`pip`命令对应的是Python 3的包管理工具。 - - ```Shell - pip install django==2.2.13 - ``` - - 方法二:在PyCharm的偏好设置中,可以找到项目的解释器环境和已经安装的三方库,可以通过点击添加按钮来安装新的依赖项,需要提醒大家的是在安装Django依赖项时,需要指定版本号,否则将默认安装更新本文时最新的3.0.7版本。 - - ![](res/pycharm-install-django.png) - - 下图展示了Django版本和Python版本的对应关系,请大家自行对号入座。 - - | Django版本 | Python版本 | - | ---------- | ----------------------------------------- | - | 1.8 | 2.7、3.2、3.3、3.4、3.5 | - | 1.9、1.10 | 2.7、3.4、3.5 | - | 1.11 | 2.7、3.4、3.5、3.6、3.7(Django 1.11.17) | - | 2.0 | 3.4、3.5、3.6、3.7 | - | 2.1 | 3.5、3.6、3.7 | - | 2.2 | 3.5、3.6、3.7、3.8(Django 2.2.8) | - | 3.0 | 3.6、3.7、3.8 | - -6. 启动Django自带的服务器运行项目。 - - 方法一:在“Run”菜单选择“Edit Configuration”,配置“Django server”运行项目(适用于专业版PyCharm)。 - - ![](res/pycharm-django-server.png) - - 方法二:在“Run”菜单选择“Edit Configuration”,配置运行“Python”程序运行项目(适用于专业版和社区版PyCharm)。 - - ![](res/pycharm-python-manage.png) - - 方法三:在PyCharm的终端(Terminal)中通过命令运行项目(适用于专业版和社区版PyCharm)。 - - ```Shell - python manage.py runserver - ``` - -7. 查看运行效果。 - - 在浏览器中输入`http://127.0.0.1:8000`访问我们的服务器,效果如下图所示。 - - ![](./res/django-index-1.png) - - > **说明**: - > - > 1. 刚刚启动的Django自带的服务器只能用于开发和测试环境,因为这个服务器是纯Python编写的轻量级Web服务器,不适合在生产环境中使用。 - > 2. 如果修改了代码,不需要为了让修改的代码生效而重新启动Django自带的服务器。但是,在添加新的项目文件时,该服务器不会自动重新加载,这个时候就得手动重启服务器。 - > 3. 可以在终端中通过`python manage.py help`命令查看Django管理脚本程序可用的命令参数。 - > 4. 使用`python manage.py runserver`启动服务器时,可以在后面添加参数来指定IP地址和端口号,默认情况下启动的服务器将运行在本机的`8000`端口。 - > 5. 在终端中运行的服务器,可以通过Ctrl+C来停止它 。通过PyCharm的“运行配置”运行的服务器直接点击窗口上的关闭按钮就可以终止服务器的运行。 - > 6. 不能在同一个端口上启动多个服务器,因为会导致地址的冲突(端口是对IP地址的扩展,也是计算机网络地址的一部分)。 -8. 修改项目的配置文件`settings.py`。 - - Django是一个支持国际化和本地化的框架,因此刚才我们看到的Django项目的默认首页也是支持国际化的,我们可以通过修改配置文件将默认语言修改为中文,时区设置为东八区。 - - 找到修改前的配置(在`settings.py`文件第100行以后)。 - - ```Python - LANGUAGE_CODE = 'en-us' - TIME_ZONE = 'UTC' - ``` - - 修改为以下内容。 - - ```Python - LANGUAGE_CODE = 'zh-hans' - TIME_ZONE = 'Asia/Chongqing' - ``` - - 刷新刚才的页面,可以看到修改语言代码和时区之后的结果。 - - ![](./res/django-index-2.png) - -#### 创建自己的应用 - -如果要开发自己的Web应用,需要先在Django项目中创建“应用”,一个Django项目可以包含一个或多个应用。 - -1. 在PyCharm的终端中执行下面的命令,创建名为`first`的应用。 - - ```Shell - python manage.py startapp first - ``` - - 执行上面的命令会在当前路径下创建`first`目录,其目录结构如下所示: - - - `__init__.py`:一个空文件,告诉Python解释器这个目录应该被视为一个Python的包。 - - `admin.py`:可以用来注册模型,用于在Django框架自带的管理后台中管理模型。 - - `apps.py`:当前应用的配置文件。 - - `migrations`:存放与模型有关的数据库迁移信息。 - - `__init__.py`:一个空文件,告诉Python解释器这个目录应该被视为一个Python的包。 - - `models.py`:存放应用的数据模型(MTV中的M)。 - - `tests.py`:包含测试应用各项功能的测试类和测试函数。 - - `views.py`:处理用户HTTP请求并返回HTTP响应的函数或类(MTV中的V)。 - -2. 修改应用目录下的视图文件`views.py`。 - - ```Python - from django.http import HttpResponse - - - def show_index(request): - return HttpResponse('

Hello, Django!

') - ``` - -4. 修改Django项目目录下的`urls.py`文件,将视图函数和用户在浏览器中请求的路径对应。 - - ```Python - from django.contrib import admin - from django.urls import path, include - - from first.views import show_index - - urlpatterns = [ - path('admin/', admin.site.urls), - path('hello/', show_index), - ] - ``` - -5. 重新运行项目,并打开浏览器中访问`http://127.0.0.1:8000/hello/`。 - -5. 上面我们通过代码为浏览器生成了内容,但仍然是静态内容,如果要生成动态内容,可以修改`views.py`文件并添加如下所示的代码。 - - ```Python - from random import sample - - from django.http import HttpResponse - - - def show_index(request): - fruits = [ - 'Apple', 'Orange', 'Pitaya', 'Durian', 'Waxberry', 'Blueberry', - 'Grape', 'Peach', 'Pear', 'Banana', 'Watermelon', 'Mango' - ] - selected_fruits = sample(fruits, 3) - content = '

今天推荐的水果是:

' - content += '
' - content += '
    ' - for fruit in selected_fruits: - content += f'
  • {fruit}
  • ' - content += '
' - return HttpResponse(content) - ``` - -6. 刷新页面查看程序的运行结果,看看每次刷新的网页的时候,是不是可以看到不一样的内容。 - - -#### 使用模板 - -上面通过拼接HTML代码的方式为浏览器生成动态内容的做法在实际开发中是无能接受的,因为实际项目中的前端页面可能非常复杂,无法用这种拼接动态内容的方式来完成,这一点大家一定能够想到。为了解决这个问题,我们可以提前准备一个模板页(MTV中的T),所谓模板页就是一个带占位符和模板指令的HTML页面。 - -Django框架中有一个名为`render`的便捷函数可以来完成渲染模板的操作。所谓的渲染就是用数据替换掉模板页中的模板指令和占位符,当然这里的渲染称为后端渲染,即在服务器端完成页面的渲染再输出到浏览器中。后端渲染的做法在Web应用的访问量较大时,会让服务器承受较大的负担,所以越来越多的Web应用会选择前端渲染的方式,即服务器只提供页面所需的数据(通常是JSON格式),在浏览器中通过JavaScript代码获取这些数据并渲染页面上。关于前端渲染的内容,我们会在后续的课程中为大家讲解,目前我们使用的是通过模板页进行后端渲染的做法,具体步骤如下所示。 - -使用模板页的步骤如下所示。 - -1. 在项目目录下创建名为templates文件夹。 - - ![](res/pycharm-django-template.png) - -2. 添加模板页`index.html`。 - - > **说明**:实际项目开发中,静态页由前端开发者提供,后端开发者需要将静态页修改为模板页,以便通过Python程序对其进行渲染,这种做法就是上面提到的后端渲染。 - - ```HTML - - - - - 首页 - - - -

今天推荐的水果是:

-
-
    - {% for fruit in fruits %} -
  • {{ fruit }}
  • - {% endfor %} -
- - - ``` - 在上面的模板页中我们使用了`{{ fruit }}`这样的模板占位符语法,也使用了`{% for %}`这样的模板指令,这些都是Django模板语言(DTL)的一部分。关于模板语法和指令,大家可以看看官方文档,相信这些内容还是很容易理解的,并不需要过多的赘述,大家也可以参考[官方文档]()了解模板指令和语法。 - -3. 修改`views.py`文件,调用`render`函数渲染模板页。 - - ```Python - from random import sample - - from django.shortcuts import render - - - def show_index(request): - fruits = [ - 'Apple', 'Orange', 'Pitaya', 'Durian', 'Waxberry', 'Blueberry', - 'Grape', 'Peach', 'Pear', 'Banana', 'Watermelon', 'Mango' - ] - selected_fruits = sample(fruits, 3) - return render(request, 'index.html', {'fruits': selected_fruits}) - ``` - - `render`函数的第一个参数是请求对象request,第二个参数是我们要渲染的模板页的名字,第三个参数是要渲染到页面上的数据,我们通过一个字典将数据交给模板页,字典中的键就是模板页中使用的模板指令或占位符中的变量名。 - -4. 到此为止,视图函数中的`render`还无法找到模板文件`index.html`,需要修改`settings.py`文件,配置模板文件所在的路径。修改`settings.py`文件,找到`TEMPLATES`配置,修改其中的`DIRS`配置。 - - ```Python - TEMPLATES = [ - { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [os.path.join(BASE_DIR, 'templates'), ], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - ], - }, - }, - ] - ``` - -5. 重新运行项目或直接刷新页面查看结果。 - -### 总结 - -至此,我们已经利用Django框架完成了一个非常小的Web应用,虽然它并没有任何的实际价值,但是可以通过这个项目对Django框架有一个感性的认识。学习Django最好的资料肯定是它的[官方文档](https://docs.djangoproject.com/zh-hans/2.0/),官方文档提供了对多国语言的支持,而且有新手教程引导初学者学习使用Django框架,建议大家通过阅读Django的官方文档来学习和使用这个框架。当然图灵社区出版的[《Django基础教程》](http://www.ituring.com.cn/book/2630)也是非常适合初学者的入门级读物,有兴趣的读者可以点击链接进行购买。 diff --git "a/Day41-55/42.\346\267\261\345\205\245\346\250\241\345\236\213.md" "b/Day41-55/42.\346\267\261\345\205\245\346\250\241\345\236\213.md" deleted file mode 100755 index dc9b86b1f6..0000000000 --- "a/Day41-55/42.\346\267\261\345\205\245\346\250\241\345\236\213.md" +++ /dev/null @@ -1,681 +0,0 @@ -## 深入模型 - -在上一个章节中,我们提到了Django是基于MVC架构的Web框架,MVC架构追求的是“模型”和“视图”的解耦合。所谓“模型”说得更直白一些就是数据(的表示),所以通常也被称作“数据模型”。在实际的项目中,数据模型通常通过数据库实现持久化操作,而关系型数据库在过去和当下都是持久化的首选方案,下面我们通过完成一个投票项目来讲解和模型相关的知识点。投票项目的首页会展示某在线教育平台所有的学科;点击学科可以查看到该学科的老师及其信息;用户登录后在查看老师的页面为老师投票,可以投赞成票和反对票;未登录的用户可以通过登录页进行登录;尚未注册的用户可以通过注册页输入个人信息进行注册。在这个项目中,我们使用MySQL数据库来实现数据持久化操作。 - -### 创建项目和应用 - -我们首先创建Django项目`vote`并为其添加虚拟环境和依赖项。接下来,在项目下创建名为`polls`的应用和保存模板页的文件夹`tempaltes`,项目文件夹的结构如下所示。 - -![](res/pycharm-vote-project.png) - -根据上面描述的项目需求,我们准备了四个静态页面,分别是展示学科的页面`subjects.html`,显示学科老师的页面`teachers.html`,登录页面`login.html`,注册页面`register.html`,稍后我们会将静态页修改为Django项目所需的模板页。 - -### 配置关系型数据库MySQL - -1. 在MySQL中创建数据库,创建用户,授权用户访问该数据库。 - - ```SQL - create database vote default charset utf8; - create user 'hellokitty'@'%' identified by 'Hellokitty.618'; - grant all privileges on vote.* to 'hellokitty'@'%'; - flush privileges; - ``` - -2. 在MySQL中创建保存学科和老师信息的二维表(保存用户信息的表稍后处理)。 - - ```SQL - use vote; - - -- 创建学科表 - create table `tb_subject` - ( - `no` integer auto_increment comment '学科编号', - `name` varchar(50) not null comment '学科名称', - `intro` varchar(1000) not null default '' comment '学科介绍', - `is_hot` boolean not null default 0 comment '是不是热门学科', - primary key (`no`) - ); - -- 创建老师表 - create table `tb_teacher` - ( - `no` integer auto_increment comment '老师编号', - `name` varchar(20) not null comment '老师姓名', - `sex` boolean not null default 1 comment '老师性别', - `birth` date not null comment '出生日期', - `intro` varchar(1000) not null default '' comment '老师介绍', - `photo` varchar(255) not null default '' comment '老师照片', - `gcount` integer not null default 0 comment '好评数', - `bcount` integer not null default 0 comment '差评数', - `sno` integer not null comment '所属学科', - primary key (`no`), - foreign key (`sno`) references `tb_subject` (`no`) - ); - ``` - -3. 在虚拟环境中安装连接MySQL数据库所需的依赖项。 - - ```Bash - pip install mysqlclient - ``` - - > **说明**:如果因为某些原因无法安装`mysqlclient`三方库,可以使用它的替代品`pymysql`,`pymysql`是用纯Python开发的连接MySQL的Python库,安装更容易成功,但是需要在Django项目文件夹的`__init__.py`中添加如下所示的代码。 - > - > ```Python - > import pymysql - > - > pymysql.install_as_MySQLdb() - > ``` - > - > 如果使用Django 2.2及以上版本,还会遇到PyMySQL跟Django框架的兼容性问题,兼容性问题会导致项目无法运行,需要按照GitHub上PyMySQL仓库[Issues](https://github.com/PyMySQL/PyMySQL/issues/790)中提供的方法进行处理。总体来说,使用`pymysql`会比较麻烦,强烈建议大家首选安装`mysqlclient`。 - -4. 修改项目的settings.py文件,首先将我们创建的应用`polls`添加已安装的项目(`INSTALLED_APPS`)中,然后配置MySQL作为持久化方案。 - - ```Python - INSTALLED_APPS = [ - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'polls', - ] - - DATABASES = { - 'default': { - # 数据库引擎配置 - 'ENGINE': 'django.db.backends.mysql', - # 数据库的名字 - 'NAME': 'vote', - # 数据库服务器的IP地址(本机可以写localhost或127.0.0.1) - 'HOST': 'localhost', - # 启动MySQL服务的端口号 - 'PORT': 3306, - # 数据库用户名和口令 - 'USER': 'hellokitty', - 'PASSWORD': 'Hellokitty.618', - # 数据库使用的字符集 - 'CHARSET': 'utf8', - # 数据库时间日期的时区设定 - 'TIME_ZONE': 'Asia/Chongqing', - } - } - ``` - - 在配置ENGINE属性时,常用的可选值包括: - - - `'django.db.backends.sqlite3'`:SQLite嵌入式数据库。 - - `'django.db.backends.postgresql'`:BSD许可证下发行的开源关系型数据库产品。 - - `'django.db.backends.mysql'`:甲骨文公司经济高效的数据库产品。 - - `'django.db.backends.oracle'`:甲骨文公司关系型数据库旗舰产品。 - - 其他的配置可以参考官方文档中[数据库配置](https://docs.djangoproject.com/zh-hans/2.0/ref/databases/#third-party-notes)的部分。 - -5. Django框架提供了ORM来解决数据持久化问题,ORM翻译成中文叫“对象关系映射”。因为Python是面向对象的编程语言,我们在Python程序中使用对象模型来保存数据,而关系型数据库使用关系模型,用二维表来保存数据,这两种模型并不匹配。使用ORM是为了实现对象模型到关系模型的**双向转换**,这样就不用在Python代码中书写SQL语句和游标操作,因为这些都会由ORM自动完成。利用Django的ORM,我们可以直接将刚才创建的学科表和老师表变成Django中的模型类。 - - ```Bash - python manage.py inspectdb > polls/models.py - ``` - - 我们可以对自动生成的模型类稍作调整,代码如下所示。 - - ```Python - from django.db import models - - - class Subject(models.Model): - no = models.AutoField(primary_key=True, verbose_name='编号') - name = models.CharField(max_length=50, verbose_name='名称') - intro = models.CharField(max_length=1000, verbose_name='介绍') - is_hot = models.BooleanField(verbose_name='是否热门') - - class Meta: - managed = False - db_table = 'tb_subject' - - - class Teacher(models.Model): - no = models.AutoField(primary_key=True, verbose_name='编号') - name = models.CharField(max_length=20, verbose_name='姓名') - sex = models.BooleanField(default=True, verbose_name='性别') - birth = models.DateField(verbose_name='出生日期') - intro = models.CharField(max_length=1000, verbose_name='个人介绍') - photo = models.ImageField(max_length=255, verbose_name='照片') - good_count = models.IntegerField(default=0, db_column='gcount', verbose_name='好评数') - bad_count = models.IntegerField(default=0, db_column='bcount', verbose_name='差评数') - subject = models.ForeignKey(Subject, models.DO_NOTHING, db_column='sno') - - class Meta: - managed = False - db_table = 'tb_teacher' - ``` - - > **说明**:模型类都直接或间接继承自`Model`类,模型类跟关系型数据库的二维表对应,模型对象跟表中的记录对应,模型对象的属性跟表中的字段对应。如果对上面模型类的属性定义不是特别理解,可以看看本文后面提供的“模型定义参考”部分的内容。 - -### 使用ORM完成模型的CRUD操作 - -有了Django框架的ORM,我们可以直接使用面向对象的方式来实现对数据的CRUD(增删改查)操作。我们可以在PyCharm的终端中输入下面的命令进入到Django项目的交互式环境,然后尝试对模型的操作。 - -```Bash -python manage.py shell -``` - -#### 新增 - -```Python -from polls.models import Subject - -subject1 = Subject(name='Python全栈开发', intro='当下最热门的学科', is_hot=True) -subject1.save() -subject2 = Subject(name='全栈软件测试', intro='学习自动化测试的学科', is_hot=False) -subject2.save() -subject3 = Subject(name='JavaEE分布式开发', intro='基于Java语言的服务器应用开发', is_hot=True) -``` - -#### 删除 - -```Python -subject = Subject.objects.get(no=2) -subject.delete() -``` - -#### 更新 - -```Shell -subject = Subject.objects.get(no=1) -subject.name = 'Python全栈+人工智能' -subject.save() -``` - -#### 查询 - -1. 查询所有对象。 - -```Shell -Subjects.objects.all() -``` - -2. 过滤数据。 - -```Shell -# 查询名称为“Python全栈+人工智能”的学科 -Subject.objects.filter(name='Python全栈+人工智能') - -# 查询名称包含“全栈”的学科(模糊查询) -Subject.objects.filter(name__contains='全栈') -Subject.objects.filter(name__startswith='全栈') -Subject.objects.filter(name__endswith='全栈') - -# 查询所有热门学科 -Subject.objects.filter(is_hot=True) - -# 查询编号大于3小于10的学科 -Subject.objects.filter(no__gt=3).filter(no__lt=10) -Subject.objects.filter(no__gt=3, no__lt=10) - -# 查询编号在3到7之间的学科 -Subject.objects.filter(no__ge=3, no__le=7) -Subject.objects.filter(no__range=(3, 7)) -``` - -3. 查询单个对象。 - -```Shell -# 查询主键为1的学科 -Subject.objects.get(pk=1) -Subject.objects.get(no=1) -Subject.objects.filter(no=1).first() -Subject.objects.filter(no=1).last() -``` - -4. 排序。 - -```Shell -# 查询所有学科按编号升序排列 -Subject.objects.order_by('no') -# 查询所有部门按部门编号降序排列 -Subject.objects.order_by('-no') -``` - -5. 切片(分页查询)。 - -```Shell -# 按编号从小到大查询前3个学科 -Subject.objects.order_by('no')[:3] -``` - -6. 计数。 - -```Python -# 查询一共有多少个学科 -Subject.objects.count() -``` - -7. 高级查询。 - -```Shell -# 查询编号为1的学科的老师 -Teacher.objects.filter(subject__no=1) -Subject.objects.get(pk=1).teacher_set.all() - -# 查询学科名称有“全栈”二字的学科的老师 -Teacher.objects.filter(subject__name__contains='全栈') -``` - -> **说明1**:由于老师与学科之间存在多对一外键关联,所以能通过学科反向查询到该学科的老师(从一对多关系中“一”的一方查询“多”的一方),反向查询属性默认的名字是`类名小写_set`(如上面例子中的`teacher_set`),当然也可以在创建模型时通过`ForeingKey`的`related_name`属性指定反向查询属性的名字。如果不希望执行反向查询可以将`related_name`属性设置为`'+'`或者以`'+'`开头的字符串。 - -> **说明2**:ORM查询多个对象时会返回QuerySet对象,QuerySet使用了惰性查询,即在创建QuerySet对象的过程中不涉及任何数据库活动,等真正用到对象时(对QuerySet求值)才向数据库发送SQL语句并获取对应的结果,这一点在实际开发中需要引起注意! - -> **说明3**:如果希望更新多条数据,不用先逐一获取模型对象再修改对象属性,可以直接使用QuerySet对象的`update()`方法一次性更新多条数据。 - - -### 利用Django后台管理模型 - -在创建好模型类之后,可以通过Django框架自带的后台管理应用(`admin`应用)实现对模型的管理。虽然实际应用中,这个后台可能并不能满足我们的需求,但是在学习Django框架时,我们可以利用`admin`应用来管理我们的模型,同时也通过它来了解一个项目的后台管理系统需要哪些功能。使用Django自带的`admin`应用步骤如下所示。 - -1. 将`admin`应用所需的表迁移到数据库中。`admin`应用本身也需要数据库的支持,而且在`admin`应用中已经定义好了相关的数据模型类,我们只需要通过模型迁移操作就能自动在数据库中生成所需的二维表。 - - ```Bash - python manage.py migrate - ``` - -2. 创建访问`admin`应用的超级用户账号,这里需要输入用户名、邮箱和口令。 - - ```Shell - python manage.py createsuperuser - ``` - - > **说明**:输入口令时没有回显也不能退格,需要一气呵成完成输入。 - -3. 运行项目,在浏览器中访问`http://127.0.0.1:8000/admin`,输入刚才创建的超级用户账号和密码进行登录。 - - ![](/Users/Hao/Desktop/Python-100-Days/Day41-55/res/django-admin-login.png) - - 登录后进入管理员操作平台。 - - ![](res/django-admin-apps.png) - - 注意,我们暂时还没能在`admin`应用中看到之前创建的模型类,为此需要在`polls`应用的`admin.py`文件中对需要管理的模型进行注册。 - -4. 注册模型类。 - - ```Python - from django.contrib import admin - - from polls.models import Subject, Teacher - - admin.site.register(Subject) - admin.site.register(Teacher) - ``` - - 注册模型类后,就可以在后台管理系统中看到它们。 - - ![](./res/django-admin-models.png) - -5. 对模型进行CRUD操作。 - - 可以在管理员平台对模型进行C(新增)、R(查看)、U(更新)、D(删除)操作,如下图所示。 - - - 添加学科。 - - ![](res/django-admin-add-model.png) - - - 查看所有学科。 - - ![](res/django-admin-view-models.png) - - - 删除和更新学科。 - - ![](res/django-admin-delete-update-model.png) - -6. 注册模型管理类。 - - 可能大家已经注意到了,刚才在后台查看部门信息的时候,显示的部门信息并不直观,为此我们再修改`admin.py`文件,通过注册模型管理类,可以在后台管理系统中更好的管理模型。 - - ```Python - from django.contrib import admin - - from polls.models import Subject, Teacher - - - class SubjectModelAdmin(admin.ModelAdmin): - list_display = ('no', 'name', 'intro', 'is_hot') - search_fields = ('name', ) - ordering = ('no', ) - - - class TeacherModelAdmin(admin.ModelAdmin): - list_display = ('no', 'name', 'sex', 'birth', 'good_count', 'bad_count', 'subject') - search_fields = ('name', ) - ordering = ('no', ) - - - admin.site.register(Subject, SubjectModelAdmin) - admin.site.register(Teacher, TeacherModelAdmin) - ``` - - ![](res/django-admin-view-models-subject.png) - - ![](res/django-admin-view-models-teacher.png) - - 为了更好的查看模型,我们为`Subject`类添加`__str__`魔法方法,并在该方法中返回学科名字。这样在如上图所示的查看老师的页面上显示老师所属学科时,就不再是`Subject object(1)`这样晦涩的信息,而是学科的名称。 - -### 实现学科页和老师页效果 - -1. 修改`polls/views.py`文件,编写视图函数实现对学科页和老师页的渲染。 - - ```Python - from django.shortcuts import render, redirect - - from polls.models import Subject, Teacher - - - def show_subjects(request): - subjects = Subject.objects.all().order_by('no') - return render(request, 'subjects.html', {'subjects': subjects}) - - - def show_teachers(request): - try: - sno = int(request.GET.get('sno')) - teachers = [] - if sno: - subject = Subject.objects.only('name').get(no=sno) - teachers = Teacher.objects.filter(subject=subject).order_by('no') - return render(request, 'teachers.html', { - 'subject': subject, - 'teachers': teachers - }) - except (ValueError, Subject.DoesNotExist): - return redirect('/') - ``` - -2. 修改`templates/subjects.html`和`templates/teachers.html`模板页。 - - `subjects.html` - - ```HTML - - - - - 学科信息 - - - -
- -

扣丁学堂所有学科

-
-
- {% for subject in subjects %} -
-
- {{ subject.name }} - {% if subject.is_hot %} - - {% endif %} -
-
{{ subject.intro }}
-
- {% endfor %} -
-
- - - ``` - - `teachers.html` - - ```HTML - - - - - 老师信息 - - - -
-

{{ subject.name }}学科的老师信息

-
- {% if not teachers %} -

暂无该学科老师信息

- {% endif %} - {% for teacher in teachers %} -
-
- -
-
-
- 姓名:{{ teacher.name }} - 性别:{{ teacher.sex | yesno:'男,女' }} - 出生日期:{{ teacher.birth | date:'Y年n月j日'}} -
-
{{ teacher.intro }}
-
- 好评 ({{ teacher.good_count }}) -      - 差评 {{ teacher.bad_count }}) -
-
-
- {% endfor %} - 返回首页 -
- - - ``` - -3. 修改`vote/urls.py`文件,实现映射URL。 - - ```Python - from django.contrib import admin - from django.urls import path - - from polls.views import show_subjects, show_teachers - - urlpatterns = [ - path('admin/', admin.site.urls), - path('', show_subjects), - path('teachers/', show_teachers), - ] - ``` - -到此为止,页面上需要的图片(静态资源)还没有能够正常展示,我们在下一章节中为大家介绍如何处理模板页上的需要的静态资源。 - -### 补充内容 - -#### Django模型最佳实践 - -1. 正确的为模型和关系字段命名。 -2. 设置适当的`related_name`属性。 -3. 用`OneToOneField`代替`ForeignKeyField(unique=True)`。 -4. 通过“迁移操作”(migrate)来添加模型。 -5. 用NoSQL来应对需要降低范式级别的场景。 -6. 如果布尔类型可以为空要使用`NullBooleanField`。 -7. 在模型中放置业务逻辑。 -8. 用`.DoesNotExists`取代`ObjectDoesNotExists`。 -9. 在数据库中不要出现无效数据。 -10. 不要对`QuerySet`调用`len()`函数。 -11. 将`QuerySet`的`exists()`方法的返回值用于`if`条件。 -12. 用`DecimalField`来存储货币相关数据而不是`FloatField`。 -13. 定义`__str__`方法。 -14. 不要将数据文件放在同一个目录中。 - -> **说明**:以上内容来自于STEELKIWI网站的[*Best Practice working with Django models in Python*](https://steelkiwi.com/blog/best-practices-working-django-models-python/),有兴趣的小伙伴可以阅读原文。 - -#### 模型定义参考 - -##### 字段 - -对字段名称的限制 - -- 字段名不能是Python的保留字,否则会导致语法错误 -- 字段名不能有多个连续下划线,否则影响ORM查询操作 - -Django模型字段类 - -| 字段类 | 说明 | -| ----------------------- | ------------------------------------------------------------ | -| `AutoField` | 自增ID字段 | -| `BigIntegerField` | 64位有符号整数 | -| `BinaryField` | 存储二进制数据的字段,对应Python的`bytes`类型 | -| `BooleanField` | 存储`True`或`False` | -| `CharField` | 长度较小的字符串 | -| `DateField` | 存储日期,有`auto_now`和`auto_now_add`属性 | -| `DateTimeField` | 存储日期和日期,两个附加属性同上 | -| `DecimalField` | 存储固定精度小数,有`max_digits`(有效位数)和`decimal_places`(小数点后面)两个必要的参数 | -| `DurationField` | 存储时间跨度 | -| `EmailField` | 与`CharField`相同,可以用`EmailValidator`验证 | -| `FileField` | 文件上传字段 | -| `FloatField` | 存储浮点数 | -| `ImageField` | 其他同`FileFiled`,要验证上传的是不是有效图像 | -| `IntegerField` | 存储32位有符号整数。 | -| `GenericIPAddressField` | 存储IPv4或IPv6地址 | -| `NullBooleanField` | 存储`True`、`False`或`null`值 | -| `PositiveIntegerField` | 存储无符号整数(只能存储正数) | -| `SlugField` | 存储slug(简短标注) | -| `SmallIntegerField` | 存储16位有符号整数 | -| `TextField` | 存储数据量较大的文本 | -| `TimeField` | 存储时间 | -| `URLField` | 存储URL的`CharField` | -| `UUIDField` | 存储全局唯一标识符 | - -##### 字段属性 - -通用字段属性 - -| 选项 | 说明 | -| ---------------- | ------------------------------------------------------------ | -| `null` | 数据库中对应的字段是否允许为`NULL`,默认为`False` | -| `blank` | 后台模型管理验证数据时,是否允许为`NULL`,默认为`False` | -| `choices` | 设定字段的选项,各元组中的第一个值是设置在模型上的值,第二值是人类可读的值 | -| `db_column` | 字段对应到数据库表中的列名,未指定时直接使用字段的名称 | -| `db_index` | 设置为`True`时将在该字段创建索引 | -| `db_tablespace` | 为有索引的字段设置使用的表空间,默认为`DEFAULT_INDEX_TABLESPACE` | -| `default` | 字段的默认值 | -| `editable` | 字段在后台模型管理或`ModelForm`中是否显示,默认为`True` | -| `error_messages` | 设定字段抛出异常时的默认消息的字典,其中的键包括`null`、`blank`、`invalid`、`invalid_choice`、`unique`和`unique_for_date` | -| `help_text` | 表单小组件旁边显示的额外的帮助文本。 | -| `primary_key` | 将字段指定为模型的主键,未指定时会自动添加`AutoField`用于主键,只读。 | -| `unique` | 设置为`True`时,表中字段的值必须是唯一的 | -| `verbose_name` | 字段在后台模型管理显示的名称,未指定时使用字段的名称 | - -`ForeignKey`属性 - -1. `limit_choices_to`:值是一个Q对象或返回一个Q对象,用于限制后台显示哪些对象。 -2. `related_name`:用于获取关联对象的关联管理器对象(反向查询),如果不允许反向,该属性应该被设置为`'+'`,或者以`'+'`结尾。 -3. `to_field`:指定关联的字段,默认关联对象的主键字段。 -4. `db_constraint`:是否为外键创建约束,默认值为`True`。 -5. `on_delete`:外键关联的对象被删除时对应的动作,可取的值包括`django.db.models`中定义的: - - `CASCADE`:级联删除。 - - `PROTECT`:抛出`ProtectedError`异常,阻止删除引用的对象。 - - `SET_NULL`:把外键设置为`null`,当`null`属性被设置为`True`时才能这么做。 - - `SET_DEFAULT`:把外键设置为默认值,提供了默认值才能这么做。 - -`ManyToManyField`属性 - -1. `symmetrical`:是否建立对称的多对多关系。 -2. `through`:指定维持多对多关系的中间表的Django模型。 -3. `throughfields`:定义了中间模型时可以指定建立多对多关系的字段。 -4. `db_table`:指定维持多对多关系的中间表的表名。 - -##### 模型元数据选项 - -| 选项 | 说明 | -| ----------------------- | ------------------------------------------------------------ | -| `abstract` | 设置为True时模型是抽象父类 | -| `app_label` | 如果定义模型的应用不在INSTALLED_APPS中可以用该属性指定 | -| `db_table` | 模型使用的数据表名称 | -| `db_tablespace` | 模型使用的数据表空间 | -| `default_related_name` | 关联对象回指这个模型时默认使用的名称,默认为_set | -| `get_latest_by` | 模型中可排序字段的名称。 | -| `managed` | 设置为True时,Django在迁移中创建数据表并在执行flush管理命令时把表移除 | -| `order_with_respect_to` | 标记对象为可排序的 | -| `ordering` | 对象的默认排序 | -| `permissions` | 创建对象时写入权限表的额外权限 | -| `default_permissions` | 默认为`('add', 'change', 'delete')` | -| `unique_together` | 设定组合在一起时必须独一无二的字段名 | -| `index_together` | 设定一起建立索引的多个字段名 | -| `verbose_name` | 为对象设定人类可读的名称 | -| `verbose_name_plural` | 设定对象的复数名称 | - -#### 查询参考 - -##### 按字段查找可以用的条件 - -1. `exact` / `iexact`:精确匹配/忽略大小写的精确匹配查询 -2. `contains` / `icontains` / `startswith` / `istartswith` / `endswith` / `iendswith`:基于`like`的模糊查询 -3. `in` :集合运算 -4. `gt` / `gte` / `lt` / `lte`:大于/大于等于/小于/小于等于关系运算 -5. `range`:指定范围查询(SQL中的`between…and…`) -6. `year` / `month` / `day` / `week_day` / `hour` / `minute` / `second`:查询时间日期 -7. `isnull`:查询空值(True)或非空值(False) -8. `search`:基于全文索引的全文检索(一般很少使用) -9. `regex` / `iregex`:基于正则表达式的模糊匹配查询 - - diff --git "a/Day41-55/54.\345\215\225\345\205\203\346\265\213\350\257\225.md" "b/Day41-55/54.\345\215\225\345\205\203\346\265\213\350\257\225.md" deleted file mode 100755 index 763300df96..0000000000 --- "a/Day41-55/54.\345\215\225\345\205\203\346\265\213\350\257\225.md" +++ /dev/null @@ -1,4 +0,0 @@ -## 单元测试 - -请各位读者移步到[《使用Django开发商业项目》](../Day91-100/95.使用Django开发商业项目.md)一文。 - diff --git "a/Day41-55/55.\351\241\271\347\233\256\344\270\212\347\272\277.md" "b/Day41-55/55.\351\241\271\347\233\256\344\270\212\347\272\277.md" deleted file mode 100755 index eac5b54527..0000000000 --- "a/Day41-55/55.\351\241\271\347\233\256\344\270\212\347\272\277.md" +++ /dev/null @@ -1,4 +0,0 @@ -## 项目上线 - -请各位读者移步到[《项目部署上线和性能调优》](../Day91-100/98.项目部署上线和性能调优.md)一文。 - diff --git "a/Day91-100/93.MySQL\346\200\247\350\203\275\344\274\230\345\214\226.md" "b/Day91-100/93.MySQL\346\200\247\350\203\275\344\274\230\345\214\226.md" deleted file mode 100755 index 22d656517c..0000000000 --- "a/Day91-100/93.MySQL\346\200\247\350\203\275\344\274\230\345\214\226.md" +++ /dev/null @@ -1,312 +0,0 @@ -## MySQL性能优化 - -### 基本原则 - -想要发挥 MySQL 的最佳性能,需要遵循 3 个基本使用原则。 - -1. 让MySQL回归存储的基本职能:MySQL 数据库只用于数据的存储,不进行数据的复杂计算,不承载业务逻辑,确保存储和计算分离; -2. 查询数据时,尽量单表查询,减少跨库查询和多表关联; -3. 杜绝大事务、大 SQL、大批量、大字段等一系列性能杀手。 - - 大事务:运行步骤较多,涉及的表和字段较多,容易造成资源的争抢,甚至形成死锁。一旦事务回滚,会导致资源占用时间过长。 - - 大 SQL:复杂的SQL意味着过多的表的关联,MySQL 数据库处理关联超过3张表以上的SQL时,占用资源多,性能低下。 - - 大批量:多条SQL一次性执行完成,可以减少一条条执行SQL产生的额外开销,但必须确保进行充分的测试,并且在业务低峰时段或者非业务时段执行。 - - 大字段:blob、text类型的大字段要尽量少用,必须要用时,尽量与主业务表分离,减少对这类字段的检索和更新。 - -### 建库建表 - -1. 必须指定默认存储引擎为 InnoDB,并且禁用 MyISAM 存储引擎,随着 MySQL 8.0 版本的发布,所有的数据字典表都已经转换成了 InnoDB,MyISAM 存储引擎已成为了历史。 -2. 默认字符集 UTF8mb4,以前版本的 UTF8 是 UTF8mb3,未包含个别特殊字符,新版本的 UTF8mb4 包含所有字符,官方强烈建议使用此字符集。 -3. 关闭区分大小写功能。设置参数`lower_case_table_names`的值为`1`,即可关闭区分大小写功能,即大写字母 T 和小写字母 t 一样。 -4. 存储过程、触发器、视图、event等功能尽量在程序中实现,一方面是为了存储和计算分离,另一方面是因为这些功能非常不完整,调试、排错、监控都非常困难,相关数据字典也不完善,存在潜在的风险。一般在生产数据库中,禁止使用。 -5. 单个数据库实例表数量控制在2000个以内。 - -#### InnoDB表的注意事项 - -1. 主键列使用`unsigned`整数,可以使用`auto_increment`,但是要禁止手动更新主键。 -2. 每个列都必须添加`comment`注释。 -3. 在建表时必须显示指定`engine`。 -4. 表必备三字段:`xxx_id`、 `xxx_create`、 `xxx_modified`。其中`xxx_id`为主键,类型`unsigned`整数类型(例如:`int unsigned`);`xxx_create`、`xxx_modified`的类型均为`datetime`类型,分别记录该条数据的创建时间、修改时间。 -5. 所有字段必须指定`not null`,为空值指定`default`值,因为MySQL难以优化`null`值,含`null`值的复合索引会失效,最终导致查询效率低。 -6. 单张表的字段数尽量空值在50个字段以内,如果字段过多可以考虑垂直拆分。 -7. 禁用`enum`和`set`类型,因为这样的类型兼容性不好且性能较差。 -8. 大文件不应该使用`blob`类型而是保存它们的路径,`blob`和`text`这样的类型会导致处理性能下降,全表扫描代价大大增加。 -9. 对货币等对精度敏感的数据,应该使用定点数(`decimal`)而不是浮点数(`float`)。 -10. 保存IP地址不要用`char(15)`,应该使用`int unsigned`,可以使用`inet_aton`和`inet_ntoa`函数实现整数和IP地址的转换。 - -### 使用索引 - -在前面[《关系型数据库MySQL》](../Day36-40/36-38.关系型数据库MySQL.md)一文中,我们已经讲到过索引的相关知识,这里我们做一个简单的回顾。 - -#### 索引的设计原则 - -1. 创建索引的列并不一定是`select`操作中要查询的列,最适合做索引的列是出现在`where`子句中经常用作筛选条件或连表子句中作为表连接条件的列。 -2. 具有唯一性的列,索引效果好;重复值较多的列,索引效果差。 -3. 如果为字符串类型创建索引,最好指定一个前缀长度,创建短索引。短索引可以减少磁盘I/O而且在做比较时性能也更好,更重要的是MySQL底层的高速索引缓存能够缓存更多的键值。 -4. 创建一个包含N列的复合索引(多列索引)时,相当于是创建了N个索引,此时应该利用最左前缀进行匹配。 -5. 不要过度使用索引。索引并不是越多越好,索引需要占用额外的存储空间而且会影响写操作的性能(插入、删除、更新数据时索引也需要更新)。MySQL在生成执行计划时,要考虑各个索引的使用,这个也是需要耗费时间的。 -6. 要注意可能使索引失效的场景,例如:模糊查询使用了前置通配符、使用负向条件进行查询等。 - -### 使用过程 - -过程,通常也称之为存储过程,它是事先编译好存储在数据库中的一组SQL的集合。调用存储过程可以简化应用程序开发人员的工作,减少与数据库服务器之间的通信,对于提升数据操作的性能是有帮助的,这些我们在之前的[《关系型数据库MySQL》](../Day36-40/36-38.关系型数据库MySQL.md)一文中已经提到过。 - -### 数据分区 - -MySQL支持做数据分区,通过分区可以存储更多的数据、优化查询,获得更大的吞吐量并快速删除过期的数据。关于这个知识点建议大家看看MySQL的[官方文档](https://dev.mysql.com/doc/refman/5.7/en/partitioning-overview.html)。数据分区有以下几种类型: - -1. RANGE分区:基于连续区间范围,把数据分配到不同的分区。 - - ```SQL - CREATE TABLE tb_emp ( - eno INT NOT NULL, - ename VARCHAR(20) NOT NULL, - job VARCHAR(10) NOT NULL, - hiredate DATE NOT NULL, - dno INT NOT NULL - ) - PARTITION BY RANGE( YEAR(hiredate) ) ( - PARTITION p0 VALUES LESS THAN (1960), - PARTITION p1 VALUES LESS THAN (1970), - PARTITION p2 VALUES LESS THAN (1980), - PARTITION p3 VALUES LESS THAN (1990), - PARTITION p4 VALUES LESS THAN MAXVALUE - ); - ``` - -2. LIST分区:基于枚举值的范围,把数据分配到不同的分区。 - -3. HASH分区 / KEY分区:基于分区个数,把数据分配到不同的分区。 - - ```SQL - CREATE TABLE tb_emp ( - eno INT NOT NULL, - ename VARCHAR(20) NOT NULL, - job VARCHAR(10) NOT NULL, - hiredate DATE NOT NULL, - dno INT NOT NULL - ) - PARTITION BY HASH(dno) - PARTITIONS 4; - ``` - -### SQL优化 - -1. 定位低效率的SQL语句 - 慢查询日志。 - - - 查看慢查询日志相关配置 - - ```SQL - mysql> show variables like 'slow_query%'; - +---------------------------+----------------------------------+ - | Variable_name | Value | - +---------------------------+----------------------------------+ - | slow_query_log | OFF | - | slow_query_log_file | /mysql/data/localhost-slow.log | - +---------------------------+----------------------------------+ - - mysql> show variables like 'long_query_time'; - +-----------------+-----------+ - | Variable_name | Value | - +-----------------+-----------+ - | long_query_time | 10.000000 | - +-----------------+-----------+ - ``` - - - 创建慢查询日志文件并修改所有者。 - - ```Bash - touch /var/log/mysqld-slow.log - chown mysql /var/log/mysqld-slow.log - ``` - - - 修改全局慢查询日志配置。 - - ```SQL - mysql> set global slow_query_log_file='/var/log/mysqld-slow.log' - mysql> set global slow_query_log='ON'; - mysql> set global long_query_time=1; - ``` - - - 或者直接修改MySQL配置文件启用慢查询日志。 - - ```INI - [mysqld] - slow_query_log=ON - slow_query_log_file=/var/log/mysqld-slow.log - long_query_time=1 - ``` - - > **注意**:修改了配置文件需要重启MySQL,CentOS上对应的命令是`systemctl restart mysqld`。 - -2. 通过`explain`了解SQL的执行计划。例如: - - ```SQL - explain select ename, job, sal from tb_emp where dno=20\G - *************************** 1. row *************************** - id: 1 - select_type: SIMPLE - table: tb_emp - type: ref - possible_keys: fk_emp_dno - key: fk_emp_dno - key_len: 5 - ref: const - rows: 7 - Extra: NULL - 1 row in set (0.00 sec) - ``` - - - `select_type`:查询类型(SIMPLE - 简单查询、PRIMARY - 主查询、UNION - 并集、SUBQUERY - 子查询)。 - - `table`:输出结果集的表。 - - `type`:访问类型(ALL - 全表查询性能最差、index、range、ref、eq_ref、const、NULL)。 - - `possible_keys`:查询时可能用到的索引。 - - `key`:实际使用的索引。 - - `key_len`:索引字段的长度。 - - `rows`:扫描的行数,行数越少肯定性能越好。 - - `extra`:额外信息。 - -3. 通过`show profiles`和`show profile for query`分析SQL。 - - MySQL从5.0.37开始支持剖面系统来帮助用户了解SQL执行性能的细节,可以通过下面的方式来查看MySQL是否支持和开启了剖面系统。 - - ```SQL - select @@have_profiling; - select @@profiling; - ``` - - 如果没有开启剖面系统,可以通过下面的SQL来打开它。 - - ```SQL - set profiling=1; - ``` - - 接下来就可以通过剖面系统来了解SQL的执行性能,例如: - - ```SQL - mysql> select count(*) from tb_emp; - +----------+ - | count(*) | - +----------+ - | 14 | - +----------+ - 1 row in set (0.00 sec) - - mysql> show profiles; - +----------+------------+-----------------------------+ - | Query_ID | Duration | Query | - +----------+------------+-----------------------------+ - | 1 | 0.00029600 | select count(*) from tb_emp | - +----------+------------+-----------------------------+ - 1 row in set, 1 warning (0.00 sec) - - mysql> show profile for query 1; - +----------------------+----------+ - | Status | Duration | - +----------------------+----------+ - | starting | 0.000076 | - | checking permissions | 0.000007 | - | Opening tables | 0.000016 | - | init | 0.000013 | - | System lock | 0.000007 | - | optimizing | 0.000005 | - | statistics | 0.000012 | - | preparing | 0.000010 | - | executing | 0.000003 | - | Sending data | 0.000070 | - | end | 0.000012 | - | query end | 0.000008 | - | closing tables | 0.000012 | - | freeing items | 0.000032 | - | cleaning up | 0.000013 | - +----------------------+----------+ - 15 rows in set, 1 warning (0.00 sec) - ``` - -4. 优化CRUD操作。 - - - 优化`insert`语句 - - 在`insert`语句后面跟上多组值进行插入在性能上优于分开`insert`。 - - 如果有多个连接向同一个表插入数据,使用`insert delayed`可以获得更好的性能。 - - 如果要从一个文本文件装载数据到表时,使用`load data infile`比`insert`性能好得多。 - - - 优化`order by`语句 - - - 如果`where`子句的条件和`order by`子句的条件相同,而且排序的顺序与索引的顺序相同,如果还同时满足排序字段都是升序或者降序,那么只靠索引就能完成排序。 - - - 优化`group by`语句 - - - 在使用`group by`子句分组时,如果希望避免排序带来的开销,可以用`order by null`禁用排序。 - - - 优化嵌套查询 - - - MySQL从4.1开始支持嵌套查询(子查询),这使得可以将一个查询的结果当做另一个查询的一部分来使用。在某些情况下,子查询可以被更有效率的连接查询取代,因为在连接查询时MySQL不需要在内存中创建临时表来完成这个逻辑上需要多个步骤才能完成的查询。 - - - 优化or条件 - - - 如果条件之间是`or`关系,则只有在所有条件都用到索引的情况下索引才会生效。 - - - 优化分页查询 - - - 分页查询时,一个比较头疼的事情是如同`limit 1000, 20`,此时MySQL已经排序出前1020条记录但是仅仅返回第1001到1020条记录,前1000条实际都用不上,查询和排序的代价非常高。一种常见的优化思路是在索引上完成排序和分页的操作,然后根据返回的结果做表连接操作来得到最终的结果,这样可以避免出现全表查询,也避免了外部排序。 - - ```SQL - select * from tb_emp order by ename limit 10000, 20; - select * from tb_emp t1 inner join (select eno from tb_emp order by ename limit 10000, 20) t2 on t1.eno=t2.eno; - ``` - - 上面的代码中,第2行SQL是优于第1行SQL的,当然我们的前提是已经在`ename`字段上创建了索引。 - - - 使用SQL提示 - - USE INDEX:建议MySQL使用指定的索引。 - - IGNORE INDEX:建议MySQL忽略掉指定的索引。 - - FORCE INDEX:强制MySQL使用指定的索引。 - -### 配置优化 - -可以使用下面的命令来查看MySQL服务器配置参数的默认值。 - -```SQL -show variables; -show variables like 'key_%'; -show variables like '%cache%'; -show variables like 'innodb_buffer_pool_size'; -``` - -通过下面的命令可以了解MySQL服务器运行状态值。 - -```SQL -show status; -show status like 'com_%'; -show status like 'innodb_%'; -show status like 'connections'; -show status like 'slow_queries'; -``` - -1. 调整`max_connections`:MySQL最大连接数量,默认151。在Linux系统上,如果内存足够且不考虑用户等待响应时间这些问题,MySQL理论上可以支持到万级连接,但是通常情况下,这个值建议控制在1000以内。 -2. 调整`back_log`:TCP连接的积压请求队列大小,通常是max_connections的五分之一,最大不能超过900。 -3. 调整`table_open_cache`:这个值应该设置为max_connections的N倍,其中N代表每个连接在查询时打开的表的最大个数。 -4. 调整`innodb_lock_wait_timeout`:该参数可以控制InnoDB事务等待行锁的时间,默认值是50ms,对于反馈响应要求较高的应用,可以将这个值调小避免事务长时间挂起;对于后台任务,可以将这个值调大来避免发生大的回滚操作。 -5. 调整`innodb_buffer_pool_size`:InnoDB数据和索引的内存缓冲区大小,以字节为单位,这个值设置得越高,访问表数据需要进行的磁盘I/O操作就越少,如果可能甚至可以将该值设置为物理内存大小的80%。 - -### 架构优化 - -1. 通过拆分提高表的访问效率。 - - 垂直拆分 - - 水平拆分 - -2. 逆范式理论。数据表设计的规范程度称之为范式(Normal Form),要提升表的规范程度通常需要将大表拆分为更小的表,范式级别越高数据冗余越小,而且在插入、删除、更新数据时出问题的可能性会大幅度降低,但是节省了空间就意味着查询数据时可能花费更多的时间,原来的单表查询可能会变成连表查询。为此,项目实践中我们通常会进行逆范式操作,故意降低范式级别增加冗余来减少查询的时间开销。 - - 1NF:列不能再拆分 - - 2NF:所有的属性都依赖于主键 - - 3NF:所有的属性都直接依赖于主键(消除传递依赖) - - BCNF:消除非平凡多值依赖 - -3. 使用中间表提高统计查询速度。 - - 使用`insert into 中间表 select ... where ...`这样的语句先将需要的数据筛选出来放到中间表中,然后再对中间表进行统计,避免不必要的运算和处理。 - -4. 主从复制和读写分离,具体内容请参考[《项目部署上线和性能调优》](./98.项目部署上线和性能调优.md)。 - -5. 配置MySQL集群。 - -> **说明**:本章内容参考了网易出品的《深入浅出MySQL》一书,该书和《高性能MySQL》一样,都对MySQL进行了深入细致的讲解,虽然总体感觉后者更加高屋建瓴,但是前者也算得上是提升MySQL技能的佳作(作者的文字功底稍显粗糙,深度也不及后者),建议有兴趣的读者可以阅读这两本书。 - diff --git "a/Day91-100/98.\351\241\271\347\233\256\351\203\250\347\275\262\344\270\212\347\272\277\345\222\214\346\200\247\350\203\275\350\260\203\344\274\230.md" "b/Day91-100/98.\351\241\271\347\233\256\351\203\250\347\275\262\344\270\212\347\272\277\345\222\214\346\200\247\350\203\275\350\260\203\344\274\230.md" deleted file mode 100755 index 785830deec..0000000000 --- "a/Day91-100/98.\351\241\271\347\233\256\351\203\250\347\275\262\344\270\212\347\272\277\345\222\214\346\200\247\350\203\275\350\260\203\344\274\230.md" +++ /dev/null @@ -1,883 +0,0 @@ -## 项目部署上线指南 - -### 准备上线 - -1. 上线前的检查工作。 - - ```Shell - python manage.py check --deploy - ``` - -2. 将DEBUG设置为False并配置ALLOWED_HOSTS。 - - ```Python - DEBUG = False - ALLOWED_HOSTS = ['*'] - ``` - -3. 安全相关的配置。 - - ```Python - # 保持HTTPS连接的时间 - SECURE_HSTS_SECONDS = 3600 - SECURE_HSTS_INCLUDE_SUBDOMAINS = True - SECURE_HSTS_PRELOAD = True - - # 自动重定向到安全连接 - SECURE_SSL_REDIRECT = True - - # 避免浏览器自作聪明推断内容类型 - SECURE_CONTENT_TYPE_NOSNIFF = True - - # 避免跨站脚本攻击 - SECURE_BROWSER_XSS_FILTER = True - - # COOKIE只能通过HTTPS进行传输 - SESSION_COOKIE_SECURE = True - CSRF_COOKIE_SECURE = True - - # 防止点击劫持攻击手段 - 修改HTTP协议响应头 - # 当前网站是不允许使用