├── .gitignore ├── README.md ├── docs └── zh_CN │ ├── .gitignore │ ├── Makefile │ ├── _disabled │ └── source │ │ ├── builtin-objects │ │ ├── float.rst │ │ └── index.rst │ │ ├── index.rst │ │ ├── object-model │ │ ├── index.rst │ │ ├── object-life-cycle.rst │ │ ├── overview.rst │ │ └── pyobject.rst │ │ └── virtual-machine │ │ └── interview.rst │ ├── _fragments │ ├── appendix.rst │ ├── disqus.rst │ ├── next-step-to-wechat-mp.rst │ ├── wechat-reward.rst │ └── zsxq.rst │ ├── _images │ ├── libs │ │ ├── html-table │ │ │ └── 997ad67a7f305a39e5a77e3bf86c7798.png │ │ ├── matplotlib │ │ │ └── index │ │ │ │ ├── 47e3e92e52e71feb5b01afe83a5b4135.png │ │ │ │ ├── 93498df23549c42e72dcd5361dce6f7b.png │ │ │ │ └── ca76641457d181dd6713f2f5d6681164.png │ │ └── openpyxl │ │ │ └── 004c33e629837e01938a4810910f17b2.png │ ├── practices │ │ ├── binary-release │ │ │ └── 3b69fba0e9d9577ba7b7f2746a61516b.png │ │ └── coding │ │ │ ├── 1327be41bba7074cb15bc7466bce83fe-tiny.svg │ │ │ ├── 1327be41bba7074cb15bc7466bce83fe.svg │ │ │ ├── 1b82a506c385957ce899d0d027fc7ab6.png │ │ │ ├── 1bd6bfa4291cea53ea102a6a05fcdba2.png │ │ │ ├── 29ffff6c6a7fe03e54c1add05b526211.svg │ │ │ ├── 3aa9e337e9deebd578cf1d687d0c936b.svg │ │ │ ├── 4ea27ce5fbce4c7b310a029edadb72a5.svg │ │ │ ├── 4f0bdb9aec64ab25376f46f560bbfd71.png │ │ │ ├── 6d5bf7af588decefa03e3796af6ed260.png │ │ │ ├── 7c5356851dd49d6dcf7d70564aa7be73.png │ │ │ ├── 7d2c3e4066b3a28b092def0e08edb384.png │ │ │ ├── 7f524be0e18ac44cc71276393e60718a.svg │ │ │ ├── 892499ea16f81e1f597c87e302b84fb4.svg │ │ │ ├── a55355eccc6d635eba72c147badf0c63.png │ │ │ ├── d77f60debd77d112c1b78f190b223ddd.png │ │ │ ├── e0dcdd21f0d34f879abcfeaeb33aa475.png │ │ │ ├── fb9147b0d0080d2759bbe1fefde6c2b1.svg │ │ │ └── fd3a4b1205b5bb1511ae43303a7275a3.png │ ├── source │ │ ├── builtin-objects │ │ │ └── float │ │ │ │ ├── 0c492e7b150cca14d7a970b47256676e.svg │ │ │ │ ├── 801e0c7131c1b8dd37bcbba8209a3c6c.svg │ │ │ │ ├── ddbb0877006e20ac126cd154a6c2b4bd.svg │ │ │ │ └── fe41f87c3ee5c2400511476d60ab4d1e.svg │ │ └── object-model │ │ │ ├── object-life-cycle │ │ │ ├── 03c8786d171b8e384c251410359c5534.png │ │ │ └── 12385f519697112a85e9a6a10044ab2f.svg │ │ │ ├── overview │ │ │ ├── 17f03f631e2abac6e8c5e02747b2ef40.svg │ │ │ ├── 22d0382e81f6de23ed983877bb42ecba.svg │ │ │ ├── 3f7447fb33ed1dc500b39e1332bf364f.svg │ │ │ ├── 448bc221c7548e3e05e0aae215e7e60e.png │ │ │ ├── 65fc5ff9a56a98eaf091102b463b42ff.svg │ │ │ ├── 74e6c3b3bf9bcdfd8911bff60595ad01.svg │ │ │ ├── 7d217c8c58dab4624208b04f50ab0ec0.svg │ │ │ ├── 91a5aa4a35b5edb01c5b5041887b18fd.png │ │ │ ├── adb61e45a487fe66d37810856d0667c4.svg │ │ │ ├── b28d8cfa7168543b878375c0e661c22d.svg │ │ │ ├── c429593b3aa1b16f9813d1b658e7ddec.png │ │ │ ├── d528a1c29fe1f100822b569c44db78ee.png │ │ │ ├── e49cd0fafc506f576b0c87ad8cae4925.png │ │ │ ├── ea1367b9738de0d0ab5e1d7df6d59b32.png │ │ │ └── ef2893471a35c80a4b03f179bf0ad123.png │ │ │ └── pyobject │ │ │ ├── 1165277301cb052cd36ef00b6ad142df.svg │ │ │ ├── 29c687effd0464eb074bf1aa7002fe21.svg │ │ │ ├── 3be2746586ad4fa2dce9d37ceba35fae.svg │ │ │ ├── 6607df6e351a7fbf68145ba0f7eb8c9b.svg │ │ │ ├── 7745cfb792be1483addf9c55e7100f28.svg │ │ │ └── b886457105881ce9b6fcffb0964f61db.svg │ └── tutorial │ │ ├── condition │ │ ├── 3f6deeb783d1d135880a8dd6776814aa.png │ │ ├── 5fcd46532e730e668245b18751491f55.webp │ │ ├── 755637ea7b53648f78032cff2fbe408a.svg │ │ ├── 761edd878643e26832d88b5f8ca0ad24.png │ │ └── 8e556101bb9b43a00dd325c6baee8b7a.png │ │ └── prepare │ │ ├── 103edcde70f4483d67d4bb57f4a7cfb8.png │ │ ├── 1279dc29cb3fb67995797b1a815c14e7.png │ │ ├── 183c7f22507364172b0c3dfe4bc630cb.png │ │ ├── 25e827b9d57fd969aff754c5eff991c7.png │ │ ├── 2b61abc3cbfe066babe267c1792c48fa.png │ │ ├── 328f3d36b38281c4e8610158c0ab531a.png │ │ ├── 359b20925aeaec421620f09d40739d8c.png │ │ ├── 8333a0438108a6918bb019f59915922c.png │ │ ├── 845b26786be67369999be4da7c63e8fa.png │ │ ├── 987c88e5e6860bc61280df7035adb73e.png │ │ ├── 9c993ff30d24652b983f83a8ba98fcec.png │ │ ├── bb0399070c7d32c0728a82160bea01ee.png │ │ ├── bc058ec0ac3b9c727de6aec8e8f40048.png │ │ ├── cdfc0bddc3e38e96ce9b509061c162c8.png │ │ ├── f07028520b90eb758cae80c85c0ed4ea.png │ │ ├── f9a8891083f963159dd1278164721add.png │ │ └── fcfab7c8303c418d371d288f66609ec6.png │ ├── _src │ ├── _static │ ├── css │ │ ├── hide-ad.css │ │ └── search-box.css │ ├── favicon.png │ ├── golang-core-course.jpg │ ├── linux-performance-course.jpg │ ├── logo.jpg │ ├── web-front-end-course.jpg │ ├── wechat-mp-qrcode.png │ ├── wechat-reward-g-concise.png │ ├── wechat-reward-g.png │ ├── wechat-reward-lnp.png │ ├── zedhz-course-qrcode.jpg │ └── zedhz-course.jpg │ ├── _templates │ ├── baidu_tongji.html │ ├── baidu_ziyuan.html │ ├── busuanzi.html │ ├── course-ad.html │ ├── course-ad2.html │ ├── disqus.html │ ├── google_analytics.html │ ├── layout.html │ ├── livere.html │ ├── more.html │ ├── reward.html │ ├── sf-namecard-fasionchan.html │ └── wechat-mp-qrcode.html │ ├── about │ ├── contact.rst │ └── index.rst │ ├── acknowledgements │ ├── index.rst │ └── shoulders.rst │ ├── appendices │ ├── index.rst │ └── resources.rst │ ├── conf.py │ ├── database │ ├── index.rst │ └── mongodb │ │ └── index.rst │ ├── deployment │ ├── index.rst │ └── pip-conf.rst │ ├── index.rst │ ├── interview │ └── index.rst │ ├── libs │ ├── exchangelib.rst │ ├── faker.rst │ ├── html-table.rst │ ├── index.rst │ ├── ipy.rst │ ├── kazoo.rst │ ├── matplotlib │ │ ├── index.rst │ │ └── issues.rst │ ├── openpyxl.rst │ ├── tabulate.rst │ └── zbarlight.rst │ ├── make.bat │ ├── practices │ ├── advanced-decorator.rst │ ├── argparse.rst │ ├── binary-release.rst │ ├── coding.rst │ ├── datetime.rst │ ├── debug-python-with-gdb.rst │ ├── index.rst │ ├── logging.rst │ ├── publish-package.rst │ ├── publish-package.rst.old │ ├── py2-encoding.rst │ └── string-similarity.rst │ ├── scripts │ ├── auto-build.sh │ ├── build-deploy.sh │ ├── build.sh │ └── setup.sh │ └── tutorial │ ├── arithmetic.rst │ ├── condition.rst │ ├── index.rst │ └── prepare.rst ├── readthedocs.yml ├── requirements ├── docs-dev.txt └── docs.txt └── src ├── .gitignore ├── libs ├── html-table │ └── fruit-output.py ├── matplotlib │ ├── font.py │ └── pie.py └── zbarlight │ ├── read_qrcode.py │ └── zedhz-course-qrcode.jpg ├── practices ├── argparse │ └── agentx.py ├── binary-release │ ├── checktime.py │ └── requirements.txt ├── citer │ └── 3 │ │ └── citer.c └── py2-encoding │ ├── say-hello-utf8-2.py │ ├── say-hello-utf8.py │ ├── say-hello.py │ └── stdio-encoding.py └── tutorial └── condition ├── pass-or-not.py ├── show-level.py └── whether-pass.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | .hypothesis/ 50 | .pytest_cache/ 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Django stuff: 57 | *.log 58 | local_settings.py 59 | db.sqlite3 60 | 61 | # Flask stuff: 62 | instance/ 63 | .webassets-cache 64 | 65 | # Scrapy stuff: 66 | .scrapy 67 | 68 | # Sphinx documentation 69 | docs/_build/ 70 | 71 | # PyBuilder 72 | target/ 73 | 74 | # Jupyter Notebook 75 | .ipynb_checkpoints 76 | 77 | # IPython 78 | profile_default/ 79 | ipython_config.py 80 | 81 | # pyenv 82 | .python-version 83 | 84 | # celery beat schedule file 85 | celerybeat-schedule 86 | 87 | # SageMath parsed files 88 | *.sage.py 89 | 90 | # Environments 91 | .env 92 | .venv 93 | env/ 94 | venv/ 95 | ENV/ 96 | env.bak/ 97 | venv.bak/ 98 | 99 | # Spyder project settings 100 | .spyderproject 101 | .spyproject 102 | 103 | # Rope project settings 104 | .ropeproject 105 | 106 | # mkdocs documentation 107 | /site 108 | 109 | # mypy 110 | .mypy_cache/ 111 | .dmypy.json 112 | dmypy.json 113 | 114 | # Pyre type checker 115 | .pyre/ 116 | 117 | *.swp 118 | 119 | .DS_Store 120 | .vscode/ 121 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python语言小册 2 | 3 | - [首页](https://python.fasionchan.com) 4 | - [快速入门](https://python.fasionchan.com/zh_CN/latest/tutorial/index.html) 5 | - [数据库操作](https://python.fasionchan.com/zh_CN/latest/database/index.html) 6 | - [最佳实践](https://python.fasionchan.com/zh_CN/latest/practices/index.html) 7 | - [推荐类库](https://python.fasionchan.com/zh_CN/latest/libs/index.html) 8 | - [部署方案](https://python.fasionchan.com/zh_CN/latest/deployment/index.html) 9 | - [面试题精选](https://python.fasionchan.com/zh_CN/latest/interview/index.html) 10 | 11 | 订阅更新,获取更多学习资料,请关注我们的 [微信公众号](https://network.fasionchan.com/zh_CN/latest/about/contact.html#wechat-mp) : 12 | 13 | ![小菜学编程](https://cdn.fasionchan.com/coding-fan-wechat-soso-qrcode.png?x-oss-process=image/resize,w_400) 14 | -------------------------------------------------------------------------------- /docs/zh_CN/.gitignore: -------------------------------------------------------------------------------- 1 | _build/ 2 | opt/ 3 | .todo 4 | -------------------------------------------------------------------------------- /docs/zh_CN/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = Python 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/zh_CN/_disabled/source/builtin-objects/index.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Author: fasion 3 | Created time: 2019-10-13 11:07:43 4 | Last Modified by: fasion 5 | Last Modified time: 2020-03-07 18:24:27 6 | 7 | ======== 8 | 内建对象 9 | ======== 10 | 11 | .. toctree:: 12 | :titlesonly: 13 | 14 | 从 float 对象开始探索 15 | -------------------------------------------------------------------------------- /docs/zh_CN/_disabled/source/index.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Author: fasion 3 | Created time: 2019-10-13 11:02:47 4 | Last Modified by: fasion 5 | Last Modified time: 2019-11-05 09:48:16 6 | 7 | ============== 8 | Python源码剖析 9 | ============== 10 | 11 | .. toctree:: 12 | :titlesonly: 13 | 14 | 对象模型 15 | 内建对象 16 | -------------------------------------------------------------------------------- /docs/zh_CN/_disabled/source/object-model/index.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Author: fasion 3 | Created time: 2019-10-13 11:07:43 4 | Last Modified by: fasion 5 | Last Modified time: 2019-10-20 15:28:06 6 | 7 | ======== 8 | 对象模型 9 | ======== 10 | 11 | .. toctree:: 12 | :titlesonly: 13 | 14 | 对象体系概述 15 | 揭开对象神秘的面纱 16 | 从创建到销毁,对象的生命周期 17 | -------------------------------------------------------------------------------- /docs/zh_CN/_disabled/source/virtual-machine/interview.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Author: fasion 3 | Created time: 2019-10-24 19:14:13 4 | Last Modified by: fasion 5 | Last Modified time: 2019-10-24 10:18:00 6 | 7 | ====================== 8 | 用字节码彻底征服面试官 9 | ====================== 10 | 11 | .. comments 12 | comment something out below 13 | 14 | - is vs == 15 | - swap 16 | - global 17 | - locals 18 | - 修饰器 19 | -------------------------------------------------------------------------------- /docs/zh_CN/_fragments/appendix.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Author: fasion 3 | Created time: 2020-03-21 18:18:09 4 | Last Modified by: fasion 5 | Last Modified time: 2020-03-21 18:35:24 6 | 7 | .. include:: /_fragments/next-step-to-wechat-mp.rst 8 | 9 | .. include:: /_fragments/zsxq.rst 10 | 11 | 创作不易,如果觉得我们写得还行,就请我们喝杯咖啡吧😋 12 | 13 | .. include:: /_fragments/wechat-reward.rst 14 | -------------------------------------------------------------------------------- /docs/zh_CN/_fragments/disqus.rst: -------------------------------------------------------------------------------- 1 | .. 评论系统 2 | Author: fasion 3 | Created time: 2018-03-26 21:33:34 4 | Last Modified by: fasion 5 | Last Modified time: 2020-03-20 11:13:08 6 | 7 | .. raw:: html 8 | 9 |
10 | 11 | .. comments 12 | comment something out below 13 | -------------------------------------------------------------------------------- /docs/zh_CN/_fragments/next-step-to-wechat-mp.rst: -------------------------------------------------------------------------------- 1 | .. 微信公众号 2 | Author: fasion 3 | Created time: 2018-02-01 20:13:35 4 | Last Modified by: fasion 5 | Last Modified time: 2020-03-18 08:29:32 6 | 7 | 订阅更新,获取更多学习资料,请关注我们的 :ref:`wechat-mp` : 8 | 9 | .. figure:: https://cdn.fasionchan.com/coding-fan-wechat-soso-qrcode.png 10 | :width: 428px 11 | :alt: 微信搜索:小菜学编程 12 | 13 | .. comments 14 | comment something out below 15 | -------------------------------------------------------------------------------- /docs/zh_CN/_fragments/wechat-reward.rst: -------------------------------------------------------------------------------- 1 | .. 给赞打赏 2 | Author: fasion 3 | Created time: 2018-02-03 20:16:18 4 | Last Modified by: fasion 5 | Last Modified time: 2020-03-18 08:32:24 6 | 7 | .. figure:: https://cdn.fasionchan.com/coding-fan-geizan.png 8 | :width: 340 9 | :alt: 微信搜索:小菜学编程 10 | 11 | .. comments 12 | comment something out blow 13 | -------------------------------------------------------------------------------- /docs/zh_CN/_fragments/zsxq.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Author: fasion 3 | Created time: 2020-03-21 18:32:00 4 | Last Modified by: fasion 5 | Last Modified time: 2020-03-21 18:32:35 6 | 7 | 如有疑问,请在公众号上留言,也可在 `知识星球 `_ 上提问: 8 | 9 | .. figure:: https://cdn.fasionchan.com/coding-fan-zsxq-qrcode-card.jpg 10 | :width: 345px 11 | :alt: 知识星球搜索:小菜学编程 12 | -------------------------------------------------------------------------------- /docs/zh_CN/_images/libs/html-table/997ad67a7f305a39e5a77e3bf86c7798.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/libs/html-table/997ad67a7f305a39e5a77e3bf86c7798.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/libs/matplotlib/index/47e3e92e52e71feb5b01afe83a5b4135.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/libs/matplotlib/index/47e3e92e52e71feb5b01afe83a5b4135.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/libs/matplotlib/index/93498df23549c42e72dcd5361dce6f7b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/libs/matplotlib/index/93498df23549c42e72dcd5361dce6f7b.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/libs/matplotlib/index/ca76641457d181dd6713f2f5d6681164.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/libs/matplotlib/index/ca76641457d181dd6713f2f5d6681164.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/libs/openpyxl/004c33e629837e01938a4810910f17b2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/libs/openpyxl/004c33e629837e01938a4810910f17b2.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/practices/binary-release/3b69fba0e9d9577ba7b7f2746a61516b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/practices/binary-release/3b69fba0e9d9577ba7b7f2746a61516b.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/practices/coding/1327be41bba7074cb15bc7466bce83fe.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/zh_CN/_images/practices/coding/1b82a506c385957ce899d0d027fc7ab6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/practices/coding/1b82a506c385957ce899d0d027fc7ab6.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/practices/coding/1bd6bfa4291cea53ea102a6a05fcdba2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/practices/coding/1bd6bfa4291cea53ea102a6a05fcdba2.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/practices/coding/29ffff6c6a7fe03e54c1add05b526211.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/zh_CN/_images/practices/coding/4f0bdb9aec64ab25376f46f560bbfd71.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/practices/coding/4f0bdb9aec64ab25376f46f560bbfd71.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/practices/coding/6d5bf7af588decefa03e3796af6ed260.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/practices/coding/6d5bf7af588decefa03e3796af6ed260.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/practices/coding/7c5356851dd49d6dcf7d70564aa7be73.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/practices/coding/7c5356851dd49d6dcf7d70564aa7be73.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/practices/coding/7d2c3e4066b3a28b092def0e08edb384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/practices/coding/7d2c3e4066b3a28b092def0e08edb384.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/practices/coding/892499ea16f81e1f597c87e302b84fb4.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/zh_CN/_images/practices/coding/a55355eccc6d635eba72c147badf0c63.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/practices/coding/a55355eccc6d635eba72c147badf0c63.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/practices/coding/d77f60debd77d112c1b78f190b223ddd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/practices/coding/d77f60debd77d112c1b78f190b223ddd.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/practices/coding/e0dcdd21f0d34f879abcfeaeb33aa475.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/practices/coding/e0dcdd21f0d34f879abcfeaeb33aa475.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/practices/coding/fd3a4b1205b5bb1511ae43303a7275a3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/practices/coding/fd3a4b1205b5bb1511ae43303a7275a3.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/source/object-model/object-life-cycle/03c8786d171b8e384c251410359c5534.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/source/object-model/object-life-cycle/03c8786d171b8e384c251410359c5534.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/source/object-model/overview/17f03f631e2abac6e8c5e02747b2ef40.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/zh_CN/_images/source/object-model/overview/22d0382e81f6de23ed983877bb42ecba.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/zh_CN/_images/source/object-model/overview/448bc221c7548e3e05e0aae215e7e60e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/source/object-model/overview/448bc221c7548e3e05e0aae215e7e60e.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/source/object-model/overview/65fc5ff9a56a98eaf091102b463b42ff.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/zh_CN/_images/source/object-model/overview/74e6c3b3bf9bcdfd8911bff60595ad01.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/zh_CN/_images/source/object-model/overview/91a5aa4a35b5edb01c5b5041887b18fd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/source/object-model/overview/91a5aa4a35b5edb01c5b5041887b18fd.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/source/object-model/overview/b28d8cfa7168543b878375c0e661c22d.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/zh_CN/_images/source/object-model/overview/c429593b3aa1b16f9813d1b658e7ddec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/source/object-model/overview/c429593b3aa1b16f9813d1b658e7ddec.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/source/object-model/overview/d528a1c29fe1f100822b569c44db78ee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/source/object-model/overview/d528a1c29fe1f100822b569c44db78ee.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/source/object-model/overview/e49cd0fafc506f576b0c87ad8cae4925.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/source/object-model/overview/e49cd0fafc506f576b0c87ad8cae4925.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/source/object-model/overview/ea1367b9738de0d0ab5e1d7df6d59b32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/source/object-model/overview/ea1367b9738de0d0ab5e1d7df6d59b32.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/source/object-model/overview/ef2893471a35c80a4b03f179bf0ad123.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/source/object-model/overview/ef2893471a35c80a4b03f179bf0ad123.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/condition/3f6deeb783d1d135880a8dd6776814aa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/condition/3f6deeb783d1d135880a8dd6776814aa.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/condition/5fcd46532e730e668245b18751491f55.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/condition/5fcd46532e730e668245b18751491f55.webp -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/condition/761edd878643e26832d88b5f8ca0ad24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/condition/761edd878643e26832d88b5f8ca0ad24.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/condition/8e556101bb9b43a00dd325c6baee8b7a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/condition/8e556101bb9b43a00dd325c6baee8b7a.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/prepare/103edcde70f4483d67d4bb57f4a7cfb8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/prepare/103edcde70f4483d67d4bb57f4a7cfb8.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/prepare/1279dc29cb3fb67995797b1a815c14e7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/prepare/1279dc29cb3fb67995797b1a815c14e7.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/prepare/183c7f22507364172b0c3dfe4bc630cb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/prepare/183c7f22507364172b0c3dfe4bc630cb.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/prepare/25e827b9d57fd969aff754c5eff991c7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/prepare/25e827b9d57fd969aff754c5eff991c7.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/prepare/2b61abc3cbfe066babe267c1792c48fa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/prepare/2b61abc3cbfe066babe267c1792c48fa.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/prepare/328f3d36b38281c4e8610158c0ab531a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/prepare/328f3d36b38281c4e8610158c0ab531a.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/prepare/359b20925aeaec421620f09d40739d8c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/prepare/359b20925aeaec421620f09d40739d8c.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/prepare/8333a0438108a6918bb019f59915922c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/prepare/8333a0438108a6918bb019f59915922c.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/prepare/845b26786be67369999be4da7c63e8fa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/prepare/845b26786be67369999be4da7c63e8fa.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/prepare/987c88e5e6860bc61280df7035adb73e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/prepare/987c88e5e6860bc61280df7035adb73e.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/prepare/9c993ff30d24652b983f83a8ba98fcec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/prepare/9c993ff30d24652b983f83a8ba98fcec.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/prepare/bb0399070c7d32c0728a82160bea01ee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/prepare/bb0399070c7d32c0728a82160bea01ee.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/prepare/bc058ec0ac3b9c727de6aec8e8f40048.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/prepare/bc058ec0ac3b9c727de6aec8e8f40048.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/prepare/cdfc0bddc3e38e96ce9b509061c162c8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/prepare/cdfc0bddc3e38e96ce9b509061c162c8.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/prepare/f07028520b90eb758cae80c85c0ed4ea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/prepare/f07028520b90eb758cae80c85c0ed4ea.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/prepare/f9a8891083f963159dd1278164721add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/prepare/f9a8891083f963159dd1278164721add.png -------------------------------------------------------------------------------- /docs/zh_CN/_images/tutorial/prepare/fcfab7c8303c418d371d288f66609ec6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_images/tutorial/prepare/fcfab7c8303c418d371d288f66609ec6.png -------------------------------------------------------------------------------- /docs/zh_CN/_src: -------------------------------------------------------------------------------- 1 | ../../src -------------------------------------------------------------------------------- /docs/zh_CN/_static/css/hide-ad.css: -------------------------------------------------------------------------------- 1 | .rtd-pro-footer-wrapper.body { 2 | display: none; 3 | } 4 | -------------------------------------------------------------------------------- /docs/zh_CN/_static/css/search-box.css: -------------------------------------------------------------------------------- 1 | #searchbox { 2 | margin-bottom: 12px; 3 | } 4 | 5 | #searchbox .searchformwrapper { 6 | overflow: hidden; 7 | } 8 | 9 | #searchbox .search div { 10 | display: inline-block; 11 | } 12 | 13 | div.sphinxsidebar #searchbox input[type="text"] { 14 | width: 120px; 15 | } 16 | -------------------------------------------------------------------------------- /docs/zh_CN/_static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_static/favicon.png -------------------------------------------------------------------------------- /docs/zh_CN/_static/golang-core-course.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_static/golang-core-course.jpg -------------------------------------------------------------------------------- /docs/zh_CN/_static/linux-performance-course.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_static/linux-performance-course.jpg -------------------------------------------------------------------------------- /docs/zh_CN/_static/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_static/logo.jpg -------------------------------------------------------------------------------- /docs/zh_CN/_static/web-front-end-course.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_static/web-front-end-course.jpg -------------------------------------------------------------------------------- /docs/zh_CN/_static/wechat-mp-qrcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_static/wechat-mp-qrcode.png -------------------------------------------------------------------------------- /docs/zh_CN/_static/wechat-reward-g-concise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_static/wechat-reward-g-concise.png -------------------------------------------------------------------------------- /docs/zh_CN/_static/wechat-reward-g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_static/wechat-reward-g.png -------------------------------------------------------------------------------- /docs/zh_CN/_static/wechat-reward-lnp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_static/wechat-reward-lnp.png -------------------------------------------------------------------------------- /docs/zh_CN/_static/zedhz-course-qrcode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_static/zedhz-course-qrcode.jpg -------------------------------------------------------------------------------- /docs/zh_CN/_static/zedhz-course.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-fans/python-book/7b7f7d20fdb43b81ca33625d13a458708d8470e1/docs/zh_CN/_static/zedhz-course.jpg -------------------------------------------------------------------------------- /docs/zh_CN/_templates/baidu_tongji.html: -------------------------------------------------------------------------------- 1 | {% set baidu_analytics_id='1b9c6e93cc0c84d4dfbcf58e956d340c' %} 2 | 3 | 12 | -------------------------------------------------------------------------------- /docs/zh_CN/_templates/baidu_ziyuan.html: -------------------------------------------------------------------------------- 1 | 15 | -------------------------------------------------------------------------------- /docs/zh_CN/_templates/busuanzi.html: -------------------------------------------------------------------------------- 1 | 2 | 本站总访问量 3 | -------------------------------------------------------------------------------- /docs/zh_CN/_templates/course-ad.html: -------------------------------------------------------------------------------- 1 |

大牛课程

2 | 3 | 加入学习 4 | -------------------------------------------------------------------------------- /docs/zh_CN/_templates/course-ad2.html: -------------------------------------------------------------------------------- 1 |
2 |

大牛课程

3 | 4 | {% for course in [ 5 | { 6 | "url": "https://time.geekbang.org/column/intro/140?code=watzFY59C5wIYB3ECn%2FScBaIFq5k8pPz9UU8ADR%2Fd4s%3D&utm_term=SPoster", 7 | "url": "https://time.geekbang.org/column/intro/140?code=watzFY59C5wIYB3ECn%2FScBaIFq5k8pPz9UU8ADR%2Fd4s%3D", 8 | "path": "_static/linux-performance-course.jpg", 9 | }, 10 | { 11 | "url": "https://time.geekbang.org/column/intro/112?code=S1Gimo52SvlZRR-d1JmFhwo3qiM%2FeyKiszh4wwpkW70%3D&utm_term=SPoster", 12 | "url": "https://time.geekbang.org/column/intro/112?code=S1Gimo52SvlZRR-d1JmFhwo3qiM%2FeyKiszh4wwpkW70%3D", 13 | "path": "_static/golang-core-course.jpg", 14 | }, 15 | { 16 | "url": "https://time.geekbang.org/column/intro/154?code=VicNYaXq1%2Ff9xQ-rrWlMfr%2FPoyYAw4D8eN8mB5SZTjA%3D&utm_term=SPoster", 17 | "url": "https://time.geekbang.org/column/intro/154?code=VicNYaXq1%2Ff9xQ-rrWlMfr%2FPoyYAw4D8eN8mB5SZTjA%3D", 18 | "path": "_static/web-front-end-course.jpg", 19 | }, 20 | { 21 | "url": "https://time.geekbang.org/column/intro/48?code=vPMg2o7CvYAvCtdAV7DY5UvvS1DzcRNcImRZy3KzttE%3D&utm_term=SPoster", 22 | "url": "https://time.geekbang.org/column/intro/48?code=vPMg2o7CvYAvCtdAV7DY5UvvS1DzcRNcImRZy3KzttE%3D", 23 | "path": "_static/zedhz-course.jpg", 24 | }, 25 | ] %} 26 | 27 | 28 | 29 | {% endfor %} 30 | 31 |
32 | 33 | 41 | -------------------------------------------------------------------------------- /docs/zh_CN/_templates/disqus.html: -------------------------------------------------------------------------------- 1 | {% set disqus_domain='python-book.disqus.com' %} 2 | 3 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /docs/zh_CN/_templates/google_analytics.html: -------------------------------------------------------------------------------- 1 | {% set google_analytics_id='UA-113160431-3' %} 2 | 3 | 4 | 5 | 12 | -------------------------------------------------------------------------------- /docs/zh_CN/_templates/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "!layout.html" %} 2 | 3 | {% block extrahead %} 4 | {% include 'google_analytics.html' %} 5 | {{ super() }} 6 | {% endblock extrahead %} 7 | 8 | {% block document %} 9 | {{ super() }} 10 | {% endblock %} 11 | 12 | {% block content %} 13 |
14 | 15 |
16 | 17 | {{ super() }} 18 | {% endblock %} 19 | 20 | {% block footer %} 21 | 35 | 36 | {% if theme_github_banner|lower != 'false' %} 37 | 38 | Fork me on GitHub 39 | 40 | {% endif %} 41 | 42 | {% include 'baidu_tongji.html' %} 43 | {% include 'baidu_ziyuan.html' %} 44 | {% include 'disqus.html' %} 45 | {% endblock %} 46 | 47 | {# 48 | {% include 'livere.html' %} 49 | {% include 'busuanzi.html' %} 50 | #} 51 | -------------------------------------------------------------------------------- /docs/zh_CN/_templates/livere.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 16 | 17 |
18 | 19 | -------------------------------------------------------------------------------- /docs/zh_CN/_templates/more.html: -------------------------------------------------------------------------------- 1 |

更多阅读

2 |
    3 | {% for link in [ 4 | { 5 | "title": "Go语言小册", 6 | "url": "https://golang.fasionchan.com/zh_CN/latest/index.html", 7 | }, 8 | { 9 | "title": "学习Linux", 10 | "url": "https://linux.fasionchan.com/zh_CN/latest/index.html", 11 | }, 12 | { 13 | "title": "Linux网络编程", 14 | "url": "https://network.fasionchan.com/zh_CN/latest/index.html", 15 | }, 16 | { 17 | "title": "NodeJs小册", 18 | "url": "https://nodejs.fasionchan.com/zh_CN/latest/index.html", 19 | }, 20 | { 21 | "title": "OSX操作指南", 22 | "url": "https://osx-guide.readthedocs.io/zh_CN/latest/", 23 | }, 24 | ] %} 25 |
  • {{ link.title }}
  • 26 | {% endfor %} 27 |
28 | -------------------------------------------------------------------------------- /docs/zh_CN/_templates/reward.html: -------------------------------------------------------------------------------- 1 |

微信打赏

2 | 3 | -------------------------------------------------------------------------------- /docs/zh_CN/_templates/sf-namecard-fasionchan.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/zh_CN/_templates/wechat-mp-qrcode.html: -------------------------------------------------------------------------------- 1 |

微信公众号

2 | 3 | -------------------------------------------------------------------------------- /docs/zh_CN/about/contact.rst: -------------------------------------------------------------------------------- 1 | .. 交流 2 | FileName: contact.rst 3 | Author: Fasion Chan 4 | Created: 2018-03-03 20:09:58 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | ==== 13 | 交流 14 | ==== 15 | 16 | GitHub 17 | ====== 18 | 19 | 本项目所有示例代码托管在 ``GitHub`` 上,仓库是: 20 | `python-book `_ 。 21 | 22 | 建议初学者亲自动手,将所有示例程序编写一遍,加深理解。 23 | **编程没有捷径** ,唯有带着 **好奇心** 探索程序背后的秘密,多动手勤练习,方能编写出你的理想世界。 24 | 25 | 如需与我们交流,也可以在在本项目中 `新建一个Issue `_ , 26 | 以这种形式进行讨论。 27 | 内容可以包括但不局限于: 28 | 29 | - ``BUG`` 反馈 30 | - 建议 31 | - 提问 32 | 33 | 点击左边 ``Star`` 按钮,关注本项目。 34 | 对于后续任何更新,尽在掌握! 35 | 36 | .. _wechat-mp: 37 | 38 | 微信公众号 39 | ========== 40 | 41 | .. figure:: /_static/wechat-mp-qrcode.png 42 | :align: center 43 | 44 | *小菜学编程* 45 | 46 | 我们维护了一个微信公众号—— **小菜学编程** ,欢迎扫二维码关注我们。 47 | 48 | 对于后续更新,我们会以公众号文章的形式进行推送,这是订阅我们内容的最佳渠道。 49 | 也欢迎通过公众号给我们留言,同样可以包括但不局限于: 50 | 51 | - ``BUG`` 反馈 52 | - 建议 53 | - 提问 54 | 55 | 邮件 56 | ==== 57 | 58 | 当然了,更书面的形式也支持,你可以给我们:`发送邮件 `_ 。 59 | 60 | .. comments 61 | comment something out blow 62 | 63 | -------------------------------------------------------------------------------- /docs/zh_CN/about/index.rst: -------------------------------------------------------------------------------- 1 | .. 关于 2 | FileName: index.rst 3 | Author: Fasion Chan 4 | Created: 2018-03-03 20:08:14 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | ==== 13 | 关于 14 | ==== 15 | 16 | .. toctree:: 17 | :maxdepth: 2 18 | 19 | 交流 20 | 21 | .. comments 22 | comment something out blow 23 | 24 | 内推 25 | -------------------------------------------------------------------------------- /docs/zh_CN/acknowledgements/index.rst: -------------------------------------------------------------------------------- 1 | .. 鸣谢 2 | FileName: index.rst 3 | Author: Fasion Chan 4 | Created: 2018-01-27 15:43:10 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | 鸣谢 13 | ==== 14 | 15 | .. toctree:: 16 | :maxdepth: 2 17 | 18 | 巨人肩膀 19 | 20 | 21 | .. comments 22 | comment something out below 23 | 24 | http://www.sphinx-doc.org/en/stable/markup/code.html#directive-code-block 25 | http://pygments.org/docs/lexers/ 26 | http://docs.readthedocs.io/en/latest/getting_started.html 27 | -------------------------------------------------------------------------------- /docs/zh_CN/acknowledgements/shoulders.rst: -------------------------------------------------------------------------------- 1 | .. 巨人肩膀 2 | FileName: shoulders.rst 3 | Author: Fasion Chan 4 | Created: 2018-01-27 15:47:28 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | ======== 13 | 巨人肩膀 14 | ======== 15 | 16 | 创作工具 17 | ======== 18 | 19 | - **代码高亮** 使用 `Pygments `_ ,`支持语言 `_ 非常全面; 20 | 21 | .. comments 22 | comment something out blow 23 | 24 | -------------------------------------------------------------------------------- /docs/zh_CN/appendices/index.rst: -------------------------------------------------------------------------------- 1 | .. 附录 2 | FileName: index.rst 3 | Author: Fasion Chan 4 | Created: 2018-01-27 14:24:28 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | ==== 13 | 附录 14 | ==== 15 | 16 | .. toctree:: 17 | :titlesonly: 18 | 19 | 学习资料 20 | 21 | .. comments 22 | comment something out blow 23 | 24 | -------------------------------------------------------------------------------- /docs/zh_CN/appendices/resources.rst: -------------------------------------------------------------------------------- 1 | .. 学习资料 2 | FileName: resources.rst 3 | Author: Fasion Chan 4 | Created: 2018-12-03 18:13:39 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :description lang=zh: 14 | 用Python做科学计算介绍如何用Python开发科学计算应用程序。 15 | :keywords: python, 学习资料, 科学计算 16 | 17 | ======== 18 | 学习资料 19 | ======== 20 | 21 | 免费资料 22 | ======== 23 | 24 | 编程派 25 | ------ 26 | 27 | `编程派`_ 是一位 `Python` 编程爱好者利用业余时间开发出了自己的网站,专注 `Python` 编程。 28 | 网站致力于让更多的人了解 `Python` 语言,更快地获取国外的 `Python` 教程和资源,一起交流、学习 `Python` 。 29 | 30 | `http://www.codingpy.com/ `_ 31 | 32 | 用Python做科学计算 33 | ------------------ 34 | 35 | `用Python做科学计算 `_ 36 | 介绍如何用 `Python` 开发 **科学计算** 应用程序,除此还包括: 37 | 如何制作交互式的 *2D* 、 *3D* 图像; 38 | 如何设计精巧的程序界面; 39 | 如何和 *C* 语言所编写的高速计算程序结合; 40 | 如何编写声音、图像处理算法。 41 | 42 | .. _编程派: http://www.codingpy.com/ 43 | 44 | .. comments 45 | comment something out below 46 | 47 | -------------------------------------------------------------------------------- /docs/zh_CN/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Configuration file for the Sphinx documentation builder. 4 | # 5 | # This file does only contain a selection of the most common options. For a 6 | # full list see the documentation: 7 | # http://www.sphinx-doc.org/en/stable/config 8 | 9 | # -- Path setup -------------------------------------------------------------- 10 | 11 | # If extensions (or modules to document with autodoc) are in another directory, 12 | # add these directories to sys.path here. If the directory is relative to the 13 | # documentation root, use os.path.abspath to make it absolute, like shown here. 14 | # 15 | import datetime 16 | import os 17 | # import sys 18 | # sys.path.insert(0, os.path.abspath('.')) 19 | 20 | now = datetime.datetime.now() 21 | 22 | 23 | # -- Project information ----------------------------------------------------- 24 | 25 | project = u'Python语言小册' 26 | copyright = u'%d, fasionchan' % (now.year,) 27 | author = u'fasionchan' 28 | site_domain = os.environ.get('SITE_DOMAIN', 'python.fasionchan.com') 29 | 30 | # The short X.Y version 31 | version = u'1.0' 32 | # The full version, including alpha/beta/rc tags 33 | release = u'1.0' 34 | 35 | 36 | # -- General configuration --------------------------------------------------- 37 | 38 | # If your documentation needs a minimal Sphinx version, state it here. 39 | # 40 | # needs_sphinx = '1.0' 41 | 42 | # Add any Sphinx extension module names here, as strings. They can be 43 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 44 | # ones. 45 | extensions = [ 46 | 'sphinx.ext.autodoc', 47 | "sphinx_sitemap", 48 | ] 49 | 50 | # Add any paths that contain templates here, relative to this directory. 51 | templates_path = ['_templates'] 52 | 53 | # The suffix(es) of source filenames. 54 | # You can specify multiple suffix as a list of string: 55 | # 56 | # source_suffix = ['.rst', '.md'] 57 | source_suffix = '.rst' 58 | 59 | # The master toctree document. 60 | master_doc = 'index' 61 | 62 | # The language for content autogenerated by Sphinx. Refer to documentation 63 | # for a list of supported languages. 64 | # 65 | # This is also used if you do content translation via gettext catalogs. 66 | # Usually you set "language" from the command line for these cases. 67 | language = u'zh_CN' 68 | 69 | # List of patterns, relative to source directory, that match files and 70 | # directories to ignore when looking for source files. 71 | # This pattern also affects html_static_path and html_extra_path . 72 | exclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store', '_fragments', 'opt', '_src', '_disabled', 'var'] 73 | 74 | # The name of the Pygments (syntax highlighting) style to use. 75 | pygments_style = 'sphinx' 76 | 77 | 78 | # -- Options for HTML output ------------------------------------------------- 79 | html_title = project 80 | html_favicon = '_static/favicon.png' 81 | html_last_updated_fmt = '%Y-%m-%d %H:%M' 82 | 83 | # The theme to use for HTML and HTML Help pages. See the documentation for 84 | # a list of builtin themes. 85 | # 86 | html_theme = 'alabaster' 87 | 88 | # Theme options are theme-specific and customize the look and feel of a theme 89 | # further. For a list of options available for each theme, see the 90 | # documentation. 91 | # 92 | html_theme_options = { 93 | 'logo': 'logo.jpg', 94 | #'logo_name': True, 95 | 'description': u'Python语言小册子,涵盖高级用法、推荐类库以及最佳实践等。', 96 | 97 | 'font_family': ','.join(map(repr, [ 98 | 'Arial', 99 | 'Heiti SC', 100 | 'Microsoft YaHei', 101 | ])), 102 | 103 | #'fixed_sidebar': True, 104 | 105 | # GitHub 106 | 'github_user': 'coding-fans', 107 | 'github_repo': 'python-book', 108 | 'github_banner': True, 109 | 'github_type': 'star', 110 | 111 | # GratiPay 112 | #'gratipay_user': 'fasionchan@gmail.com', 113 | 114 | # Google Analytics 115 | #'analytics_id': 'UA-113160431-1', 116 | 117 | #'show_related': True, 118 | } 119 | 120 | # Add any paths that contain custom static files (such as style sheets) here, 121 | # relative to this directory. They are copied after the builtin static files, 122 | # so a file named "default.css" will overwrite the builtin "default.css". 123 | html_static_path = ['_static'] 124 | 125 | # Custom sidebar templates, must be a dictionary that maps document names 126 | # to template names. 127 | # 128 | # The default sidebars (for documents that don't match any pattern) are 129 | # defined by theme itself. Builtin themes are using these templates by 130 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', 131 | # 'searchbox.html']``. 132 | # 133 | html_sidebars = { 134 | '**': [ 135 | 'about.html', 136 | 'searchbox.html', 137 | 'navigation.html', 138 | 'more.html', 139 | #'sf-namecard-fasionchan.html', 140 | 'wechat-mp-qrcode.html', 141 | 'course-ad2.html', 142 | #'donate.html', 143 | 144 | #'reward.html', 145 | 146 | #'relations.html', # needs 'show_related': True theme option to display 147 | ] 148 | } 149 | 150 | 151 | # -- Options for HTMLHelp output --------------------------------------------- 152 | 153 | # Output file base name for HTML help builder. 154 | htmlhelp_basename = 'PythonBookdoc' 155 | 156 | 157 | # -- Options for LaTeX output ------------------------------------------------ 158 | 159 | latex_elements = { 160 | # The paper size ('letterpaper' or 'a4paper'). 161 | # 162 | # 'papersize': 'letterpaper', 163 | 164 | # The font size ('10pt', '11pt' or '12pt'). 165 | # 166 | # 'pointsize': '10pt', 167 | 168 | # Additional stuff for the LaTeX preamble. 169 | # 170 | # 'preamble': '', 171 | 172 | # Latex figure (float) alignment 173 | # 174 | # 'figure_align': 'htbp', 175 | } 176 | 177 | # Grouping the document tree into LaTeX files. List of tuples 178 | # (source start file, target name, title, 179 | # author, documentclass [howto, manual, or own class]). 180 | latex_documents = [ 181 | (master_doc, 'Python.tex', u'Python语言小册 Documentation', 182 | author, 'manual'), 183 | ] 184 | 185 | 186 | # -- Options for manual page output ------------------------------------------ 187 | 188 | # One entry per manual page. List of tuples 189 | # (source start file, name, description, authors, manual section). 190 | man_pages = [ 191 | (master_doc, 'python', u'Python语言小册 Documentation', 192 | [author], 1) 193 | ] 194 | 195 | 196 | # -- Options for Texinfo output ---------------------------------------------- 197 | 198 | # Grouping the document tree into Texinfo files. List of tuples 199 | # (source start file, target name, title, author, 200 | # dir menu entry, description, category) 201 | texinfo_documents = [ 202 | (master_doc, 'Python', u'Python语言小册 Documentation', 203 | author, 'Python', 'One line description of project.', 204 | 'Miscellaneous'), 205 | ] 206 | 207 | site_url = 'https://%s/zh_CN/latest/' % (site_domain,) 208 | 209 | def setup(app): 210 | app.add_stylesheet('css/hide-ad.css') 211 | app.add_stylesheet('css/search-box.css') 212 | -------------------------------------------------------------------------------- /docs/zh_CN/database/index.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Author: fasion 3 | Created time: 2019-11-09 15:05:24 4 | Last Modified by: fasion 5 | Last Modified time: 2020-03-10 09:14:17 6 | 7 | 8 | ========== 9 | 数据库操作 10 | ========== 11 | 12 | .. toctree:: 13 | :titlesonly: 14 | 15 | MongoDB 16 | -------------------------------------------------------------------------------- /docs/zh_CN/deployment/index.rst: -------------------------------------------------------------------------------- 1 | .. 部署方案 2 | FileName: index.rst 3 | Author: Fasion Chan 4 | Created: 2018-05-29 20:59:40 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :keywords: python, deploy, virtualenv, pip, requirements.txt, python deploy, python部署 14 | 15 | ======== 16 | 部署方案 17 | ======== 18 | 19 | .. toctree:: 20 | :titlesonly: 21 | 22 | pip 配置 23 | 24 | `Python` 版本繁多, `Python` 应用需要依赖一些包,版本也不尽相同。 25 | 如果在系统级 `Python` 环境部署应用,可以预想到,一定存在冲突风险。 26 | 试想一下场景: 27 | 28 | 应用 `A` 、 `B` 均依赖一个数据库连接包,版本分别是 `a` 和 `b` ,两个版本有些不兼容。 29 | 如果两个应用部署在同个 `Python` 环境,那么数据库包应该安装什么版本呢? 30 | 31 | 独立部署环境 32 | ============ 33 | 34 | 问题只能通过部署独立的 `Python` 环境来解决。那么同台机器如何部署多个 `Python` 环境呢? 35 | 甚至是版本不同的 `Python` 环境?—— `virtualenv`_ ! 36 | 37 | 首先,初始化一个新的 `Python` 环境: 38 | 39 | .. code-block:: shell-session 40 | 41 | $ virtualenv ~/python 42 | New python executable in /Users/fasion/python/bin/python 43 | Installing setuptools, pip, wheel...done. 44 | 45 | 完成之后,便可启动 `Python` 解析器了: 46 | 47 | .. code-block:: shell-session 48 | 49 | $ ~/python/bin/python 50 | Python 3.6.4 (default, Jan 6 2018, 11:51:59) 51 | [GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin 52 | Type "help", "copyright", "credits" or "license" for more information. 53 | >>> print('abc') 54 | abc 55 | >>> 56 | 57 | 自然也可以用这个独立的环境来跑应用了: 58 | 59 | .. code-block:: shell-session 60 | 61 | $ ~/python/bin/python /some/path/to/app.py 62 | 63 | 当然了,也可以指定 `Python` 版本: 64 | 65 | .. code-block:: shell-session 66 | 67 | $ virtualenv -p python3 ~/python3 68 | 69 | .. tip:: 70 | 71 | 用 `virtualenv`_ 制作独立的 `Python` 环境,对其任何操作均不影响其他环境。 72 | 73 | 依赖管理 74 | ======== 75 | 76 | `Python` 通过 `pip`_ 命令安装依赖包,大家应该都知道: 77 | 78 | .. code-block:: shell-session 79 | 80 | $ pip install Flask 81 | 82 | 依赖包版本也很重要,用了错误版本的包可能导致应用异常。保险起见,装包时指定版本: 83 | 84 | .. code-block:: shell-session 85 | 86 | $ pip install Flask==1.0.2 87 | 88 | 每次部署应用时,检查所有依赖包及版本是否就绪。 89 | 方法非常简单,直接运行装包命令即可。 90 | `pip` 将确保依赖包以指定版本安装。 91 | 92 | 此外,最好可以通过配置文件将所有依赖保存下来。 93 | `pip` 命令也支持依赖配置文件 `requirements.txt` ,内容格式如下: 94 | 95 | .. code-block:: text 96 | 97 | Flask==1.0.2 98 | Jinja2==2.10 99 | 100 | 这样一来,一个命令就可以完成所有依赖包的安装: 101 | 102 | .. code-block:: shell-session 103 | 104 | $ pip install -r requirements.txt 105 | 106 | .. tip:: 107 | 108 | 应用在 `requirements.txt` 配置文件维护所有依赖包及版本并通过 `pip`_ 命令安装。 109 | 110 | 下一步 111 | ====== 112 | 113 | .. include:: /_fragments/next-step-to-wechat-mp.rst 114 | 115 | .. include:: /_fragments/wechat-reward.rst 116 | 117 | .. include:: /_fragments/disqus.rst 118 | 119 | .. _pip: https://pip.pypa.io/ 120 | .. _virtualenv: https://virtualenv.pypa.io/ 121 | 122 | .. comments 123 | comment something out below 124 | 125 | -------------------------------------------------------------------------------- /docs/zh_CN/deployment/pip-conf.rst: -------------------------------------------------------------------------------- 1 | .. pip 配置 2 | FileName: pip-conf.rst 3 | Author: Fasion Chan 4 | Created: 2018-05-29 20:04:19 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :keywords: pip, python, pip config 14 | 15 | ======== 16 | pip 配置 17 | ======== 18 | 19 | .. code-block:: ini 20 | 21 | [global] 22 | 23 | index-url = http://pypi.douban.com/simple 24 | extra-index-url = http://mirrors.aliyun.com/pypi/simple 25 | trusted-host = 26 | pypi.douban.com 27 | mirrors.aliyun.com 28 | timeout = 120 29 | 30 | 下一步 31 | ====== 32 | 33 | .. include:: /_fragments/next-step-to-wechat-mp.rst 34 | 35 | .. include:: /_fragments/wechat-reward.rst 36 | 37 | .. include:: /_fragments/disqus.rst 38 | 39 | .. comments 40 | comment something out below 41 | 42 | -------------------------------------------------------------------------------- /docs/zh_CN/index.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Author: fasion 3 | Created time: 2018-03-03 11:45:04 4 | Last Modified by: fasion 5 | Last Modified time: 2020-03-16 11:05:31 6 | 7 | ============== 8 | Python语言小册 9 | ============== 10 | 11 | .. toctree:: 12 | :titlesonly: 13 | 14 | 关于 15 | 快速入门 16 | 数据库操作 17 | 最佳实践 18 | 推荐类库 19 | 部署方案 20 | 面试题精选 21 | 译文 22 | 附录 23 | 鸣谢 24 | 25 | .. comments 26 | comment something out below 27 | 28 | 异步编程 29 | -------------------------------------------------------------------------------- /docs/zh_CN/interview/index.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Author: fasion 3 | Created time: 2020-03-12 19:08:41 4 | Last Modified by: fasion 5 | Last Modified time: 2020-03-14 11:07:22 6 | 7 | .. meta:: 8 | :description lang=zh: 9 | 编者担任Python面试官多年,积累了很多面试题,特整理起来,希望对求职者有所帮助。 10 | 此外,我们从网上摘录了很多经典面试题,配以详尽的讲解,举一反三。 11 | :keywords: python, 面试题, 大全, 精讲 12 | 13 | ================= 14 | Python 面试题精选 15 | ================= 16 | 17 | 编者担任 *Python* 面试官多年,积累了很多面试题,特整理起来,希望对求职者有所帮助。 18 | 此外,我们从网上摘录了很多经典面试题,配以详尽的讲解,举一反三。 19 | 20 | 我们将不定期更新,订阅可以关注我们的公众号: **小菜学编程** 。 21 | 22 | 面试题 23 | ====== 24 | 25 | #. **用一行代码实现整数 1 至 100 之和** 26 | 27 | 网上的答案是通过 *range* 生成 *1* 至 *100* 的整数,然后用 *sum* 求和: 28 | 29 | .. code-block:: python 30 | 31 | >>> # 解法一 32 | >>> sum(range(1, 101)) 33 | 5050 34 | 35 | 这行代码确实很有美感,但你想过没有:如果是求 *1* 至 *10000000000* 之和呢? 36 | 候选人必须认识到这是一个 *O(N)* 算法,真的适合所有场景吗?为什么不用等差数列前 *N* 项和公式进行计算呢? 37 | 38 | .. code-block:: python 39 | 40 | >>> # 解法二 41 | >>> n = 100 42 | >>> (n + 1) * n >> 1 43 | 5050 44 | 45 | 采用前 *N* 项和公式,求和时间复杂度是 *O(1)* ,孰优孰劣应该很明显了吧。 46 | 大家可以对比下当 *N* 很大时,这两种计算方式的表现: 47 | 48 | .. code-block:: python 49 | 50 | >>> n = 100000000 51 | >>> sum(range(1, n+1)) 52 | 5000000050000000 53 | >>> (n + 1) * n >> 1 54 | 5000000050000000 55 | 56 | 面试官喜欢引申,候选人如果只是刷题记答案而不会分析,肯定是过不了关的。 57 | 58 | #. **如何在一个函数内部修改全局变量** 59 | 60 | 在函数内部用 *global* 关键字将变量申明为全局,然后再进行修改: 61 | 62 | .. code-block:: python 63 | 64 | >>> a = 1 65 | >>> def func(): 66 | ... global a 67 | ... a = 2 68 | ... 69 | >>> print(a) 70 | 1 71 | >>> func() 72 | >>> print(a) 73 | 2 74 | 75 | 面试官还可能引申到以下概念讨论,必须滚瓜烂熟: 76 | 77 | - **变量作用域** ( *scope* ) 78 | - **局部名字空间** ( *locals* ) 79 | - **闭包名字空间** ( *globals* ) 80 | - **全局名字空间** ( *enclosing* ) 81 | - **内建名字空间** ( *builtin* ) 82 | 83 | #. **列出 5 个 Python 标准库** 84 | 85 | 这是一个开发性题目,面试官以考察候选人知识面以及学习深度为目的。 86 | 必须结合自身情况,选择一些自己比较熟悉的标准库作答,面试官随时可能深入讨论。 87 | 88 | 保险一点,可以回答一些常用但很浅显的,例如: 89 | 90 | - `re`_ ,正则表达式处理 91 | - `datetime`_ ,日期时间处理 92 | - `json`_ , *JSON* 数据处理 93 | - `math`_ , 数学计算 94 | - `random`_ , 随机数 95 | 96 | 想要获得加分,也可以回答一些高级的,例如: 97 | 98 | - `os`_ ,系统调用 99 | - `socket`_ ,套接字编程与网络通讯 100 | - `threading`_ ,多线程处理 101 | - `multiprocessing`_ ,多进程处理 102 | - `queue`_ ,同步任务队列 103 | 104 | 面试官很有很能深入提问,切记:如果自己不是很熟悉,就不要班门弄斧了。 105 | 106 | #. **字典如何删除键** 107 | 108 | - 方法一,使用 *del* 语句进行删除, *del* 关键字还可用于删除 **变量** 、 **属性** 109 | 110 | .. code-block:: python 111 | 112 | >>> ages = {'tom': 18, 'jim': 20, 'lily': 19} 113 | >>> del ages['jim'] 114 | >>> ages 115 | {'tom': 18, 'lily': 19} 116 | 117 | - 方法二,调用 *pop* 方法进行删除,这样可以拿到被删除键对应的值: 118 | 119 | .. code-block:: python 120 | 121 | >>> ages = {'tom': 18, 'jim': 20, 'lily': 19} 122 | >>> jims_age = ages.pop('jim') 123 | >>> jims_age 124 | 20 125 | >>> ages 126 | {'tom': 18, 'lily': 19} 127 | 128 | #. **如何合并两个字典** 129 | 130 | .. code-block:: python 131 | 132 | >>> info1 = {'name': 'jim', 'age': 18} 133 | >>> info2 = {'name': 'jim', 'score': 95} 134 | 135 | - 方法一,调用 *dict* 对象 *update* 方法: 136 | 137 | .. code-block:: python 138 | 139 | >>> info1.update(info2) 140 | >>> info1 141 | {'name': 'jim', 'age': 18, 'score': 95} 142 | 143 | - 方法二: 144 | 145 | .. code-block:: python 146 | 147 | >>> info = {**info1, **info2} 148 | >>> info 149 | {'name': 'jim', 'age': 18, 'score': 95} 150 | 151 | #. **Python 2 和 Python 3 中的 range(100) 的区别** 152 | 153 | *Python 2* 中的 *range* 函数返回一个列表,长度越大消耗内存越多: 154 | 155 | .. code-block:: python 156 | 157 | >>> print(range(10)) 158 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 159 | 160 | *Python 2* 中的 *xrange* 函数与 *range* 类似,但返回 **生成器** : 161 | 162 | .. code-block:: python 163 | 164 | >>> r = xrange(10) 165 | >>> ri = iter(r) 166 | >>> next(ri) 167 | 0 168 | >>> next(ri) 169 | 1 170 | 171 | 生成器内存消耗固定,与长度无关。因此,循环一般使用 *xrange* : 172 | 173 | .. code-block:: python 174 | 175 | >>> for i in range(10000): 176 | ... pass 177 | ... 178 | 179 | 由于生成器比较高效, *Python 3* 的 *range* 函数也选择返回生成器,可以认为与 *Python 2* 中的 *xrange* 等价: 180 | 181 | .. code-block:: python 182 | 183 | >>> r = range(10) 184 | >>> ri = iter(r) 185 | >>> next(ri) 186 | 0 187 | >>> next(ri) 188 | 1 189 | 190 | 当然了,*Python 3* 中也可以实现与 *Python 2* 中的 *range* 函数一样的效果: 191 | 192 | .. code-block:: python 193 | 194 | >>> list(range(10)) 195 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 196 | 197 | #. **Python 列表如何去重** 198 | 199 | .. code-block:: python 200 | 201 | >>> l = [7, 3, 0, 3, 0, 8, 4, 9, 3, 8] 202 | 203 | 先将列表转换成 **集合** ( *set* ),由于集合元素不重复,便实现去重: 204 | 205 | .. code-block:: python 206 | 207 | >>> set(l) 208 | {0, 3, 4, 7, 8, 9} 209 | 210 | 最后再将集合转化成列表即可: 211 | 212 | .. code-block:: python 213 | 214 | >>> list(set(l)) 215 | [0, 3, 4, 7, 8, 9] 216 | 217 | #. **一句话解释什么样的语言能够用装饰器** 218 | 219 | 函数可以 **作为参数传递** 、 **可以作为返回值返回** 的语言,都可以实现装饰器。 220 | 221 | #. **Python 内建数据类型有哪些** 222 | 223 | - **布尔** , *bool* 224 | - **整数** , *int* 225 | - **浮点** , *float* 226 | - **字符串** , *str* 227 | - **字节序列** , *bytes* 228 | - **元组** , *tuple* 229 | - **列表** , *list* 230 | - **字典** , *dict* 231 | 232 | 面试官可进一步延伸到对象 **内部结构** ,相关操作 **时间复杂度** 等高级知识点。 233 | 234 | #. **请编写正则表达式,提取以下网页中所有 a 标签的 URL** 235 | 236 | .. code-block:: html 237 | 238 | 239 | 240 | 小菜学编程 241 | 242 | 243 | 250 | 251 | 252 | 253 | 这题目考察标准库 *re* 模块的基本用法,难度不高,根据文本特征写正则即可: 254 | 255 | .. code-block:: python 256 | 257 | >>> import re 258 | >>> re.findall(r'', page) 259 | ['https://python.fasionchan.com', 'https://linux.fasionchan.com', 'https://network.fasionchan.com', 'https://golang.fasionchan.com', 'https://nodejs.fasionchan.com'] 260 | 261 | 注意到,参考答案中的正则表达式匹配 *a* 开标签,括号表示 **内容提取** 。 262 | 正则表达式在日常开发中应用场景很多,必须完全掌握。 263 | 264 | #. **Python 中有几个名字空间,分别是什么** 265 | 266 | *Python* 总共有 *4* 个名字空间: 267 | 268 | - **局部名字空间** ( *locals* ) 269 | - **闭包名字空间** ( *globals* ) 270 | - **全局名字空间** ( *enclosing* ) 271 | - **内建名字空间** ( *builtin* ) 272 | 273 | 274 | 附录 275 | ==== 276 | 277 | .. include:: /_fragments/next-step-to-wechat-mp.rst 278 | 279 | 参考文献 280 | ======== 281 | 282 | #. `110道Python面试题(真题) - 知乎 `_ 283 | 284 | .. include:: /_fragments/wechat-reward.rst 285 | 286 | .. include:: /_fragments/disqus.rst 287 | 288 | .. _re: https://docs.python.org/3/library/re.html 289 | .. _datetime: https://docs.python.org/3/library/datetime.html 290 | .. _math: https://docs.python.org/3/library/math.html 291 | .. _random: https://docs.python.org/3/library/random.html 292 | .. _json: https://docs.python.org/3/library/json.html 293 | 294 | .. _os: https://docs.python.org/3/library/os.html 295 | .. _threading: https://docs.python.org/3/library/threading.html 296 | .. _multiprocessing: https://docs.python.org/3/library/multiprocessing.html 297 | .. _queue: https://docs.python.org/3/library/queue.html 298 | .. _socket: https://docs.python.org/3/library/socket.html 299 | -------------------------------------------------------------------------------- /docs/zh_CN/libs/exchangelib.rst: -------------------------------------------------------------------------------- 1 | .. exchangelib 2 | FileName: exchangelib.rst 3 | Author: Fasion Chan 4 | Created: 2018-10-23 18:27:25 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :keywords: exchangelib, python, exchange mail, exchange邮件, exchange收发 14 | 15 | =========== 16 | exchangelib 17 | =========== 18 | 19 | `exchangelib`_ 是一个用于操作 `Exchange` 邮箱的第三方库,其接口设计简单易用。 20 | 类库现有功能如下: 21 | 22 | - 服务器自动发现( `autodiscover` ) 23 | - 对象搜索( `searching` ) 24 | - 对象创建( `creating` ) 25 | - 对象更新( `updating` ) 26 | - 对象发送( `sending` ) 27 | - 对象删除( `deleting` ) 28 | - etc 29 | 30 | 抢先一览 31 | ======== 32 | 33 | 下面这个例子仅用若干行代码便实现了打印输出收件箱前 `100` 封邮件: 34 | 35 | .. code-block:: python 36 | 37 | from exchangelib import Credentials, Account 38 | 39 | credentials = Credentials('john@example.com', 'topsecret') 40 | account = Account('john@example.com', credentials=credentials, autodiscover=True) 41 | 42 | for item in account.inbox.all().order_by('-datetime_received')[:100]: 43 | print(item.subject, item.sender, item.datetime_received) 44 | 45 | 可以看到,将邮箱账号和密码传给 `exchangelib`_ 之后,即可通过简单的操作函数完成各种不可以思议的操作! 46 | 47 | 安装 48 | ==== 49 | 50 | 开始使用 `exchangelib`_ 之前,你需要先装好它。推荐从 `PYPI`_ 安装: 51 | 52 | .. code-block:: shell-session 53 | 54 | $ pip install exchangelib 55 | 56 | 默认的安装版本不支持 `Kerberos` 。 57 | 如果实在需要 `Kerberos` ,可以安装带 `Kerberos` 依赖的版本: 58 | 59 | .. code-block:: shell-session 60 | 61 | $ pip install exchangelib[kerberos] 62 | 63 | 想要安装最新的代码,则可以直接从 `Github`_ 安装: 64 | 65 | .. code-block:: shell-session 66 | 67 | $ pip install git+https://github.com/ecederstrand/exchangelib.git 68 | 69 | .. warning:: 70 | 71 | 最新的代码可能不太稳定,在生产中使用需要谨慎测试验证。 72 | 73 | 此外,由于 `exchangelib` 用到 `lxml` 包以及用以支持 `Kerberos` 认证的 `pykerberos` 包, 74 | 你可能需要装一些额外的系统包,具体方法因操作系统而异。 75 | 76 | 对于 `Debian` 系列系统: 77 | 78 | .. code-block:: shell-session 79 | 80 | $ apt-get install libxml2-dev libxslt1-dev 81 | 82 | $ # For Kerberos support, also install these: 83 | % apt-get install libkrb5-dev build-essential libssl-dev libffi-dev python-dev 84 | 85 | 对于 `CentOS` 系列系统: 86 | 87 | .. code-block:: shell-session 88 | 89 | $ # For Kerberos support, install these: 90 | $ yum install gcc python-devel krb5-devel krb5-workstation python-devel 91 | 92 | 发送邮件 93 | ======== 94 | 95 | 发送邮件只需初始化 `Message` 对象并调用 `send` 方法即可: 96 | 97 | .. code-block:: python 98 | 99 | from exchangelib import Message 100 | 101 | message = Message( 102 | account=account, 103 | subject='测试主题', 104 | body='这是一封测试邮件', 105 | to_recipients=( 106 | 'jim@example.com', 107 | ), 108 | ) 109 | message.send() 110 | 111 | 其中, *account* 参数是账号授权信息,抢先一览小节已介绍过; 112 | *subject* 为邮件主题; *body* 为邮件体; 113 | *to_recipients* 指定收件人列表。 114 | 115 | 抄送、密送 116 | ---------- 117 | 118 | **抄送** 收件人列表通过 `cc_recipients` 参数指定: 119 | 120 | .. code-block:: python 121 | 122 | message = Message( 123 | account=account, 124 | subject='测试主题', 125 | body='这是一封测试邮件', 126 | to_recipients=( 127 | 'jim@example.com', 128 | ), 129 | cc_recipients=( 130 | 'another-one@example.com', 131 | ), 132 | ) 133 | 134 | 类似地, **密送** 收件人通过 `bcc_recipients` 参数指定: 135 | 136 | .. code-block:: python 137 | 138 | message = Message( 139 | account=account, 140 | subject='测试主题', 141 | body='这是一封测试邮件', 142 | to_recipients=( 143 | 'jim@example.com', 144 | ), 145 | bcc_recipients=( 146 | 'another-one@example.com', 147 | ), 148 | ) 149 | 150 | HTML邮件 151 | -------- 152 | 153 | 邮件一般不局限于纯文本,可以用 `HTML` 编写格式丰富的内容: 154 | 155 | .. code-block:: python 156 | 157 | from exchangelib import HTMLBody 158 | 159 | html = 'Hello happy OWA user!' 160 | message = Message( 161 | account=account, 162 | subject='测试主题', 163 | body=HTMLBody(html), 164 | to_recipients=( 165 | 'jim@example.com', 166 | ), 167 | ) 168 | 169 | 发送附件 170 | -------- 171 | 172 | 发送附件需要初始化 `FileAttachment` 对象,指定文件名以及文件内容, 173 | 并通过 `Message` 对象 *attach* 方法附着到邮件上: 174 | 175 | .. code-block:: python 176 | 177 | from exchangelib import FileAttachment 178 | 179 | logo_filename = 'logo.png' 180 | with open(logo_filename, 'rb') as f: 181 | logo = FileAttachment( 182 | filename=logo_filename, 183 | content=f.read(), 184 | ) 185 | message.attach(logo) 186 | message.send() 187 | 188 | 内嵌附件图片 189 | ------------ 190 | 191 | 附件图片可以嵌到 `HTML` 邮件体中进行展示。 192 | 此时,需要为附件指定一个 `CID` ,以便在 `HTML` 中引用: 193 | 194 | .. code-block:: python 195 | 196 | logo_filename = 'logo.png' 197 | with open(logo_filename, 'rb') as f: 198 | logo = FileAttachment( 199 | filename=logo_filename, 200 | content=f.read(), 201 | content_id=logo_filename, 202 | ) 203 | message.attach(logo) 204 | message.body = HTMLBody('Hello logo: ' % (logo_filename,)) 205 | message.send() 206 | 207 | 下一步 208 | ====== 209 | 210 | .. include:: /_fragments/next-step-to-wechat-mp.rst 211 | 212 | 参考文献 213 | ======== 214 | 215 | #. `How to Embed Images in Your Emails: The Facts `_ 216 | 217 | .. include:: /_fragments/wechat-reward.rst 218 | 219 | .. include:: /_fragments/disqus.rst 220 | 221 | .. _exchangelib: https://pypi.org/project/exchangelib/ 222 | .. _PYPI: https://pypi.org/ 223 | .. _Github: https://github.com/ecederstrand/exchangelib 224 | 225 | .. comments 226 | comment something out below 227 | 228 | -------------------------------------------------------------------------------- /docs/zh_CN/libs/faker.rst: -------------------------------------------------------------------------------- 1 | .. 更优雅地造测试数据 2 | FileName: faker.rst 3 | Author: Fasion Chan 4 | Created: 2018-10-31 18:12:32 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :keywords: python, faker, 测试数据, 姓名, 地址, 手机号, 邮箱, name, address, telephone, email 14 | 15 | ================== 16 | 更优雅地造测试数据 17 | ================== 18 | 19 | 开发系统时,经常需要一些伪数据用于测试。 20 | 举个例子,设计一个学生管理系统,测试注册功能,总需要一些用户信息吧。 21 | 我猜大部分人都会填:用户 ``aaaa`` ,密码 ``1111`` ,手机号码 ``1111`` ……感觉略无追求~ 22 | 23 | 那么有没有办法造一些看上是真的数据呢?肯定是有的——人是活的嘛~ 24 | 25 | 自己造很累,有没有不需要大脑的方法的? 26 | 还真有,这就是本文要介绍的一个 `Python` 模块—— `Faker `_ 。 27 | 28 | 安装 29 | ==== 30 | 31 | 其实,这节可以不必说, `Python` 装包无非就是 `pip` 嘛: 32 | 33 | .. code-block:: shell-session 34 | 35 | $ pip install Faker 36 | 37 | 快速入手 38 | ======== 39 | 40 | 生成数据前需要先初始化一个生成器,有两种方式可以完成: 41 | 42 | #. 用 `faker.Factory.create()` ; 43 | #. 用 `faker.Faker()` ; 44 | 45 | .. code-block:: pycon 46 | 47 | >>> from faker import Factory 48 | >>> fake = Factory.create() 49 | 50 | >>> # OR 51 | >>> from faker import Faker 52 | >>> fake = Faker() 53 | 54 | >>> fake.name() 55 | 'Lucy Cechtelar' 56 | 57 | >>> fake.address() 58 | '426 Jordy Lodge Cartwrightshire, SC 88120-6700' 59 | 60 | >>> fake.text() 61 | 'Sint velit eveniet. Rerum atque repellat voluptatem quia rerum. Numquam excepturi beatae sint laudantium consequatur. Magni occaecati itaque sint et sit tempore. Nesciunt amet quidem. Iusto deleniti cum autem ad quia aperiam. A consectetur quos aliquam. In iste aliquid et aut similique suscipit. Consequatur qui quaerat iste minus hic expedita. Consequuntur error magni et laboriosam. Aut aspernatur voluptatem sit aliquam. Dolores voluptatum est. Aut molestias et maxime. Fugit autem facilis quos vero. Eius quibusdam possimus est. Ea quaerat et quisquam. Deleniti sunt quam. Adipisci consequatur id in occaecati. Et sint et. Ut ducimus quod nemo ab voluptatum.' 62 | 63 | 可以写一个循环批量生成: 64 | 65 | .. code-block:: pycon 66 | 67 | >>> for _ in range(0, 10): 68 | ... print(fake.name()) 69 | ... 70 | Adaline Reichel 71 | Dr. Santa Prosacco DVM 72 | Noemy Vandervort V 73 | Lexi O'Conner 74 | Gracie Weber 75 | Roscoe Johns 76 | Emmett Lebsack 77 | Keegan Thiel 78 | Wellington Koelpin II 79 | Ms. Karley Kiehn V 80 | 81 | 看看自动化的威力!批量生成,每次都是随机的哦! 82 | 83 | 本地化 84 | ====== 85 | 86 | 你可能会说,这个玩意儿太洋气了——生成一堆英文名字地址啥的有毛用? 87 | 确实,在计算机领域,英文有天生优势。 88 | 89 | 好在 `Faker` 还支持本地化,真是天地良心! 90 | 一起来看看怎么生成中文信息吧: 91 | 92 | .. code-block:: pycon 93 | 94 | >>> from faker import Factory 95 | >>> fake = Factory.create('zh_CN') 96 | 97 | >>> for _ in range(0, 10): 98 | ... print(fake.name()) 99 | ... 100 | 於涛 101 | 万静 102 | 孙秀荣 103 | 丘辉 104 | 方玉 105 | 虞建国 106 | 丘丽丽 107 | 郭杨 108 | 江欣 109 | 狐龙 110 | 111 | >>> for _ in range(0, 10): 112 | ... print(fake.address()) 113 | ... 114 | 杰市戚路d座 855521 115 | 丽华市魏街e座 800775 116 | 坤市莘路P座 376919 117 | 秀云市温街s座 518607 118 | 晨市季街Z座 931186 119 | 丽市夹路N座 670627 120 | 坤市漆街k座 968075 121 | 瑞市於街z座 168689 122 | 金凤市雍路E座 148292 123 | 晨市黎路R座 916369 124 | 125 | 高级用法 126 | ======== 127 | 128 | 功能扩展 129 | -------- 130 | 131 | `Faker` 已经提供了足够丰富的信息生成,包括 **名字** 、 **手机号** 、 **邮箱地址** 、 **邮编** 等。 132 | 尽管如此,可能还是没有办法满足你的需求。 133 | 这时,你可以自己动手,丰衣足食。 134 | 下面,我们通过一个例子看看怎么扩展 `Faker` 的功能吧: 135 | 136 | .. code-block:: python 137 | 138 | from faker import Faker 139 | fake = Faker() 140 | 141 | # first, import a similar Provider or use the default one 142 | from faker.providers import BaseProvider 143 | # create new provider class 144 | class MyProvider(BaseProvider): 145 | def foo(self): 146 | return 'bar' 147 | 148 | # then add new provider to faker instance 149 | fake.add_provider(MyProvider) 150 | 151 | fake.foo() 152 | 153 | 程序运行后,输出 ``bar`` 。 154 | 155 | 随机控制 156 | -------- 157 | 158 | `Faker` 随机生成由 `random.Random` 驱动。 159 | 其中, `.random` 属性返回 `random.Random` 对象。 160 | 通过对该对象的操作,可以实现自定义的行为。 161 | 162 | .. code-block:: python 163 | 164 | from faker import Faker 165 | fake = Faker() 166 | fake.random 167 | fake.random.getstate() 168 | 169 | 那么,可以实现什么自定义呢? 170 | 举个例子,我们可以设置 `seed` 。 171 | `seed` 在随机数生成逻辑中什么作用,估计大家都清楚。 172 | 比如,通过给定 `seed` 可以控制每次生成的内容都是一样的: 173 | 174 | .. code-block:: pycon 175 | 176 | >>> from faker import Faker 177 | >>> fake = Faker() 178 | >>> faker.random.seed(4321) 179 | >>> print(fake.name()) 180 | Margaret Boehm 181 | 182 | 还有等价写法哦: 183 | 184 | .. code-block:: pycon 185 | 186 | >>> from faker import Faker 187 | >>> fake = Faker() 188 | >>> fake.seed(4321) 189 | >>> print(fake.name()) 190 | Margaret Boehm 191 | 192 | 注意到,不同的两次运行,只要 `seed` 一样,生成出来的信息就是一样的。 193 | 194 | 命令行生成 195 | ---------- 196 | 197 | 有时想在 `shell` 或者其他程序中生成一些伪数据,是不是一定要写一个 `Python` 脚本呢? 198 | 当然不是—— `Faker` 提供了一个命令行工具,应该可以应对大部分场景了: 199 | 200 | .. code-block:: shell-session 201 | 202 | $ faker address 203 | 968 Bahringer Garden Apt. 722Kristinaland, NJ 09890 204 | 205 | $ faker -l de_DE address 206 | Samira-Niemeier-Allee 5694812 Biedenkopf 207 | 208 | $ faker profile ssn,birthdate 209 | {'ssn': u'628-10-1085', 'birthdate': '2008-03-29'} 210 | 211 | $ faker -r=3 -s=";" name 212 | Willam Kertzmann; 213 | Josiah Maggio; 214 | Gayla Schmitt; 215 | 216 | 最后,可以通过 `-h` 选项查看使用帮助: 217 | 218 | .. code-block:: shell-session 219 | 220 | $ faker -h 221 | usage: faker [-h] [--version] [-o output] [-l LOCALE] [-r REPEAT] [-s SEP] 222 | [-i [INCLUDE [INCLUDE ...]]] 223 | [fake] [fake argument [fake argument ...]] 224 | 225 | 下一步 226 | ====== 227 | 228 | .. include:: /_fragments/next-step-to-wechat-mp.rst 229 | 230 | .. include:: /_fragments/wechat-reward.rst 231 | 232 | .. include:: /_fragments/disqus.rst 233 | 234 | .. comments 235 | comment something out below 236 | 237 | -------------------------------------------------------------------------------- /docs/zh_CN/libs/html-table.rst: -------------------------------------------------------------------------------- 1 | .. html-table 2 | FileName: html-table.rst 3 | Author: Fasion Chan 4 | Created: 2019-04-09 15:38:19 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :keywords: python, html, table, generate, 生成, rowspan, colspan, css, 合并单元格, html-table 14 | 15 | ========== 16 | html-table 17 | ========== 18 | 19 | 在 **邮件报表** 之类的开发任务中,需要生成 `HTML` 表格。 20 | 21 | 使用 `Python` 生成 `HTML` 表格基本没啥难度, `for` 循环遍历一遍数据并输出标签即可。 22 | 如果需要实现合并单元格,或者按需调整表格样式,就比较麻烦了。 23 | 24 | 这时,可以试试本文的主角—— `html-table`_ 包,借助它可生成各种样式的 `HTML` 表格。 25 | 接下来,以一个简单的例子演示 `html-table` 的常用用法: 26 | 27 | .. figure:: /_images/libs/html-table/997ad67a7f305a39e5a77e3bf86c7798.png 28 | :width: 366px 29 | 30 | 开始之前,须通过 `pip` 安装 `html-table`_ 包: 31 | 32 | .. code-block:: shell-session 33 | 34 | $ python -m pip install html-table 35 | 36 | 安装完毕后,即可导入 `HTMLTable` 类: 37 | 38 | .. literalinclude:: /_src/libs/html-table/fruit-output.py 39 | :language: python 40 | :lines: 16-18 41 | 42 | 创建一个新表格,标题为 *果园收成表* : 43 | 44 | .. literalinclude:: /_src/libs/html-table/fruit-output.py 45 | :language: python 46 | :lines: 20-21 47 | 48 | 附上表头: 49 | 50 | .. literalinclude:: /_src/libs/html-table/fruit-output.py 51 | :language: python 52 | :lines: 23-27 53 | 54 | 注意到,表头分为两行,有些单元格需要合并,被合并的单元格需要留空占位。 55 | 56 | 合并单元格设置: 57 | 58 | .. literalinclude:: /_src/libs/html-table/fruit-output.py 59 | :language: python 60 | :lines: 29-32 61 | 62 | *table[0]* 取出第一行,即第一个 ** 标签; 63 | *table[0][0]* 取出第一个单元格,对应 **名称** ; 64 | *table[0][0].attr* 则是其标签 ** 的属性。 65 | 该单元格合并下方一个单元格,需要将标签属性 *rowspan* 设置为 *2* 。 66 | 67 | 接着,加入数据,方法与表头类似,总共有 *3* 行: 68 | 69 | .. literalinclude:: /_src/libs/html-table/fruit-output.py 70 | :language: python 71 | :lines: 34-39 72 | 73 | 至此,数据准备完毕,可以着手调整样式。先设置表格标题样式: 74 | 75 | .. literalinclude:: /_src/libs/html-table/fruit-output.py 76 | :language: python 77 | :lines: 41-44 78 | 79 | 设置 ** 标签的样式: 80 | 81 | .. literalinclude:: /_src/libs/html-table/fruit-output.py 82 | :language: python 83 | :lines: 46-53 84 | 85 | 以上 `CSS` 样式设置在 `
` 标签上,作用于整个表格,影响表格边框、字体大小等。 86 | 注意到,下面会覆盖部分单元格(如表头单元格)的字体大小。 87 | 88 | 接着,设置每个单元格的样式,主要是规定边框样式: 89 | 90 | .. literalinclude:: /_src/libs/html-table/fruit-output.py 91 | :language: python 92 | :lines: 55-62 93 | 94 | 接着,设置表头单元格样式,规定颜色、字体大小、以及填充大小: 95 | 96 | .. literalinclude:: /_src/libs/html-table/fruit-output.py 97 | :language: python 98 | :lines: 64-73 99 | 100 | `set_header_row_style` 将样式设置到表头两个 `` 标签上; 101 | `set_header_cell_style` 则将样式设置到每个 ** 标签上,而不是 *
* 标签上。 102 | 应该尽量将颜色等样式设置到 *
* 标签上,以生成精简的 *HTML* 。 103 | 104 | 将次级表头字体大小调小,不再赘述: 105 | 106 | .. literalinclude:: /_src/libs/html-table/fruit-output.py 107 | :language: python 108 | :lines: 75-79 109 | 110 | 遍历每个数据行,如果第 *2* 个单元格值小于 *0* ,设置样式标红背景颜色: 111 | 112 | .. literalinclude:: /_src/libs/html-table/fruit-output.py 113 | :language: python 114 | :lines: 81-86 115 | 116 | 最后,生成 `HTML` 文本: 117 | 118 | .. literalinclude:: /_src/libs/html-table/fruit-output.py 119 | :language: python 120 | :lines: 88-89 121 | 122 | 下一步 123 | ====== 124 | 125 | .. include:: /_fragments/next-step-to-wechat-mp.rst 126 | 127 | .. include:: /_fragments/wechat-reward.rst 128 | 129 | .. include:: /_fragments/disqus.rst 130 | 131 | .. _html-table: https://github.com/fasionchan/py-html-table 132 | 133 | .. comments 134 | comment something out below 135 | 136 | -------------------------------------------------------------------------------- /docs/zh_CN/libs/index.rst: -------------------------------------------------------------------------------- 1 | .. 推荐类库 2 | FileName: index.rst 3 | Author: Fasion Chan 4 | Created: 2018-03-14 20:37:32 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | ======== 13 | 推荐类库 14 | ======== 15 | 16 | .. toctree:: 17 | :titlesonly: 18 | 19 | exchangelib 20 | Faker 21 | html-table 22 | IPy 23 | kazoo 24 | matplotlib 25 | openpyxl 26 | tabulate 27 | zbarlight 28 | -------------------------------------------------------------------------------- /docs/zh_CN/libs/ipy.rst: -------------------------------------------------------------------------------- 1 | .. IPy 2 | FileName: ipy.rst 3 | Author: Fasion Chan 4 | Created: 2018-05-31 20:05:51 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :keywords: python, ip block, ip, ip segment 14 | 15 | === 16 | IPy 17 | === 18 | 19 | `IPy `_ 是一个用来处理 `IP` 地址和网段的类库。 20 | 21 | IP地址 22 | ====== 23 | 24 | `IP` 类用来表示 `IP` 地址, `IPv4` 和 `IPv6` 都支持。 25 | 26 | .. code-block:: pycon 27 | 28 | >>> from IPy import IP 29 | >>> IP('10.0.0.0').version() 30 | 4 31 | >>> IP('::1').version() 32 | 6 33 | 34 | 可以判断 `IP` 类型: 35 | 36 | .. code-block:: pycon 37 | 38 | >>> ip.iptype() 39 | 'PRIVATE' 40 | 41 | IP网络 42 | ====== 43 | 44 | 通过 `IP` 表示一个网络,即相邻的多个 `IP` 地址: 45 | 46 | .. code-block:: pycon 47 | 48 | >>> from IPy import IP 49 | >>> ip = IP('10.2.32.0/30') 50 | >>> ip.len() 51 | 4 52 | >>> for x in ip: 53 | ... print(x) 54 | ... 55 | 10.2.32.0 56 | 10.2.32.1 57 | 10.2.32.2 58 | 10.2.32.3 59 | 60 | 还可以通过掩码指定: 61 | 62 | .. code-block:: pycon 63 | 64 | >>> ip = IP('10.2.32.0/255.255.255.252') 65 | 66 | 也可以直接指定范围: 67 | 68 | .. code-block:: pycon 69 | 70 | >>> ip = IP('10.2.32.0-10.2.32.3') 71 | 72 | 这几种写法是等价的。 73 | 74 | 下一步 75 | ====== 76 | 77 | .. include:: /_fragments/next-step-to-wechat-mp.rst 78 | 79 | .. include:: /_fragments/wechat-reward.rst 80 | 81 | .. include:: /_fragments/disqus.rst 82 | 83 | .. comments 84 | comment something out below 85 | 86 | -------------------------------------------------------------------------------- /docs/zh_CN/libs/kazoo.rst: -------------------------------------------------------------------------------- 1 | .. kazoo 2 | FileName: kazoo.rst 3 | Author: Fasion Chan 4 | Created: 2019-01-14 15:55:55 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :description lang=zh: 14 | kazoo是一个更优雅的Zookeeper库,用法更简单,也不容易出错。 15 | 本文介绍kazoo的一些典型用法,并提供代码示例。 16 | :keywords: python, kazoo, zookeeper 17 | 18 | ===== 19 | kazoo 20 | ===== 21 | 22 | `kazoo`_ 是一个更优雅的 `Zookeeper`_ 库,用法更简单,也不容易出错。 23 | 24 | 安装 25 | ==== 26 | 27 | 开始使用 `kazoo`_ 之前,你需要先装好它。推荐从 `PYPI`_ 安装: 28 | 29 | .. code-block:: shell-session 30 | 31 | $ pip install kazoo 32 | 33 | 连接处理 34 | ======== 35 | 36 | 建立连接 37 | -------- 38 | 39 | 开始操作 `Zookeeper`_ 之前,需要先创建 `KazooClient`_ 对象并与 `Zookeeper` 建立连接: 40 | 41 | .. code-block:: python 42 | 43 | from kazoo.client import KazooClient 44 | 45 | zk = KazooClient(hosts='127.0.0.1:2181') 46 | zk.start() 47 | 48 | 默认,客户端通过本地端口( *2181* )连接 `Zookeeper` 服务器。 49 | 这种情况下,需要先确保 `Zookeeper` 已在本地运行,否则 `start` 方法将一直等待直到超时。 50 | 51 | 一旦成功连接,客户端会尝试保持连接状态,自动处理 **间歇性连接中断** 以及 **会话过期** 等问题。 52 | 如果需要放弃当前连接,需要调用 `stop` 方法: 53 | 54 | .. code-block:: python 55 | 56 | zk.stop() 57 | 58 | 鉴权 59 | ---- 60 | 61 | 如果 `Zookeeper` 设置了用户密码,则需要额外指定: 62 | 63 | .. code-block:: python 64 | 65 | zk = KazooClient( 66 | hosts='127.0.0.1:2181', 67 | auto_data=[ 68 | ('digest', 'user:password'), 69 | ], 70 | ) 71 | 72 | 监听连接事件 73 | ------------ 74 | 75 | 掌握连接状态非常重要,用户需要知晓 **连接中断** 、 **重连** 以及 **会话过期** 等事件。 76 | 为了简化处理逻辑, `kazoo`_ 将其抽象成一个状态系统。 77 | 用户可以在上面注册监听函数,监听函数在连接状态发生变化时得到调用。 78 | 79 | .. code-block:: python 80 | 81 | from kazoo.client import KazooState 82 | 83 | def my_listener(state): 84 | if state == KazooState.LOST: 85 | # 连接丢失 86 | elif state == KazooState.SUSPENDED: 87 | # 连接断开 88 | else: 89 | # 连接建立或重连 90 | 91 | zk.add_listener(my_listener) 92 | 93 | 在使用 `kazoo.recipe.lock.Lock`_ 或者创建临时节点等场景, 94 | 强烈建议添加状态监听函数,以便程序在连接中断或者会话丢失时可以正确应对。 95 | 96 | 理解连接状态 97 | ------------ 98 | 99 | 日志设置 100 | -------- 101 | 102 | 如果应用代码未设置 `logging` ,则可能出现以下错误信息: 103 | 104 | .. code-block:: text 105 | 106 | No handlers could be found for logger "kazoo.client" 107 | 108 | 为了避免这个问题,你可以添加以下两行代码: 109 | 110 | .. code-block:: python 111 | 112 | import logging 113 | logging.basicConfig() 114 | 115 | 增删改查 116 | ======== 117 | 118 | 读取数据 119 | -------- 120 | 121 | 相关方法: 122 | 123 | - *exists()* ,检查路径节点是否存在; 124 | - *get()* ,读取节点数据以及节点详情信息( `ZnodeStat` 对象); 125 | - *get_children()* ,获取指定节点下所有子节点; 126 | 127 | 判断路径节点是否存在: 128 | 129 | .. code-block:: python 130 | 131 | if zk.exists('/path/to/given/node'): 132 | # do something 133 | 134 | 读取节点数据以及版本: 135 | 136 | .. code-block:: python 137 | 138 | data, stat = zk.get('/path/to/given/node') 139 | print('Version:', stat.version) 140 | print('Data:', data.decode('utf-8')) 141 | 142 | 列举子节点: 143 | 144 | .. code-block:: python 145 | 146 | children = zk.get_children('/path/to/given/node') 147 | for child in children: 148 | print('Child:', child) 149 | 150 | 下一步 151 | ====== 152 | 153 | .. include:: /_fragments/next-step-to-wechat-mp.rst 154 | 155 | 参考文献 156 | ======== 157 | 158 | #. `Basic Usage — kazoo 2.6.0 documentation `_ 159 | 160 | .. include:: /_fragments/wechat-reward.rst 161 | 162 | .. include:: /_fragments/disqus.rst 163 | 164 | .. _kazoo: https://kazoo.readthedocs.io/en/latest/index.html 165 | .. _kazoo.recipe.lock.Lock: https://kazoo.readthedocs.io/en/latest/api/recipe/lock.html#kazoo.recipe.lock.Lock 166 | .. _KazooClient: https://kazoo.readthedocs.io/en/latest/api/client.html#kazoo.client.KazooClient 167 | .. _PYPI: https://pypi.org/ 168 | .. _Zookeeper: https://zookeeper.apache.org/ 169 | 170 | .. comments 171 | comment something out below 172 | 173 | -------------------------------------------------------------------------------- /docs/zh_CN/libs/matplotlib/index.rst: -------------------------------------------------------------------------------- 1 | .. matplotlib 2 | FileName: index.rst 3 | Author: Fasion Chan 4 | Created: 2019-01-03 18:36:43 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :description lang=zh: 14 | matplotlib是一个用于科学计算绘图的Python包,功能非常强大,堪比Matlab! 15 | 饼状图应该是最简单的统计图表了,用以介绍matplotlib画图方式最为合适。 16 | 让matplotlib支持中文的方式有不少,接下来介绍一种最简单的。 17 | :keywords: python, matplotlib, matlab, pie, font, 中文, 统计图表, 科学计算 18 | 19 | ========== 20 | matplotlib 21 | ========== 22 | 23 | `matplotlib`_ 是一个用于 **科学计算绘图** 的 `Python` 包,功能非常强大,堪比 `Matlab`_ ! 24 | 开始前,先通过几张图来感受一下: 25 | 26 | .. figure:: /_images/libs/matplotlib/index/93498df23549c42e72dcd5361dce6f7b.png 27 | 28 | 29 | 快速开始 30 | ======== 31 | 32 | 饼状图应该是最简单的统计图表了,用以介绍 `matplotlib`_ 画图方式最为合适。 33 | 数据准备就绪,生成饼状图只需若干行代码: 34 | 35 | .. literalinclude:: /_src/libs/matplotlib/pie.py 36 | :caption: 37 | :name: libs/matplotlib/pie.py 38 | :language: python 39 | :lines: 19- 40 | :linenos: 41 | 42 | 第 *4-5* 行,为待渲染数据,包括 **数值** 以及 **标签** ; 43 | 第 *7* 行,定义渲染 **颜色** ; 44 | 第 *9-14* 行,配置饼图,包括数值、标签、颜色以及百分比展示; 45 | 第 *16* 行,为图表追加 **标题** ; 46 | 第 *18* 行,将图表展示出来。 47 | 48 | 运行程序后,画出的图表效果如下: 49 | 50 | .. figure:: /_images/libs/matplotlib/index/ca76641457d181dd6713f2f5d6681164.png 51 | :width: 640px 52 | 53 | 字体 54 | ==== 55 | 56 | 在编程世界,中文一直是个麻烦事。 57 | 不折腾一番, `matplotlib`_ 是不能渲染中文文本的。 58 | 59 | 让 `matplotlib`_ **支持中文** 的方式有不少,接下来介绍一种最简单的: 60 | 准备好字体文件,为文本定义 `FontProperties`_ 并设置。 61 | 除了指定 **字体** , `FontProperties`_ 还支持 **字号** 、 **粗细** 、 **斜体** 、 **下划线** 等属性设置。 62 | 63 | .. literalinclude:: /_src/libs/matplotlib/font.py 64 | :caption: 65 | :name: libs/matplotlib/font.py 66 | :language: python 67 | :lines: 19- 68 | :linenos: 69 | 70 | 程序第 `11-15` 行加载字体文件,并设置字号; 71 | 第 `17-18` 行在第一个标签字体基础上设置新字号,作为标题字体, 72 | 第 `33-34` 行为 *4* 个标签分别设置字体; 73 | 第 `36` 行指定标题,同时设置标题字体。 74 | 75 | 运行程序后,画出的图表效果如下: 76 | 77 | .. figure:: /_images/libs/matplotlib/index/47e3e92e52e71feb5b01afe83a5b4135.png 78 | :width: 640px 79 | 80 | .. note:: 81 | 82 | `Github`_ 上有个项目提供一些字体文件,以供测试: `dolbydu/font `_ 。 83 | 84 | 保存图片 85 | ======== 86 | 87 | 将图表保存成文件,只需调用 `savefig` 方法。保存为 `PNG` 图片: 88 | 89 | .. code-block:: python 90 | 91 | plt.savefig('foo.png') 92 | 93 | 文件格式由文件后缀名决定,另存为 `PDF` 文件: 94 | 95 | .. code-block:: python 96 | 97 | plt.savefig('foo.pdf') 98 | 99 | 如果仅需获取保存文件内容,则可借助 `BytesIO` : 100 | 101 | .. code-block:: python 102 | 103 | import io 104 | 105 | bio = io.BytesIO() 106 | plt.savefig(bio, format='png') 107 | 108 | bio.seek(0) 109 | content = bio.read() 110 | 111 | 下一步 112 | ====== 113 | 114 | .. toctree:: 115 | :titlesonly: 116 | 117 | 疑难杂症 118 | 119 | .. include:: /_fragments/next-step-to-wechat-mp.rst 120 | 121 | 参考文献 122 | ======== 123 | 124 | #. `Matplotlib Pie chart - Python Tutorials `_ 125 | 126 | .. include:: /_fragments/wechat-reward.rst 127 | 128 | .. include:: /_fragments/disqus.rst 129 | 130 | .. _FontProperties: https://matplotlib.org/api/font_manager_api.html#matplotlib.font_manager.FontProperties 131 | .. _Github: https://github.com 132 | .. _Matlab: https://www.mathworks.com/products/matlab.html 133 | .. _matplotlib: https://matplotlib.org 134 | 135 | .. comments 136 | comment something out below 137 | 138 | -------------------------------------------------------------------------------- /docs/zh_CN/libs/matplotlib/issues.rst: -------------------------------------------------------------------------------- 1 | .. 疑难杂症 2 | FileName: issues.rst 3 | Author: Fasion Chan 4 | Created: 2019-01-08 19:04:50 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :description lang=zh: 14 | 本文记录一些使用matplotlib过程中遇到的问题,以及针对问题的解决方案。 15 | :keywords: matplotlib, 常见问题, backend, framework, Agg, TkAgg, 椭圆 16 | 17 | ======== 18 | 疑难杂症 19 | ======== 20 | 21 | 本文记录一些使用 `matplotlib`_ 过程中遇到的 **问题** ,以及针对问题的 **解决方案** 。 22 | 23 | backend 24 | ======= 25 | 26 | 在 `OSX`_ 下,用 `virtualenv` 提供的虚拟 `Python` 环境运行 `matplotlib` ,会抛异常: 27 | 28 | .. code-block:: text 29 | 30 | ImportError: Python is not installed as a framework. The Mac OS X backend will not be able to function correctly if Python is not installed as a framework. See the Python documentation for more information on installing Python as a framework on Mac OS X. Please either reinstall Python as a framework, or try one of the other backends. If you are using (Ana)Conda please install python.app and replace the use of 'python' with 'pythonw'. See 'Working with Matplotlib on OSX' in the Matplotlib FAQ for more information. 31 | 32 | 关键信息是, `Python` 不是作为 `framework` 安装,因此找不到 `Mac OS X backend` 。 33 | 解决方法也非常简单,只需在使用 `matplotlib` 之前,先设置使用 `TkAgg` : 34 | 35 | .. code-block:: python 36 | 37 | import matplotlib 38 | matplotlib.use('TkAgg') 39 | 40 | import matplotlib.pyplot as plt 41 | 42 | 当然了,也可以将设置写到配置文件,一劳永逸: 43 | 44 | .. code-block:: shell-session 45 | 46 | $ cat ~/.matplotlib/matplotlibrc 47 | backend: TkAgg 48 | 49 | 详情请参考文章: 50 | `Python via virtualenv on Mac OS X: RuntimeError: Python is not installed as a framework. `_ 51 | 。 52 | 53 | 圆形不圆 54 | ======== 55 | 56 | 使用 `pyinstaller` 对程序进行打包后再运行,发现一个诡异的现象: 57 | 用 `pie` 方法画出的饼状图变成了一个椭圆! 58 | 同样的程序直接运行 `python` 命令运行是完全正常的,这太奇怪了! 59 | 应该是 `pyinstaller` 额外运行一些 `hook` 代码导致的,由于时间关系没细究。 60 | 61 | 为了解决这个问题,只需添加一行代码: 62 | 63 | .. code-block:: python 64 | 65 | ax.set_aspect('equal') 66 | 67 | 详情请参考文章: 68 | `Why is matplotlib plotting my circles as ovals? - Stack Overflow `_ 69 | 。 70 | 71 | 参考文献 72 | ======== 73 | 74 | #. `Python via virtualenv on Mac OS X: RuntimeError: Python is not installed as a framework. `_ 75 | #. `Why is matplotlib plotting my circles as ovals? - Stack Overflow `_ 76 | 77 | .. _matplotlib: https://matplotlib.org 78 | .. _OSX: https://osx-guide.readthedocs.io/zh_CN/latest/ 79 | 80 | .. comments 81 | comment something out below 82 | 83 | -------------------------------------------------------------------------------- /docs/zh_CN/libs/openpyxl.rst: -------------------------------------------------------------------------------- 1 | .. openpyxl 2 | FileName: openpyxl.rst 3 | Author: Fasion Chan 4 | Created: 2018-10-15 20:44:41 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :keywords: python, excel, openpyxl 14 | 15 | ======== 16 | openpyxl 17 | ======== 18 | 19 | `Python` 可以读写 `Excel` 表格吗? 20 | 21 | 当然可以。 `Python` 下有很多类库可以做到, `openpyxl`_ 就是其中的佼佼者。 22 | 23 | `openpyxl`_ 的 **设计非常漂亮** ,你一定会喜欢它!不信请往下看: 24 | 25 | 工作簿 26 | ====== 27 | 28 | 开始 `openpyxl`_ 前,无需提前建好工作簿( `Workbook` )。 29 | 只需导入 `Workbook` 类,便可在内存中创建新工作簿并开始操作: 30 | 31 | .. code-block:: pycon 32 | 33 | >>> from openpyxl import Workbook 34 | >>> wb = Workbook() 35 | 36 | 新建的工作簿默认预先建好一个工作表,通过 `active` 属性即可获取: 37 | 38 | .. code-block:: pycon 39 | 40 | >>> ws = wb.active 41 | 42 | .. note:: 43 | 44 | 如果工作簿包含多个工作表,该属性将返回第一个。 45 | 46 | 通过 `create_sheet` 方法,可以创建新的工作表。 47 | 创建可以是在后面追加: 48 | 49 | .. code-block:: pycon 50 | 51 | >>> ws1 = wb.create_sheet('Mysheet') 52 | 53 | 或者,在前面插入: 54 | 55 | .. code-block:: pycon 56 | 57 | >>> ws1 = wb.create_sheet('Mysheet', 0) 58 | 59 | 未指定表格名将自动生成,序列形如: `Sheet` 、 `Sheet1` 、 `Sheet2` ,以此类推。 60 | 当然了,你觉得不合适可以进行修改: 61 | 62 | .. code-block:: pycon 63 | 64 | >>> ws.title = 'New Title' 65 | 66 | 工作表标题标签背景颜色默认是白色。 67 | 用一个 `RGB` 颜色代码设置 `sheet_properties.tabColor` 属性即可修改: 68 | 69 | .. code-block:: pycon 70 | 71 | >>> ws.sheet_properties.tabColor = "1072BA" 72 | 73 | 一旦你给工作表命名,便可以通过该名字来定位: 74 | 75 | .. code-block:: pycon 76 | 77 | >>> ws3 = wb["New Title"] 78 | 79 | 通过 `sheetnames` 属性,可以取出所有工作表表名: 80 | 81 | .. code-block:: pycon 82 | 83 | >>> print(wb.sheetnames) 84 | ['Sheet2', 'New Title', 'Sheet1'] 85 | 86 | 当然了,遍历所有工作表,直接 `for-in` 更为优雅: 87 | 88 | .. code-block:: pycon 89 | 90 | >>> for sheet in wb: 91 | ... print(sheet.title) 92 | 93 | 使用 `copy_worksheet` 方法,可在工作簿内拷贝工作表: 94 | 95 | .. code-block:: pycon 96 | 97 | >>> source = wb.active 98 | >>> target = wb.copy_worksheet(source) 99 | 100 | 从文件加载 101 | ---------- 102 | 103 | 如果已有工作簿,可通过 `openpyxl.load_workbook` 函数进行加载: 104 | 105 | .. code-block:: pycon 106 | 107 | >>> from openpyxl import load_workbook 108 | >>> wb2 = load_workbook('test.xlsx') 109 | >>> print wb2.sheetnames 110 | ['Sheet2', 'New Title', 'Sheet1'] 111 | 112 | 数据处理 113 | ======== 114 | 115 | 单个单元格 116 | ---------- 117 | 118 | 操作工作表,从修改单元格内容开始。单元格可以通过工作表键直接访问: 119 | 120 | .. code-block:: pycon 121 | 122 | >>> cell = ws['A4'] 123 | 124 | 这个语句将返回 `A4` 单元格,或者在单元格不存在时创建它。可以直接赋值: 125 | 126 | .. code-block:: pycon 127 | 128 | >>> ws['A4'] = 10 129 | 130 | 另一种方式是使用 `cell` 方法访问单元格,指定行和列: 131 | 132 | .. code-block:: pycon 133 | 134 | >>> cell = ws.cell(row=4, column=2, value=10) 135 | 136 | .. note:: 137 | 138 | 工作表创建后,不包含任何单元格,单元格在第一次被访问时自动创建。 139 | 140 | 多单元格 141 | -------- 142 | 143 | 连续多个单元格可以通过切片获得: 144 | 145 | .. code-block:: pycon 146 | 147 | >>> cell_range = ws['A1':'C2'] 148 | 149 | 切片取得的单元格范围如下: 150 | 151 | .. figure:: /_images/libs/openpyxl/004c33e629837e01938a4810910f17b2.png 152 | 153 | 以行或列为单位也可以: 154 | 155 | .. code-block:: pycon 156 | 157 | # 取出 C 列 158 | >>> colC = ws['C'] 159 | 160 | # 取出 C 至 D 列 161 | >>> col_range = ws['C:D'] 162 | 163 | # 取出第 10 行 164 | >>> row10 = ws[10] 165 | 166 | # 取出第 5 至 10 行 167 | >>> row_range = ws[5:10] 168 | 169 | 使用 `iter_rows` 方法也可以: 170 | 171 | .. code-block:: pycon 172 | 173 | # 从第 1 行开始遍历,直到第 2 行,每行最多返回 3 列 174 | >>> for row in ws.iter_rows(min_row=1, max_row=2, max_col=3): 175 | ... for cell in row: 176 | ... print(cell) 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 如需遍历表格所有行或列,可以使用相关属性。使用 `rows` 属性遍历所有行: 185 | 186 | .. code-block:: pycon 187 | 188 | >>> ws = wb.active 189 | >>> ws['C9'] = 'hello world' 190 | >>> tuple(ws.rows) 191 | ((, , ), 192 | (, , ), 193 | (, , ), 194 | (, , ), 195 | (, , ), 196 | (, , ), 197 | (, , ), 198 | (, , ), 199 | (, , )) 200 | 201 | 使用 `columns` 属性遍历所有列: 202 | 203 | .. code-block:: pycon 204 | 205 | >>> tuple(ws.columns) 206 | ((, 207 | , 208 | , 209 | , 210 | , 211 | , 212 | ... 213 | , 214 | , 215 | ), 216 | (, 217 | , 218 | , 219 | , 220 | , 221 | , 222 | , 223 | , 224 | )) 225 | 226 | 数据存储 227 | ======== 228 | 229 | `Excel` 表格通过单元格存储数据,直接赋值即可: 230 | 231 | .. code-block:: pycon 232 | 233 | >>> cell.value = 'hello, world' 234 | >>> print(cell.value) 235 | 'hello, world' 236 | 237 | >>> cell2.value = 3.14 238 | >>> print(cell2.value) 239 | 3.14 240 | 241 | 与此同时,还可以给单元格附加类型以及格式化信息。有个前提,创建工作簿时需要指定 `guess_types` 参数: 242 | 243 | .. code-block:: pycon 244 | 245 | >>> wb = Workbook(guess_types=True) 246 | 247 | 这样一来,文本(包括百分比)将自动转换成浮点数: 248 | 249 | .. code-block:: pycon 250 | 251 | >>> cell.value = '31.50' 252 | >>> print(cell.value) 253 | 31.5 254 | 255 | >>> cell2.value = '12%' 256 | >>> print(cell2.value) 257 | 0.12 258 | 259 | 日期可以直接由原生的 `datetime`_ 对象来设置: 260 | 261 | .. code-block:: pycon 262 | 263 | >>> import datetime 264 | >>> cell.value = datetime.datetime.now() 265 | >>> print cell.value 266 | datetime.datetime(2010, 9, 10, 22, 25, 18) 267 | 268 | 269 | 保存至文件 270 | ---------- 271 | 272 | 最保险的保存方式是调用 `save` 方法保存到指定文件: 273 | 274 | .. code-block:: pycon 275 | 276 | >>> wb = Workbook() 277 | >>> wb.save('balances.xlsx') 278 | 279 | .. warning:: 280 | 281 | 这个操作将覆盖已存在的文件,没有任何提示! 282 | 283 | 借助 `template` 属性,可以将工作表保存成文档: 284 | 285 | .. code-block:: pycon 286 | 287 | >>> wb = load_workbook('document.xlsx') 288 | >>> wb.template = True 289 | >>> wb.save('document_template.xltx') 290 | 291 | 或者保存成普通文档: 292 | 293 | .. code-block:: pycon 294 | 295 | >>> wb = load_workbook('document_template.xltx') 296 | >>> wb.template = False 297 | >>> wb.save('document.xlsx', as_template=False) 298 | 299 | 300 | 保存至流 301 | -------- 302 | 303 | 在 `Flask` 、 `Django` 等 `Web` 应用,可能需要将文件保存到流( `stream` )。 304 | 借助一个临时文件( `NamedTemporaryFile` )可以轻松实现: 305 | 306 | .. code-block:: pycon 307 | 308 | >>> from tempfile import NamedTemporaryFile 309 | >>> from openpyxl import Workbook 310 | >>> wb = Workbook() 311 | 312 | # 先保存到临时文件,再将文件内容读出 313 | >>> with NamedTemporaryFile() as tmp: 314 | ... wb.save(tmp.name) 315 | ... tmp.seek(0) 316 | ... stream = tmp.read() 317 | 318 | 下一步 319 | ====== 320 | 321 | .. include:: /_fragments/next-step-to-wechat-mp.rst 322 | 323 | .. include:: /_fragments/wechat-reward.rst 324 | 325 | .. include:: /_fragments/disqus.rst 326 | 327 | .. _openpyxl: https://openpyxl.readthedocs.io/en/stable/ 328 | .. _datetime: https://docs.python.org/3/library/datetime.html#datetime-objects 329 | 330 | .. comments 331 | comment something out below 332 | 333 | -------------------------------------------------------------------------------- /docs/zh_CN/libs/tabulate.rst: -------------------------------------------------------------------------------- 1 | .. tabulate 2 | FileName: tabulate.rst 3 | Author: Fasion Chan 4 | Created: 2018-03-14 20:40:35 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :description lang=zh: 14 | 用过 MySQL 的童鞋一定对那个非常好看的字符表格印象深刻吧! 15 | 在 Python 中,使用 tabulate 库,可轻松实现一模一样的字符表格。 16 | from tabulate import tabulate 17 | print(tabulate(table_data, headers=table_header, tablefmt='grid')) 18 | :keywords: python, tabulate, 输出表格, 字符表格, 格式化表格式数据, MySQL表格输出 19 | 20 | ======== 21 | tabulate 22 | ======== 23 | 24 | 用过 ``MySQL`` 的童鞋一定对那个非常好看的字符表格印象深刻吧! 25 | 26 | 在 `Python` 中,使用 `tabulate `_ 库,可轻松实现一模一样的字符表格。 27 | 28 | 快速上手 29 | ======== 30 | 31 | 废话不多说,先来看看效果: 32 | 33 | .. code-block:: pycon 34 | 35 | >>> from tabulate import tabulate 36 | 37 | >>> table_header = ['Name', 'Chinese', 'Math', 'English'] 38 | >>> table_data = [ 39 | ... ('Tom', '90', '80', '85'), 40 | ... ('Jim', '70', '90', '80'), 41 | ... ('Lucy', '90', '70', '90'), 42 | ... ] 43 | 44 | >>> print(tabulate(table_data, headers=table_header, tablefmt='grid')) 45 | +--------+-----------+--------+-----------+ 46 | | Name | Chinese | Math | English | 47 | +========+===========+========+===========+ 48 | | Tom | 90 | 80 | 85 | 49 | +--------+-----------+--------+-----------+ 50 | | Jim | 70 | 90 | 80 | 51 | +--------+-----------+--------+-----------+ 52 | | Lucy | 90 | 70 | 90 | 53 | +--------+-----------+--------+-----------+ 54 | 55 | 上述代码,先从 `tabulate` 库导入同名工具函数; 56 | 接着,定义一个用于演示的数据表格,包括表头和表数据; 57 | 最后,用 ``tabulate`` 函数格式化表格,传参包括表数据,表头以及表格样式。 58 | 59 | 看到没有,引入 ``tabulate`` 函数后,只需要一行代码即可完成表格输出! 60 | 61 | 回过头来看看如何安装 `tabulate` 。你可能已经猜到了: 62 | 63 | .. code-block:: shell-session 64 | 65 | $ pip install tabulate 66 | 67 | 是的,就是这么简单! 68 | 69 | 中文对齐 70 | ======== 71 | 72 | 默认没有考虑中文字符宽度,因此无法对齐: 73 | 74 | .. code-block:: text 75 | 76 | +---------+--------+---------+--------+ 77 | | 工具 | 持仓 | 总成本 | 平均成本 | 78 | +---------+--------+---------+--------+ 79 | 80 | 解决这个问题只需安装 `wcwidth` 包: 81 | 82 | .. code-block:: shell-session 83 | 84 | $ pip install wcwidth 85 | 86 | 并在代码中导入: 87 | 88 | .. code-block:: python 89 | 90 | import wcwidth 91 | 92 | 表格样式 93 | ======== 94 | 95 | `tabulate` 提供多种表格输出风格,列举如下: 96 | 97 | plain 98 | ----- 99 | 100 | .. code-block:: pycon 101 | 102 | >>> print(tabulate(table_data, headers=table_header, tablefmt='plain')) 103 | Name Chinese Math English 104 | Tom 90 80 85 105 | Jim 70 90 80 106 | Lucy 90 70 90 107 | 108 | simple 109 | ------ 110 | 111 | .. code-block:: pycon 112 | 113 | >>> print(tabulate(table_data, headers=table_header, tablefmt='simple')) 114 | Name Chinese Math English 115 | ------ --------- ------ --------- 116 | Tom 90 80 85 117 | Jim 70 90 80 118 | Lucy 90 70 90 119 | 120 | grid 121 | ---- 122 | 123 | .. code-block:: pycon 124 | 125 | >>> print(tabulate(table_data, headers=table_header, tablefmt='grid')) 126 | +--------+-----------+--------+-----------+ 127 | | Name | Chinese | Math | English | 128 | +========+===========+========+===========+ 129 | | Tom | 90 | 80 | 85 | 130 | +--------+-----------+--------+-----------+ 131 | | Jim | 70 | 90 | 80 | 132 | +--------+-----------+--------+-----------+ 133 | | Lucy | 90 | 70 | 90 | 134 | +--------+-----------+--------+-----------+ 135 | 136 | fancy_grid 137 | ---------- 138 | 139 | .. code-block:: pycon 140 | 141 | >>> print(tabulate(table_data, headers=table_header, tablefmt='fancy_grid')) 142 | ╒════════╤═══════════╤════════╤═══════════╕ 143 | │ Name │ Chinese │ Math │ English │ 144 | ╞════════╪═══════════╪════════╪═══════════╡ 145 | │ Tom │ 90 │ 80 │ 85 │ 146 | ├────────┼───────────┼────────┼───────────┤ 147 | │ Jim │ 70 │ 90 │ 80 │ 148 | ├────────┼───────────┼────────┼───────────┤ 149 | │ Lucy │ 90 │ 70 │ 90 │ 150 | ╘════════╧═══════════╧════════╧═══════════╛ 151 | 152 | pipe 153 | ---- 154 | 155 | .. code-block:: pycon 156 | 157 | >>> print(tabulate(table_data, headers=table_header, tablefmt='pipe')) 158 | | Name | Chinese | Math | English | 159 | |:-------|----------:|-------:|----------:| 160 | | Tom | 90 | 80 | 85 | 161 | | Jim | 70 | 90 | 80 | 162 | | Lucy | 90 | 70 | 90 | 163 | 164 | orgtlb 165 | ------ 166 | 167 | .. code-block:: pycon 168 | 169 | >>> print(tabulate(table_data, headers=table_header, tablefmt='orgtbl')) 170 | | Name | Chinese | Math | English | 171 | |--------+-----------+--------+-----------| 172 | | Tom | 90 | 80 | 85 | 173 | | Jim | 70 | 90 | 80 | 174 | | Lucy | 90 | 70 | 90 | 175 | 176 | jira 177 | ---- 178 | 179 | .. code-block:: pycon 180 | 181 | >>> print(tabulate(table_data, headers=table_header, tablefmt='jira')) 182 | || Name || Chinese || Math || English || 183 | | Tom | 90 | 80 | 85 | 184 | | Jim | 70 | 90 | 80 | 185 | | Lucy | 90 | 70 | 90 | 186 | 187 | presto 188 | ------ 189 | 190 | .. code-block:: pycon 191 | 192 | >>> print(tabulate(table_data, headers=table_header, tablefmt='presto')) 193 | Name | Chinese | Math | English 194 | --------+-----------+--------+----------- 195 | Tom | 90 | 80 | 85 196 | Jim | 70 | 90 | 80 197 | Lucy | 90 | 70 | 90 198 | 199 | psql 200 | ---- 201 | 202 | .. code-block:: pycon 203 | 204 | >>> print(tabulate(table_data, headers=table_header, tablefmt='psql')) 205 | +--------+-----------+--------+-----------+ 206 | | Name | Chinese | Math | English | 207 | |--------+-----------+--------+-----------| 208 | | Tom | 90 | 80 | 85 | 209 | | Jim | 70 | 90 | 80 | 210 | | Lucy | 90 | 70 | 90 | 211 | +--------+-----------+--------+-----------+ 212 | 213 | rst 214 | --- 215 | 216 | .. code-block:: pycon 217 | 218 | >>> print(tabulate(table_data, headers=table_header, tablefmt='rst')) 219 | ====== ========= ====== ========= 220 | Name Chinese Math English 221 | ====== ========= ====== ========= 222 | Tom 90 80 85 223 | Jim 70 90 80 224 | Lucy 90 70 90 225 | ====== ========= ====== ========= 226 | 227 | html 228 | ---- 229 | 230 | .. code-block:: pycon 231 | 232 | >>> print(tabulate(table_data, headers=table_header, tablefmt='html')) 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 |
Name Chinese Math English
Tom 90 80 85
Jim 70 90 80
Lucy 90 70 90
243 | 244 | 注意到, ``tabulate`` 函数也可以用来生成 ``html`` 表格定义代码。 245 | 此外,还支持 ``mediawiki`` 、 ``moinmoin`` 、 ``youtrack`` 、 ``latex`` 、 ``latex_raw`` 、 ``latex__booktabs`` 、 ``textile`` 表格生成。 246 | 247 | 下一步 248 | ====== 249 | 250 | .. include:: /_fragments/next-step-to-wechat-mp.rst 251 | 252 | .. include:: /_fragments/wechat-reward.rst 253 | -------------------------------------------------------------------------------- /docs/zh_CN/libs/zbarlight.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Author: fasion 3 | Created time: 2018-11-19 10:30:21 4 | Last Modified by: fasion 5 | Last Modified time: 2020-03-07 21:09:20 6 | 7 | 8 | ========= 9 | zbarlight 10 | ========= 11 | 12 | `zbarlight `_ 是 `zbar `_ 库的一个封装,可以方便地读取(识别)二维码内容。 13 | 14 | 安装 15 | ==== 16 | 17 | 安装 `zbarlight` 之前,需要先安装 `zbar` 以及其头文件。 18 | 因此,安装方式因平台而异: 19 | 20 | Debian 21 | ------ 22 | 23 | .. code-block:: shell 24 | 25 | sudo apt-get install libzbar0 libzbar-dev 26 | sudo pip install zbarlight 27 | 28 | Mac OS X 29 | -------- 30 | 31 | .. code-block:: shell 32 | 33 | brew install zbar 34 | export LDFLAGS="-L$(brew --prefix zbar)/lib" 35 | export CFLAGS="-I$(brew --prefix zbar)/include" 36 | pip install zbarlight 37 | 38 | 例子 39 | ==== 40 | 41 | .. literalinclude:: /_src/libs/zbarlight/read_qrcode.py 42 | :caption: 43 | :name: libs/zbarlight/read_qrcode.py 44 | :language: python 45 | :linenos: 46 | :lines: 16-29 47 | 48 | 这个例子非常简单: 49 | 第 ``8`` - ``10`` 行打开文件并加载二维码图片, 50 | 第 ``12`` 行调用 ``zbarlight`` 工具函数识别二维码。 51 | 52 | 下一步 53 | ====== 54 | 55 | .. include:: /_fragments/next-step-to-wechat-mp.rst 56 | 57 | .. include:: /_fragments/wechat-reward.rst 58 | 59 | .. include:: /_fragments/disqus.rst 60 | 61 | .. comments 62 | comment something out below 63 | 64 | .. meta:: 65 | :description lang=zh: 66 | :keywords: 67 | 68 | -------------------------------------------------------------------------------- /docs/zh_CN/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | set SPHINXPROJ=Python 13 | 14 | if "%1" == "" goto help 15 | 16 | %SPHINXBUILD% >NUL 2>NUL 17 | if errorlevel 9009 ( 18 | echo. 19 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 20 | echo.installed, then set the SPHINXBUILD environment variable to point 21 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 22 | echo.may add the Sphinx directory to PATH. 23 | echo. 24 | echo.If you don't have Sphinx installed, grab it from 25 | echo.http://sphinx-doc.org/ 26 | exit /b 1 27 | ) 28 | 29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 30 | goto end 31 | 32 | :help 33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 34 | 35 | :end 36 | popd 37 | -------------------------------------------------------------------------------- /docs/zh_CN/practices/argparse.rst: -------------------------------------------------------------------------------- 1 | .. 处理命令行参数 2 | FileName: argparse.rst 3 | Author: Fasion Chan 4 | Created: 2018-03-10 15:53:31 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | ============== 13 | 处理命令行参数 14 | ============== 15 | 16 | 在程序开发中,经常需要调整程序的执行行为。 17 | 18 | 大部分情况下,最佳实践是—— **实现规范的命令行参数** ,而不是动不动就改代码。 19 | 试想一下,程序配置文件是通过命令行指定好呢?还是写死在代码里好呢? 20 | 21 | 每个程序都应该实现 ``-h`` 或者 ``--help`` 参数选项,输出帮助信息。 22 | 这样一来,谁都可以通过该途径获悉程序用法,应用自如。 23 | 这便是惯例的力量! 24 | 25 | 实现命令行参数的成本也不高,大部分语言都提供了足够方便的程序库,无需也不推荐重复造轮子: 26 | 27 | `Python `_ 程序可以通过标准库 `argparse `_ 解析命令行参数。 28 | 29 | 快速上手 30 | ======== 31 | 32 | 接下来,以一个名为 `AgentX` 的程序为例,讲解如何使用 `argparse `_ 模块。 33 | `AgentX` 的用法如下: 34 | 35 | .. code-block:: shell-session 36 | 37 | $ python agentx.py -h 38 | usage: agentx [-h] [-c conf_path] action 39 | 40 | positional arguments: 41 | action action to carry out: status/start/stop 42 | 43 | optional arguments: 44 | -h, --help show this help message and exit 45 | -c conf_path, --conf conf_path 46 | configuration file path 47 | 48 | ``-h`` 选项显示帮助文档; ``-c`` 选项指定配置文件目录; 49 | 位置参数 ``action`` 指定要执行的操作。 50 | 51 | 借助 `argparse `_ ,解析命令行参数只需代码若干: 52 | 53 | .. literalinclude:: /_src/practices/argparse/agentx.py 54 | :caption: 55 | :name: practices/argparse/agentx.py 56 | :language: python 57 | :linenos: 58 | 59 | 代码看似很长,但参数解析部分却只有一小段。 60 | 61 | 第 ``19`` - ``57`` 行是服务控制类 ``ServiceController`` 定义,我们需要根据命令行参数驱动该类执行选定逻辑。 62 | 63 | 紧接着是 ``main`` 函数定义,命令行解析逻辑代码所在。 64 | 65 | ``68`` 行处先初始化一个参数解析器, ``prog`` 参数是程序名字。 66 | 67 | ``82`` 行处是 ``-c`` 参数的定义: ``dest`` 执行参数值存放位置; 68 | ``metavar`` 是选项名称占位符,与 ``help`` 结合在帮助文档中显示; 69 | ``default`` 是默认值; ``required`` 指定选项是否必填。 70 | 71 | ``82`` 行处是位置参数 ``action`` 的定义: 72 | ``nargs`` 指定参数个数,这里为 ``1`` ; 73 | ``choices`` 指定参数可选值。 74 | 75 | ``91`` 行处调用解析器进行解析;``94`` 行处从解析结果中取值。 76 | 注意到,属性名和参数定义中 ``dest`` 参数一致。 77 | 78 | 总结起来,参数解析只需要这几个步骤: 79 | 80 | #. 初始化解析器; 81 | #. 定义选项; 82 | #. 调用解析器解析参数; 83 | #. 从解析结果取值; 84 | 85 | 下一步 86 | ====== 87 | 88 | .. include:: /_fragments/next-step-to-wechat-mp.rst 89 | 90 | .. include:: /_fragments/wechat-reward.rst 91 | 92 | .. include:: /_fragments/disqus.rst 93 | -------------------------------------------------------------------------------- /docs/zh_CN/practices/binary-release.rst: -------------------------------------------------------------------------------- 1 | .. 打包分发Python程序 2 | FileName: binary-release.rst 3 | Author: Fasion Chan 4 | Created: 2019-02-01 19:30:10 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :description lang=zh: 14 | 运行Python程序,需要部署Python执行环境并安装依赖包,操作繁琐。 15 | 借助PyInstaller等工具,可以将Python程序和Python环境一起打包成可执行程序,极大改善部署体验。 16 | 本文以一个简单的实验程序,演示打包方法。 17 | :keywords: python, pyinstaller, 二进制, 打包 18 | 19 | ================== 20 | 打包分发Python程序 21 | ================== 22 | 23 | 运行 `Python` 程序,需要部署 `Python` 执行环境并安装依赖包,操作繁琐。 24 | 25 | 借助 `PyInstaller`_ 等工具,可以将 `Python` 程序和 `Python` 环境一起打包成可执行程序, 26 | 极大改善部署体验。 27 | 本文以一个简单的实验程序,演示打包方法。 28 | 29 | 实验程序 30 | ======== 31 | 32 | 我们编写一个程序,并用它演示如何打包 `Python` 程序。 33 | 程序通过 `ntplib`_ 查询 `NTP` **服务器** 并输出相关信息: 34 | 35 | .. literalinclude:: /_src/practices/binary-release/checktime.py 36 | :language: python 37 | :lines: 16- 38 | 39 | 先使用 `virtualenv` 初始化一个 `Python` 隔离环境进行实验: 40 | 41 | .. code-block:: shell-session 42 | 43 | $ virtualenv env 44 | 45 | 验证 `Python` 隔离环境功能是否正常: 46 | 47 | .. code-block:: shell-session 48 | 49 | $ env/bin/python --version 50 | Python 3.7.1 51 | 52 | 接着执行 `pip` 工具安装依赖包: 53 | 54 | .. code-block:: shell-session 55 | 56 | $ env/bin/pip install ntplib==0.3.3 57 | 58 | 可以通过 `python` 命令执行程序了: 59 | 60 | .. code-block:: shell-session 61 | 62 | $ env/bin/python checktime.py 63 | Server: 119.160.254.155 64 | Offset: 0.004868745803833008 65 | Time: 2019-02-01 19:34:17 66 | 67 | PyInstaller 68 | =========== 69 | 70 | .. figure:: /_images/practices/binary-release/3b69fba0e9d9577ba7b7f2746a61516b.png 71 | :width: 500px 72 | 73 | `PyInstaller` 工具用于将 `Python` 应用及其依赖打包成一个 **单文件程序** 。支持系统包括: 74 | 75 | - `Windows` 76 | - `GNU/Linux `_ 77 | - `Mac OS X `_ 78 | - `FreeBSD` 79 | - `Solaris` 80 | - `AIX` 81 | 82 | 使用之前,需进行安装: 83 | 84 | .. code-block:: shell-session 85 | 86 | $ env/bin/pip install pyinstaller==3.4 87 | 88 | 执行 `pyinstaller` 命令, `checktime.py` 是待打包脚本, `-F` 表示打包成单文件程序: 89 | 90 | .. code-block:: shell-session 91 | 92 | $ env/bin/pyinstaller -F checktime.py 93 | 94 | 如无意外,在 `dist` 目录下可以找到打包后的程序。可以直接执行: 95 | 96 | .. code-block:: shell-session 97 | 98 | $ dist/checktime 99 | Server: 42.204.179.159 100 | Offset: -0.024485349655151367 101 | Time: 2019-02-01 10:51:08 102 | 103 | 将以上程序拷贝到其他同类型系统上,也可以 **直接执行** 。 104 | 这样一来,其他系统无需安装 `Python` 环境,也无需安装依赖库即可执行 `Python` 应用,非常便捷! 105 | 106 | 下一步 107 | ====== 108 | 109 | .. include:: /_fragments/next-step-to-wechat-mp.rst 110 | 111 | .. include:: /_fragments/wechat-reward.rst 112 | 113 | .. include:: /_fragments/disqus.rst 114 | 115 | .. _ntplib: https://pypi.org/project/ntplib/ 116 | 117 | .. comments 118 | comment something out below 119 | 120 | -------------------------------------------------------------------------------- /docs/zh_CN/practices/datetime.rst: -------------------------------------------------------------------------------- 1 | .. 日期时间处理 2 | FileName: datetime.rst 3 | Author: Fasion Chan 4 | Created: 2018-12-03 18:20:40 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :description lang=zh: 14 | :keywords: python, datetime, last_month, last_week, 上周, 上月 15 | 16 | 17 | ============ 18 | 日期时间处理 19 | ============ 20 | 21 | 格式化 22 | ====== 23 | 24 | 上周 25 | ==== 26 | 27 | 如何判断上周是啥日期?以上周一为例: 28 | 29 | .. code-block:: python 30 | :linenos: 31 | 32 | def get_this_monday(): 33 | today = datetime.today() 34 | this_monday = (today - timedelta(days=today.weekday())).replace( 35 | hour=0, 36 | minute=0, 37 | second=0, 38 | microsecond=0, 39 | ) 40 | return this_monday 41 | 42 | def get_last_monday(): 43 | this_monday = get_this_monday() 44 | last_monday = this_monday - timedelta(days=7) 45 | return last_monday 46 | 47 | 函数 `get_this_monday` 获取本周一的日期,其中第 *2* 行取出当前日期时间; 48 | 第 *3-8* 行计算得到本周一。 49 | 50 | 函数 `get_last_monday` 获取上周一的日期,其中第 *12* 行获取本周一的日期; 51 | 第 *13* 行将其减去 *7* 天得到上周一。 52 | 53 | 54 | 上月 55 | ==== 56 | 57 | 如何判断上月是何年何月? 58 | 59 | 可以将月减一,但对于一月份需要做特殊处理:则将年减一,月设置为 *12* : 60 | 61 | .. code-block:: python 62 | :linenos: 63 | 64 | import datetime 65 | 66 | def get_last_month(): 67 | today = datetime.today() 68 | this_month = today.replace(day=1, hour=0, minute=0, second=0, microsecond=0) 69 | if this_month.month > 1: 70 | last_month = this_month.replace(month=this_month.month-1) 71 | else: 72 | last_month = this_month.replace(year=this_month.year-1, month=12) 73 | return last_month 74 | 75 | 第 *4* 行取出当前日期时间; 76 | 第 *5* 行将日期替换为 *1* 得到本月 *1* 号; 77 | 最后一个 *if* 语句判断本月是否为 **一月份** ,并据此分别进行处理。 78 | 这个方法简单粗暴,但是不是很优雅。 79 | 80 | 当然可以更优雅地处理:先将本月 *1* 号减去一天得到上个月最后一天; 81 | 接着将日期设置为 *1* 则得到上月 *1* 号。 82 | 代码如下: 83 | 84 | .. code-block:: python 85 | :linenos: 86 | 87 | import datetime 88 | 89 | def get_last_month(): 90 | today = datetime.today() 91 | this_month = today.replace(day=1, hour=0, minute=0, second=0, microsecond=0) 92 | last_month = (this_month - timedelta(days=1)).replace(day=1) 93 | return last_month 94 | 95 | 下一步 96 | ====== 97 | 98 | .. include:: /_fragments/next-step-to-wechat-mp.rst 99 | 100 | .. include:: /_fragments/wechat-reward.rst 101 | 102 | .. include:: /_fragments/disqus.rst 103 | 104 | .. comments 105 | comment something out below 106 | 107 | -------------------------------------------------------------------------------- /docs/zh_CN/practices/debug-python-with-gdb.rst: -------------------------------------------------------------------------------- 1 | .. 使用GDB调试Python程序 2 | FileName: debug-python-with-gdb.rst 3 | Author: Fasion Chan 4 | Created: 2019-02-15 17:46:36 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :description lang=zh: 14 | Python程序吐coredump文件怎么办? 15 | 很多人会想到用gdb加载coredump文件,然后查看信号及堆栈信息,据此分析原因。 16 | 堆栈信息在调试中非常有用,可别忘了,待调试的是Python代码,而gdb提供的是C堆栈信息! 17 | 难道要撸Python源码,然后分析各种核心数据结构吗? 18 | 有什么方式可以查看到Python堆栈信息吗? 19 | :keywords: python, coredump, gdb, threads, stack, strace, 调试 20 | 21 | ===================== 22 | 使用GDB调试Python程序 23 | ===================== 24 | 25 | 最近用在开发一个 *agent* 程序,需要支持 `Linux`_ 、 *FreeBSD* 及 *Windows* 等操作系统。 26 | 复杂的机器环境,导致一系列诡异问题,尽管代码发布前在不少测试机上验证过。 27 | 28 | `Python` 程序吐 `coredump` 文件怎么办? 29 | 很多人会想到用 `gdb` 加载 `coredump` 文件,然后查看 **信号** 及 **堆栈** 信息,据此分析原因。 30 | 堆栈信息在调试中非常有用,可别忘了,待调试的是 `Python` 代码,而 `gdb` 提供的是 `C` 堆栈信息! 31 | 难道要撸 `Python` 源码,然后分析各种核心数据结构吗? 32 | 有什么方式可以查看到 `Python` 堆栈信息吗? 33 | 34 | 还遇到过另一个问题,一个 `Python` 进程突然间陷入死循环,所有其他线程都调度不到。 35 | 遇到这种情况,首先可能需要知道死循环到底在干什么。 36 | 如何获悉呢?可能用 `strace`_ 跟一下系统调用可以看出一点端倪。 37 | 但是一个堆栈信息更为具体更有说服力,就算是只有 `C` 堆栈信息有时也是足以说明问题的。 38 | 39 | `gdb`_ 就可以解决以上难题(其实远不止),接下来,我们一起看看具体要怎么操作吧~ 40 | 41 | 准备 42 | ==== 43 | 44 | 首先得有 `gdb`_ 吧,这个就不细说了, `Debian` 系发行版上运行以下命令完成安装: 45 | 46 | .. code-block:: shell-session 47 | 48 | $ apt-get install gdb 49 | 50 | 其次,还需要装一个包—— `python-dbg` 。 51 | 这个包有什么作用呢? 52 | 前面不是抱怨过 `C` 堆栈对于调试一个 `Python` 有何用? 53 | 我们更需要的是 `Python` 堆栈信息, `python-dbg` 就是为了完成这个使命。 54 | 55 | 运行 56 | ==== 57 | 58 | 全新启动一个 `Python` 程序并进行调试,可以采用交互式方式, 59 | 先启动 `gdb`_ 然后在 `gdb shell` 中启动 `Python` 程序: 60 | 61 | .. code-block:: shell-session 62 | 63 | $ gdb python 64 | ... 65 | (gdb) run .py 66 | 67 | 当然了,也可以一步到位,一条命令搞定这两步: 68 | 69 | .. code-block:: shell-session 70 | 71 | $ gdb -ex r --args python .py 72 | 73 | 遗憾的是,现实中往往是这样的情景——一个正在运行的程序突然异常了,你需要调试它!这时为之奈何? 74 | 75 | 有一种方法你可以给它发一个信号,出一个 `coredump` 文件,然后用 `gdb` 来调试 `coredump` 文件: 76 | 77 | .. code-block:: shell-session 78 | 79 | $ gdb 80 | 81 | 显然易见,这并不是一种很好的方式,那么有没有什么办法可以捕获进程并调试呢? 82 | 你想得到的很有可能都有人实现了—— 83 | 84 | .. code-block:: shell-session 85 | 86 | $ gdb python 87 | 88 | .. code-block:: shell-session 89 | 90 | $ gdb attach 91 | 92 | 这两种方式都可以让 `gdb` 捕获一个进程。 93 | 因此,我们需要做的只是确定问题进程的 `pid` ,这个总该没有难度了吧—— `top` 、 `ps` 等等一系列命令都可以做到。 94 | 95 | 堆栈查看 96 | ======== 97 | 98 | 查看 `C` 堆栈信息,用过 `gdb` 命令的估计都知道怎么做: 99 | 100 | .. code-block:: text 101 | 102 | (gdb) bt 103 | #0 0x0000002a95b3b705 in raise () from /lib/libc.so.6 104 | #1 0x0000002a95b3ce8e in abort () from /lib/libc.so.6 105 | #2 0x00000000004c164f in posix_abort (self=0x0, noargs=0x0) at ../Modules/posixmodule.c:7158 106 | #3 0x0000000000489fac in call_function (pp_stack=0x7fbffff110, oparg=0) at ../Python/ceval.c:3531 107 | #4 0x0000000000485fc2 in PyEval_EvalFrame (f=0x66ccd8) at ../Python/ceval.c:2163 108 | ... 109 | 110 | 那么,怎么查看 `Python` 堆栈呢。安装 `python-gdb` 之后, `gdb` 会提供若干相关的操作。 111 | 其中 `py-bt` 就是用来查看 `Python` 堆栈的: 112 | 113 | .. code-block:: text 114 | 115 | (gdb) py-bt 116 | 117 | 线程查看 118 | ======== 119 | 120 | 调试多线程程序,首先总得搞清楚到底有哪些线程吧: 121 | 122 | .. code-block:: text 123 | 124 | (gdb) info threads 125 | Id Target Id Frame 126 | 37 Thread 0xa29feb40 (LWP 17914) "NotificationThr" 0xb7fdd424 in __kernel_vsyscall () 127 | 36 Thread 0xa03fcb40 (LWP 17913) "python2.7" 0xb7fdd424 in __kernel_vsyscall () 128 | 35 Thread 0xa0bfdb40 (LWP 17911) "QProcessManager" 0xb7fdd424 in __kernel_vsyscall () 129 | 34 Thread 0xa13feb40 (LWP 17910) "python2.7" 0xb7fdd424 in __kernel_vsyscall () 130 | 33 Thread 0xa1bffb40 (LWP 17909) "python2.7" 0xb7fdd424 in __kernel_vsyscall () 131 | 31 Thread 0xa31ffb40 (LWP 17907) "QFileInfoGather" 0xb7fdd424 in __kernel_vsyscall () 132 | 30 Thread 0xa3fdfb40 (LWP 17906) "QInotifyFileSys" 0xb7fdd424 in __kernel_vsyscall () 133 | 29 Thread 0xa481cb40 (LWP 17905) "QFileInfoGather" 0xb7fdd424 in __kernel_vsyscall () 134 | 7 Thread 0xa508db40 (LWP 17883) "QThread" 0xb7fdd424 in __kernel_vsyscall () 135 | 6 Thread 0xa5cebb40 (LWP 17882) "python2.7" 0xb7fdd424 in __kernel_vsyscall () 136 | 5 Thread 0xa660cb40 (LWP 17881) "python2.7" 0xb7fdd424 in __kernel_vsyscall () 137 | 3 Thread 0xabdffb40 (LWP 17876) "gdbus" 0xb7fdd424 in __kernel_vsyscall () 138 | 2 Thread 0xac7b7b40 (LWP 17875) "dconf worker" 0xb7fdd424 in __kernel_vsyscall () 139 | * 1 Thread 0xb7d876c0 (LWP 17863) "python2.7" 0xb7fdd424 in __kernel_vsyscall () 140 | 141 | 请注意 `*` 号哦——它标识的是当前线程。 142 | 143 | 那么如何切换线程呢? 144 | 145 | .. code-block:: text 146 | 147 | (gdb) thread 37 148 | 149 | 这样就将37号线程设置为当前线程进行调试了。 150 | 151 | 好,那么怎么查看当前线程的相关信息呢? 152 | 上节中, `py-bt` 可以帮上忙——至少知道线程的执行堆栈。 153 | 还有一个操作 `py-list` ,可以清楚看到当前执行到代码的第几行, 154 | 还有前后若干行的代码可以对照哦: 155 | 156 | .. code-block:: text 157 | 158 | (gdb) py-list 159 | 2025 # Open external files with our Mac app 160 | 2026 if sys.platform == "darwin" and 'Spyder.app' in __file__: 161 | 2027 main.connect(app, SIGNAL('open_external_file(QString)'), 162 | 2028 lambda fname: main.open_external_file(fname)) 163 | 2029 164 | >2030 app.exec_() 165 | 2031 return main 166 | 2032 167 | 2033 168 | 2034 def __remove_temp_session(): 169 | 2035 if osp.isfile(TEMP_SESSION_PATH): 170 | 171 | 还有更 *6* 的,查看所有进程执行位置,非常方便有木有: 172 | 173 | .. code-block:: text 174 | 175 | (gdb) thread apply all py-list 176 | ... 177 | 200 178 | 201 def accept(self): 179 | >202 sock, addr = self._sock.accept() 180 | 203 return _socketobject(_sock=sock), addr 181 | 204 accept.__doc__ = _realsocket.accept.__doc__ 182 | 205 183 | 206 def dup(self): 184 | 207 """dup() -> socket object 185 | 186 | Thread 35 (Thread 0xa0bfdb40 (LWP 17911)): 187 | Unable to locate python frame 188 | 189 | Thread 34 (Thread 0xa13feb40 (LWP 17910)): 190 | 197 for method in _delegate_methods: 191 | 198 setattr(self, method, dummy) 192 | 199 close.__doc__ = _realsocket.close.__doc__ 193 | 200 194 | 201 def accept(self): 195 | >202 sock, addr = self._sock.accept() 196 | 203 return _socketobject(_sock=sock), addr... 197 | 198 | 下一步 199 | ====== 200 | 201 | .. include:: /_fragments/next-step-to-wechat-mp.rst 202 | 203 | 参考文献 204 | ======== 205 | 206 | #. `DebuggingWithGdb - Python Wiki `_ 207 | 208 | .. include:: /_fragments/wechat-reward.rst 209 | 210 | .. include:: /_fragments/disqus.rst 211 | 212 | .. _gdb: http://man7.org/linux/man-pages/man1/gdb.1.html 213 | .. _strace: http://man7.org/linux/man-pages/man1/strace.1.html 214 | .. _Linux: https://learn-linux.readthedocs.io/zh_CN/latest/ 215 | 216 | .. comments 217 | comment something out below 218 | 219 | -------------------------------------------------------------------------------- /docs/zh_CN/practices/index.rst: -------------------------------------------------------------------------------- 1 | .. 最佳实践 2 | FileName: index.rst 3 | Author: Fasion Chan 4 | Created: 2018-03-10 15:54:50 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | ======== 13 | 最佳实践 14 | ======== 15 | 16 | .. toctree:: 17 | :titlesonly: 18 | 19 | 更优雅地造测试数据 <../libs/faker> 20 | 装饰器高级用法 21 | 处理命令行参数 22 | 打包分发Python程序 23 | 一文说清文本编码那些事 24 | 日期时间处理 25 | 使用GDB调试Python程序 26 | 发布自己的Python包 27 | 解决Python2的编码问题 28 | 日志输出 29 | 计算字符串相似度 30 | -------------------------------------------------------------------------------- /docs/zh_CN/practices/logging.rst: -------------------------------------------------------------------------------- 1 | .. 日志输出 2 | FileName: logging.rst 3 | Author: Fasion Chan 4 | Created: 2019-01-07 19:55:21 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :description lang=zh: 14 | 日志在问题分析时必不可少,好的程序应该输出足够的日志信息。 15 | 那么,用Python语言开发程序时,如何输出日志呢? 16 | :keywords: python, logging, 日志输出, 日志格式, Logger, Handler, Formatter 17 | 18 | ======== 19 | 日志输出 20 | ======== 21 | 22 | 日志在问题分析时必不可少,好的程序应该输出足够的日志信息。 23 | 24 | 那么,用 `Python` 语言开发程序时,如何输出日志呢? 25 | 26 | —— `logging`_ 模块! 27 | 28 | .. code-block:: pycon 29 | 30 | >>> import logging 31 | >>> logging.warning('something wrong happended.') 32 | WARNING:root:Something wrong happended. 33 | >>> logging.info('seems good!') 34 | 35 | 这是一个入门级例子,导入 `logging`_ 模块后,调用 `warning` 方法即可输出警告信息。 36 | 37 | 日志级别 38 | ======== 39 | 40 | 日志输出视轻重缓急,可分为多个级别。 41 | 例子还调用 `info` 方法输出一条普通信息,级别比警告信息低。 42 | `Python` 支持的日志级别包括: 43 | 44 | .. csv-table:: 表格-1 日志级别 45 | :header: "名称", "数值", "方法", "含义" 46 | 47 | "CRITICAL", "logging.CRITICAL", "logger.critical", "严重错误" 48 | "ERROR", "logging.ERROR", "logger.error", "错误" 49 | "WARNING", "logging.WARNING", "logger.warning", "警告" 50 | "INFO", "logging.INFO", "logger.info", "普通信息" 51 | "DEBUG", "logging.DEBUG", "logger.debug", "调试信息" 52 | "NOTSET", "logging.NOTSET", "", "未指定" 53 | 54 | 注意到,例子中 `info` 输出的普通信息并没有真正打印到屏幕上, 55 | 这是因为默认的 `logger`_ 对象只输出较高级别日志。 56 | 为了输出想要的级别,我们需要自行定制 `Logger`_ 对象。 57 | 58 | 日志对象 59 | ======== 60 | 61 | `Logger`_ 对象通过 `getLogger` 方法创建: 62 | 63 | .. code-block:: pycon 64 | 65 | >>> logger = logging.getLogger(__name__) 66 | >>> logger.setLevel(logging.INFO) 67 | >>> logger.info('you must be able to see me!') 68 | INFO:__main__:you must be able to see me! 69 | 70 | 调用 `Logger`_ 对象 `setLevel` 方法设置日志输出级别,后续将忽略比该级别低的日志。 71 | 调用 `debug` 方法输出日志将被忽略: 72 | 73 | .. code-block:: pycon 74 | 75 | >>> logger.debug('you cant see me now!') 76 | 77 | 更多定制方法,请查看 `帮助文档 `_ : 78 | 79 | .. code-block:: pycon 80 | 81 | >>> help(logger) 82 | 83 | 日志处理器 84 | ========== 85 | 86 | 前面几个例子,日志均输出到标准输出,因此我们可以在屏幕中看到。 87 | 当然了,日志还可以输出到文件,甚至可以通过网络发送出去,这都是通过 `Handler`_ 对象控制的。 88 | 89 | 标准输出 90 | -------- 91 | 92 | 日志对象默认输出到标准输出,等价于: 93 | 94 | .. code-block:: python 95 | 96 | logger_handler = logging.StreamHandler(sys.stdout) 97 | 98 | logger = logging.getLogger(__name__) 99 | logger.setLevel(logging.DEBUG) 100 | logger.addHandler(logger_handler) 101 | 102 | 可以进一步控制处理器可以输出的 **日志级别** : 103 | 104 | .. code-block:: python 105 | 106 | logger_handler = logging.StreamHandler(sys.stdout) 107 | logger_handler.setLevel(logging.WARNING) 108 | 109 | 这样一来,只有不低于 `WARNING` 级别的日志才会被该处理器处理。 110 | 需要注意的是, `Logger`_ 对象以及 `Handler`_ 对象级别同时影响日志输出行为。 111 | 112 | 文件 113 | ---- 114 | 115 | 相比标准输出,将日志输出到文件更为妥当,文件可以保留一定的历史待查。 116 | 117 | 日志格式 118 | ======== 119 | 120 | 采用默认格式输出的日志非常丑陋,信息量也不够,甚至连时间都没有! 121 | 因此,需要根据应用需求,灵活调整日志输出格式。 122 | 为 `Handler` 对象自定义格式: 123 | 124 | .. code-block:: python 125 | :linenos: 126 | 127 | import logging, sys 128 | 129 | FMT = '%(asctime)s %(levelname) 8s: [%(filename)s:%(lineno)d] [%(processName)s:%(process)d %(threadName)s] - %(message)s' 130 | DATEFMT = '[%Y-%m-%d %H:%M:%S]' 131 | 132 | logger_handler = logging.StreamHandler(sys.stdout) 133 | logger_handler.setLevel(logging.DEBUG) 134 | 135 | formatter = logging.Formatter(fmt=FMT, datefmt=DATEFMT) 136 | logger_handler.setFormatter(formatter) 137 | 138 | logger = logging.getLogger(__name__) 139 | logger.setLevel(logging.DEBUG) 140 | logger.addHandler(logger_handler) 141 | 142 | 关键代码是 `9-10` 行,初始化一个格式化器,并设置到 `Handler` 对象上。 143 | 初始化器需要两个参数, `fmt` 指定日志格式, `datefmt` 指定日期格式。 144 | 除了日志内容,日志记录可以注入 **时间** 、 **级别** 、 **代码文件名** 、 145 | **代码行数** 、 **进程名** 、 **进程ID** 、 **线程名** 等信息。 146 | 147 | 例子输出大致如下,可以看到 **格式更为美观,信息更为丰富** 了: 148 | 149 | .. code-block:: pycon 150 | 151 | >>> logger.info('Hello, world!') 152 | [2019-01-08 11:25:50] INFO: [:1] [MainProcess:99324 MainThread] - Hello, world! 153 | 154 | 下一步 155 | ====== 156 | 157 | .. include:: /_fragments/next-step-to-wechat-mp.rst 158 | 159 | 参考文献 160 | ======== 161 | 162 | #. `logging — Logging facility for Python `_ 163 | 164 | .. include:: /_fragments/wechat-reward.rst 165 | 166 | .. include:: /_fragments/disqus.rst 167 | 168 | .. _logging: https://docs.python.org/3/library/logging.html 169 | .. _Logger: https://docs.python.org/3/library/logging.html#logger-objects 170 | .. _Handler: https://docs.python.org/3/library/logging.html#handler-objects 171 | 172 | .. comments 173 | comment something out below 174 | 175 | -------------------------------------------------------------------------------- /docs/zh_CN/practices/publish-package.rst: -------------------------------------------------------------------------------- 1 | .. 发布自己的Python包 2 | FileName: publish-package.rst 3 | Author: Fasion Chan 4 | Created: 2019-02-15 18:26:54 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :description lang=zh: 14 | :keywords: python, package, upload, publish, pip, twine, setup.py, python包, 上传, 发布 15 | 16 | ================== 17 | 发布自己的Python包 18 | ================== 19 | 20 | 注册 21 | ==== 22 | 23 | 先在 `Python` 官网注册一个账号,地址是:`https://pypi.python.org/pypi `_ 。 24 | 25 | 配置 26 | ==== 27 | 28 | 账号注册后,就可以用其来登记新建的 `Python` 包,以及上传包更新。 29 | 上传新包一般由 `twine` 命令完成, `twine` 需要知道 `Python` 仓库地址以及账号信息。 30 | 因此,可以将这些信息写在配置文件 `~/.pypirc` 里,这样运行命令时便不需要再次输入了。 31 | 下面是一个配置示例,以 `foo` 为用户名, `bar` 为密码: 32 | 33 | .. code-block:: text 34 | 35 | [distutils] 36 | index-servers=pypi 37 | 38 | [pypi] 39 | repository = https://upload.pypi.org/legacy/ 40 | username = foo 41 | password = bar 42 | 43 | 其中,密码也可以不写进配置,这样每次运行 `twine` 时,将提示输入密码。 44 | 45 | 准备 46 | ==== 47 | 48 | 编写 `Python` 包的过程,这里就不细说了。 49 | 本文的重点是怎么将自己的 `Python` 包发布出去,然后可以用 `pip` 命令安装。 50 | 51 | `Python` 包的实现方式可以参考其他文档。其实无非就是规划好目录结构,然后编写 `setup.py` 文件: 52 | 53 | .. code-block:: python 54 | 55 | #!/usr/bin/env python 56 | # -*- encoding=utf8 -*- 57 | 58 | VERSION = '1.0' 59 | 60 | from setuptools import ( 61 | setup, 62 | ) 63 | 64 | setup( 65 | name='libase', 66 | version=VERSION, 67 | author='Fasion Chan', 68 | author_email='fasionchan@gmail.com', 69 | packages=[ 70 | 'libase', 71 | ], 72 | scripts=[ 73 | ], 74 | package_data={ 75 | }, 76 | install_requires=[ 77 | ], 78 | ) 79 | 80 | 构建 81 | ==== 82 | 83 | 运行命令 `python setup.py sdist` 进行构建并打包。 84 | 完成之后,在 `dist` 目录下可以看到形如 `xxxx-1.0.tar.gz` 的压缩包。 85 | 86 | 上传 87 | ==== 88 | 89 | 运行命令 `twine upload dist/*` 便可将构建的所有包上传,这时便大功告成了! 90 | 91 | 应用 92 | ==== 93 | 94 | 运行命令 `pip install xxxx` 便可以安装你发布的 `Python` 包了! 95 | 你可以发布任何你想发布的东西,任何人也可以安装任何你发布的东西,成就感杠杠的有木有! 96 | 97 | 我们提倡自由分享的精神,有用的代码无私奉献出来可以节约很多人很多时间! 98 | —— `Life is short, use Python!` 99 | 100 | 当然了,努力提升自己,分享高质量代码,不要坑别人哦~ 101 | 102 | 下一步 103 | ====== 104 | 105 | .. include:: /_fragments/next-step-to-wechat-mp.rst 106 | 107 | .. include:: /_fragments/wechat-reward.rst 108 | 109 | .. include:: /_fragments/disqus.rst 110 | 111 | .. comments 112 | comment something out below 113 | 114 | -------------------------------------------------------------------------------- /docs/zh_CN/practices/publish-package.rst.old: -------------------------------------------------------------------------------- 1 | .. 发布自己的Python包 2 | FileName: publish-package.rst 3 | Author: Fasion Chan 4 | Created: 2019-02-15 18:26:54 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :description lang=zh: 14 | :keywords: python, package, upload, publish, pip, twine, setup.py, python包, 上传, 发布 15 | 16 | ================== 17 | 发布自己的Python包 18 | ================== 19 | 20 | 注册 21 | ==== 22 | 23 | 先在 `Python` 官网注册一个账号,地址是:`https://pypi.python.org/pypi `_ 。 24 | 25 | 配置 26 | ==== 27 | 28 | 账号注册后,就可以用其来登记新建的 `Python` 包,以及上传包更新。 29 | 上传新包一般由 `twine` 命令完成, `twine` 需要知道 `Python` 仓库地址以及账号信息。 30 | 因此,可以将这些信息写在配置文件 `~/.pypirc` 里,这样运行命令时便不需要再次输入了。 31 | 下面是一个配置示例,以 `foo` 为用户名, `bar` 为密码: 32 | 33 | .. code-block:: text 34 | 35 | [distutils] 36 | index-servers=pypi 37 | 38 | [pypi] 39 | repository = https://pypi.python.org/pypi 40 | username = foo 41 | password = bar 42 | 43 | 其中,密码也可以不写进配置,这样每次运行 `twine` 时,将提示输入密码。 44 | 45 | 准备 46 | ==== 47 | 48 | 编写 `Python` 包的过程,这里就不细说了。 49 | 本文的重点是怎么将自己的 `Python` 包发布出去,然后可以用 `pip` 命令安装。 50 | 51 | `Python` 包的实现方式可以参考其他文档。其实无非就是规划好目录结构,然后编写 `setup.py` 文件: 52 | 53 | .. code-block:: python 54 | 55 | #!/usr/bin/env python 56 | # -*- encoding=utf8 -*- 57 | 58 | VERSION = '1.0' 59 | 60 | from setuptools import ( 61 | setup, 62 | ) 63 | 64 | setup( 65 | name='libase', 66 | version=VERSION, 67 | author='Fasion Chan', 68 | author_email='fasionchan@gmail.com', 69 | packages=[ 70 | 'libase', 71 | ], 72 | scripts=[ 73 | ], 74 | package_data={ 75 | }, 76 | install_requires=[ 77 | ], 78 | ) 79 | 80 | 登记 81 | ==== 82 | 83 | 运行命令 `python setup.py egg_info` 生成包信息, 84 | 找到 `xxxx.egg_info` 目录下 `PKG-INFO` 文件, 85 | 在 `Python` 官网 `提交表单 `_ 上传即可。 86 | 87 | 构建 88 | ==== 89 | 90 | 运行命令 `python setup.py sdist` 进行构建并打包。 91 | 完成之后,在 `dist` 目录下可以看到形如 `xxxx-1.0.tar.gz` 的压缩包。 92 | 93 | 上传 94 | ==== 95 | 96 | 运行命令 `twine upload dist/*` 便可将构建的所有包上传,这时便大功告成了! 97 | 98 | 应用 99 | ==== 100 | 101 | 运行命令 `pip install xxxx` 便可以安装你发布的 `Python` 包了! 102 | 你可以发布任何你想发布的东西,任何人也可以安装任何你发布的东西,成就感杠杠的有木有! 103 | 104 | 我们提倡自由分享的精神,有用的代码无私奉献出来可以节约很多人很多时间! 105 | —— `Life is short, use Python!` 106 | 107 | 当然了,努力提升自己,分享高质量代码,不要坑别人哦~ 108 | 109 | 下一步 110 | ====== 111 | 112 | .. include:: /_fragments/next-step-to-wechat-mp.rst 113 | 114 | .. include:: /_fragments/wechat-reward.rst 115 | 116 | .. include:: /_fragments/disqus.rst 117 | 118 | .. comments 119 | comment something out below 120 | 121 | -------------------------------------------------------------------------------- /docs/zh_CN/practices/py2-encoding.rst: -------------------------------------------------------------------------------- 1 | .. 完美解决Python2的编码问题 2 | FileName: py2-encoding.rst 3 | Author: Fasion Chan 4 | Created: 2019-01-30 19:54:04 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :description lang=zh: 14 | 将输出Unicode的Python程序重定向到文件,程序便抛异常,这是由编码问题导致的。 15 | 找到问题症结后,可通过三种方法解决: 16 | 一、设置PYTHONIOENCODING环境变量; 17 | 二、替换 `sys.stdout` 文件对象,指定编码; 18 | 三、重新设置程序默认编码方式。 19 | :keywords: python2, 编码, 乱码, UnicodeEncodeError, ascii, 标准输出, 重定向, 20 | 21 | ========================= 22 | 完美解决Python2的编码问题 23 | ========================= 24 | 25 | 背景 26 | ==== 27 | 28 | 计算机无论 **存储信息** ,或者通过网络 **交换信息** , **基本单位** 都是 **八位字节** ( `octet` )。 29 | 八位字节能够表示的字符数最多不超过 *256* 种: 30 | 31 | .. math:: 32 | 2^8 = 256 33 | 34 | 这用来存储英文字母是绰绰有余,但是要满足全世界人民可就难了——汉字光常用的就几千个呢! 35 | 怎么办呢?——用多个字节存储呗。这时,全世界人民齐头并进: 36 | 37 | - 中国人民使用 *GB2312* 、 *GBK* 、 *GB18030* ; 38 | - 日本人民使用 *Shift JIS* 、 *EUC-JP* ; 39 | - 韩国人民使用 *EUC_KR* ; 40 | - *etc* 41 | 42 | 各家自扫门前雪, **互不兼容** 。直到有个老好人 `Unicode` 出来统一世界,收录人类所有字符。 43 | `Unicode` 字符集非常庞大,也需要多个字节存储,最常见的编码方式是 `UTF-8` 。 44 | 因此,对于同一个汉字 **我** ,按不同的编码存储后的字节是不一样的: 45 | 46 | .. csv-table:: 汉字与编码 47 | 48 | "汉字", "我" 49 | "Unicode", "25105" 50 | "GBK", "两字节:0xce 0xd2" 51 | "UTF-8", "三字节:0xe6 0x88 0x91" 52 | 53 | 一个 `GBK` 编码的字节序列,如果以 `UTF-8` 来读,肯定是一坨狗屎。 54 | 因此,知晓数据编码方式非常重要,直接关系到数据的解读。 55 | 中文编码方式有好几套,互不兼容,因此中文世界里的乱码现象就不难理解了。 56 | 57 | 在 `Python 2` ,字符分为两种,首先是 `Unicode` 字符: 58 | 59 | .. code-block:: python 60 | 61 | u'你好,世界!' 62 | 63 | 普通字符串可以理解成字符序列: 64 | 65 | .. code-block:: python 66 | 67 | '你好,世界!' 68 | 69 | .. note:: 70 | 71 | 代码中的普通字符串编码与代码文件相同;交互式模式中输入时与终端编码相同。 72 | 73 | 在两种字符串之间转换,需要 **编码** 或者 **解码** : 74 | 75 | .. code-block:: python 76 | 77 | # 编码 78 | a = u'你好,世界!' 79 | b = a.encode('utf8') 80 | 81 | # 解码 82 | b.decode('utf8') 83 | 84 | 文件流 85 | ====== 86 | 87 | 文件存储 **八位字节** ,不管待存数据是啥,最终要转化成字节。 88 | 那么,如果直接写入 `Unicode` 字符串,会发生什么事情: 89 | 90 | .. code-block:: pycon 91 | 92 | >>> f = open('somefile.out', 'w+') 93 | >>> f.write(u'你好,世界!') 94 | Traceback (most recent call last): 95 | File "", line 1, in 96 | UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128) 97 | 98 | 毫不意外,提示默认的 `ascii` 编码器不能编码待写入的数据。 99 | 100 | 但注意到,我们在终端运行程序,却可以输出 `Unicode` 字符串。 101 | 将以下代码保存成 `say-hello.py` 文件,并运行: 102 | 103 | .. literalinclude:: /_src/practices/py2-encoding/say-hello.py 104 | :language: python 105 | :lines: 16- 106 | 107 | .. code-block:: shell-session 108 | 109 | $ python2 say-hello.py 110 | 你好,世界! 111 | 112 | 为啥呢?理论上, ``print`` 也是写到 `sys.stdout` 中,它也是一个文件对象呀! 113 | 114 | 然而, `Python` 初学者还经常被另一个问题困扰,将输出重定向到文件就又不行了? 115 | 116 | .. code-block:: shell-session 117 | 118 | $ python2 say-hello.py > /dev/null 119 | Traceback (most recent call last): 120 | File "say-hello.py", line 16, in 121 | print u'你好,世界!' 122 | UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128) 123 | 124 | 还记得吗, `Python` 打开文件有两种不同的模式, **文本模式** 和 **二进制模式** : 125 | 126 | .. code-block:: python 127 | 128 | # 文本模式 129 | f = open('somefile.out', 'w+') 130 | 131 | # 二进制模式 132 | f = open('somefile.out', 'wb+') 133 | 134 | 既然默认是文本模式,可以非常合理地怀疑 `sys.stdout` 文件对象的编码设置。 135 | 接下来,写一个程序 `stdio-encoding.py` 来检查在不同的运行方式下, 标准 *IO* 对象的编码方式: 136 | 137 | .. literalinclude:: /_src/practices/py2-encoding/stdio-encoding.py 138 | :language: python 139 | :lines: 16- 140 | 141 | 直接运行,继承终端输入输出,文件对象的编码方式是 `UTF-8` (因环境而已): 142 | 143 | .. code-block:: shell-session 144 | 145 | $ python2 stdio-encoding.py 146 | stdin UTF-8 147 | stdout UTF-8 148 | stderr UTF-8 149 | 150 | 标准错误重定向, `stderr` 文件对象编码方式变成了 `None` ! 151 | 152 | .. code-block:: shell-session 153 | 154 | $ python2 stdio-encoding.py 2>/dev/null 155 | stdin UTF-8 156 | stdout UTF-8 157 | stderr None 158 | 159 | 将标准输出写到管道,行为也是一样的! 160 | 161 | .. code-block:: shell-session 162 | 163 | $ python2 stdio-encoding.py | cat 164 | stdin UTF-8 165 | stdout None 166 | stderr UTF-8 167 | 168 | 为啥继承终端输入输出, `Python` 可以给标准 `IO` 文件对象设置正确的编码呢? 169 | 这是因为 `Python` 可通过用户设置的环境变量获悉终端的编码方式: 170 | 171 | .. code-block:: shell-session 172 | 173 | $ env | grep UTF 174 | LANG=en_US.UTF-8 175 | LC_ALL=en_US.UTF-8 176 | LC_CTYPE=UTF-8 177 | 178 | 至此,问题的症结已经对位到,解决方案也呼之欲出。 179 | 180 | 方法一:PYTHONIOENCODING 环境变量 181 | --------------------------------- 182 | 183 | 第一种解决方法是,通过环境变量,明确告诉 `Python` 进行 `IO` 的编码方式: 184 | 185 | .. code-block:: shell-session 186 | 187 | $ PYTHONIOENCODING=UTF-8 python2 say-hello.py 188 | 你好,世界! 189 | 190 | 还是原来的代码,设置 `PYTHONIOENCODING` 环境变量后程序成功运行了! 191 | 192 | 方法二:设置文件对象编码 193 | ------------------------ 194 | 195 | 第二种方法,则是将 `sys.stdout` 换掉: 196 | 197 | .. literalinclude:: /_src/practices/py2-encoding/say-hello-utf8.py 198 | :language: python 199 | :lines: 16- 200 | 201 | .. code-block:: shell-session 202 | 203 | $ python2 say-hello-utf8.py | cat 204 | 你好,世界! 205 | 206 | 看到没有,程序运行也正常了! 207 | 208 | 方法三:设置程序默认编码 209 | ------------------------ 210 | 211 | 这是一个无脑大招,几乎可以应对大部分编码问题! 212 | 213 | 方法很简单,只需将入一下若干代码,重新设置程序的默认编码方式即可: 214 | 215 | .. code-block:: python 216 | 217 | import sys 218 | reload(sys) 219 | sys.setdefaultencoding('UTF8') 220 | 221 | 下一步 222 | ====== 223 | 224 | .. include:: /_fragments/next-step-to-wechat-mp.rst 225 | 226 | .. include:: /_fragments/wechat-reward.rst 227 | 228 | .. include:: /_fragments/disqus.rst 229 | 230 | .. comments 231 | comment something out below 232 | 233 | -------------------------------------------------------------------------------- /docs/zh_CN/practices/string-similarity.rst: -------------------------------------------------------------------------------- 1 | .. Python计算字符串相似度 2 | FileName: string-similarity.rst 3 | Author: Fasion Chan 4 | Created: 2018-12-10 17:16:50 5 | @contact: fasionchan@gmail.com 6 | @version: $Id$ 7 | 8 | Description: 9 | 10 | Changelog: 11 | 12 | .. meta:: 13 | :description lang=zh: 14 | 基于difflib.SequenceMatcher类,我们可以实现一个用于计算字符串相似度的函数。 15 | ratio方法返回一个系数,衡量两个字符串的相识度,取值在0-1之间。 16 | :keywords: python, string similarity, 字符串相似度, difflib 17 | 18 | ====================== 19 | Python计算字符串相似度 20 | ====================== 21 | 22 | 背景 23 | ==== 24 | 25 | 笔者最近有个任务需要从多个系统取出工单信息进行处理, 26 | 但是工单只有一个标题可以关联,而且还不是严格相等的。 27 | 例如: 28 | 29 | - 易查通日常升级的发布请示 30 | - 【易查通】易查通系统日常升级 31 | 32 | 这种判断比较棘手,只能利用 **字符串相似度** 进行衡量: 33 | 34 | .. code-block:: python 35 | 36 | if similarity('易查通日常升级的发布请示', '【易查通】易查通系统日常升级') > 0.5: 37 | print('哥俩是同个工单') 38 | 39 | 那么, `Python` 有现成的类库可衡量字符串相似度么? 40 | 41 | difflib 42 | ======= 43 | 44 | 基于 `difflib.SequenceMatcher`_ 类,我们可以实现一个用于计算字符串相似度的函数: 45 | 46 | .. code-block:: python 47 | 48 | from difflib import SequenceMatcher 49 | 50 | def similarity(a, b): 51 | return SequenceMatcher(None, a, b).ratio() 52 | 53 | `ratio` 方法返回一个系数,衡量两个字符串的相识度,取值在 `0-1` 之间。 54 | 55 | 如果两个字符串完全相同,则系数为 `1.0` : 56 | 57 | .. code-block:: pycon 58 | 59 | >>> similarity('fasionchan', 'fasionchan') 60 | 1.0 61 | 62 | 如果两个字符串完全没有任何相同之处,则系数为 `0.0` : 63 | 64 | .. code-block:: pycon 65 | 66 | >>> similarity('fasionchan', '') 67 | 0.0 68 | >>> similarity('aaaaaaaa', 'bbbbbbbb') 69 | 0.0 70 | 71 | 其他情况则介于 `0` 与 `1` 之间,越接近 `1` 越相似: 72 | 73 | .. code-block:: pycon 74 | 75 | >>> similarity('apple', 'banana') 76 | 0.18181818181818182 77 | >>> similarity('易查通日常升级的发布请示', '【易查通】易查通系统日常升级') 78 | 0.5384615384615384 79 | 80 | 下一步 81 | ====== 82 | 83 | .. include:: /_fragments/next-step-to-wechat-mp.rst 84 | 85 | .. include:: /_fragments/wechat-reward.rst 86 | 87 | .. include:: /_fragments/disqus.rst 88 | 89 | .. _difflib.SequenceMatcher: https://docs.python.org/2/library/difflib.html#difflib.SequenceMatcher 90 | 91 | .. comments 92 | comment something out below 93 | 94 | -------------------------------------------------------------------------------- /docs/zh_CN/scripts/auto-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # FileName: auto-build.sh 3 | # Author: Fasion Chan 4 | # @contact: fasionchan@gmail.com 5 | # @version: $Id$ 6 | # 7 | # Description: 8 | # 9 | # Changelog: 10 | # 11 | # 12 | 13 | SELF_PATH=`realpath "$0"` 14 | SCRIPT_DIR_PATH=`dirname "$SELF_PATH"` 15 | DOC_ROOT_PATH=`dirname "$SCRIPT_DIR_PATH"` 16 | PYENV_PATH="$DOC_ROOT_PATH/opt/pyenv" 17 | BUILD_PATH="$DOC_ROOT_PATH/_build" 18 | 19 | BIND_ADDR=python.local 20 | sudo ifconfig lo0 alias $BIND_ADDR up 21 | 22 | rm -rf "$BUILD_PATH" 23 | ( 24 | cd "$DOC_ROOT_PATH" 25 | PATH="$PYENV_PATH/bin:$PATH" "$PYENV_PATH/bin/sphinx-autobuild" \ 26 | --ignore "*.swp" \ 27 | -H $BIND_ADDR \ 28 | -p 58000 \ 29 | . "$BUILD_PATH/html" 30 | ) 31 | -------------------------------------------------------------------------------- /docs/zh_CN/scripts/build-deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Author: fasion 4 | # Created time: 2019-11-04 09:34:59 5 | # Last Modified by: fasion 6 | # Last Modified time: 2019-11-04 20:30:18 7 | 8 | SELF_PATH=`realpath "$0"` 9 | SCRIPT_DIR_PATH=`dirname "$SELF_PATH"` 10 | DOC_ROOT_PATH=`dirname "$SCRIPT_DIR_PATH"` 11 | DOCS_PATH=`dirname "$DOC_ROOT_PATH"` 12 | REPO_PATH=`dirname "$DOCS_PATH"` 13 | VAR_PATH="$DOC_ROOT_PATH/var" 14 | CLONE_PATH="$VAR_PATH/clone" 15 | 16 | if [ -e "$CLONE_PATH" ]; then 17 | read -p "delete clone repo $CLONE_PATH (y or n)? " value 18 | if [ "$value" == "y" ]; then 19 | rm -rf "$CLONE_PATH" 20 | else 21 | exit 1 22 | fi 23 | fi 24 | 25 | git clone $REPO_PATH $CLONE_PATH 26 | 27 | ( 28 | cd "$CLONE_PATH" && \ 29 | "$CLONE_PATH/docs/zh_CN/scripts/setup.sh" && \ 30 | "$CLONE_PATH/docs/zh_CN/scripts/build.sh" && \ 31 | ossutil -e oss-cn-shanghai.aliyuncs.com cp -f -r "$CLONE_PATH/docs/zh_CN/_build/html" oss://works-python/zh_CN/latest 32 | ) 33 | -------------------------------------------------------------------------------- /docs/zh_CN/scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Author: fasion 4 | # Created time: 2019-11-04 08:38:35 5 | # Last Modified by: fasion 6 | # Last Modified time: 2019-11-04 08:44:15 7 | 8 | SELF_PATH=`realpath "$0"` 9 | SCRIPT_DIR_PATH=`dirname "$SELF_PATH"` 10 | DOC_ROOT_PATH=`dirname "$SCRIPT_DIR_PATH"` 11 | DOCS_PATH=`dirname "$DOC_ROOT_PATH"` 12 | REPO_PATH=`dirname "$DOCS_PATH"` 13 | PYENV_PATH="$DOC_ROOT_PATH/opt/pyenv" 14 | PIP_PATH="$PYENV_PATH/bin/pip" 15 | REAL_PYENV_PATH="$HOME/opt/pythons/pyenv.sphinx" 16 | PYENV_BIN_PATH="$PYENV_PATH/bin" 17 | 18 | ( 19 | cd "$DOC_ROOT_PATH" 20 | PATH="$PATH:$PYENV_BIN_PATH" make html 21 | ) 22 | -------------------------------------------------------------------------------- /docs/zh_CN/scripts/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # FileName: setup.sh 3 | # Author: Fasion Chan 4 | # @contact: fasionchan@gmail.com 5 | # @version: $Id$ 6 | # 7 | # Description: 8 | # 9 | # Changelog: 10 | # 11 | # 12 | 13 | SELF_PATH=`realpath "$0"` 14 | SCRIPT_DIR_PATH=`dirname "$SELF_PATH"` 15 | DOC_ROOT_PATH=`dirname "$SCRIPT_DIR_PATH"` 16 | DOCS_PATH=`dirname "$DOC_ROOT_PATH"` 17 | REPO_PATH=`dirname "$DOCS_PATH"` 18 | PYENV_PATH="$DOC_ROOT_PATH/opt/pyenv" 19 | PIP_PATH="$PYENV_PATH/bin/pip" 20 | REAL_PYENV_PATH="$HOME/opt/pythons/pyenv.sphinx" 21 | 22 | if [ ! -e "$REAL_PYENV_PATH" ]; then 23 | mkdir -p "$REAL_PYENV_PATH" 24 | virtualenv -p python3 "$REAL_PYENV_PATH" 25 | fi 26 | 27 | if [ ! -e "$PYENV_PATH" ]; then 28 | mkdir -p `dirname "$PYENV_PATH"` 29 | ln -s "$REAL_PYENV_PATH" "$PYENV_PATH" 30 | fi 31 | 32 | "$PIP_PATH" install -r "$REPO_PATH/requirements/docs.txt" 33 | "$PIP_PATH" install -r "$REPO_PATH/requirements/docs-dev.txt" 34 | -------------------------------------------------------------------------------- /docs/zh_CN/tutorial/arithmetic.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Author: fasion 3 | Created time: 2020-03-15 22:15:01 4 | Last Modified by: fasion 5 | Last Modified time: 2020-03-16 20:15:12 6 | 7 | .. meta:: 8 | :description lang=zh: 9 | :keywords: python, 教程, 入门, 基础, 菜鸟, 数学运算, 变量 10 | 11 | ======== 12 | 数学运算 13 | ======== 14 | 15 | 我们已经 *Python* 开发环境,并且成功运行第一个 *Python* 程序。 16 | 虽然程序只是在屏幕上打印一句话,但这只是第一步,我们还可以让计算机执行更高级的任务呢! 17 | 18 | 计算器 19 | ====== 20 | 21 | 我们可以将 *Python* 当做计算器来用,让计算机做一些简单的数学运算。 22 | 打开 *Python* 终端,输入算式并按回车即可,例如计算 *1 + 1* 的值: 23 | 24 | .. code-block:: python 25 | 26 | >>> 1 + 1 27 | 2 28 | 29 | 不止加法,常用的数学运算符, *Python* 都支持: 30 | 31 | .. code-block:: python 32 | 33 | >>> # 减法 34 | >>> 10 - 2 35 | 8 36 | 37 | >>> # 乘法 38 | >>> 5 * 5 39 | 25 40 | 41 | >>> # 除法 42 | >>> 1 / 4 43 | 0.25 44 | 45 | >>> # 平方 46 | >>> 5 ** 2 47 | 25 48 | 49 | >>> # 立方 50 | >>> 2 ** 3 51 | 8 52 | 53 | # 乘方(10的10次方) 54 | >>> 10 ** 10 55 | 10000000000 56 | 57 | .. note:: 58 | 59 | 请注意,*#* 号开头表示 **注释** , *Python* 将忽略注释内容。 60 | 61 | 运算符优先级 62 | ============ 63 | 64 | 对于包含多个运算符的算式,计算顺序由运算符优先级决定。 65 | 小时候我们都知道,先算乘除,再算加减,同级按从左到右的顺序计算。 66 | 67 | .. code-block:: python 68 | 69 | >>> 1 + 2 + 3 70 | 6 71 | 72 | 这个式子先计算 *1 + 2* ,再将结果与 *3* 相加,等价于: 73 | 74 | .. code-block:: python 75 | 76 | >>> 1 + 2 77 | 3 78 | >>> 3 + 3 79 | 6 80 | 81 | 而下面这个式子则先计算乘法,再跟前面的 *1* 相加: 82 | 83 | .. code-block:: python 84 | 85 | >>> 1 + 10 * 10 86 | 101 87 | 88 | >>> # 等价于 89 | >>> 10 * 10 90 | 100 91 | >>> 1 + 100 92 | 101 93 | 94 | 如果需要先计算加法,可以用括号将加法括起来: 95 | 96 | .. code-block:: python 97 | 98 | >>> (1 + 10) * 10 99 | 110 100 | 101 | 变量 102 | ==== 103 | 104 | 现在,我们来做一些有意义的计算,例如计算圆的面积。 105 | 假设以 *3.14* 为圆周率,按圆面积计算公式 :math:`\pi r^2` 半径为 *1* 的圆面积可以这样计算: 106 | 107 | .. code-block:: python 108 | 109 | >>> 3.14 * 1 ** 2 110 | 3.14 111 | 112 | 这么简单不如口算得了,来点稍微复杂一点的: 113 | 114 | .. code-block:: python 115 | 116 | >>> 3.14 * 1.5 ** 2 117 | 7.065 118 | 119 | 如果以 *3.14159* 为圆周率,结果又是多少呢? 120 | 121 | .. code-block:: python 122 | 123 | >>> 3.14159 * 1.5 ** 2 124 | 7.0685775 125 | 126 | 由于圆周率是一个很长的常数,容易写错,我们可以用一个变量将它保存起来: 127 | 128 | .. code-block:: python 129 | 130 | >>> pi = 3.14159 131 | 132 | 程序中的变量可以理解成一个保存着某个值的名字,通过 **变量名** 即可取出对应的 **值** 。 133 | 我们将变量 *pi* 的值打印到屏幕看看: 134 | 135 | .. code-block:: python 136 | 137 | >>> print(pi) 138 | 3.14159 139 | 140 | 这样一来,我们计算圆面积时便无须敲下长长的小数了,直接使用变量 *pi* 即可: 141 | 142 | .. code-block:: python 143 | 144 | >>> pi * 1.5 ** 2 145 | 7.0685775 146 | 147 | 变量,顾名思义,值是可以改变的。例如,我们可以将 *pi* 的值修改为 *3.14* : 148 | 149 | .. code-block:: python 150 | 151 | >>> pi = 3.14 152 | >>> pi 153 | 3.14 154 | 155 | 现在,以新的圆周率,重新计算半径为 *1.5* 的圆的面积: 156 | 157 | .. code-block:: python 158 | 159 | >>> pi * 1.5 ** 2 160 | 7.065 161 | 162 | 顺便提一下,使用变量前必须先定义变量,否则程序将报错: 163 | 164 | .. code-block:: python 165 | 166 | >>> pi2 167 | Traceback (most recent call last): 168 | File "", line 1, in 169 | NameError: name 'pi2' is not defined 170 | 171 | 附录 172 | ==== 173 | 174 | .. include:: /_fragments/next-step-to-wechat-mp.rst 175 | 176 | .. include:: /_fragments/wechat-reward.rst 177 | 178 | .. include:: /_fragments/disqus.rst 179 | -------------------------------------------------------------------------------- /docs/zh_CN/tutorial/condition.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Author: fasion 3 | Created time: 2020-03-16 20:13:34 4 | Last Modified by: fasion 5 | Last Modified time: 2020-03-21 22:24:46 6 | 7 | .. meta:: 8 | :description lang=zh: 9 | :keywords: python, 教程, 入门, 基础, 菜鸟, 条件判断, if, else, elif 10 | 11 | =============== 12 | Python 条件判断 13 | =============== 14 | 15 | 考试成绩出来了,同学们都考得怎么样呢?心里不禁忐忑起来。 16 | 17 | 老师说,成绩达到 *60* 分或以上的才及格,不及格的童鞋要完成额外布置的作业!!! 18 | 那么,怎么让 *Python* 帮我们判断成绩是不是及格呢? 19 | 20 | if 语句 21 | ======= 22 | 23 | 我们可以用 *if* 语句来判断某个成绩是否及格,示例程序如下: 24 | 25 | .. literalinclude:: /_src/tutorial/condition/whether-pass.py 26 | :language: python 27 | :linenos: 28 | 29 | 第 *10* 行中的 *if* 语句意思是:如果变量 *score* 的值大于等于 *60* 就执行 *if* 下面的代码块。 30 | 代码块只有一行代码,即 *print* 语句,将字符串 ``成绩及格!`` 输出到屏幕。 31 | 32 | 注意到,代码块比 *if* 缩进了 *4* 个空格。 33 | *Python* 以缩进区分不同代码块,这跟其他主流编程语言略有差异。 34 | 缩进可以是空格,也可以是制表符,同一代码块缩进必须一致。 35 | 36 | 小明这次考了 *85* 分,大于等于 *60* 条件成立,程序将如我们所料,输出 ``成绩及格!`` : 37 | 38 | .. code-block:: shell-session 39 | 40 | $ python whether-pass.py 41 | 请输入分数:85 42 | 成绩及格! 43 | 44 | 小刚这次只考了 *55* 分,不满足大于等于 *60* 的条件,因此没有输出 ``成绩及格!`` : 45 | 46 | .. code-block:: shell-session 47 | 48 | $ python whether-pass.py 49 | 请输入分数:55 50 | 51 | if 语法结构 52 | =========== 53 | 54 | 现在,回过头来研究 *if* 语句的语法结构。 55 | 56 | 计算机只能读懂编程语言,无法理解自然语言,我们只能通过编程语言与计算机交互。 57 | 从这个角度看,编程就像翻译——将任务翻译成编程语言,再交给计算机来执行。 58 | 59 | 汉语、英语等自然语言都有一定的语法结构,编程语言也有自己的语法。 60 | 与自然语言相比,编程语言规则更加简单,但也更加严格,错一个符号都不行。 61 | 62 | 那么, *Python* 这种编程语言的语法结构是怎样的呢? 63 | 我们以 *if* 为起点,开始学习: 64 | 65 | .. figure:: /_images/tutorial/condition/761edd878643e26832d88b5f8ca0ad24.png 66 | 67 | 如上图, *if* 语句是由以下 *3* 个部分构成有机整体: 68 | 69 | - *if* **关键词** ( *keyword* ),它标志着一个 *if* 语句的开始,还有其他关键字在等着我们; 70 | - **判断条件** ( *condition* ),这是一个逻辑表达式,可求值为 **真** ( *true* )或 **假** ( *false* ); 71 | - **真分支** ( *true branch* ),这是一个代码块,当条件成立(表达式求值为真)时才执行; 72 | 73 | 请注意,条件表达式后面有一个英文冒号 ``:`` 。 74 | 此外,代码块必须缩进,可以是一个 **空格** 或者 **制表符** 。 75 | 如果代码块里有多条语句, *Python* 将按照从上往下的顺序依次执行。 76 | 77 | 当条件表达式求值为 **真** 时, *Python* 先执行真分支代码块,再接着执行下面的语句,如绿色箭头所示。 78 | 当条件表达式求值为 **假** 时, *Python* 跳过真分支代码块,直接执行下面的语句,如红色箭头所示。 79 | 80 | .. figure:: /_images/tutorial/condition/5fcd46532e730e668245b18751491f55.webp 81 | :width: 360px 82 | 83 | 逻辑表达式 84 | ========== 85 | 86 | **逻辑表达式** ( *logic expression* )是一种求值结果是 **布尔值** ( *boolean value* )的表达式。 87 | 布尔只有两种值,要么为 **真** ( *true* ),要么为 **假** ( *false* )。 88 | 如果表达式成立,求值结果为真;否则,求值结果为假。 89 | 90 | 例如, ``1 < 2`` 成立,因此 *Python* 判断为 *True* : 91 | 92 | .. code-block:: python 93 | 94 | >>> 1 < 2 95 | True 96 | 97 | 这里小于号 ``<`` 是一个 **比较操作符** ( *comparison operator* ),对两个操作数进行比较,返回布尔值,表明比较关系是否成立。 98 | ``2 < 2`` 由于比较不成立, *Python* 判断为 *False* : 99 | 100 | .. code-block:: python 101 | 102 | >>> 2 < 2 103 | False 104 | 105 | 小明考了 *85* 分,大于等于 *60* 分成立,因此及格: 106 | 107 | .. code-block:: python 108 | 109 | >>> score = 85 110 | >>> score >= 60 111 | True 112 | 113 | 小刚只考了 *55* 分,大于等于 *60* 分不成立,也就不及格了: 114 | 115 | .. code-block:: python 116 | 117 | >>> score = 55 118 | >>> score >= 60 119 | False 120 | 121 | if-else 语句 122 | ============ 123 | 124 | 如果想在成绩及格时输出 ``成绩及格!`` ,不及格时输出 ``成绩不及格!`` ,有办法做到吗? 125 | 126 | 当然了,我们可以用 *if-else* 语句,程序示例如下: 127 | 128 | .. literalinclude:: /_src/tutorial/condition/pass-or-not.py 129 | :language: python 130 | :linenos: 131 | 132 | *if-else* 语句比 *if* 多了一个 *else* 分支,即 **假分支** , 假分支在条件不成立时才执行。 133 | 134 | 小刚成绩只有 *55* 分,不满足大于等于 *60* 这个条件。 135 | 因此, *Python* 选择执行假分支,即第 *13* 处的代码块,向屏幕输出 ``成绩不及格!`` 字样。 136 | 137 | .. code-block:: shell-session 138 | 139 | $ python pass-or-not.py 140 | 请输入分数:55 141 | 成绩不及格! 142 | 143 | if-else 语法结构 144 | ================ 145 | 146 | *if-else* 语句是 *if* 语句的扩展,包含一个 *else* 分支,由以下 *5* 个部分组成: 147 | 148 | .. figure:: /_images/tutorial/condition/8e556101bb9b43a00dd325c6baee8b7a.png 149 | 150 | - *if* **关键词** ( *keyword* ),同 *if* 语句; 151 | - **判断条件** ( *condition* ),同 *if* 语句; 152 | - **真分支** ( *true branch* ),同 *if* 语句; 153 | - *else* **关键词** ( *keyword* ),标志着假分支的开始; 154 | - **假分支** ( *false branch* ),当条件不成立(条件表达式求值为 **假** )时才执行的代码块; 155 | 156 | 请特别注意, *else* 关键词后面同样需要一个英文冒号 ``:`` 。 157 | 158 | if-elif-else 语句 159 | ================= 160 | 161 | 现在,老师想根据成绩为同学们计算等级,分为 *4* 档: 162 | 163 | - 优秀,成绩 *90* 分或以上; 164 | - 良好,成绩 *70* 分或以上; 165 | - 及格,成绩 *60* 分或以上; 166 | - 不及格,成绩达不到 *60* 分; 167 | 168 | 等级计算需要判断多个条件,相对复杂些,用一个流程图来表示更清晰: 169 | 170 | .. figure:: /_images/tutorial/condition/755637ea7b53648f78032cff2fbe408a.svg 171 | :width: 600px 172 | 173 | 那么, *Python* 有办法实现这种同时包含多个条件的判断吗? 174 | 答案是肯定的, *if-elif-else* 语句闪亮登场! 175 | 成绩等级计算程序可以这样来写: 176 | 177 | .. literalinclude:: /_src/tutorial/condition/show-level.py 178 | :language: python 179 | :linenos: 180 | 181 | *if-elif-else* 同时包含多个判断条件,第一条件以 *if* 关键字开头,其余条件均以 *elif* 开头。 182 | 每个判断条件都关联着一个真分支,包含条件成立时需要执行的代码块。 183 | *Python* 依次对每个条件进行检查,一旦某个条件成立便执行对应的代码块,其余条件则不再检查。 184 | 如果所有条件均不成立, *Python* 将执行 *else* 分支,即假分支的代码。 185 | 186 | 由于小军考了 *95* 分满足第一个条件, *Python* 输出 ``优秀`` ,不再检查其余条件了: 187 | 188 | .. code-block:: shell-session 189 | 190 | $ python show-level.py 191 | 请输入分数:95 192 | 优秀 193 | 194 | 而小刚只有 *55* 分, *Python* 逐个检查判断条件,均不成立,便只好输出 ``不及格`` 了: 195 | 196 | .. code-block:: shell-session 197 | 198 | $ python show-level.py 199 | 请输入分数:55 200 | 不及格 201 | 202 | #. *55* 大于 *90* 是否成立? 👉 不成立; 203 | #. *55* 大于 *70* 是否成立? 👉 不成立; 204 | #. *55* 大于 *60* 是否成立? 👉 不成立; 205 | #. 执行 *else* 分支,输出不及格; 206 | 207 | if-elif-else 语法结构 208 | ===================== 209 | 210 | *if-elif-else* 语句是 *if-else* 语句的扩展,可以包括若干个 *elif* 分支,结构如下: 211 | 212 | .. figure:: /_images/tutorial/condition/3f6deeb783d1d135880a8dd6776814aa.png 213 | 214 | - *if* **关键词** ( *keyword* ),标志着第一个判断条件的开始; 215 | - **判断条件** ( *condition* ),同 *if* 语句; 216 | - **真分支** ( *true branch* ),同 *if* 语句; 217 | - *elif* **关键词** ( *keyword* ),标志着另一个判断条件的开始; 218 | - *else* **关键词** ( *keyword* ),同 *if-else* 语句; 219 | - **假分支** ( *false branch* ),同 *if-else* 语句; 220 | 221 | 同样请注意,每个条件表达式后都有一个英文冒号 ``:`` 。 222 | 223 | 练习 224 | ==== 225 | 226 | 学校修改了成绩等级规则,现划分为 *5* 个等级,分别如下: 227 | 228 | - 卓越,成绩 *90* 分或以上; 229 | - 优秀,成绩 *80* 分或以上; 230 | - 良好,成绩 *70* 分或以上; 231 | - 及格,成绩 *60* 分或以上; 232 | - 不及格,成绩不足 *60* 分; 233 | 234 | 请动动手指,帮老师修改程序,以适应新等级划分规则。 235 | 236 | 附录 237 | ==== 238 | 239 | .. include:: /_fragments/appendix.rst 240 | 241 | 参考文献 242 | ======== 243 | 244 | #. `Python if else elif Statement `_ 245 | 246 | .. include:: /_fragments/disqus.rst 247 | -------------------------------------------------------------------------------- /docs/zh_CN/tutorial/index.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Author: fasion 3 | Created time: 2020-03-14 11:51:12 4 | Last Modified by: fasion 5 | Last Modified time: 2020-03-21 23:18:07 6 | 7 | ============== 8 | Python入门教程 9 | ============== 10 | 11 | .. toctree:: 12 | :titlesonly: 13 | 14 | 环境准备 15 | 数学运算 16 | 条件判断 17 | -------------------------------------------------------------------------------- /docs/zh_CN/tutorial/prepare.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Author: huangxiaoyan 3 | Created time: 2020-02-29 11:18:33 4 | Last Modified by: fasion 5 | Last Modified time: 2020-03-21 23:18:43 6 | 7 | ==================== 8 | 搭建 Python 编程环境 9 | ==================== 10 | 11 | *Python* 是一种解释型、面向对象、动态数据类型的高级程序设计语言。 12 | 语法简单易学,不管是用来专业开发,还是业余辅助办公,都是不二之选。 13 | 本教程将结合实际应用场景,提供丰富的例子,一步步教你快速掌握 *Python*。 14 | 15 | 开始学习 *Python* 编程前,需要先准备 *Python* 运行环境。 16 | 17 | *Python* 编程环境搭建步骤,因操作系统类型而异。 18 | 目前,市面上主流操作系统有 :ref:`prepare-windows` ,以及 `Linux`_ 、 *macOS* 等类 :ref:`prepare-unix` 系统,编程环境搭建步骤分别如下: 19 | 20 | - :ref:`prepare-windows` 21 | - :ref:`prepare-unix` 22 | 23 | .. _prepare-windows: 24 | 25 | Windows 26 | ======= 27 | 28 | 如果你使用的是 *Windows* 系统,就需要手动进行安装。 29 | 下面以 *Windows 10* 系统为例,介绍如何安装并运行 *Python* 。 30 | 31 | 下载 Python 32 | ----------- 33 | 34 | 首先,进入 *Python* 官网( `www.python.org`_ ),下载最新版本。如果需要下载其他的 *Python* 版本,也可以在下载页面找到对应的版本: 35 | 36 | .. figure:: /_images/tutorial/prepare/8333a0438108a6918bb019f59915922c.png 37 | :width: 441px 38 | 39 | 选择对应版本后,可以找到这些安装程序,请根据系统位数选择: 40 | 41 | .. figure:: /_images/tutorial/prepare/cdfc0bddc3e38e96ce9b509061c162c8.png 42 | :width: 460px 43 | 44 | 本文以 *Python 3.8.1* 为例,演示 *Python* 安装方法。 45 | 46 | 安装 Python 47 | ----------- 48 | 49 | 下载后的 *Python 3.8.1* 版本是一个 *exe* 文件,即可执行文件,双击该文件进行安装: 50 | 51 | .. figure:: /_images/tutorial/prepare/bc058ec0ac3b9c727de6aec8e8f40048.png 52 | :width: 600px 53 | 54 | 点击 *Install Now* ,选择要安装的组件,默认即可: 55 | 56 | .. figure:: /_images/tutorial/prepare/183c7f22507364172b0c3dfe4bc630cb.png 57 | :width: 600px 58 | 59 | 点击 *Next*,出现下图: 60 | 61 | .. figure:: /_images/tutorial/prepare/328f3d36b38281c4e8610158c0ab531a.png 62 | :width: 600px 63 | 64 | 在此勾选 *Add Python to environment variables*,意为将 *Python* 加入环境变量: 65 | 66 | .. figure:: /_images/tutorial/prepare/845b26786be67369999be4da7c63e8fa.png 67 | :width: 600px 68 | 69 | 点击 *Install*,开始安装。 70 | 71 | 运行 Python 72 | ----------- 73 | 74 | 现在,让我们来验证下,*Python* 是否安装成功了。 75 | 76 | IDLE 77 | ++++ 78 | 79 | 我们可以使用 *Python* 的 *IDLE* 工具来执行代码。在 *Windows* 搜索框输入 *idle*: 80 | 81 | .. figure:: /_images/tutorial/prepare/25e827b9d57fd969aff754c5eff991c7.png 82 | :width: 600px 83 | 84 | 打开 *IDLE* 工具,可以看到如下界面: 85 | 86 | .. figure:: /_images/tutorial/prepare/bb0399070c7d32c0728a82160bea01ee.png 87 | :width: 600px 88 | 89 | 三个大于号组成输入提示符 ``>>>``,提示我们输入需要执行的 *Python* 代码。 90 | 91 | 现在,让 *Python* 执行什么任务好呢?不如先让它在屏幕上打印一句话吧! 92 | 输入 ``print('Hello, world!')`` ,然后按回车: 93 | 94 | .. figure:: /_images/tutorial/prepare/9c993ff30d24652b983f83a8ba98fcec.png 95 | :width: 600px 96 | 97 | 看到没, *Python* 在屏幕上输出了 ``Hello, world!`` ! 98 | 99 | 你或许还心存疑虑,然而此刻你只需知道 *print* 是一个将内容输出到屏幕的函数,单引号包括的是待输出内容即可。 100 | 至于其他的,我们接着慢慢学习。 101 | 102 | CMD 103 | +++ 104 | 105 | 除了 *IDLE* 工具外,也可以使用 *Windows* 的命令行工具来启动 *Python* 程序。 106 | 107 | 同样,*Windows* 搜索框输入 *cmd*: 108 | 109 | .. figure:: /_images/tutorial/prepare/f07028520b90eb758cae80c85c0ed4ea.png 110 | :width: 600px 111 | 112 | 由此可以打开 *Windows* 命令行工具: 113 | 114 | .. figure:: /_images/tutorial/prepare/1279dc29cb3fb67995797b1a815c14e7.png 115 | :width: 600px 116 | 117 | 首先,输入 *python* 并按回车,即可启动 *Python* 终端。 118 | 如果看到以下界面,说明 *Windows* 找到了这个程序: 119 | 120 | .. figure:: /_images/tutorial/prepare/359b20925aeaec421620f09d40739d8c.png 121 | :width: 600px 122 | 123 | 还记得在安装时,我们勾选了将 *Python* 加入到环境变量吗?正是这一步,让 *Windows* 能够识别 *Python* 程序。 124 | 125 | 我们同样让 *Python* 输出一句话。输入 ``print('Hello, world!')``,然后按回车: 126 | 127 | .. figure:: /_images/tutorial/prepare/2b61abc3cbfe066babe267c1792c48fa.png 128 | :width: 600px 129 | 130 | 可以看到,屏幕同样输出了 ``Hello, world!``。 131 | 132 | 至此,*Python* 环境搭建完毕,可以愉快地开始学习了! 133 | 134 | .. _prepare-unix: 135 | 136 | Unix 137 | ==== 138 | 139 | 如果你使用的是 *Linux* 和 *macOS* 等类 *Unix* 系统,事情就简单了。 140 | 类 *Unix* 系统一般都内置了 *Python* 环境,打开终端工具,即可使用。 141 | 142 | 以 *MacOS* 为例,先找到系统终端程序,它一般是这个样子的: 143 | 144 | .. figure:: /_images/tutorial/prepare/103edcde70f4483d67d4bb57f4a7cfb8.png 145 | 146 | 打开终端,将看到以下界面: 147 | 148 | .. figure:: /_images/tutorial/prepare/987c88e5e6860bc61280df7035adb73e.png 149 | 150 | 输入 *python*,然后按回车,启动 *Python* 解析器: 151 | 152 | .. figure:: /_images/tutorial/prepare/fcfab7c8303c418d371d288f66609ec6.png 153 | 154 | 三个大于号组成输入提示符 ``>>>`` ,提示我们输入需要执行的 *Python* 代码。 155 | 156 | 现在,让 *Python* 执行什么任务好呢?不如先让它在屏幕上打印一句话吧! 157 | 输入 ``print('Hello, world!')`` ,然后按回车: 158 | 159 | .. figure:: /_images/tutorial/prepare/f9a8891083f963159dd1278164721add.png 160 | 161 | 看到没, *Python* 在屏幕上输出了 ``Hello, world!`` ! 162 | 163 | 你或许还心存疑虑,然而此刻你只需知道 *print* 是一个将内容输出到屏幕的函数,单引号包括的是待输出内容即可。 164 | 至于其他的,我们接着慢慢学习。 165 | 166 | 附录 167 | ==== 168 | 169 | .. include:: /_fragments/appendix.rst 170 | 171 | .. include:: /_fragments/disqus.rst 172 | 173 | .. _Linux: https://linux.fasionchan.com/zh_CN/latest/index.html 174 | .. _www.python.org: https://www.python.org/ 175 | -------------------------------------------------------------------------------- /readthedocs.yml: -------------------------------------------------------------------------------- 1 | formats: [] 2 | requirements_file: requirements/docs.txt 3 | -------------------------------------------------------------------------------- /requirements/docs-dev.txt: -------------------------------------------------------------------------------- 1 | sphinx-autobuild==0.7.1 2 | -------------------------------------------------------------------------------- /requirements/docs.txt: -------------------------------------------------------------------------------- 1 | Sphinx==1.8.2 2 | sphinx-sitemap==0.3.1 3 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | .hypothesis/ 50 | .pytest_cache/ 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Django stuff: 57 | *.log 58 | local_settings.py 59 | db.sqlite3 60 | 61 | # Flask stuff: 62 | instance/ 63 | .webassets-cache 64 | 65 | # Scrapy stuff: 66 | .scrapy 67 | 68 | # Sphinx documentation 69 | docs/_build/ 70 | 71 | # PyBuilder 72 | target/ 73 | 74 | # Jupyter Notebook 75 | .ipynb_checkpoints 76 | 77 | # IPython 78 | profile_default/ 79 | ipython_config.py 80 | 81 | # pyenv 82 | .python-version 83 | 84 | # celery beat schedule file 85 | celerybeat-schedule 86 | 87 | # SageMath parsed files 88 | *.sage.py 89 | 90 | # Environments 91 | .env 92 | .venv 93 | env/ 94 | venv/ 95 | ENV/ 96 | env.bak/ 97 | venv.bak/ 98 | 99 | # Spyder project settings 100 | .spyderproject 101 | .spyproject 102 | 103 | # Rope project settings 104 | .ropeproject 105 | 106 | # mkdocs documentation 107 | /site 108 | 109 | # mypy 110 | .mypy_cache/ 111 | .dmypy.json 112 | dmypy.json 113 | 114 | # Pyre type checker 115 | .pyre/ 116 | -------------------------------------------------------------------------------- /src/libs/html-table/fruit-output.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding=utf8 -*- 3 | 4 | ''' 5 | FileName: fruit-output.py 6 | Author: Fasion Chan 7 | @contact: fasionchan@gmail.com 8 | @version: $Id$ 9 | 10 | Description: 11 | 12 | Changelog: 13 | 14 | ''' 15 | 16 | from HTMLTable import ( 17 | HTMLTable, 18 | ) 19 | 20 | # 标题 21 | table = HTMLTable(caption='果园收成表') 22 | 23 | # 表头行 24 | table.append_header_rows(( 25 | ('名称', '产量 (吨)', '环比', ''), 26 | ('', '', '增长量 (吨)', '增长率 (%)'), 27 | )) 28 | 29 | # 合并单元格 30 | table[0][0].attr.rowspan = 2 31 | table[0][1].attr.rowspan = 2 32 | table[0][2].attr.colspan = 2 33 | 34 | # 数据行 35 | table.append_data_rows(( 36 | ('荔枝', 11, 1, 10), 37 | ('芒果', 9, -1, -10), 38 | ('香蕉', 6, 1, 20), 39 | )) 40 | 41 | # 标题样式 42 | table.caption.set_style({ 43 | 'font-size': '15px', 44 | }) 45 | 46 | # 表格样式,即标签样式 47 | table.set_style({ 48 | 'border-collapse': 'collapse', 49 | 50 | 'word-break': 'keep-all', 51 | 'white-space': 'nowrap', 52 | 'font-size': '14px', 53 | }) 54 | 55 | # 统一设置所有单元格样式,
56 | table.set_cell_style({ 57 | 'border-color': '#000', 58 | 'border-width': '1px', 59 | 'border-style': 'solid', 60 | 61 | 'padding': '5px', 62 | }) 63 | 64 | # 表头样式 65 | table.set_header_row_style({ 66 | 'color': '#fff', 67 | 'background-color': '#48a6fb', 68 | 'font-size': '18px', 69 | }) 70 | # 覆盖表头单元格字体样式 71 | table.set_header_cell_style({ 72 | 'padding': '15px', 73 | }) 74 | 75 | # 调小次表头字体大小 76 | table[1].set_cell_style({ 77 | 'padding': '8px', 78 | 'font-size': '15px', 79 | }) 80 | 81 | # 遍历数据行,如果增长量为负,标红背景颜色 82 | for row in table.iter_data_rows(): 83 | if row[2].value < 0: 84 | row.set_style({ 85 | 'background-color': '#ffdddd', 86 | }) 87 | 88 | html = table.to_html() 89 | print(html) 90 | -------------------------------------------------------------------------------- /src/libs/matplotlib/font.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding=utf8 -*- 3 | 4 | ''' 5 | FileName: font.py 6 | Author: Fasion Chan 7 | @contact: fasionchan@gmail.com 8 | @version: $Id$ 9 | 10 | Description: 11 | 12 | Changelog: 13 | 14 | ''' 15 | 16 | import matplotlib 17 | matplotlib.use('TkAgg') 18 | 19 | import matplotlib.pyplot as plt 20 | import matplotlib.font_manager as mfm 21 | 22 | fonts = ( 23 | ('微软雅黑', 'Downloads/Microsoft Yahei.ttf',), 24 | ('中易黑体', 'Downloads/SimHei.ttf',), 25 | ('仿宋', 'Downloads/FangSong.ttf',), 26 | ('宋体', 'Downloads/STSong.ttf',), 27 | ) 28 | 29 | # load font files 30 | label_fonts = tuple( 31 | mfm.FontProperties(fname=path, size=10) 32 | for _, path in fonts 33 | ) 34 | 35 | title_fonts = label_fonts[0].copy() 36 | title_fonts.set_size(18) 37 | 38 | # data to plot 39 | labels = [name for name, _ in fonts] 40 | sizes = (215, 130, 245, 210,) 41 | 42 | colors = ('gold', 'yellowgreen', 'lightcoral', 'lightskyblue',) 43 | 44 | patches, texts, autotexts = plt.pie( 45 | sizes, 46 | labels=labels, 47 | colors=colors, 48 | autopct='%1.1f%%', 49 | ) 50 | 51 | for text, font in zip(texts, label_fonts): 52 | text.set_fontproperties(font) 53 | 54 | plt.title("编程语言", fontproperties=title_fonts) 55 | 56 | plt.show() 57 | -------------------------------------------------------------------------------- /src/libs/matplotlib/pie.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding=utf8 -*- 3 | 4 | ''' 5 | FileName: pie.py 6 | Author: Fasion Chan 7 | @contact: fasionchan@gmail.com 8 | @version: $Id$ 9 | 10 | Description: 11 | 12 | Changelog: 13 | 14 | ''' 15 | 16 | import matplotlib 17 | matplotlib.use('TkAgg') 18 | 19 | import matplotlib.pyplot as plt 20 | 21 | # data to plot 22 | labels = ('Python', 'C++', 'Ruby', 'Java',) 23 | sizes = (215, 130, 245, 210,) 24 | 25 | colors = ('gold', 'yellowgreen', 'lightcoral', 'lightskyblue',) 26 | 27 | plt.pie( 28 | sizes, 29 | labels=labels, 30 | colors=colors, 31 | autopct='%1.1f%%', 32 | ) 33 | 34 | plt.title("Programming Languages") 35 | 36 | plt.show() 37 | -------------------------------------------------------------------------------- /src/libs/zbarlight/read_qrcode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding=utf8 -*- 3 | 4 | ''' 5 | FileName: read_qrcode.py 6 | Author: Fasion Chan 7 | @contact: fasionchan@gmail.com 8 | @version: $Id$ 9 | 10 | Description: 11 | 12 | Changelog: 13 | 14 | ''' 15 | 16 | from PIL import Image 17 | import zbarlight 18 | 19 | # 二维码图片路径 20 | file_path = './zedhz-course-qrcode.jpg' 21 | 22 | # 读取文件 23 | with open(file_path, 'rb') as image_file: 24 | image = Image.open(image_file) 25 | image.load() 26 | 27 | # 识别二维码 28 | codes = zbarlight.scan_codes('qrcode', image) 29 | print('QR codes: %s' % codes) 30 | -------------------------------------------------------------------------------- /src/libs/zbarlight/zedhz-course-qrcode.jpg: -------------------------------------------------------------------------------- 1 | ../../docs/zh_CN/_static/zedhz-course-qrcode.jpg -------------------------------------------------------------------------------- /src/practices/argparse/agentx.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding=utf8 -*- 3 | 4 | ''' 5 | FileName: agentx.py 6 | Author: Fasion Chan 7 | @contact: fasionchan@gmail.com 8 | @version: $Id$ 9 | 10 | Description: 11 | 12 | Changelog: 13 | 14 | ''' 15 | 16 | import argparse 17 | 18 | 19 | class ServiceController(object): 20 | 21 | ''' 22 | 服务控制器 23 | 24 | 根据命令行参数,操作后台服务(守护进程)。 25 | ''' 26 | 27 | def __init__(self, conf_path): 28 | # 命令行参数 29 | self.conf_path = conf_path 30 | 31 | def status(self): 32 | ''' 33 | 查询服务运行状态 34 | ''' 35 | 36 | print('service is ...') 37 | 38 | def start(self): 39 | ''' 40 | 启动服务 41 | ''' 42 | 43 | print('starting') 44 | 45 | def stop(self): 46 | ''' 47 | 停止服务 48 | ''' 49 | 50 | print('stopping') 51 | 52 | def process(self, action): 53 | ''' 54 | 处理入口 55 | ''' 56 | 57 | getattr(self, action)() 58 | 59 | 60 | def main(): 61 | ''' 62 | 主函数 63 | 64 | 负责处理命令行参数并调用服务控制器。 65 | ''' 66 | 67 | # 命令行解析 68 | parser = argparse.ArgumentParser(prog='agentx') 69 | 70 | # 配置文件选项 71 | parser.add_argument( 72 | '-c', 73 | '--conf', 74 | dest='conf_path', 75 | metavar='conf_path', 76 | default='', 77 | required=False, 78 | help='configuration file path', 79 | ) 80 | 81 | # 操作选项 82 | parser.add_argument( 83 | 'action', 84 | nargs=1, 85 | metavar='action', 86 | choices=('status', 'start', 'stop',), 87 | help='action to carry out: status/start/stop', 88 | ) 89 | 90 | # 解析 91 | args = parser.parse_args() 92 | 93 | # 配置文件路径 94 | conf_path = args.conf_path 95 | # 执行动作 96 | action, = args.action 97 | 98 | 99 | # 处理 100 | service_controller = ServiceController(conf_path=conf_path) 101 | service_controller.process(action=action) 102 | 103 | if __name__ == '__main__': 104 | main() 105 | -------------------------------------------------------------------------------- /src/practices/binary-release/checktime.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding=utf8 -*- 3 | 4 | ''' 5 | FileName: checktime.py 6 | Author: Fasion Chan 7 | @contact: fasionchan@gmail.com 8 | @version: $Id$ 9 | 10 | Description: 11 | 12 | Changelog: 13 | 14 | ''' 15 | 16 | import ntplib 17 | 18 | from datetime import ( 19 | datetime, 20 | ) 21 | 22 | def format_ts(ts): 23 | return datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') 24 | 25 | def check_time(): 26 | client = ntplib.NTPClient() 27 | rsps = client.request('asia.pool.ntp.org', version=3) 28 | 29 | print('Server:', ntplib.ref_id_to_text(rsps.ref_id)) 30 | print('Offset:', rsps.offset) 31 | print('Time:', format_ts(rsps.tx_time)) 32 | 33 | if __name__ == '__main__': 34 | check_time() 35 | -------------------------------------------------------------------------------- /src/practices/binary-release/requirements.txt: -------------------------------------------------------------------------------- 1 | ntplib==0.3.3 2 | pyinstaller==3.6 3 | -------------------------------------------------------------------------------- /src/practices/citer/3/citer.c: -------------------------------------------------------------------------------- 1 | /** 2 | * FileName: citer.c 3 | * Author: Fasion Chan 4 | * @contact: fasionchan@gmail.com 5 | * @version: $Id$ 6 | * 7 | * Description: 8 | * 9 | * Changelog: 10 | * 11 | **/ 12 | 13 | #include 14 | 15 | 16 | /** 17 | * Iter type 18 | **/ 19 | typedef struct { 20 | // include object head 21 | PyObject_HEAD 22 | 23 | // util n, not included 24 | long int n; 25 | // current value 26 | long int i; 27 | } citer_Iter; 28 | 29 | 30 | /** 31 | * init function 32 | **/ 33 | static int citer_Iter_init(PyObject* self, PyObject* args, PyObject* kwds) { 34 | // pointer cast 35 | citer_Iter* iter = (citer_Iter*)self; 36 | 37 | // argument list 38 | // only one argument is needed: n 39 | static char *kw_list[] = {"n"}; 40 | 41 | // parse args 42 | if (! PyArg_ParseTupleAndKeywords(args, kwds, "|l", kw_list, &(iter->n))) { 43 | return -1; 44 | } 45 | 46 | // set current value to 0 47 | iter->i = 0; 48 | 49 | return 0; 50 | } 51 | 52 | 53 | /** 54 | * iter function 55 | **/ 56 | static PyObject* citer_Iter_iter(PyObject* self) { 57 | // just return itself 58 | Py_INCREF(self); 59 | return self; 60 | } 61 | 62 | 63 | /** 64 | * iternext function 65 | **/ 66 | static PyObject* citer_Iter_iternext(PyObject* self) { 67 | citer_Iter* iter = (citer_Iter*)self; 68 | 69 | // return current value and increase 70 | if (iter->i < iter->n) { 71 | PyObject *value = Py_BuildValue("l", iter->i); 72 | ++(iter->i); 73 | return value; 74 | } 75 | else { 76 | PyErr_SetNone(PyExc_StopIteration); 77 | return NULL; 78 | } 79 | } 80 | 81 | 82 | /** 83 | * Type object for Iter type 84 | **/ 85 | static PyTypeObject citer_IterType = { 86 | PyVarObject_HEAD_INIT(NULL, 0) 87 | "citer.Iter", /*tp_name*/ 88 | sizeof(citer_Iter), /*tp_basicsize*/ 89 | 0, /*tp_itemsize*/ 90 | 0, /*tp_dealloc*/ 91 | 0, /*tp_print*/ 92 | 0, /*tp_getattr*/ 93 | 0, /*tp_setattr*/ 94 | 0, /*tp_compare*/ 95 | 0, /*tp_repr*/ 96 | 0, /*tp_as_number*/ 97 | 0, /*tp_as_sequence*/ 98 | 0, /*tp_as_mapping*/ 99 | 0, /*tp_hash */ 100 | 0, /*tp_call*/ 101 | 0, /*tp_str*/ 102 | 0, /*tp_getattro*/ 103 | 0, /*tp_setattro*/ 104 | 0, /*tp_as_buffer*/ 105 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ 106 | "Iter object.", /* tp_doc */ 107 | 0, /* tp_traverse */ 108 | 0, /* tp_clear */ 109 | 0, /* tp_richcompare */ 110 | 0, /* tp_weaklistoffset */ 111 | citer_Iter_iter, /* tp_iter: __iter__() method */ 112 | citer_Iter_iternext, /* tp_iternext: next() method */ 113 | 0, /* tp_methods */ 114 | 0, /* tp_members */ 115 | 0, /* tp_getset */ 116 | 0, /* tp_base */ 117 | 0, /* tp_dict */ 118 | 0, /* tp_descr_get */ 119 | 0, /* tp_descr_set */ 120 | 0, /* tp_dictoffset */ 121 | (initproc)citer_Iter_init, /* tp_init */ 122 | 0, /* tp_alloc */ 123 | PyType_GenericNew, /* tp_new */ 124 | }; 125 | 126 | /** 127 | * module defination 128 | **/ 129 | static PyModuleDef citer_module = { 130 | PyModuleDef_HEAD_INIT, 131 | "citer", 132 | "Iter type for c iterator tutorial.", 133 | -1, 134 | NULL, NULL, NULL, NULL, NULL 135 | }; 136 | 137 | 138 | /** 139 | * module init function, called when being imported 140 | **/ 141 | PyMODINIT_FUNC 142 | PyInit_citer(void) { 143 | // initialize new data type 144 | if (PyType_Ready(&citer_IterType) < 0) { 145 | return NULL; 146 | } 147 | 148 | // create module object 149 | PyObject* module = PyModule_Create(&citer_module); 150 | if (NULL == module) { 151 | return NULL; 152 | } 153 | 154 | // add new type to module 155 | Py_INCREF(&citer_IterType); 156 | PyModule_AddObject(module, "Iter", (PyObject*)&citer_IterType); 157 | 158 | return module; 159 | } 160 | -------------------------------------------------------------------------------- /src/practices/py2-encoding/say-hello-utf8-2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding=utf8 -*- 3 | 4 | ''' 5 | FileName: say-hello-utf8-2.py 6 | Author: Fasion Chan 7 | @contact: fasionchan@gmail.com 8 | @version: $Id$ 9 | 10 | Description: 11 | 12 | Changelog: 13 | 14 | ''' 15 | 16 | import sys 17 | reload(sys) 18 | sys.setdefaultencoding('UTF8') 19 | 20 | print u'你好,世界!' 21 | -------------------------------------------------------------------------------- /src/practices/py2-encoding/say-hello-utf8.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding=utf8 -*- 3 | 4 | ''' 5 | FileName: say-hello-utf8.py 6 | Author: Fasion Chan 7 | @contact: fasionchan@gmail.com 8 | @version: $Id$ 9 | 10 | Description: 11 | 12 | Changelog: 13 | 14 | ''' 15 | 16 | import codecs 17 | import sys 18 | 19 | sys.stdout = codecs.getwriter('utf8')(sys.stdout) 20 | 21 | print u'你好,世界!' 22 | -------------------------------------------------------------------------------- /src/practices/py2-encoding/say-hello.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding=utf8 -*- 3 | 4 | ''' 5 | FileName: say-hello.py 6 | Author: Fasion Chan 7 | @contact: fasionchan@gmail.com 8 | @version: $Id$ 9 | 10 | Description: 11 | 12 | Changelog: 13 | 14 | ''' 15 | 16 | print u'你好,世界!' 17 | -------------------------------------------------------------------------------- /src/practices/py2-encoding/stdio-encoding.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding=utf8 -*- 3 | 4 | ''' 5 | FileName: stdio-encoding.py 6 | Author: Fasion Chan 7 | @contact: fasionchan@gmail.com 8 | @version: $Id$ 9 | 10 | Description: 11 | 12 | Changelog: 13 | 14 | ''' 15 | 16 | import sys 17 | 18 | for name in ('stdin', 'stdout', 'stderr'): 19 | print name, getattr(sys, name).encoding 20 | -------------------------------------------------------------------------------- /src/tutorial/condition/pass-or-not.py: -------------------------------------------------------------------------------- 1 | # -*- encoding=utf8 -*- 2 | 3 | # 提示用户输入分数,获取用户输入内容,并保存到变量 data 4 | data = input('请输入分数:') 5 | 6 | # 将用户输入分数从字符串转成整数数值,并保存到变量 score 7 | score = int(data) 8 | 9 | # 判断分数是否大于等于60 10 | if score >= 60: 11 | print('成绩及格!') 12 | else: 13 | print('成绩不及格!') 14 | -------------------------------------------------------------------------------- /src/tutorial/condition/show-level.py: -------------------------------------------------------------------------------- 1 | # -*- encoding=utf8 -*- 2 | 3 | # 提示用户输入分数,获取用户输入内容,并保存到变量 data 4 | data = input('请输入分数:') 5 | 6 | # 将用户输入分数从字符串转成整数数值,并保存到变量 score 7 | score = int(data) 8 | 9 | if score >= 90: 10 | print('优秀') 11 | elif score >= 70: 12 | print('良好') 13 | elif score >= 60: 14 | print('及格') 15 | else: 16 | print('不及格') 17 | -------------------------------------------------------------------------------- /src/tutorial/condition/whether-pass.py: -------------------------------------------------------------------------------- 1 | # -*- encoding=utf8 -*- 2 | 3 | # 提示用户输入分数,获取用户输入内容,并保存到变量 data 4 | data = input('请输入分数:') 5 | 6 | # 将用户输入分数从字符串转成整数数值,并保存到变量 score 7 | score = int(data) 8 | 9 | # 判断分数是否大于等于60 10 | if score >= 60: 11 | print('成绩及格!') 12 | --------------------------------------------------------------------------------