diff --git a/.gitignore b/.gitignore index 8fcada4..1260683 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ build/ *.pyc Makefile Pipfile +test* diff --git a/README.md b/README.md index 9b9c616..8f1fdc2 100644 --- a/README.md +++ b/README.md @@ -1,121 +1,1153 @@ +# 从零到一的 Python 学习路线 + +我在我的个人公众号(Python编程时光)分享过非常多的 Python 干货,由于公众号是个十分封闭的生态,读过之后,就没什么人会记住它了。不像网站那样有搜索引擎会给它们持续的曝光,历久弥香。 + +我自认为在我公众号里,发布的文章质量是非常高的,为了不让这些干货沉入海底,我开了这个仓库,方便有需要的人进行索引,择需阅读。 + + + +目前目录更新内容至 2021/3/20 发的文章。 + +## 01. 基础系列 + +### 1.1 基础必学 + +1、[盘点 Python 高手都写不出来的几个错误](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485974&idx=1&sn=6a6a2fb8bc5c2acd300ebecdf625086c&chksm=e8866af4dff1e3e2c528594310475edaf2839d7b09048270acbb0dccc124581eaa65b123d393&scene=27#wechat_redirect) + +2、[Python基础|深入闭包与变量作用域](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485039&idx=1&sn=23557ac2640819b568a426b2db4df69c&scene=21#wechat_redirect) + +3、[Python基础|类方法的强制重写与禁止重写](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485037&idx=1&sn=8f4838b5bc919631c5cb642120b010c2&scene=21#wechat_redirect) + +4、[Python基础|多继承与Mixin设计模式](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485032&idx=1&sn=35e1c7014bc3f668cc4b48d9c318f1f9&scene=21#wechat_redirect) + +5、[Python基础|理解元组存在的意义](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485038&idx=1&sn=d0c7ab3fc20b299e4a0b9f6b414e4070&scene=21#wechat_redirect) + +6、[你知道 Python里的「单分派泛函数」?](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484938&idx=1&sn=061fdb00ccc499aa0cfc304852adb143&scene=21#wechat_redirect) + +7、[类型注解的福音,提高Python代码可读性](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484901&idx=1&sn=8f506cb46edb94dfb668525399f30f9e&scene=21#wechat_redirect) + +8、[写几个 Python 进阶必备函数](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484973&idx=1&sn=451d381fa3021e14b514cc15907ce0c3&scene=21#wechat_redirect) + +9、[Python 字符串连接,哪种的效率最高?](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485016&idx=1&sn=88497c09c8785b656ae1fee1406827dc&scene=21#wechat_redirect) + +10、[深入理解Python中的上下文管理器](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484950&idx=1&sn=9d78e469f8f190ef0484842b0391bec9&scene=21#wechat_redirect) + +11、[秒杀市面 90% 的 Python 入门教程 (上)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484852&idx=1&sn=2362e034c2740d9f53c3cc99a6908cbd&scene=21#wechat_redirect) + +12、[秒杀市面 90% 的 Python 入门教程 (中)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484856&idx=1&sn=881ee5d8154a85479d71ca4594f90142&scene=21#wechat_redirect) + +13、[秒杀市面 90% 的 Python 入门教程 (下)](https://mp.weixin.qq.com/s?__biz=MzU4OTUwMDE1Mw==&mid=2247485231&idx=1&sn=fa7146937f51110eb7356154bc2e2282&scene=21#wechat_redirect) + +14、[检验你 Python 基本功的 17 个骚操作](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484863&idx=2&sn=ff11a17ad82938b3a4f83ee5fbc2e497&scene=21#wechat_redirect) + +25、[和import说再见,这个库教你怎么偷懒](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485325&idx=2&sn=90c6dfbdbb36f63db72d1c0af67c1115&scene=21#wechat_redirect) + +16、[如何修改 CentOS 6.x 上默认Python 版本](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484881&idx=1&sn=ecb99878d3e2fca2bedc808b1e7aae9c&scene=21#wechat_redirect) + +17、[写 Python 时你要避免的十个错误](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484885&idx=1&sn=6acba3bf872fe1309308d9ef6cde53ce&scene=21#wechat_redirect) + +18、[看完这篇,你也是字符编码大神!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488475&idx=2&sn=17ca56435158c6c19134e30bda6e2b2d&chksm=e8867339dff1fa2f99cb0d85d99a2befa3689951778fbef8f2e0bad1042ae0c4813b99860c33&scene=27#wechat_redirect) + +19、[大白话解释什么是 Python Launcher?](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485268&idx=1&sn=9cea766f1e1a1f6278fca4665fc33a87&scene=21#wechat_redirect) + +20、[13条Python2.x和3.x的区别,你知道几条?](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485044&idx=1&sn=f38e2036317893be8388900dde3077e8&scene=21#wechat_redirect) + +21、[Python基础|新式类和经典类的区别?](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485033&idx=1&sn=8b6357d5a66f9a06347bf0922ae11946&scene=21#wechat_redirect) + +22、[Python 中有 3 个不可思议的返回功能](https://mp.weixin.qq.com/s/dSky88bOCPgYDprzJhnlbg) + +23、[太干了!一张图整理了 Python 所有内置异常](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247490040&idx=2&sn=59578093d82362c023ce305b2fc55103&chksm=e886791adff1f00c0a76154c7c7101d39b151891cc07b33dfe2523c95d9e38250c3684f674bb&scene=27#wechat_redirect) + +24、[有了这篇文章, Python 中的编码不再是噩梦](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486174&idx=1&sn=ceb21deb2ff3ce750117c23f414416e3&chksm=e8866a3cdff1e32a1fcf07880803a7a3c350cc40d612bbd4f34b84cb06bf39250932f1ba5f05&scene=27#wechat_redirect) + +25、[ 别笑!Python 新手这五大坑你躲不过](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485573&idx=1&sn=362e7c5e73c27942e8250375257620e2&chksm=e8866867dff1e17140dc043b5dd33eec0e94e1616eab7e4b415bb767883d46d58a7243fb198f#rd) + +26、[Python 3.9 发布,字典的合并操作符终于来了](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485825&idx=1&sn=04075357936423097f692fa19857c3aa&chksm=e8866963dff1e075707b605fb1352f7760fb1b41040bdda4dec6b83370af37e009424d24f65e&token=2013245174&lang=zh_CN#rd) + +27、[Python 3 入门,看这篇就够了(超全整理)](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492484&idx=1&sn=7985df89a647c271a9c99b1a25f87cb4&chksm=e8858366dff20a7062c54d79cfc85945d4ae91e96c0a0dcb8383d24680c6eeb80d68a6f2b718&scene=27#wechat_redirect) + +28、[掌握 Python 中下划线的 5 个潜规则](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492133&idx=2&sn=ba4631b32f8fb4cd018a68b5411771b1&chksm=e88582c7dff20bd1c417c97e6798ba5bcacc90b55161976d7529d12f1850e413ede66110cbe3&scene=27#wechat_redirect) + +29、[还傻傻分不清什么是方法,什么是函数?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491545&idx=2&sn=193bb88089cc7583989db44707aeca90&chksm=e8867f3bdff1f62d159dca793efc1c937b1c7a135b6f25ff9d77d8d1b819c7ddc66b3ba1f8d0&scene=27#wechat_redirect) + +30、[Python 如何像 awk一样分割字符串?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491382&idx=2&sn=6e3824fa540fe7225d0cd1e7180559b6&chksm=e8867fd4dff1f6c2d2c024b6a07f616794c5b89a1b2b08ab05d029e5de1a59ff751bb03a6561&scene=27#wechat_redirect) + +31、[一篇文章带你剖析Python 字节流处理神器struct](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491241&idx=2&sn=889bf712f4115a27f321e791b3862405&chksm=e8867e4bdff1f75dc9e1e2374c3302753c3a6a28b42436e6e2550aa8ac528652b2561ad2ca48&scene=27#wechat_redirect) + +32、[OrderedDict 是如何保证 Key 的插入顺序的?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486136&idx=2&sn=81fd4039611666917ae8801bd73fe921&chksm=e8866a5adff1e34c603500e97c4b7e1cecb7a1fb43e01c6ff5a794d526d54e5a02b35240d2db&scene=27#wechat_redirect) + +33、[字典访问不存在的key 时,如何才能不报错?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247490809&idx=2&sn=a256a0d8b86bae3a7dc65f7a88e4ab39&chksm=e8867c1bdff1f50d1da0e11d2dca288b085064062ecb8f68891b0bd48b8a1fca4f8ca594fc22&scene=27#wechat_redirect) + +34、[如何使用 Python 执行 js 代码?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491161&idx=2&sn=d89bbc4c214563807427703aa584a26d&chksm=e8867ebbdff1f7ad301b58ac567faec95be2d8f5be921b23ea5d3722d377c2926f32ff7b68ac&scene=27#wechat_redirect) + +35、[Python 代码覆盖率工具 - Coverage](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489752&idx=2&sn=b115d9377feb0129985295e5a3c8ec5e&chksm=e886783adff1f12c7bb14c55560f06f6a5327d6beee9bba38b9965784baf197918ae3898e95d&scene=27#wechat_redirect) + +36、[超赞!100 道让你练习 Python 基础的题目](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488558&idx=1&sn=58a53b85a7e49989794d8d0e9885f335&chksm=e88674ccdff1fdda61609dc4aa811dc6a52a819fe56da3bd0480f9f21ae248c94d8f8f3f8798&scene=27#wechat_redirect) + +37、[一道 3 行代码的 Python面试题,我懵逼了一天](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486901&idx=1&sn=73fe3a92ac2639706d9573a0eaffd48f&chksm=e8866d57dff1e441d6ffad3c4f00b053db39df1cec4e6cf69992641b359cc96448f7f3068918&scene=27#wechat_redirect) + +38、[学习 Python 的指南大纲,从基础到核心知识全都有](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486246&idx=1&sn=58665e2be95f71415ac3e2c1c5f4f690&chksm=e8866bc4dff1e2d212a4d93c0c83cd39cd534f64a8e113b208f96a6156e75ef652ee1ac32270&scene=27#wechat_redirect) + +39、[Python 中常见的配置文件写法](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496552&idx=2&sn=cc57aee69875c855fcc7e7d4098dda44&chksm=e885938adff21a9cb0cd1ee105af9001ca2a597ae37fba35c76de13eb2a69033133a866950d6&scene=27#wechat_redirect) + +40、[Python 的 \__name__ 变量,到底是个什么东西?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496153&idx=3&sn=44fbf9d2c5bf1c629dab6abc1f429a1b&chksm=e885913bdff2182d69117d5f85ede8eed726f1bf00192cb270dc4dfd6e20a1e51638c6520bee&scene=27#wechat_redirect) + +### 1.2 基础库 + +1、[Python时间模块,超实用总结!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493317&idx=2&sn=b821b2765cfcdf7da8858b962f092980&chksm=e8858627dff20f31b14090d0ff178002ea0544196d8d63e595f5f6787f8e95d60df292f80bb4&scene=27#wechat_redirect) + +2、[用 Python 玩转正则表达式,这篇讲得太好了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493207&idx=2&sn=ca2c44f056ce22d132089d200951ee6d&chksm=e88586b5dff20fa3db38273731c3521a278c09ff81570d01512f203d280d253ae1f3d5fc1799&scene=27#wechat_redirect) + +3、[打基础一定要吃透这12类 Python 内置函数](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486198&idx=1&sn=efea0e57956188eeafb163d7bb2448c4&chksm=e8866a14dff1e3022f361245b182a30fbbf40550f3e8dc4456e1acf260aa73d35a20c010559d&scene=27#wechat_redirect) + +4、[8个超好用的Python内置函数,提升效率必备!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485943&idx=2&sn=ecb57c8dbf0e4965d4842cc6f614da64&chksm=e8866915dff1e0035ded3974097c1f0e00561962eeb0498c633fdf664cd429749aa6e6eca806&scene=27#wechat_redirect) + +5、[用 Python 操作 Redis,看这一篇就够了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492907&idx=2&sn=f44d9ef0e624b150c080dd075974e540&chksm=e88585c9dff20cdf6ed8b913312602838fbdffcade584412e43326d11f0a1cc41bd4ffbce94c&scene=27#wechat_redirect) + +6、[超全!我把 Python 的 200个标准库整理出来了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492755&idx=1&sn=c0f99bb14839677d228d029a564d457c&chksm=e8858471dff20d67bc162863a6193998f39aae3e1103a5b3015ceb79f4cea1dde4fda5d2cff3&scene=27#wechat_redirect) + +7、[一篇文章掌握 Python 内置 zip() 的全部内容](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491227&idx=2&sn=61efa9b45c112a25be348a94a9ac8151&chksm=e8867e79dff1f76fcc3858afdfd4e68aef0a5d0430f0420aacd2045aac86d3c31ff88bac464d&scene=27#wechat_redirect) + +8、[通过“四不要”,掌握 Python 的 Lambda 函数](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493501&idx=2&sn=696cb2ef4c3fcc6713f148d42f6eb0be&chksm=e885879fdff20e897b71e791caa6a6dbfb783c22a3ea7bf9c4cfb8406b668e57914c1c209707#rd) + +9、[原来 collections 这么好用!!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493894&idx=2&sn=3f16362bfa3ec2ecf9f7318cc50e2f95&chksm=e88589e4dff200f25c4c03294f59716431c57a65161f6c364d610950650b24a7cb4b037345e4#rd) + +10、[使用 Python 打印漂亮的表格,这两项基本功你可会?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494135&idx=2&sn=f055f78da070dc71c2593540f3272988&chksm=e8858915dff20003c05bc328b09a8cdb8dda3e37118201fb2eb317c1296e788aa1f50c8edf45&scene=27#wechat_redirect) + +11、[73个f-string的例子,帮你吃透字符串格式化](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497032&idx=2&sn=dc4761acf90fa7ff71833f0e7f952189&chksm=e88595aadff21cbca930dfa432106b6645b01ae1485d09f1d860a5779311b1d9c1bf23123146&scene=27#wechat_redirect) + +12、[一学就会的 Python 时间转化总结(超全)](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496446&idx=1&sn=98c71ceefb10fb049ec33c3c1aa2bc6c&chksm=e885921cdff21b0adf359a9b75e5a44033a6cfa86a05cb6ed9e19f07c6b73b6cf97c4e3cd3c1&scene=27#wechat_redirect) + +13、[适合新手的 SQLAlchemy 上手教程](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247498470&idx=2&sn=d0ee4a5367ad5195bcb8377ea6fc6101&chksm=e8859a04dff21312e8172de1e1986d41b4cf60d653d923954f48e111258a0e6019fc1bb50c1a&scene=27#wechat_redirect) + +14、[不服不行,Python 操作 JSON 的门道也这么多~](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247498220&idx=1&sn=249796b68dadafc9f85600fb03f8b0ae&chksm=e885990edff21018ad853a24abcd4a7c6780cc1740daddcd622bb233cdaa6d4834468284ac96&scene=27#wechat_redirect) + +15、[没想到吧?这货比 open 更适合读取文件](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247498035&idx=1&sn=66e076de5448b41f252127b1f12a6d7e&chksm=e88599d1dff210c7f6f470b7917cf6b099febc93af25740562b2e2e0ec1ea42968128d26186b&scene=27#wechat_redirect) + +16、[Python输出简洁美观的文本化表格](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497768&idx=2&sn=2c49bcdf0264481f75658db0c0dbc54c&chksm=e88598cadff211dc7f140bc8c0d59d88169fde365567c82bcd8f7a8dccb4081072da83d88df0&scene=27#wechat_redirect) + +17、[使用 Python 操作 MySQL,这篇文章别错过~](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497264&idx=2&sn=b11ff1be91e3297575d9eb9de3465257&chksm=e88596d2dff21fc4e404e0df21d096426df4eae33d6143bd851244cbf00adc3dc9072e9ac1a6&scene=27#wechat_redirect) + +18、[一篇文章教你如何用 Python 记录日志](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497049&idx=2&sn=0bb3de6705dd1dcef5352c2ff37991d5&chksm=e88595bbdff21cad17c69ee31955572ff64fed9ea38a8ef0a63472e89c97bc027d89101b8b57&scene=27#wechat_redirect) + +### 1.3 代码案例 + +1、[15个Pythonic的代码示例](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485036&idx=1&sn=24de1996a63bf25b0c0deec782f688cf&scene=21#wechat_redirect) + +2、[常见 Python 简洁代码的样例](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484823&idx=2&sn=4459a7edc4a4989068b22b31c76f2c92&scene=21#wechat_redirect) + +3、[每天花 30 秒,就可以练习的 Python 小技巧!](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484861&idx=1&sn=e5fa97570b3c180e5a5edc753fc62669&scene=21#wechat_redirect) + +4、[精心整理!9个 Python 实用案例分享](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492921&idx=2&sn=800c245cf392dfed915c618c68a5fe80&chksm=e88585dbdff20ccdd85dc21989092ab3e028dd2e3bcfb8f349bc3a7df99b299b6f8a43b57371&scene=27#wechat_redirect) + +5、[瞧瞧,这样的代码才叫 Pythonic](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493439&idx=1&sn=2ed198c261ee285f2e3c1cbdf5c78541&chksm=e88587dddff20ecb24804e6b191b690d7950584104b5ed94b2f1e6a043a24909dfe418e64df6#rd) + +6、[瞧瞧,这样的『函数』才叫 Pythonic](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493550&idx=1&sn=cd5cf944c3e3ac3f2b567def827de2d4&chksm=e885874cdff20e5aeb438aab72e2f87329a403024bb0cae3308e61d5f9cc9a15609da6d8b7dd#rd) + +7、[这样的奇技淫巧不可取,切记切记](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493635&idx=2&sn=cc61ae5798c278c52a07e3e7129a5bb1&chksm=e88588e1dff201f7c4997d9fe8004d86973833bbe91ded31fbf93cdf00d1ec22f19f8cff825c&token=58703854&lang=zh_CN#rd) + +8、[别这样直接运行Python命令,否则电脑等于“裸奔”](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494114&idx=1&sn=202d3492ae48d73431173b76caa64345&chksm=e8858900dff2001626f47454f8dee79679f43b74701c7730e1c499f4c895edafca5aa68e280f&scene=27#wechat_redirect) + +9、[6 个例子教你重构 Python 代码](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494309&idx=2&sn=e1cffffa71b5cc76434b6771cfcc0bae&chksm=e8858a47dff20351575b1cd29e35a51b30c7859c9dffbf816df883bc7ccee9ea15aa5eaad812&scene=27#wechat_redirect) + +10、[25 条很棒的 Python 一行代码](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496971&idx=2&sn=9196437b9976a382b277c7780f8aa04b&chksm=e88595e9dff21cffc32c8da9d2a5d59ab40d7e1d1d32f9193687c35cba490919c624d04d7ef6&scene=27#wechat_redirect) + +11、[Python 中的 EAFP 和 LBYL 代码风格到底是什么?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496204&idx=2&sn=5aa0cca75c6b59bd5f1b6f9cd1bfe07e&chksm=e88592eedff21bf857a0d53a1c3515e5e4ad32c5ae728218b6dedf63fcd02a9750a9f66387d4&scene=27#wechat_redirect) + +12、[3000 字教你学会最地道的 Python 编程风格](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494858&idx=1&sn=9386de992ce9f9b08d2d6d2721584a39&chksm=e8858c28dff2053ec9ca59d1d4244c119ca4363b6914e87b3ef250a54bb8a82c611ab437763e&scene=27#wechat_redirect) + +13、[再来 6 个例子教你重构 Python 代码](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494838&idx=2&sn=eeaf56eeaf9cc72f1340233bcd88b5a7&chksm=e8858c54dff20542f4712be4bd185f2e27e78e09bb77acb97e2be2d4c1329553be4abe25a3e2&scene=27#wechat_redirect) + +14、[如何在Python里面实现链式调用?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247498592&idx=2&sn=19b2f757b9887a67b0d2cfb8b0cb924e&chksm=e8859b82dff21294793e2b9a4eac9c375509796044d964aeb24c0448f9ec16b4cf3cad0102a9&scene=27#wechat_redirect) + +15、[Python 怎么捕获警告?(注意:不是捕获异常)](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247498517&idx=1&sn=2540f928893ffecc88a7aa86c330de91&chksm=e8859bf7dff212e1d8425ccff1c2dd043b5d611b291c4a5db729d7416189571d99e2c8d4fdee&scene=27#wechat_redirect) + +16、[a is b 为 True,a == b 一定为 True 吗?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497362&idx=1&sn=993ad8a3f86d467db967ea13d52175cc&chksm=e8859670dff21f66c76d2c4e0c61db9adda56824eba878be40e8b4ed8409c6922c8526f818fc&scene=27#wechat_redirect) + +## 02. 进阶系列 + +### 2.1 进阶必学 + +1、[描述符:其实你不懂我(一)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484934&idx=1&sn=ef8b30ffe2467e5736036bd083b340ca&scene=21#wechat_redirect) + +2、[描述符:我无处不在!(二)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484927&idx=1&sn=8a3d673ee20bd418d93a249380ca8e76&scene=21#wechat_redirect) + +3、[Python静态方法其实暗藏玄机](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484911&idx=1&sn=a16846030c3589c912aec9efdf4f7f80&scene=21#wechat_redirect) + +4、[全面深入理解 Python 面向对象](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485208&idx=1&sn=61bf8d3ec81fa85b0bc9de6e5f5d6611&scene=21#wechat_redirect) + +5、[几个使用装饰器的小技巧](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484930&idx=1&sn=ed731e32b6e95e7d83d74a544f97142a&scene=21#wechat_redirect) + +6、[围观大神是如何用 Python 处理文件的?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497532&idx=1&sn=bed756631d9c94c2eb2d57e0b29f6ab6&chksm=e88597dedff21ec899e90126cbe219be5fc738229bf69a02c490435c4ed57cbe32636198bb44&scene=27#wechat_redirect) + +7、[Python进阶开发|元类编程](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485080&idx=1&sn=45e6d9995e4469d8b7bce2f800ac0f9b&scene=21#wechat_redirect) + +8、[Python进阶开发之网络编程](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485078&idx=1&sn=e0a3855d959c178b8c01bd196a048dce&scene=21#wechat_redirect) + +9、[Python 进阶:深入 GIL (上篇)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484875&idx=2&sn=8780a349c60522ad1b7aa20a3fe7a19c&scene=21#wechat_redirect) + +10、[没掌握好这24条,别说Python慢。](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484910&idx=1&sn=df8fb32a840a28954614b09bce730b72&scene=21#wechat_redirect) + +11、[花了两个星期,我终于把WSGI整明白了](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484919&idx=1&sn=bd7d2bc0ab8a41110d5d93e44ad20b1f&scene=21#wechat_redirect) + +12、[源码解读|Flask 上下文核心机制](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484943&idx=1&sn=ca846404d30a2ec775ab7db5df73aa8e&scene=21#wechat_redirect) + +13、[说说几个 Python 内存分配时的小秘密](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484853&idx=2&sn=edf7c3225d119291fae5d05820f55aac&scene=21#wechat_redirect) + +14、[写了三年代码,还是不懂 Python 世界的规则](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484886&idx=1&sn=f46917f6e23f8961c912606a281a354d&scene=21#wechat_redirect) + +15、[如何保护你写的 Python 代码?](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484858&idx=1&sn=e18a1c89f14d4e4043833e3ff5cc8d32&scene=21#wechat_redirect) + +16、[27 个问题,告诉你 Python 为什么如此设计?](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484862&idx=1&sn=89500433bc174dfc0530eebea2fb91d1&scene=21#wechat_redirect) + +17、[精心整理 30 个Python代码实现的常用功能](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485147&idx=2&sn=c5b871e1cebde6b311609f6de703f2e3&scene=21#wechat_redirect) + +18、[高手之路:从零开始打造一个Web服务器](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484891&idx=1&sn=ed12d175452c2efedeefb1635063177c&scene=21#wechat_redirect) + +19、[从0到1:全面理解 RPC 远程调用](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484915&idx=1&sn=427b9dda155e4201c2f939c3919def91&scene=21#wechat_redirect) + +20、[一篇 Python 函数式编程指南](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484834&idx=1&sn=559bac4ff85f7082bc989a6fde04d3f3&scene=21#wechat_redirect) + +21、[没看完这11 条,别说你精通 Python 装饰器](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484900&idx=1&sn=3997a2a377577e3d16a9b7f8e6a5ea53&scene=21#wechat_redirect) + +22、[程序卡住了?教你如何调试已在运行的程序](https://mp.weixin.qq.com/s/QC-Pc-0iifaVKOfsiNTYmA) + +23、[字符串在Python内部是如何省内存的](https://mp.weixin.qq.com/s/jp_I82fnr0-3cd6ioZcoGQ) + +24、[巧用 traceback 定位 Python 内存泄漏](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485751&idx=1&sn=8a054a575767c103c830a6b3ef5f73c8&chksm=e88669d5dff1e0c3ae1c7c32f35a8f46a3a2e0a637fb4b947566f417dd8f4419bec636c8a667#rd) + +25、[非常全的通俗易懂 Python 魔法方法指南(上)](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485551&idx=1&sn=4c0983f22269a113bcdf83690e5e2b20&chksm=e886688ddff1e19b9ad230128a67ee1a9ee1eced0720c14b5d48f68943be10b1b85b23d8ca2d#rd) + +26、[非常全的通俗易懂 Python 魔法方法指南(下)](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485555&idx=1&sn=0a218b796e651b451a17112e22790d07&chksm=e8866891dff1e18771a9392da7f509732244ebc4d1a6e2427acd39ee8b59b146e3d4961a2a62#rd) + +27、[教你如何阅读 Python 开源项目代码](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485451&idx=1&sn=e15856352c18297770c67d9df66ec3b0&chksm=e88668e9dff1e1ff0f6a39f3885f4126232213149ac09daa1fc0ec9e0de2095bd11fb727d63a#rd) + +28、[这个 Python 知识点,90% 的人都得挂~](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247490984&idx=1&sn=135b7b187d8d41b3c10179dbaedaf77e&chksm=e8867d4adff1f45cd90fe2609fe7d1840b07fab8cf19cb7406ebd038c31df0028e611077d80e&scene=27#wechat_redirect) + +29、[一篇长文学懂 PyTorch](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489158&idx=1&sn=2e2e88565131d11271aea61b0bedf182&chksm=e8867664dff1ff728ee30e1baab0d7df0139fc67e2514ffcaebda6d50e5d08bd2866ad7dee35&scene=27#wechat_redirect) + +30、[学了这么久,你知道Python是如何运作的吗?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488458&idx=1&sn=23040c906e83462c4f64039cba6e3dfb&chksm=e8867328dff1fa3e149248e53762444b1abc72df395a597639357b5525d16b1b6db242339d20&scene=27#wechat_redirect) + +31、[求你了,别再使用 pprint 打印字典了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486288&idx=1&sn=7647e1ee63c49c14472baec19fb79b87&chksm=e8866bb2dff1e2a4d5b85ae9db1e8f4d8dda839643fb02b9e0b7f7fe6143cb627773e56d44bf&scene=27#wechat_redirect) + +32、[Python实现RabbitMQ中6种消息模型](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486017&idx=1&sn=9b95896abee7a345e3abee1ac4f2edab&chksm=e8866aa3dff1e3b547ef5062c30516b2d54a051fd4a07d85078223ea673af1400be1a6c56ad5&scene=27#wechat_redirect) + +33、[想写好面向对象的代码,这几篇一定要看(下)](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485938&idx=1&sn=a725785ef8000868b7cb85606ee754d3&chksm=e8866910dff1e006f195d6ea0d66f4b4f1fe5a9b97debc18ae4b04a239a347d342fbc67b44e4&scene=27#wechat_redirect) + +34、[想写好面向对象的代码,这几篇一定要看(中)](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485926&idx=1&sn=ce148af333d9f377d8a6fb9577bbf57c&chksm=e8866904dff1e012ec1bb8f418c43cca7954979bd1481707761b29d1e632ace6369efd50210b&scene=27#wechat_redirect) + +35、[想写好面向对象的代码,这几篇一定要看(上)](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485913&idx=1&sn=74b34bd95d513a94201ad05604c4a05f&chksm=e886693bdff1e02dd2079cb90458aac914e5cb832aec59677da8b2f85200baaa57e804a4b58e&scene=27#wechat_redirect) + +36、[教你 10 分钟构建一套 RESTful API 服务](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488534&idx=2&sn=d593dbf907217ff4dea1daf636062778&chksm=e88674f4dff1fde26b1a1074a0a0c78be0630a34b4aed705755946bd8cfcde1a23e0df916392&scene=27#wechat_redirect) + +37、[要搞懂元类(metaclasses),这篇文章一定要看](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493280&idx=2&sn=d1a0aa45b9ecd03bd940328bc031458c&chksm=e8858642dff20f54ecbe8d03aebe2dacdc1fe0fdb1daa3855e09f565f05b711c9aa4eabd9ddb&scene=27#wechat_redirect) + +38、[弄懂这 6 个问题,拿下 Python 生成器!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493273&idx=2&sn=89bd3d18e7837f59c41d2f021047a1f9&chksm=e885867bdff20f6d0d72d463a255d2a51225321f8bc6115523411e540305e669a24580e58d78&scene=27#wechat_redirect) + +39、[`[]` 与 list() 哪个快?为什么快?快多少呢?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493457&idx=2&sn=67d576d2aeab16d4ad9c1b491e10deaf&chksm=e88587b3dff20ea501789da4c67560e21708f89032732eaca544e22c65780ea249e98e6ab50e#rd) + +40、[连 Python 生成器的原理都解释不了,还敢说 Python 用了 5 年?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493530&idx=1&sn=5096c680a63a57b1f55d1a9d372ec302&chksm=e8858778dff20e6e257fcacfb644bc4736afac692ab19f41717f4cdc084eb43951aba0912187#rd) + +41、[Python 列表去重的4种方式及性能对比](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493746&idx=2&sn=218b1a28af72347363557bdaac32d016&chksm=e8858890dff20186a8fefe81e11a1aa64e787a75b3930ecb6e4421e132a8322dbc5fe3b81b30#rd) + +42、[第一次把 Python 的切片理解得如此透彻](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493987&idx=2&sn=ca90bbc53a31c0ccc84fea4869fd1b81&chksm=e8858981dff20097a5167ef9d60fe4c54479b6f50b85188ffc43490c03b8cb2bec8464975793#rd) + +43、[为什么继承 Python 内置类型会出问题?!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494268&idx=2&sn=67ea6f78e7add1d43174f601626d1cb5&chksm=e8858a9edff20388c08f6e3f9c8ce9db6969174fc3674bf04d65cf0fbcda48c08217de5d622b&scene=27#wechat_redirect) + +44、[Python最会变魔术的魔术方法,竟能"大变活人"](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496126&idx=2&sn=083eafff3facad62a0660061990c7387&chksm=e885915cdff2184aa79584c1e46d3b40bc928eeb732a856e9ff26e7864a3fb1fb81749d73364&scene=27#wechat_redirect) + +45、[说说 Python 的内置电池,你学过吗?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247495322&idx=2&sn=7271490d820c6a48b9ee7d090c1c88bd&chksm=e8858e78dff2076e4b5651811652d2da47d2a1db07eda9362120b51f83da7b65aca58d1ad3a6&scene=27#wechat_redirect) + +46、[恶补了 Python 装饰器的六种写法,你随便问~](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494951&idx=1&sn=43b65fade87940be918ff1ff066b9ca8&chksm=e8858dc5dff204d3571414164e63a1de715499418805477d012104fa12e6a2577ef5fa58e6a8&scene=27#wechat_redirect) + +47、[Python 从业十年的程序员,写的万字经验分享](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494942&idx=1&sn=84efbced575838b9b8e169e8c59383b7&chksm=e8858dfcdff204eaf7d251ddf1ea69655bd5eb69da596a4970c845f912c2ac9e3f2f18e5e7b5&scene=27#wechat_redirect) + +48、[Python 优化机制 "常量折叠" 是究竟是怎么回事?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497951&idx=2&sn=e54c8412c056e98a34a4ce622915221d&chksm=e885983ddff2112b359c3e2a3856357a3fcccc24e5825fa0a6b972d0f5c64662df363c8d705e&scene=27#wechat_redirect) + + +### 2.2 包的管理 + +1、[最全的 pip 使用指南,50% 你可能没用过](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484827&idx=1&sn=df0923856c820e10baca20c9873b336b&scene=21#wechat_redirect) + +2、[花了两天,终于把 Python 的 setup.py 给整明白了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497217&idx=1&sn=acce69f1f39f2688056fd72a9d7044bf&chksm=e88596e3dff21ff5bf1c0e6f8a26e218458aa079d987810811f2d1ebd3704cdb1f35881229c8&scene=27#wechat_redirect) + +3、[深入探讨 Python 的import机制:实现远程导入模块](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484838&idx=1&sn=1e6fbf5d7546902c6965c60383f7b639&scene=21#wechat_redirect) + +4、[盘点 Python 依赖库管理的工具:pip、pipreqs、pigar、pip-tools、pipdeptree](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485120&idx=1&sn=170ef1173eabc5bed28c724e19d6c0ac&scene=21#wechat_redirect) + +5、[如何使用 pyenv 运行Python的多个版本?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486239&idx=2&sn=863e80589f5eb9b2daa9701f6b494997&chksm=e8866bfddff1e2ebc244354238aedfa9291aa27ad8f7e466213236369dae9800b29b5766c0cf&scene=27#wechat_redirect) + +6、[如何管理 Python 的虚拟环境?超全讲解virtualenv的使用](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485049&idx=1&sn=c16383d6cc91a7ed8254e344d994f101&scene=21#wechat_redirect) + +7、[一款让Python开发效率提升50%的工具包](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489006&idx=1&sn=eead45b3c34777085465f9854a433e36&chksm=e886750cdff1fc1ae2791adba1231e045630417f9b4185217817183aa1f260815acabcd39363&scene=27#wechat_redirect) + +8、[记 Python “用户环境”的一次完美应用](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486191&idx=1&sn=e556df305ce1df4c4969d2fdbe884cfa&chksm=e8866a0ddff1e31b2ca8ca8fbbe0355fb8c24376d715224ef2176e613b5601764be0193e3aa4&scene=27#wechat_redirect) + +9、[学了半天,import 到底在干啥?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493413&idx=2&sn=770c9bb7104dfb8c53c544f546cf7aa4&chksm=e88587c7dff20ed143cb93b4cd1b0f64af8b9c849fd9d531e58a9ba27a449d4a28cd96091b40&scene=27#wechat_redirect) + +10、[非常干货:Python 探针实现原理](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493427&idx=1&sn=d9e0c646a98cf2b54b5724ebc3262255&chksm=e88587d1dff20ec71ed33c5165bbdec377eea89307da0f924784cff0f4c01c05a5f3247de50e&token=58703854&lang=zh_CN#rd) + +11、[如何编码检查依赖关系是否有循环依赖](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496866&idx=2&sn=a25b46ef4aa67a007612ef53bc832811&chksm=e8859440dff21d5647027fdcdad642c3f9781f140f7ecb47f975678eb74b8321d4b65ec076cc&scene=27#wechat_redirect) + +12、[关于包导入,这三个知识点太多人不知道了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496204&idx=1&sn=cf788dfc35b7377ed70369aafba19c47&chksm=e88592eedff21bf872d8b6c5ded642ea5e2f2f55dcd31331da9bcd13f265cde7fee2f65ca8f5&scene=27#wechat_redirect) + +13、[手把手教你发布 Python 项目开源包](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494964&idx=2&sn=cac94af61d53857c2fa7362f2b4f8564&chksm=e8858dd6dff204c02b5235eb0a705e9193d3c5107369a87d35753bcb2e7f80020ceaccfbb9e9&scene=27#wechat_redirect) + +14、[有人在代码里下毒!慎用 pip install 命令](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494847&idx=1&sn=822e027acb42d6ab882687fc515f14ae&chksm=e8858c5ddff2054b80c6eda85f27331472ad78bcc11ca980cf03cae0824255666b0518afb2cc&scene=27#wechat_redirect) + +15、[简化 Python 函数调用的 3 种技巧](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494847&idx=2&sn=bec329103690975870e79fc00abdeba7&chksm=e8858c5ddff2054bdbddfb145caf763aab5130c3939d39a737cb3bd42934f7a74b8d3fb0e06d&scene=27#wechat_redirect) + +16、[如何 Import 自定义的 Python 模块?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494821&idx=2&sn=646396ea0a67ab3eed7b0f0652e647dd&chksm=e8858c47dff2055109d74b13de70efe7a5083fd1a99a1323043e932694a572291d00359bec15&scene=27#wechat_redirect) + +17、[解锁装包新姿势,这个场景下 pip 真的难用~](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494820&idx=1&sn=24ceaa11376cbfa5a4d48adc076603db&chksm=e8858c46dff20550d0124ef1bf1e481e14ffcf485e8c49aa77f6f9541f6163850538e4af05f9&scene=27#wechat_redirect) + +18、[Python 的 import 居然这么有料](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497490&idx=1&sn=8667466d2dcaee300e990b0d4462e485&chksm=e88597f0dff21ee6787df0506a0c4b354df6b960c2c8dbf349ead6e43557230ae81fa0c661d7&scene=27#wechat_redirect) + +### 2.3 性能优化 + +1、[Python高效代码实践:性能、内存和可用性](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485161&idx=1&sn=07625f06db330897bc8bfee880ceac18&scene=21#wechat_redirect) + +2、[Python 代码的性能优化之道](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485004&idx=1&sn=8dc07a40bcac30c93874398b17a52831&scene=21#wechat_redirect) + +3、[7 个习惯帮你提升Python运行性能](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484957&idx=1&sn=9b3c644e6b1777b77ce7f84047c6d500&scene=21#wechat_redirect) + +4、[如何提升你的 Python 代码健壮性(上)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484871&idx=1&sn=985b79143d0cafd21e5263ee79afa777&scene=21#wechat_redirect) + +5、[如何提升你的 Python 代码健壮性(下)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484867&idx=1&sn=b8eab8416229dc74f1ac96e099a3df71&scene=21#wechat_redirect) + +6、[将 Python 运行速度提升 30 倍的神技巧](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484877&idx=1&sn=f6067875f1e807d19291e383f8421a3b&scene=21#wechat_redirect) + +7、[实战讲解:Python 性能分析与优化实践](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485404&idx=1&sn=486fcf898d6dd21b0feb990de3c1e08f&chksm=e886673edff1ee28b8c6e1d520b2732b2f66f4c4691ef2696b54743b1ad0769356e12a1e98b2#rd) + +8、[如何调试Python 程序的内存泄露问题](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488577&idx=2&sn=16aff9687a4a16faa492118cd5c1bfae&chksm=e88674a3dff1fdb5b80a4547cb863fcf4255f90ab2024ae8c3bbf1f270efb13333b2f7426baf&scene=27#wechat_redirect) + +9、[牛逼!一行代码让 pandas 的 apply 速度飙到极致!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493908&idx=2&sn=0413803e1a73bf632c2d5ba24c6e7ce4&chksm=e88589f6dff200e020a32578706e7c4791be700ce9f16f810d5b19dcc6a99bce2d5c7ba96b6d#rd) + +10、[3 倍性能提升!升级 Flask 到 Quart](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494567&idx=1&sn=d91202b10ab957a58c5eb70fa159fe67&chksm=e8858b45dff2025387626bac42e8441e8d0c8c290070f5fc1a885776fb6a3a06ce3467b1b8d2&scene=27#wechat_redirect) + +11、[超干分享!如何提高Python的运行速度?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494621&idx=2&sn=00c8aa00a85f8710fada38d35b2c8388&chksm=e8858b3fdff2022991a0024757c64faaed81da830cbbf1fa62b6b218d7271b0837b11922c1f0&scene=27#wechat_redirect) + +12、[程序运行慢?你怕是写的假 Python](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247495235&idx=1&sn=816c6de9e1d23d65fe8c1db458426f68&chksm=e8858ea1dff207b749b64461bb06bf8818883644a4450b6400efda4d7e54d4832162448e9f68&scene=27#wechat_redirect) + +13、[超干分享!如何提高Python的运行速度?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494621&idx=2&sn=00c8aa00a85f8710fada38d35b2c8388&chksm=e8858b3fdff2022991a0024757c64faaed81da830cbbf1fa62b6b218d7271b0837b11922c1f0&scene=27#wechat_redirect) + +14、[快亦有道!让 Python 变快的 5个方案](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497409&idx=2&sn=12667ea2e03ecb9db03478b17778ffea&chksm=e8859623dff21f358e56375becfa2ea8873235c2f25a216c36ffbd7a76ce2f13c7cbc269d58d&scene=27#wechat_redirect) + +### 2.4 并发编程 + +1、[并发编程01|从性能角度来初探并发编程](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485074&idx=1&sn=a859c6ab1d9b95c30c9f8b06f9489887&scene=21#wechat_redirect) + +2、[并发编程02|创建多线程的几种方法](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485073&idx=1&sn=854ff524645247e5020d977e57d9c0e6&scene=21#wechat_redirect) + +3、[并发编程03|谈谈线程中的“锁机制”](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485069&idx=1&sn=52370a27d4a5c4541969921ada890e0b&scene=21#wechat_redirect) + +4、[并发编程04|消息通信机制/任务协调](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485068&idx=1&sn=fc0798e84e7845cd9efee1809f932f15&scene=21#wechat_redirect) + +5、[并发编程05|线程中的信息隔离](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485066&idx=1&sn=0bb9d6c82a6d062e50d09e1eefd09427&scene=21#wechat_redirect) + +6、[并发编程06|如何创建线程池](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485065&idx=1&sn=60891b67b139806cf6bf4c05f5861f02&scene=21#wechat_redirect) + +7、[并发编程07|从生成器使用入门协程](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485064&idx=1&sn=8584bb778152a12ca335970bed9fdbdc&scene=21#wechat_redirect) + +8、[并发编程08|深入理解yield from语法](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485063&idx=1&sn=0ff7a99058320ff90a6237e7e03367fb&scene=21#wechat_redirect) + +9、[并发编程09|初识异步IO框架:asyncio](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485061&idx=1&sn=9e846df1a5cb57e0bc6254dcc953e243&scene=21#wechat_redirect) + +10、[并发编程12|学习异步IO框架:asyncio](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485058&idx=1&sn=92ef1f79ce6488670ae13e5d6a1c7908&scene=21#wechat_redirect) + +11、[并发编程11|实战异步IO框架:asyncio](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485057&idx=1&sn=8bacf0f2b42de5962fbdf32796903f27&scene=21#wechat_redirect) + +12、[百万「并发」之Python异步编程(上篇)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484896&idx=2&sn=5d8458ede3440ae501d19c5ffd5f8a99&scene=21#wechat_redirect) + +13、[百万「并发」之Python异步编程(中篇)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484889&idx=2&sn=25d11042e5b2ab17dff40535d354b8f8&scene=21#wechat_redirect) + +14、[百万「并发」之Python异步编程(下篇)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484885&idx=2&sn=b9e62a9b024358aec629e876b76e0eb5&scene=21#wechat_redirect) + +15、[如何一行 Python 代码实现并行?](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484826&idx=1&sn=6c5b575b7b134642077cfde2bb8b613f&scene=21#wechat_redirect) + +16、[asyncio:从原理、源码到实现](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485245&idx=1&sn=a08826c3d28037479190fd652438bcca&scene=21#wechat_redirect) + +17、[为什么说线程是CPU调度的基本单位?](https://mp.weixin.qq.com/s/c3aZ-6UzZVD3_PvVhiDPWA) + +18、[非常适合小白的 Asyncio 教程](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247495734&idx=1&sn=2fb31e6fd306f19ba03b368f5924b7e8&chksm=e88590d4dff219c252b4e1126f196e0a0c395f4f8d22d58cc5c531d9dd2acad6f6e295a1fee8&scene=27#wechat_redirect) + +19、[说说 Python 里关于线程安全的那些事儿](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486279&idx=1&sn=2b6acf717b7f5cc6a2b72c62266dbe01&chksm=e8866ba5dff1e2b318c679413fd7d0ac3a69db7cab1ceda03eca26fb71f6d2837af80e2143d0&scene=27#wechat_redirect) + +20、[异步 Python 比同步 Python 快在哪里?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494549&idx=2&sn=1120b33a12bf8ab25df805cfab9afbc8&chksm=e8858b77dff20261afdf788de30c7e14f3d66ff52215b8c0db66320a118e4544283424340d4e&scene=27#wechat_redirect) + +21、[为什么 Python 多线程无法利用多核?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494567&idx=2&sn=653795446bacff2d445cabd417748756&chksm=e8858b45dff202530afc05a00469b20a0a95f53bcaefc49472240e1c905459ecfb74edbe0461&scene=27#wechat_redirect) + +22、[Flask 之父:我不觉得有异步压力](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496214&idx=2&sn=cd813e57b7e03aff0300f1f65cc583f0&chksm=e88592f4dff21be2738eaf2745cf828841fea934e986f9a4ee7d13eb9fe09701d1c13993435c&scene=27#wechat_redirect) + +23、[Python 协程的本质?原来也不过如此](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247495553&idx=1&sn=d00916691bf2cddc576f1346672ef603&chksm=e8858f63dff20675238e5eee747645d022aa316bd5417004c296157aadb4de6134d6118e66e7&scene=27#wechat_redirect) + +### 2.5 实战练习 + +1、[适合 Python 新手练习的绝佳项目](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485898&idx=2&sn=36a1b1a94dece0a290652da23679cff0&chksm=e8866928dff1e03e58b95b3cd24dbc23e368b6eb2c0599b2efe814924e21ec5c01935b2e0455&token=2013245174&lang=zh_CN#rd) + +2、[4个Python实战项目,让你瞬间读懂Python!](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485852&idx=2&sn=eb3471a260cce835a755a780d6cc690d&chksm=e886697edff1e068bd0f9d456e26ee5ebe482580457951e42807e731d266c95f00c37de22fea&token=2013245174&lang=zh_CN#rd) + +### 2.6 GUI 应用 + +1、[如何在Python中编写精美图形界面?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486179&idx=1&sn=eed86ec2f44a92fadb94f237178b3f8a&chksm=e8866a01dff1e317f450d91b88e91d6912d6a1b2ac7a34ebb86b74a2abc0f912d8ced5a3baac&scene=27#wechat_redirect) + +2、[或许,这是最强大的一款Python GUI工具](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492571&idx=2&sn=6ac2c0c19d86d653acd82d5b4ef86126&chksm=e8858339dff20a2f595159499e8eb8e072b52e61521e4a1322337f174bff942134a25b3b6b9b&scene=27#wechat_redirect) + +### 2.7 自动化 + +1、[付费?是不可能的!20行Python代码实现一款永久免费PDF编辑工具](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492085&idx=1&sn=785968af86bf998ecad9b11583a23ad6&chksm=e8858117dff2080119f596c6447d9a0c7b73c6bced8306883900f2f4d9582929f9d5c26ac45d&scene=27#wechat_redirect) + +2、[带你用 Python 实现自动化群控(入门篇)](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491979&idx=2&sn=7489738d3225a96767173e4b54023f95&chksm=e8858169dff2087fed0f11ad6b880c110e3530eae28ed7702343f6d81163860ed20a2f056294&scene=27#wechat_redirect) + +3、[最全总结:Python 发送邮件的几种方式](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489568&idx=2&sn=bdac42b533784bf3a8ee523da36bacba&chksm=e88678c2dff1f1d499321032e6871f2810608909121bf56aee184c6d7770d3b310f39cad7c43&scene=27#wechat_redirect) + +4、[太全了!使用 Python 转换 PDF,看这一篇总结就够了。](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488934&idx=2&sn=eed1cab8e03c908fdfe311bf4bbd91a6&chksm=e8867544dff1fc52e0d9dd62c61d36ec5a5b6847aeb9992e5423eb4e01f08995461160adbb45#rd) + +5、[Python吊打Excel?屁!那是你不会用!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247487151&idx=2&sn=9c4a697758af01c086cced44b98a3380&chksm=e8866e4ddff1e75bd2f19e036c3e338edee50871364d2f185afa51cb361c83f3bbda8ce2d92f&scene=27#wechat_redirect) + +6、[收藏|Python办公自动化不得不会的十大文件操作](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247495776&idx=2&sn=50e900caa96346371045145170dc9073&chksm=e8859082dff219940436120f8fa9ae329dc655e69335f967e2f926786420d9d97b1b11711100&scene=27#wechat_redirect) + +7、[再见 VBA!神器工具统一 Excel 和 Python](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247495801&idx=1&sn=becae030a09a689e1f231a5c3c1ef7bd&chksm=e885909bdff2198d1d2aafaf0077a2763d796e435817b70b612095ae944489581f3bbffe0a69&scene=27#wechat_redirect) + +8、[微软最强 Python 自动化工具开源了!不用写一行代码!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494621&idx=1&sn=61d9f8b7557cb2ff517fde1a414b219d&chksm=e8858b3fdff2022954d383579b6392362e99e99af4a6309028dfa6ddd7bfc90a02c85d599b50&scene=27#wechat_redirect) + +### 2.8 网络爬虫 + +1、[想逆向我的 js 代码?先过了我的反 debug 再说吧!](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484876&idx=1&sn=ed81400f77deb2af18311f8e42e9b11b&scene=21#wechat_redirect) + +2、[教你实现一个可视化爬虫监控系统](https://mp.weixin.qq.com/s?__biz=MzU4OTUwMDE1Mw==&mid=2247484208&idx=1&sn=d04421526cf0e12089541063b4ec448d&scene=21#wechat_redirect) + +3、[估计是讲得最清楚的「异步爬虫」指南](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484929&idx=1&sn=7055414a33d7cbadaeb5645cbd5203ec&scene=21#wechat_redirect) + +4、[10 个爬虫工程师必备的工具](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484958&idx=1&sn=3422e53de4ae701a922104ad26f8e256&scene=21#wechat_redirect) + +5、[Selenium自动登录淘宝,我无意间发现了登录漏洞!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247490737&idx=2&sn=6a33873b3777afd420f3c56078a88687&chksm=e8867c53dff1f5455fe54e1ee0044cc97638fbc96983f36e19938810bea4e06d5af0ba3036df&scene=27#wechat_redirect) + +6、[干!一篇文章讲了这么多爬虫的技巧](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247490557&idx=2&sn=f5128b1dc827cc4a6035d46714a484b1&chksm=e8867b1fdff1f20993b024fbfaa4445763a5949174913a58d9f17ddcb0286be8b325516cb449&scene=27#wechat_redirect) + +7、[谈谈常见网站加密和混淆技术](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486218&idx=2&sn=6261fa602eb4f73365a9d372376594ed&chksm=e8866be8dff1e2fea5082dd13dc7799a1cbc829f2e41a32891db411152153cb261d01be5807b&scene=27#wechat_redirect) + +8、[初识网络爬虫之夜探老王家](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486179&idx=2&sn=3a1b880c7f1b37d095359b35ff96e9b4&chksm=e8866a01dff1e31711d7fb093a96f54eaf374b46c686b0ea4e49d6f926018ad5b6c27aebfa9d&scene=27#wechat_redirect) + +9、[不懂爬虫也能轻易爬取数据的 6 大工具](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486085&idx=1&sn=51c740e1d848f1624a5a8e582434f661&chksm=e8866a67dff1e371de89a64503591ae0c42b67cd43434fa394125f09a2f65bc23817a266ac13&scene=27#wechat_redirect) + +10、[效率提高十倍,Puppeteer 如何启动交互模式?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496566&idx=2&sn=efc444487afd08ec055ceaee414857d6&chksm=e8859394dff21a824ccc8e2679f985e94c60d6b680f6856aa7a7a9ed608c9dc1ad552f0f2b40&scene=27#wechat_redirect) + +11、[别去送死了,你这样写爬虫,早晚得进去~](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247495216&idx=2&sn=648a296205fb3310287d95907d5126ef&chksm=e8858ed2dff207c4c42eb8b224bfe4f68186108642afd8ad7dfddef2628ff2c8f93170dbd948&scene=27#wechat_redirect) + +12、[如何在 APP 上爬取数据?多图教程带你实操](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247498688&idx=2&sn=4125d37e4f552bb0fd186fd066c07eb6&chksm=e8859b22dff21234d15301eeeaef6f61acce0f9c6020285029e61448357b6703a53a51984d12&scene=27#wechat_redirect) + +### 2.9 实用系列 + +1、[你抢不到的火车票,我帮你!](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484972&idx=1&sn=19ac660b61f046c5d419acdae7f394a6&scene=21#wechat_redirect) + +2、[30分钟教你快速搭建一个顔值超高的博客](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485045&idx=1&sn=8b250c0c174e418e2025d86f42c695b6&scene=21#wechat_redirect) + +3、[用Python写一个表白神器让你七夕脱离单身](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485021&idx=1&sn=123b39391d11e9c7160b47a4c6a3dcb1&scene=21#wechat_redirect) + +4、[用 Sphinx 搭建博客时,如何导流到公众号?](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484848&idx=1&sn=80ae18e7f53a64e62ac9c0ef0c21362e&scene=21#wechat_redirect) + +5、[10 行 Python 代码写 1 个 USB 病毒](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484832&idx=1&sn=43c353856c7dd9ea2cb1a9bbcd077fa2&scene=21#wechat_redirect) + +6、[废旧 Android 手机如何改造成 Linux 服务器](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485279&idx=1&sn=7166a2c9445438eaaf63a25b598e5427&scene=21#wechat_redirect) + +7、[如何将手机打造成 Python 开发利器?](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485256&idx=1&sn=2e646e28287707c67c22fbe68112e622&scene=21#wechat_redirect) + +8、[我用 Python 做了一回黑客,批量破解了朋友的网站密码](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485156&idx=1&sn=05142ae7b4bf7e97ebe042e394aa7084&scene=21#wechat_redirect) + +9、[手把手教你安装Win+Ubuntu双系统](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485030&idx=1&sn=8383a7306381f36781957b807fa93961&scene=21#wechat_redirect) + +10、[一篇文章让你的 MacBook 进入超神状态](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484906&idx=1&sn=b2c3c969e53beae53aa7be7959227b5b&scene=21#wechat_redirect) + +11、[情人节来了,教你个用 Python 表白的技巧](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485701&idx=1&sn=ef7f0b83e60f397c1839259b275575bf&chksm=e88669e7dff1e0f1317ec429cf9e70442bb3a08ec46efe9a0d06f4ec9847574ea30b53904670&token=1148998814&lang=zh_CN#rd) + +12、[“Hack” 微信实战:如何用 Python 分析微信群聊记录?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486141&idx=1&sn=8b32c57dce0f3a33127c39c9cd35509e&chksm=e8866a5fdff1e349f16f677304716e40a305e60168fe7e30361de675dad5dfa956c9d7c79089&scene=27#wechat_redirect) + +13、[5 行 Python 代码生成自定义二维码](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488795&idx=2&sn=8e03e01e861753f7ccf3adeb1f3cb848&chksm=e88675f9dff1fcef328c69b1519743fcc3ae83b80dd3d66cb934acb346781497f83c5a9051a5&scene=27#wechat_redirect) + +14、[女朋友背着我,用 Python 偷偷隐藏了她的行踪](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247487175&idx=1&sn=c3ba19bdbcb6fd59b37ff04d02bce63b&chksm=e8866e25dff1e733b31386fda99271eefadc77b3e0579df4d74617b561ecf0fa0db70f9f2860&scene=27#wechat_redirect) + +15、[zip 解压炸弹? ?在 Python 面前,啥也不是..](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491841&idx=2&sn=307a29d71776f6d1c68567a16727a7e5&chksm=e88581e3dff208f55a48081cb8f951ca7d977c9b1ec3ac9aaf26bc8c53904ac0e15035e5c680&scene=27#wechat_redirect) + +16、[把你的朋友变成表情包?Python:So easy](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493765&idx=2&sn=cd3cd2a891cb3bc47956ac3bc8a06dd1&chksm=e8858867dff20171241f81274eec097f48ea23558029b42a3e7565833c8a62d20e52d2dea87e#rd) + +17、[超干!如何建立一个完美的 Python 项目?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493789&idx=1&sn=7f0f4c40e410a3cfb01706dd9c8c8fc6&chksm=e885887fdff2016930accb8ea6d4e2cb67d4d6983ca716148da7f63c62a6b96f518497ed2575&token=58703854&lang=zh_CN#rd) + +18、[10 个“疯狂”的 Python 项目创意](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493963&idx=2&sn=e4ff38bc55f4ad4d990191e81a316421&chksm=e88589a9dff200bff3e65c19744e59dd3407a48ff5b104bc7b71771762b331daca5c7772892a#rd) + +19、[使用 Python 自动化清理微信僵尸好友](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496922&idx=2&sn=3b2233563ed7a02df94ab2600fe737f3&chksm=e8859438dff21d2eb4874859a839f6c03b74cbd217a2e92eb6ece714051af11fdcb81c76c4d7&scene=27#wechat_redirect) + +20、[别再问我怎么Python打包成exe了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496522&idx=2&sn=5579b947755bcc4aa2d2dd098d4396bc&chksm=e88593a8dff21abe09ab37a9c6ee855bab17342a7397b946514acb9db281c629502709adc6ae&scene=27#wechat_redirect) + +21、[还没抢到票?试下这个用 Python 写的最新抢票神器](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496260&idx=2&sn=6f0b4ea3960b25640eb2936f65ac9e0a&chksm=e88592a6dff21bb0140bb319486321f16a41679a53f68ea8cdbe0cad3fa9fbb6996fcc2019ec&scene=27#wechat_redirect) + +22、[使用 Python 制作按键触发Windows通知的脚本](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494892&idx=2&sn=6c633c829e9e996bf6c3109911d2e20e&chksm=e8858c0edff205181ebc2eb5e907ea38b0dc0fa581a243fe57269968dc1aab147d3230c8a8cf&scene=27#wechat_redirect) + +23、[纯Python方案实现中英文全文搜索](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494874&idx=2&sn=f515724a52613a875869e6aa31ae3e78&chksm=e8858c38dff2052ede9f42592fb59446b68bb3fff84870601c36ee64b864527d25cb9619ccae&scene=27#wechat_redirect) + +24、[两行 Python 代码,精准识别一张图片的格式](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497854&idx=2&sn=ca9066d3d7e4f3a0e8dfa18429683b30&chksm=e885989cdff2118a81ecd769cf1443e252d5347a7c76e7d5b2d9c494d0afa2dbda5fbe467897&scene=27#wechat_redirect) + +25、[明哥放大招! 这下看你们还怎么搬运我的文章 ~](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247498344&idx=1&sn=c3707e3058f444fc42e373155f82c514&chksm=e8859a8adff2139c790e5240dd4339b5cf7493e959eba0ddff5738a2432ff287ba6488b59b18#rd) + +26、[如何在手机上配置 Python 环境](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497813&idx=2&sn=b4b09859f7b175e0a60ca7e61131d475&chksm=e88598b7dff211a124f85f82db20a3c7742dce30f7218dcd00ac393cc49ad7754b2401f8e1bd&scene=27#wechat_redirect) + +27、[在手机上运行 Python,这款工具比 QPython 还好用~](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497684&idx=2&sn=62756dddcd6d8a8e29326d33b1d9e70e&chksm=e8859736dff21e20cf67f8c29e87cdcd2849f04bb9567dc2f5c2dcc6a00cbd8aeeecaace335f&scene=27#wechat_redirect) + +28、[情人节表白神器,v2.0 版本](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497554&idx=1&sn=032200c99fcb0841246cb5eed74dc73b&chksm=e88597b0dff21ea6b20f8301a3c2e2dfdf914d49f23155f81113c90b7b6135802f252481a318&scene=27#wechat_redirect) + +29、[5个无聊透顶的 Python 程序](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497441&idx=1&sn=a6e7b24b13cee4c7f580587f0303a579&chksm=e8859603dff21f158b9560b6b397b13a26d71ef6c72d47d220c65812f5c0f9d7f15a3c209fe5&scene=27#wechat_redirect) + +30、[怎样用Python制作好玩的GIF动图?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497164&idx=2&sn=cfc237768c53716f4554ea89bbca3294&chksm=e885952edff21c381eb898a203bed86a1b96eba8e1cabecabf0c896489c5fc3a0022b0be8527&scene=27#wechat_redirect) + + +## 03. 数据分析 + +### 3.1 基础库 + +1、[有关 NumPy 和数据表达的可视化介绍](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485295&idx=1&sn=6220c2ed0d73feade0c9691fbf214ba7&scene=21#wechat_redirect) + +2、[快速提升效率,这6个 Pandas 技巧一定要知道](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491909&idx=2&sn=3f3bf16784689a5e8bd5f9ef9478040f&chksm=e88581a7dff208b12e25ddaf6a047abc47878eee56f85309b6618cfd92a4dfeb2445f23e2f05#rd) + +3、[50题 讲透 matplotlib :从入门到精通](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486026&idx=1&sn=7b333759709c30fe442732b7a107e3c1&chksm=e8866aa8dff1e3be37f5169ac53bbcf71a76514e99fbbcbe458ec15aa1204d988ad44d689eb3&scene=27#wechat_redirect) + +4、[实用的 Pandas 技巧,估计 80% 的人不知道](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496209&idx=2&sn=8f8db418261326c981cd27f57cc3fc5b&chksm=e88592f3dff21be543cc302a715ea39ae8a1adacb7342f45d5bcf2eca9c2b398b05955408597&scene=27#wechat_redirect) + +5、[用Python 操作 Excel,这篇文章别错过了!(超全总结)](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247498065&idx=1&sn=5f2bb43d9d960c2a7330353c4ac926a8&chksm=e88599b3dff210a528c3e6aac2ea1708b7aa5e3d58c49d12d63492271396ccebee8f0a4a6eae&scene=27#wechat_redirect) + +6、[别找了,这是 Pandas 最详细教程了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497846&idx=2&sn=9483146777ac86567e3933e6d5475e5f&chksm=e8859894dff2118208b517d0d9e753fbf8b1bb83995d36cf04694825972b6a82e195d706852d&scene=27#wechat_redirect) + +7、[再见 for 循环!pandas 提速 315 倍~](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497472&idx=2&sn=df1089640d2beb3607518d0ea9f3e709&chksm=e88597e2dff21ef45a7c3b25e102bc665368f628d1b76decfbeeb18a4cd1a2605737c4c8fb21&scene=27#wechat_redirect) + +8、[Python 操作 Excel 库 xlwings 常用操作详解](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497164&idx=1&sn=281a25369e47ecba1951d4e92f01d5d0&chksm=e885952edff21c38f633910f3c2aac54f8e379707e70d9a70a1cdde5bfd4b7fde145315ea54f&scene=27#wechat_redirect) + +### 3.2 数据可视化 + +1、[可视化01|一图带你入门matplotlib](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485022&idx=1&sn=76d4270a15c430217588bd9f8be8303b&chksm=e88666bcdff1efaa35c6d685f19b04e62f58e768dc9d1819bcb9f8211f65d3fd83296259d923&token=1148998814&lang=zh_CN#rd) + +2、[可视化02|详解六种可视化图表](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485020&idx=1&sn=7f82736e6a2e5442ed59c82d8e242ca4&scene=21#wechat_redirect) + +3、[可视化03|用正余弦学习matplotlib](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485019&idx=1&sn=9d44ee27fd888831e94845d6d0256deb&scene=21#wechat_redirect) + +4、[可视化04|子图与子区难点剖析](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485014&idx=1&sn=90dbdf17f049c152944a4c28642df249&scene=21#wechat_redirect) + +5、[可视化05|绘制酷炫的GIF动态图](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485007&idx=1&sn=1464dee30d006ddb5111f9827b0c4081&scene=21#wechat_redirect) + +6、[可视化06|自动生成图像视频](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485002&idx=1&sn=f09c089328eb0fe39721b73272c81214&scene=21#wechat_redirect) + +7、[可视化07|50个最有价值的图表](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484920&idx=1&sn=92eb2fd55f13a8bda75a7103a73f8d50&scene=21#wechat_redirect) + +8、[ 可视货08|利用 Flask 动态展示 Pyecharts 图表数据的几种方法](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485658&idx=1&sn=f78e976889de52c0ce35e862bafacd8a&chksm=e8866838dff1e12e41b8f2dd1a43dc540ff39484ae64831332d233b5a4f7ca3b439d370ef1ed#rd) + +9、[一个没法商用,但是好玩有趣的 Python 手绘图形库!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491212&idx=2&sn=66a5fd4f672b668aee6bb2c3a01a92f6&chksm=e8867e6edff1f77813b2b59f6219d18041963e6011afa1a590925c71ebd79c7e90b03e82c606&scene=27#wechat_redirect) + +10、[如何使用 Python 绘制一套动态图形?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488616&idx=1&sn=ef094168fc5ff4c46a66b2068cb1011e&chksm=e886748adff1fd9cc9f9f3ed3b2210c9f9f2c770458b3207f9fd6b12ee37a5451e9444b41e59&scene=27#wechat_redirect) + +11、[一文学会制作 6 种炫酷的 Python 动态图](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486111&idx=2&sn=fadf51d43bc468c58ba6885db3006e7a&chksm=e8866a7ddff1e36b5815a9693150799d5925727f5a425e642fd136283ff4a58b7f19ba9da39d&scene=27#wechat_redirect) + +12、[如何使用 Python 绘制一套动态图形?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488616&idx=1&sn=ef094168fc5ff4c46a66b2068cb1011e&chksm=e886748adff1fd9cc9f9f3ed3b2210c9f9f2c770458b3207f9fd6b12ee37a5451e9444b41e59&scene=27#wechat_redirect) + +13、[超硬核的 Python 数据可视化教程](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492265&idx=2&sn=2aede70646f9ee34ad526d2d99b6549e&chksm=e885824bdff20b5d428dbb09daeae2f3e96f1362372bf6ffb16fae1f06263703379873025d43&scene=27#wechat_redirect) + +14、[收藏!最全的可视化学入门算法教程(Python实现)](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491520&idx=1&sn=55804b80dcc56a3923255abf58e08968&chksm=e8867f22dff1f6340a7f61f7796a1e78bd695278a340351860efc244c8a9bbf80cc02bbfaf05&scene=27#wechat_redirect) + +15、[50 款数据可视化分析工具大集合,总有一款适合你](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247490737&idx=1&sn=f447d6e27504611baf8a4ad4056c6e5a&chksm=e8867c53dff1f5450ff808baec53797bd772cdd3c0e43f2f0c278cd4b8867223d5591ab2aa7d&scene=27#wechat_redirect) + +16、[用Python画漂亮的专业插图 ?So easy!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247490251&idx=1&sn=14df276f09201930fdc413d8f9a772df&chksm=e8867a29dff1f33fd0f85cf4412c42cc1145e917b3cd06e158aa31356525799033dd8c6e620f&scene=27#wechat_redirect) + +17、[太好玩了,看看我用 Pyecharts绘制的“时间轮播图”](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489657&idx=2&sn=6359a534033c0a6f21af28a7d9f8b768&chksm=e886789bdff1f18d6719558e305453cba2b6c8a55d66c9bcb6dd5678209d89c1594d87de0a87&scene=27#wechat_redirect) + +18、[实战!用60行Python代码画出30万条房产数据分析图](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489032&idx=1&sn=6b9c7281d3090783a9a486b81f749789&chksm=e88676eadff1fffcec00d3c44ee9b34496dc886417da55aeabed017d496da85d442f205c227d&scene=27#wechat_redirect) + +19、[刷爆全网的动态条形图,原来5行Python代码就能实现!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492725&idx=1&sn=964c45002220761dafcf537d5f9fe802&chksm=e8858497dff20d8175b87ddb1997b1dd71c91a03a92e60611718fdbf2bdbe3cee41d239b360d&scene=27#wechat_redirect) + +20、[这 10 个 Python 可视化动图,学会了就吹牛了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493551&idx=2&sn=dee235d803b491163f74a49f5cf0d12f&chksm=e885874ddff20e5bf639454c226f6e74e5180dbab3803db08c2bd72d67347aa52dede40da4c9#rd) + +21、[牛批了,1行python代码就可实现炫酷可视化](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494580&idx=2&sn=bf87885645377449f3a94d6d8122e1f6&chksm=e8858b56dff2024046c48ccf0ff087c42fa2608c0d0b6183ea61ffb85278a9c52138cdfbef13&scene=27#wechat_redirect) + +22、[珍藏版 | 这 30 个细节,决定了数据可视化的质量](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496866&idx=1&sn=f1ba05ed6a4db3e507f0cf0d4ce3ac59&chksm=e8859440dff21d56256e0ad9a9c739dca37fae6c40843fe98033a2e77a412a667407f36a7113&scene=27#wechat_redirect) + +23、[吹爆了这个可视化神器,上手后直接开大~](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247495182&idx=1&sn=d8e913a808796e6fa793d58df26d209f&chksm=e8858eecdff207fac878d4b27894b5a2c69812d6803262e430d2244443a2c23e38d91a697556&scene=27#wechat_redirect) + +24、[Pygal,可导出矢量图的Python可视化利器](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497951&idx=1&sn=7cce71d5c34fdeb89509e97817a5f0af&chksm=e885983ddff2112bc76bd9a4dbe14f407c5fe8b2ea0010b353e760b59c4476603f1d82a26eac&scene=27#wechat_redirect) + +25、[这可能是 Python里最强的绘制地图神器](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497813&idx=1&sn=c5034f6ecf03fe3ccb6771b39faa8230&chksm=e88598b7dff211a11145c44db19f50df244ab3c2b740e1d51ead51b25d7fa9643660ca5cc29a&scene=27#wechat_redirect) + +### 3.3 工具使用 + +1、[ 整理了 50个 IPython 的实用技巧](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485613&idx=1&sn=70f89faf2573b3025edc73f525f22a0a&chksm=e886684fdff1e159509d30fd0a24854da39fb5a6ae55e0ed6e40b7971d3219968006f80aad7b#rd) + +2、[ Jupyter NoteBook 的使用指南](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485024&idx=1&sn=aac0db4b2c97c7f5c2871342b936eaa2&chksm=e8866682dff1ef947ec6474b8c03f668e462232ebd0ec0f137d42e5e63b9b66a3d9e303c1caf&token=1148998814&lang=zh_CN#rd) + +3、[Jupyter Notebook最常用的五大配置技巧](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491411&idx=2&sn=88c290af7793ddc024cf2a39875b97e8&chksm=e8867fb1dff1f6a731077d749b1ea44fd558995f3448e27da9becf7b035ed777774d1b0bb0ec&scene=27#wechat_redirect) + +4、[强烈安利!这十二个 IPython 魔法命令](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488777&idx=2&sn=3b14fe7faa4d2a26b702c15ebe6b6103&chksm=e88675ebdff1fcfd471dc84c802dab2c37889d59e55711c5d521c80fdbf38291b4092b840083&scene=27#wechat_redirect) + +5、[真香!安利 6 个 Python 数据分析神器](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488619&idx=1&sn=0c6c76b9deaa4f1976dcacaaee018312&chksm=e8867489dff1fd9fa2b0ac08696c4dae1b48054ca64aefef6d2117179dbbffbfe4ae9d1a4f81&scene=27#wechat_redirect) + +6、[使用 pyecharts 打造酷炫的 BI 大屏](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247487730&idx=2&sn=b2ee3058d63ebf702f3f0f9a6ca9c623&chksm=e8867010dff1f90686948269ca5e0907d726fc775029cc414285d71c0176ce859b818d2e34d5&scene=27#wechat_redirect) + +7、[酷炫的动态可视化交互大屏,用Excel就能做!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486295&idx=2&sn=2826a69402912a70955209192e761c4d&chksm=e8866bb5dff1e2a30d374d5f46afa1cb9d952a0c939701b9f8b5bc52df4169d5e2da30236505&scene=27#wechat_redirect) + +8、[像操作Excel一样玩Pandas,这款可视化神器太棒了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493689&idx=1&sn=2e614500c8359e4b87de55128fe69593&chksm=e88588dbdff201cd761e20605f10f1aa9525d6d89072cbbc9a307e35788b8a425c2044d337d4#rd) + +9、[8 个 Jupyter Notebook Tips,隐藏得太深了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494062&idx=2&sn=860539d7eae82c53791cd7a2eb005536&chksm=e885894cdff2005ae9169c7dfabe3760c19eded392ec18805f1d763ad8dce77c21150698178a&scene=27#wechat_redirect) + +10、[PyCaret:几行代码轻松搞定从数据处理到模型部署](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247495402&idx=2&sn=bb0664c6ac7995dfad4f4a1268e2e374&chksm=e8858e08dff2071e121d81fa564671ba4425814687fd2df3aa32898ffb3bdbe72d303bc9d66a&scene=27#wechat_redirect) + +11、[这个 Jupyter 插件,用起来就像 Excel 一样简单](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247498500&idx=2&sn=672a1da1a9957c84a19802842df5b5d9&chksm=e8859be6dff212f0754dd0a3820241be3af34d72e6dc32e7d83d1f87198bd549ccfd66c55029&scene=27#wechat_redirect) + + +## 04. 开发工具 + +1、[代码调试|无图形调试工具 - pdb](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484969&idx=1&sn=a99fc31865edc4b439707d2be6f66654&scene=21#wechat_redirect) + +2、[代码调试|远程调试图文超详细教程](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484970&idx=1&sn=9ac9c5dfcdc8c6b48a7b4c9854825734&scene=21#wechat_redirect) + +3、[优化Python开发环境的几个技巧](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485131&idx=1&sn=f1bd7b31a3624f015c74f56a8888a695&scene=21#wechat_redirect) + +4、[让你重新爱上 Windows 的小众软件](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484964&idx=1&sn=1479536416788a6c55dddef70167eb88&scene=21#wechat_redirect) + +5、[Python 的命令行参数解析工具](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484960&idx=1&sn=3456d9a05b35588b060833ceb189db6e&scene=21#wechat_redirect) + +6、[搜索神器 EveryThing,你把它的潜力用到极致了吗?](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484894&idx=1&sn=59877fe818739175d3d075458594f563&scene=21#wechat_redirect) + +7、[开发工具|盘点 Xshell 的那些奇淫技巧](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485043&idx=1&sn=8c240e569c60607cd4cea8888a6aa2e1&scene=21#wechat_redirect) + +8、[告别996,全靠这个Python补全利器](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484824&idx=2&sn=8f20af371954dfd2a5c890bb5814b4c9&scene=21#wechat_redirect) + +9、[学会这21条,你离 Vim 大神就不远了!](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484902&idx=1&sn=d677261fda90b67bf5eda886447a4f77&scene=21#wechat_redirect) + +10、[用 Python 做开发,做到这些才能一直爽](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484874&idx=1&sn=abffab70b1e265ede1fd3b994dedab90&scene=21#wechat_redirect) + +11、[这款神器,能把 Python 代码执行过程看地一清二楚](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484878&idx=1&sn=9bc941ff19ec38e7c7137a22df981f27&scene=21#wechat_redirect) + +12、[如何把自己的 Python 包发布到 PYPI?](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484835&idx=2&sn=f24a415d47d4122c4d6b1a6ccf254a51&scene=21#wechat_redirect) + +13、[谁说 Vim 不好用?送你一个五彩斑斓的编辑器!](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484872&idx=2&sn=ce718e511b754fe936172724a824a716&scene=21#wechat_redirect) + +14、[迄今为止,我见过最好的正则入门教程(上)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484831&idx=1&sn=077d14410db6a906c3b962f0ba18b2d4&scene=21#wechat_redirect) + +15、[迄今为止,我见过最好的正则入门教程(下)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484830&idx=1&sn=4d48b1c7f2b5234992732f8f15b868df&scene=21#wechat_redirect) + +16、[Win 平台做 Python 开发的最佳组合](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484837&idx=2&sn=68935077ae9eeb6fe4f708565aa0a9ed&scene=21#wechat_redirect) + +17、[15 款Python编辑器的优缺点,别再问我“选什么编辑器”啦!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492759&idx=1&sn=6c6e6606fd9da9d2b951bda9e8a1b223&chksm=e8858475dff20d638f4b731a44dd48fe01a68f16480bcaed2516fc7d3d56c61cc6c62afccb9d&scene=27#wechat_redirect) + +18、[用了三年的 pdb,没想到还能这么调试](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247498550&idx=1&sn=d2d0ba8987509a67ba40c19f7dcfd719&chksm=e8859bd4dff212c2f4d6f07c42ae81af046aeb8611c3c869143ed7e4ebac03fd011ddc8b88e6&scene=27#wechat_redirect) + +19、[调试 Python 代码,可别再用 Print了!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497083&idx=1&sn=47fa23a2104c2e75ad71c56b6d89b84d&chksm=e8859599dff21c8f0f832e83f3e5220bef96fbba7514863e4e8fcd178818258f024744902806&scene=27#wechat_redirect) + +### 4.1 PyCharm + +1、[受用一生的高效PyCharm使用技巧(一)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484946&idx=1&sn=12a891db18e9d1233535fa4aca9a3892&scene=21#wechat_redirect) + +2、[受用一生的高效PyCharm使用技巧(二)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484942&idx=1&sn=9dbb2cfe2a277bd3519d37414fcc608e&scene=21#wechat_redirect) + +3、[受用一生的高效PyCharm使用技巧(三)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484932&idx=1&sn=347b35ccdee94895652caa86191360c8&scene=21#wechat_redirect) + +4、[受用一生的高效PyCharm使用技巧(四)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484918&idx=1&sn=66b3fd784050e5cb85109faa3d063993&scene=21#wechat_redirect) + +5、[受用一生的高的PyCharm使用技巧(五)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484914&idx=1&sn=cd1282f94f9326647b05ad9090afd2c8&scene=21#wechat_redirect) + +6、[受用一生的高效PyCharm使用技巧(六)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484907&idx=1&sn=647a75b96884b39c57664f62ead11b89&scene=21#wechat_redirect) + +7、[受用一生的高效 PyCharm 使用技巧(七)](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485372&idx=1&sn=3ed61c4ccbb089358213304cd70bb0f7&chksm=e886675edff1ee487911e922279675264916dd08120f5f40113f37dc080b94c7bf9ad67719c4&token=1148998814&lang=zh_CN#rd) + +8、[代码调试|远程调试图文超详细教程](https://mp.weixin.qq.com/s?__biz=MzU4OTUwMDE1Mw==&mid=2247484304&idx=1&sn=7612f0c2fd6232723ca2733fb1e8f46d&scene=21#wechat_redirect) + +9、[手把手教你打造一个顔值超高的IDE](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485052&idx=1&sn=2e0bb1a3af4206fd2cf8e3650f695e6b&scene=21#wechat_redirect) + +10、[玩转 PyCharm ,这篇文章就够了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247487629&idx=1&sn=9a19cbcce2effcc242cc8d6d33cd2762&chksm=e886706fdff1f97955e73495c0be5b104f834d569d75e9e1470417f79e1d19ff4937683484ad&scene=27#wechat_redirect) + +11、[用动画展示 Pycharm 十大实用技巧](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486118&idx=1&sn=990c35adb86919bda2f2cb82e7c5fb9e&chksm=e8866a44dff1e35200244e3d369ad6c0f736d3511dcfb086b7641339e20ae62e35b8fd60bdd9&scene=27#wechat_redirect) + +12、[太棒了!Jupyter 与PyCharm 完美融合,Jupytext 来啦!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496487&idx=1&sn=344204a2893c7bb54e9977f274c29fef&chksm=e88593c5dff21ad366d0fa3c2a1af3760f8f67b167ee8b29e016fe31adc66bb84c3e018e25ad&scene=27#wechat_redirect) + +13、[装上后这 14 个插件后,PyCharm 真的是无敌的存在](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247495720&idx=1&sn=3233659fa9c975df9e95402a8c68b405&chksm=e88590cadff219dcd82f22d1d4684dda09a2db3469a0826ffe7605388fc37fb3a2c7cca49e0f&scene=27#wechat_redirect) + +14、[卸载 PyCharm!这才是 Python 小白的最理想的 IDE](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497739&idx=1&sn=2e4795f4ddc784cfa796fb59b3d0e707&chksm=e88598e9dff211ffbe2cea5f574c8ee6117f4e7cd5d4869a804422139360421e4803df270f19&scene=27#wechat_redirect) + +### 4.2 VSCode + +1、[这 21 个VSCode 快捷键,能让你的代码飞起来](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484893&idx=1&sn=421b544115efad388314ccd027761b40&scene=21#wechat_redirect) + +2、[神技巧!在浏览器中也能用 VS Code](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484859&idx=2&sn=70abd19426374271a10cbef8e1645c7a&scene=21#wechat_redirect) + +3、[生产力终极指南:用了两年,如今才算真正会用VS Code](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492595&idx=2&sn=a39a7cb70908d442a399ac80a272f90e&chksm=e8858311dff20a0782cca942c7e9f3444bb443cf816fd05d76c5f7c234930afacb6c948802bf&scene=27#wechat_redirect) + +4、[VS Code的7个开源替代品,全都知道算我输!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247490251&idx=2&sn=ef0eca9da6eff8405a5a48d89a6b2e54&chksm=e8867a29dff1f33f29487864efb1389b02705d81d0198df581b5b71085ff238f24ffe99f154c&scene=27#wechat_redirect) + +5、[再见了,PyCharm](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489522&idx=1&sn=d7d45dba4a7c9e2f010d09f757639a19&chksm=e8867710dff1fe0657a16b6087ad4a50fdceb8f324bef5f950b3320e33e09ce10d1fa045827d&scene=27#wechat_redirect) + +6、[微软推出 Pylance,改善 VS Code 中的 Python 体验](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489006&idx=2&sn=58f6dbe10cba98cebab0fd19f124e4df&chksm=e886750cdff1fc1a6cfe249a2f76213fef1a789f4a5006704e33d00b9abadde489af7052a8a9&scene=27#wechat_redirect) + +7、[VS Code 连接远程服务器运行 Jupyter Notebook](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486773&idx=2&sn=75b2453513b1445d9881f5ec8c1f44d1&chksm=e8866dd7dff1e4c167b27eccec9a6469b7988d6b05010160247b3e1a549764201807212ed581&scene=27#wechat_redirect) + +8、[GitHub 发布重磅更新:你电脑上的 IDE 可以删了?!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486295&idx=1&sn=e5bd46de0616fad6105d2e46a359cd3d&chksm=e8866bb5dff1e2a37058e1cbc502863f8b8a885a493b7ef9f5e442a1b554ffeb0ae09d77026e&scene=27#wechat_redirect) + +9、[用 VS Code 写 Python,这8个扩展装上后无敌了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492505&idx=1&sn=ba354ab86500280d46038d2fa2f3572b&chksm=e885837bdff20a6dd2d4411719e44a3b88371b5006e9dc2b2580e6862f3161e70cb339240512&scene=27#wechat_redirect) + +10、[有了这个VSCode神器,从此爱上调试代码](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497025&idx=2&sn=91734e86eb03b0ad8b299fa05fb89896&chksm=e88595a3dff21cb5638a874e6ea75aefa8539eb832e239d8103fd66584d1276edbe1d616c4fb&scene=27#wechat_redirect) + +11、[用 VS Code 写 Python,这几个插件是必装的](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496552&idx=1&sn=ab85fc16d53f5d6bbcb0c030cae51402&chksm=e885938adff21a9ca75d485aab0980cb5cb7363d4eadaf0e1867dbb955c7296d1e16f7c7c367&scene=27#wechat_redirect) + +12、[出炉了! 2021 年将火爆的 10款 VSCode 扩展插件](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497928&idx=1&sn=0ec6994930f1cf8bd3a1ed8d8404eb18&chksm=e885982adff2113c94ba7c0ddc989c174daeedd159359d9289b48006e0c6b1d0aa8b87980ef1&scene=27#wechat_redirect) + +13、[神器 VS Code,超详细Python配置使用指南](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497249&idx=1&sn=00a13cb6099f487ce3f88f27923d6a3b&chksm=e88596c3dff21fd504d3e469a0eddc00f8febdeb95b7b8c7483dfad7ef84382d2cc1f3b16f2c&scene=27#wechat_redirect) + +### 4.3 好用的库 + +1、[使用 Python 远程登陆服务器的最佳实践](https://mp.weixin.qq.com/s/aRXYAP9D9rgil-0_Etb0SQ) + +2、[这么设置 Python 的环境变量,我还是第一次见](https://mp.weixin.qq.com/s/LcjIPZPSg0KbL9X-i6vigg) + +3、[太强了!Python中完美的日志解决方案](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485741&idx=1&sn=505c06669baa44873171a3eed81f32b4&chksm=e88669cfdff1e0d91635b75f54998667e04bfb05a1aebae096930bd23acdd9d35ea858861bb2#rd) + +4、[如何使用 Python 操作 Git 代码?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485723&idx=1&sn=35511b71347111c00a9e1633309efd13&chksm=e88669f9dff1e0ef7aec03f2bdbddb8408bf12a57a36add441b75e486dd72df13be7629625ab#rd) + +5、[用它5分钟以后,我放弃用了四年的 Flask](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485657&idx=1&sn=e21ddc5b670a9b667135df2ca97ec99c&chksm=e886683bdff1e12d9e1d64a7f5bfbc65ca2372711cd9b08ef36ce0cdd99811ce44ff162585df#rd) + +6、[整理了 34 个被吹爆了的Python开源框架](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485653&idx=1&sn=edd893dd711b3681aa0bacdf8ab384fd&chksm=e8866837dff1e1216f6fbf413118f839e6e1dc5ed7b45117df55f13e25670c5ffba34966abff#rd) + +7、[ 为了选出最合适的 http客户端,我做了个测评](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485651&idx=1&sn=647c22ac66e469ccc33478457dadf224&chksm=e8866831dff1e1279149ff1e3af84bef86d24c524b7b7c14e9c519cf7c4739fa8f10dcc4a8d0#rd) + +8、[凭什么 FastAPI 火成这样?看这篇文章就知道了](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485891&idx=1&sn=82bde3e83435ebb6beb7e3581f12f7b0&chksm=e8866921dff1e0376befb029e9f1d81f33b0fa55242182f8de20d2a6e6b0cce0b5efd02f9aef&token=2013245174&lang=zh_CN#rd) + +9、[要想 BUG 变得富有美感,这个库你一定要看](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485889&idx=1&sn=0258eb138dce2c71b533d340770d5d09&chksm=e8866923dff1e03548dee4f780b410c22b51e1c3ffde3ef814f6a9b94e49af941fc04c79a660&token=2013245174&lang=zh_CN#rd) + +10、[如何使用 Python 输出漂亮的表格?](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485841&idx=2&sn=705c123abed5441a52f8640b65f3c400&chksm=e8866973dff1e0650e4b2e025d0e86b3aedeb7ea8f68ad560f37cb033f36660b6eee15fb3ce4&token=2013245174&lang=zh_CN#rd) + +11、[用 Python 写出来的进度条,竟如此美妙~](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492108&idx=2&sn=2fa1e31f9684df6d6f3da21aa4cba6e5&chksm=e88582eedff20bf886c29d480245d835c0a3fbea49e54909abbeb703bb7149d4e3444202e97c&scene=27#wechat_redirect) + +12、[推荐一些能提高生产力的 Python 库](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491947&idx=2&sn=765ca757e0aee7fd4dd3f7779f409ff3&chksm=e8858189dff2089f74a97972c1f213291a8680a766b328a74c609f465f7dcf16c324df57a660&scene=27#wechat_redirect) + +13、[规整字符串的数据提取神器:parse 库](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491617&idx=1&sn=b77cd25d6c92f86c1492f913edcb51c7&chksm=e88580c3dff209d500525bbc81464034ca431c92603b5ec83046faaac7ca4c012034964805e0&scene=27#wechat_redirect) + +14、[微软再出神器,这次终于对 Python下手了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491407&idx=1&sn=0044bf683ddc4799ef2e7c04fb75ebf8&chksm=e8867faddff1f6bbbae3e716e7b686eeb4a5b49f19a2fb2b8743ae2e641ee529189d313f6fe8&scene=27#wechat_redirect) + +15、[这个 Python 库有点黑科技](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491241&idx=1&sn=700979655adce734f5300e7ee380d4ab&chksm=e8867e4bdff1f75d355b34ca8561844c920a2434357350e06a87c99cdbdfb094ee29e7957988&scene=27#wechat_redirect) + +16、[适合 Python 入门的 8 款强大工具!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491088&idx=2&sn=23cd3b06b8117a5d996d258dd9c0eb23&chksm=e8867ef2dff1f7e479ad5a633295f1be0fc272f6b4de2526c21129b2dee23cb517e51b508f8f&scene=27#wechat_redirect) + +17、[这些Python库虽然冷门,但功能真的很强大!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247490868&idx=2&sn=7bda9c9021cd26eb43d752f6ff84dbe7&chksm=e8867dd6dff1f4c0398b427f13787c99f24cea2a7b2c7b10fbc3316b0215b3ea861f197e604f&scene=27#wechat_redirect) + +18、[那些被低估了的 Python 库,看看你用过几个?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247490782&idx=1&sn=2c710eca844da200dac14ab017ffcdb3&chksm=e8867c3cdff1f52a86c291e34e458f57bd5572c6fdeb75cdb84fdfba2d9bb1731067dca7d195&scene=27#wechat_redirect) + +19、[用 Python 写出这样的进度条,刷新了我对进度条的认知](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247490326&idx=1&sn=867061f4ad793e957161c30be77ef9bb&chksm=e8867bf4dff1f2e2f1cdc5af4366540d33fc0edfc52810af09b82a590fcd6ec4c5c2d7a528c6&scene=27#wechat_redirect) + +20、[少有人知的 Python "重试机制",请了解一下 tenacity ](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489274&idx=1&sn=7ddc4505f932b386ee22c7873ff5df1a&chksm=e8867618dff1ff0ea5aa55c6acfeb85944028f1bb0be7fb2697f4ec018de297579b797ce048b&scene=27#wechat_redirect) + +21、[一个极具意义的 Python 前端开发工具](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489090&idx=1&sn=1e7ee21422440dc32d7a9a40eaab6c4e&chksm=e88676a0dff1ffb6731df2996d3a4011eebdd8af4926920eefb30d086fa909943179e83d8957&scene=27#wechat_redirect) + +22、[非常实用的 Python 库,推一次火一次](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493413&idx=1&sn=2405d851af05549d5cb5f79353fdc393&chksm=e88587c7dff20ed1c2f93c9a042b293eae294f17bf13cbbebdf50682c8fd24e09e4647dbbe6b&scene=27#wechat_redirect) + +23、[新一代 Notebook 的神器出现,替代 JuPyter 指日可待](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493296&idx=2&sn=075bc9476933eec961bc2e9a7245d2d0&chksm=e8858652dff20f44a4d9cb30ad03841bc991a0efc2a63e63b04d5c8f68b3c6a67fbfa884551e&scene=27#wechat_redirect) + +24、[使用 Python 下载的 11 种姿势,一种比一种高级](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493230&idx=2&sn=8d356b9e0a9d597fbca1ef6ea2f8ca4d&chksm=e885868cdff20f9a2d220f18ecc27909c1217568728f213f492bf566578da5742190bcff4862&scene=27#wechat_redirect) + +25、[一个非常好用的 Python 魔法库](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493501&idx=1&sn=fc2575646311350cb47f6caed6102539&chksm=e885879fdff20e89c9600b6147885523fa0dbb7182fdf458c5aad5cd76ba6b415d25694f6bed#rd) + +26、[终于来了!!Pyston v2.0 发布,解决 Python 慢速的救星](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493602&idx=1&sn=3ba266f9460d94eb4d16c50bffe3ca94&chksm=e8858700dff20e1621fa34dae0b983c38fbcb5575d03f4c951c34a6d0a5f3b81e6c61fddd68a&token=58703854&lang=zh_CN#rd) + +27、[献给 Python 开发人员的 25 个最佳 GitHub 代码库!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493878&idx=1&sn=f476bbed89543828b54e7c9fcd93abbb&chksm=e8858814dff20102b366afa61e870c2d82d3f8fd332dbf39f3824867a3f8b5e7a5ad4b0bfb89#rd) + +28、[求你了,别再用 print 调试代码了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494015&idx=1&sn=dc0dd7179d00d074e3013658760fe41d&chksm=e885899ddff2008be8fde435d8ed2fb80057386aa13f8eee273fd02e8c1ca99201130881380e#rd) + +29、[爱了爱了!0.052秒打开100GB数据,这个Python开源库火爆了!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494268&idx=1&sn=db20e8232caa59512c852dcd723e3a46&chksm=e8858a9edff2038857440f061ec0cef305011d967dfd738df8187f10a2f44d90e3fd7c07e946&scene=27#wechat_redirect) + +30、[用 Hypothesis 快速测试你的 Python 代码](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494299&idx=2&sn=d8af7430ff62c90179491a097a5b43fd&chksm=e8858a79dff2036fae8f7ec05e6827c52cb27149d00a32f9a7dea9ab0e8ed1736fe4b0b3495c&scene=27#wechat_redirect) + +31、[微软最强 Python 自动化工具开源了!不用写一行代码!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494621&idx=1&sn=61d9f8b7557cb2ff517fde1a414b219d&chksm=e8858b3fdff2022954d383579b6392362e99e99af4a6309028dfa6ddd7bfc90a02c85d599b50&scene=27#wechat_redirect) + +32、[Python 中 Mock 到底该怎么玩?一篇文章告诉你(超全)](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496880&idx=2&sn=88899b73e7ca5f261be2b0ab245703ac&chksm=e8859452dff21d4473f5a73b7d87a800ce177581d94028b7911c0187b3f92bd2762d03195126&scene=27#wechat_redirect) + +33、[这款 Python 版终端资源监控器,火了!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496153&idx=2&sn=8b53b63e04b2eff07a16bb8ef641aaca&chksm=e885913bdff2182dd176a5f6b1e324ed18f788830037c649915dc24df289139fd402e97c91b5&scene=27#wechat_redirect) + +34、[谁是 2020 年最强 Python 库?年度 Top 10 出炉!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496075&idx=1&sn=f05417a3c7adb638d394741a0b47c21e&chksm=e8859169dff2187ff80b3fd056160ae9d25009f7b373f82a5bc2c7d6f104a5f12ee52a623a3a&scene=27#wechat_redirect) + +35、[Python 算法模板库,Pythonista 找工作利器](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247495227&idx=2&sn=c7899ab854da814888ef853023d8b74c&chksm=e8858ed9dff207cf571d1819770952180f9c882b63e62025e819fe25538fe4f3a3148d73c228&scene=27#wechat_redirect) + +36、[终于把所有的Python库,都整理出来啦!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247498689&idx=1&sn=66743481223ff48bcb5c8ed257b95754&chksm=e8859b23dff212350492116b1cdc3527f969fbb62cac8309ef91932e02842f35b5f7f4d08661&scene=27#wechat_redirect) + +37、[Python 超级强大的模式匹配工具—Pampy](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247498439&idx=1&sn=1613fd0fb2154bb3a9b5caefb1225b41&chksm=e8859a25dff21333272d75f14badb8491295351b0b3542db7cc1506a7462359ed297ce228710&scene=27#wechat_redirect) + +## 05. 网络基础 + +1、[点亮你的 HTTPS?原来这么简单!!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492265&idx=1&sn=46b095516bf3c0ebfc367ab64f8fd42c&chksm=e885824bdff20b5db2861a411a07653135ffbafaa1e772588bcf86cf9ad54433a0ff492355ad&scene=27#wechat_redirect) + +2、[手绘 10 张图,把 CSRF 跨域攻击、JWT 跨域认证说得明明白白的](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489610&idx=1&sn=c9442c4ad370c318ea7ebafb26208b9c&chksm=e88678a8dff1f1bec43cd601b0c0e3eaff32d168dc2ad69f6273e27f2e6d72b49b7585046057&scene=27#wechat_redirect) + +3、[网络出了问题,如何排查? 这篇文章告诉你](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488835&idx=2&sn=edac7045eb00479481365334ba198f50&chksm=e88675a1dff1fcb76f10049aa97ade7c0669fc1a8c32649a810c1d43b37c7dbe964c17b0730f&scene=27#wechat_redirect) + +4、[肝了三天,万字长文教你玩转 tcpdump,从此抓包不用愁](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488684&idx=1&sn=9a9d717a6c00f978c6575cb934c5c942&chksm=e886744edff1fd58ebb593338484013442c8c2f481497d6c5246cabce3ad43c1ee28299f9098&scene=27#wechat_redirect) + +5、[三张图彻底搞懂 iptables 和 netfilter](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488534&idx=1&sn=44856bba34b906930780535a7000a5af&chksm=e88674f4dff1fde263c119bb66a5fa879e6c07b12d50035552dbd529757bedc45a3a41823013&scene=27#wechat_redirect) + +6、[tcpdump / wireshark 抓包及分析](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488505&idx=2&sn=5e7d7a204c9eef4537fd352090086685&chksm=e886731bdff1fa0d3ba2c9a951fdbd849858a58ea630adab247f3b8b3ff7e76d7de022a8270d&scene=27#wechat_redirect) + +7、[100 个网络基础知识,看完成半个网络高手](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488490&idx=1&sn=a8725e200b3ac351ab4f0a2b6d112199&chksm=e8867308dff1fa1e1d55c89b691394902d5c7f8965063acd8551ad14269135d603f7bef22281&scene=27#wechat_redirect) + +8、[网络知识扫盲:扒开 TCP 的外衣,我看清了 TCP 的本质](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488180&idx=1&sn=09526224732ebfcccb52847f27298c70&chksm=e8867256dff1fb40c9f47bafd0e87a9237c5a9ebf33c8a3d0a598276b496d29cdaa3fbff8d26&scene=27#wechat_redirect) + +9、[网络知识扫盲:一篇文章搞懂 DNS](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247487859&idx=1&sn=55c2c40b807a6bd7036763e99954f063&chksm=e8867191dff1f88743bf88b809471926245a0ec3ef9c9d2c9f311d99533ed5656b7b3617431c&scene=27#wechat_redirect) + +10、[路由器里的广告秘密](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489132&idx=2&sn=4cf42aeef93396f7665a06b2d1dc7fba&chksm=e886768edff1ff98bbd9572d85ddd97ef91ad8d19fdd951c15520cd9756d2c40a53d7cd8111c&scene=27#wechat_redirect) + +11、[10张动图,让你搞懂计算中很重要的名词](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247487331&idx=2&sn=70146e780ca63c55ca3446a5e238b487&chksm=e8866f81dff1e6974610866f756b099e0b8bed5389cfa594f4b94b6092ae31db305b1485aadd&scene=27#wechat_redirect) + +12、[数字证书、签名到底是什么?这篇文章讲得太好了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493263&idx=1&sn=8b26b39da435b619d1344b4aca79b9f7&chksm=e885866ddff20f7b936601facff760969e1ba36d981a9d26920f0acce65c96562ebffcb7d954&scene=27#wechat_redirect) + +13、[为何无法使用 ip 访问网站?](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484976&idx=1&sn=503d75faea7a633729ec90d6f26e21a2&scene=21#wechat_redirect) + +## 06. 实用工具 + +### 6.1 Linux + +1、[值得收藏的 14 个 Linux 下 CPU 监控工具](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485356&idx=1&sn=9dc2f440299ad179e1874febdffa04d6&scene=21#wechat_redirect) + +2、[19 个没什么用,但是”特好玩“的命令](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485142&idx=2&sn=97b0f02f8f0153b1c7ba4899359d55e4&scene=21#wechat_redirect) + +3、[相见恨晚的15个 Linux 神器,你可能一个都没见过](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484887&idx=1&sn=3473df33893a23b4de1e176985a5265e&scene=21#wechat_redirect) + +4、[这 22 款 CLI工具,每一个都是精品](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491148&idx=1&sn=92b194ad574e8b793ebb608319c7d1df&chksm=e8867eaedff1f7b8e257ce6e80890cef6aa72b9078d20a0e1f0241a1c05f660c69891b6a7d12&scene=27#wechat_redirect) + +5、[Github 热榜项目:如何让你的终端酷炫到没朋友](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488641&idx=2&sn=c8ea38a8e216f123ca320d3ec8449bc0&chksm=e8867463dff1fd7522e9556f3ca97bb691ea92625ca664919dddabd35ead37dbd06a16b75b17&scene=27#wechat_redirect) + +6、[如何在1s内创建上百G的超大文件?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247487906&idx=1&sn=a892ae3f3ab0ed0a2a20cf5d51ff1c65&chksm=e8867140dff1f85674d8c01df3c3d4a92cc75cdd34c68c3b86f8c5eb660f500f033ed35deef8&scene=27#wechat_redirect) + +7、[千万不要运行的 Linux 命令](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486845&idx=2&sn=31c1ba636db4d687b16b10981833bfbc&chksm=e8866d9fdff1e48976cab2cb62e3b4a4e2e373aeaa0e961847e49cd13ec4ea417b5162fa165b&scene=27#wechat_redirect) + +8、[不想装系统?这8个网站让你在线体验 Linux](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486303&idx=1&sn=fc6c9b73fcb12c5c0c8257e223c8f657&chksm=e8866bbddff1e2ab5edf8b3d4783bcc65975c0385c140d1c954e7d4949e334b9d6ed92ae98a2&scene=27#wechat_redirect) + +9、[比虚拟机更轻量,比 Docker 和 WSL 更简单的 Linux 环境](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247498054&idx=2&sn=1aa6a118f214f3488c1188cdb2471834&chksm=e88599a4dff210b273db8dffda010bca3f1eb15219b7c268ea941bf1d036cec3fed8fac9f3db&scene=27#wechat_redirect) + +### 6.2 版本管理 + +1、[关于 Git 和 GitHub,你所不知道的十件事](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485232&idx=2&sn=c3314e79af9029bdd76ae187f7b4eb19&scene=21#wechat_redirect) + +2、[关于 Git 图谱,这一篇文章讲得很细。](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485179&idx=2&sn=a9f0a8a669d70c0dccedf71a530d1d93&scene=21#wechat_redirect) + +3、[如何巧妙处理 Git 多平台换行符问题(LF or CRLF)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485333&idx=2&sn=4e8e95e5cb12d27ea6b510aaaf15b4c0&scene=21#wechat_redirect) + +4、[这 7 个高级技巧,不会还怎么玩GitHub](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484940&idx=1&sn=9ad168943b03dff09d53e5d73e13ed46&scene=21#wechat_redirect) + +5、[ 神器!这款VSCode插件能填满Github绿色格子](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485595&idx=1&sn=65df21ab0b4042953dd8257bea8b1848&chksm=e8866879dff1e16fff97584467f2f1728f9c2da007894ae062e9201d53b82a30054036f8e81e#rd) + +6、[Git 中冷门却又非常需要的高级用法](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485890&idx=2&sn=528df28585ec16114324e391dbfebab4&chksm=e8866920dff1e036d5da7f5dfe3c944ef8b13d72f022d72b209117120c7e27ebb71036b99893&token=2013245174&lang=zh_CN#rd) + +7、[别乱提交代码了,来围观下大厂的 Git 提交规范](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486877&idx=1&sn=f14a8add6cee89f8312c7077e4e1ed22&chksm=e8866d7fdff1e4691e6b3627fdd7963942d4d568a1e1ba1d7e8ba81944e6afaadc6923429006&scene=27#wechat_redirect) + +8、[盘点提高国内访问 Github 的速度的 9 种方案](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491802&idx=2&sn=30df1c954dd8505639c6cd71c0e37d76&chksm=e8858038dff2092eed0b603635b648f2c52d720e98536aee1d50b774c9feac6b25fec6ca9a7c&scene=27#wechat_redirect) + +9、[工作流一目了然,看小姐姐用动图展示10大Git命令](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486154&idx=1&sn=9a409d493eb789c66cb5c3596195582c&chksm=e8866a28dff1e33e13148dbb98dd8a3899392481f4806805bc96de3b6dc7a954ef3eb899bace&scene=27#wechat_redirect) + +10、[如何用 GitHub Actions 写出高质量的 Python代码?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485985&idx=2&sn=ec7a102012096847b8fdf7156d9260f3&chksm=e8866ac3dff1e3d53d2ae587e0769b1c42ab0176a7982751fc9a740ae45fe1a592691f373dcc&scene=27#wechat_redirect) + +11、[连 Git 都玩不转,还写什么代码?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493645&idx=2&sn=d9408f63f9afccd28482e41efe2ba11e&chksm=e88588efdff201f9d3cc513591ad0c7b791616e8ca10a7b091038094b8b52eb1f2585c22e799#rd) + +12、[5 个 Git 工作流,改善你的开发流程](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494114&idx=2&sn=f75412a52b9c36e268decf013fffa6de&chksm=e8858900dff2001686dc51e3227a9565f7e97033539a1f2af3d9f38aad87b55a8b5d2ea6d405&scene=27#wechat_redirect) + +13、[提高国内访问 GitHub 的速度的 9 种方案](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247498432&idx=2&sn=d7f398a5598e9dd6636961387a64860f&chksm=e8859a22dff21334695d1495ead5adaf9a8102d1ba85bdfe0cd8b51fc6a8db08742bec95819e&scene=27#wechat_redirect) + + +### 6.3 数据库 + +1、[写给程序员的 MySQL 面试高频 100 问](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485321&idx=1&sn=30432df24d4e7858a475192bcf233914&scene=21#wechat_redirect) + +2、[开发人员必学的几点 SQL 优化点](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485892&idx=1&sn=e0b526002a5568391e75fb0cac60ab0b&chksm=e8866926dff1e0303f2717e95ff801c2550d97812c1a775cc232d48183af802db1be54f26105&token=2013245174&lang=zh_CN#rd) + +3、[再见,Navicat!同事安利的这个 PyCharm 的兄弟,真的香!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247490040&idx=1&sn=754ca33e3ddbde88ee1b7b918e89d39c&chksm=e886791adff1f00c3cd0ac513cae55ac3bbb2732c637433d15bf42c22139dd54ee47f399b492&scene=27#wechat_redirect) + +4、[太牛逼了!一款软件几乎可以操作所有的数据库!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492595&idx=1&sn=b83bab19f921bcd104caf3ed0f1cf0e3&chksm=e8858311dff20a070cd8063efbca76c74439b18f6c8863f3da14621afb082d246f204ccdba92&scene=27#wechat_redirect) + +5、[硬核!15张图解Redis为什么这么快](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494364&idx=2&sn=c1fcdfda4df97a61cf765f2b5ef1873d&chksm=e8858a3edff20328886dc88e78a2b6ea670825a3e4531d635a1bb5684671c293ac67fa079e68&scene=27#wechat_redirect) + +6、[败家玩意儿!Redis 竟然浪费了这么多内存!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494605&idx=2&sn=3e7c69fece14132d8c8df75cf282c19f&chksm=e8858b2fdff202393289d3aa73f5702ab53afb27758a64bfe4288e4489d68a896411fb33c7c2&scene=27#wechat_redirect) + +### 6.4 Chrome + +1、[推荐 8个 超实用的 Chrome 插件](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484925&idx=1&sn=110e4da78a20e8b5721f00bb36ba9d4c&scene=21#wechat_redirect) + +2、[没有这 42 款插件的Chrome是没有灵魂的](https://mp.weixin.qq.com/s?__biz=MzU4OTUwMDE1Mw==&mid=2247485016&idx=1&sn=ba38963413ee2926f6f5e69b1427491d&scene=21#wechat_redirect) + +### 6.5 Windows + +1、[没钱买 mac?一招教你如何让 Windows 秒变 macOS](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492484&idx=2&sn=d82c0faaf39c420729fba238c65d2fc8&chksm=e8858366dff20a70abbabb14693f265d7fdb1c831cd2b464c9cf1ce8431feb4f07cbb76627ec&scene=27#wechat_redirect) + +2、[微软太良心,这么强大的软件竟然完全免费!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491841&idx=1&sn=80c8c0247f9100e29f7066c874400755&chksm=e88581e3dff208f503da7dafdee037e8db578186dbef79df648c054f54c6e86b9336ff86bde3&scene=27#wechat_redirect) + +3、[双系统的日子结束了:Windows和Linux将合二为一](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491306&idx=1&sn=dfdbc7e02b54622c2eed5f36501444f0&chksm=e8867e08dff1f71e02038aa720fdd99c524adbc6687c2f32070af638b713a154f0f9767205cc&scene=27#wechat_redirect) + +4、[这个只有1.5M的软件,能让你的网速快3倍](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488856&idx=1&sn=8a96c373b04c4ce7d78c7f87f5928c1e&chksm=e88675badff1fcac0086cb2ec20845821d2441d0909b9a3395b249744217944b1fb8f3e442c9&scene=27#wechat_redirect) + +5、[原来,我一直都不会用Windows](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494412&idx=2&sn=044b47f18f70e5179c5e5c84cb6f4ec4&chksm=e8858beedff202f8728666709b385c476fe41c7d41ed1c63e40afd198db5fe27fbeed2c1639b&scene=27#wechat_redirect) + +6、[Chrome 和 Edge最大的威胁来了....](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247495227&idx=1&sn=0175723a1ee9b54d6d40010aa28447b3&chksm=e8858ed9dff207cfc51eef087c07d4f6ee1bd341937c6228605fe9281d5c80ab7e02a7d617f4&scene=27#wechat_redirect) + +### 6.6 其他工具 + +1、[整理了 11 个好用的代码质量审核和管理工具](https://mp.weixin.qq.com/s/DH_TOA3Cr3y37yZ5F4bU5A) + +2、[11 个最佳的 Python 编译器和解释器](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485682&idx=1&sn=31b1b68432ca1f1db3866fb0f670270b&chksm=e8866810dff1e106a21c63c1ee198069223047afc72482c1f14ee4f473211aca85273c57d529#rd) + +3、[太酷了!用上这 5 款神器后,你写的代码逼格瞬间爆表](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486248&idx=1&sn=ff17f64475d82e99d32e35f290a49edd&chksm=e8866bcadff1e2dc2ba61ca6a0f63fd753d60e77891ee0ae93207890ee891a9097a6d27b5695&scene=27#wechat_redirect) + +4、[我最喜欢的云 IDE 有哪些?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485965&idx=1&sn=3457ed667d64773bd83bdc3432c06dc7&chksm=e8866aefdff1e3f9407dce655688e2899c177c17a6472b0d50c15e2454cd6450165aee81877d&scene=27#wechat_redirect) + +5、[整理了6个好用的程序员开发在线工具](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489186&idx=2&sn=6099d58947654ddb35b43d7067d574d6&chksm=e8867640dff1ff56fb33df9d0de1ea820f14f3690d11184b1fcf02fa9480450a0b5639a754df&scene=27#wechat_redirect) + +6、[Github上这些可视化面板也太好看了吧](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488270&idx=1&sn=459867f1761d29e4a46f2e450e3ea975&chksm=e88673ecdff1fafaa0f1f89c9739b928e0227ac54059d4ff96c15faf8b88cd3752a929e018e1&scene=27#wechat_redirect) + +7、[腾讯终于良心了!桌面混乱终于有救了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492724&idx=1&sn=58cc2c03fffcbc87995a9927b6168ba7&chksm=e8858496dff20d80365246706c32bfebceb008f28cc04cb420cddd73cd50446495d02204099b&scene=27#wechat_redirect) + +8、[奇技淫巧:在 ssh 里面把服务器的文本复制到本地电脑](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493550&idx=2&sn=2619c1402e8951ff812c69994d922eb0&chksm=e885874cdff20e5adfcd9a95bf199cfcb73fbc7962c6de11c42240e3741eb5b5de75cc711649&token=58703854&lang=zh_CN#rd) + +9、[真神器!不用手写一行代码就能做网站~](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494412&idx=1&sn=6789d2aa73a05671c219db659d5ad739&chksm=e8858beedff202f880c3255210e7880bb7c56ad378a1f7b9b82f4e2f24126e4ef8ca7c435103&scene=27#wechat_redirect) + +10、[用 Python 使用 Google Colab?岂止是炫酷](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494533&idx=2&sn=58e2fd5fc63936d89853c5d550293d00&chksm=e8858b67dff2027179fd492d796d537bad57caf830e0aa3fbd51061cd91bd7c7f3f2ce56eb80&scene=27#wechat_redirect) + +11、[自从用了这个神器,我再也不想写代码了...](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247498473&idx=1&sn=448af801d90b29a69cb79b4089868f97&chksm=e8859a0bdff2131dd9fa0d6923fb8ae1de9e7311691a7558499cf995c0e4be8fd036031ee1c7&scene=27#wechat_redirect) + +12、[牛逼至极!用这个神器看代码太舒服了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497577&idx=1&sn=d0061deb47fa2c6441eb7dd11272af5d&chksm=e885978bdff21e9d4bc0a8747d9b2f6b04288095c7a019cfe1214a4ae382de657076313387bf&scene=27#wechat_redirect) + +## 07. 代码优化 + +### 7.1 算法讲解 + +1、[策略模式:商场促销活动背后的代码哲学](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484937&idx=1&sn=61b81dddfb20d80060fee5f22ab28d5f&scene=21#wechat_redirect) + +2、[算法教程|八张图带你轻松理解经典排序算法(上)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485042&idx=1&sn=b9e8503905be5a960119c2893995fb6d&scene=21#wechat_redirect) + +3、[算法教程|八张图带你轻松理解经典排序算法(中)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485041&idx=1&sn=12d05e0316c8866e3876c3ed484ced15&scene=21#wechat_redirect) + +4、[一次忘记密码引发的算法思考](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484981&idx=1&sn=96f49ab2225c61b45601b68521135dd6&scene=21#wechat_redirect) + +5、[程序员走楼梯都会思考的一道题](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484993&idx=1&sn=36cc1466ed73af2fcf4a8430368a62ee&scene=21#wechat_redirect) + +6、[以为是高性能神仙算法,一看源代码才发现...](https://mp.weixin.qq.com/s/L_OvCcpIFKBLckLBvit8UQ) + +7、[ 用Python手写十大经典排序算法](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485494&idx=1&sn=1580e9fc17086bc83e30b0fa4c850bd8&chksm=e88668d4dff1e1c27a26b31fda2f0e413be83519aa9dd0e3c8d3cfd08a2478eb2596ed7ba535#rd) + +### 7.2设计模式 + +1、[单例模式告诉你只能娶一个老婆](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484921&idx=1&sn=493d0a492277ecb223ddfff9de8720ff&scene=21#wechat_redirect) + +### 7.3 代码优化 + +1、[看了同事的代码,我忍不住写了这份代码指南](https://mp.weixin.qq.com/s/goqj1YVdKV171LLpjtXruQ) + +2、[怎样才能写好一个 Python 函数](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485416&idx=1&sn=85b14857e795a92985230ba3f51b73f6&chksm=e886670adff1ee1c7f4266d4e3b931d2e3d1de4dff30dc869eae2cd174da7f54080787f60a1b#rd) + +3、[三个异常处理的好习惯](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484947&idx=1&sn=2bd31279dd9714045ed4dc5481b44208&scene=21#wechat_redirect) + +4、[超实用的 30 段 Python 案例](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484866&idx=1&sn=9c85dd1b58f319bb0339e2db577a0be6&scene=21#wechat_redirect) + +5、[删除系统 Python 引发的惨案](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485386&idx=1&sn=59eed0894159f4d0599be3fb787b5201&chksm=e8866728dff1ee3ef9fb7a0464df481306be11d9aeba944804e7ea74e660501d42e159ada7fc#rd) + +6、[提速72倍,在Python里面调用Golang函数](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492536&idx=2&sn=360f13b4678fcc6a6f14ee6221474285&chksm=e885835adff20a4ca2025c926c754b9bf6accc6b5b7021f97878163491122ea97d2721c279f6&scene=27#wechat_redirect) + +7、[这一行代码,能让你的 Python运行速度提高100倍](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492321&idx=1&sn=87dc6b52a0c63b8326bcc50b2c7b3a68&chksm=e8858203dff20b15d1e4730e2851d7523c30db9b404fdfa5b1b19978a1e326e2205e3d6bf7ac&scene=27#wechat_redirect) + +8、[三行Python代码,让数据处理速度提高2到6倍](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491111&idx=2&sn=d27c6398b82749a20c46490b8fdd900f&chksm=e8867ec5dff1f7d3e9f95f221a2f33003bec76da1f0c002f97a59c7887cf460c887e1ad5a579&scene=27#wechat_redirect) + +9、[一文教你节省 90% 的内存占用](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489739&idx=1&sn=6589629f52a3a6ec18e67a3ca4952616&chksm=e8867829dff1f13fa87b08ecd09ce319dbd955c8ee15b44c60509e171f1920a6da600075dcd0&scene=27#wechat_redirect) + +10、[写出漂亮 Python 代码的 20条准则](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488402&idx=1&sn=231c2954b0ccca44a18268ab80ddbe88&chksm=e8867370dff1fa66a12d6af4adb66a1d80cbccbf9093c3a8b966a406bf5d8fc005a08166ef45&scene=27#wechat_redirect) + +11、[阅读优秀的项目代码,几点实用的经验分享](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247487922&idx=2&sn=c330d9b4c7bbc1b838e8a9fe90283c27&chksm=e8867150dff1f846628f181ff9687ebf91ba5d06f7721a67bf746698c6f02ea398cdc33c5a0d&scene=27#wechat_redirect) + +12、[一行 Python 代码实现并行](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247487299&idx=2&sn=5dffb95993b6fd87c6a3dd1a56b56814&chksm=e8866fa1dff1e6b78239ffa2fe8d124e4ee3af2b7b71f8e9593bdeae2221fcd2afa2b5773e26&scene=27#wechat_redirect) + +13、[代码被反编译了?这两个小技巧能帮到你](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247487287&idx=1&sn=05c7ca030257db25623e98ed5d302878&chksm=e8866fd5dff1e6c3219dc6d78717411f716bfa38d89a34ed64a88c0702765258fd34b4edd428&scene=27#wechat_redirect) + +14、[一份可以令 Python 变快的工具清单](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486107&idx=1&sn=83a3f95fea5cb2c24d7f44bf11f2acdb&chksm=e8866a79dff1e36ff4e6c8c546568bca0a36ea3de0550bd87a785ed9ce5cbda4a6d84b5b5fc9&scene=27#wechat_redirect) + +15、[记一次 Python Web 接口优化](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486053&idx=1&sn=862e6fbaa8a85a4a10ee35d9eba00196&chksm=e8866a87dff1e391399c252ffcb3168ef1f4c85d5ea52d6f43ceaf81e3f7cb3e548f6de505df&scene=27#wechat_redirect) + +16、[翻车了!pyc 文件居然曝光了我的密码](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247487730&idx=1&sn=eed309620be1092cf5af030be6b354ff&chksm=e8867010dff1f90611e155156075c2479bab5c9237e8a514a2c7ffe2a317ba16baa30b76d9c9&scene=27#wechat_redirect) + +17、[没有什么内存问题,是一行Python代码解决不了的](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492724&idx=2&sn=a84245d93d4191f157bac3e6a38d7066&chksm=e8858496dff20d808bb6ce5876bb0669a72722b6f90ec74f3b43de49ca1e07101c410138e113&scene=27#wechat_redirect) + + +## 08. 冷技巧集锦 + +### 8.1 冷知识 + +1、[Python那些不为人知的冷知识(一)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485031&idx=1&sn=e5ab670ce6485a50c4b7eeaee11e6f34&scene=21#wechat_redirect) + +2、[Python那些不为人知的冷知识(二)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485029&idx=1&sn=5db54b5777348e827c274cd932a15a15&scene=21#wechat_redirect) + +3、[Python那些不为人知的冷知识(三)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485009&idx=1&sn=92e268c20c6f01278e220e11397cc2f0&scene=21#wechat_redirect) + +4、[Python那些不为人知的冷知识(四)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485001&idx=1&sn=5a02f8c912518d15a0b96319cf2da7d1&scene=21#wechat_redirect) + +5、[Python那些不为人知的冷知识(五)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484997&idx=1&sn=5b8cf44b62550e1bd67284fb2b0780dc&scene=21#wechat_redirect) + +6、[Python那些不为人知的冷知识(六)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484990&idx=1&sn=bd28368eff832ba2b24a64f637a6d0c8&scene=21#wechat_redirect) + +7、[Python那些不为人知的冷知识(七)](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484874&idx=1&sn=abffab70b1e265ede1fd3b994dedab90&scene=21#wechat_redirect) + +8、[Python 之父为什么嫌弃 lambda 匿名函数?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492291&idx=2&sn=3cfdde7bc5e7b55aae00a30c63abe562&chksm=e8858221dff20b3719dfed632d181b95599b843006ae0c2186b5c69593ee7c22c5a5d2c82509&scene=27#wechat_redirect) + +9、[Python 到底是强类型语言,还是弱类型语言?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491532&idx=1&sn=a86bccc1d270390331c36205d3e46497&chksm=e8867f2edff1f6388d80289bff567445c2c9c9414efec74e4a308f7e8a1cabf662c8fc0a6cc0&scene=27#wechat_redirect) + +10、[Python 为什么不支持 i++ 自增语法,不提供 ++ 操作符?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489219&idx=2&sn=0dfa7ae7d4dcdda538b35bbea80b34e4&chksm=e8867621dff1ff372969bf3901835e67a1bfa7cb72709b491987fda3daa0e5f8d15a86c2b6b5&scene=27#wechat_redirect) + +11、[Python 为什么没有 main 函数?为什么我不推荐写 main 函数?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489175&idx=2&sn=2f8f9fb4b31c91ef71d1f34841da6450&chksm=e8867675dff1ff63e6e1f28eec9f18c41c30c050118eb65cde6960e5f6ee5866d7515f2b0040&scene=27#wechat_redirect) + +12、[Python 列表的这 8 个实用技巧,你都 OK 么?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489032&idx=2&sn=38d3985803cb5b6ed10e4cc11972eff7&chksm=e88676eadff1fffc88a3a3a2e3815b2abff43318c597344857c9c5f7806b6b0e6c457b33842d&scene=27#wechat_redirect) + +13、[Python 为什么不用分号作终止符?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488816&idx=2&sn=6bc8aa32d9a266cbffabcd87664e75fd&chksm=e88675d2dff1fcc4e845a90903bda5dfe59262a2b60533045a03e574076e92aa6f30974a73f5&scene=27#wechat_redirect) + +14、[Python 为什么推荐蛇形命名法?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488517&idx=1&sn=8b449c2d7c831600be6c5d57e9cb0837&chksm=e88674e7dff1fdf1ab8092ac3cdd2f3978ee6b219daa18a5407c390f62e11448c39455437bb0&scene=27#wechat_redirect) + +15、[Python 为什么用 # 号作注释符?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489657&idx=1&sn=820a070f05096dbe2bdb979fc9492cdb&chksm=e886789bdff1f18d420ee3efa8f85468303690232c4005f775191b0a84a1921430e37aa7e74f&scene=27#wechat_redirect) + +16、[!/usr/bin/python与#!/usr/bin/env python的区别](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486008&idx=2&sn=8637cdc12799f084cd5ecdba9534fb76&chksm=e8866adadff1e3cc49b369dddfaeecc1d9b51f13de1f2733266b2f9fc8426d9e3944a15eb074&scene=27#wechat_redirect) + +17、[pip install 和conda install有什么区别吗?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247487164&idx=2&sn=18de23de9c79f3c20e5a432bb675c262&chksm=e8866e5edff1e748cb6c83d2f4368cbab805fd7bfd41820b60da22061818e8d84548ac14714c&scene=27#wechat_redirect) + +18、[Python 什么情况下会生成 pyc 文件?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486071&idx=2&sn=533257b9b6156bd5588199b349266a3d&chksm=e8866a95dff1e383991b311dc73994ca103c380433a620c5bdf9f8d09b1c49daa74dce6ea941&scene=27#wechat_redirect) + + +### 8.2 冷技巧 + +1、[让Python中类的属性具有惰性求值的能力](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485759&idx=2&sn=e32b66c4666f96f84572738549a47a24&chksm=e88669dddff1e0cb0a4b6e6e965c9570b273236fa58a54351ae3b118d6a4bcbd52e452109a63&token=1148998814&lang=zh_CN#rd) + +2、[ 小技巧:如何在 Python 中实现延迟调用](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485689&idx=2&sn=43e35ff93918ef090480672d4685bce3&chksm=e886681bdff1e10dd0edee95c73a977da51fdeb514dcf8c3bb88f7f9aacc22ce155f45e84268#rd) + +3、[整理了 18个 Python 高效编程技巧](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491418&idx=1&sn=89c35f5d69a54196bd7f32a64171e05d&chksm=e8867fb8dff1f6aee18414c89c31ce118550ba11b645e2e4f6014af4d15d319decc000a70c91&scene=27#wechat_redirect) + +4、[Python 程序报错崩溃后,如何倒回到崩溃的位置?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488434&idx=1&sn=e2b4ca12b228c16e944ff36abec53e22&chksm=e8867350dff1fa46ee7799e460d2b304dbb0c227d33a39d18099761c205319d99a9b4135f9fa&scene=27#wechat_redirect) + +5、[如何用简单的位操作实现高级算法](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247487151&idx=1&sn=5376f42c8990027132deb52a6b66307e&chksm=e8866e4ddff1e75b3af85905177130d23118254d42e9452930cc784b209cdf294d9bb73aa247&scene=27#wechat_redirect) + +6、[如何限定Python函数只能被特定函数调用](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247490777&idx=2&sn=6572f957117e0a0256da2b85c7221a37&chksm=e8867c3bdff1f52d045cadb962a2da16b015d8455147afe374cf3067dd89c580e1f9514d57d0&scene=27#wechat_redirect) + +7、[pylint 除了检查代码风格,居然还能...](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491737&idx=2&sn=f6781d158c5af171f1b916ee7b0c7a68&chksm=e885807bdff2096dc1580abbba594ed1cc1c0994c06f6bd5ede233df0593a43842f7af3e2f8b&scene=27#wechat_redirect) + +8、[让Python在退出时强制运行一段代码](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486207&idx=2&sn=5586a204b9537d37c02b9926a01719dc&chksm=e8866a1ddff1e30bb77d72ba0013d870f80e0029546729f0e8c65512c4969f5f0733f60ecddf&scene=27#wechat_redirect) + +9、[不使用 if-elif 语句,如何优雅地判断某个数字所属的等级?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486167&idx=2&sn=a31cbf6d3526bfc860b0daa69889193f&chksm=e8866a35dff1e323ed958858223dda1af6ae0d371be0037c35f9ae6894e776dec1ee53c2a00b&scene=27#wechat_redirect) + +10、[涨姿势了,raise...from... 是个什么操作?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486001&idx=1&sn=b9a89305dae7d4f57105be1d274fae43&chksm=e8866ad3dff1e3c51b5fa132147b9f9c9e4ba14b41c5409e62e2f2696d1389c6ac4ddd1e7bec&scene=27#wechat_redirect) + +11、[一些我日常使用的 Python 技巧分享](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488382&idx=2&sn=f2b090fe47bb56e0463126c69726bf10&chksm=e886739cdff1fa8a65ce4869a8bdb8fbd28396e3fbcdac2a4441b7c58ba5c77cea1765858146&scene=27#wechat_redirect) + +12、[5年 Python 功力,总结了 10 个开发技巧](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488243&idx=1&sn=66d2f534ddcbed582e7ba734b53701f5&chksm=e8867211dff1fb07f2edcebfda9e7863ee57266c15d4276bc89c2ee69baafc46fbc0e85fe703&scene=27#wechat_redirect) + +13、[我发现了个 Python 黑魔法,执行任意代码都会自动念上一段 『平安经』](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247490548&idx=1&sn=c71772cc40992d8912fd8a3fa1607038&chksm=e8867b16dff1f20081431362c99fb981d0cd75f2bd5baf981b7db18e08492138aab10f98efb8&scene=27#wechat_redirect) + +14、[实用技巧分享:如何批量更新已安装的库?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247487862&idx=2&sn=a1c092467b471db82060b395c341be6c&chksm=e8867194dff1f882da87863f4d4a4ccbd687daa0b4a742dc6d01fd01d0a6ca6c5fb7cc28629b&scene=27#wechat_redirect) + +15、[如何导入父文件夹中的模块并读取当前文件夹内的资源](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493878&idx=2&sn=36c70addd7c0c0640d1285ab590410e4&chksm=e8858814dff201026397c7b08034ad513c4b9e5dcf8307325951ae4077e386f87f5685ca528f#rd) + +16、[用 Python 读取资源文件?这个技巧保你涨姿势](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494041&idx=2&sn=3b3a43157290f0ff542185982aa4b537&chksm=e885897bdff2006dd634e39ccc3c753704ad0f74e2fec95249d0d7f0c30bee85426ef86028e0#rd) + +### 8.3 炫技操作 + +1、[Python 炫技操作(01):条件语句的七种写法](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485991&idx=1&sn=98e17f91d2f66f62c9aa644c03d8259d&chksm=e8866ac5dff1e3d3f6810a3f9e388d46d95945af9748baea0380ecec83c768eaac09738cf959&scene=27#wechat_redirect) + + +2、[Python 炫技操作(02):合并字典的七种方法](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486080&idx=1&sn=f1c5c4fc5363a1d787b9ae9baba0d07b&chksm=e8866a62dff1e374ad1e5ae2e51bc6cbeb41f631899cde980555ded61be840f0fe6c76c44b7d&scene=27#wechat_redirect) + +3、[Python 炫技操作(03):连接列表的八种方法](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486132&idx=1&sn=3827cf8672d4121b77225dbf9d377d69&chksm=e8866a56dff1e34094f2f834a613800480c0cdb078ab5656640fcb8c445ffa020b175b0f55cb&scene=27#wechat_redirect) + +4、[Python 炫技操作(04):海象运算符的三种用法](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486158&idx=1&sn=0bd0647702a1599082e5bf1710d89e37&chksm=e8866a2cdff1e33ab4465d88497ea3505ad8fe614365eec7592a8c75053a6c8218206807c1a3&scene=27#wechat_redirect) + +5、[Python 炫技操作(05):花式导包的八种方法](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486799&idx=1&sn=1be136d4e45c1b6f8a5eda567aaf259d&chksm=e8866daddff1e4bbddc0164ae795d6c302e36226cb3ba76ffc57e5c993b0861ef4ad693c2a56&scene=27#wechat_redirect) + +6、[Python 炫技操作(06):判断是否包含子串的七种方法](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491171&idx=2&sn=4596043fb72b75a04a778942c61cc2af&chksm=e8867e81dff1f7979e21f58716b3ce3e09f8515829b15acd5169dd3f160e302d617a1b94cb2d&scene=27#wechat_redirect) + +7、[Python 炫技操作(07):模块重载的五种方法](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247492817&idx=1&sn=cfb52d1a3f88a61e7b22a63306dac0e9&chksm=e8858433dff20d25f06ac0b5b767121907a4679b9e6da0905694d15c432ba596ce7b202ec7bb&scene=27#wechat_redirect) + +8、[Python 炫技操作(08):五种 Python 转义表示法](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247494334&idx=1&sn=9f55122545b7b5d81049af27eff7800c&chksm=e8858a5cdff2034a8158b14669aaf695656c1227428ce86f22b19230769b5b45104b0a885205&scene=27#wechat_redirect) + +9、[最全总结:把模块当做脚本来执行的 7 种案例及其原理](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247490904&idx=1&sn=ca3725510c7510965cbc76bd1bf06949&chksm=e8867dbadff1f4acb08c0daf08272ca61757909b0b73a4cde1aa4d86965c149c40f44417f7d0&scene=27#wechat_redirect) + +10、[这个 Python 炫技操作千万不要用,别问我怎么知道的?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491171&idx=1&sn=27d55a4b8b717450f1ab0596263f453f&chksm=e8867e81dff1f7975674ab7fcc0019654ae0e867db045fb575623f91cb143801d03aa365be2d&scene=27#wechat_redirect) + +11、[涨见识了,在终端执行 Python 代码的 6 种方式](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488283&idx=1&sn=24a78834ec3434a90ca7c3e6e972495c&chksm=e88673f9dff1faef908c43a41133f65695a68579e0edb2d7b15f131d9be26bcf919d66a7d9e3&scene=27#wechat_redirect) + +12、[Python 炫技操作:推导式的五种写法](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496358&idx=2&sn=1d4c4463663f546b5768945ce31598f7&chksm=e8859244dff21b52cd0dce2ca366782ea14bf194f66498b07b6125426cc324c21a13be5abd3a&scene=27#wechat_redirect) + +13、[Python 炫技操作:安装包的八种方法](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247495287&idx=1&sn=1eb6f14782f17a552320b3d6af5e17f3&chksm=e8858e95dff207836d575464ccc2f1be06b8fa824dcd1589613fe8d6ca48ebb4578f57378858&scene=27#wechat_redirect) + + + + +## 9. 云计算 + +1、[一份面向初学者的云计算通识指南](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484908&idx=1&sn=3085e048da685440408e1bdc54feb4aa&scene=21#wechat_redirect) + +2、[ 如何探测虚拟环境是物理机、虚拟机还是容器?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485401&idx=2&sn=8bfb6e1a71e0777a4d5e55f64b55ace5&chksm=e886673bdff1ee2d8acce291e402cd2ae0c7f64e455fdeea158eb53e535ee79b2aadc449935e#rd) + +3、[超详细教你如何阅读 OpenStack 源码?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485899&idx=1&sn=7a578a553c67e794ef6ec2f463864a46&chksm=e8866929dff1e03fa8152751967106e9262980db6afdff106fe9e39854d24d25494b3e8a3a4e&token=2013245174&lang=zh_CN#rd) + +## 10. 职场相关 + +1、[一个专科生的 Python 转行之路](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485012&idx=1&sn=751796e63a30d84be01486619b5fb806&scene=21#wechat_redirect) + +2、[一个机械生的Python转行自述](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484979&idx=1&sn=6513e940bc7c0677dedf7efff80aa4c6&scene=21#wechat_redirect) + +3、[自学 Python后端开发 到什么程度可以找工作?](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485010&idx=1&sn=e76d031f91633f9bfde9da36d8dcf996&scene=21#wechat_redirect) + +4、[工作不是游戏,写给编程新人的五点建议](https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247484984&idx=1&sn=0934415cc48004ae76345dcfb8e33b94&scene=21#wechat_redirect) + +5、[Python 从业十年是种什么体验?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485601&idx=1&sn=0dbebc02002ab01a8cd42265822ff81c&chksm=e8866843dff1e15509f2a9d2cd551b2360607cf88e73e5d3036388716ee57949d726dcea209c#rd) + +6、[40条提升编程技能的小妙招](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489765&idx=2&sn=79287da847c25ce0d72db6a33eb0c5a0&chksm=e8867807dff1f111043fe22bbfc776a52331c28abf85c2f658cbbaba3235c4e9d3c070c44d8c&scene=27#wechat_redirect) + +7、[我,一个靠GitHub打赏谋生的码农,年入十万美元](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247488934&idx=1&sn=56f51b946908ed89a58b311fc77f47d6&chksm=e8867544dff1fc52e30288685c89e86cefd063d5d37f5b1aba5fb30fd3665cf18346533cad96&scene=27#wechat_redirect) + +8、[5 年 Python 的我,总结了这 90 条写 Python 程序的建议](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247487323&idx=1&sn=1b6594d63319faaadefad1f5e178235f&chksm=e8866fb9dff1e6af732304c8f3645cecca8b4bfa4158e45b0ea6c5167c2675bd748ce23e8239&scene=27#wechat_redirect) + +9、[Python这么慢,为啥大公司还在用?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489132&idx=1&sn=55dda8a6a10429b3a7016393bc058493&chksm=e886768edff1ff981d67b2ecfe52ebf5b8dbc0085289e6bd3f8a6c6631ee6fc4a633fb6bc4b8&scene=27#wechat_redirect) + +10、[一个中科大差生的 8年 程序员工作总结](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497523&idx=1&sn=725c1167873927aea519f690f3c106ec&chksm=e88597d1dff21ec709eeba54a9fb35318afcac3cb3b235e0ab831fd40f9917dc2acb40d1bbb3&scene=27#wechat_redirect) + +## 11. 通用文章 + +1、[假如有人把支付宝存储服务器炸了,你的存款会怎样?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247485171&idx=1&sn=d6e2e24f68f3c6eb35e880f32e12d4ab&chksm=e8866611dff1ef0791cf5aae05697592cb804010aecd783a8592f7a90a387645fe4b47a376ea&scene=27#wechat_redirect) + +2、[手机没网了,却还能支付,这是什么原理?](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493296&idx=1&sn=8dae2411c61b7e5ab4a1fcdf45b86c79&chksm=e8858652dff20f44519c328ba22b4f22c8b2320bc1464319e98d6084697dfab3ef2346a5cf49&scene=27#wechat_redirect) + +3、[Chrome 的小恐龙游戏,被我破解了...](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491911&idx=1&sn=1dcab055e480fe626d50b0324ed5b9f1&chksm=e88581a5dff208b3fbf88017c15ccfa966eec3b25e4804a72401773d7b87d5b6a2bcd8db9ac7&scene=27#wechat_redirect) + +4、[深扒微信多开的秘密后,我竟然发现了个 bug](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247489704&idx=1&sn=a33559f22517c744367a660f78dbb25a&chksm=e886784adff1f15c1524f90487d6957c86dee0f5c499528630f43b62320b28e66977afe4d884&scene=27#wechat_redirect) + +5、[让许多 Python “老玩家”心寒的 10 大槽点](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497032&idx=1&sn=0347edefbb9fc47d13c58379130aa327&chksm=e88595aadff21cbc3a6c8ad6752a75ce708244ed517fd9a3230efa2eb783927033977ba26b82&scene=27#wechat_redirect) + +6、[别瞎学了,这几门语言要被淘汰了!](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247496522&idx=1&sn=1aaa60b8295378cfcbeaaaf528b13df0&chksm=e88593a8dff21abe290ee23821ed9cebb2aa68148548852319363b4de4663d0a5ab646451e5e&scene=27#wechat_redirect) + +7、[是的,Python是慢,但我不在乎](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247497752&idx=1&sn=0d207936a803b414b04d13bb167124ba&chksm=e88598fadff211ecd77676506b5f039c0fbd8bd32eb5f68df2c41a277526304dc89f3d6f7dad&scene=27#wechat_redirect) + +8、[当今全球最厉害的14位程序员,说没听过简直离谱~](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247498702&idx=1&sn=8b5a405de0649de1bf52235956840af7&chksm=e8859b2cdff2123a2f6168fb846781f2ba678ac4b70fd01513c2547b14b4d1a053ca0b67e5f6&scene=27#wechat_redirect) + +## 12. 明哥的作品 + +1、[太赞了!《Python 黑魔法指南》终于面世了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247486834&idx=1&sn=f5b94c3a520624786162f78246e60246&chksm=e8866d90dff1e486a3dae97aaf347e83834c8cf204849e5f9ae23dc9fdf0c470f97e0298cf74&scene=27#wechat_redirect) + +2、[《Python黑魔法指南》全新版本 v2.0 上线发布](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247490543&idx=1&sn=449a1c7adfafdd5cf37874ed67620e89&chksm=e8867b0ddff1f21b9d622ba7a53b35143cd7fbb3da0d7c091b3d2cdd71d817a4397a99fa424e&scene=27#wechat_redirect) + +3、[明哥写了两个月,这 200页《PyCharm 中文指南》 终于可以发布了](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491716&idx=1&sn=76a9f3ad5163a9ffdbaf0fefd0259261&chksm=e8858066dff20970fa9988675154fff6a6f84793a80b8ea1d6fe5d5bbb5bc816d2feabc50664#rd) + +4、[一个明哥真正意义上的个人网站,现在来啦~](http://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247493207&idx=1&sn=ced486f99dc7d9ab665849da1016ceb1&chksm=e88586b5dff20fa32db6f3074ee954cbe30b34846c5852d8772184a41e9ad58293947e22095d&scene=27#wechat_redirect) + -这是我的个人博客( [MING's BLOG](http://python-online.cn/) ),主要写关于Python的一些思考总结。 - -关于搭建教程,感兴趣的可以查看这边:[Sphinx 搭建博客的图文教程](https://github.com/BingmingWong/MING-BLOG/blob/master/source/c04/c04_03.rst) - -# 博客目录: - -## 第一章:基础知识 -- 1.1 [13条Python2.x和3.x的区别?](http://python-online.cn/zh_CN/latest/c01/c01_01.html) -- 1.2 [Python的自省机制](http://python-online.cn/zh_CN/latest/c01/c01_02.html) -- 1.3 [谈谈深贝和浅拷贝的区别](http://python-online.cn/zh_CN/latest/c01/c01_03.html) -- 1.4 [什么是猴子补丁?](http://python-online.cn/zh_CN/latest/c01/c01_04.html) -- 1.5 [深入理解闭包与变量作用域](http://python-online.cn/zh_CN/latest/c01/c01_05.html) -- 1.6 [深入理解元组存在的意义](http://python-online.cn/zh_CN/latest/c01/c01_07.html) -- 1.7 [15个Pythonic的代码示例](https://python-online.cn/zh_CN/latest/c01/c01_06.html) -- 1.8 [新式类和经典类的区别?](https://python-online.cn/zh_CN/latest/c01/c01_08.html) -- 1.9 [多继承与Mixin设计模式](https://python-online.cn/zh_CN/latest/c01/c01_09.html) -- 1.10 [盘点 Python 中那些冷知识](https://python-online.cn/zh_CN/latest/c01/c01_10.html) -- 1.11 [正则表达式必知必会](http://python-online.cn/zh_CN/latest/c01/c01_11.html) -- 1.12 [搞懂字符编码的前世今生](http://python-online.cn/zh_CN/latest/c01/c01_12.html) -- 1.13 [Python几个高阶函数](http://python-online.cn/zh_CN/latest/c01/c01_13.html) -- 1.14 [with 与 上下文管理器](http://python-online.cn/zh_CN/latest/c01/c01_14.html) -- 1.15 [提升Python性能的7个习惯](http://python-online.cn/zh_CN/latest/c01/c01_15.html) -- 1.16 [泛型函数怎么写?](http://python-online.cn/zh_CN/latest/c01/c01_16.html) -- 1.17 [深入理解「描述符」](http://python-online.cn/zh_CN/latest/c01/c01_17.html) -- 1.18 [MySQL使用总结](http://python-online.cn/zh_CN/latest/c01/c01_18.html) -- 1.19 [MySQL 使用总结](http://python-online.cn/zh_CN/latest/c01/c01_18.html) -- 1.20 [静态方法其实暗藏玄机](http://python-online.cn/zh_CN/latest/c01/c01_20.html) -- 1.21 [开发小技巧](http://python-online.cn/zh_CN/latest/c01/c01_21.html) - -## 第二章:并发编程 -- 2.1 [从性能角度来初探并发编程](http://python-online.cn/zh_CN/latest/c02/c02_01.html) -- 2.2 [创建多线程的几种方法](http://python-online.cn/zh_CN/latest/c02/c02_02.html) -- 2.3 [谈谈线程中的“锁机制”](http://python-online.cn/zh_CN/latest/c02/c02_03.html) -- 2.4 [线程消息通信机制任务协调](http://python-online.cn/zh_CN/latest/c02/c02_04.html) -- 2.5 [线程中的信息隔离](http://python-online.cn/zh_CN/latest/c02/c02_05.html) -- 2.6 [消息队列补充及如何创建线程池](http://python-online.cn/zh_CN/latest/c02/c02_06.html) -- 2.7 [从生成器使用入门协程](http://python-online.cn/zh_CN/latest/c02/c02_07.html) -- 2.8 [深入理解yield from语法](http://python-online.cn/zh_CN/latest/c02/c02_08.html) -- 2.9 [初识异步IO框架:asyncio 上篇](http://python-online.cn/zh_CN/latest/c02/c02_09.html) -- 2.10 [学习异步IO框架:asyncio 中篇](http://python-online.cn/zh_CN/latest/c02/c02_10.html) -- 2.11 [实战异步IO框架:asyncio 下篇](http://python-online.cn/zh_CN/latest/c02/c02_11.html) -- 2.12 [生成器与协程,你分清了吗?](http://python-online.cn/zh_CN/latest/c02/c02_12.html) - -## 第三章:高级编程 -- 3.1 [装饰器从入门到高阶](http://python-online.cn/zh_CN/latest/c02/c03_01.html) -- 3.2 [学会使用元类定制类](http://python-online.cn/zh_CN/latest/c02/c03_02.html) -- 3.3 [学会使用socket网络编程](http://python-online.cn/zh_CN/latest/c02/c03_03.html) -- 3.4 [Django+Uwsgi部署网站](http://python-online.cn/zh_CN/latest/c03/c03_04.html) -- 3.5 [源码解读:Flask上下文与代理模式](http://python-online.cn/zh_CN/latest/c03/c03_05.html) -- 3.6 [Web开发者必看:理解WSGI](http://python-online.cn/zh_CN/latest/c03/c03_06.html) - -## 第四章:开发工具 -- 4.1 [虚拟环境的搭建与使用](http://python-online.cn/zh_CN/latest/c02/c04_01.html) -- 4.2 [Xshell的高效使用手册](http://python-online.cn/zh_CN/latest/c02/c04_02.html) -- 4.3 [30分钟教你搭建顔值超高的博客](http://python-online.cn/zh_CN/latest/c02/c04_03.html) -- 4.4 [Jupyter NoteBook 的使用指南](https://python-online.cn/zh_CN/latest/c04/c04_04.html) -- 4.5 [Win10 + Ubuntu 双系统安装指南](https://python-online.cn/zh_CN/latest/c04/c04_05.html) -- 4.6 [我的 Git 使用指南](http://python-online.cn/zh_CN/latest/c04/c04_06.html) -- 4.7 [ Hexo 搭建博客教程](http://python-online.cn/zh_CN/latest/c04/c04_07.html) -- 4.8[珍惜生命,远离鼠标](http://python-online.cn/zh_CN/latest/c04/c04_08.html) -- 4.9 [MySQL的基本使用](http://python-online.cn/zh_CN/latest/c04/c04_09.html) -- 4.10 [MySQL的高级进阶](http://python-online.cn/zh_CN/latest/c04/c04_10.html) -- 4.11 [不能不会的远程调试技巧](http://python-online.cn/zh_CN/latest/c04/c04_11.html) -- 4.12 [服务器调试神器:pdb](http://python-online.cn/zh_CN/latest/c04/c04_12.html) -- 4.13 [命令行解析工具:argparse](http://python-online.cn/zh_CN/latest/c04/c04_13.html) -- 4.14 [虚拟环境:Pipenv](http://python-online.cn/zh_CN/latest/c04/c04_14.html) -- 4.15 [15个 PyCharm 小技巧](http://python-online.cn/zh_CN/latest/c04/c04_15.html) -- 4.16 [Python 开发技巧集合](http://python-online.cn/zh_CN/latest/c04/c04_16.html) -- 4.17 [Python 实现 23 种设计模式](http://python-online.cn/zh_CN/latest/c04/c04_17.html) -- 4.18 [Mac 高效工具](http://python-online.cn/zh_CN/latest/c04/c04_18.html) -- 4.19 [程序员编码必学:Vim](http://python-online.cn/zh_CN/latest/c04/c04_19.html) - -## 第五章:算法教程 -- 5.1 [图解九大经典排序算法](http://python-online.cn/zh_CN/latest/c02/c05_01.html) -- 5.2 [递归算法:走楼梯会思考的题](http://python-online.cn/zh_CN/latest/c04/c04_18.html) -- 5.3 [哈希算法:安全方面的算法](http://python-online.cn/zh_CN/latest/c04/c04_18.html) - -## 第六章:数据分析 -- 6.1 [一张图带你入门matplotlib](https://python-online.cn/zh_CN/latest/c06/c06_01.html) -- 6.2 [详解六种可视化图表](https://python-online.cn/zh_CN/latest/c06/c06_02.html) -- 6.3 [如何绘制正余弦函数图象](https://python-online.cn/zh_CN/latest/c06/c06_03.html) -- 6.4 [子图与子区 难点突破](https://python-online.cn/zh_CN/latest/c06/c06_04.html) -- 6.5 [绘制酷炫的gif动图](http://python-online.cn/zh_CN/latest/c06/c06_05.html) -- 6.6 [自动生成图像视频](http://python-online.cn/zh_CN/latest/c06/c06_06.html) - -## 第七章:运维人生 - -- 7.1 [Linux 命令行的艺术](http://python-online.cn/zh_CN/latest/c07/c07_01.html) -- 7.2 [Zabbix 监控部署文档](http://python-online.cn/zh_CN/latest/c07/c07_02.html) -- 7.3 [Docker:Hello world](http://python-online.cn/zh_CN/latest/c07/c07_03.html) -- 7.4 [Docker:关于镜像](http://python-online.cn/zh_CN/latest/c07/c07_04.html) -- 7.5 [Docker:网络通信](http://python-online.cn/zh_CN/latest/c07/c07_05.html) -- 7.6 [Docker:存储与多主机](http://python-online.cn/zh_CN/latest/c07/c07_06.html) -- 7.7 [SaltStack 入门指南](http://python-online.cn/zh_CN/latest/c07/c07_07.html) -- 7.8 [Keepalived 部署文档](http://python-online.cn/zh_CN/latest/c07/c07_08.html) -- 7.9 [Ansible使用总结](http://python-online.cn/zh_CN/latest/c07/c07_09.html) -- 7.10 [Ansible API 最全使用文档(中文)](http://python-online.cn/zh_CN/latest/c07/c07_10.html) - -## 第八章:OpenStack - -- 8.1 [OpenStack 运维命令](http://python-online.cn/zh_CN/latest/c08/c08_01.html) -- 8.2 [OpenStack 部署SR-IOV](http://python-online.cn/zh_CN/latest/c08/c08_02.html) -- 8.3 [制作 OpenStack 镜像](http://python-online.cn/zh_CN/latest/c08/c08_03.html) -- 8.4 [虚拟化入门概念](http://python-online.cn/zh_CN/latest/c08/c08_04.html) -- 8.5 [OpenStack 源码剖析](http://python-online.cn/zh_CN/latest/c08/c08_05.html) -- 8.6 [深度解读Cloud-init源码](http://python-online.cn/zh_CN/latest/c08/c08_06.html) -- 8.7 [OpenStack 实现GPU直通](http://python-online.cn/zh_CN/latest/c08/c08_07.html) -- 8.8 [OpenStack 如何使用DHCP?](http://python-online.cn/zh_CN/latest/c08/c08_08.html) -- 8.9 [全面理解RPC远程调用](http://python-online.cn/zh_CN/latest/c08/c08_09.html) -- 8.11 [OpenStack问题排查](http://python-online.cn/zh_CN/latest/c08/c08_11.html) -- 8.12 [OpenStack之主机调度](http://python-online.cn/zh_CN/latest/c08/c08_12.html) -- 8.13 [网络知识必知必会](http://python-online.cn/zh_CN/latest/c08/c08_13.html) -- 8.14 [OpenStack 支持 ipv6](http://python-online.cn/zh_CN/latest/c08/c08_14.html) - -## LeetCode Challenge - -- [NO.1-10](http://python-online.cn/zh_CN/latest/lc01/1-10.html) --- -![关注公众号,获取最新干货!](http://image.python-online.cn/20190511161447.png) + + + +都看到这儿了,还不点个关注嘛? `*^_^*` + +![](http://image.iswbm.com/20201024132326.png) + +## 欢迎交流 + +对文章有什么疑问,对项目有什么建议,可以添加微信与我交流,同时欢迎关注我的个人微信公众号。 + +![](http://image.iswbm.com/image-20201117215520960.png) + + diff --git a/exts/smallseg.py b/exts/smallseg.py index ad96da2..06dd1a1 100644 --- a/exts/smallseg.py +++ b/exts/smallseg.py @@ -19,15 +19,15 @@ def __init__(self): with open(os.path.join(curpath, "main.dic")) as in_file: self.set([x.rstrip() for x in in_file]) with open(os.path.join(curpath,"suffix.dic")) as in_file: - self.specialwords= set([x.rstrip().decode('utf-8') for x in in_file]) + self.specialwords= set([x.rstrip() for x in in_file]) print('dict ok.', file=sys.stderr) + #set dictionary(a list) def set(self,keywords): p = self.d q = {} k = '' for word in keywords: - word = (chr(11)+word).decode('utf-8') if len(word)>5: continue p = self.d @@ -149,3 +149,5 @@ def cut(self,text): else: recognised.extend(self._pro_unreg(text[i-j:z])) return recognised + +SEG() diff --git a/github-toc-maker-for-sphinx.py b/github-toc-maker-for-sphinx.py new file mode 100644 index 0000000..49f3f5c --- /dev/null +++ b/github-toc-maker-for-sphinx.py @@ -0,0 +1,71 @@ +import os +import re +from glob import glob + +pwd = os.getcwd() +all_chapters_path = glob(pwd + "/source/c0*") + + +def get_chapter_name(file): + with open(file) as f: + f.readline() + chapter_name = f.readline().strip() + + return chapter_name + +def get_title(file): + with open(file) as f: + first_line = f.readline() + + if first_line.startswith("#"): + return first_line[1:].strip() + +def generate_mapping(): + mapping = dict.fromkeys([os.path.basename(chapter_path) for chapter_path in all_chapters_path]) + for key in mapping.keys(): + chapter_file = os.path.join(pwd, "source", "chapters", key.replace("c", "p") + ".rst") + mapping[key] = get_chapter_name(chapter_file) + + return mapping + +def get_toc_info(): + toc = {} + for dir_path in all_chapters_path: + dir_name = os.path.basename(dir_path) + + chapter_toc = {} + files = glob(dir_path + "/*.md") + + for file in files: + file_name = os.path.basename(file) + section = int(re.findall(r"c\d{2}_(\d{2}).md", file_name)[0]) + + #md_path = os.path.join("./source/", dir_name, file_name) + md_path = os.path.join("http://pythontime.iswbm.com/en/latest/", dir_name, file_name.replace("md", "html")) + title = get_title(file) + if not title: + continue + + chapter_toc[section] = (title, md_path) + + toc[dir_name] = chapter_toc + + return toc + +def print_md_toc(toc_info, mapping): + for chapter in sorted(toc_info.items(), key=lambda item: item[0]): + posts = chapter[1] + chapter_name = mapping[chapter[0]] + print(f"- **{chapter_name}**") + for post in sorted(posts.items(), key=lambda item:item[0]): + # print title only + # print(f"{post[1][0]}") + print(" ", f"* [{post[1][0]}]({post[1][1]})") + +def main(): + mapping = generate_mapping() + toc_info = get_toc_info() + print_md_toc(toc_info, mapping) + +if __name__ == '__main__': + main() diff --git a/md2rst.py b/md2rst.py index 07fb79c..51a7a32 100644 --- a/md2rst.py +++ b/md2rst.py @@ -1,35 +1,149 @@ # coding:utf-8 import os -import commands +# import commands import subprocess +import platform +from git import Repo -blog_path = '/Users/MING/Github/PythonCodingTime/source' - -file_list = os.listdir(blog_path) - -dir_list = [] -for item in file_list: - abs_path = os.path.join(blog_path, item) - if os.path.isdir(abs_path): - dir_list.append(abs_path) - -for folder in dir_list: - os.chdir(folder) - print('==== Processing folder {}'.format(folder)) - all_file = os.listdir(folder) - all_md_file = [file for file in all_file if file.endswith('md')] - for file in all_md_file: - (filename, extension) = os.path.splitext(file) - convert_cmd = 'pandoc -V mainfont="SimSun" -f markdown -t rst {md_file} -o {rst_file}'.format( - md_file=filename+'.md', rst_file=filename+'.rst' - ) - status, output = commands.getstatusoutput(convert_cmd) - #retcode = subprocess.call(convert_cmd) - if status != 0: - print(output) - if status == 0: - print(file + ' 处理完成') - else: - print(file + '处理失败') +osName = platform.system() +repo_path ='.' +if (osName == 'Windows'): + repo_path = 'E:\\MING-Git\\PythonCodingTime' + blog_path = 'E:\\MING-Git\\PythonCodingTime\\source' + index_path = 'E:\\MING-Git\\PythonCodingTime\\README.md' +elif (osName == 'Darwin'): + repo_path = '/Users/MING/Github/PythonCodingTime/' + blog_path = '/Users/MING/Github/PythonCodingTime/source' + index_path = '/Users/MING/Github/PythonCodingTime/README.md' + + +repo = Repo.init(path=repo_path) +if not repo.is_dirty(): + # 没有文件变更 + os._exit(0) + +base_link = "http://pythontime.iswbm.com/en/latest/" +readme_header = ''' +![](http://image.iswbm.com/20200607120940.png) + +

+ Build Status + + + + +

+ +## [项目主页](http://pythontime.iswbm.com/) + +在线阅读:[Python 编程时光](http://pythontime.iswbm.com/) + +![](http://image.iswbm.com/20200607130051.png) + +## 文章结构 + +![](http://image.iswbm.com/20200607131339.png) + +''' +readme_tooter = ''' +--- +![](http://image.iswbm.com/20200607174235.png) + +''' + + +def get_file_info(filename): + with open(filename, 'r', encoding="utf-8") as file: + first_line = file.readline().replace("#", "").strip() + return first_line.split(' ', 1) + +def make_line(chapter, file): + page_name, _ = os.path.splitext(file) + (index, title) = get_file_info(file) + url = base_link + chapter + "/" + page_name + ".html" + item_list = ["-", index, "[{}]({})\n".format(title, url)] + return " ".join(item_list) + +def render_index_page(index_info): + ''' + 生成 readme.md 索引文件,包含所有文件目录 + ''' + # 重新排序 + index_info = sorted(index_info.items(), key=lambda item:item[0], reverse=False) + + # 写入文件 + with open(index_path, 'w+', encoding="utf-8") as file: + file.write(readme_header) + for chp, info in index_info: + chp_name = info["name"] + file.write("## " + chp_name + "\n") + for line in info["contents"]: + file.write(line) + file.write("\n") + file.write(readme_tooter) + +def convert_md5_to_rst(file): + ''' + 转换格式:md5转换成rst + ''' + (filename, extension) = os.path.splitext(file) + convert_cmd = 'pandoc -V mainfont="SimSun" -f markdown -t rst {md_file} -o {rst_file}'.format( + md_file=filename+'.md', rst_file=filename+'.rst' + ) + # status, output = commands.getstatusoutput(convert_cmd) + status = subprocess.call(convert_cmd.split(" ")) + if status != 0: + print("命令执行失败: " + convert_cmd) + os._exit(1) + if status == 0: + print(file + ' 处理完成') + else: + print(file + '处理失败') + +def get_all_dir(): + ''' + 获取所有的目录 + ''' + dir_list = [] + file_list = os.listdir(blog_path) + for item in file_list: + abs_path = os.path.join(blog_path, item) + if os.path.isdir(abs_path): + dir_list.append(abs_path) + return dir_list + + +def init_index_info(): + ''' + 初始化索引 + ''' + index_info = {} + chapter_dir = os.path.join(blog_path, "chapters") + os.chdir(chapter_dir) + for file in os.listdir(chapter_dir): + name, _ = os.path.splitext(file) + with open(file, 'r', encoding="utf-8") as f: + chapter_name = f.readlines()[1].strip() + index_info[name.replace("p", "")] = {"name": chapter_name, "contents": []} + return index_info + +def main(index_info): + for folder in get_all_dir(): + os.chdir(folder) + chapter = os.path.split(folder)[1] + all_file = os.listdir(folder) + all_md_file = sorted([file for file in all_file if file.endswith('md')]) + + for file in all_md_file: + line = make_line(chapter, file) + index_info[chapter.replace("c", "")]["contents"].append(line) + convert_md5_to_rst(file) + + +if __name__ == '__main__': + index_info = init_index_info() + main(index_info) + # render_index_page(index_info) + print("OK") diff --git a/rebuild.sh b/rebuild.sh new file mode 100755 index 0000000..319b303 --- /dev/null +++ b/rebuild.sh @@ -0,0 +1,13 @@ +cat << EOF >/usr/local/lib/python3.6/site-packages/sphinx_rtd_theme/comments.html + + + +EOF + +rm -rf build/ && sphinx-multiversion source build/html && cp -rf build/html/master/* build/html/ diff --git a/requirements.txt b/requirements.txt index 47a657a..2a34b8d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,41 @@ -greenlet==0.4.5 -oauthlib==0.7.2 -paho-mqtt==1.0 -tzlocal==1.1.2 -redis==2.10.3 -requests==2.4.3 -requests-oauthlib==0.4.2 -whitenoise==1.0.3 -openpyxl==2.1.5 - +alabaster==0.7.12 +argh==0.26.2 +Babel==2.9.1 +certifi==2019.6.16 +chardet==3.0.4 +docutils==0.14 +imagesize==1.1.0 +Jinja2==2.11.3 +livereload==2.6.1 +MarkupSafe==1.1.1 +packaging==19.0 +pathtools==0.1.2 +port-for==0.3.1 +Pygments==2.7.4 +pyparsing==2.4.0 +pytz==2019.1 +PyYAML==6.0.1 +#requests==2.32.3 +six==1.12.0 +snowballstemmer==1.9.0 +Sphinx==2.1.2 +sphinx-autobuild==0.7.1 +sphinx-rtd-theme==0.4.3 +sphinxcontrib-applehelp==1.0.1 +sphinxcontrib-devhelp==1.0.1 +sphinxcontrib-htmlhelp==1.0.2 +sphinxcontrib-jsmath==1.0.1 +sphinxcontrib-qthelp==1.0.2 +sphinxcontrib-serializinghtml==1.1.3 +tornado==6.0.3 +#urllib3==2.2.2 +watchdog==0.9.0 +sphinxcontrib-disqus==1.1.0 +sphinxcontrib-applehelp==1.0.1 +sphinxcontrib-devhelp==1.0.1 +sphinxcontrib-htmlhelp==1.0.2 +sphinxcontrib-jsmath==1.0.1 +sphinxcontrib-qthelp==1.0.2 +sphinxcontrib-serializinghtml==1.1.3 +sphinx-sitemap==2.2.0 +sphinx-multiversion==0.2.4 diff --git a/source/.DS_Store b/source/.DS_Store deleted file mode 100644 index a844301..0000000 Binary files a/source/.DS_Store and /dev/null differ diff --git a/source/_static/js/baidutongji.js b/source/_static/js/baidutongji.js new file mode 100644 index 0000000..0a7873f --- /dev/null +++ b/source/_static/js/baidutongji.js @@ -0,0 +1,7 @@ +var _hmt = _hmt || []; +(function() { + var hm = document.createElement("script"); + hm.src = "https://hm.baidu.com/hm.js?26ee367cf320d48d046542295cdb0dad"; + var s = document.getElementsByTagName("script")[0]; + s.parentNode.insertBefore(hm, s); +})(); diff --git a/source/_static/js/readmore.js b/source/_static/js/readmore.js new file mode 100644 index 0000000..f2a29c2 --- /dev/null +++ b/source/_static/js/readmore.js @@ -0,0 +1,50 @@ +!function (e, t) { "use strict"; "object" == typeof module && "object" == typeof module.exports ? module.exports = e.document ? t(e, !0) : function (e) { if (!e.document) throw new Error("jQuery requires a window with a document"); return t(e) } : t(e) }("undefined" != typeof window ? window : this, function (C, e) { "use strict"; var t = [], E = C.document, r = Object.getPrototypeOf, s = t.slice, g = t.concat, u = t.push, i = t.indexOf, n = {}, o = n.toString, v = n.hasOwnProperty, a = v.toString, l = a.call(Object), y = {}, m = function (e) { return "function" == typeof e && "number" != typeof e.nodeType }, x = function (e) { return null != e && e === e.window }, c = { type: !0, src: !0, nonce: !0, noModule: !0 }; function b(e, t, n) { var r, i, o = (n = n || E).createElement("script"); if (o.text = e, t) for (r in c) (i = t[r] || t.getAttribute && t.getAttribute(r)) && o.setAttribute(r, i); n.head.appendChild(o).parentNode.removeChild(o) } function w(e) { return null == e ? e + "" : "object" == typeof e || "function" == typeof e ? n[o.call(e)] || "object" : typeof e } var f = "3.4.1", k = function (e, t) { return new k.fn.init(e, t) }, p = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; function d(e) { var t = !!e && "length" in e && e.length, n = w(e); return !m(e) && !x(e) && ("array" === n || 0 === t || "number" == typeof t && 0 < t && t - 1 in e) } k.fn = k.prototype = { jquery: f, constructor: k, length: 0, toArray: function () { return s.call(this) }, get: function (e) { return null == e ? s.call(this) : e < 0 ? this[e + this.length] : this[e] }, pushStack: function (e) { var t = k.merge(this.constructor(), e); return t.prevObject = this, t }, each: function (e) { return k.each(this, e) }, map: function (n) { return this.pushStack(k.map(this, function (e, t) { return n.call(e, t, e) })) }, slice: function () { return this.pushStack(s.apply(this, arguments)) }, first: function () { return this.eq(0) }, last: function () { return this.eq(-1) }, eq: function (e) { var t = this.length, n = +e + (e < 0 ? t : 0); return this.pushStack(0 <= n && n < t ? [this[n]] : []) }, end: function () { return this.prevObject || this.constructor() }, push: u, sort: t.sort, splice: t.splice }, k.extend = k.fn.extend = function () { var e, t, n, r, i, o, a = arguments[0] || {}, s = 1, u = arguments.length, l = !1; for ("boolean" == typeof a && (l = a, a = arguments[s] || {}, s++), "object" == typeof a || m(a) || (a = {}), s === u && (a = this, s--); s < u; s++)if (null != (e = arguments[s])) for (t in e) r = e[t], "__proto__" !== t && a !== r && (l && r && (k.isPlainObject(r) || (i = Array.isArray(r))) ? (n = a[t], o = i && !Array.isArray(n) ? [] : i || k.isPlainObject(n) ? n : {}, i = !1, a[t] = k.extend(l, o, r)) : void 0 !== r && (a[t] = r)); return a }, k.extend({ expando: "jQuery" + (f + Math.random()).replace(/\D/g, ""), isReady: !0, error: function (e) { throw new Error(e) }, noop: function () { }, isPlainObject: function (e) { var t, n; return !(!e || "[object Object]" !== o.call(e)) && (!(t = r(e)) || "function" == typeof (n = v.call(t, "constructor") && t.constructor) && a.call(n) === l) }, isEmptyObject: function (e) { var t; for (t in e) return !1; return !0 }, globalEval: function (e, t) { b(e, { nonce: t && t.nonce }) }, each: function (e, t) { var n, r = 0; if (d(e)) { for (n = e.length; r < n; r++)if (!1 === t.call(e[r], r, e[r])) break } else for (r in e) if (!1 === t.call(e[r], r, e[r])) break; return e }, trim: function (e) { return null == e ? "" : (e + "").replace(p, "") }, makeArray: function (e, t) { var n = t || []; return null != e && (d(Object(e)) ? k.merge(n, "string" == typeof e ? [e] : e) : u.call(n, e)), n }, inArray: function (e, t, n) { return null == t ? -1 : i.call(t, e, n) }, merge: function (e, t) { for (var n = +t.length, r = 0, i = e.length; r < n; r++)e[i++] = t[r]; return e.length = i, e }, grep: function (e, t, n) { for (var r = [], i = 0, o = e.length, a = !n; i < o; i++)!t(e[i], i) !== a && r.push(e[i]); return r }, map: function (e, t, n) { var r, i, o = 0, a = []; if (d(e)) for (r = e.length; o < r; o++)null != (i = t(e[o], o, n)) && a.push(i); else for (o in e) null != (i = t(e[o], o, n)) && a.push(i); return g.apply([], a) }, guid: 1, support: y }), "function" == typeof Symbol && (k.fn[Symbol.iterator] = t[Symbol.iterator]), k.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "), function (e, t) { n["[object " + t + "]"] = t.toLowerCase() }); var h = function (n) { var e, d, b, o, i, h, f, g, w, u, l, T, C, a, E, v, s, c, y, k = "sizzle" + 1 * new Date, m = n.document, S = 0, r = 0, p = ue(), x = ue(), N = ue(), A = ue(), D = function (e, t) { return e === t && (l = !0), 0 }, j = {}.hasOwnProperty, t = [], q = t.pop, L = t.push, H = t.push, O = t.slice, P = function (e, t) { for (var n = 0, r = e.length; n < r; n++)if (e[n] === t) return n; return -1 }, R = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", M = "[\\x20\\t\\r\\n\\f]", I = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", W = "\\[" + M + "*(" + I + ")(?:" + M + "*([*^$|!~]?=)" + M + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + I + "))|)" + M + "*\\]", $ = ":(" + I + ")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|" + W + ")*)|.*)\\)|)", F = new RegExp(M + "+", "g"), B = new RegExp("^" + M + "+|((?:^|[^\\\\])(?:\\\\.)*)" + M + "+$", "g"), _ = new RegExp("^" + M + "*," + M + "*"), z = new RegExp("^" + M + "*([>+~]|" + M + ")" + M + "*"), U = new RegExp(M + "|>"), X = new RegExp($), V = new RegExp("^" + I + "$"), G = { ID: new RegExp("^#(" + I + ")"), CLASS: new RegExp("^\\.(" + I + ")"), TAG: new RegExp("^(" + I + "|[*])"), ATTR: new RegExp("^" + W), PSEUDO: new RegExp("^" + $), CHILD: new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + M + "*(even|odd|(([+-]|)(\\d*)n|)" + M + "*(?:([+-]|)" + M + "*(\\d+)|))" + M + "*\\)|)", "i"), bool: new RegExp("^(?:" + R + ")$", "i"), needsContext: new RegExp("^" + M + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + M + "*((?:-\\d)?\\d*)" + M + "*\\)|)(?=[^-]|$)", "i") }, Y = /HTML$/i, Q = /^(?:input|select|textarea|button)$/i, J = /^h\d$/i, K = /^[^{]+\{\s*\[native \w/, Z = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, ee = /[+~]/, te = new RegExp("\\\\([\\da-f]{1,6}" + M + "?|(" + M + ")|.)", "ig"), ne = function (e, t, n) { var r = "0x" + t - 65536; return r != r || n ? t : r < 0 ? String.fromCharCode(r + 65536) : String.fromCharCode(r >> 10 | 55296, 1023 & r | 56320) }, re = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, ie = function (e, t) { return t ? "\0" === e ? "\ufffd" : e.slice(0, -1) + "\\" + e.charCodeAt(e.length - 1).toString(16) + " " : "\\" + e }, oe = function () { T() }, ae = be(function (e) { return !0 === e.disabled && "fieldset" === e.nodeName.toLowerCase() }, { dir: "parentNode", next: "legend" }); try { H.apply(t = O.call(m.childNodes), m.childNodes), t[m.childNodes.length].nodeType } catch (e) { H = { apply: t.length ? function (e, t) { L.apply(e, O.call(t)) } : function (e, t) { var n = e.length, r = 0; while (e[n++] = t[r++]); e.length = n - 1 } } } function se(t, e, n, r) { var i, o, a, s, u, l, c, f = e && e.ownerDocument, p = e ? e.nodeType : 9; if (n = n || [], "string" != typeof t || !t || 1 !== p && 9 !== p && 11 !== p) return n; if (!r && ((e ? e.ownerDocument || e : m) !== C && T(e), e = e || C, E)) { if (11 !== p && (u = Z.exec(t))) if (i = u[1]) { if (9 === p) { if (!(a = e.getElementById(i))) return n; if (a.id === i) return n.push(a), n } else if (f && (a = f.getElementById(i)) && y(e, a) && a.id === i) return n.push(a), n } else { if (u[2]) return H.apply(n, e.getElementsByTagName(t)), n; if ((i = u[3]) && d.getElementsByClassName && e.getElementsByClassName) return H.apply(n, e.getElementsByClassName(i)), n } if (d.qsa && !A[t + " "] && (!v || !v.test(t)) && (1 !== p || "object" !== e.nodeName.toLowerCase())) { if (c = t, f = e, 1 === p && U.test(t)) { (s = e.getAttribute("id")) ? s = s.replace(re, ie) : e.setAttribute("id", s = k), o = (l = h(t)).length; while (o--) l[o] = "#" + s + " " + xe(l[o]); c = l.join(","), f = ee.test(t) && ye(e.parentNode) || e } try { return H.apply(n, f.querySelectorAll(c)), n } catch (e) { A(t, !0) } finally { s === k && e.removeAttribute("id") } } } return g(t.replace(B, "$1"), e, n, r) } function ue() { var r = []; return function e(t, n) { return r.push(t + " ") > b.cacheLength && delete e[r.shift()], e[t + " "] = n } } function le(e) { return e[k] = !0, e } function ce(e) { var t = C.createElement("fieldset"); try { return !!e(t) } catch (e) { return !1 } finally { t.parentNode && t.parentNode.removeChild(t), t = null } } function fe(e, t) { var n = e.split("|"), r = n.length; while (r--) b.attrHandle[n[r]] = t } function pe(e, t) { var n = t && e, r = n && 1 === e.nodeType && 1 === t.nodeType && e.sourceIndex - t.sourceIndex; if (r) return r; if (n) while (n = n.nextSibling) if (n === t) return -1; return e ? 1 : -1 } function de(t) { return function (e) { return "input" === e.nodeName.toLowerCase() && e.type === t } } function he(n) { return function (e) { var t = e.nodeName.toLowerCase(); return ("input" === t || "button" === t) && e.type === n } } function ge(t) { return function (e) { return "form" in e ? e.parentNode && !1 === e.disabled ? "label" in e ? "label" in e.parentNode ? e.parentNode.disabled === t : e.disabled === t : e.isDisabled === t || e.isDisabled !== !t && ae(e) === t : e.disabled === t : "label" in e && e.disabled === t } } function ve(a) { return le(function (o) { return o = +o, le(function (e, t) { var n, r = a([], e.length, o), i = r.length; while (i--) e[n = r[i]] && (e[n] = !(t[n] = e[n])) }) }) } function ye(e) { return e && "undefined" != typeof e.getElementsByTagName && e } for (e in d = se.support = {}, i = se.isXML = function (e) { var t = e.namespaceURI, n = (e.ownerDocument || e).documentElement; return !Y.test(t || n && n.nodeName || "HTML") }, T = se.setDocument = function (e) { var t, n, r = e ? e.ownerDocument || e : m; return r !== C && 9 === r.nodeType && r.documentElement && (a = (C = r).documentElement, E = !i(C), m !== C && (n = C.defaultView) && n.top !== n && (n.addEventListener ? n.addEventListener("unload", oe, !1) : n.attachEvent && n.attachEvent("onunload", oe)), d.attributes = ce(function (e) { return e.className = "i", !e.getAttribute("className") }), d.getElementsByTagName = ce(function (e) { return e.appendChild(C.createComment("")), !e.getElementsByTagName("*").length }), d.getElementsByClassName = K.test(C.getElementsByClassName), d.getById = ce(function (e) { return a.appendChild(e).id = k, !C.getElementsByName || !C.getElementsByName(k).length }), d.getById ? (b.filter.ID = function (e) { var t = e.replace(te, ne); return function (e) { return e.getAttribute("id") === t } }, b.find.ID = function (e, t) { if ("undefined" != typeof t.getElementById && E) { var n = t.getElementById(e); return n ? [n] : [] } }) : (b.filter.ID = function (e) { var n = e.replace(te, ne); return function (e) { var t = "undefined" != typeof e.getAttributeNode && e.getAttributeNode("id"); return t && t.value === n } }, b.find.ID = function (e, t) { if ("undefined" != typeof t.getElementById && E) { var n, r, i, o = t.getElementById(e); if (o) { if ((n = o.getAttributeNode("id")) && n.value === e) return [o]; i = t.getElementsByName(e), r = 0; while (o = i[r++]) if ((n = o.getAttributeNode("id")) && n.value === e) return [o] } return [] } }), b.find.TAG = d.getElementsByTagName ? function (e, t) { return "undefined" != typeof t.getElementsByTagName ? t.getElementsByTagName(e) : d.qsa ? t.querySelectorAll(e) : void 0 } : function (e, t) { var n, r = [], i = 0, o = t.getElementsByTagName(e); if ("*" === e) { while (n = o[i++]) 1 === n.nodeType && r.push(n); return r } return o }, b.find.CLASS = d.getElementsByClassName && function (e, t) { if ("undefined" != typeof t.getElementsByClassName && E) return t.getElementsByClassName(e) }, s = [], v = [], (d.qsa = K.test(C.querySelectorAll)) && (ce(function (e) { a.appendChild(e).innerHTML = "", e.querySelectorAll("[msallowcapture^='']").length && v.push("[*^$]=" + M + "*(?:''|\"\")"), e.querySelectorAll("[selected]").length || v.push("\\[" + M + "*(?:value|" + R + ")"), e.querySelectorAll("[id~=" + k + "-]").length || v.push("~="), e.querySelectorAll(":checked").length || v.push(":checked"), e.querySelectorAll("a#" + k + "+*").length || v.push(".#.+[+~]") }), ce(function (e) { e.innerHTML = ""; var t = C.createElement("input"); t.setAttribute("type", "hidden"), e.appendChild(t).setAttribute("name", "D"), e.querySelectorAll("[name=d]").length && v.push("name" + M + "*[*^$|!~]?="), 2 !== e.querySelectorAll(":enabled").length && v.push(":enabled", ":disabled"), a.appendChild(e).disabled = !0, 2 !== e.querySelectorAll(":disabled").length && v.push(":enabled", ":disabled"), e.querySelectorAll("*,:x"), v.push(",.*:") })), (d.matchesSelector = K.test(c = a.matches || a.webkitMatchesSelector || a.mozMatchesSelector || a.oMatchesSelector || a.msMatchesSelector)) && ce(function (e) { d.disconnectedMatch = c.call(e, "*"), c.call(e, "[s!='']:x"), s.push("!=", $) }), v = v.length && new RegExp(v.join("|")), s = s.length && new RegExp(s.join("|")), t = K.test(a.compareDocumentPosition), y = t || K.test(a.contains) ? function (e, t) { var n = 9 === e.nodeType ? e.documentElement : e, r = t && t.parentNode; return e === r || !(!r || 1 !== r.nodeType || !(n.contains ? n.contains(r) : e.compareDocumentPosition && 16 & e.compareDocumentPosition(r))) } : function (e, t) { if (t) while (t = t.parentNode) if (t === e) return !0; return !1 }, D = t ? function (e, t) { if (e === t) return l = !0, 0; var n = !e.compareDocumentPosition - !t.compareDocumentPosition; return n || (1 & (n = (e.ownerDocument || e) === (t.ownerDocument || t) ? e.compareDocumentPosition(t) : 1) || !d.sortDetached && t.compareDocumentPosition(e) === n ? e === C || e.ownerDocument === m && y(m, e) ? -1 : t === C || t.ownerDocument === m && y(m, t) ? 1 : u ? P(u, e) - P(u, t) : 0 : 4 & n ? -1 : 1) } : function (e, t) { if (e === t) return l = !0, 0; var n, r = 0, i = e.parentNode, o = t.parentNode, a = [e], s = [t]; if (!i || !o) return e === C ? -1 : t === C ? 1 : i ? -1 : o ? 1 : u ? P(u, e) - P(u, t) : 0; if (i === o) return pe(e, t); n = e; while (n = n.parentNode) a.unshift(n); n = t; while (n = n.parentNode) s.unshift(n); while (a[r] === s[r]) r++; return r ? pe(a[r], s[r]) : a[r] === m ? -1 : s[r] === m ? 1 : 0 }), C }, se.matches = function (e, t) { return se(e, null, null, t) }, se.matchesSelector = function (e, t) { if ((e.ownerDocument || e) !== C && T(e), d.matchesSelector && E && !A[t + " "] && (!s || !s.test(t)) && (!v || !v.test(t))) try { var n = c.call(e, t); if (n || d.disconnectedMatch || e.document && 11 !== e.document.nodeType) return n } catch (e) { A(t, !0) } return 0 < se(t, C, null, [e]).length }, se.contains = function (e, t) { return (e.ownerDocument || e) !== C && T(e), y(e, t) }, se.attr = function (e, t) { (e.ownerDocument || e) !== C && T(e); var n = b.attrHandle[t.toLowerCase()], r = n && j.call(b.attrHandle, t.toLowerCase()) ? n(e, t, !E) : void 0; return void 0 !== r ? r : d.attributes || !E ? e.getAttribute(t) : (r = e.getAttributeNode(t)) && r.specified ? r.value : null }, se.escape = function (e) { return (e + "").replace(re, ie) }, se.error = function (e) { throw new Error("Syntax error, unrecognized expression: " + e) }, se.uniqueSort = function (e) { var t, n = [], r = 0, i = 0; if (l = !d.detectDuplicates, u = !d.sortStable && e.slice(0), e.sort(D), l) { while (t = e[i++]) t === e[i] && (r = n.push(i)); while (r--) e.splice(n[r], 1) } return u = null, e }, o = se.getText = function (e) { var t, n = "", r = 0, i = e.nodeType; if (i) { if (1 === i || 9 === i || 11 === i) { if ("string" == typeof e.textContent) return e.textContent; for (e = e.firstChild; e; e = e.nextSibling)n += o(e) } else if (3 === i || 4 === i) return e.nodeValue } else while (t = e[r++]) n += o(t); return n }, (b = se.selectors = { cacheLength: 50, createPseudo: le, match: G, attrHandle: {}, find: {}, relative: { ">": { dir: "parentNode", first: !0 }, " ": { dir: "parentNode" }, "+": { dir: "previousSibling", first: !0 }, "~": { dir: "previousSibling" } }, preFilter: { ATTR: function (e) { return e[1] = e[1].replace(te, ne), e[3] = (e[3] || e[4] || e[5] || "").replace(te, ne), "~=" === e[2] && (e[3] = " " + e[3] + " "), e.slice(0, 4) }, CHILD: function (e) { return e[1] = e[1].toLowerCase(), "nth" === e[1].slice(0, 3) ? (e[3] || se.error(e[0]), e[4] = +(e[4] ? e[5] + (e[6] || 1) : 2 * ("even" === e[3] || "odd" === e[3])), e[5] = +(e[7] + e[8] || "odd" === e[3])) : e[3] && se.error(e[0]), e }, PSEUDO: function (e) { var t, n = !e[6] && e[2]; return G.CHILD.test(e[0]) ? null : (e[3] ? e[2] = e[4] || e[5] || "" : n && X.test(n) && (t = h(n, !0)) && (t = n.indexOf(")", n.length - t) - n.length) && (e[0] = e[0].slice(0, t), e[2] = n.slice(0, t)), e.slice(0, 3)) } }, filter: { TAG: function (e) { var t = e.replace(te, ne).toLowerCase(); return "*" === e ? function () { return !0 } : function (e) { return e.nodeName && e.nodeName.toLowerCase() === t } }, CLASS: function (e) { var t = p[e + " "]; return t || (t = new RegExp("(^|" + M + ")" + e + "(" + M + "|$)")) && p(e, function (e) { return t.test("string" == typeof e.className && e.className || "undefined" != typeof e.getAttribute && e.getAttribute("class") || "") }) }, ATTR: function (n, r, i) { return function (e) { var t = se.attr(e, n); return null == t ? "!=" === r : !r || (t += "", "=" === r ? t === i : "!=" === r ? t !== i : "^=" === r ? i && 0 === t.indexOf(i) : "*=" === r ? i && -1 < t.indexOf(i) : "$=" === r ? i && t.slice(-i.length) === i : "~=" === r ? -1 < (" " + t.replace(F, " ") + " ").indexOf(i) : "|=" === r && (t === i || t.slice(0, i.length + 1) === i + "-")) } }, CHILD: function (h, e, t, g, v) { var y = "nth" !== h.slice(0, 3), m = "last" !== h.slice(-4), x = "of-type" === e; return 1 === g && 0 === v ? function (e) { return !!e.parentNode } : function (e, t, n) { var r, i, o, a, s, u, l = y !== m ? "nextSibling" : "previousSibling", c = e.parentNode, f = x && e.nodeName.toLowerCase(), p = !n && !x, d = !1; if (c) { if (y) { while (l) { a = e; while (a = a[l]) if (x ? a.nodeName.toLowerCase() === f : 1 === a.nodeType) return !1; u = l = "only" === h && !u && "nextSibling" } return !0 } if (u = [m ? c.firstChild : c.lastChild], m && p) { d = (s = (r = (i = (o = (a = c)[k] || (a[k] = {}))[a.uniqueID] || (o[a.uniqueID] = {}))[h] || [])[0] === S && r[1]) && r[2], a = s && c.childNodes[s]; while (a = ++s && a && a[l] || (d = s = 0) || u.pop()) if (1 === a.nodeType && ++d && a === e) { i[h] = [S, s, d]; break } } else if (p && (d = s = (r = (i = (o = (a = e)[k] || (a[k] = {}))[a.uniqueID] || (o[a.uniqueID] = {}))[h] || [])[0] === S && r[1]), !1 === d) while (a = ++s && a && a[l] || (d = s = 0) || u.pop()) if ((x ? a.nodeName.toLowerCase() === f : 1 === a.nodeType) && ++d && (p && ((i = (o = a[k] || (a[k] = {}))[a.uniqueID] || (o[a.uniqueID] = {}))[h] = [S, d]), a === e)) break; return (d -= v) === g || d % g == 0 && 0 <= d / g } } }, PSEUDO: function (e, o) { var t, a = b.pseudos[e] || b.setFilters[e.toLowerCase()] || se.error("unsupported pseudo: " + e); return a[k] ? a(o) : 1 < a.length ? (t = [e, e, "", o], b.setFilters.hasOwnProperty(e.toLowerCase()) ? le(function (e, t) { var n, r = a(e, o), i = r.length; while (i--) e[n = P(e, r[i])] = !(t[n] = r[i]) }) : function (e) { return a(e, 0, t) }) : a } }, pseudos: { not: le(function (e) { var r = [], i = [], s = f(e.replace(B, "$1")); return s[k] ? le(function (e, t, n, r) { var i, o = s(e, null, r, []), a = e.length; while (a--) (i = o[a]) && (e[a] = !(t[a] = i)) }) : function (e, t, n) { return r[0] = e, s(r, null, n, i), r[0] = null, !i.pop() } }), has: le(function (t) { return function (e) { return 0 < se(t, e).length } }), contains: le(function (t) { return t = t.replace(te, ne), function (e) { return -1 < (e.textContent || o(e)).indexOf(t) } }), lang: le(function (n) { return V.test(n || "") || se.error("unsupported lang: " + n), n = n.replace(te, ne).toLowerCase(), function (e) { var t; do { if (t = E ? e.lang : e.getAttribute("xml:lang") || e.getAttribute("lang")) return (t = t.toLowerCase()) === n || 0 === t.indexOf(n + "-") } while ((e = e.parentNode) && 1 === e.nodeType); return !1 } }), target: function (e) { var t = n.location && n.location.hash; return t && t.slice(1) === e.id }, root: function (e) { return e === a }, focus: function (e) { return e === C.activeElement && (!C.hasFocus || C.hasFocus()) && !!(e.type || e.href || ~e.tabIndex) }, enabled: ge(!1), disabled: ge(!0), checked: function (e) { var t = e.nodeName.toLowerCase(); return "input" === t && !!e.checked || "option" === t && !!e.selected }, selected: function (e) { return e.parentNode && e.parentNode.selectedIndex, !0 === e.selected }, empty: function (e) { for (e = e.firstChild; e; e = e.nextSibling)if (e.nodeType < 6) return !1; return !0 }, parent: function (e) { return !b.pseudos.empty(e) }, header: function (e) { return J.test(e.nodeName) }, input: function (e) { return Q.test(e.nodeName) }, button: function (e) { var t = e.nodeName.toLowerCase(); return "input" === t && "button" === e.type || "button" === t }, text: function (e) { var t; return "input" === e.nodeName.toLowerCase() && "text" === e.type && (null == (t = e.getAttribute("type")) || "text" === t.toLowerCase()) }, first: ve(function () { return [0] }), last: ve(function (e, t) { return [t - 1] }), eq: ve(function (e, t, n) { return [n < 0 ? n + t : n] }), even: ve(function (e, t) { for (var n = 0; n < t; n += 2)e.push(n); return e }), odd: ve(function (e, t) { for (var n = 1; n < t; n += 2)e.push(n); return e }), lt: ve(function (e, t, n) { for (var r = n < 0 ? n + t : t < n ? t : n; 0 <= --r;)e.push(r); return e }), gt: ve(function (e, t, n) { for (var r = n < 0 ? n + t : n; ++r < t;)e.push(r); return e }) } }).pseudos.nth = b.pseudos.eq, { radio: !0, checkbox: !0, file: !0, password: !0, image: !0 }) b.pseudos[e] = de(e); for (e in { submit: !0, reset: !0 }) b.pseudos[e] = he(e); function me() { } function xe(e) { for (var t = 0, n = e.length, r = ""; t < n; t++)r += e[t].value; return r } function be(s, e, t) { var u = e.dir, l = e.next, c = l || u, f = t && "parentNode" === c, p = r++; return e.first ? function (e, t, n) { while (e = e[u]) if (1 === e.nodeType || f) return s(e, t, n); return !1 } : function (e, t, n) { var r, i, o, a = [S, p]; if (n) { while (e = e[u]) if ((1 === e.nodeType || f) && s(e, t, n)) return !0 } else while (e = e[u]) if (1 === e.nodeType || f) if (i = (o = e[k] || (e[k] = {}))[e.uniqueID] || (o[e.uniqueID] = {}), l && l === e.nodeName.toLowerCase()) e = e[u] || e; else { if ((r = i[c]) && r[0] === S && r[1] === p) return a[2] = r[2]; if ((i[c] = a)[2] = s(e, t, n)) return !0 } return !1 } } function we(i) { return 1 < i.length ? function (e, t, n) { var r = i.length; while (r--) if (!i[r](e, t, n)) return !1; return !0 } : i[0] } function Te(e, t, n, r, i) { for (var o, a = [], s = 0, u = e.length, l = null != t; s < u; s++)(o = e[s]) && (n && !n(o, r, i) || (a.push(o), l && t.push(s))); return a } function Ce(d, h, g, v, y, e) { return v && !v[k] && (v = Ce(v)), y && !y[k] && (y = Ce(y, e)), le(function (e, t, n, r) { var i, o, a, s = [], u = [], l = t.length, c = e || function (e, t, n) { for (var r = 0, i = t.length; r < i; r++)se(e, t[r], n); return n }(h || "*", n.nodeType ? [n] : n, []), f = !d || !e && h ? c : Te(c, s, d, n, r), p = g ? y || (e ? d : l || v) ? [] : t : f; if (g && g(f, p, n, r), v) { i = Te(p, u), v(i, [], n, r), o = i.length; while (o--) (a = i[o]) && (p[u[o]] = !(f[u[o]] = a)) } if (e) { if (y || d) { if (y) { i = [], o = p.length; while (o--) (a = p[o]) && i.push(f[o] = a); y(null, p = [], i, r) } o = p.length; while (o--) (a = p[o]) && -1 < (i = y ? P(e, a) : s[o]) && (e[i] = !(t[i] = a)) } } else p = Te(p === t ? p.splice(l, p.length) : p), y ? y(null, t, p, r) : H.apply(t, p) }) } function Ee(e) { for (var i, t, n, r = e.length, o = b.relative[e[0].type], a = o || b.relative[" "], s = o ? 1 : 0, u = be(function (e) { return e === i }, a, !0), l = be(function (e) { return -1 < P(i, e) }, a, !0), c = [function (e, t, n) { var r = !o && (n || t !== w) || ((i = t).nodeType ? u(e, t, n) : l(e, t, n)); return i = null, r }]; s < r; s++)if (t = b.relative[e[s].type]) c = [be(we(c), t)]; else { if ((t = b.filter[e[s].type].apply(null, e[s].matches))[k]) { for (n = ++s; n < r; n++)if (b.relative[e[n].type]) break; return Ce(1 < s && we(c), 1 < s && xe(e.slice(0, s - 1).concat({ value: " " === e[s - 2].type ? "*" : "" })).replace(B, "$1"), t, s < n && Ee(e.slice(s, n)), n < r && Ee(e = e.slice(n)), n < r && xe(e)) } c.push(t) } return we(c) } return me.prototype = b.filters = b.pseudos, b.setFilters = new me, h = se.tokenize = function (e, t) { var n, r, i, o, a, s, u, l = x[e + " "]; if (l) return t ? 0 : l.slice(0); a = e, s = [], u = b.preFilter; while (a) { for (o in n && !(r = _.exec(a)) || (r && (a = a.slice(r[0].length) || a), s.push(i = [])), n = !1, (r = z.exec(a)) && (n = r.shift(), i.push({ value: n, type: r[0].replace(B, " ") }), a = a.slice(n.length)), b.filter) !(r = G[o].exec(a)) || u[o] && !(r = u[o](r)) || (n = r.shift(), i.push({ value: n, type: o, matches: r }), a = a.slice(n.length)); if (!n) break } return t ? a.length : a ? se.error(e) : x(e, s).slice(0) }, f = se.compile = function (e, t) { var n, v, y, m, x, r, i = [], o = [], a = N[e + " "]; if (!a) { t || (t = h(e)), n = t.length; while (n--) (a = Ee(t[n]))[k] ? i.push(a) : o.push(a); (a = N(e, (v = o, m = 0 < (y = i).length, x = 0 < v.length, r = function (e, t, n, r, i) { var o, a, s, u = 0, l = "0", c = e && [], f = [], p = w, d = e || x && b.find.TAG("*", i), h = S += null == p ? 1 : Math.random() || .1, g = d.length; for (i && (w = t === C || t || i); l !== g && null != (o = d[l]); l++) { if (x && o) { a = 0, t || o.ownerDocument === C || (T(o), n = !E); while (s = v[a++]) if (s(o, t || C, n)) { r.push(o); break } i && (S = h) } m && ((o = !s && o) && u-- , e && c.push(o)) } if (u += l, m && l !== u) { a = 0; while (s = y[a++]) s(c, f, t, n); if (e) { if (0 < u) while (l--) c[l] || f[l] || (f[l] = q.call(r)); f = Te(f) } H.apply(r, f), i && !e && 0 < f.length && 1 < u + y.length && se.uniqueSort(r) } return i && (S = h, w = p), c }, m ? le(r) : r))).selector = e } return a }, g = se.select = function (e, t, n, r) { var i, o, a, s, u, l = "function" == typeof e && e, c = !r && h(e = l.selector || e); if (n = n || [], 1 === c.length) { if (2 < (o = c[0] = c[0].slice(0)).length && "ID" === (a = o[0]).type && 9 === t.nodeType && E && b.relative[o[1].type]) { if (!(t = (b.find.ID(a.matches[0].replace(te, ne), t) || [])[0])) return n; l && (t = t.parentNode), e = e.slice(o.shift().value.length) } i = G.needsContext.test(e) ? 0 : o.length; while (i--) { if (a = o[i], b.relative[s = a.type]) break; if ((u = b.find[s]) && (r = u(a.matches[0].replace(te, ne), ee.test(o[0].type) && ye(t.parentNode) || t))) { if (o.splice(i, 1), !(e = r.length && xe(o))) return H.apply(n, r), n; break } } } return (l || f(e, c))(r, t, !E, n, !t || ee.test(e) && ye(t.parentNode) || t), n }, d.sortStable = k.split("").sort(D).join("") === k, d.detectDuplicates = !!l, T(), d.sortDetached = ce(function (e) { return 1 & e.compareDocumentPosition(C.createElement("fieldset")) }), ce(function (e) { return e.innerHTML = "", "#" === e.firstChild.getAttribute("href") }) || fe("type|href|height|width", function (e, t, n) { if (!n) return e.getAttribute(t, "type" === t.toLowerCase() ? 1 : 2) }), d.attributes && ce(function (e) { return e.innerHTML = "", e.firstChild.setAttribute("value", ""), "" === e.firstChild.getAttribute("value") }) || fe("value", function (e, t, n) { if (!n && "input" === e.nodeName.toLowerCase()) return e.defaultValue }), ce(function (e) { return null == e.getAttribute("disabled") }) || fe(R, function (e, t, n) { var r; if (!n) return !0 === e[t] ? t.toLowerCase() : (r = e.getAttributeNode(t)) && r.specified ? r.value : null }), se }(C); k.find = h, k.expr = h.selectors, k.expr[":"] = k.expr.pseudos, k.uniqueSort = k.unique = h.uniqueSort, k.text = h.getText, k.isXMLDoc = h.isXML, k.contains = h.contains, k.escapeSelector = h.escape; var T = function (e, t, n) { var r = [], i = void 0 !== n; while ((e = e[t]) && 9 !== e.nodeType) if (1 === e.nodeType) { if (i && k(e).is(n)) break; r.push(e) } return r }, S = function (e, t) { for (var n = []; e; e = e.nextSibling)1 === e.nodeType && e !== t && n.push(e); return n }, N = k.expr.match.needsContext; function A(e, t) { return e.nodeName && e.nodeName.toLowerCase() === t.toLowerCase() } var D = /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i; function j(e, n, r) { return m(n) ? k.grep(e, function (e, t) { return !!n.call(e, t, e) !== r }) : n.nodeType ? k.grep(e, function (e) { return e === n !== r }) : "string" != typeof n ? k.grep(e, function (e) { return -1 < i.call(n, e) !== r }) : k.filter(n, e, r) } k.filter = function (e, t, n) { var r = t[0]; return n && (e = ":not(" + e + ")"), 1 === t.length && 1 === r.nodeType ? k.find.matchesSelector(r, e) ? [r] : [] : k.find.matches(e, k.grep(t, function (e) { return 1 === e.nodeType })) }, k.fn.extend({ find: function (e) { var t, n, r = this.length, i = this; if ("string" != typeof e) return this.pushStack(k(e).filter(function () { for (t = 0; t < r; t++)if (k.contains(i[t], this)) return !0 })); for (n = this.pushStack([]), t = 0; t < r; t++)k.find(e, i[t], n); return 1 < r ? k.uniqueSort(n) : n }, filter: function (e) { return this.pushStack(j(this, e || [], !1)) }, not: function (e) { return this.pushStack(j(this, e || [], !0)) }, is: function (e) { return !!j(this, "string" == typeof e && N.test(e) ? k(e) : e || [], !1).length } }); var q, L = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/; (k.fn.init = function (e, t, n) { var r, i; if (!e) return this; if (n = n || q, "string" == typeof e) { if (!(r = "<" === e[0] && ">" === e[e.length - 1] && 3 <= e.length ? [null, e, null] : L.exec(e)) || !r[1] && t) return !t || t.jquery ? (t || n).find(e) : this.constructor(t).find(e); if (r[1]) { if (t = t instanceof k ? t[0] : t, k.merge(this, k.parseHTML(r[1], t && t.nodeType ? t.ownerDocument || t : E, !0)), D.test(r[1]) && k.isPlainObject(t)) for (r in t) m(this[r]) ? this[r](t[r]) : this.attr(r, t[r]); return this } return (i = E.getElementById(r[2])) && (this[0] = i, this.length = 1), this } return e.nodeType ? (this[0] = e, this.length = 1, this) : m(e) ? void 0 !== n.ready ? n.ready(e) : e(k) : k.makeArray(e, this) }).prototype = k.fn, q = k(E); var H = /^(?:parents|prev(?:Until|All))/, O = { children: !0, contents: !0, next: !0, prev: !0 }; function P(e, t) { while ((e = e[t]) && 1 !== e.nodeType); return e } k.fn.extend({ has: function (e) { var t = k(e, this), n = t.length; return this.filter(function () { for (var e = 0; e < n; e++)if (k.contains(this, t[e])) return !0 }) }, closest: function (e, t) { var n, r = 0, i = this.length, o = [], a = "string" != typeof e && k(e); if (!N.test(e)) for (; r < i; r++)for (n = this[r]; n && n !== t; n = n.parentNode)if (n.nodeType < 11 && (a ? -1 < a.index(n) : 1 === n.nodeType && k.find.matchesSelector(n, e))) { o.push(n); break } return this.pushStack(1 < o.length ? k.uniqueSort(o) : o) }, index: function (e) { return e ? "string" == typeof e ? i.call(k(e), this[0]) : i.call(this, e.jquery ? e[0] : e) : this[0] && this[0].parentNode ? this.first().prevAll().length : -1 }, add: function (e, t) { return this.pushStack(k.uniqueSort(k.merge(this.get(), k(e, t)))) }, addBack: function (e) { return this.add(null == e ? this.prevObject : this.prevObject.filter(e)) } }), k.each({ parent: function (e) { var t = e.parentNode; return t && 11 !== t.nodeType ? t : null }, parents: function (e) { return T(e, "parentNode") }, parentsUntil: function (e, t, n) { return T(e, "parentNode", n) }, next: function (e) { return P(e, "nextSibling") }, prev: function (e) { return P(e, "previousSibling") }, nextAll: function (e) { return T(e, "nextSibling") }, prevAll: function (e) { return T(e, "previousSibling") }, nextUntil: function (e, t, n) { return T(e, "nextSibling", n) }, prevUntil: function (e, t, n) { return T(e, "previousSibling", n) }, siblings: function (e) { return S((e.parentNode || {}).firstChild, e) }, children: function (e) { return S(e.firstChild) }, contents: function (e) { return "undefined" != typeof e.contentDocument ? e.contentDocument : (A(e, "template") && (e = e.content || e), k.merge([], e.childNodes)) } }, function (r, i) { k.fn[r] = function (e, t) { var n = k.map(this, i, e); return "Until" !== r.slice(-5) && (t = e), t && "string" == typeof t && (n = k.filter(t, n)), 1 < this.length && (O[r] || k.uniqueSort(n), H.test(r) && n.reverse()), this.pushStack(n) } }); var R = /[^\x20\t\r\n\f]+/g; function M(e) { return e } function I(e) { throw e } function W(e, t, n, r) { var i; try { e && m(i = e.promise) ? i.call(e).done(t).fail(n) : e && m(i = e.then) ? i.call(e, t, n) : t.apply(void 0, [e].slice(r)) } catch (e) { n.apply(void 0, [e]) } } k.Callbacks = function (r) { var e, n; r = "string" == typeof r ? (e = r, n = {}, k.each(e.match(R) || [], function (e, t) { n[t] = !0 }), n) : k.extend({}, r); var i, t, o, a, s = [], u = [], l = -1, c = function () { for (a = a || r.once, o = i = !0; u.length; l = -1) { t = u.shift(); while (++l < s.length) !1 === s[l].apply(t[0], t[1]) && r.stopOnFalse && (l = s.length, t = !1) } r.memory || (t = !1), i = !1, a && (s = t ? [] : "") }, f = { add: function () { return s && (t && !i && (l = s.length - 1, u.push(t)), function n(e) { k.each(e, function (e, t) { m(t) ? r.unique && f.has(t) || s.push(t) : t && t.length && "string" !== w(t) && n(t) }) }(arguments), t && !i && c()), this }, remove: function () { return k.each(arguments, function (e, t) { var n; while (-1 < (n = k.inArray(t, s, n))) s.splice(n, 1), n <= l && l-- }), this }, has: function (e) { return e ? -1 < k.inArray(e, s) : 0 < s.length }, empty: function () { return s && (s = []), this }, disable: function () { return a = u = [], s = t = "", this }, disabled: function () { return !s }, lock: function () { return a = u = [], t || i || (s = t = ""), this }, locked: function () { return !!a }, fireWith: function (e, t) { return a || (t = [e, (t = t || []).slice ? t.slice() : t], u.push(t), i || c()), this }, fire: function () { return f.fireWith(this, arguments), this }, fired: function () { return !!o } }; return f }, k.extend({ Deferred: function (e) { var o = [["notify", "progress", k.Callbacks("memory"), k.Callbacks("memory"), 2], ["resolve", "done", k.Callbacks("once memory"), k.Callbacks("once memory"), 0, "resolved"], ["reject", "fail", k.Callbacks("once memory"), k.Callbacks("once memory"), 1, "rejected"]], i = "pending", a = { state: function () { return i }, always: function () { return s.done(arguments).fail(arguments), this }, "catch": function (e) { return a.then(null, e) }, pipe: function () { var i = arguments; return k.Deferred(function (r) { k.each(o, function (e, t) { var n = m(i[t[4]]) && i[t[4]]; s[t[1]](function () { var e = n && n.apply(this, arguments); e && m(e.promise) ? e.promise().progress(r.notify).done(r.resolve).fail(r.reject) : r[t[0] + "With"](this, n ? [e] : arguments) }) }), i = null }).promise() }, then: function (t, n, r) { var u = 0; function l(i, o, a, s) { return function () { var n = this, r = arguments, e = function () { var e, t; if (!(i < u)) { if ((e = a.apply(n, r)) === o.promise()) throw new TypeError("Thenable self-resolution"); t = e && ("object" == typeof e || "function" == typeof e) && e.then, m(t) ? s ? t.call(e, l(u, o, M, s), l(u, o, I, s)) : (u++ , t.call(e, l(u, o, M, s), l(u, o, I, s), l(u, o, M, o.notifyWith))) : (a !== M && (n = void 0, r = [e]), (s || o.resolveWith)(n, r)) } }, t = s ? e : function () { try { e() } catch (e) { k.Deferred.exceptionHook && k.Deferred.exceptionHook(e, t.stackTrace), u <= i + 1 && (a !== I && (n = void 0, r = [e]), o.rejectWith(n, r)) } }; i ? t() : (k.Deferred.getStackHook && (t.stackTrace = k.Deferred.getStackHook()), C.setTimeout(t)) } } return k.Deferred(function (e) { o[0][3].add(l(0, e, m(r) ? r : M, e.notifyWith)), o[1][3].add(l(0, e, m(t) ? t : M)), o[2][3].add(l(0, e, m(n) ? n : I)) }).promise() }, promise: function (e) { return null != e ? k.extend(e, a) : a } }, s = {}; return k.each(o, function (e, t) { var n = t[2], r = t[5]; a[t[1]] = n.add, r && n.add(function () { i = r }, o[3 - e][2].disable, o[3 - e][3].disable, o[0][2].lock, o[0][3].lock), n.add(t[3].fire), s[t[0]] = function () { return s[t[0] + "With"](this === s ? void 0 : this, arguments), this }, s[t[0] + "With"] = n.fireWith }), a.promise(s), e && e.call(s, s), s }, when: function (e) { var n = arguments.length, t = n, r = Array(t), i = s.call(arguments), o = k.Deferred(), a = function (t) { return function (e) { r[t] = this, i[t] = 1 < arguments.length ? s.call(arguments) : e, --n || o.resolveWith(r, i) } }; if (n <= 1 && (W(e, o.done(a(t)).resolve, o.reject, !n), "pending" === o.state() || m(i[t] && i[t].then))) return o.then(); while (t--) W(i[t], a(t), o.reject); return o.promise() } }); var $ = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; k.Deferred.exceptionHook = function (e, t) { C.console && C.console.warn && e && $.test(e.name) && C.console.warn("jQuery.Deferred exception: " + e.message, e.stack, t) }, k.readyException = function (e) { C.setTimeout(function () { throw e }) }; var F = k.Deferred(); function B() { E.removeEventListener("DOMContentLoaded", B), C.removeEventListener("load", B), k.ready() } k.fn.ready = function (e) { return F.then(e)["catch"](function (e) { k.readyException(e) }), this }, k.extend({ isReady: !1, readyWait: 1, ready: function (e) { (!0 === e ? --k.readyWait : k.isReady) || (k.isReady = !0) !== e && 0 < --k.readyWait || F.resolveWith(E, [k]) } }), k.ready.then = F.then, "complete" === E.readyState || "loading" !== E.readyState && !E.documentElement.doScroll ? C.setTimeout(k.ready) : (E.addEventListener("DOMContentLoaded", B), C.addEventListener("load", B)); var _ = function (e, t, n, r, i, o, a) { var s = 0, u = e.length, l = null == n; if ("object" === w(n)) for (s in i = !0, n) _(e, t, s, n[s], !0, o, a); else if (void 0 !== r && (i = !0, m(r) || (a = !0), l && (a ? (t.call(e, r), t = null) : (l = t, t = function (e, t, n) { return l.call(k(e), n) })), t)) for (; s < u; s++)t(e[s], n, a ? r : r.call(e[s], s, t(e[s], n))); return i ? e : l ? t.call(e) : u ? t(e[0], n) : o }, z = /^-ms-/, U = /-([a-z])/g; function X(e, t) { return t.toUpperCase() } function V(e) { return e.replace(z, "ms-").replace(U, X) } var G = function (e) { return 1 === e.nodeType || 9 === e.nodeType || !+e.nodeType }; function Y() { this.expando = k.expando + Y.uid++ } Y.uid = 1, Y.prototype = { cache: function (e) { var t = e[this.expando]; return t || (t = {}, G(e) && (e.nodeType ? e[this.expando] = t : Object.defineProperty(e, this.expando, { value: t, configurable: !0 }))), t }, set: function (e, t, n) { var r, i = this.cache(e); if ("string" == typeof t) i[V(t)] = n; else for (r in t) i[V(r)] = t[r]; return i }, get: function (e, t) { return void 0 === t ? this.cache(e) : e[this.expando] && e[this.expando][V(t)] }, access: function (e, t, n) { return void 0 === t || t && "string" == typeof t && void 0 === n ? this.get(e, t) : (this.set(e, t, n), void 0 !== n ? n : t) }, remove: function (e, t) { var n, r = e[this.expando]; if (void 0 !== r) { if (void 0 !== t) { n = (t = Array.isArray(t) ? t.map(V) : (t = V(t)) in r ? [t] : t.match(R) || []).length; while (n--) delete r[t[n]] } (void 0 === t || k.isEmptyObject(r)) && (e.nodeType ? e[this.expando] = void 0 : delete e[this.expando]) } }, hasData: function (e) { var t = e[this.expando]; return void 0 !== t && !k.isEmptyObject(t) } }; var Q = new Y, J = new Y, K = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, Z = /[A-Z]/g; function ee(e, t, n) { var r, i; if (void 0 === n && 1 === e.nodeType) if (r = "data-" + t.replace(Z, "-$&").toLowerCase(), "string" == typeof (n = e.getAttribute(r))) { try { n = "true" === (i = n) || "false" !== i && ("null" === i ? null : i === +i + "" ? +i : K.test(i) ? JSON.parse(i) : i) } catch (e) { } J.set(e, t, n) } else n = void 0; return n } k.extend({ hasData: function (e) { return J.hasData(e) || Q.hasData(e) }, data: function (e, t, n) { return J.access(e, t, n) }, removeData: function (e, t) { J.remove(e, t) }, _data: function (e, t, n) { return Q.access(e, t, n) }, _removeData: function (e, t) { Q.remove(e, t) } }), k.fn.extend({ data: function (n, e) { var t, r, i, o = this[0], a = o && o.attributes; if (void 0 === n) { if (this.length && (i = J.get(o), 1 === o.nodeType && !Q.get(o, "hasDataAttrs"))) { t = a.length; while (t--) a[t] && 0 === (r = a[t].name).indexOf("data-") && (r = V(r.slice(5)), ee(o, r, i[r])); Q.set(o, "hasDataAttrs", !0) } return i } return "object" == typeof n ? this.each(function () { J.set(this, n) }) : _(this, function (e) { var t; if (o && void 0 === e) return void 0 !== (t = J.get(o, n)) ? t : void 0 !== (t = ee(o, n)) ? t : void 0; this.each(function () { J.set(this, n, e) }) }, null, e, 1 < arguments.length, null, !0) }, removeData: function (e) { return this.each(function () { J.remove(this, e) }) } }), k.extend({ queue: function (e, t, n) { var r; if (e) return t = (t || "fx") + "queue", r = Q.get(e, t), n && (!r || Array.isArray(n) ? r = Q.access(e, t, k.makeArray(n)) : r.push(n)), r || [] }, dequeue: function (e, t) { t = t || "fx"; var n = k.queue(e, t), r = n.length, i = n.shift(), o = k._queueHooks(e, t); "inprogress" === i && (i = n.shift(), r--), i && ("fx" === t && n.unshift("inprogress"), delete o.stop, i.call(e, function () { k.dequeue(e, t) }, o)), !r && o && o.empty.fire() }, _queueHooks: function (e, t) { var n = t + "queueHooks"; return Q.get(e, n) || Q.access(e, n, { empty: k.Callbacks("once memory").add(function () { Q.remove(e, [t + "queue", n]) }) }) } }), k.fn.extend({ queue: function (t, n) { var e = 2; return "string" != typeof t && (n = t, t = "fx", e--), arguments.length < e ? k.queue(this[0], t) : void 0 === n ? this : this.each(function () { var e = k.queue(this, t, n); k._queueHooks(this, t), "fx" === t && "inprogress" !== e[0] && k.dequeue(this, t) }) }, dequeue: function (e) { return this.each(function () { k.dequeue(this, e) }) }, clearQueue: function (e) { return this.queue(e || "fx", []) }, promise: function (e, t) { var n, r = 1, i = k.Deferred(), o = this, a = this.length, s = function () { --r || i.resolveWith(o, [o]) }; "string" != typeof e && (t = e, e = void 0), e = e || "fx"; while (a--) (n = Q.get(o[a], e + "queueHooks")) && n.empty && (r++ , n.empty.add(s)); return s(), i.promise(t) } }); var te = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, ne = new RegExp("^(?:([+-])=|)(" + te + ")([a-z%]*)$", "i"), re = ["Top", "Right", "Bottom", "Left"], ie = E.documentElement, oe = function (e) { return k.contains(e.ownerDocument, e) }, ae = { composed: !0 }; ie.getRootNode && (oe = function (e) { return k.contains(e.ownerDocument, e) || e.getRootNode(ae) === e.ownerDocument }); var se = function (e, t) { return "none" === (e = t || e).style.display || "" === e.style.display && oe(e) && "none" === k.css(e, "display") }, ue = function (e, t, n, r) { var i, o, a = {}; for (o in t) a[o] = e.style[o], e.style[o] = t[o]; for (o in i = n.apply(e, r || []), t) e.style[o] = a[o]; return i }; function le(e, t, n, r) { var i, o, a = 20, s = r ? function () { return r.cur() } : function () { return k.css(e, t, "") }, u = s(), l = n && n[3] || (k.cssNumber[t] ? "" : "px"), c = e.nodeType && (k.cssNumber[t] || "px" !== l && +u) && ne.exec(k.css(e, t)); if (c && c[3] !== l) { u /= 2, l = l || c[3], c = +u || 1; while (a--) k.style(e, t, c + l), (1 - o) * (1 - (o = s() / u || .5)) <= 0 && (a = 0), c /= o; c *= 2, k.style(e, t, c + l), n = n || [] } return n && (c = +c || +u || 0, i = n[1] ? c + (n[1] + 1) * n[2] : +n[2], r && (r.unit = l, r.start = c, r.end = i)), i } var ce = {}; function fe(e, t) { for (var n, r, i, o, a, s, u, l = [], c = 0, f = e.length; c < f; c++)(r = e[c]).style && (n = r.style.display, t ? ("none" === n && (l[c] = Q.get(r, "display") || null, l[c] || (r.style.display = "")), "" === r.style.display && se(r) && (l[c] = (u = a = o = void 0, a = (i = r).ownerDocument, s = i.nodeName, (u = ce[s]) || (o = a.body.appendChild(a.createElement(s)), u = k.css(o, "display"), o.parentNode.removeChild(o), "none" === u && (u = "block"), ce[s] = u)))) : "none" !== n && (l[c] = "none", Q.set(r, "display", n))); for (c = 0; c < f; c++)null != l[c] && (e[c].style.display = l[c]); return e } k.fn.extend({ show: function () { return fe(this, !0) }, hide: function () { return fe(this) }, toggle: function (e) { return "boolean" == typeof e ? e ? this.show() : this.hide() : this.each(function () { se(this) ? k(this).show() : k(this).hide() }) } }); var pe = /^(?:checkbox|radio)$/i, de = /<([a-z][^\/\0>\x20\t\r\n\f]*)/i, he = /^$|^module$|\/(?:java|ecma)script/i, ge = { option: [1, ""], thead: [1, "", "
"], col: [2, "", "
"], tr: [2, "", "
"], td: [3, "", "
"], _default: [0, "", ""] }; function ve(e, t) { var n; return n = "undefined" != typeof e.getElementsByTagName ? e.getElementsByTagName(t || "*") : "undefined" != typeof e.querySelectorAll ? e.querySelectorAll(t || "*") : [], void 0 === t || t && A(e, t) ? k.merge([e], n) : n } function ye(e, t) { for (var n = 0, r = e.length; n < r; n++)Q.set(e[n], "globalEval", !t || Q.get(t[n], "globalEval")) } ge.optgroup = ge.option, ge.tbody = ge.tfoot = ge.colgroup = ge.caption = ge.thead, ge.th = ge.td; var me, xe, be = /<|&#?\w+;/; function we(e, t, n, r, i) { for (var o, a, s, u, l, c, f = t.createDocumentFragment(), p = [], d = 0, h = e.length; d < h; d++)if ((o = e[d]) || 0 === o) if ("object" === w(o)) k.merge(p, o.nodeType ? [o] : o); else if (be.test(o)) { a = a || f.appendChild(t.createElement("div")), s = (de.exec(o) || ["", ""])[1].toLowerCase(), u = ge[s] || ge._default, a.innerHTML = u[1] + k.htmlPrefilter(o) + u[2], c = u[0]; while (c--) a = a.lastChild; k.merge(p, a.childNodes), (a = f.firstChild).textContent = "" } else p.push(t.createTextNode(o)); f.textContent = "", d = 0; while (o = p[d++]) if (r && -1 < k.inArray(o, r)) i && i.push(o); else if (l = oe(o), a = ve(f.appendChild(o), "script"), l && ye(a), n) { c = 0; while (o = a[c++]) he.test(o.type || "") && n.push(o) } return f } me = E.createDocumentFragment().appendChild(E.createElement("div")), (xe = E.createElement("input")).setAttribute("type", "radio"), xe.setAttribute("checked", "checked"), xe.setAttribute("name", "t"), me.appendChild(xe), y.checkClone = me.cloneNode(!0).cloneNode(!0).lastChild.checked, me.innerHTML = "", y.noCloneChecked = !!me.cloneNode(!0).lastChild.defaultValue; var Te = /^key/, Ce = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, Ee = /^([^.]*)(?:\.(.+)|)/; function ke() { return !0 } function Se() { return !1 } function Ne(e, t) { return e === function () { try { return E.activeElement } catch (e) { } }() == ("focus" === t) } function Ae(e, t, n, r, i, o) { var a, s; if ("object" == typeof t) { for (s in "string" != typeof n && (r = r || n, n = void 0), t) Ae(e, s, n, r, t[s], o); return e } if (null == r && null == i ? (i = n, r = n = void 0) : null == i && ("string" == typeof n ? (i = r, r = void 0) : (i = r, r = n, n = void 0)), !1 === i) i = Se; else if (!i) return e; return 1 === o && (a = i, (i = function (e) { return k().off(e), a.apply(this, arguments) }).guid = a.guid || (a.guid = k.guid++)), e.each(function () { k.event.add(this, t, i, r, n) }) } function De(e, i, o) { o ? (Q.set(e, i, !1), k.event.add(e, i, { namespace: !1, handler: function (e) { var t, n, r = Q.get(this, i); if (1 & e.isTrigger && this[i]) { if (r.length) (k.event.special[i] || {}).delegateType && e.stopPropagation(); else if (r = s.call(arguments), Q.set(this, i, r), t = o(this, i), this[i](), r !== (n = Q.get(this, i)) || t ? Q.set(this, i, !1) : n = {}, r !== n) return e.stopImmediatePropagation(), e.preventDefault(), n.value } else r.length && (Q.set(this, i, { value: k.event.trigger(k.extend(r[0], k.Event.prototype), r.slice(1), this) }), e.stopImmediatePropagation()) } })) : void 0 === Q.get(e, i) && k.event.add(e, i, ke) } k.event = { global: {}, add: function (t, e, n, r, i) { var o, a, s, u, l, c, f, p, d, h, g, v = Q.get(t); if (v) { n.handler && (n = (o = n).handler, i = o.selector), i && k.find.matchesSelector(ie, i), n.guid || (n.guid = k.guid++), (u = v.events) || (u = v.events = {}), (a = v.handle) || (a = v.handle = function (e) { return "undefined" != typeof k && k.event.triggered !== e.type ? k.event.dispatch.apply(t, arguments) : void 0 }), l = (e = (e || "").match(R) || [""]).length; while (l--) d = g = (s = Ee.exec(e[l]) || [])[1], h = (s[2] || "").split(".").sort(), d && (f = k.event.special[d] || {}, d = (i ? f.delegateType : f.bindType) || d, f = k.event.special[d] || {}, c = k.extend({ type: d, origType: g, data: r, handler: n, guid: n.guid, selector: i, needsContext: i && k.expr.match.needsContext.test(i), namespace: h.join(".") }, o), (p = u[d]) || ((p = u[d] = []).delegateCount = 0, f.setup && !1 !== f.setup.call(t, r, h, a) || t.addEventListener && t.addEventListener(d, a)), f.add && (f.add.call(t, c), c.handler.guid || (c.handler.guid = n.guid)), i ? p.splice(p.delegateCount++, 0, c) : p.push(c), k.event.global[d] = !0) } }, remove: function (e, t, n, r, i) { var o, a, s, u, l, c, f, p, d, h, g, v = Q.hasData(e) && Q.get(e); if (v && (u = v.events)) { l = (t = (t || "").match(R) || [""]).length; while (l--) if (d = g = (s = Ee.exec(t[l]) || [])[1], h = (s[2] || "").split(".").sort(), d) { f = k.event.special[d] || {}, p = u[d = (r ? f.delegateType : f.bindType) || d] || [], s = s[2] && new RegExp("(^|\\.)" + h.join("\\.(?:.*\\.|)") + "(\\.|$)"), a = o = p.length; while (o--) c = p[o], !i && g !== c.origType || n && n.guid !== c.guid || s && !s.test(c.namespace) || r && r !== c.selector && ("**" !== r || !c.selector) || (p.splice(o, 1), c.selector && p.delegateCount-- , f.remove && f.remove.call(e, c)); a && !p.length && (f.teardown && !1 !== f.teardown.call(e, h, v.handle) || k.removeEvent(e, d, v.handle), delete u[d]) } else for (d in u) k.event.remove(e, d + t[l], n, r, !0); k.isEmptyObject(u) && Q.remove(e, "handle events") } }, dispatch: function (e) { var t, n, r, i, o, a, s = k.event.fix(e), u = new Array(arguments.length), l = (Q.get(this, "events") || {})[s.type] || [], c = k.event.special[s.type] || {}; for (u[0] = s, t = 1; t < arguments.length; t++)u[t] = arguments[t]; if (s.delegateTarget = this, !c.preDispatch || !1 !== c.preDispatch.call(this, s)) { a = k.event.handlers.call(this, s, l), t = 0; while ((i = a[t++]) && !s.isPropagationStopped()) { s.currentTarget = i.elem, n = 0; while ((o = i.handlers[n++]) && !s.isImmediatePropagationStopped()) s.rnamespace && !1 !== o.namespace && !s.rnamespace.test(o.namespace) || (s.handleObj = o, s.data = o.data, void 0 !== (r = ((k.event.special[o.origType] || {}).handle || o.handler).apply(i.elem, u)) && !1 === (s.result = r) && (s.preventDefault(), s.stopPropagation())) } return c.postDispatch && c.postDispatch.call(this, s), s.result } }, handlers: function (e, t) { var n, r, i, o, a, s = [], u = t.delegateCount, l = e.target; if (u && l.nodeType && !("click" === e.type && 1 <= e.button)) for (; l !== this; l = l.parentNode || this)if (1 === l.nodeType && ("click" !== e.type || !0 !== l.disabled)) { for (o = [], a = {}, n = 0; n < u; n++)void 0 === a[i = (r = t[n]).selector + " "] && (a[i] = r.needsContext ? -1 < k(i, this).index(l) : k.find(i, this, null, [l]).length), a[i] && o.push(r); o.length && s.push({ elem: l, handlers: o }) } return l = this, u < t.length && s.push({ elem: l, handlers: t.slice(u) }), s }, addProp: function (t, e) { Object.defineProperty(k.Event.prototype, t, { enumerable: !0, configurable: !0, get: m(e) ? function () { if (this.originalEvent) return e(this.originalEvent) } : function () { if (this.originalEvent) return this.originalEvent[t] }, set: function (e) { Object.defineProperty(this, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) } }) }, fix: function (e) { return e[k.expando] ? e : new k.Event(e) }, special: { load: { noBubble: !0 }, click: { setup: function (e) { var t = this || e; return pe.test(t.type) && t.click && A(t, "input") && De(t, "click", ke), !1 }, trigger: function (e) { var t = this || e; return pe.test(t.type) && t.click && A(t, "input") && De(t, "click"), !0 }, _default: function (e) { var t = e.target; return pe.test(t.type) && t.click && A(t, "input") && Q.get(t, "click") || A(t, "a") } }, beforeunload: { postDispatch: function (e) { void 0 !== e.result && e.originalEvent && (e.originalEvent.returnValue = e.result) } } } }, k.removeEvent = function (e, t, n) { e.removeEventListener && e.removeEventListener(t, n) }, k.Event = function (e, t) { if (!(this instanceof k.Event)) return new k.Event(e, t); e && e.type ? (this.originalEvent = e, this.type = e.type, this.isDefaultPrevented = e.defaultPrevented || void 0 === e.defaultPrevented && !1 === e.returnValue ? ke : Se, this.target = e.target && 3 === e.target.nodeType ? e.target.parentNode : e.target, this.currentTarget = e.currentTarget, this.relatedTarget = e.relatedTarget) : this.type = e, t && k.extend(this, t), this.timeStamp = e && e.timeStamp || Date.now(), this[k.expando] = !0 }, k.Event.prototype = { constructor: k.Event, isDefaultPrevented: Se, isPropagationStopped: Se, isImmediatePropagationStopped: Se, isSimulated: !1, preventDefault: function () { var e = this.originalEvent; this.isDefaultPrevented = ke, e && !this.isSimulated && e.preventDefault() }, stopPropagation: function () { var e = this.originalEvent; this.isPropagationStopped = ke, e && !this.isSimulated && e.stopPropagation() }, stopImmediatePropagation: function () { var e = this.originalEvent; this.isImmediatePropagationStopped = ke, e && !this.isSimulated && e.stopImmediatePropagation(), this.stopPropagation() } }, k.each({ altKey: !0, bubbles: !0, cancelable: !0, changedTouches: !0, ctrlKey: !0, detail: !0, eventPhase: !0, metaKey: !0, pageX: !0, pageY: !0, shiftKey: !0, view: !0, "char": !0, code: !0, charCode: !0, key: !0, keyCode: !0, button: !0, buttons: !0, clientX: !0, clientY: !0, offsetX: !0, offsetY: !0, pointerId: !0, pointerType: !0, screenX: !0, screenY: !0, targetTouches: !0, toElement: !0, touches: !0, which: function (e) { var t = e.button; return null == e.which && Te.test(e.type) ? null != e.charCode ? e.charCode : e.keyCode : !e.which && void 0 !== t && Ce.test(e.type) ? 1 & t ? 1 : 2 & t ? 3 : 4 & t ? 2 : 0 : e.which } }, k.event.addProp), k.each({ focus: "focusin", blur: "focusout" }, function (e, t) { k.event.special[e] = { setup: function () { return De(this, e, Ne), !1 }, trigger: function () { return De(this, e), !0 }, delegateType: t } }), k.each({ mouseenter: "mouseover", mouseleave: "mouseout", pointerenter: "pointerover", pointerleave: "pointerout" }, function (e, i) { k.event.special[e] = { delegateType: i, bindType: i, handle: function (e) { var t, n = e.relatedTarget, r = e.handleObj; return n && (n === this || k.contains(this, n)) || (e.type = r.origType, t = r.handler.apply(this, arguments), e.type = i), t } } }), k.fn.extend({ on: function (e, t, n, r) { return Ae(this, e, t, n, r) }, one: function (e, t, n, r) { return Ae(this, e, t, n, r, 1) }, off: function (e, t, n) { var r, i; if (e && e.preventDefault && e.handleObj) return r = e.handleObj, k(e.delegateTarget).off(r.namespace ? r.origType + "." + r.namespace : r.origType, r.selector, r.handler), this; if ("object" == typeof e) { for (i in e) this.off(i, t, e[i]); return this } return !1 !== t && "function" != typeof t || (n = t, t = void 0), !1 === n && (n = Se), this.each(function () { k.event.remove(this, e, n, t) }) } }); var je = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, qe = /\s*$/g; function Oe(e, t) { return A(e, "table") && A(11 !== t.nodeType ? t : t.firstChild, "tr") && k(e).children("tbody")[0] || e } function Pe(e) { return e.type = (null !== e.getAttribute("type")) + "/" + e.type, e } function Re(e) { return "true/" === (e.type || "").slice(0, 5) ? e.type = e.type.slice(5) : e.removeAttribute("type"), e } function Me(e, t) { var n, r, i, o, a, s, u, l; if (1 === t.nodeType) { if (Q.hasData(e) && (o = Q.access(e), a = Q.set(t, o), l = o.events)) for (i in delete a.handle, a.events = {}, l) for (n = 0, r = l[i].length; n < r; n++)k.event.add(t, i, l[i][n]); J.hasData(e) && (s = J.access(e), u = k.extend({}, s), J.set(t, u)) } } function Ie(n, r, i, o) { r = g.apply([], r); var e, t, a, s, u, l, c = 0, f = n.length, p = f - 1, d = r[0], h = m(d); if (h || 1 < f && "string" == typeof d && !y.checkClone && Le.test(d)) return n.each(function (e) { var t = n.eq(e); h && (r[0] = d.call(this, e, t.html())), Ie(t, r, i, o) }); if (f && (t = (e = we(r, n[0].ownerDocument, !1, n, o)).firstChild, 1 === e.childNodes.length && (e = t), t || o)) { for (s = (a = k.map(ve(e, "script"), Pe)).length; c < f; c++)u = e, c !== p && (u = k.clone(u, !0, !0), s && k.merge(a, ve(u, "script"))), i.call(n[c], u, c); if (s) for (l = a[a.length - 1].ownerDocument, k.map(a, Re), c = 0; c < s; c++)u = a[c], he.test(u.type || "") && !Q.access(u, "globalEval") && k.contains(l, u) && (u.src && "module" !== (u.type || "").toLowerCase() ? k._evalUrl && !u.noModule && k._evalUrl(u.src, { nonce: u.nonce || u.getAttribute("nonce") }) : b(u.textContent.replace(He, ""), u, l)) } return n } function We(e, t, n) { for (var r, i = t ? k.filter(t, e) : e, o = 0; null != (r = i[o]); o++)n || 1 !== r.nodeType || k.cleanData(ve(r)), r.parentNode && (n && oe(r) && ye(ve(r, "script")), r.parentNode.removeChild(r)); return e } k.extend({ htmlPrefilter: function (e) { return e.replace(je, "<$1>") }, clone: function (e, t, n) { var r, i, o, a, s, u, l, c = e.cloneNode(!0), f = oe(e); if (!(y.noCloneChecked || 1 !== e.nodeType && 11 !== e.nodeType || k.isXMLDoc(e))) for (a = ve(c), r = 0, i = (o = ve(e)).length; r < i; r++)s = o[r], u = a[r], void 0, "input" === (l = u.nodeName.toLowerCase()) && pe.test(s.type) ? u.checked = s.checked : "input" !== l && "textarea" !== l || (u.defaultValue = s.defaultValue); if (t) if (n) for (o = o || ve(e), a = a || ve(c), r = 0, i = o.length; r < i; r++)Me(o[r], a[r]); else Me(e, c); return 0 < (a = ve(c, "script")).length && ye(a, !f && ve(e, "script")), c }, cleanData: function (e) { for (var t, n, r, i = k.event.special, o = 0; void 0 !== (n = e[o]); o++)if (G(n)) { if (t = n[Q.expando]) { if (t.events) for (r in t.events) i[r] ? k.event.remove(n, r) : k.removeEvent(n, r, t.handle); n[Q.expando] = void 0 } n[J.expando] && (n[J.expando] = void 0) } } }), k.fn.extend({ detach: function (e) { return We(this, e, !0) }, remove: function (e) { return We(this, e) }, text: function (e) { return _(this, function (e) { return void 0 === e ? k.text(this) : this.empty().each(function () { 1 !== this.nodeType && 11 !== this.nodeType && 9 !== this.nodeType || (this.textContent = e) }) }, null, e, arguments.length) }, append: function () { return Ie(this, arguments, function (e) { 1 !== this.nodeType && 11 !== this.nodeType && 9 !== this.nodeType || Oe(this, e).appendChild(e) }) }, prepend: function () { return Ie(this, arguments, function (e) { if (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) { var t = Oe(this, e); t.insertBefore(e, t.firstChild) } }) }, before: function () { return Ie(this, arguments, function (e) { this.parentNode && this.parentNode.insertBefore(e, this) }) }, after: function () { return Ie(this, arguments, function (e) { this.parentNode && this.parentNode.insertBefore(e, this.nextSibling) }) }, empty: function () { for (var e, t = 0; null != (e = this[t]); t++)1 === e.nodeType && (k.cleanData(ve(e, !1)), e.textContent = ""); return this }, clone: function (e, t) { return e = null != e && e, t = null == t ? e : t, this.map(function () { return k.clone(this, e, t) }) }, html: function (e) { return _(this, function (e) { var t = this[0] || {}, n = 0, r = this.length; if (void 0 === e && 1 === t.nodeType) return t.innerHTML; if ("string" == typeof e && !qe.test(e) && !ge[(de.exec(e) || ["", ""])[1].toLowerCase()]) { e = k.htmlPrefilter(e); try { for (; n < r; n++)1 === (t = this[n] || {}).nodeType && (k.cleanData(ve(t, !1)), t.innerHTML = e); t = 0 } catch (e) { } } t && this.empty().append(e) }, null, e, arguments.length) }, replaceWith: function () { var n = []; return Ie(this, arguments, function (e) { var t = this.parentNode; k.inArray(this, n) < 0 && (k.cleanData(ve(this)), t && t.replaceChild(e, this)) }, n) } }), k.each({ appendTo: "append", prependTo: "prepend", insertBefore: "before", insertAfter: "after", replaceAll: "replaceWith" }, function (e, a) { k.fn[e] = function (e) { for (var t, n = [], r = k(e), i = r.length - 1, o = 0; o <= i; o++)t = o === i ? this : this.clone(!0), k(r[o])[a](t), u.apply(n, t.get()); return this.pushStack(n) } }); var $e = new RegExp("^(" + te + ")(?!px)[a-z%]+$", "i"), Fe = function (e) { var t = e.ownerDocument.defaultView; return t && t.opener || (t = C), t.getComputedStyle(e) }, Be = new RegExp(re.join("|"), "i"); function _e(e, t, n) { var r, i, o, a, s = e.style; return (n = n || Fe(e)) && ("" !== (a = n.getPropertyValue(t) || n[t]) || oe(e) || (a = k.style(e, t)), !y.pixelBoxStyles() && $e.test(a) && Be.test(t) && (r = s.width, i = s.minWidth, o = s.maxWidth, s.minWidth = s.maxWidth = s.width = a, a = n.width, s.width = r, s.minWidth = i, s.maxWidth = o)), void 0 !== a ? a + "" : a } function ze(e, t) { return { get: function () { if (!e()) return (this.get = t).apply(this, arguments); delete this.get } } } !function () { function e() { if (u) { s.style.cssText = "position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0", u.style.cssText = "position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%", ie.appendChild(s).appendChild(u); var e = C.getComputedStyle(u); n = "1%" !== e.top, a = 12 === t(e.marginLeft), u.style.right = "60%", o = 36 === t(e.right), r = 36 === t(e.width), u.style.position = "absolute", i = 12 === t(u.offsetWidth / 3), ie.removeChild(s), u = null } } function t(e) { return Math.round(parseFloat(e)) } var n, r, i, o, a, s = E.createElement("div"), u = E.createElement("div"); u.style && (u.style.backgroundClip = "content-box", u.cloneNode(!0).style.backgroundClip = "", y.clearCloneStyle = "content-box" === u.style.backgroundClip, k.extend(y, { boxSizingReliable: function () { return e(), r }, pixelBoxStyles: function () { return e(), o }, pixelPosition: function () { return e(), n }, reliableMarginLeft: function () { return e(), a }, scrollboxSize: function () { return e(), i } })) }(); var Ue = ["Webkit", "Moz", "ms"], Xe = E.createElement("div").style, Ve = {}; function Ge(e) { var t = k.cssProps[e] || Ve[e]; return t || (e in Xe ? e : Ve[e] = function (e) { var t = e[0].toUpperCase() + e.slice(1), n = Ue.length; while (n--) if ((e = Ue[n] + t) in Xe) return e }(e) || e) } var Ye = /^(none|table(?!-c[ea]).+)/, Qe = /^--/, Je = { position: "absolute", visibility: "hidden", display: "block" }, Ke = { letterSpacing: "0", fontWeight: "400" }; function Ze(e, t, n) { var r = ne.exec(t); return r ? Math.max(0, r[2] - (n || 0)) + (r[3] || "px") : t } function et(e, t, n, r, i, o) { var a = "width" === t ? 1 : 0, s = 0, u = 0; if (n === (r ? "border" : "content")) return 0; for (; a < 4; a += 2)"margin" === n && (u += k.css(e, n + re[a], !0, i)), r ? ("content" === n && (u -= k.css(e, "padding" + re[a], !0, i)), "margin" !== n && (u -= k.css(e, "border" + re[a] + "Width", !0, i))) : (u += k.css(e, "padding" + re[a], !0, i), "padding" !== n ? u += k.css(e, "border" + re[a] + "Width", !0, i) : s += k.css(e, "border" + re[a] + "Width", !0, i)); return !r && 0 <= o && (u += Math.max(0, Math.ceil(e["offset" + t[0].toUpperCase() + t.slice(1)] - o - u - s - .5)) || 0), u } function tt(e, t, n) { var r = Fe(e), i = (!y.boxSizingReliable() || n) && "border-box" === k.css(e, "boxSizing", !1, r), o = i, a = _e(e, t, r), s = "offset" + t[0].toUpperCase() + t.slice(1); if ($e.test(a)) { if (!n) return a; a = "auto" } return (!y.boxSizingReliable() && i || "auto" === a || !parseFloat(a) && "inline" === k.css(e, "display", !1, r)) && e.getClientRects().length && (i = "border-box" === k.css(e, "boxSizing", !1, r), (o = s in e) && (a = e[s])), (a = parseFloat(a) || 0) + et(e, t, n || (i ? "border" : "content"), o, r, a) + "px" } function nt(e, t, n, r, i) { return new nt.prototype.init(e, t, n, r, i) } k.extend({ cssHooks: { opacity: { get: function (e, t) { if (t) { var n = _e(e, "opacity"); return "" === n ? "1" : n } } } }, cssNumber: { animationIterationCount: !0, columnCount: !0, fillOpacity: !0, flexGrow: !0, flexShrink: !0, fontWeight: !0, gridArea: !0, gridColumn: !0, gridColumnEnd: !0, gridColumnStart: !0, gridRow: !0, gridRowEnd: !0, gridRowStart: !0, lineHeight: !0, opacity: !0, order: !0, orphans: !0, widows: !0, zIndex: !0, zoom: !0 }, cssProps: {}, style: function (e, t, n, r) { if (e && 3 !== e.nodeType && 8 !== e.nodeType && e.style) { var i, o, a, s = V(t), u = Qe.test(t), l = e.style; if (u || (t = Ge(s)), a = k.cssHooks[t] || k.cssHooks[s], void 0 === n) return a && "get" in a && void 0 !== (i = a.get(e, !1, r)) ? i : l[t]; "string" === (o = typeof n) && (i = ne.exec(n)) && i[1] && (n = le(e, t, i), o = "number"), null != n && n == n && ("number" !== o || u || (n += i && i[3] || (k.cssNumber[s] ? "" : "px")), y.clearCloneStyle || "" !== n || 0 !== t.indexOf("background") || (l[t] = "inherit"), a && "set" in a && void 0 === (n = a.set(e, n, r)) || (u ? l.setProperty(t, n) : l[t] = n)) } }, css: function (e, t, n, r) { var i, o, a, s = V(t); return Qe.test(t) || (t = Ge(s)), (a = k.cssHooks[t] || k.cssHooks[s]) && "get" in a && (i = a.get(e, !0, n)), void 0 === i && (i = _e(e, t, r)), "normal" === i && t in Ke && (i = Ke[t]), "" === n || n ? (o = parseFloat(i), !0 === n || isFinite(o) ? o || 0 : i) : i } }), k.each(["height", "width"], function (e, u) { k.cssHooks[u] = { get: function (e, t, n) { if (t) return !Ye.test(k.css(e, "display")) || e.getClientRects().length && e.getBoundingClientRect().width ? tt(e, u, n) : ue(e, Je, function () { return tt(e, u, n) }) }, set: function (e, t, n) { var r, i = Fe(e), o = !y.scrollboxSize() && "absolute" === i.position, a = (o || n) && "border-box" === k.css(e, "boxSizing", !1, i), s = n ? et(e, u, n, a, i) : 0; return a && o && (s -= Math.ceil(e["offset" + u[0].toUpperCase() + u.slice(1)] - parseFloat(i[u]) - et(e, u, "border", !1, i) - .5)), s && (r = ne.exec(t)) && "px" !== (r[3] || "px") && (e.style[u] = t, t = k.css(e, u)), Ze(0, t, s) } } }), k.cssHooks.marginLeft = ze(y.reliableMarginLeft, function (e, t) { if (t) return (parseFloat(_e(e, "marginLeft")) || e.getBoundingClientRect().left - ue(e, { marginLeft: 0 }, function () { return e.getBoundingClientRect().left })) + "px" }), k.each({ margin: "", padding: "", border: "Width" }, function (i, o) { k.cssHooks[i + o] = { expand: function (e) { for (var t = 0, n = {}, r = "string" == typeof e ? e.split(" ") : [e]; t < 4; t++)n[i + re[t] + o] = r[t] || r[t - 2] || r[0]; return n } }, "margin" !== i && (k.cssHooks[i + o].set = Ze) }), k.fn.extend({ css: function (e, t) { return _(this, function (e, t, n) { var r, i, o = {}, a = 0; if (Array.isArray(t)) { for (r = Fe(e), i = t.length; a < i; a++)o[t[a]] = k.css(e, t[a], !1, r); return o } return void 0 !== n ? k.style(e, t, n) : k.css(e, t) }, e, t, 1 < arguments.length) } }), ((k.Tween = nt).prototype = { constructor: nt, init: function (e, t, n, r, i, o) { this.elem = e, this.prop = n, this.easing = i || k.easing._default, this.options = t, this.start = this.now = this.cur(), this.end = r, this.unit = o || (k.cssNumber[n] ? "" : "px") }, cur: function () { var e = nt.propHooks[this.prop]; return e && e.get ? e.get(this) : nt.propHooks._default.get(this) }, run: function (e) { var t, n = nt.propHooks[this.prop]; return this.options.duration ? this.pos = t = k.easing[this.easing](e, this.options.duration * e, 0, 1, this.options.duration) : this.pos = t = e, this.now = (this.end - this.start) * t + this.start, this.options.step && this.options.step.call(this.elem, this.now, this), n && n.set ? n.set(this) : nt.propHooks._default.set(this), this } }).init.prototype = nt.prototype, (nt.propHooks = { _default: { get: function (e) { var t; return 1 !== e.elem.nodeType || null != e.elem[e.prop] && null == e.elem.style[e.prop] ? e.elem[e.prop] : (t = k.css(e.elem, e.prop, "")) && "auto" !== t ? t : 0 }, set: function (e) { k.fx.step[e.prop] ? k.fx.step[e.prop](e) : 1 !== e.elem.nodeType || !k.cssHooks[e.prop] && null == e.elem.style[Ge(e.prop)] ? e.elem[e.prop] = e.now : k.style(e.elem, e.prop, e.now + e.unit) } } }).scrollTop = nt.propHooks.scrollLeft = { set: function (e) { e.elem.nodeType && e.elem.parentNode && (e.elem[e.prop] = e.now) } }, k.easing = { linear: function (e) { return e }, swing: function (e) { return .5 - Math.cos(e * Math.PI) / 2 }, _default: "swing" }, k.fx = nt.prototype.init, k.fx.step = {}; var rt, it, ot, at, st = /^(?:toggle|show|hide)$/, ut = /queueHooks$/; function lt() { it && (!1 === E.hidden && C.requestAnimationFrame ? C.requestAnimationFrame(lt) : C.setTimeout(lt, k.fx.interval), k.fx.tick()) } function ct() { return C.setTimeout(function () { rt = void 0 }), rt = Date.now() } function ft(e, t) { var n, r = 0, i = { height: e }; for (t = t ? 1 : 0; r < 4; r += 2 - t)i["margin" + (n = re[r])] = i["padding" + n] = e; return t && (i.opacity = i.width = e), i } function pt(e, t, n) { for (var r, i = (dt.tweeners[t] || []).concat(dt.tweeners["*"]), o = 0, a = i.length; o < a; o++)if (r = i[o].call(n, t, e)) return r } function dt(o, e, t) { var n, a, r = 0, i = dt.prefilters.length, s = k.Deferred().always(function () { delete u.elem }), u = function () { if (a) return !1; for (var e = rt || ct(), t = Math.max(0, l.startTime + l.duration - e), n = 1 - (t / l.duration || 0), r = 0, i = l.tweens.length; r < i; r++)l.tweens[r].run(n); return s.notifyWith(o, [l, n, t]), n < 1 && i ? t : (i || s.notifyWith(o, [l, 1, 0]), s.resolveWith(o, [l]), !1) }, l = s.promise({ elem: o, props: k.extend({}, e), opts: k.extend(!0, { specialEasing: {}, easing: k.easing._default }, t), originalProperties: e, originalOptions: t, startTime: rt || ct(), duration: t.duration, tweens: [], createTween: function (e, t) { var n = k.Tween(o, l.opts, e, t, l.opts.specialEasing[e] || l.opts.easing); return l.tweens.push(n), n }, stop: function (e) { var t = 0, n = e ? l.tweens.length : 0; if (a) return this; for (a = !0; t < n; t++)l.tweens[t].run(1); return e ? (s.notifyWith(o, [l, 1, 0]), s.resolveWith(o, [l, e])) : s.rejectWith(o, [l, e]), this } }), c = l.props; for (!function (e, t) { var n, r, i, o, a; for (n in e) if (i = t[r = V(n)], o = e[n], Array.isArray(o) && (i = o[1], o = e[n] = o[0]), n !== r && (e[r] = o, delete e[n]), (a = k.cssHooks[r]) && "expand" in a) for (n in o = a.expand(o), delete e[r], o) n in e || (e[n] = o[n], t[n] = i); else t[r] = i }(c, l.opts.specialEasing); r < i; r++)if (n = dt.prefilters[r].call(l, o, c, l.opts)) return m(n.stop) && (k._queueHooks(l.elem, l.opts.queue).stop = n.stop.bind(n)), n; return k.map(c, pt, l), m(l.opts.start) && l.opts.start.call(o, l), l.progress(l.opts.progress).done(l.opts.done, l.opts.complete).fail(l.opts.fail).always(l.opts.always), k.fx.timer(k.extend(u, { elem: o, anim: l, queue: l.opts.queue })), l } k.Animation = k.extend(dt, { tweeners: { "*": [function (e, t) { var n = this.createTween(e, t); return le(n.elem, e, ne.exec(t), n), n }] }, tweener: function (e, t) { m(e) ? (t = e, e = ["*"]) : e = e.match(R); for (var n, r = 0, i = e.length; r < i; r++)n = e[r], dt.tweeners[n] = dt.tweeners[n] || [], dt.tweeners[n].unshift(t) }, prefilters: [function (e, t, n) { var r, i, o, a, s, u, l, c, f = "width" in t || "height" in t, p = this, d = {}, h = e.style, g = e.nodeType && se(e), v = Q.get(e, "fxshow"); for (r in n.queue || (null == (a = k._queueHooks(e, "fx")).unqueued && (a.unqueued = 0, s = a.empty.fire, a.empty.fire = function () { a.unqueued || s() }), a.unqueued++ , p.always(function () { p.always(function () { a.unqueued-- , k.queue(e, "fx").length || a.empty.fire() }) })), t) if (i = t[r], st.test(i)) { if (delete t[r], o = o || "toggle" === i, i === (g ? "hide" : "show")) { if ("show" !== i || !v || void 0 === v[r]) continue; g = !0 } d[r] = v && v[r] || k.style(e, r) } if ((u = !k.isEmptyObject(t)) || !k.isEmptyObject(d)) for (r in f && 1 === e.nodeType && (n.overflow = [h.overflow, h.overflowX, h.overflowY], null == (l = v && v.display) && (l = Q.get(e, "display")), "none" === (c = k.css(e, "display")) && (l ? c = l : (fe([e], !0), l = e.style.display || l, c = k.css(e, "display"), fe([e]))), ("inline" === c || "inline-block" === c && null != l) && "none" === k.css(e, "float") && (u || (p.done(function () { h.display = l }), null == l && (c = h.display, l = "none" === c ? "" : c)), h.display = "inline-block")), n.overflow && (h.overflow = "hidden", p.always(function () { h.overflow = n.overflow[0], h.overflowX = n.overflow[1], h.overflowY = n.overflow[2] })), u = !1, d) u || (v ? "hidden" in v && (g = v.hidden) : v = Q.access(e, "fxshow", { display: l }), o && (v.hidden = !g), g && fe([e], !0), p.done(function () { for (r in g || fe([e]), Q.remove(e, "fxshow"), d) k.style(e, r, d[r]) })), u = pt(g ? v[r] : 0, r, p), r in v || (v[r] = u.start, g && (u.end = u.start, u.start = 0)) }], prefilter: function (e, t) { t ? dt.prefilters.unshift(e) : dt.prefilters.push(e) } }), k.speed = function (e, t, n) { var r = e && "object" == typeof e ? k.extend({}, e) : { complete: n || !n && t || m(e) && e, duration: e, easing: n && t || t && !m(t) && t }; return k.fx.off ? r.duration = 0 : "number" != typeof r.duration && (r.duration in k.fx.speeds ? r.duration = k.fx.speeds[r.duration] : r.duration = k.fx.speeds._default), null != r.queue && !0 !== r.queue || (r.queue = "fx"), r.old = r.complete, r.complete = function () { m(r.old) && r.old.call(this), r.queue && k.dequeue(this, r.queue) }, r }, k.fn.extend({ fadeTo: function (e, t, n, r) { return this.filter(se).css("opacity", 0).show().end().animate({ opacity: t }, e, n, r) }, animate: function (t, e, n, r) { var i = k.isEmptyObject(t), o = k.speed(e, n, r), a = function () { var e = dt(this, k.extend({}, t), o); (i || Q.get(this, "finish")) && e.stop(!0) }; return a.finish = a, i || !1 === o.queue ? this.each(a) : this.queue(o.queue, a) }, stop: function (i, e, o) { var a = function (e) { var t = e.stop; delete e.stop, t(o) }; return "string" != typeof i && (o = e, e = i, i = void 0), e && !1 !== i && this.queue(i || "fx", []), this.each(function () { var e = !0, t = null != i && i + "queueHooks", n = k.timers, r = Q.get(this); if (t) r[t] && r[t].stop && a(r[t]); else for (t in r) r[t] && r[t].stop && ut.test(t) && a(r[t]); for (t = n.length; t--;)n[t].elem !== this || null != i && n[t].queue !== i || (n[t].anim.stop(o), e = !1, n.splice(t, 1)); !e && o || k.dequeue(this, i) }) }, finish: function (a) { return !1 !== a && (a = a || "fx"), this.each(function () { var e, t = Q.get(this), n = t[a + "queue"], r = t[a + "queueHooks"], i = k.timers, o = n ? n.length : 0; for (t.finish = !0, k.queue(this, a, []), r && r.stop && r.stop.call(this, !0), e = i.length; e--;)i[e].elem === this && i[e].queue === a && (i[e].anim.stop(!0), i.splice(e, 1)); for (e = 0; e < o; e++)n[e] && n[e].finish && n[e].finish.call(this); delete t.finish }) } }), k.each(["toggle", "show", "hide"], function (e, r) { var i = k.fn[r]; k.fn[r] = function (e, t, n) { return null == e || "boolean" == typeof e ? i.apply(this, arguments) : this.animate(ft(r, !0), e, t, n) } }), k.each({ slideDown: ft("show"), slideUp: ft("hide"), slideToggle: ft("toggle"), fadeIn: { opacity: "show" }, fadeOut: { opacity: "hide" }, fadeToggle: { opacity: "toggle" } }, function (e, r) { k.fn[e] = function (e, t, n) { return this.animate(r, e, t, n) } }), k.timers = [], k.fx.tick = function () { var e, t = 0, n = k.timers; for (rt = Date.now(); t < n.length; t++)(e = n[t])() || n[t] !== e || n.splice(t--, 1); n.length || k.fx.stop(), rt = void 0 }, k.fx.timer = function (e) { k.timers.push(e), k.fx.start() }, k.fx.interval = 13, k.fx.start = function () { it || (it = !0, lt()) }, k.fx.stop = function () { it = null }, k.fx.speeds = { slow: 600, fast: 200, _default: 400 }, k.fn.delay = function (r, e) { return r = k.fx && k.fx.speeds[r] || r, e = e || "fx", this.queue(e, function (e, t) { var n = C.setTimeout(e, r); t.stop = function () { C.clearTimeout(n) } }) }, ot = E.createElement("input"), at = E.createElement("select").appendChild(E.createElement("option")), ot.type = "checkbox", y.checkOn = "" !== ot.value, y.optSelected = at.selected, (ot = E.createElement("input")).value = "t", ot.type = "radio", y.radioValue = "t" === ot.value; var ht, gt = k.expr.attrHandle; k.fn.extend({ attr: function (e, t) { return _(this, k.attr, e, t, 1 < arguments.length) }, removeAttr: function (e) { return this.each(function () { k.removeAttr(this, e) }) } }), k.extend({ attr: function (e, t, n) { var r, i, o = e.nodeType; if (3 !== o && 8 !== o && 2 !== o) return "undefined" == typeof e.getAttribute ? k.prop(e, t, n) : (1 === o && k.isXMLDoc(e) || (i = k.attrHooks[t.toLowerCase()] || (k.expr.match.bool.test(t) ? ht : void 0)), void 0 !== n ? null === n ? void k.removeAttr(e, t) : i && "set" in i && void 0 !== (r = i.set(e, n, t)) ? r : (e.setAttribute(t, n + ""), n) : i && "get" in i && null !== (r = i.get(e, t)) ? r : null == (r = k.find.attr(e, t)) ? void 0 : r) }, attrHooks: { type: { set: function (e, t) { if (!y.radioValue && "radio" === t && A(e, "input")) { var n = e.value; return e.setAttribute("type", t), n && (e.value = n), t } } } }, removeAttr: function (e, t) { var n, r = 0, i = t && t.match(R); if (i && 1 === e.nodeType) while (n = i[r++]) e.removeAttribute(n) } }), ht = { set: function (e, t, n) { return !1 === t ? k.removeAttr(e, n) : e.setAttribute(n, n), n } }, k.each(k.expr.match.bool.source.match(/\w+/g), function (e, t) { var a = gt[t] || k.find.attr; gt[t] = function (e, t, n) { var r, i, o = t.toLowerCase(); return n || (i = gt[o], gt[o] = r, r = null != a(e, t, n) ? o : null, gt[o] = i), r } }); var vt = /^(?:input|select|textarea|button)$/i, yt = /^(?:a|area)$/i; function mt(e) { return (e.match(R) || []).join(" ") } function xt(e) { return e.getAttribute && e.getAttribute("class") || "" } function bt(e) { return Array.isArray(e) ? e : "string" == typeof e && e.match(R) || [] } k.fn.extend({ prop: function (e, t) { return _(this, k.prop, e, t, 1 < arguments.length) }, removeProp: function (e) { return this.each(function () { delete this[k.propFix[e] || e] }) } }), k.extend({ prop: function (e, t, n) { var r, i, o = e.nodeType; if (3 !== o && 8 !== o && 2 !== o) return 1 === o && k.isXMLDoc(e) || (t = k.propFix[t] || t, i = k.propHooks[t]), void 0 !== n ? i && "set" in i && void 0 !== (r = i.set(e, n, t)) ? r : e[t] = n : i && "get" in i && null !== (r = i.get(e, t)) ? r : e[t] }, propHooks: { tabIndex: { get: function (e) { var t = k.find.attr(e, "tabindex"); return t ? parseInt(t, 10) : vt.test(e.nodeName) || yt.test(e.nodeName) && e.href ? 0 : -1 } } }, propFix: { "for": "htmlFor", "class": "className" } }), y.optSelected || (k.propHooks.selected = { get: function (e) { var t = e.parentNode; return t && t.parentNode && t.parentNode.selectedIndex, null }, set: function (e) { var t = e.parentNode; t && (t.selectedIndex, t.parentNode && t.parentNode.selectedIndex) } }), k.each(["tabIndex", "readOnly", "maxLength", "cellSpacing", "cellPadding", "rowSpan", "colSpan", "useMap", "frameBorder", "contentEditable"], function () { k.propFix[this.toLowerCase()] = this }), k.fn.extend({ addClass: function (t) { var e, n, r, i, o, a, s, u = 0; if (m(t)) return this.each(function (e) { k(this).addClass(t.call(this, e, xt(this))) }); if ((e = bt(t)).length) while (n = this[u++]) if (i = xt(n), r = 1 === n.nodeType && " " + mt(i) + " ") { a = 0; while (o = e[a++]) r.indexOf(" " + o + " ") < 0 && (r += o + " "); i !== (s = mt(r)) && n.setAttribute("class", s) } return this }, removeClass: function (t) { var e, n, r, i, o, a, s, u = 0; if (m(t)) return this.each(function (e) { k(this).removeClass(t.call(this, e, xt(this))) }); if (!arguments.length) return this.attr("class", ""); if ((e = bt(t)).length) while (n = this[u++]) if (i = xt(n), r = 1 === n.nodeType && " " + mt(i) + " ") { a = 0; while (o = e[a++]) while (-1 < r.indexOf(" " + o + " ")) r = r.replace(" " + o + " ", " "); i !== (s = mt(r)) && n.setAttribute("class", s) } return this }, toggleClass: function (i, t) { var o = typeof i, a = "string" === o || Array.isArray(i); return "boolean" == typeof t && a ? t ? this.addClass(i) : this.removeClass(i) : m(i) ? this.each(function (e) { k(this).toggleClass(i.call(this, e, xt(this), t), t) }) : this.each(function () { var e, t, n, r; if (a) { t = 0, n = k(this), r = bt(i); while (e = r[t++]) n.hasClass(e) ? n.removeClass(e) : n.addClass(e) } else void 0 !== i && "boolean" !== o || ((e = xt(this)) && Q.set(this, "__className__", e), this.setAttribute && this.setAttribute("class", e || !1 === i ? "" : Q.get(this, "__className__") || "")) }) }, hasClass: function (e) { var t, n, r = 0; t = " " + e + " "; while (n = this[r++]) if (1 === n.nodeType && -1 < (" " + mt(xt(n)) + " ").indexOf(t)) return !0; return !1 } }); var wt = /\r/g; k.fn.extend({ val: function (n) { var r, e, i, t = this[0]; return arguments.length ? (i = m(n), this.each(function (e) { var t; 1 === this.nodeType && (null == (t = i ? n.call(this, e, k(this).val()) : n) ? t = "" : "number" == typeof t ? t += "" : Array.isArray(t) && (t = k.map(t, function (e) { return null == e ? "" : e + "" })), (r = k.valHooks[this.type] || k.valHooks[this.nodeName.toLowerCase()]) && "set" in r && void 0 !== r.set(this, t, "value") || (this.value = t)) })) : t ? (r = k.valHooks[t.type] || k.valHooks[t.nodeName.toLowerCase()]) && "get" in r && void 0 !== (e = r.get(t, "value")) ? e : "string" == typeof (e = t.value) ? e.replace(wt, "") : null == e ? "" : e : void 0 } }), k.extend({ valHooks: { option: { get: function (e) { var t = k.find.attr(e, "value"); return null != t ? t : mt(k.text(e)) } }, select: { get: function (e) { var t, n, r, i = e.options, o = e.selectedIndex, a = "select-one" === e.type, s = a ? null : [], u = a ? o + 1 : i.length; for (r = o < 0 ? u : a ? o : 0; r < u; r++)if (((n = i[r]).selected || r === o) && !n.disabled && (!n.parentNode.disabled || !A(n.parentNode, "optgroup"))) { if (t = k(n).val(), a) return t; s.push(t) } return s }, set: function (e, t) { var n, r, i = e.options, o = k.makeArray(t), a = i.length; while (a--) ((r = i[a]).selected = -1 < k.inArray(k.valHooks.option.get(r), o)) && (n = !0); return n || (e.selectedIndex = -1), o } } } }), k.each(["radio", "checkbox"], function () { k.valHooks[this] = { set: function (e, t) { if (Array.isArray(t)) return e.checked = -1 < k.inArray(k(e).val(), t) } }, y.checkOn || (k.valHooks[this].get = function (e) { return null === e.getAttribute("value") ? "on" : e.value }) }), y.focusin = "onfocusin" in C; var Tt = /^(?:focusinfocus|focusoutblur)$/, Ct = function (e) { e.stopPropagation() }; k.extend(k.event, { trigger: function (e, t, n, r) { var i, o, a, s, u, l, c, f, p = [n || E], d = v.call(e, "type") ? e.type : e, h = v.call(e, "namespace") ? e.namespace.split(".") : []; if (o = f = a = n = n || E, 3 !== n.nodeType && 8 !== n.nodeType && !Tt.test(d + k.event.triggered) && (-1 < d.indexOf(".") && (d = (h = d.split(".")).shift(), h.sort()), u = d.indexOf(":") < 0 && "on" + d, (e = e[k.expando] ? e : new k.Event(d, "object" == typeof e && e)).isTrigger = r ? 2 : 3, e.namespace = h.join("."), e.rnamespace = e.namespace ? new RegExp("(^|\\.)" + h.join("\\.(?:.*\\.|)") + "(\\.|$)") : null, e.result = void 0, e.target || (e.target = n), t = null == t ? [e] : k.makeArray(t, [e]), c = k.event.special[d] || {}, r || !c.trigger || !1 !== c.trigger.apply(n, t))) { if (!r && !c.noBubble && !x(n)) { for (s = c.delegateType || d, Tt.test(s + d) || (o = o.parentNode); o; o = o.parentNode)p.push(o), a = o; a === (n.ownerDocument || E) && p.push(a.defaultView || a.parentWindow || C) } i = 0; while ((o = p[i++]) && !e.isPropagationStopped()) f = o, e.type = 1 < i ? s : c.bindType || d, (l = (Q.get(o, "events") || {})[e.type] && Q.get(o, "handle")) && l.apply(o, t), (l = u && o[u]) && l.apply && G(o) && (e.result = l.apply(o, t), !1 === e.result && e.preventDefault()); return e.type = d, r || e.isDefaultPrevented() || c._default && !1 !== c._default.apply(p.pop(), t) || !G(n) || u && m(n[d]) && !x(n) && ((a = n[u]) && (n[u] = null), k.event.triggered = d, e.isPropagationStopped() && f.addEventListener(d, Ct), n[d](), e.isPropagationStopped() && f.removeEventListener(d, Ct), k.event.triggered = void 0, a && (n[u] = a)), e.result } }, simulate: function (e, t, n) { var r = k.extend(new k.Event, n, { type: e, isSimulated: !0 }); k.event.trigger(r, null, t) } }), k.fn.extend({ trigger: function (e, t) { return this.each(function () { k.event.trigger(e, t, this) }) }, triggerHandler: function (e, t) { var n = this[0]; if (n) return k.event.trigger(e, t, n, !0) } }), y.focusin || k.each({ focus: "focusin", blur: "focusout" }, function (n, r) { var i = function (e) { k.event.simulate(r, e.target, k.event.fix(e)) }; k.event.special[r] = { setup: function () { var e = this.ownerDocument || this, t = Q.access(e, r); t || e.addEventListener(n, i, !0), Q.access(e, r, (t || 0) + 1) }, teardown: function () { var e = this.ownerDocument || this, t = Q.access(e, r) - 1; t ? Q.access(e, r, t) : (e.removeEventListener(n, i, !0), Q.remove(e, r)) } } }); var Et = C.location, kt = Date.now(), St = /\?/; k.parseXML = function (e) { var t; if (!e || "string" != typeof e) return null; try { t = (new C.DOMParser).parseFromString(e, "text/xml") } catch (e) { t = void 0 } return t && !t.getElementsByTagName("parsererror").length || k.error("Invalid XML: " + e), t }; var Nt = /\[\]$/, At = /\r?\n/g, Dt = /^(?:submit|button|image|reset|file)$/i, jt = /^(?:input|select|textarea|keygen)/i; function qt(n, e, r, i) { var t; if (Array.isArray(e)) k.each(e, function (e, t) { r || Nt.test(n) ? i(n, t) : qt(n + "[" + ("object" == typeof t && null != t ? e : "") + "]", t, r, i) }); else if (r || "object" !== w(e)) i(n, e); else for (t in e) qt(n + "[" + t + "]", e[t], r, i) } k.param = function (e, t) { var n, r = [], i = function (e, t) { var n = m(t) ? t() : t; r[r.length] = encodeURIComponent(e) + "=" + encodeURIComponent(null == n ? "" : n) }; if (null == e) return ""; if (Array.isArray(e) || e.jquery && !k.isPlainObject(e)) k.each(e, function () { i(this.name, this.value) }); else for (n in e) qt(n, e[n], t, i); return r.join("&") }, k.fn.extend({ serialize: function () { return k.param(this.serializeArray()) }, serializeArray: function () { return this.map(function () { var e = k.prop(this, "elements"); return e ? k.makeArray(e) : this }).filter(function () { var e = this.type; return this.name && !k(this).is(":disabled") && jt.test(this.nodeName) && !Dt.test(e) && (this.checked || !pe.test(e)) }).map(function (e, t) { var n = k(this).val(); return null == n ? null : Array.isArray(n) ? k.map(n, function (e) { return { name: t.name, value: e.replace(At, "\r\n") } }) : { name: t.name, value: n.replace(At, "\r\n") } }).get() } }); var Lt = /%20/g, Ht = /#.*$/, Ot = /([?&])_=[^&]*/, Pt = /^(.*?):[ \t]*([^\r\n]*)$/gm, Rt = /^(?:GET|HEAD)$/, Mt = /^\/\//, It = {}, Wt = {}, $t = "*/".concat("*"), Ft = E.createElement("a"); function Bt(o) { return function (e, t) { "string" != typeof e && (t = e, e = "*"); var n, r = 0, i = e.toLowerCase().match(R) || []; if (m(t)) while (n = i[r++]) "+" === n[0] ? (n = n.slice(1) || "*", (o[n] = o[n] || []).unshift(t)) : (o[n] = o[n] || []).push(t) } } function _t(t, i, o, a) { var s = {}, u = t === Wt; function l(e) { var r; return s[e] = !0, k.each(t[e] || [], function (e, t) { var n = t(i, o, a); return "string" != typeof n || u || s[n] ? u ? !(r = n) : void 0 : (i.dataTypes.unshift(n), l(n), !1) }), r } return l(i.dataTypes[0]) || !s["*"] && l("*") } function zt(e, t) { var n, r, i = k.ajaxSettings.flatOptions || {}; for (n in t) void 0 !== t[n] && ((i[n] ? e : r || (r = {}))[n] = t[n]); return r && k.extend(!0, e, r), e } Ft.href = Et.href, k.extend({ active: 0, lastModified: {}, etag: {}, ajaxSettings: { url: Et.href, type: "GET", isLocal: /^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Et.protocol), global: !0, processData: !0, async: !0, contentType: "application/x-www-form-urlencoded; charset=UTF-8", accepts: { "*": $t, text: "text/plain", html: "text/html", xml: "application/xml, text/xml", json: "application/json, text/javascript" }, contents: { xml: /\bxml\b/, html: /\bhtml/, json: /\bjson\b/ }, responseFields: { xml: "responseXML", text: "responseText", json: "responseJSON" }, converters: { "* text": String, "text html": !0, "text json": JSON.parse, "text xml": k.parseXML }, flatOptions: { url: !0, context: !0 } }, ajaxSetup: function (e, t) { return t ? zt(zt(e, k.ajaxSettings), t) : zt(k.ajaxSettings, e) }, ajaxPrefilter: Bt(It), ajaxTransport: Bt(Wt), ajax: function (e, t) { "object" == typeof e && (t = e, e = void 0), t = t || {}; var c, f, p, n, d, r, h, g, i, o, v = k.ajaxSetup({}, t), y = v.context || v, m = v.context && (y.nodeType || y.jquery) ? k(y) : k.event, x = k.Deferred(), b = k.Callbacks("once memory"), w = v.statusCode || {}, a = {}, s = {}, u = "canceled", T = { readyState: 0, getResponseHeader: function (e) { var t; if (h) { if (!n) { n = {}; while (t = Pt.exec(p)) n[t[1].toLowerCase() + " "] = (n[t[1].toLowerCase() + " "] || []).concat(t[2]) } t = n[e.toLowerCase() + " "] } return null == t ? null : t.join(", ") }, getAllResponseHeaders: function () { return h ? p : null }, setRequestHeader: function (e, t) { return null == h && (e = s[e.toLowerCase()] = s[e.toLowerCase()] || e, a[e] = t), this }, overrideMimeType: function (e) { return null == h && (v.mimeType = e), this }, statusCode: function (e) { var t; if (e) if (h) T.always(e[T.status]); else for (t in e) w[t] = [w[t], e[t]]; return this }, abort: function (e) { var t = e || u; return c && c.abort(t), l(0, t), this } }; if (x.promise(T), v.url = ((e || v.url || Et.href) + "").replace(Mt, Et.protocol + "//"), v.type = t.method || t.type || v.method || v.type, v.dataTypes = (v.dataType || "*").toLowerCase().match(R) || [""], null == v.crossDomain) { r = E.createElement("a"); try { r.href = v.url, r.href = r.href, v.crossDomain = Ft.protocol + "//" + Ft.host != r.protocol + "//" + r.host } catch (e) { v.crossDomain = !0 } } if (v.data && v.processData && "string" != typeof v.data && (v.data = k.param(v.data, v.traditional)), _t(It, v, t, T), h) return T; for (i in (g = k.event && v.global) && 0 == k.active++ && k.event.trigger("ajaxStart"), v.type = v.type.toUpperCase(), v.hasContent = !Rt.test(v.type), f = v.url.replace(Ht, ""), v.hasContent ? v.data && v.processData && 0 === (v.contentType || "").indexOf("application/x-www-form-urlencoded") && (v.data = v.data.replace(Lt, "+")) : (o = v.url.slice(f.length), v.data && (v.processData || "string" == typeof v.data) && (f += (St.test(f) ? "&" : "?") + v.data, delete v.data), !1 === v.cache && (f = f.replace(Ot, "$1"), o = (St.test(f) ? "&" : "?") + "_=" + kt++ + o), v.url = f + o), v.ifModified && (k.lastModified[f] && T.setRequestHeader("If-Modified-Since", k.lastModified[f]), k.etag[f] && T.setRequestHeader("If-None-Match", k.etag[f])), (v.data && v.hasContent && !1 !== v.contentType || t.contentType) && T.setRequestHeader("Content-Type", v.contentType), T.setRequestHeader("Accept", v.dataTypes[0] && v.accepts[v.dataTypes[0]] ? v.accepts[v.dataTypes[0]] + ("*" !== v.dataTypes[0] ? ", " + $t + "; q=0.01" : "") : v.accepts["*"]), v.headers) T.setRequestHeader(i, v.headers[i]); if (v.beforeSend && (!1 === v.beforeSend.call(y, T, v) || h)) return T.abort(); if (u = "abort", b.add(v.complete), T.done(v.success), T.fail(v.error), c = _t(Wt, v, t, T)) { if (T.readyState = 1, g && m.trigger("ajaxSend", [T, v]), h) return T; v.async && 0 < v.timeout && (d = C.setTimeout(function () { T.abort("timeout") }, v.timeout)); try { h = !1, c.send(a, l) } catch (e) { if (h) throw e; l(-1, e) } } else l(-1, "No Transport"); function l(e, t, n, r) { var i, o, a, s, u, l = t; h || (h = !0, d && C.clearTimeout(d), c = void 0, p = r || "", T.readyState = 0 < e ? 4 : 0, i = 200 <= e && e < 300 || 304 === e, n && (s = function (e, t, n) { var r, i, o, a, s = e.contents, u = e.dataTypes; while ("*" === u[0]) u.shift(), void 0 === r && (r = e.mimeType || t.getResponseHeader("Content-Type")); if (r) for (i in s) if (s[i] && s[i].test(r)) { u.unshift(i); break } if (u[0] in n) o = u[0]; else { for (i in n) { if (!u[0] || e.converters[i + " " + u[0]]) { o = i; break } a || (a = i) } o = o || a } if (o) return o !== u[0] && u.unshift(o), n[o] }(v, T, n)), s = function (e, t, n, r) { var i, o, a, s, u, l = {}, c = e.dataTypes.slice(); if (c[1]) for (a in e.converters) l[a.toLowerCase()] = e.converters[a]; o = c.shift(); while (o) if (e.responseFields[o] && (n[e.responseFields[o]] = t), !u && r && e.dataFilter && (t = e.dataFilter(t, e.dataType)), u = o, o = c.shift()) if ("*" === o) o = u; else if ("*" !== u && u !== o) { if (!(a = l[u + " " + o] || l["* " + o])) for (i in l) if ((s = i.split(" "))[1] === o && (a = l[u + " " + s[0]] || l["* " + s[0]])) { !0 === a ? a = l[i] : !0 !== l[i] && (o = s[0], c.unshift(s[1])); break } if (!0 !== a) if (a && e["throws"]) t = a(t); else try { t = a(t) } catch (e) { return { state: "parsererror", error: a ? e : "No conversion from " + u + " to " + o } } } return { state: "success", data: t } }(v, s, T, i), i ? (v.ifModified && ((u = T.getResponseHeader("Last-Modified")) && (k.lastModified[f] = u), (u = T.getResponseHeader("etag")) && (k.etag[f] = u)), 204 === e || "HEAD" === v.type ? l = "nocontent" : 304 === e ? l = "notmodified" : (l = s.state, o = s.data, i = !(a = s.error))) : (a = l, !e && l || (l = "error", e < 0 && (e = 0))), T.status = e, T.statusText = (t || l) + "", i ? x.resolveWith(y, [o, l, T]) : x.rejectWith(y, [T, l, a]), T.statusCode(w), w = void 0, g && m.trigger(i ? "ajaxSuccess" : "ajaxError", [T, v, i ? o : a]), b.fireWith(y, [T, l]), g && (m.trigger("ajaxComplete", [T, v]), --k.active || k.event.trigger("ajaxStop"))) } return T }, getJSON: function (e, t, n) { return k.get(e, t, n, "json") }, getScript: function (e, t) { return k.get(e, void 0, t, "script") } }), k.each(["get", "post"], function (e, i) { k[i] = function (e, t, n, r) { return m(t) && (r = r || n, n = t, t = void 0), k.ajax(k.extend({ url: e, type: i, dataType: r, data: t, success: n }, k.isPlainObject(e) && e)) } }), k._evalUrl = function (e, t) { return k.ajax({ url: e, type: "GET", dataType: "script", cache: !0, async: !1, global: !1, converters: { "text script": function () { } }, dataFilter: function (e) { k.globalEval(e, t) } }) }, k.fn.extend({ wrapAll: function (e) { var t; return this[0] && (m(e) && (e = e.call(this[0])), t = k(e, this[0].ownerDocument).eq(0).clone(!0), this[0].parentNode && t.insertBefore(this[0]), t.map(function () { var e = this; while (e.firstElementChild) e = e.firstElementChild; return e }).append(this)), this }, wrapInner: function (n) { return m(n) ? this.each(function (e) { k(this).wrapInner(n.call(this, e)) }) : this.each(function () { var e = k(this), t = e.contents(); t.length ? t.wrapAll(n) : e.append(n) }) }, wrap: function (t) { var n = m(t); return this.each(function (e) { k(this).wrapAll(n ? t.call(this, e) : t) }) }, unwrap: function (e) { return this.parent(e).not("body").each(function () { k(this).replaceWith(this.childNodes) }), this } }), k.expr.pseudos.hidden = function (e) { return !k.expr.pseudos.visible(e) }, k.expr.pseudos.visible = function (e) { return !!(e.offsetWidth || e.offsetHeight || e.getClientRects().length) }, k.ajaxSettings.xhr = function () { try { return new C.XMLHttpRequest } catch (e) { } }; var Ut = { 0: 200, 1223: 204 }, Xt = k.ajaxSettings.xhr(); y.cors = !!Xt && "withCredentials" in Xt, y.ajax = Xt = !!Xt, k.ajaxTransport(function (i) { var o, a; if (y.cors || Xt && !i.crossDomain) return { send: function (e, t) { var n, r = i.xhr(); if (r.open(i.type, i.url, i.async, i.username, i.password), i.xhrFields) for (n in i.xhrFields) r[n] = i.xhrFields[n]; for (n in i.mimeType && r.overrideMimeType && r.overrideMimeType(i.mimeType), i.crossDomain || e["X-Requested-With"] || (e["X-Requested-With"] = "XMLHttpRequest"), e) r.setRequestHeader(n, e[n]); o = function (e) { return function () { o && (o = a = r.onload = r.onerror = r.onabort = r.ontimeout = r.onreadystatechange = null, "abort" === e ? r.abort() : "error" === e ? "number" != typeof r.status ? t(0, "error") : t(r.status, r.statusText) : t(Ut[r.status] || r.status, r.statusText, "text" !== (r.responseType || "text") || "string" != typeof r.responseText ? { binary: r.response } : { text: r.responseText }, r.getAllResponseHeaders())) } }, r.onload = o(), a = r.onerror = r.ontimeout = o("error"), void 0 !== r.onabort ? r.onabort = a : r.onreadystatechange = function () { 4 === r.readyState && C.setTimeout(function () { o && a() }) }, o = o("abort"); try { r.send(i.hasContent && i.data || null) } catch (e) { if (o) throw e } }, abort: function () { o && o() } } }), k.ajaxPrefilter(function (e) { e.crossDomain && (e.contents.script = !1) }), k.ajaxSetup({ accepts: { script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" }, contents: { script: /\b(?:java|ecma)script\b/ }, converters: { "text script": function (e) { return k.globalEval(e), e } } }), k.ajaxPrefilter("script", function (e) { void 0 === e.cache && (e.cache = !1), e.crossDomain && (e.type = "GET") }), k.ajaxTransport("script", function (n) { var r, i; if (n.crossDomain || n.scriptAttrs) return { send: function (e, t) { r = k("