├── .gitignore ├── LICENSE ├── README.md ├── docs ├── CNAME └── pyscript_plugin.js └── samples ├── advance ├── do_generator.py ├── do_iter.py ├── do_listcompr.py ├── do_slice.py └── do_yield.py ├── async ├── aio_web.py ├── async_hello.py ├── async_hello2.py ├── async_wget.py ├── async_wget2.py └── coroutine.py ├── basic ├── do_for.py ├── do_if.py ├── do_input.py ├── do_match.py ├── do_print.py ├── do_while.py ├── hello │ └── hello.py ├── the_dict.py ├── the_list.py ├── the_set.py ├── the_string.py └── the_tuple.py ├── commonlib ├── check_bmp.py ├── do_base64.py ├── use_chainmap.py ├── use_collections.py ├── use_datetime.py ├── use_hashlib.py ├── use_htmlparser.py ├── use_itertools.py ├── use_sax.py └── use_urllib.py ├── context ├── do_closing.py ├── do_suppress.py └── do_with.py ├── db ├── do_mysql.py ├── do_sqlalchemy.py └── do_sqlite.py ├── debug ├── do_assert.py ├── do_logging.py ├── do_pdb.py ├── do_try.py ├── err.py ├── err_logging.py ├── err_raise.py ├── err_reraise.py ├── mydict.py ├── mydict2.py └── mydict_test.py ├── function ├── call_func.py ├── def_func.py ├── kw_args.py ├── recur.py └── var_args.py ├── functional ├── decorator.py ├── do_filter.py ├── do_map.py ├── do_partial.py ├── do_reduce.py ├── do_sorted.py ├── prime_numbers.py └── return_func.py ├── gui ├── hello_gui.py └── turtle │ ├── rect.py │ ├── stars.py │ └── tree.py ├── io ├── do_bytesio.py ├── do_dir.py ├── do_stringio.py ├── use_json.py ├── use_pickle.py └── with_file.py ├── mail ├── fetch_mail.py └── send_mail.py ├── micropython ├── hellorobot │ ├── .vscode │ │ ├── extensions.json │ │ ├── launch.json │ │ └── settings.json │ └── main.py ├── rccar │ ├── .vscode │ │ ├── extensions.json │ │ ├── launch.json │ │ └── settings.json │ ├── devices.py │ └── main.py ├── smallcar │ ├── .vscode │ │ ├── extensions.json │ │ ├── launch.json │ │ └── settings.json │ └── main.py └── tank │ ├── .vscode │ ├── extensions.json │ ├── launch.json │ └── settings.json │ ├── cannon.wav │ ├── devices.py │ ├── joystick.py │ └── main.py ├── module └── hello.py ├── multitask ├── do_folk.py ├── do_lock.py ├── do_queue.py ├── do_subprocess.py ├── multi_processing.py ├── multi_threading.py ├── pooled_processing.py ├── task_master.py ├── task_worker.py └── use_threadlocal.py ├── oop_advance ├── create_class_on_the_fly.py ├── orm.py ├── special_call.py ├── special_getattr.py ├── special_getitem.py ├── special_iter.py ├── special_str.py ├── use_enum.py ├── use_metaclass.py ├── use_property.py └── use_slots.py ├── oop_basic ├── animals.py ├── attrs.py ├── get_instance.py ├── get_type.py ├── protected_student.py └── student.py ├── packages └── pil │ ├── README │ ├── test.jpg │ ├── use_pil_blur.py │ ├── use_pil_draw.py │ └── use_pil_resize.py ├── regex └── regex.py ├── socket ├── do_tcp.py ├── udp_client.py └── udp_server.py ├── test ├── dict_doctest.py └── dict_unittest.py └── web ├── do_flask.py ├── do_wsgi.py ├── hello.py └── mvc ├── app.py └── templates ├── form.html ├── home.html └── signin-ok.html /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | test.db 4 | test.txt 5 | sina.html 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Packages 11 | *.egg 12 | *.egg-info 13 | dist 14 | build 15 | eggs 16 | parts 17 | bin 18 | var 19 | sdist 20 | develop-eggs 21 | .installed.cfg 22 | lib 23 | lib64 24 | __pycache__ 25 | 26 | # Installer logs 27 | pip-log.txt 28 | 29 | # Unit test / coverage reports 30 | .coverage 31 | .tox 32 | nosetests.xml 33 | 34 | ###################### 35 | # OS generated files # 36 | ###################### 37 | .DS_Store 38 | .DS_Store? 39 | ._* 40 | .Spotlight-V100 41 | .Trashes 42 | Icon? 43 | ehthumbs.db 44 | Thumbs.db 45 | dist 46 | MANIFEST 47 | 48 | # Translations 49 | *.mo 50 | 51 | # Mr Developer 52 | .mr.developer.cfg 53 | .project 54 | .pydevproject 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Python 3 教程 2 | ============ 3 | 4 | [Python 3 教程](https://www.liaoxuefeng.com/wiki/1016959663602400) 5 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | learn-python3.itranswarp.com -------------------------------------------------------------------------------- /docs/pyscript_plugin.js: -------------------------------------------------------------------------------- 1 | export default class LearnPython3Plugin { 2 | afterStartup(runtime) { 3 | console.log('[plugin] pyscript startup.'); 4 | window.__pyscript_ready__ = true; 5 | } 6 | 7 | afterPyScriptExec(opt) { 8 | let 9 | tag = opt.pyScriptTag, 10 | outputId = tag.getAttribute('output'), 11 | $btn = $('button[outputId=' + outputId + ']'), 12 | $i = $btn.find('i'); 13 | $i.removeClass('uk-icon-spinner'); 14 | $i.removeClass('uk-icon-spin'); 15 | $btn.removeAttr('disabled'); 16 | let err = $(tag).find('pre.py-error').html(); 17 | if (err) { 18 | let 19 | $out = $('#' + outputId), 20 | s = $out.html(); 21 | s = s + err.replaceAll(' ', ' '); 22 | $out.html(s); 23 | $out.addClass('uk-alert-danger'); 24 | } 25 | } 26 | 27 | onUserError(err) { 28 | console.log('Error >>>'); 29 | console.error(err); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /samples/advance/do_generator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | s = (x * x for x in range(5)) 5 | print(s) 6 | for x in s: 7 | print(x) 8 | 9 | def fib(max): 10 | n, a, b = 0, 0, 1 11 | while n < max: 12 | yield b 13 | a, b = b, a + b 14 | n = n + 1 15 | return 'done' 16 | 17 | f = fib(10) 18 | print('fib(10):', f) 19 | for x in f: 20 | print(x) 21 | 22 | # call generator manually: 23 | g = fib(5) 24 | while 1: 25 | try: 26 | x = next(g) 27 | print('g:', x) 28 | except StopIteration as e: 29 | print('Generator return value:', e.value) 30 | break 31 | 32 | -------------------------------------------------------------------------------- /samples/advance/do_iter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from collections.abc import Iterable, Iterator 5 | 6 | def g(): 7 | yield 1 8 | yield 2 9 | yield 3 10 | 11 | print('Iterable? [1, 2, 3]:', isinstance([1, 2, 3], Iterable)) 12 | print('Iterable? \'abc\':', isinstance('abc', Iterable)) 13 | print('Iterable? 123:', isinstance(123, Iterable)) 14 | print('Iterable? g():', isinstance(g(), Iterable)) 15 | 16 | print('Iterator? [1, 2, 3]:', isinstance([1, 2, 3], Iterator)) 17 | print('Iterator? iter([1, 2, 3]):', isinstance(iter([1, 2, 3]), Iterator)) 18 | print('Iterator? \'abc\':', isinstance('abc', Iterator)) 19 | print('Iterator? 123:', isinstance(123, Iterator)) 20 | print('Iterator? g():', isinstance(g(), Iterator)) 21 | 22 | # iter list: 23 | print('for x in [1, 2, 3, 4, 5]:') 24 | for x in [1, 2, 3, 4, 5]: 25 | print(x) 26 | 27 | print('for x in iter([1, 2, 3, 4, 5]):') 28 | for x in iter([1, 2, 3, 4, 5]): 29 | print(x) 30 | 31 | print('next():') 32 | it = iter([1, 2, 3, 4, 5]) 33 | print(next(it)) 34 | print(next(it)) 35 | print(next(it)) 36 | print(next(it)) 37 | print(next(it)) 38 | 39 | d = {'a': 1, 'b': 2, 'c': 3} 40 | 41 | # iter each key: 42 | print('iter key:', d) 43 | for k in d.keys(): 44 | print('key:', k) 45 | 46 | # iter each value: 47 | print('iter value:', d) 48 | for v in d.values(): 49 | print('value:', v) 50 | 51 | # iter both key and value: 52 | print('iter item:', d) 53 | for k, v in d.items(): 54 | print('item:', k, v) 55 | 56 | # iter list with index: 57 | print('iter enumerate([\'A\', \'B\', \'C\']') 58 | for i, value in enumerate(['A', 'B', 'C']): 59 | print(i, value) 60 | 61 | # iter complex list: 62 | print('iter [(1, 1), (2, 4), (3, 9)]:') 63 | for x, y in [(1, 1), (2, 4), (3, 9)]: 64 | print(x, y) 65 | -------------------------------------------------------------------------------- /samples/advance/do_listcompr.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | print([x * x for x in range(1, 11)]) 5 | print([x * x for x in range(1, 11) if x % 2 == 0]) 6 | print([m + n for m in 'ABC' for n in 'XYZ']) 7 | 8 | d = {'x': 'A', 'y': 'B', 'z': 'C' } 9 | print([k + '=' + v for k, v in d.items()]) 10 | 11 | L = ['Hello', 'World', 'IBM', 'Apple'] 12 | print([s.lower() for s in L]) 13 | -------------------------------------------------------------------------------- /samples/advance/do_slice.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack'] 5 | 6 | print('L[0:3] =', L[0:3]) 7 | print('L[:3] =', L[:3]) 8 | print('L[1:3] =', L[1:3]) 9 | print('L[-2:] =', L[-2:]) 10 | 11 | R = list(range(100)) 12 | print('R[:10] =', R[:10]) 13 | print('R[-10:] =', R[-10:]) 14 | print('R[10:20] =', R[10:20]) 15 | print('R[:10:2] =', R[:10:2]) 16 | print('R[::5] =', R[::5]) 17 | -------------------------------------------------------------------------------- /samples/advance/do_yield.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | def each_ascii(s): 5 | for ch in s: 6 | yield ord(ch) 7 | return '%s chars' % len(s) 8 | 9 | def yield_from(s): 10 | r = yield from each_ascii(s) 11 | print(r) 12 | 13 | def main(): 14 | for x in each_ascii('abc'): 15 | print(x) # => 'a', 'b', 'c' 16 | it = each_ascii('xyz') 17 | try: 18 | while True: 19 | print(next(it)) # => 'x', 'y', 'z' 20 | except StopIteration as s: 21 | print(s.value) # => '3 chars' 22 | 23 | # using yield from in main() will change main() from function to generator: 24 | # r = yield from each_ascii('hello') 25 | 26 | for ch in yield_from('hello'): 27 | pass 28 | 29 | main() 30 | -------------------------------------------------------------------------------- /samples/async/aio_web.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | __author__ = 'Michael Liao' 5 | 6 | ''' 7 | async web application. 8 | ''' 9 | 10 | import asyncio 11 | 12 | from aiohttp import web 13 | 14 | async def index(request): 15 | await asyncio.sleep(0.5) 16 | return web.Response(body=b'

Index

') 17 | 18 | async def hello(request): 19 | await asyncio.sleep(0.5) 20 | text = '

hello, %s!

' % request.match_info['name'] 21 | return web.Response(body=text.encode('utf-8')) 22 | 23 | async def init(loop): 24 | app = web.Application(loop=loop) 25 | app.router.add_route('GET', '/', index) 26 | app.router.add_route('GET', '/hello/{name}', hello) 27 | srv = await loop.create_server(app.make_handler(), '127.0.0.1', 8000) 28 | print('Server started at http://127.0.0.1:8000...') 29 | return srv 30 | 31 | loop = asyncio.get_event_loop() 32 | loop.run_until_complete(init(loop)) 33 | loop.run_forever() 34 | -------------------------------------------------------------------------------- /samples/async/async_hello.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import threading 5 | import asyncio 6 | 7 | @asyncio.coroutine 8 | def hello(): 9 | print('Hello world! (%s)' % threading.currentThread()) 10 | yield from asyncio.sleep(1) 11 | print('Hello again! (%s)' % threading.currentThread()) 12 | 13 | loop = asyncio.get_event_loop() 14 | tasks = [hello(), hello()] 15 | loop.run_until_complete(asyncio.wait(tasks)) 16 | loop.close() 17 | -------------------------------------------------------------------------------- /samples/async/async_hello2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import threading 5 | import asyncio 6 | 7 | async def hello(): 8 | print('Hello world! (%s)' % threading.currentThread()) 9 | await asyncio.sleep(1) 10 | print('Hello again! (%s)' % threading.currentThread()) 11 | 12 | loop = asyncio.get_event_loop() 13 | tasks = [hello(), hello()] 14 | loop.run_until_complete(asyncio.wait(tasks)) 15 | loop.close() 16 | -------------------------------------------------------------------------------- /samples/async/async_wget.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import asyncio 5 | 6 | @asyncio.coroutine 7 | def wget(host): 8 | print('wget %s...' % host) 9 | connect = asyncio.open_connection(host, 80) 10 | reader, writer = yield from connect 11 | header = 'GET / HTTP/1.0\r\nHost: %s\r\n\r\n' % host 12 | writer.write(header.encode('utf-8')) 13 | yield from writer.drain() 14 | while True: 15 | line = yield from reader.readline() 16 | if line == b'\r\n': 17 | break 18 | print('%s header > %s' % (host, line.decode('utf-8').rstrip())) 19 | # Ignore the body, close the socket 20 | writer.close() 21 | 22 | loop = asyncio.get_event_loop() 23 | tasks = [wget(host) for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']] 24 | loop.run_until_complete(asyncio.wait(tasks)) 25 | loop.close() 26 | -------------------------------------------------------------------------------- /samples/async/async_wget2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import threading 5 | import asyncio 6 | 7 | async def hello(): 8 | print('Hello world! (%s)' % threading.currentThread()) 9 | await asyncio.sleep(1) 10 | print('Hello again! (%s)' % threading.currentThread()) 11 | 12 | loop = asyncio.get_event_loop() 13 | tasks = [hello(), hello()] 14 | loop.run_until_complete(asyncio.wait(tasks)) 15 | loop.close() 16 | -------------------------------------------------------------------------------- /samples/async/coroutine.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | def consumer(): 5 | r = '' 6 | while True: 7 | n = yield r 8 | if not n: 9 | return 10 | print('[CONSUMER] Consuming %s...' % n) 11 | r = '200 OK' 12 | 13 | def produce(c): 14 | c.send(None) 15 | n = 0 16 | while n < 5: 17 | n = n + 1 18 | print('[PRODUCER] Producing %s...' % n) 19 | r = c.send(n) 20 | print('[PRODUCER] Consumer return: %s' % r) 21 | c.close() 22 | 23 | c = consumer() 24 | produce(c) 25 | -------------------------------------------------------------------------------- /samples/basic/do_for.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | # 打印list: 5 | names = ['Michael', 'Bob', 'Tracy'] 6 | for name in names: 7 | print(name) 8 | 9 | # 打印数字 0 - 9 10 | for x in range(10): 11 | print(x) 12 | -------------------------------------------------------------------------------- /samples/basic/do_if.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | # 注意: 5 | # input()返回的是字符串 6 | # 必须通过int()将字符串转换为整数 7 | # 才能用于数值比较: 8 | age = int(input('Input your age: ')) 9 | 10 | if age >= 18: 11 | print('adult') 12 | elif age >= 6: 13 | print('teenager') 14 | else: 15 | print('kid') 16 | -------------------------------------------------------------------------------- /samples/basic/do_input.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | name = input() 5 | print('Hello,', name) 6 | -------------------------------------------------------------------------------- /samples/basic/do_match.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | # 简单匹配: 5 | print('-- simple match --') 6 | 7 | score = 'A' 8 | 9 | match score: 10 | case 'A': 11 | print('score is A.') 12 | case 'B': 13 | print('score is B.') 14 | case 'C': 15 | print('score is C.') 16 | case _: 17 | print('score is ???.') 18 | 19 | # 复杂匹配: 20 | print('-- complex match --') 21 | 22 | age = 15 23 | 24 | match age: 25 | case x if x < 10: 26 | print('< 10 years old.') 27 | case 10: 28 | print('10 years old.') 29 | case 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18: 30 | print('11~18 years old.') 31 | case 19: 32 | print('19 years old.') 33 | case _: 34 | print('not sure.') 35 | 36 | # 列表匹配: 37 | print('-- match list --') 38 | 39 | args = ['gcc', 'hello.c', 'world.c'] 40 | # args = ['clean'] 41 | # args = ['gcc'] 42 | 43 | match args: 44 | # 如果仅出现gcc,报错: 45 | case ['gcc']: 46 | print('gcc: missing source file(s).') 47 | # 出现gcc,且至少指定了一个文件: 48 | case ['gcc', file1, *files]: 49 | print('gcc compile: ' + file1 + ', ' + ', '.join(files)) 50 | # 仅出现clean: 51 | case ['clean']: 52 | print('clean') 53 | case _: 54 | print('invalid command.') 55 | -------------------------------------------------------------------------------- /samples/basic/do_print.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | print('The quick brown fox', 'jumps over', 'the lazy dog') 5 | print(300) 6 | print(100 + 200) 7 | print('100 + 200 =', 100 + 200) 8 | -------------------------------------------------------------------------------- /samples/basic/do_while.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | # 计算1+2+3+...+100: 5 | sum = 0 6 | n = 1 7 | while n <= 100: 8 | sum = sum + n 9 | n = n + 1 10 | print(sum) 11 | 12 | # 计算1x2x3x...x100: 13 | acc = 1 14 | n = 1 15 | while n <= 100: 16 | acc = acc * n 17 | n = n + 1 18 | print(acc) 19 | -------------------------------------------------------------------------------- /samples/basic/hello/hello.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | print('Hello, world') 5 | -------------------------------------------------------------------------------- /samples/basic/the_dict.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | d = { 5 | 'Michael': 95, 6 | 'Bob': 75, 7 | 'Tracy': 85 8 | } 9 | print('d[\'Michael\'] =', d['Michael']) 10 | print('d[\'Bob\'] =', d['Bob']) 11 | print('d[\'Tracy\'] =', d['Tracy']) 12 | print('d.get(\'Thomas\', -1) =', d.get('Thomas', -1)) 13 | -------------------------------------------------------------------------------- /samples/basic/the_list.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | classmates = ['Michael', 'Bob', 'Tracy'] 5 | print('classmates =', classmates) 6 | print('len(classmates) =', len(classmates)) 7 | print('classmates[0] =', classmates[0]) 8 | print('classmates[1] =', classmates[1]) 9 | print('classmates[2] =', classmates[2]) 10 | print('classmates[-1] =', classmates[-1]) 11 | classmates.pop() 12 | print('classmates =', classmates) 13 | -------------------------------------------------------------------------------- /samples/basic/the_set.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | s1 = set([1, 1, 2, 2, 3, 3]) 5 | print(s1) 6 | s2 = set([2, 3, 4]) 7 | print(s1 & s2) 8 | print(s1 | s2) 9 | -------------------------------------------------------------------------------- /samples/basic/the_string.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | s = 'Python-中文' 5 | print(s) 6 | b = s.encode('utf-8') 7 | print(b) 8 | print(b.decode('utf-8')) 9 | -------------------------------------------------------------------------------- /samples/basic/the_tuple.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | classmates = ('Michael', 'Bob', 'Tracy') 5 | print('classmates =', classmates) 6 | print('len(classmates) =', len(classmates)) 7 | print('classmates[0] =', classmates[0]) 8 | print('classmates[1] =', classmates[1]) 9 | print('classmates[2] =', classmates[2]) 10 | print('classmates[-1] =', classmates[-1]) 11 | 12 | # cannot modify tuple: 13 | classmates[0] = 'Adam' 14 | -------------------------------------------------------------------------------- /samples/commonlib/check_bmp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import struct 5 | 6 | bmp_header = b'\x42\x4d\x38\x8c\x0a\x00\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00\x00\x00\x80\x02\x00\x00\x68\x01\x00\x00\x01\x00\x18\x00' 7 | 8 | print(struct.unpack(' timestamp:', dt.timestamp()) 17 | 18 | # 把timestamp转换为datetime: 19 | t = dt.timestamp() 20 | print('timestamp -> datetime:', datetime.fromtimestamp(t)) 21 | print('timestamp -> datetime as UTC+0:', datetime.utcfromtimestamp(t)) 22 | 23 | # 从str读取datetime: 24 | cday = datetime.strptime('2015-6-1 18:19:59', '%Y-%m-%d %H:%M:%S') 25 | print('strptime:', cday) 26 | 27 | # 把datetime格式化输出: 28 | print('strftime:', cday.strftime('%a, %b %d %H:%M')) 29 | 30 | # 对日期进行加减: 31 | print('current datetime =', cday) 32 | print('current + 10 hours =', cday + timedelta(hours=10)) 33 | print('current - 1 day =', cday - timedelta(days=1)) 34 | print('current + 2.5 days =', cday + timedelta(days=2, hours=12)) 35 | 36 | # 把时间从UTC+0时区转换为UTC+8: 37 | utc_dt = datetime.utcnow().replace(tzinfo=timezone.utc) 38 | utc8_dt = utc_dt.astimezone(timezone(timedelta(hours=8))) 39 | print('UTC+0:00 now =', utc_dt) 40 | print('UTC+8:00 now =', utc8_dt) 41 | -------------------------------------------------------------------------------- /samples/commonlib/use_hashlib.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import hashlib 5 | 6 | md5 = hashlib.md5() 7 | md5.update('how to use md5 in python hashlib?'.encode('utf-8')) 8 | print(md5.hexdigest()) 9 | 10 | sha1 = hashlib.sha1() 11 | sha1.update('how to use sha1 in '.encode('utf-8')) 12 | sha1.update('python hashlib?'.encode('utf-8')) 13 | print(sha1.hexdigest()) 14 | -------------------------------------------------------------------------------- /samples/commonlib/use_htmlparser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from html.parser import HTMLParser 5 | from html.entities import name2codepoint 6 | 7 | class MyHTMLParser(HTMLParser): 8 | 9 | def handle_starttag(self, tag, attrs): 10 | print('<%s>' % tag) 11 | 12 | def handle_endtag(self, tag): 13 | print('' % tag) 14 | 15 | def handle_startendtag(self, tag, attrs): 16 | print('<%s/>' % tag) 17 | 18 | def handle_data(self, data): 19 | print(data) 20 | 21 | def handle_comment(self, data): 22 | print('') 23 | 24 | def handle_entityref(self, name): 25 | print('&%s;' % name) 26 | 27 | def handle_charref(self, name): 28 | print('&#%s;' % name) 29 | 30 | parser = MyHTMLParser() 31 | parser.feed(''' 32 | 33 | 34 | 35 |

Some html HTML tutorial...
END

36 | ''') 37 | -------------------------------------------------------------------------------- /samples/commonlib/use_itertools.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import itertools 5 | 6 | natuals = itertools.count(1) 7 | for n in natuals: 8 | print(n) 9 | if n >= 100: 10 | break 11 | 12 | cs = itertools.cycle('ABC') 13 | t = 10 14 | for c in cs: 15 | print(c) 16 | t = t - 1 17 | if t == 0: 18 | break 19 | -------------------------------------------------------------------------------- /samples/commonlib/use_sax.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from xml.parsers.expat import ParserCreate 5 | 6 | class DefaultSaxHandler(object): 7 | def start_element(self, name, attrs): 8 | print('sax:start_element: %s, attrs: %s' % (name, str(attrs))) 9 | 10 | def end_element(self, name): 11 | print('sax:end_element: %s' % name) 12 | 13 | def char_data(self, text): 14 | print('sax:char_data: %s' % text) 15 | 16 | xml = r''' 17 |
    18 |
  1. Python
  2. 19 |
  3. Ruby
  4. 20 |
21 | ''' 22 | 23 | handler = DefaultSaxHandler() 24 | parser = ParserCreate() 25 | parser.StartElementHandler = handler.start_element 26 | parser.EndElementHandler = handler.end_element 27 | parser.CharacterDataHandler = handler.char_data 28 | parser.Parse(xml) 29 | -------------------------------------------------------------------------------- /samples/commonlib/use_urllib.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from urllib import request, parse 5 | 6 | # get: 7 | 8 | with request.urlopen('https://api.douban.com/v2/book/2129650') as f: 9 | data = f.read() 10 | print('Status:', f.status, f.reason) 11 | for k, v in f.getheaders(): 12 | print('%s: %s' % (k, v)) 13 | print('Data:', data.decode('utf-8')) 14 | 15 | # advanced get: 16 | 17 | req = request.Request('http://www.douban.com/') 18 | req.add_header('User-Agent', 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25') 19 | with request.urlopen(req) as f: 20 | print('Status:', f.status, f.reason) 21 | for k, v in f.getheaders(): 22 | print('%s: %s' % (k, v)) 23 | print('Data:', f.read().decode('utf-8')) 24 | 25 | # post: 26 | 27 | print('Login to weibo.cn...') 28 | email = input('Email: ') 29 | passwd = input('Password: ') 30 | login_data = parse.urlencode([ 31 | ('username', email), 32 | ('password', passwd), 33 | ('entry', 'mweibo'), 34 | ('client_id', ''), 35 | ('savestate', '1'), 36 | ('ec', ''), 37 | ('pagerefer', 'https://passport.weibo.cn/signin/welcome?entry=mweibo&r=http%3A%2F%2Fm.weibo.cn%2F%3Fjumpfrom%3Dweibocom&jumpfrom=weibocom') 38 | ]) 39 | 40 | req = request.Request('https://passport.weibo.cn/sso/login') 41 | req.add_header('Origin', 'https://passport.weibo.cn') 42 | req.add_header('User-Agent', 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25') 43 | req.add_header('Referer', 'https://passport.weibo.cn/signin/login?entry=mweibo&res=wel&wm=3349&r=http%3A%2F%2Fm.weibo.cn%2F%3Fjumpfrom%3Dweibocom') 44 | 45 | with request.urlopen(req, data=login_data.encode('utf-8')) as f: 46 | print('Status:', f.status, f.reason) 47 | for k, v in f.getheaders(): 48 | print('%s: %s' % (k, v)) 49 | print('Data:', f.read().decode('utf-8')) 50 | 51 | # with proxy and proxy auth: 52 | 53 | proxy_handler = urllib.request.ProxyHandler({'http': 'http://www.example.com:3128/'}) 54 | proxy_auth_handler = urllib.request.ProxyBasicAuthHandler() 55 | proxy_auth_handler.add_password('realm', 'host', 'username', 'password') 56 | opener = urllib.request.build_opener(proxy_handler, proxy_auth_handler) 57 | with opener.open('http://www.example.com/login.html') as f: 58 | pass 59 | -------------------------------------------------------------------------------- /samples/context/do_closing.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from contextlib import contextmanager 5 | 6 | @contextmanager 7 | def closing(fname): 8 | f = None 9 | try: 10 | f = open(fname, 'r') 11 | yield f 12 | finally: 13 | if f: 14 | f.close() 15 | 16 | with closing('test.txt') as f: 17 | print(f.read()) 18 | -------------------------------------------------------------------------------- /samples/context/do_suppress.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | 6 | from contextlib import suppress 7 | 8 | with suppress(FileNotFoundError): 9 | os.remove('tempfile.1') 10 | os.remove('tempfile.2') 11 | os.remove('tempfile.3') 12 | -------------------------------------------------------------------------------- /samples/context/do_with.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from contextlib import contextmanager 5 | 6 | @contextmanager 7 | def log(name): 8 | print('[%s] start...' % name) 9 | yield 10 | print('[%s] end.' % name) 11 | 12 | with log('DEBUG'): 13 | print('Hello, world!') 14 | print('Hello, Python!') 15 | -------------------------------------------------------------------------------- /samples/db/do_mysql.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | ########## prepare ########## 5 | 6 | # install mysql-connector-python: 7 | # pip3 install mysql-connector-python --allow-external mysql-connector-python 8 | 9 | import mysql.connector 10 | 11 | # change root password to yours: 12 | conn = mysql.connector.connect(user='root', password='password', database='test') 13 | 14 | cursor = conn.cursor() 15 | # 创建user表: 16 | cursor.execute('create table user (id varchar(20) primary key, name varchar(20))') 17 | # 插入一行记录,注意MySQL的占位符是%s: 18 | cursor.execute('insert into user (id, name) values (%s, %s)', ('1', 'Michael')) 19 | print('rowcount =', cursor.rowcount) 20 | # 提交事务: 21 | conn.commit() 22 | cursor.close() 23 | 24 | # 运行查询: 25 | cursor = conn.cursor() 26 | cursor.execute('select * from user where id = %s', ('1',)) 27 | values = cursor.fetchall() 28 | print(values) 29 | # 关闭Cursor和Connection: 30 | cursor.close() 31 | conn.close() 32 | -------------------------------------------------------------------------------- /samples/db/do_sqlalchemy.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from sqlalchemy import Column, String, create_engine 5 | from sqlalchemy.orm import sessionmaker 6 | from sqlalchemy.ext.declarative import declarative_base 7 | 8 | # 创建对象的基类: 9 | Base = declarative_base() 10 | 11 | # 定义User对象: 12 | class User(Base): 13 | # 表的名字: 14 | __tablename__ = 'user' 15 | 16 | # 表的结构: 17 | id = Column(String(20), primary_key=True) 18 | name = Column(String(20)) 19 | 20 | # 初始化数据库连接: 21 | engine = create_engine('mysql+mysqlconnector://root:password@localhost:3306/test') 22 | # 创建DBSession类型: 23 | DBSession = sessionmaker(bind=engine) 24 | 25 | # 创建session对象: 26 | session = DBSession() 27 | # 创建新User对象: 28 | new_user = User(id='5', name='Bob') 29 | # 添加到session: 30 | session.add(new_user) 31 | # 提交即保存到数据库: 32 | session.commit() 33 | # 关闭session: 34 | session.close() 35 | 36 | # 创建Session: 37 | session = DBSession() 38 | # 创建Query查询,filter是where条件,最后调用one()返回唯一行,如果调用all()则返回所有行: 39 | user = session.query(User).filter(User.id=='5').one() 40 | # 打印类型和对象的name属性: 41 | print('type:', type(user)) 42 | print('name:', user.name) 43 | # 关闭Session: 44 | session.close() 45 | -------------------------------------------------------------------------------- /samples/db/do_sqlite.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import sqlite3 5 | 6 | # 连接到SQLite数据库 7 | # 数据库文件是test.db 8 | # 如果文件不存在,会自动在当前目录创建: 9 | conn = sqlite3.connect('test.db') 10 | # 创建一个Cursor: 11 | cursor = conn.cursor() 12 | # 执行一条SQL语句,创建user表: 13 | cursor.execute('create table user (id varchar(20) primary key, name varchar(20))') 14 | # 继续执行一条SQL语句,插入一条记录: 15 | cursor.execute('insert into user (id, name) values (\'1\', \'Michael\')') 16 | # 通过rowcount获得插入的行数: 17 | print('rowcount =', cursor.rowcount) 18 | # 关闭Cursor: 19 | cursor.close() 20 | # 提交事务: 21 | conn.commit() 22 | # 关闭Connection: 23 | conn.close() 24 | 25 | # 查询记录: 26 | conn = sqlite3.connect('test.db') 27 | cursor = conn.cursor() 28 | # 执行查询语句: 29 | cursor.execute('select * from user where id=?', '1') 30 | # 获得查询结果集: 31 | values = cursor.fetchall() 32 | print(values) 33 | cursor.close() 34 | conn.close() 35 | -------------------------------------------------------------------------------- /samples/debug/do_assert.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | def foo(s): 5 | n = int(s) 6 | assert n != 0, 'n is zero!' 7 | return 10 / n 8 | 9 | def main(): 10 | foo('0') 11 | 12 | main() 13 | -------------------------------------------------------------------------------- /samples/debug/do_logging.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import logging 5 | logging.basicConfig(level=logging.INFO) 6 | 7 | s = '0' 8 | n = int(s) 9 | logging.info('n = %d' % n) 10 | print(10 / n) 11 | -------------------------------------------------------------------------------- /samples/debug/do_pdb.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import pdb 5 | 6 | s = '0' 7 | n = int(s) 8 | pdb.set_trace() # 运行到这里会自动暂停 9 | print(10 / n) 10 | -------------------------------------------------------------------------------- /samples/debug/do_try.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | try: 5 | print('try...') 6 | r = 10 / 0 7 | print('result:', r) 8 | except ZeroDivisionError as e: 9 | print('except:', e) 10 | finally: 11 | print('finally...') 12 | print('END') 13 | -------------------------------------------------------------------------------- /samples/debug/err.py: -------------------------------------------------------------------------------- 1 | # err.py 2 | def foo(s): 3 | return 10 / int(s) 4 | 5 | def bar(s): 6 | return foo(s) * 2 7 | 8 | def main(): 9 | bar('0') 10 | 11 | main() 12 | 13 | -------------------------------------------------------------------------------- /samples/debug/err_logging.py: -------------------------------------------------------------------------------- 1 | # err_logging.py 2 | 3 | import logging 4 | 5 | def foo(s): 6 | return 10 / int(s) 7 | 8 | def bar(s): 9 | return foo(s) * 2 10 | 11 | def main(): 12 | try: 13 | bar('0') 14 | except Exception as e: 15 | logging.exception(e) 16 | 17 | main() 18 | print('END') 19 | 20 | -------------------------------------------------------------------------------- /samples/debug/err_raise.py: -------------------------------------------------------------------------------- 1 | # err_raise.py 2 | class FooError(ValueError): 3 | pass 4 | 5 | def foo(s): 6 | n = int(s) 7 | if n==0: 8 | raise FooError('invalid value: %s' % s) 9 | return 10 / n 10 | 11 | foo('0') 12 | 13 | -------------------------------------------------------------------------------- /samples/debug/err_reraise.py: -------------------------------------------------------------------------------- 1 | # err_reraise.py 2 | 3 | def foo(s): 4 | n = int(s) 5 | if n==0: 6 | raise ValueError('invalid value: %s' % s) 7 | return 10 / n 8 | 9 | def bar(): 10 | try: 11 | foo('0') 12 | except ValueError as e: 13 | print('ValueError!') 14 | raise 15 | 16 | bar() 17 | 18 | -------------------------------------------------------------------------------- /samples/debug/mydict.py: -------------------------------------------------------------------------------- 1 | class Dict(dict): 2 | 3 | def __init__(self, **kw): 4 | super().__init__(**kw) 5 | 6 | def __getattr__(self, key): 7 | try: 8 | return self[key] 9 | except KeyError: 10 | raise AttributeError(r"'Dict' object has no attribute '%s'" % key) 11 | 12 | def __setattr__(self, key, value): 13 | self[key] = value 14 | 15 | -------------------------------------------------------------------------------- /samples/debug/mydict2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | class Dict(dict): 5 | ''' 6 | Simple dict but also support access as x.y style. 7 | 8 | >>> d1 = Dict() 9 | >>> d1['x'] = 100 10 | >>> d1.x 11 | 100 12 | >>> d1.y = 200 13 | >>> d1['y'] 14 | 200 15 | >>> d2 = Dict(a=1, b=2, c='3') 16 | >>> d2.c 17 | '3' 18 | >>> d2['empty'] 19 | Traceback (most recent call last): 20 | ... 21 | KeyError: 'empty' 22 | >>> d2.empty 23 | Traceback (most recent call last): 24 | ... 25 | AttributeError: 'Dict' object has no attribute 'empty' 26 | ''' 27 | def __init__(self, **kw): 28 | super(Dict, self).__init__(**kw) 29 | 30 | def __getattr__(self, key): 31 | try: 32 | return self[key] 33 | except KeyError: 34 | raise AttributeError(r"'Dict' object has no attribute '%s'" % key) 35 | 36 | def __setattr__(self, key, value): 37 | self[key] = value 38 | 39 | if __name__=='__main__': 40 | import doctest 41 | doctest.testmod() 42 | 43 | -------------------------------------------------------------------------------- /samples/debug/mydict_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import unittest 5 | 6 | from mydict import Dict 7 | 8 | class TestDict(unittest.TestCase): 9 | 10 | def test_init(self): 11 | d = Dict(a=1, b='test') 12 | self.assertEqual(d.a, 1) 13 | self.assertEqual(d.b, 'test') 14 | self.assertTrue(isinstance(d, dict)) 15 | 16 | def test_key(self): 17 | d = Dict() 18 | d['key'] = 'value' 19 | self.assertEqual(d.key, 'value') 20 | 21 | def test_attr(self): 22 | d = Dict() 23 | d.key = 'value' 24 | self.assertTrue('key' in d) 25 | self.assertEqual(d['key'], 'value') 26 | 27 | def test_keyerror(self): 28 | d = Dict() 29 | with self.assertRaises(KeyError): 30 | value = d['empty'] 31 | 32 | def test_attrerror(self): 33 | d = Dict() 34 | with self.assertRaises(AttributeError): 35 | value = d.empty 36 | 37 | if __name__ == '__main__': 38 | unittest.main() 39 | 40 | -------------------------------------------------------------------------------- /samples/function/call_func.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | x = abs(100) 5 | y = abs(-20) 6 | print(x, y) 7 | print('max(1, 2, 3) =', max(1, 2, 3)) 8 | print('min(1, 2, 3) =', min(1, 2, 3)) 9 | print('sum([1, 2, 3]) =', sum([1, 2, 3])) 10 | -------------------------------------------------------------------------------- /samples/function/def_func.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import math 5 | 6 | def my_abs(x): 7 | if not isinstance(x, (int, float)): 8 | raise TypeError('bad operand type') 9 | if x >= 0: 10 | return x 11 | else: 12 | return -x 13 | 14 | def move(x, y, step, angle=0): 15 | nx = x + step * math.cos(angle) 16 | ny = y - step * math.sin(angle) 17 | return nx, ny 18 | 19 | n = my_abs(-20) 20 | print(n) 21 | 22 | x, y = move(100, 100, 60, math.pi / 6) 23 | print(x, y) 24 | 25 | # TypeError: bad operand type: 26 | my_abs('123') 27 | -------------------------------------------------------------------------------- /samples/function/kw_args.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | def print_scores(**kw): 5 | print(' Name Score') 6 | print('------------------') 7 | for name, score in kw.items(): 8 | print('%10s %d' % (name, score)) 9 | print() 10 | 11 | print_scores(Adam=99, Lisa=88, Bart=77) 12 | 13 | data = { 14 | 'Adam Lee': 99, 15 | 'Lisa S': 88, 16 | 'F.Bart': 77 17 | } 18 | 19 | print_scores(**data) 20 | 21 | def print_info(name, *, gender, city='Beijing', age): 22 | print('Personal Info') 23 | print('---------------') 24 | print(' Name: %s' % name) 25 | print(' Gender: %s' % gender) 26 | print(' City: %s' % city) 27 | print(' Age: %s' % age) 28 | print() 29 | 30 | print_info('Bob', gender='male', age=20) 31 | print_info('Lisa', gender='female', city='Shanghai', age=18) 32 | -------------------------------------------------------------------------------- /samples/function/recur.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | # 利用递归函数计算阶乘 5 | # N! = 1 * 2 * 3 * ... * N 6 | def fact(n): 7 | if n == 1: 8 | return 1 9 | return n * fact(n-1) 10 | 11 | print('fact(1) =', fact(1)) 12 | print('fact(5) =', fact(5)) 13 | print('fact(10) =', fact(10)) 14 | 15 | # 利用递归函数移动汉诺塔: 16 | def move(n, a, b, c): 17 | if n == 1: 18 | print('move', a, '-->', c) 19 | else: 20 | move(n-1, a, c, b) 21 | move(1, a, b, c) 22 | move(n-1, b, a, c) 23 | 24 | move(4, 'A', 'B', 'C') 25 | -------------------------------------------------------------------------------- /samples/function/var_args.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | def hello(greeting, *args): 5 | if (len(args)==0): 6 | print('%s!' % greeting) 7 | else: 8 | print('%s, %s!' % (greeting, ', '.join(args))) 9 | 10 | hello('Hi') # => greeting='Hi', args=() 11 | hello('Hi', 'Sarah') # => greeting='Hi', args=('Sarah') 12 | hello('Hello', 'Michael', 'Bob', 'Adam') # => greeting='Hello', args=('Michael', 'Bob', 'Adam') 13 | 14 | names = ('Bart', 'Lisa') 15 | hello('Hello', *names) # => greeting='Hello', args=('Bart', 'Lisa') 16 | -------------------------------------------------------------------------------- /samples/functional/decorator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import functools 5 | 6 | def log(func): 7 | @functools.wraps(func) 8 | def wrapper(*args, **kw): 9 | print('call %s():' % func.__name__) 10 | return func(*args, **kw) 11 | return wrapper 12 | 13 | @log 14 | def now(): 15 | print('2015-3-25') 16 | 17 | now() 18 | 19 | def logger(text): 20 | def decorator(func): 21 | @functools.wraps(func) 22 | def wrapper(*args, **kw): 23 | print('%s %s():' % (text, func.__name__)) 24 | return func(*args, **kw) 25 | return wrapper 26 | return decorator 27 | 28 | @logger('DEBUG') 29 | def today(): 30 | print('2015-3-25') 31 | 32 | today() 33 | print(today.__name__) 34 | -------------------------------------------------------------------------------- /samples/functional/do_filter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | def is_odd(n): 5 | return n % 2 == 1 6 | 7 | L = range(100) 8 | 9 | print(list(filter(is_odd, L))) 10 | 11 | def not_empty(s): 12 | return s and s.strip() 13 | 14 | print(list(filter(not_empty, ['A', '', 'B', None, 'C', ' ']))) 15 | -------------------------------------------------------------------------------- /samples/functional/do_map.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | def f(x): 5 | return x * x 6 | 7 | print(list(map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]))) 8 | -------------------------------------------------------------------------------- /samples/functional/do_partial.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import functools 5 | 6 | int2 = functools.partial(int, base=2) 7 | 8 | print('1000000 =', int2('1000000')) 9 | print('1010101 =', int2('1010101')) 10 | -------------------------------------------------------------------------------- /samples/functional/do_reduce.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from functools import reduce 5 | 6 | CHAR_TO_INT = { 7 | '0': 0, 8 | '1': 1, 9 | '2': 2, 10 | '3': 3, 11 | '4': 4, 12 | '5': 5, 13 | '6': 6, 14 | '7': 7, 15 | '8': 8, 16 | '9': 9 17 | } 18 | 19 | def str2int(s): 20 | ints = map(lambda ch: CHAR_TO_INT[ch], s) 21 | return reduce(lambda x, y: x * 10 + y, ints) 22 | 23 | print(str2int('0')) 24 | print(str2int('12300')) 25 | print(str2int('0012345')) 26 | 27 | CHAR_TO_FLOAT = { 28 | '0': 0, 29 | '1': 1, 30 | '2': 2, 31 | '3': 3, 32 | '4': 4, 33 | '5': 5, 34 | '6': 6, 35 | '7': 7, 36 | '8': 8, 37 | '9': 9, 38 | '.': -1 39 | } 40 | 41 | def str2float(s): 42 | nums = map(lambda ch: CHAR_TO_FLOAT[ch], s) 43 | point = 0 44 | def to_float(f, n): 45 | nonlocal point 46 | if n == -1: 47 | point = 1 48 | return f 49 | if point == 0: 50 | return f * 10 + n 51 | else: 52 | point = point * 10 53 | return f + n / point 54 | return reduce(to_float, nums, 0.0) 55 | 56 | print(str2float('0')) 57 | print(str2float('123.456')) 58 | print(str2float('123.45600')) 59 | print(str2float('0.1234')) 60 | print(str2float('.1234')) 61 | print(str2float('120.0034')) 62 | -------------------------------------------------------------------------------- /samples/functional/do_sorted.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from operator import itemgetter 5 | 6 | L = ['bob', 'about', 'Zoo', 'Credit'] 7 | 8 | print(sorted(L)) 9 | print(sorted(L, key=str.lower)) 10 | 11 | students = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)] 12 | 13 | print(sorted(students, key=itemgetter(0))) 14 | print(sorted(students, key=lambda t: t[1])) 15 | print(sorted(students, key=itemgetter(1), reverse=True)) 16 | -------------------------------------------------------------------------------- /samples/functional/prime_numbers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | def main(): 5 | for n in primes(): 6 | if n < 1000: 7 | print(n) 8 | else: 9 | break 10 | 11 | def _odd_iter(): 12 | n = 1 13 | while True: 14 | n = n + 2 15 | yield n 16 | 17 | def _not_divisible(n): 18 | return lambda x: x % n > 0 19 | 20 | def primes(): 21 | yield 2 22 | it = _odd_iter() 23 | while True: 24 | n = next(it) 25 | yield n 26 | it = filter(_not_divisible(n), it) 27 | 28 | if __name__ == '__main__': 29 | main() 30 | -------------------------------------------------------------------------------- /samples/functional/return_func.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | def lazy_sum(*args): 5 | def sum(): 6 | ax = 0 7 | for n in args: 8 | ax = ax + n 9 | return ax 10 | return sum 11 | 12 | f = lazy_sum(1, 2, 4, 5, 7, 8, 9) 13 | print(f) 14 | print(f()) 15 | 16 | # why f1(), f2(), f3() returns 9, 9, 9 rather than 1, 4, 9? 17 | def count(): 18 | fs = [] 19 | for i in range(1, 4): 20 | def f(): 21 | return i * i 22 | fs.append(f) 23 | return fs 24 | 25 | f1, f2, f3 = count() 26 | 27 | print(f1()) 28 | print(f2()) 29 | print(f3()) 30 | 31 | # fix: 32 | def count(): 33 | fs = [] 34 | def f(n): 35 | def j(): 36 | return n * n 37 | return j 38 | for i in range(1, 4): 39 | fs.append(f(i)) 40 | return fs 41 | 42 | f1, f2, f3 = count() 43 | 44 | print(f1()) 45 | print(f2()) 46 | print(f3()) 47 | -------------------------------------------------------------------------------- /samples/gui/hello_gui.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from tkinter import * 5 | import tkinter.messagebox as messagebox 6 | 7 | class Application(Frame): 8 | def __init__(self, master=None): 9 | Frame.__init__(self, master) 10 | self.pack() 11 | self.createWidgets() 12 | 13 | def createWidgets(self): 14 | self.nameInput = Entry(self) 15 | self.nameInput.pack() 16 | self.alertButton = Button(self, text='Hello', command=self.hello) 17 | self.alertButton.pack() 18 | 19 | def hello(self): 20 | name = self.nameInput.get() or 'world' 21 | messagebox.showinfo('Message', 'Hello, %s' % name) 22 | 23 | app = Application() 24 | # 设置窗口标题: 25 | app.master.title('Hello World') 26 | # 主消息循环: 27 | app.mainloop() 28 | -------------------------------------------------------------------------------- /samples/gui/turtle/rect.py: -------------------------------------------------------------------------------- 1 | # 导入turtle包的所有内容: 2 | from turtle import * 3 | 4 | # 设置笔刷宽度: 5 | width(4) 6 | 7 | # 前进: 8 | forward(200) 9 | # 右转90度: 10 | right(90) 11 | 12 | # 笔刷颜色: 13 | pencolor('red') 14 | forward(100) 15 | right(90) 16 | 17 | pencolor('green') 18 | forward(200) 19 | right(90) 20 | 21 | pencolor('blue') 22 | forward(100) 23 | right(90) 24 | 25 | # 调用done()使得窗口等待被关闭,否则将立刻关闭窗口: 26 | done() 27 | -------------------------------------------------------------------------------- /samples/gui/turtle/stars.py: -------------------------------------------------------------------------------- 1 | from turtle import * 2 | 3 | def drawStar(x, y): 4 | pu() 5 | goto(x, y) 6 | pd() 7 | # set heading: 0 8 | seth(0) 9 | for i in range(5): 10 | fd(40) 11 | rt(144) 12 | 13 | for x in range(0, 250, 50): 14 | drawStar(x, 0) 15 | 16 | done() 17 | -------------------------------------------------------------------------------- /samples/gui/turtle/tree.py: -------------------------------------------------------------------------------- 1 | from turtle import * 2 | 3 | colormode(255) 4 | 5 | lt(90) 6 | 7 | lv = 14 8 | l = 120 9 | s = 45 10 | 11 | width(lv) 12 | 13 | r = 0 14 | g = 0 15 | b = 0 16 | pencolor(r, g, b) 17 | 18 | penup() 19 | bk(l) 20 | pendown() 21 | fd(l) 22 | 23 | def draw_tree(l, level): 24 | global r, g, b 25 | # save the current pen width 26 | w = width() 27 | 28 | # narrow the pen width 29 | width(w * 3.0 / 4.0) 30 | # set color: 31 | r = r + 1 32 | g = g + 2 33 | b = b + 3 34 | pencolor(r % 200, g % 200, b % 200) 35 | 36 | l = 3.0 / 4.0 * l 37 | 38 | lt(s) 39 | fd(l) 40 | 41 | if level < lv: 42 | draw_tree(l, level + 1) 43 | bk(l) 44 | rt(2 * s) 45 | fd(l) 46 | 47 | if level < lv: 48 | draw_tree(l, level + 1) 49 | bk(l) 50 | lt(s) 51 | 52 | # restore the previous pen width 53 | width(w) 54 | 55 | speed("fastest") 56 | 57 | draw_tree(l, 4) 58 | 59 | done() 60 | -------------------------------------------------------------------------------- /samples/io/do_bytesio.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from io import BytesIO 5 | 6 | # write to BytesIO: 7 | f = BytesIO() 8 | f.write(b'hello') 9 | f.write(b' ') 10 | f.write(b'world!') 11 | print(f.getvalue()) 12 | 13 | # read from BytesIO: 14 | data = '人闲桂花落,夜静春山空。月出惊山鸟,时鸣春涧中。'.encode('utf-8') 15 | f = BytesIO(data) 16 | print(f.read()) 17 | -------------------------------------------------------------------------------- /samples/io/do_dir.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from datetime import datetime 5 | import os 6 | 7 | pwd = os.path.abspath('.') 8 | 9 | print(' Size Last Modified Name') 10 | print('------------------------------------------------------------') 11 | 12 | for f in os.listdir(pwd): 13 | fsize = os.path.getsize(f) 14 | mtime = datetime.fromtimestamp(os.path.getmtime(f)).strftime('%Y-%m-%d %H:%M') 15 | flag = '/' if os.path.isdir(f) else '' 16 | print('%10d %s %s%s' % (fsize, mtime, f, flag)) 17 | -------------------------------------------------------------------------------- /samples/io/do_stringio.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from io import StringIO 5 | 6 | # write to StringIO: 7 | f = StringIO() 8 | f.write('hello') 9 | f.write(' ') 10 | f.write('world!') 11 | print(f.getvalue()) 12 | 13 | # read from StringIO: 14 | f = StringIO('水面细风生,\n菱歌慢慢声。\n客亭临小市,\n灯火夜妆明。') 15 | while True: 16 | s = f.readline() 17 | if s == '': 18 | break 19 | print(s.strip()) 20 | -------------------------------------------------------------------------------- /samples/io/use_json.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import json 5 | 6 | d = dict(name='Bob', age=20, score=88) 7 | data = json.dumps(d) 8 | print('JSON Data is a str:', data) 9 | reborn = json.loads(data) 10 | print(reborn) 11 | 12 | class Student(object): 13 | 14 | def __init__(self, name, age, score): 15 | self.name = name 16 | self.age = age 17 | self.score = score 18 | 19 | def __str__(self): 20 | return 'Student object (%s, %s, %s)' % (self.name, self.age, self.score) 21 | 22 | s = Student('Bob', 20, 88) 23 | std_data = json.dumps(s, default=lambda obj: obj.__dict__) 24 | print('Dump Student:', std_data) 25 | rebuild = json.loads(std_data, object_hook=lambda d: Student(d['name'], d['age'], d['score'])) 26 | print(rebuild) 27 | -------------------------------------------------------------------------------- /samples/io/use_pickle.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import pickle 5 | 6 | d = dict(name='Bob', age=20, score=88) 7 | data = pickle.dumps(d) 8 | print(data) 9 | 10 | reborn = pickle.loads(data) 11 | print(reborn) 12 | -------------------------------------------------------------------------------- /samples/io/with_file.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from datetime import datetime 5 | 6 | with open('test.txt', 'w') as f: 7 | f.write('今天是 ') 8 | f.write(datetime.now().strftime('%Y-%m-%d')) 9 | 10 | with open('test.txt', 'r') as f: 11 | s = f.read() 12 | print('open for read...') 13 | print(s) 14 | 15 | with open('test.txt', 'rb') as f: 16 | s = f.read() 17 | print('open as binary for read...') 18 | print(s) 19 | -------------------------------------------------------------------------------- /samples/mail/fetch_mail.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from email.parser import Parser 5 | from email.header import decode_header 6 | from email.utils import parseaddr 7 | 8 | import poplib 9 | 10 | # 输入邮件地址, 口令和POP3服务器地址: 11 | email = input('Email: ') 12 | password = input('Password: ') 13 | pop3_server = input('POP3 server: ') 14 | 15 | def guess_charset(msg): 16 | charset = msg.get_charset() 17 | if charset is None: 18 | content_type = msg.get('Content-Type', '').lower() 19 | pos = content_type.find('charset=') 20 | if pos >= 0: 21 | charset = content_type[pos + 8:].strip() 22 | return charset 23 | 24 | def decode_str(s): 25 | value, charset = decode_header(s)[0] 26 | if charset: 27 | value = value.decode(charset) 28 | return value 29 | 30 | def print_info(msg, indent=0): 31 | if indent == 0: 32 | for header in ['From', 'To', 'Subject']: 33 | value = msg.get(header, '') 34 | if value: 35 | if header=='Subject': 36 | value = decode_str(value) 37 | else: 38 | hdr, addr = parseaddr(value) 39 | name = decode_str(hdr) 40 | value = u'%s <%s>' % (name, addr) 41 | print('%s%s: %s' % (' ' * indent, header, value)) 42 | if (msg.is_multipart()): 43 | parts = msg.get_payload() 44 | for n, part in enumerate(parts): 45 | print('%spart %s' % (' ' * indent, n)) 46 | print('%s--------------------' % (' ' * indent)) 47 | print_info(part, indent + 1) 48 | else: 49 | content_type = msg.get_content_type() 50 | if content_type=='text/plain' or content_type=='text/html': 51 | content = msg.get_payload(decode=True) 52 | charset = guess_charset(msg) 53 | if charset: 54 | content = content.decode(charset) 55 | print('%sText: %s' % (' ' * indent, content + '...')) 56 | else: 57 | print('%sAttachment: %s' % (' ' * indent, content_type)) 58 | 59 | # 连接到POP3服务器: 60 | server = poplib.POP3(pop3_server) 61 | # 可以打开或关闭调试信息: 62 | server.set_debuglevel(1) 63 | # 可选:打印POP3服务器的欢迎文字: 64 | print(server.getwelcome().decode('utf-8')) 65 | # 身份认证: 66 | server.user(email) 67 | server.pass_(password) 68 | # stat()返回邮件数量和占用空间: 69 | print('Messages: %s. Size: %s' % server.stat()) 70 | # list()返回所有邮件的编号: 71 | resp, mails, octets = server.list() 72 | # 可以查看返回的列表类似[b'1 82923', b'2 2184', ...] 73 | print(mails) 74 | # 获取最新一封邮件, 注意索引号从1开始: 75 | index = len(mails) 76 | resp, lines, octets = server.retr(index) 77 | # lines存储了邮件的原始文本的每一行, 78 | # 可以获得整个邮件的原始文本: 79 | msg_content = b'\r\n'.join(lines).decode('utf-8') 80 | # 稍后解析出邮件: 81 | msg = Parser().parsestr(msg_content) 82 | print_info(msg) 83 | # 可以根据邮件索引号直接从服务器删除邮件: 84 | # server.dele(index) 85 | # 关闭连接: 86 | server.quit() 87 | -------------------------------------------------------------------------------- /samples/mail/send_mail.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from email import encoders 5 | from email.header import Header 6 | from email.mime.text import MIMEText 7 | from email.utils import parseaddr, formataddr 8 | import smtplib 9 | 10 | def _format_addr(s): 11 | name, addr = parseaddr(s) 12 | return formataddr((Header(name, 'utf-8').encode(), addr)) 13 | 14 | from_addr = input('From: ') 15 | password = input('Password: ') 16 | to_addr = input('To: ') 17 | smtp_server = input('SMTP server: ') 18 | 19 | msg = MIMEText('hello, send by Python...', 'plain', 'utf-8') 20 | msg['From'] = _format_addr('Python爱好者 <%s>' % from_addr) 21 | msg['To'] = _format_addr('管理员 <%s>' % to_addr) 22 | msg['Subject'] = Header('来自SMTP的问候……', 'utf-8').encode() 23 | 24 | server = smtplib.SMTP(smtp_server, 25) 25 | server.set_debuglevel(1) 26 | server.login(from_addr, password) 27 | server.sendmail(from_addr, [to_addr], msg.as_string()) 28 | server.quit() 29 | -------------------------------------------------------------------------------- /samples/micropython/hellorobot/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | 5 | // List of extensions which should be recommended for users of this workspace. 6 | "recommendations": [ 7 | "lego-education.ev3-micropython" 8 | ], 9 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace. 10 | "unwantedRecommendations": [ 11 | "ms-python.python" 12 | ] 13 | } -------------------------------------------------------------------------------- /samples/micropython/hellorobot/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Download and Run", 9 | "type": "ev3devBrowser", 10 | "request": "launch", 11 | "program": "/home/robot/${workspaceRootFolderName}/main.py" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /samples/micropython/hellorobot/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.eol": "\n", 4 | "debug.openDebug": "neverOpen", 5 | "python.linting.enabled": false 6 | } 7 | -------------------------------------------------------------------------------- /samples/micropython/hellorobot/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env pybricks-micropython 2 | 3 | from pybricks import ev3brick as brick 4 | from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor, InfraredSensor, UltrasonicSensor, GyroSensor) 5 | from pybricks.parameters import (Port, Stop, Direction, Button, Color, SoundFile, ImageFile, Align) 6 | from pybricks.tools import print, wait, StopWatch 7 | from pybricks.robotics import DriveBase 8 | 9 | # Write your program here 10 | brick.sound.beep() 11 | # 输出到控制台: 12 | print('Hello, robot!') 13 | # 输出到EV3屏幕: 14 | brick.display.text('Hello, robot!') 15 | -------------------------------------------------------------------------------- /samples/micropython/rccar/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | 5 | // List of extensions which should be recommended for users of this workspace. 6 | "recommendations": [ 7 | "lego-education.ev3-micropython" 8 | ], 9 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace. 10 | "unwantedRecommendations": [ 11 | "ms-python.python" 12 | ] 13 | } -------------------------------------------------------------------------------- /samples/micropython/rccar/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Download and Run", 9 | "type": "ev3devBrowser", 10 | "request": "launch", 11 | "program": "/home/robot/${workspaceRootFolderName}/main.py" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /samples/micropython/rccar/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.eol": "\n", 4 | "debug.openDebug": "neverOpen", 5 | "python.linting.enabled": false 6 | } 7 | -------------------------------------------------------------------------------- /samples/micropython/rccar/devices.py: -------------------------------------------------------------------------------- 1 | # list input devices 2 | 3 | class InputDevice(): 4 | def __init__(self): 5 | self.name = '' 6 | self.handler = '' 7 | 8 | def __str__(self): 9 | return '' % (self.name, self.handler) 10 | 11 | def setName(self, name): 12 | if len(name) >= 2 and name.startswith('"') and name.endswith('"'): 13 | name = name[1:len(name)-1] 14 | self.name = name 15 | 16 | def setHandler(self, handlers): 17 | for handler in handlers.split(' '): 18 | if handler.startswith('event'): 19 | self.handler = handler 20 | 21 | def listDevices(): 22 | devices = [] 23 | with open('/proc/bus/input/devices', 'r') as f: 24 | device = None 25 | while True: 26 | s = f.readline() 27 | if s == '': 28 | break 29 | s = s.strip() 30 | if s == '': 31 | devices.append(device) 32 | device = None 33 | else: 34 | if device is None: 35 | device = InputDevice() 36 | if s.startswith('N: Name='): 37 | device.setName(s[8:]) 38 | elif s.startswith('H: Handlers='): 39 | device.setHandler(s[12:]) 40 | return devices 41 | 42 | def detectJoystick(joystickNames): 43 | for device in listDevices(): 44 | for joystickName in joystickNames: 45 | if joystickName in device.name: 46 | return '/dev/input/%s' % device.handler 47 | return None 48 | -------------------------------------------------------------------------------- /samples/micropython/rccar/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env pybricks-micropython 2 | 3 | import struct, threading 4 | 5 | from pybricks import ev3brick as brick 6 | from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor, InfraredSensor, UltrasonicSensor, GyroSensor) 7 | from pybricks.parameters import (Port, Stop, Direction, Button, Color, SoundFile, ImageFile, Align) 8 | from pybricks.tools import print, wait, StopWatch 9 | from pybricks.robotics import DriveBase 10 | from devices import detectJoystick 11 | 12 | class Robot(): 13 | def __init__(self): 14 | self.motor = Motor(Port.B) 15 | self.ultrasonic = UltrasonicSensor(Port.S4) 16 | self.active = True 17 | self.speed = 0 18 | self.colors = [None, Color.GREEN, Color.YELLOW, Color.RED] 19 | 20 | def setSpeed(self, acc): 21 | if acc < 0: 22 | self.speed = max(-3, self.speed - 1) 23 | elif acc > 0: 24 | self.speed = min(3, self.speed + 1) 25 | else: 26 | self.speed = 0 27 | if self.speed != 0: 28 | self.motor.run(self.speed * 90) 29 | else: 30 | self.motor.stop() 31 | brick.light(self.colors[abs(self.speed)]) 32 | 33 | def inactive(self): 34 | self.active = False 35 | self.setSpeed(0) 36 | brick.sound.beep() 37 | 38 | def autoStopLoop(robot): 39 | while robot.active: 40 | if robot.speed > 0 and robot.ultrasonic.distance() < 200: 41 | robot.setSpeed(0) 42 | wait(100) 43 | 44 | def joystickLoop(robot, eventFile): 45 | FORMAT = 'llHHI' 46 | EVENT_SIZE = struct.calcsize(FORMAT) 47 | with open(eventFile, 'rb') as infile: 48 | while True: 49 | event = infile.read(EVENT_SIZE) 50 | _, _, t, c, v = struct.unpack(FORMAT, event) 51 | # button A, B: 52 | if t == 1 and v == 1: 53 | if c == 305: 54 | # press A: 55 | robot.setSpeed(1) 56 | elif c == 304: 57 | # press B: 58 | robot.setSpeed(-1) 59 | elif c == 307: 60 | # press X: 61 | return robot.inactive() 62 | elif t == 3: 63 | if c == 1: 64 | # Left stick & vertical: 65 | speed = 0 66 | if v < 32768: 67 | # up: 68 | speed = 1 69 | elif v > 32768: 70 | # down: 71 | speed = -1 72 | robot.setSpeed(speed) 73 | 74 | def buttonLoop(robot): 75 | while True: 76 | if not any(brick.buttons()): 77 | wait(10) 78 | else: 79 | if Button.LEFT in brick.buttons(): 80 | robot.setSpeed(-1) 81 | elif Button.RIGHT in brick.buttons(): 82 | robot.setSpeed(1) 83 | elif Button.CENTER in brick.buttons(): 84 | robot.setSpeed(0) 85 | elif Button.UP in brick.buttons(): 86 | return robot.inactive() 87 | wait(500) 88 | 89 | def main(): 90 | brick.sound.beep() 91 | joystickEvent = detectJoystick(['Controller']) 92 | robot = Robot() 93 | t = threading.Thread(target=autoStopLoop, args=(robot,)) 94 | t.start() 95 | if joystickEvent: 96 | joystickLoop(robot, joystickEvent) 97 | else: 98 | buttonLoop(robot) 99 | 100 | main() 101 | -------------------------------------------------------------------------------- /samples/micropython/smallcar/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | 5 | // List of extensions which should be recommended for users of this workspace. 6 | "recommendations": [ 7 | "lego-education.ev3-micropython" 8 | ], 9 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace. 10 | "unwantedRecommendations": [ 11 | "ms-python.python" 12 | ] 13 | } -------------------------------------------------------------------------------- /samples/micropython/smallcar/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Download and Run", 9 | "type": "ev3devBrowser", 10 | "request": "launch", 11 | "program": "/home/robot/${workspaceRootFolderName}/main.py" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /samples/micropython/smallcar/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.eol": "\n", 4 | "debug.openDebug": "neverOpen", 5 | "python.linting.enabled": false, 6 | "python.formatting.provider": "autopep8" 7 | } 8 | -------------------------------------------------------------------------------- /samples/micropython/smallcar/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env pybricks-micropython 2 | 3 | from pybricks import ev3brick as brick 4 | from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor, InfraredSensor, UltrasonicSensor, GyroSensor) 5 | from pybricks.parameters import (Port, Stop, Direction, Button, Color, SoundFile, ImageFile, Align) 6 | from pybricks.tools import print, wait, StopWatch 7 | from pybricks.robotics import DriveBase 8 | 9 | # Write your program here 10 | 11 | motor = Motor(Port.B) 12 | ultrasonic = UltrasonicSensor(Port.S4) 13 | 14 | brick.sound.beep() 15 | brick.light(None) 16 | 17 | speed = 0 18 | colors = [None, Color.GREEN, Color.YELLOW, Color.RED] 19 | 20 | def setSpeed(acc): 21 | global speed 22 | if acc < 0: 23 | speed = max(0, speed - 1) 24 | elif acc > 0: 25 | speed = min(3, speed + 1) 26 | else: 27 | speed = 0 28 | if speed > 0: 29 | motor.run(speed * 90) 30 | else: 31 | motor.stop() 32 | brick.light(colors[speed]) 33 | 34 | while True: 35 | if not any(brick.buttons()): 36 | wait(10) 37 | else: 38 | if Button.LEFT in brick.buttons(): 39 | setSpeed(-1) 40 | elif Button.RIGHT in brick.buttons(): 41 | setSpeed(1) 42 | elif Button.CENTER in brick.buttons(): 43 | setSpeed(0) 44 | elif Button.UP in brick.buttons(): 45 | setSpeed(0) 46 | break 47 | wait(500) 48 | if ultrasonic.distance() < 200: 49 | setSpeed(0) 50 | 51 | brick.sound.beep() 52 | -------------------------------------------------------------------------------- /samples/micropython/tank/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | 5 | // List of extensions which should be recommended for users of this workspace. 6 | "recommendations": [ 7 | "lego-education.ev3-micropython" 8 | ], 9 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace. 10 | "unwantedRecommendations": [ 11 | "ms-python.python" 12 | ] 13 | } -------------------------------------------------------------------------------- /samples/micropython/tank/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Download and Run", 9 | "type": "ev3devBrowser", 10 | "request": "launch", 11 | "program": "/home/robot/${workspaceRootFolderName}/main.py" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /samples/micropython/tank/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.eol": "\n", 4 | "debug.openDebug": "neverOpen", 5 | "python.linting.enabled": false 6 | } 7 | -------------------------------------------------------------------------------- /samples/micropython/tank/cannon.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelliao/learn-python3/27f49401960be8233d2c52b9e214ac9da7be22d3/samples/micropython/tank/cannon.wav -------------------------------------------------------------------------------- /samples/micropython/tank/devices.py: -------------------------------------------------------------------------------- 1 | # list input devices 2 | 3 | class InputDevice(): 4 | def __init__(self): 5 | self.name = '' 6 | self.handler = '' 7 | 8 | def __str__(self): 9 | return '' % (self.name, self.handler) 10 | 11 | def setName(self, name): 12 | if len(name) >= 2 and name.startswith('"') and name.endswith('"'): 13 | name = name[1:len(name)-1] 14 | self.name = name 15 | 16 | def setHandler(self, handlers): 17 | for handler in handlers.split(' '): 18 | if handler.startswith('event'): 19 | self.handler = handler 20 | 21 | def listDevices(): 22 | devices = [] 23 | with open('/proc/bus/input/devices', 'r') as f: 24 | device = None 25 | while True: 26 | s = f.readline() 27 | if s == '': 28 | break 29 | s = s.strip() 30 | if s == '': 31 | devices.append(device) 32 | device = None 33 | else: 34 | if device is None: 35 | device = InputDevice() 36 | if s.startswith('N: Name='): 37 | device.setName(s[8:]) 38 | elif s.startswith('H: Handlers='): 39 | device.setHandler(s[12:]) 40 | return devices 41 | 42 | def detectJoystick(joystickNames): 43 | for device in listDevices(): 44 | for joystickName in joystickNames: 45 | if joystickName in device.name: 46 | return '/dev/input/%s' % device.handler 47 | return None 48 | -------------------------------------------------------------------------------- /samples/micropython/tank/joystick.py: -------------------------------------------------------------------------------- 1 | # joystick control: 2 | 3 | import struct 4 | 5 | # define button code: 6 | 7 | BUTTON_A = 305 8 | BUTTON_B = 304 9 | BUTTON_X = 307 10 | BUTTON_Y = 306 11 | BUTTON_PLUS = 313 12 | BUTTON_MINUS = 312 13 | BUTTON_START = 317 14 | BUTTON_HOME = 316 15 | 16 | class JoyStick(): 17 | def __init__(self, eventFile): 18 | self.eventFile = eventFile 19 | self.buttonHandler = None 20 | self.joyLeftHandler = None 21 | self.joyRightHandler = None 22 | 23 | def setButtonHandler(self, buttonHandler): 24 | self.buttonHandler = buttonHandler 25 | 26 | def setJoyLeftHandler(self, joyLeftHandler): 27 | self.joyLeftHandler = joyLeftHandler 28 | 29 | def setJoyRightHandler(self, joyRightHandler): 30 | self.joyRightHandler = joyRightHandler 31 | 32 | def startLoop(self): 33 | FORMAT = 'llHHI' 34 | EVENT_SIZE = struct.calcsize(FORMAT) 35 | with open(self.eventFile, 'rb') as infile: 36 | lx, ly, rx, ry = 0, 0, 0, 0 37 | while True: 38 | event = infile.read(EVENT_SIZE) 39 | _, _, t, c, v = struct.unpack(FORMAT, event) 40 | if t == 1 and v == 1: 41 | # button pressed: 42 | if self.buttonHandler: 43 | if not self.buttonHandler(c): 44 | return 45 | if t == 3: 46 | if c == 0 and self.joyLeftHandler: 47 | # left stick & horizontal: 48 | lx = v - 32768 49 | self.joyLeftHandler(lx, ly) 50 | elif c == 1 and self.joyLeftHandler: 51 | # left stick & vertical: 52 | ly = v - 32768 53 | self.joyLeftHandler(lx, ly) 54 | elif c == 3 and self.joyRightHandler: 55 | # right stick & horizontal: 56 | rx = v - 32768 57 | self.joyRightHandler(rx, ry) 58 | elif c == 4 and self.joyRightHandler: 59 | # right stick & vertical: 60 | ry = v - 32768 61 | self.joyRightHandler(rx, ry) 62 | -------------------------------------------------------------------------------- /samples/micropython/tank/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env pybricks-micropython 2 | 3 | import struct, threading 4 | 5 | from pybricks import ev3brick as brick 6 | from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor, InfraredSensor, UltrasonicSensor, GyroSensor) 7 | from pybricks.parameters import (Port, Stop, Direction, Button, Color, SoundFile, ImageFile, Align) 8 | from pybricks.tools import print, wait, StopWatch 9 | from pybricks.robotics import DriveBase 10 | 11 | from devices import detectJoystick 12 | from joystick import JoyStick, BUTTON_A, BUTTON_X 13 | 14 | SPEED = 100 15 | STEERING = 90 16 | 17 | STATUS_STOPPED = 0 18 | STATUS_FORWARD = 1 19 | STATUS_BACKWARD = 2 20 | STATUS_STEERING = 3 21 | 22 | COLORS = (None, Color.GREEN, Color.RED, Color.YELLOW) 23 | 24 | class Driver(): 25 | def __init__(self, leftMotor, rightMotor, diameter, axle): 26 | self.driver = DriveBase(leftMotor, rightMotor, diameter, axle) 27 | self.x = 0 28 | self.y = 0 29 | self.speed = 0 30 | self.steering = 0 31 | 32 | def drive(self, speed, steering): 33 | self.speed = speed 34 | self.steering = steering 35 | if self.speed == 0: 36 | self.driver.stop() 37 | else: 38 | self.driver.drive(self.speed, self.steering) 39 | 40 | class Robot(): 41 | def __init__(self, leftMotor, rightMotor, topMotor, diameter, axle, maxSpeed=300, maxSteering=180, port=Port.S4): 42 | self.driver = Driver(leftMotor, rightMotor, diameter, axle) 43 | self.cannon = topMotor 44 | self.ultrasonic = UltrasonicSensor(port) 45 | self.speedStep = 32767 // maxSpeed 46 | self.steeringStep = 32767 // maxSteering 47 | self.active = True 48 | 49 | def drive(self, x, y): 50 | # map y (-32768 ~ +32767) to speed (+maxSpeed ~ -maxSpeed): 51 | speed = -y // self.speedStep 52 | # map x (-32768 ~ +32767) to steering (-maxSteering ~ +maxSteering): 53 | steering = x // self.steeringStep 54 | self.driver.drive(speed, steering) 55 | 56 | def target(self, x): 57 | self.cannon.run(-x // 327) 58 | 59 | def fire(self): 60 | brick.sound.file('cannon.wav') 61 | 62 | def inactive(self): 63 | self.active = False 64 | self.drive(0, 0) 65 | brick.sound.beep() 66 | 67 | def autoStopLoop(robot): 68 | while robot.active: 69 | if robot.ultrasonic.distance() < 200: 70 | robot.drive(0, 0) 71 | wait(100) 72 | 73 | def main(): 74 | brick.sound.beep() 75 | joystickEvent = detectJoystick(['Controller']) 76 | if joystickEvent: 77 | robot = Robot(Motor(Port.D), Motor(Port.A), Motor(Port.B), 55, 200) 78 | t = threading.Thread(target=autoStopLoop, args=(robot,)) 79 | t.start() 80 | 81 | def onButtonPressed(code): 82 | if code == BUTTON_X: 83 | robot.inactive() 84 | return False 85 | if code == BUTTON_A: 86 | robot.fire() 87 | return True 88 | 89 | def onLeftJoyChanged(x, y): 90 | robot.drive(x, y) 91 | 92 | def onRightJoyChanged(x, y): 93 | robot.target(x) 94 | 95 | joystick = JoyStick(joystickEvent) 96 | joystick.setButtonHandler(onButtonPressed) 97 | joystick.setJoyLeftHandler(onLeftJoyChanged) 98 | joystick.setJoyRightHandler(onRightJoyChanged) 99 | joystick.startLoop() 100 | else: 101 | brick.sound.beep() 102 | 103 | main() 104 | -------------------------------------------------------------------------------- /samples/module/hello.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | ' a test module ' 5 | 6 | __author__ = 'Michael Liao' 7 | 8 | import sys 9 | 10 | def test(): 11 | args = sys.argv 12 | if len(args)==1: 13 | print('Hello, world!') 14 | elif len(args)==2: 15 | print('Hello, %s!' % args[1]) 16 | else: 17 | print('Too many arguments!') 18 | 19 | if __name__=='__main__': 20 | test() 21 | 22 | -------------------------------------------------------------------------------- /samples/multitask/do_folk.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | 6 | print('Process (%s) start...' % os.getpid()) 7 | # Only works on Unix/Linux/Mac: 8 | pid = os.fork() 9 | if pid == 0: 10 | print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid())) 11 | else: 12 | print('I (%s) just created a child process (%s).' % (os.getpid(), pid)) 13 | -------------------------------------------------------------------------------- /samples/multitask/do_lock.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import time, threading 5 | 6 | # 假定这是你的银行存款: 7 | balance = 0 8 | lock = threading.Lock() 9 | 10 | def change_it(n): 11 | # 先存后取,结果应该为0: 12 | global balance 13 | balance = balance + n 14 | balance = balance - n 15 | 16 | def run_thread(n): 17 | for i in range(100000): 18 | # 先要获取锁: 19 | lock.acquire() 20 | try: 21 | # 放心地改吧: 22 | change_it(n) 23 | finally: 24 | # 改完了一定要释放锁: 25 | lock.release() 26 | 27 | t1 = threading.Thread(target=run_thread, args=(5,)) 28 | t2 = threading.Thread(target=run_thread, args=(8,)) 29 | t1.start() 30 | t2.start() 31 | t1.join() 32 | t2.join() 33 | print(balance) 34 | -------------------------------------------------------------------------------- /samples/multitask/do_queue.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from multiprocessing import Process, Queue 5 | import os, time, random 6 | 7 | # 写数据进程执行的代码: 8 | def write(q): 9 | print('Process to write: %s' % os.getpid()) 10 | for value in ['A', 'B', 'C']: 11 | print('Put %s to queue...' % value) 12 | q.put(value) 13 | time.sleep(random.random()) 14 | 15 | # 读数据进程执行的代码: 16 | def read(q): 17 | print('Process to read: %s' % os.getpid()) 18 | while True: 19 | value = q.get(True) 20 | print('Get %s from queue.' % value) 21 | 22 | if __name__=='__main__': 23 | # 父进程创建Queue,并传给各个子进程: 24 | q = Queue() 25 | pw = Process(target=write, args=(q,)) 26 | pr = Process(target=read, args=(q,)) 27 | # 启动子进程pw,写入: 28 | pw.start() 29 | # 启动子进程pr,读取: 30 | pr.start() 31 | # 等待pw结束: 32 | pw.join() 33 | # pr进程里是死循环,无法等待其结束,只能强行终止: 34 | pr.terminate() 35 | -------------------------------------------------------------------------------- /samples/multitask/do_subprocess.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import subprocess 5 | 6 | print('$ nslookup www.python.org') 7 | r = subprocess.call(['nslookup', 'www.python.org']) 8 | print('Exit code:', r) 9 | 10 | print('$ nslookup') 11 | p = subprocess.Popen(['nslookup'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 12 | output, err = p.communicate(b'set q=mx\npython.org\nexit\n') 13 | print(output.decode('utf-8')) 14 | print('Exit code:', p.returncode) 15 | -------------------------------------------------------------------------------- /samples/multitask/multi_processing.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from multiprocessing import Process 5 | import os 6 | 7 | # 子进程要执行的代码 8 | def run_proc(name): 9 | print('Run child process %s (%s)...' % (name, os.getpid())) 10 | 11 | if __name__=='__main__': 12 | print('Parent process %s.' % os.getpid()) 13 | p = Process(target=run_proc, args=('test',)) 14 | print('Child process will start.') 15 | p.start() 16 | p.join() 17 | print('Child process end.') 18 | -------------------------------------------------------------------------------- /samples/multitask/multi_threading.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import time, threading 5 | 6 | # 新线程执行的代码: 7 | def loop(): 8 | print('thread %s is running...' % threading.current_thread().name) 9 | n = 0 10 | while n < 5: 11 | n = n + 1 12 | print('thread %s >>> %s' % (threading.current_thread().name, n)) 13 | time.sleep(1) 14 | print('thread %s ended.' % threading.current_thread().name) 15 | 16 | print('thread %s is running...' % threading.current_thread().name) 17 | t = threading.Thread(target=loop, name='LoopThread') 18 | t.start() 19 | t.join() 20 | print('thread %s ended.' % threading.current_thread().name) 21 | -------------------------------------------------------------------------------- /samples/multitask/pooled_processing.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from multiprocessing import Pool 5 | import os, time, random 6 | 7 | def long_time_task(name): 8 | print('Run task %s (%s)...' % (name, os.getpid())) 9 | start = time.time() 10 | time.sleep(random.random() * 3) 11 | end = time.time() 12 | print('Task %s runs %0.2f seconds.' % (name, (end - start))) 13 | 14 | if __name__=='__main__': 15 | print('Parent process %s.' % os.getpid()) 16 | p = Pool(4) 17 | for i in range(5): 18 | p.apply_async(long_time_task, args=(i,)) 19 | print('Waiting for all subprocesses done...') 20 | p.close() 21 | p.join() 22 | print('All subprocesses done.') 23 | -------------------------------------------------------------------------------- /samples/multitask/task_master.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import random, time, queue 5 | from multiprocessing.managers import BaseManager 6 | 7 | # 发送任务的队列: 8 | task_queue = queue.Queue() 9 | # 接收结果的队列: 10 | result_queue = queue.Queue() 11 | 12 | # 从BaseManager继承的QueueManager: 13 | class QueueManager(BaseManager): 14 | pass 15 | 16 | # 把两个Queue都注册到网络上, callable参数关联了Queue对象: 17 | QueueManager.register('get_task_queue', callable=lambda: task_queue) 18 | QueueManager.register('get_result_queue', callable=lambda: result_queue) 19 | # 绑定端口5000, 设置验证码'abc': 20 | manager = QueueManager(address=('', 5000), authkey=b'abc') 21 | # 启动Queue: 22 | manager.start() 23 | # 获得通过网络访问的Queue对象: 24 | task = manager.get_task_queue() 25 | result = manager.get_result_queue() 26 | # 放几个任务进去: 27 | for i in range(10): 28 | n = random.randint(0, 10000) 29 | print('Put task %d...' % n) 30 | task.put(n) 31 | # 从result队列读取结果: 32 | print('Try get results...') 33 | for i in range(10): 34 | r = result.get(timeout=10) 35 | print('Result: %s' % r) 36 | # 关闭: 37 | manager.shutdown() 38 | print('master exit.') 39 | -------------------------------------------------------------------------------- /samples/multitask/task_worker.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import time, sys 5 | from multiprocessing.managers import BaseManager 6 | 7 | # 创建类似的QueueManager: 8 | class QueueManager(BaseManager): 9 | pass 10 | 11 | # 由于这个QueueManager只从网络上获取Queue,所以注册时只提供名字: 12 | QueueManager.register('get_task_queue') 13 | QueueManager.register('get_result_queue') 14 | 15 | # 连接到服务器,也就是运行task_master.py的机器: 16 | server_addr = '127.0.0.1' 17 | print('Connect to server %s...' % server_addr) 18 | # 端口和验证码注意保持与task_master.py设置的完全一致: 19 | m = QueueManager(address=(server_addr, 5000), authkey=b'abc') 20 | # 从网络连接: 21 | m.connect() 22 | # 获取Queue的对象: 23 | task = m.get_task_queue() 24 | result = m.get_result_queue() 25 | # 从task队列取任务,并把结果写入result队列: 26 | for i in range(10): 27 | try: 28 | n = task.get(timeout=1) 29 | print('run task %d * %d...' % (n, n)) 30 | r = '%d * %d = %d' % (n, n, n*n) 31 | time.sleep(1) 32 | result.put(r) 33 | except Queue.Empty: 34 | print('task queue is empty.') 35 | # 处理结束: 36 | print('worker exit.') 37 | -------------------------------------------------------------------------------- /samples/multitask/use_threadlocal.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import threading 5 | 6 | # 创建全局ThreadLocal对象: 7 | local_school = threading.local() 8 | 9 | def process_student(): 10 | # 获取当前线程关联的student: 11 | std = local_school.student 12 | print('Hello, %s (in %s)' % (std, threading.current_thread().name)) 13 | 14 | def process_thread(name): 15 | # 绑定ThreadLocal的student: 16 | local_school.student = name 17 | process_student() 18 | 19 | t1 = threading.Thread(target= process_thread, args=('Alice',), name='Thread-A') 20 | t2 = threading.Thread(target= process_thread, args=('Bob',), name='Thread-B') 21 | t1.start() 22 | t2.start() 23 | t1.join() 24 | t2.join() 25 | -------------------------------------------------------------------------------- /samples/oop_advance/create_class_on_the_fly.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | def fn(self, name='world'): # 先定义函数 5 | print('Hello, %s.' % name) 6 | 7 | Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class 8 | 9 | h = Hello() 10 | print('call h.hello():') 11 | h.hello() 12 | print('type(Hello) =', type(Hello)) 13 | print('type(h) =', type(h)) 14 | -------------------------------------------------------------------------------- /samples/oop_advance/orm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | ' Simple ORM using metaclass ' 5 | 6 | class Field(object): 7 | 8 | def __init__(self, name, column_type): 9 | self.name = name 10 | self.column_type = column_type 11 | 12 | def __str__(self): 13 | return '<%s:%s>' % (self.__class__.__name__, self.name) 14 | 15 | class StringField(Field): 16 | 17 | def __init__(self, name): 18 | super(StringField, self).__init__(name, 'varchar(100)') 19 | 20 | class IntegerField(Field): 21 | 22 | def __init__(self, name): 23 | super(IntegerField, self).__init__(name, 'bigint') 24 | 25 | class ModelMetaclass(type): 26 | 27 | def __new__(cls, name, bases, attrs): 28 | if name=='Model': 29 | return type.__new__(cls, name, bases, attrs) 30 | print('Found model: %s' % name) 31 | mappings = dict() 32 | for k, v in attrs.items(): 33 | if isinstance(v, Field): 34 | print('Found mapping: %s ==> %s' % (k, v)) 35 | mappings[k] = v 36 | for k in mappings.keys(): 37 | attrs.pop(k) 38 | attrs['__mappings__'] = mappings # 保存属性和列的映射关系 39 | attrs['__table__'] = name # 假设表名和类名一致 40 | return type.__new__(cls, name, bases, attrs) 41 | 42 | class Model(dict, metaclass=ModelMetaclass): 43 | 44 | def __init__(self, **kw): 45 | super(Model, self).__init__(**kw) 46 | 47 | def __getattr__(self, key): 48 | try: 49 | return self[key] 50 | except KeyError: 51 | raise AttributeError(r"'Model' object has no attribute '%s'" % key) 52 | 53 | def __setattr__(self, key, value): 54 | self[key] = value 55 | 56 | def save(self): 57 | fields = [] 58 | params = [] 59 | args = [] 60 | for k, v in self.__mappings__.items(): 61 | fields.append(v.name) 62 | params.append('?') 63 | args.append(getattr(self, k, None)) 64 | sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params)) 65 | print('SQL: %s' % sql) 66 | print('ARGS: %s' % str(args)) 67 | 68 | # testing code: 69 | 70 | class User(Model): 71 | id = IntegerField('id') 72 | name = StringField('username') 73 | email = StringField('email') 74 | password = StringField('password') 75 | 76 | u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd') 77 | u.save() 78 | -------------------------------------------------------------------------------- /samples/oop_advance/special_call.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | class Student(object): 5 | def __init__(self, name): 6 | self.name = name 7 | 8 | def __call__(self): 9 | print('My name is %s.' % self.name) 10 | 11 | s = Student('Michael') 12 | s() 13 | -------------------------------------------------------------------------------- /samples/oop_advance/special_getattr.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | class Student(object): 5 | 6 | def __init__(self): 7 | self.name = 'Michael' 8 | 9 | def __getattr__(self, attr): 10 | if attr=='score': 11 | return 99 12 | if attr=='age': 13 | return lambda: 25 14 | raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr) 15 | 16 | s = Student() 17 | print(s.name) 18 | print(s.score) 19 | print(s.age()) 20 | # AttributeError: 'Student' object has no attribute 'grade' 21 | print(s.grade) 22 | -------------------------------------------------------------------------------- /samples/oop_advance/special_getitem.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | class Fib(object): 5 | 6 | def __getitem__(self, n): 7 | if isinstance(n, int): 8 | a, b = 1, 1 9 | for x in range(n): 10 | a, b = b, a + b 11 | return a 12 | if isinstance(n, slice): 13 | start = n.start 14 | stop = n.stop 15 | if start is None: 16 | start = 0 17 | a, b = 1, 1 18 | L = [] 19 | for x in range(stop): 20 | if x >= start: 21 | L.append(a) 22 | a, b = b, a + b 23 | return L 24 | 25 | f = Fib() 26 | print(f[0]) 27 | print(f[5]) 28 | print(f[100]) 29 | print(f[0:5]) 30 | print(f[:10]) 31 | -------------------------------------------------------------------------------- /samples/oop_advance/special_iter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | class Fib(object): 5 | 6 | def __init__(self): 7 | self.a, self.b = 0, 1 # 初始化两个计数器a,b 8 | 9 | def __iter__(self): 10 | return self # 实例本身就是迭代对象,故返回自己 11 | 12 | def __next__(self): 13 | self.a, self.b = self.b, self.a + self.b # 计算下一个值 14 | if self.a > 100000: # 退出循环的条件 15 | raise StopIteration(); 16 | return self.a # 返回下一个值 17 | 18 | for n in Fib(): 19 | print(n) 20 | -------------------------------------------------------------------------------- /samples/oop_advance/special_str.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | class Student(object): 5 | 6 | def __init__(self, name): 7 | self.name = name 8 | 9 | def __str__(self): 10 | return 'Student object (name: %s)' % self.name 11 | 12 | __repr__ = __str__ 13 | 14 | print(Student('Michael')) 15 | -------------------------------------------------------------------------------- /samples/oop_advance/use_enum.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from enum import Enum, unique 5 | 6 | @unique 7 | class Weekday(Enum): 8 | Sun = 0 9 | Mon = 1 10 | Tue = 2 11 | Wed = 3 12 | Thu = 4 13 | Fri = 5 14 | Sat = 6 15 | 16 | day1 = Weekday.Mon 17 | 18 | print('day1 =', day1) 19 | print('Weekday.Tue =', Weekday.Tue) 20 | print('Weekday[\'Tue\'] =', Weekday['Tue']) 21 | print('Weekday.Tue.value =', Weekday.Tue.value) 22 | print('day1 == Weekday.Mon ?', day1 == Weekday.Mon) 23 | print('day1 == Weekday.Tue ?', day1 == Weekday.Tue) 24 | print('day1 == Weekday(1) ?', day1 == Weekday(1)) 25 | 26 | for name, member in Weekday.__members__.items(): 27 | print(name, '=>', member) 28 | 29 | Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')) 30 | 31 | for name, member in Month.__members__.items(): 32 | print(name, '=>', member, ',', member.value) 33 | -------------------------------------------------------------------------------- /samples/oop_advance/use_metaclass.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | # metaclass是创建类,所以必须从`type`类型派生: 5 | class ListMetaclass(type): 6 | def __new__(cls, name, bases, attrs): 7 | attrs['add'] = lambda self, value: self.append(value) 8 | return type.__new__(cls, name, bases, attrs) 9 | 10 | # 指示使用ListMetaclass来定制类 11 | class MyList(list, metaclass=ListMetaclass): 12 | pass 13 | 14 | L = MyList() 15 | L.add(1) 16 | L.add(2) 17 | L.add(3) 18 | L.add('END') 19 | print(L) 20 | -------------------------------------------------------------------------------- /samples/oop_advance/use_property.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | class Student(object): 5 | 6 | @property 7 | def score(self): 8 | return self._score 9 | 10 | @score.setter 11 | def score(self, value): 12 | if not isinstance(value, int): 13 | raise ValueError('score must be an integer!') 14 | if value < 0 or value > 100: 15 | raise ValueError('score must between 0 ~ 100!') 16 | self._score = value 17 | 18 | s = Student() 19 | s.score = 60 20 | print('s.score =', s.score) 21 | # ValueError: score must between 0 ~ 100! 22 | s.score = 9999 23 | -------------------------------------------------------------------------------- /samples/oop_advance/use_slots.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | class Student(object): 5 | __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称 6 | 7 | class GraduateStudent(Student): 8 | pass 9 | 10 | s = Student() # 创建新的实例 11 | s.name = 'Michael' # 绑定属性'name' 12 | s.age = 25 # 绑定属性'age' 13 | # ERROR: AttributeError: 'Student' object has no attribute 'score' 14 | try: 15 | s.score = 99 16 | except AttributeError as e: 17 | print('AttributeError:', e) 18 | 19 | g = GraduateStudent() 20 | g.score = 99 21 | print('g.score =', g.score) 22 | -------------------------------------------------------------------------------- /samples/oop_basic/animals.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | class Animal(object): 5 | def run(self): 6 | print('Animal is running...') 7 | 8 | class Dog(Animal): 9 | def run(self): 10 | print('Dog is running...') 11 | 12 | class Cat(Animal): 13 | def run(self): 14 | print('Cat is running...') 15 | 16 | def run_twice(animal): 17 | animal.run() 18 | animal.run() 19 | 20 | a = Animal() 21 | d = Dog() 22 | c = Cat() 23 | 24 | print('a is Animal?', isinstance(a, Animal)) 25 | print('a is Dog?', isinstance(a, Dog)) 26 | print('a is Cat?', isinstance(a, Cat)) 27 | 28 | print('d is Animal?', isinstance(d, Animal)) 29 | print('d is Dog?', isinstance(d, Dog)) 30 | print('d is Cat?', isinstance(d, Cat)) 31 | 32 | run_twice(c) 33 | -------------------------------------------------------------------------------- /samples/oop_basic/attrs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | class MyObject(object): 5 | 6 | def __init__(self): 7 | self.x = 9 8 | 9 | def power(self): 10 | return self.x * self.x 11 | 12 | obj = MyObject() 13 | 14 | print('hasattr(obj, \'x\') =', hasattr(obj, 'x')) # 有属性'x'吗? 15 | print('hasattr(obj, \'y\') =', hasattr(obj, 'y')) # 有属性'y'吗? 16 | setattr(obj, 'y', 19) # 设置一个属性'y' 17 | print('hasattr(obj, \'y\') =', hasattr(obj, 'y')) # 有属性'y'吗? 18 | print('getattr(obj, \'y\') =', getattr(obj, 'y')) # 获取属性'y' 19 | print('obj.y =', obj.y) # 获取属性'y' 20 | 21 | print('getattr(obj, \'z\') =',getattr(obj, 'z', 404)) # 获取属性'z',如果不存在,返回默认值404 22 | 23 | f = getattr(obj, 'power') # 获取属性'power' 24 | print(f) 25 | print(f()) 26 | -------------------------------------------------------------------------------- /samples/oop_basic/get_instance.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | class Animal(object): 5 | pass 6 | 7 | class Dog(Animal): 8 | pass 9 | 10 | class Husky(Dog): 11 | pass 12 | 13 | a = Animal() 14 | d = Dog() 15 | h = Husky() 16 | 17 | print('check a = Animal()...') 18 | print('isinstance(a, Animal) =', isinstance(a, Animal)) 19 | print('isinstance(a, Dog) =', isinstance(a, Dog)) 20 | print('isinstance(a, Husky) =', isinstance(a, Husky)) 21 | 22 | print('check d = Dog()...') 23 | print('isinstance(d, Animal) =', isinstance(d, Animal)) 24 | print('isinstance(d, Dog) =', isinstance(d, Dog)) 25 | print('isinstance(d, Husky) =', isinstance(d, Husky)) 26 | 27 | print('check h = Husky()...') 28 | print('isinstance(h, Animal) =', isinstance(h, Animal)) 29 | print('isinstance(h, Dog) =', isinstance(h, Dog)) 30 | print('isinstance(h, Husky) =', isinstance(h, Husky)) 31 | -------------------------------------------------------------------------------- /samples/oop_basic/get_type.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | # type() 5 | 6 | print('type(123) =', type(123)) 7 | print('type(\'123\') =', type('123')) 8 | print('type(None) =', type(None)) 9 | print('type(abs) =', type(abs)) 10 | 11 | import types 12 | 13 | print('type(\'abc\')==str?', type('abc')==str) 14 | 15 | -------------------------------------------------------------------------------- /samples/oop_basic/protected_student.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | class Student(object): 5 | 6 | def __init__(self, name, score): 7 | self.__name = name 8 | self.__score = score 9 | 10 | def get_name(self): 11 | return self.__name 12 | 13 | def get_score(self): 14 | return self.__score 15 | 16 | def set_score(self, score): 17 | if 0 <= score <= 100: 18 | self.__score = score 19 | else: 20 | raise ValueError('bad score') 21 | 22 | def get_grade(self): 23 | if self.__score >= 90: 24 | return 'A' 25 | elif self.__score >= 60: 26 | return 'B' 27 | else: 28 | return 'C' 29 | 30 | bart = Student('Bart Simpson', 59) 31 | print('bart.get_name() =', bart.get_name()) 32 | bart.set_score(60) 33 | print('bart.get_score() =', bart.get_score()) 34 | 35 | print('DO NOT use bart._Student__name:', bart._Student__name) 36 | -------------------------------------------------------------------------------- /samples/oop_basic/student.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | class Student(object): 5 | 6 | def __init__(self, name, score): 7 | self.name = name 8 | self.score = score 9 | 10 | def print_score(self): 11 | print('%s: %s' % (self.name, self.score)) 12 | 13 | def get_grade(self): 14 | if self.score >= 90: 15 | return 'A' 16 | elif self.score >= 60: 17 | return 'B' 18 | else: 19 | return 'C' 20 | 21 | bart = Student('Bart Simpson', 59) 22 | lisa = Student('Lisa Simpson', 87) 23 | 24 | print('bart.name =', bart.name) 25 | print('bart.score =', bart.score) 26 | bart.print_score() 27 | 28 | print('grade of Bart:', bart.get_grade()) 29 | print('grade of Lisa:', lisa.get_grade()) 30 | -------------------------------------------------------------------------------- /samples/packages/pil/README: -------------------------------------------------------------------------------- 1 | Install PIL 2 | =========== 3 | 4 | ### Windows 5 | 6 | Open web page: https://pypi.python.org/pypi/Pillow/2.8.1 7 | 8 | Find link of "Pillow-2.8.1.win-amd64-py3.4.exe" and download it: 9 | 10 | https://pypi.python.org/packages/3.4/P/Pillow/Pillow-2.8.1.win-amd64-py3.4.exe 11 | 12 | ### Mac OS X 13 | 14 | Step 1: Install dependencies by brew: 15 | 16 | $ brew install libtiff libjpeg webp little-cms2 17 | 18 | Step 2: Install Pillow by pip: 19 | 20 | $ sudo pip3 install Pillow 21 | 22 | ### Linux 23 | 24 | For Debian/Ubuntu: 25 | 26 | $ sudo apt-get install python3-pil 27 | -------------------------------------------------------------------------------- /samples/packages/pil/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelliao/learn-python3/27f49401960be8233d2c52b9e214ac9da7be22d3/samples/packages/pil/test.jpg -------------------------------------------------------------------------------- /samples/packages/pil/use_pil_blur.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from PIL import Image, ImageFilter 5 | 6 | # 打开一个jpg图像文件,注意是当前路径: 7 | im = Image.open('test.jpg') 8 | # 应用模糊滤镜: 9 | im2 = im.filter(ImageFilter.BLUR) 10 | im2.save('blur.jpg', 'jpeg') 11 | -------------------------------------------------------------------------------- /samples/packages/pil/use_pil_draw.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from PIL import Image, ImageDraw, ImageFont, ImageFilter 5 | 6 | import random 7 | 8 | # 随机字母: 9 | def rndChar(): 10 | return chr(random.randint(65, 90)) 11 | 12 | # 随机颜色1: 13 | def rndColor(): 14 | return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255)) 15 | 16 | # 随机颜色2: 17 | def rndColor2(): 18 | return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127)) 19 | 20 | # 240 x 60: 21 | width = 60 * 4 22 | height = 60 23 | image = Image.new('RGB', (width, height), (255, 255, 255)) 24 | # 创建Font对象: 25 | font = ImageFont.truetype('Arial.ttf', 36) 26 | # 创建Draw对象: 27 | draw = ImageDraw.Draw(image) 28 | # 填充每个像素: 29 | for x in range(width): 30 | for y in range(height): 31 | draw.point((x, y), fill=rndColor()) 32 | # 输出文字: 33 | for t in range(4): 34 | draw.text((60 * t + 10, 10), rndChar(), font=font, fill=rndColor2()) 35 | # 模糊: 36 | image = image.filter(ImageFilter.BLUR) 37 | image.save('code.jpg', 'jpeg') 38 | -------------------------------------------------------------------------------- /samples/packages/pil/use_pil_resize.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from PIL import Image 5 | 6 | # 打开一个jpg图像文件,注意是当前路径: 7 | im = Image.open('test.jpg') 8 | # 获得图像尺寸: 9 | w, h = im.size 10 | print('Original image size: %sx%s' % (w, h)) 11 | # 缩放到50%: 12 | im.thumbnail((w//2, h//2)) 13 | print('Resize image to: %sx%s' % (w//2, h//2)) 14 | # 把缩放后的图像用jpeg格式保存: 15 | im.save('thumbnail.jpg', 'jpeg') 16 | -------------------------------------------------------------------------------- /samples/regex/regex.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import re 5 | 6 | print('Test: 010-12345') 7 | m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345') 8 | print(m.group(1), m.group(2)) 9 | 10 | t = '19:05:30' 11 | print('Test:', t) 12 | m = re.match(r'^(0[0-9]|1[0-9]|2[0-3]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])$', t) 13 | print(m.groups()) 14 | -------------------------------------------------------------------------------- /samples/socket/do_tcp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import socket 5 | 6 | # 创建一个socket: 7 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 8 | 9 | # 建立连接: 10 | s.connect(('www.sina.com.cn', 80)) 11 | 12 | # 发送数据: 13 | s.send(b'GET / HTTP/1.1\r\nHost: www.sina.com.cn\r\nConnection: close\r\n\r\n') 14 | 15 | # 接收数据: 16 | buffer = [] 17 | while True: 18 | # 每次最多接收1k字节: 19 | d = s.recv(1024) 20 | if d: 21 | buffer.append(d) 22 | else: 23 | break 24 | 25 | data = b''.join(buffer) 26 | 27 | # 关闭连接: 28 | s.close() 29 | 30 | header, html = data.split(b'\r\n\r\n', 1) 31 | print(header.decode('utf-8')) 32 | 33 | # 把接收的数据写入文件: 34 | with open('sina.html', 'wb') as f: 35 | f.write(html) 36 | -------------------------------------------------------------------------------- /samples/socket/udp_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import socket 5 | 6 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 7 | 8 | for data in [b'Michael', b'Tracy', b'Sarah']: 9 | # 发送数据: 10 | s.sendto(data, ('127.0.0.1', 9999)) 11 | # 接收数据: 12 | print(s.recv(1024).decode('utf-8')) 13 | 14 | s.close() 15 | -------------------------------------------------------------------------------- /samples/socket/udp_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import socket 5 | 6 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 7 | 8 | # 绑定端口: 9 | s.bind(('127.0.0.1', 9999)) 10 | 11 | print('Bind UDP on 9999...') 12 | 13 | while True: 14 | # 接收数据: 15 | data, addr = s.recvfrom(1024) 16 | print('Received from %s:%s.' % addr) 17 | reply = 'Hello, %s!' % data.decode('utf-8') 18 | s.sendto(reply.encode('utf-8'), addr) 19 | -------------------------------------------------------------------------------- /samples/test/dict_doctest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | class Dict(dict): 5 | ''' 6 | Simple dict but also support access as x.y style. 7 | 8 | >>> d1 = Dict() 9 | >>> d1['x'] = 100 10 | >>> d1.x 11 | 100 12 | >>> d1.y = 200 13 | >>> d1['y'] 14 | 200 15 | >>> d2 = Dict(a=1, b=2, c='3') 16 | >>> d2.c 17 | '3' 18 | >>> d2['empty'] 19 | Traceback (most recent call last): 20 | ... 21 | KeyError: 'empty' 22 | >>> d2.empty 23 | Traceback (most recent call last): 24 | ... 25 | AttributeError: 'Dict' object has no attribute 'empty' 26 | ''' 27 | def __init__(self, **kw): 28 | super(Dict, self).__init__(**kw) 29 | 30 | def __getattr__(self, key): 31 | try: 32 | return self[key] 33 | except KeyError: 34 | raise AttributeError(r"'Dict' object has no attribute '%s'" % key) 35 | 36 | def __setattr__(self, key, value): 37 | self[key] = value 38 | 39 | if __name__=='__main__': 40 | import doctest 41 | doctest.testmod() 42 | -------------------------------------------------------------------------------- /samples/test/dict_unittest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import unittest 5 | 6 | class Dict(dict): 7 | 8 | def __init__(self, **kw): 9 | super(Dict, self).__init__(**kw) 10 | 11 | def __getattr__(self, key): 12 | try: 13 | return self[key] 14 | except KeyError: 15 | raise AttributeError(r"'Dict' object has no attribute '%s'" % key) 16 | 17 | def __setattr__(self, key, value): 18 | self[key] = value 19 | 20 | class TestDict(unittest.TestCase): 21 | 22 | def setUp(self): 23 | print('setUp...') 24 | 25 | def tearDown(self): 26 | print('tearDown...') 27 | 28 | def test_init(self): 29 | d = Dict(a=1, b='test') 30 | self.assertEqual(d.a, 1) 31 | self.assertEqual(d.b, 'test') 32 | self.assertTrue(isinstance(d, dict)) 33 | 34 | def test_key(self): 35 | d = Dict() 36 | d['key'] = 'value' 37 | self.assertEqual(d.key, 'value') 38 | 39 | def test_attr(self): 40 | d = Dict() 41 | d.key = 'value' 42 | self.assertTrue('key' in d) 43 | self.assertEqual(d['key'], 'value') 44 | 45 | def test_keyerror(self): 46 | d = Dict() 47 | with self.assertRaises(KeyError): 48 | value = d['empty'] 49 | 50 | def test_attrerror(self): 51 | d = Dict() 52 | with self.assertRaises(AttributeError): 53 | value = d.empty 54 | 55 | if __name__ == '__main__': 56 | unittest.main() 57 | -------------------------------------------------------------------------------- /samples/web/do_flask.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from flask import Flask 5 | from flask import request 6 | 7 | app = Flask(__name__) 8 | 9 | @app.route('/', methods=['GET', 'POST']) 10 | def home(): 11 | return '

Home

' 12 | 13 | @app.route('/signin', methods=['GET']) 14 | def signin_form(): 15 | return '''
16 |

17 |

18 |

19 |
''' 20 | 21 | @app.route('/signin', methods=['POST']) 22 | def signin(): 23 | # 需要从request对象读取表单内容: 24 | if request.form['username']=='admin' and request.form['password']=='password': 25 | return '

Hello, admin!

' 26 | return '

Bad username or password.

' 27 | 28 | if __name__ == '__main__': 29 | app.run() 30 | -------------------------------------------------------------------------------- /samples/web/do_wsgi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from wsgiref.simple_server import make_server 5 | 6 | from hello import application 7 | 8 | httpd = make_server('', 8000, application) 9 | print('Serving HTTP on port 8000...') 10 | 11 | httpd.serve_forever() 12 | -------------------------------------------------------------------------------- /samples/web/hello.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | def application(environ, start_response): 5 | start_response('200 OK', [('Content-Type', 'text/html')]) 6 | body = '

Hello, %s!

' % (environ['PATH_INFO'][1:] or 'web') 7 | return [body.encode('utf-8')] 8 | -------------------------------------------------------------------------------- /samples/web/mvc/app.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from flask import Flask, request, render_template 5 | 6 | app = Flask(__name__) 7 | 8 | @app.route('/', methods=['GET', 'POST']) 9 | def home(): 10 | return render_template('home.html') 11 | 12 | @app.route('/signin', methods=['GET']) 13 | def signin_form(): 14 | return render_template('form.html') 15 | 16 | @app.route('/signin', methods=['POST']) 17 | def signin(): 18 | username = request.form['username'] 19 | password = request.form['password'] 20 | if username=='admin' and password=='password': 21 | return render_template('signin-ok.html', username=username) 22 | return render_template('form.html', message='Bad username or password', username=username) 23 | 24 | if __name__ == '__main__': 25 | app.run() 26 | -------------------------------------------------------------------------------- /samples/web/mvc/templates/form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Please Sign In 4 | 5 | 6 | {% if message %} 7 |

{{ message }}

8 | {% endif %} 9 |
10 | Please sign in: 11 |

12 |

13 |

14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /samples/web/mvc/templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Home 4 | 5 | 6 |

Home

7 | 8 | 9 | -------------------------------------------------------------------------------- /samples/web/mvc/templates/signin-ok.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Welcome, {{ username }} 4 | 5 | 6 |

Welcome, {{ username }}!

7 | 8 | 9 | --------------------------------------------------------------------------------