├── .gitignore ├── LICENSE ├── README.md ├── ch01 └── hello.py ├── ch02 ├── ch02_arg_mutate.py ├── ch02_encoding.py ├── ch02_for_break.py ├── ch02_for_break_nested.py ├── ch02_for_multiple.py ├── ch02_for_nested.py ├── ch02_for_score.py ├── ch02_if.py ├── ch02_my_len.py ├── ch02_my_sum.py ├── ch02_return_total_avg.py ├── ch02_score_high.py ├── ch02_score_plus.py ├── ch02_while_score.py ├── myhello.py └── mymath.py ├── ch02ex ├── ch02ex2.10_answer.py ├── ch02ex2.1_answer.py ├── ch02ex2.1_more_answer.py ├── ch02ex2.2_answer.py ├── ch02ex2.3_answer.py ├── ch02ex2.4_answer.py ├── ch02ex2.5_answer.py ├── ch02ex2.6_answer.py ├── ch02ex2.7_answer.py ├── ch02ex2.8_answer.py └── ch02ex2.9_answer.py ├── ch03 ├── ch03_geom.py ├── ch03_getbits.py └── ch03_my_sqrt.py ├── ch03ex ├── ch03ex3.10_answer.py ├── ch03ex3.11_answer.py ├── ch03ex3.12_answer.py ├── ch03ex3.1_answer.py ├── ch03ex3.2_answer.py ├── ch03ex3.3_answer.py ├── ch03ex3.4_answer.py ├── ch03ex3.5_answer.py ├── ch03ex3.6_answer.py ├── ch03ex3.7_answer.py ├── ch03ex3.8_answer.py └── ch03ex3.9_answer.py ├── ch04 ├── ch04_99m_format.py ├── ch04_9x9m.py ├── ch04_anagram.py ├── ch04_base36encode.py ├── ch04_comb.py ├── ch04_cumulative_sum.py ├── ch04_duplicate.py ├── ch04_flatten.py ├── ch04_ft_to_ct.py ├── ch04_group.py ├── ch04_hamming.py ├── ch04_my_factorial.py ├── ch04_my_sum.py ├── ch04_product.py ├── ch04_unique.py └── ch04_while_iteration.py ├── ch04ex ├── ch04ex4.18_answer.py ├── ch04ex4.1_answer.py ├── ch04ex4.2_answer.py ├── ch04ex4.3_answer.py ├── ch04ex4.4_answer.py ├── ch04ex4.5_answer.py ├── ch04ex4.6_answer.py └── ch04ex4.7_answer.py ├── ch05 ├── ch05_dict_invert.py ├── ch05_dict_sort.py ├── ch05_powerset.py ├── ch05_prime_sieve.py ├── ch05_symbol_table.py ├── ch05ex5.5.py ├── ch05ex5.6.py └── ch05ex5.7.py ├── ch05ex ├── ch05ex5.1_answer.py ├── ch05ex5.2_answer.py ├── ch05ex5.3_answer.py ├── ch05ex5.5_answer.py ├── ch05ex5.6_answer.py └── ch05ex5.8_answer.py ├── ch06 ├── ch06_8queen_basic.py ├── ch06_8queen_hettingers.py ├── ch06_8queen_hettingers_gf.py ├── ch06_8queen_howell.py ├── ch06_8queen_test.py ├── ch06_counter.py ├── ch06_env.py ├── ch06_fact.py ├── ch06_fib.py ├── ch06_fib_gf.py ├── ch06_fib_hf.py ├── ch06_frange.py ├── ch06_gcd.py ├── ch06_generator_send.py ├── ch06_hanoi.py ├── ch06_hf_sum.py ├── ch06_int_from.py ├── ch06_lambda_long.py ├── ch06_lambda_sorted.py ├── ch06_multipliers.py ├── ch06_mutable_default.py ├── ch06_perm.py ├── ch06_pi_cesaro.py ├── ch06_powerset.py ├── ch06_range.py └── ch06_yield_from.py ├── ch06ex ├── ch06ex6.12_answer.py └── ch06ex6.15_answer.py ├── ch07 ├── big5ext.py ├── big5uao.py ├── big5uao_3.py ├── ch07_big5_uao.py ├── ch07_big5_uao_test.py ├── ch07_caesar.py ├── ch07_csv.py ├── ch07_enc_change.py ├── ch07_json.py ├── ch07_line_count.py ├── ch07_line_count_test │ ├── a no.py │ ├── aaa big5.py │ ├── aaa utf16be.py │ ├── empty.py │ ├── test ascii.py │ └── wrong utf8.py ├── ch07_line_number.py ├── ch07_pickle.py ├── ch07_print_self.py ├── ch07_print_self_big5.py ├── ch07_print_self_utf8.py ├── ch07_redirect.py ├── ch07_redirect_stdin.py ├── ch07_struct.c ├── ch07_struct.py ├── ch07_test.c ├── ch07_test.py ├── ch07_test_context.py ├── ch07ex7.1_answer.txt ├── ch07ex7.1_testdata_0.txt ├── ch07ex7.1_testdata_1.txt ├── ch07ex7.1_testdata_2.txt ├── ch07ex7.2_answer.txt ├── ch07ex7.2_testdata_0.txt ├── ch07ex7.2_testdata_1.txt ├── ch07ex7.2_testdata_2.txt ├── ch07ex7.3_testdata.txt ├── ch07ex7.4.py ├── ch07ex7.5_testdata.txt ├── csv.txt ├── csv_out.txt ├── i_have_a_dream.txt ├── json.txt ├── json_out1.txt ├── json_out2.txt ├── pickle.bin ├── stdin_test.txt ├── test.bin ├── test.txt ├── test_big5.txt └── test_utf8.txt ├── ch08 ├── ch08_counter.py ├── ch08_namedtuple_csv.py ├── ch08ex8.5_testdata.bin ├── ch08ex8.6_testdata.ini ├── ch08ex8.6_testdata2.ini ├── ch08ex8.7_testdata.plist ├── ch08ex8.7_testdata2.plist ├── csv.txt ├── csv_out.txt └── i_have_a_dream.txt ├── ch09 ├── ch09_coin_sum.py ├── ch09_ctof_side_effetcs.py ├── ch09_dec_memo.py ├── ch09_dec_memo_limit.py ├── ch09_dec_natural.py ├── ch09_dec_notfunc.py ├── ch09_dec_time.py ├── ch09_dec_wraps.py ├── ch09_fact_i_r.py ├── ch09_fact_tail.py ├── ch09_fact_tco.py ├── ch09_forest.py ├── ch09_i_to_r.py ├── ch09_map.py ├── ch09_odd_even.py ├── ch09_odd_fibs.py ├── ch09_sum_is_prime.py ├── ch09_sum_of_primes.py ├── ch09_sum_sq_even.py ├── ch09_tph.py ├── ch09_tree.py ├── ch09ex9.10_flatten_list.py ├── ch09ex9.7_hamming.py └── ch09ex9.xzy_accept.py ├── ch10 ├── ch10_ns_package.py ├── ch10_package_example.py ├── ch10_reload.py ├── ch10_reload_2.py ├── ch10_reload_module.py ├── myhello.py ├── myhello2.py ├── mymath.py ├── mymath2.py ├── mymath3.py ├── package_example │ ├── __init__.py │ ├── formats │ │ ├── __init__.py │ │ ├── bar.py │ │ ├── bmp.py │ │ ├── foo.py │ │ ├── jpg.py │ │ └── png.py │ ├── gui │ │ ├── __init__.py │ │ ├── canvas.py │ │ └── menu.py │ ├── info.py │ └── tools │ │ ├── __init__.py │ │ ├── bar.py │ │ ├── foo.py │ │ ├── rotate.py │ │ └── xyz │ │ └── __init__.py ├── path1 │ └── mymodule │ │ └── sub1.py └── path2 │ └── mymodule │ └── sub2.py ├── ch11 ├── ch11_abc.py ├── ch11_bankaccount.py ├── ch11_class_generator.py ├── ch11_foo.py ├── ch11_frange.py ├── ch11_inherit.py ├── ch11_mi.py ├── ch11_mi2.py ├── ch11_myclass.py ├── ch11_myclass_scope.py ├── ch11_orderedset.py ├── ch11_private.py ├── ch11_property.py ├── ch11_static_class_method.py ├── ch11_test.py ├── ch11_test2.py ├── ch11_test3.py ├── ch11_test4.py ├── ch11_test5.py └── ch11_test6.py ├── ch12 ├── ch12_2.x_old_syntax.py ├── ch12_as_e.py ├── ch12_assert.py ├── ch12_fact.py ├── ch12_fact_2.py ├── ch12_fact_exception.py ├── ch12_fact_exception_2.py ├── ch12_flow.py ├── ch12_foo_exception.py ├── ch12_list_bound.py ├── ch12_no_with.py └── test.txt ├── ch13 ├── ch13_argparse.py ├── ch13_argv.py ├── ch13_argv_basic.py ├── ch13_dining_ph.py ├── ch13_ticket.py └── ch13_tkinter.py ├── cover.jpg └── misc ├── c_rw.py ├── c_ticket.py ├── ch04_base26_aa_zz.py ├── ch04_base26_aa_zz_no_padding.py ├── ch05_stu_d.py ├── ch05_stu_data.py ├── scope_comprehension.py └── u_to_enc.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # PyInstaller 26 | # Usually these files are written by a python script from a template 27 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 28 | *.manifest 29 | *.spec 30 | 31 | # Installer logs 32 | pip-log.txt 33 | pip-delete-this-directory.txt 34 | 35 | # Unit test / coverage reports 36 | htmlcov/ 37 | .tox/ 38 | .coverage 39 | .cache 40 | nosetests.xml 41 | coverage.xml 42 | 43 | # Translations 44 | *.mo 45 | *.pot 46 | 47 | # Django stuff: 48 | *.log 49 | 50 | # Sphinx documentation 51 | docs/_build/ 52 | 53 | # PyBuilder 54 | target/ 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. 340 | 341 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 《Python程式設計入門》一書的相關程式檔案。
2 | 「ch02」資料夾,含有第2章的範例程式原始碼,以及練習題所需檔案。
3 | 「ch02ex」資料夾,含有第2章練習題的參考答案。
4 | 出版社:博碩
5 | 書號:PG21421
6 | 勘誤表與其他資訊:http://yehnan.blogspot.tw/2015/03/python_30.html
7 | 8 | ![書籍封面](cover.jpg) 9 | 10 | -------------------------------------------------------------------------------- /ch01/hello.py: -------------------------------------------------------------------------------- 1 | print('Hello Python') 2 | -------------------------------------------------------------------------------- /ch02/ch02_arg_mutate.py: -------------------------------------------------------------------------------- 1 | 2 | def my_len(seq): 3 | n = 0 4 | for x in seq: 5 | n += 1 6 | return n 7 | 8 | data = [-30.2, -22.5, 15.8, 23.7, 35.2] 9 | print(data) 10 | def ctof(temp): 11 | n = my_len(temp) 12 | i = 0 13 | while i < n: 14 | temp[i] = temp[i] * 9.0 / 5.0 + 32 15 | i += 1 16 | 17 | ctof(data) 18 | print(data) 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /ch02/ch02_encoding.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch02/ch02_encoding.py -------------------------------------------------------------------------------- /ch02/ch02_for_break.py: -------------------------------------------------------------------------------- 1 | 2 | scores = (98, 78, 64, 55, 61, 82) 3 | lowerThan60 = False 4 | for x in scores: 5 | if x < 60: 6 | lowerThan60 = True 7 | break 8 | 9 | print(lowerThan60) 10 | -------------------------------------------------------------------------------- /ch02/ch02_for_break_nested.py: -------------------------------------------------------------------------------- 1 | 2 | data = [[33, 44, 55], [18381, 99781], [60, 70, 42, 91], [32, 51]] 3 | total = 0 4 | for x in data: 5 | for y in x: 6 | if 0 <= y <= 100: 7 | total += y 8 | else: 9 | break 10 | 11 | print(total) 12 | -------------------------------------------------------------------------------- /ch02/ch02_for_multiple.py: -------------------------------------------------------------------------------- 1 | 2 | names_scores = (('Amy', 82, 90), ('John', 33, 64), ('Zoe', 91, 94)) 3 | highs = [] 4 | for x, y, z in names_scores: 5 | if y >= 90 and z >= 90: 6 | highs += [x, y, z] 7 | 8 | print(highs) 9 | -------------------------------------------------------------------------------- /ch02/ch02_for_nested.py: -------------------------------------------------------------------------------- 1 | 2 | colors = ['red', 'green', 'blue'] 3 | animals = ['cat', 'dog', 'horse', 'sheep'] 4 | results = [] 5 | for x in colors: 6 | for y in animals: 7 | results += [x + ' ' + y] 8 | 9 | print(results) 10 | 11 | -------------------------------------------------------------------------------- /ch02/ch02_for_score.py: -------------------------------------------------------------------------------- 1 | 2 | scores = [60, 73, 81, 95, 34] 3 | n = 0 4 | total = 0 5 | for x in scores: 6 | n += 1 7 | total += x 8 | 9 | avg = total / n 10 | 11 | print('total ' + str(total)) 12 | print('average ' + str(avg)) 13 | -------------------------------------------------------------------------------- /ch02/ch02_if.py: -------------------------------------------------------------------------------- 1 | 2 | a, b, c = 3, 5, 7 3 | x = None 4 | 5 | if a < b: 6 | if b < c: 7 | x = c 8 | else: 9 | x = b 10 | else: 11 | if a < c: 12 | x = c 13 | else: 14 | x = a 15 | 16 | x 17 | print(x) 18 | -------------------------------------------------------------------------------- /ch02/ch02_my_len.py: -------------------------------------------------------------------------------- 1 | 2 | li = [60, 73, 81, 95, 34] 3 | t = (0, 1, 2, 3, 4, 5) 4 | s = 'Learning Python is fun' 5 | empty = [] 6 | 7 | def my_len(seq): 8 | n = 0 9 | for x in seq: 10 | n += 1 11 | return n 12 | 13 | print(str(li) + ' length ' + str(my_len(li))) 14 | print(str(t) + ' length ' + str(my_len(t))) 15 | print(str(s) + ' length ' + str(my_len(s))) 16 | print(str(empty) + ' length ' + str(my_len(empty))) 17 | -------------------------------------------------------------------------------- /ch02/ch02_my_sum.py: -------------------------------------------------------------------------------- 1 | 2 | def my_sum(numbers, initial=0): 3 | total = initial 4 | for x in numbers: 5 | total += x 6 | return total 7 | 8 | scores0 = [60, 73, 81, 95, 34] 9 | scores1 = [10, 20, 30, 40, 50, 60] 10 | scores2 = [0, 0, 0] 11 | scores3 = [] 12 | scores4 = [-3, -5, -6, -7, -1, -2] 13 | 14 | print(str(scores0) + ' total is ' + str(my_sum(scores0))) 15 | print(str(scores1) + ' total is ' + str(my_sum(scores1))) 16 | print(str(scores2) + ' total is ' + str(my_sum(scores2))) 17 | print(str(scores3) + ' total is ' + str(my_sum(scores3))) 18 | print(str(scores4) + ' total is ' + str(my_sum(scores4, 100))) 19 | -------------------------------------------------------------------------------- /ch02/ch02_return_total_avg.py: -------------------------------------------------------------------------------- 1 | 2 | scores = [60, 73, 81, 95, 34] 3 | 4 | def total_avg(scores, initial=0): 5 | n = 0 6 | total = initial 7 | for x in scores: 8 | total += x 9 | n += 1 10 | return (total, total/n) 11 | 12 | print('total,avg ' + str(total_avg(scores))) 13 | 14 | -------------------------------------------------------------------------------- /ch02/ch02_score_high.py: -------------------------------------------------------------------------------- 1 | 2 | scores = [60, 73, 81, 95, 34] 3 | n = 0 4 | high_total = 0 5 | for x in scores: 6 | if x < 60: 7 | continue 8 | n += 1 9 | high_total += x 10 | 11 | high_avg = high_total / n 12 | 13 | print('high average ' + str(high_avg)) 14 | -------------------------------------------------------------------------------- /ch02/ch02_score_plus.py: -------------------------------------------------------------------------------- 1 | 2 | scores = [30, 99, 41, 55, 84] 3 | scores_new = [] 4 | for x in scores: 5 | if x >= 90: 6 | scores_new += [x] 7 | continue 8 | x += 10 9 | if x >= 90: 10 | x = 90 11 | scores_new += [x] 12 | 13 | print(scores) 14 | print(scores_new) 15 | -------------------------------------------------------------------------------- /ch02/ch02_while_score.py: -------------------------------------------------------------------------------- 1 | 2 | scores = [60, 73, 81, 95, 34] 3 | n = 5 4 | i = 0 5 | total = 0 6 | while i < 5: 7 | total += scores[i] 8 | i += 1 9 | 10 | avg = total / n 11 | 12 | print('total ' + str(total)) 13 | print('average ' + str(avg)) 14 | -------------------------------------------------------------------------------- /ch02/myhello.py: -------------------------------------------------------------------------------- 1 | #import mymath 2 | #from mymath import pi, gcd, factorial 3 | import mymath as m 4 | 5 | print('Hello Python') 6 | print('pi is ' + str(m.pi)) 7 | print('gcd of 24 and 16 is ' + str(m.gcd(24, 16))) 8 | print('factorial of 6 is ' + str(m.factorial(6))) 9 | print('Bye Python') 10 | 11 | if __name__ == '__main__': 12 | print('myhello as main program') 13 | else: 14 | print('myhello as module') 15 | 16 | -------------------------------------------------------------------------------- /ch02/mymath.py: -------------------------------------------------------------------------------- 1 | 2 | pi = 3.14 3 | 4 | def gcd(a, b): 5 | while b: 6 | a, b = b, a%b 7 | return a 8 | 9 | def factorial(n): 10 | result = 1 11 | for i in range(1, n+1): 12 | result *= i 13 | return result 14 | 15 | if __name__ == '__main__': 16 | print('mymath as main program') 17 | else: 18 | print('mymath as module') 19 | 20 | -------------------------------------------------------------------------------- /ch02ex/ch02ex2.10_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | li_a = [1, 5, 9, 11, 22, 4, 9, 1, 3, 7] 4 | li_b = [9, 4, 55, 66, 1, 11, 77] 5 | 6 | def f(li_a, li_b): 7 | li = [] 8 | for n in li_a: 9 | if n in li_b and n not in li: 10 | li += [n] 11 | return li 12 | 13 | print(f(li_a, li_b)) 14 | 15 | 16 | -------------------------------------------------------------------------------- /ch02ex/ch02ex2.1_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # examples: 4 | # leap year: 1600, 1992, 1996, 2000, 2060, 2400 5 | # not leap year: 1800, 1900, 2100 6 | # not leap year: 1997, 2057 7 | 8 | year = 1996 9 | 10 | if (year % 4 == 0) and (year % 100 != 0) or (year % 400 == 0): 11 | print(year) 12 | print(' is leap year') 13 | else: 14 | print(year) 15 | print(' is not leap year') 16 | 17 | year = 2100 18 | 19 | if year % 400 == 0 or year % 4 == 0 and year % 100 != 0: 20 | print(year) 21 | print(' is leap year') 22 | else: 23 | print(year) 24 | print(' is not leap year') 25 | 26 | -------------------------------------------------------------------------------- /ch02ex/ch02ex2.1_more_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from __future__ import print_function 4 | 5 | # examples: 6 | # leap year: 1600, 1992, 1996, 2000, 2060, 2400 7 | # not leap year: 1800, 1900, 2100 8 | # not leap year: 1997, 2057 9 | 10 | def leapyear_a(year): 11 | if year % 400 == 0: 12 | return True 13 | elif year % 100 == 0: 14 | return False 15 | elif year % 4 == 0: 16 | return True 17 | else: 18 | return False 19 | 20 | def leapyear_b(year): 21 | if ((year % 4 == 0) and (year % 100 != 0)) or (year % 400 == 0): 22 | return True 23 | else: 24 | return False 25 | 26 | def leapyear_c(year): 27 | if (year % 4 == 0) and (year % 100 != 0) or (year % 400 == 0): 28 | return True 29 | else: 30 | return False 31 | 32 | def leapyear_d(year): 33 | if year % 400 == 0 or year % 4 == 0 and year % 100 != 0: 34 | return True 35 | else: 36 | return False 37 | 38 | if __name__ == '__main__': 39 | funcs = [leapyear_a, leapyear_b, leapyear_c, leapyear_d] 40 | leapyears = [1600, 1992, 1996, 2000, 2060, 2400] 41 | not_leapyears = [1800, 1900, 2100, 1997, 2057] 42 | allpass = True 43 | for f in funcs: 44 | print('Testing function: %s' % f.__name__) 45 | for y in leapyears: 46 | if f(y) != True: 47 | print('Failed: %d is leap year' % y) 48 | allpass = False 49 | for y in not_leapyears: 50 | if f(y) != False: 51 | print('Failed: %d is not leap year' % y) 52 | allpass = False 53 | if allpass: 54 | print('All passed') 55 | else: 56 | print('Not all passed') 57 | 58 | -------------------------------------------------------------------------------- /ch02ex/ch02ex2.2_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # for loop 4 | for x in range(2, 9+1): 5 | for y in range(1, 9+1): 6 | print(x, ' * ', y, ' = ', x*y) 7 | # print(str(x) + ' * ' + str(y) + ' = ' + str(x*y)) 8 | # print('%d * %d = %d' % (x, y, x*y)) 9 | 10 | # while loop 11 | x = 2 12 | while x < 9+1: 13 | y = 1 14 | while y < 9+1: 15 | print(x, ' * ', y, ' = ', x*y) 16 | # print(str(x) + ' * ' + str(y) + ' = ' + str(x*y)) 17 | # print('%d * %d = %d' % (x, y, x*y)) 18 | y += 1 19 | x += 1 20 | -------------------------------------------------------------------------------- /ch02ex/ch02ex2.3_answer.py: -------------------------------------------------------------------------------- 1 | 2 | # don't use continue statement 3 | 4 | scores = [30, 99, 41, 55, 84] 5 | scores_new = [] 6 | for x in scores: 7 | if x >= 90: 8 | scores_new += [x] 9 | else: 10 | if x+10 >= 90: 11 | scores_new += [90] 12 | else: 13 | scores_new += [x+10] 14 | 15 | print(scores) 16 | print(scores_new) 17 | -------------------------------------------------------------------------------- /ch02ex/ch02ex2.4_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Celsius to Fahrenheit 4 | def ctof(temp): 5 | return temp * 9.0 / 5.0 + 32 6 | 7 | # Fahrenheit to Celsius 8 | def ftoc(temp): 9 | return (temp - 32) * 5.0 / 9.0 10 | 11 | 12 | if __name__ == '__main__': 13 | # simple tests 14 | if ctof(0) - 32 >= 0.0001: 15 | print('Failed: 0 C should be 32 F') 16 | if ctof(100) - 212 >= 0.0001: 17 | print('Failed: 100 C should be 212 F') 18 | 19 | if ftoc(32) - 0 >= 0.0001: 20 | print('Failed: 32 F should be 0 C') 21 | if ftoc(212) - 100 >= 0.0001: 22 | print('Failed: 212 F should be 100 C') 23 | 24 | -------------------------------------------------------------------------------- /ch02ex/ch02ex2.5_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def f(x, y, z): 4 | if x >= y: 5 | if y >= z: # x y z 6 | return x**2 + y**2 7 | else: # x z y 8 | return x**2 + z**2 9 | else: 10 | if x >= z: # y x z 11 | return y**2 + x**2 12 | else: # y z x 13 | return y**2 + z**2 14 | 15 | 16 | if __name__ == '__main__': 17 | # simple tests 18 | if f(1, 2, 3) != (2**2 + 3**2): 19 | print('Failed') 20 | if f(5, 3, 4) != (5**2 + 4**2): 21 | print('Failed') 22 | if f(9, 11, 10) != (11**2 + 10**2): 23 | print('Failed') 24 | 25 | -------------------------------------------------------------------------------- /ch02ex/ch02ex2.6_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # greatest common divisor 4 | def gcd(a, b): 5 | while b: 6 | a, b = b, a%b 7 | return a 8 | 9 | # least common multiple 10 | def lcm(a, b): 11 | x = gcd(a, b) 12 | return (a // x) * b 13 | 14 | if __name__ == '__main__': 15 | # simple tests 16 | if lcm(7, 13) != 91: 17 | print('Failed') 18 | if lcm(100, 25) != 100: 19 | print('Failed') 20 | if lcm(16, 24) != 48: 21 | print('Failed') 22 | 23 | -------------------------------------------------------------------------------- /ch02ex/ch02ex2.7_answer.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | # 串列裡含有由小到大排列好的整數,數字可能重複, 4 | # 例如 [0, 1, 1, 2, 3, 4, 5, 5, 9, 9, 9, 23, 25, 25, 25], 5 | # 請撰寫函式找出重複最多次的整數,若重複次數相等則回傳值較小的, 6 | # 以此例而言,9 與 25 都重複 3 次,應回傳 9。 7 | 8 | # 若把「重複的整數」稱為「平台」, 9 | # 那麼此問題可稱為找出「最長平台」的問題, 10 | # 以上例而言,整數0這個平台的長度是1,整數1這個平台的長度為2, 11 | # 依此類推,最長平台是9與25,根據題意應回傳9。 12 | 13 | def plateau(data): 14 | if len(data) == 0: 15 | return None 16 | # 記錄到目前為止找到的最長平台 17 | result_i_max = 0 # 一開始先把索引值0的元素當做最長平台 18 | result_x_max = data[0] # 記錄該平台的整數,最後會成為此函式的回傳 19 | count_max = 1 # 該平台的長度,目前是1 20 | 21 | # 記錄目前正在處理中的平台 22 | result_i = 0 # 從索引值0開始處理 23 | result_x = data[0] # 記錄該平台的整數 24 | count = 1 # 該平台的長度,目前是1 25 | 26 | for i in range(1, len(data)): # 從索引值1開始 27 | if data[i] == result_x: # 若元素(整數)等於前一平台,該平台的長度加一 28 | count += 1 # 換句話說,該平台繼續延伸 29 | 30 | else: # data[i] > result_x: # 若大於,代表進入新的平台 31 | result_i = i # 進入新的平台了, 32 | result_x = data[i] # 所以重新設定目前正在處理的平台 33 | count = 1 34 | 35 | if count > count_max: # 記錄到目前為止,最長平台的資訊 36 | result_i_max, result_x_max, count_max = result_i, result_x, count 37 | 38 | return result_x_max # 此題目要求回傳result_x_max, 39 | # 有時則會需要result_i_max或count_max 40 | 41 | if __name__ == '__main__': 42 | # simple tests 43 | data = [0, 1, 1, 2, 3, 4, 5, 5, 9, 9, 9, 23, 25, 25, 25] 44 | if plateau(data) != 9: 45 | print('Failed') 46 | 47 | data = [1, 1, 1, 2, 3, 4, 5, 5, 9, 9, 9, 23, 25, 25, 25] 48 | if plateau(data) != 1: 49 | print('Failed') 50 | 51 | data = [1, 1, 1, 2, 3, 5, 5, 5, 5, 9, 9, 23, 25, 25, 25] 52 | if plateau(data) != 5: 53 | print('Failed') 54 | 55 | data = [0, 1, 1, 2, 3, 4, 5, 5, 9, 9, 9, 23, 25, 25, 25, 25] 56 | if plateau(data) != 25: 57 | print('Failed') 58 | 59 | data = [0, 1, 2, 2, 3, 4, 5, 5, 9, 9, 9, 23, 25, 25, 25, 25, 26, 27, 27] 60 | if plateau(data) != 25: 61 | print('Failed') 62 | 63 | # 你是否能改進這支函式、使用較少的物件? 64 | 65 | # 若只需知道最長平台的長度,程式碼將非常簡短,如下: 66 | def plateau_longest_length(data): 67 | if len(data) == 0: 68 | return None 69 | 70 | length_max = 1 71 | for i in range(1, len(data)): 72 | if data[i] == data[i - length_max]: 73 | length_max += 1 74 | 75 | return length_max 76 | 77 | -------------------------------------------------------------------------------- /ch02ex/ch02ex2.8_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def is_leap_year(year): 4 | if ((year % 4 == 0) and (year % 100 != 0)) or (year % 400 == 0): 5 | return True 6 | else: 7 | return False 8 | 9 | def year_days(year): 10 | return 365 + (1 if is_leap_year(year) else 0) 11 | 12 | # argument month is 1, 2, 3, ..., 11, 12 13 | def month_days(month, year): 14 | md = [31, 28, 31, 30, 31, 30, 15 | 31, 31, 30, 31, 30, 31] 16 | return md[month-1] + (1 if month == 2 and is_leap_year(year) else 0) 17 | 18 | # assume epoch is [1970, 1, 1] 19 | def days_since_epoch(date): 20 | year, month, day = date 21 | 22 | days = day 23 | for y in range(1970, year): 24 | days += year_days(y) 25 | for m in range(1, month): 26 | days += month_days(m, year) 27 | 28 | return days 29 | 30 | def days_diff(date1, date2): 31 | return days_since_epoch(date2) - days_since_epoch(date1) 32 | 33 | 34 | ## 35 | 36 | date1 = [2014, 11, 12] 37 | date2 = [2015, 2, 15] 38 | 39 | print(days_diff(date1, date2), "days") 40 | 41 | 42 | # from datetime import date 43 | # print(date(*date2) - date(*date1)) 44 | 45 | 46 | # for y in range(1970, 2020): 47 | # for m in range(5, 11+1): 48 | # for d in range(5, 27): 49 | # date1 = [y, m, d] 50 | # date2 = [y+1, m-2, d-3] 51 | # if days_diff(date1, date2) != (date(*date2) - date(*date1)).days: 52 | # print("Failed") 53 | 54 | -------------------------------------------------------------------------------- /ch02ex/ch02ex2.9_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def factorial(n): 4 | result = 1 5 | for i in range(1, n+1): 6 | result *= i 7 | return result 8 | 9 | def f(n): 10 | fact = factorial(n) 11 | result = 0 12 | while fact > 0: 13 | result += fact % 10 14 | fact //= 10 15 | 16 | return result 17 | 18 | if __name__ == '__main__': 19 | # simple tests 20 | n_fn = ((1, 1), (2, 2), (3, 6), (4, 6), (5, 3), 21 | (6, 9), (7, 9), (8, 9), (9, 27), (10, 27)) 22 | 23 | for n, fn in n_fn: 24 | if fn != f(n): 25 | print('Failed:') 26 | print('summation of digits of %d! should be %d, not %d' % (n, fn, f(n))) 27 | 28 | -------------------------------------------------------------------------------- /ch03/ch03_geom.py: -------------------------------------------------------------------------------- 1 | 2 | def geomean(numbers): 3 | product = 1 4 | for n in numbers: 5 | product *= n 6 | return product ** (1.0 / len(numbers)) 7 | 8 | if __name__ == '__main__': 9 | a = list(range(1, 10+1)) 10 | gm = geomean(a) 11 | print(gm) 12 | 13 | -------------------------------------------------------------------------------- /ch03/ch03_getbits.py: -------------------------------------------------------------------------------- 1 | 2 | def getbits(x, p, n): 3 | return (x >> (p+1-n)) & ~(~0b0 << n) 4 | 5 | print(bin(getbits(0b10101010, 4, 3))) 6 | print(bin(getbits(0b11110101, 5, 4))) 7 | 8 | -------------------------------------------------------------------------------- /ch03/ch03_my_sqrt.py: -------------------------------------------------------------------------------- 1 | 2 | diff = 0.00001 3 | def is_ok(n, ans): 4 | return abs(ans**2 - n) < diff 5 | def get_better(n, ans): 6 | return ((float(n) / ans) + ans) / 2 7 | def my_sqrt(n): 8 | ans = 1 9 | while not is_ok(n, ans): 10 | ans = get_better(n, ans) 11 | return ans 12 | 13 | import math 14 | print(my_sqrt(9)) 15 | print(math.sqrt(9)) 16 | print(my_sqrt(2)) 17 | print(math.sqrt(2)) 18 | print(my_sqrt(3)) 19 | print(math.sqrt(3)) 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ch03ex/ch03ex3.10_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | try: 4 | input = raw_input 5 | except NameError: 6 | pass 7 | 8 | #### 9 | 10 | import random 11 | 12 | def main(): 13 | range_min = 1 14 | range_max = 100 15 | answer = random.randint(range_min+1, range_max-1) 16 | guess_count = 0 17 | 18 | while True: 19 | print('Range %d ~ %d' % (range_min, range_max)) 20 | guess = input('Input your %dth guess: ' % (guess_count+1)) 21 | guess = int(guess) 22 | if guess <= range_min or range_max <= guess: 23 | print('Your guess %d is beyond the valid range.' % guess) 24 | elif guess == answer: 25 | print('Yes, answer is %d!' % answer) 26 | break 27 | else: 28 | if answer < guess: 29 | range_max = guess 30 | else: 31 | range_min = guess 32 | guess_count += 1 33 | 34 | if __name__ == '__main__': 35 | main() 36 | -------------------------------------------------------------------------------- /ch03ex/ch03ex3.11_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from math import log2, ceil 4 | 5 | def f(a, b): 6 | bit_n = ceil(log2(max(a, b))) 7 | count = 0 8 | for i in range(bit_n): 9 | if (a ^ b) & (0x1 << i): 10 | count += 1 11 | return count 12 | 13 | 14 | if __name__ == "__main__": 15 | if f(31, 14) != 2: 16 | print('Failed: f(31, 14) should be 2') 17 | 18 | if f(0b11110000, 0b00001111) != 8: 19 | print('Failed: f(0b11110000, 0b00001111) should be 8') 20 | 21 | -------------------------------------------------------------------------------- /ch03ex/ch03ex3.12_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | def f(n): 5 | m1 = 0b10101010 6 | mask1 = (m1 << 24) | (m1 << 16) | (m1 << 8) | m1 7 | m2 = 0b01010101 8 | mask2 = (m2 << 24) | (m2 << 16) | (m2 << 8) | m2 9 | 10 | return ((n & mask1) >> 1) | ((n & mask2) << 1) 11 | 12 | 13 | if __name__ == "__main__": 14 | if f(0b10101010) != 0b01010101: 15 | print('Failed: f(0b10101010) should be 0b01010101') 16 | 17 | if f(0b11001001) != 0b11000110: 18 | print('Failed: f(0b11001001) should be 0b11000110') 19 | 20 | if f(0b1100100111001001) != 0b1100011011000110: 21 | print('Failed: f(0b1100100111001001) should be 0b1100011011000110') 22 | 23 | if f(0b101010101100100111001001) != 0b010101011100011011000110: 24 | print('Failed: f(0b101010101100100111001001) should be 0b010101011100011011000110') 25 | 26 | if f(0b11001001101010101100100111001001) != 0b11000110010101011100011011000110: 27 | print('Failed: f(0b11001001101010101100100111001001) should be 0b11000110010101011100011011000110') 28 | -------------------------------------------------------------------------------- /ch03ex/ch03ex3.1_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import math 4 | 5 | def area_circle(r): 6 | return r * r * math.pi 7 | 8 | 9 | -------------------------------------------------------------------------------- /ch03ex/ch03ex3.2_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def f(n): 4 | if n < 0: 5 | n = 0 6 | elif n > 255: 7 | n = 255 8 | 9 | if 0 <= n <= 130: 10 | a0, a1 = 0, 130 11 | b0, b1 = 0, 60 12 | elif 130 < n < 200: 13 | a0, a1 = 130, 200 14 | b0, b1 = 60, 85 15 | else: # 200 <= n <= 255 16 | a0, a1 = 200, 255 17 | b0, b1 = 85, 100 18 | 19 | return int((n - a0) / (a1 - a0) * (b1 - b0) + b0) 20 | 21 | 22 | if __name__ == '__main__': 23 | # simple tests 24 | if f(0) != 0: 25 | print('Failed') 26 | if f(130) != 60: 27 | print('Failed') 28 | if f(200) != 85: 29 | print('Failed') 30 | if f(255) != 100: 31 | print('Failed') 32 | -------------------------------------------------------------------------------- /ch03ex/ch03ex3.3_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def f(n): 4 | if n < 10: 5 | if n == 9 or n == 6 or n == 3: 6 | return True 7 | else: 8 | return False 9 | else: 10 | result = 0 11 | while n > 0: 12 | result += n % 10 13 | n //= 10 14 | return f(result) 15 | 16 | 17 | if __name__ == '__main__': 18 | # simple tests 19 | if f(9) != True: 20 | print('Failed') 21 | if f(37524) != True: 22 | print('Failed') 23 | if f(21) != True: 24 | print('Failed') 25 | if f(18) != True: 26 | print('Failed') 27 | if f(4) != False: 28 | print('Failed') 29 | -------------------------------------------------------------------------------- /ch03ex/ch03ex3.4_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def collatz(n): 4 | if n == 1: 5 | return 1 6 | elif n % 2 == 0: 7 | return collatz(n // 2) 8 | else: 9 | return collatz(3 * n + 1) 10 | 11 | def collatz_i(n): 12 | while n != 1: 13 | if n % 2 == 0: 14 | n //= 2 15 | else: 16 | n = 3 * n + 1 17 | return n 18 | 19 | if __name__ == '__main__': 20 | for i in range(1, 10000+1): 21 | if collatz_i(i) != 1: 22 | print('collatz_i(' + str(i) + ') failed'); 23 | break 24 | else: 25 | print('All passed') 26 | 27 | -------------------------------------------------------------------------------- /ch03ex/ch03ex3.5_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # note: this version is very inefficient 4 | def is_prime(n): 5 | for i in range(2, n): 6 | if n % i == 0: 7 | return False 8 | return True 9 | 10 | if __name__ == '__main__': 11 | # simple tests 12 | primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31] 13 | not_primes = [4, 6, 15, 20, 21, 25, 100, 246] 14 | for i in primes: 15 | if is_prime(i) != True: 16 | print('Failed: %d is prime' % i) 17 | for i in not_primes: 18 | if is_prime(i) != False: 19 | print('Failed: %d is not prime' % i) 20 | -------------------------------------------------------------------------------- /ch03ex/ch03ex3.6_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def is_1089(n): 4 | nabc = n 5 | ncba = int(str(nabc)[::-1]) 6 | ndef = abs(nabc - ncba) 7 | nfed = int(str(ndef)[::-1]) 8 | return (ndef + nfed) == 1089 9 | 10 | if __name__ == '__main__': 11 | # simple test 12 | if is_1089(732) != True: 13 | print('Failed: 732') 14 | if is_1089(654) != True: 15 | print('Failed: 654') 16 | if is_1089(123) != True: 17 | print('Failed: 123') 18 | 19 | # test all 3-digit numbers 20 | for x in range(1, 9+1): 21 | for y in range(0, 9+1): 22 | for z in range(0, 9+1): 23 | n = x*100 + y*10 + z 24 | if is_1089(n) != (abs(x - z) >= 2): 25 | print('Failed: %d' % n); 26 | 27 | -------------------------------------------------------------------------------- /ch03ex/ch03ex3.7_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import math 4 | 5 | def factorial(n): 6 | result = 1 7 | for i in range(1, n+1): 8 | result *= i 9 | return result 10 | 11 | def factorial_stirling(n): 12 | return math.sqrt(2 * math.pi * n) * pow(float(n) / math.e, n) 13 | 14 | if __name__ == '__main__': 15 | # simple test 16 | for n in range(2, 30): 17 | nf = factorial(n) 18 | nfs = factorial_stirling(n) 19 | error = (nfs - nf) / nf 20 | tolerance = 0.1 21 | if error >= tolerance: 22 | print('%d! = %d, stirling: %f' % (n, nf, nfs)) 23 | print('error: %f' % ((nfs - nf) / nf)) 24 | -------------------------------------------------------------------------------- /ch03ex/ch03ex3.8_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import math 4 | 5 | def is_cardano(a, b, c): 6 | return (8*a*a*a + 15*a*a + 6*a - 1) == 27*b*b*c 7 | 8 | def main(): 9 | count = 0 10 | for a in range(1, 1000-1-1 + 1): 11 | for b in range(1, 1000-a-1 + 1): 12 | for c in range(1, 1000-a-b + 1): 13 | if is_cardano(a, b, c): 14 | count += 1 15 | print("%d: %d, %d, %d" % (count, a, b, c)) 16 | print('Total: %d' % count) 17 | return count 18 | 19 | if __name__ == '__main__': 20 | # simple test 21 | if is_cardano(2, 1, 5) == False: 22 | print('Failed: (2, 1, 5) should be a Cardano Triple') 23 | if main() != 149: 24 | print('Failed: should be 149') 25 | -------------------------------------------------------------------------------- /ch03ex/ch03ex3.9_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def check_ab(answer, guess): 4 | a_count = 0 5 | b_count = 0 6 | for i in range(len(guess)): 7 | if guess[i] == answer[i]: 8 | a_count += 1 9 | elif guess[i] in answer: 10 | b_count += 1 11 | 12 | return (a_count, b_count) 13 | 14 | if __name__ == '__main__': 15 | # simple test 16 | if check_ab('5234', '5346') != (1, 2): 17 | print('Failed: answer 5234, guess 5346') 18 | if check_ab('5234', '5234') != (4, 0): 19 | print('Failed: answer 5234, guess 5234') 20 | if check_ab('1234', '4321') != (0, 4): 21 | print('Failed: answer 1234, guess 4321') 22 | if check_ab('1234', '2134') != (2, 2): 23 | print('Failed: answer 1234, guess 2134') 24 | if check_ab('1234', '3241') != (1, 3): 25 | print('Failed: answer 1234, guess 3241') 26 | -------------------------------------------------------------------------------- /ch04/ch04_99m_format.py: -------------------------------------------------------------------------------- 1 | 2 | def p99(li): 3 | for y in range(1, 9+1): 4 | result = [] 5 | for x in li: 6 | s = '%2d x%2d = %2d' % (x, y, x*y) 7 | result.append(s) 8 | print(' '.join(result)) 9 | 10 | p99([2, 3, 4, 5]) 11 | print('') 12 | p99([6, 7, 8, 9]) 13 | 14 | -------------------------------------------------------------------------------- /ch04/ch04_9x9m.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | result = [] 4 | for x in range(2, 9+1): 5 | for y in range(1, 9+1): 6 | result.append(str(x) + '*' + str(y) + '=' + str(x*y)) 7 | 8 | print(result) 9 | 10 | #### 11 | 12 | result = [str(x)+'*'+str(y)+'='+str(x*y) for x in range(2, 9+1) 13 | for y in range(1, 9+1)] 14 | 15 | print(result) 16 | -------------------------------------------------------------------------------- /ch04/ch04_anagram.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def is_anagram(s1, s2): 4 | s1 = ''.join(s1.lower().split()) 5 | s2 = ''.join(s2.lower().split()) 6 | return sorted(s1) == sorted(s2) 7 | 8 | # True 9 | print(is_anagram('heart', 'earth')) 10 | print(is_anagram('Torchwood', 'Doctor Who')) 11 | print(is_anagram('spot', 'stop')) 12 | print(is_anagram('silent', 'listen')) 13 | print(is_anagram('William Shakespeare', 'I am a weakish speller')) 14 | print(is_anagram('computer', 'cuter mop')) 15 | print(is_anagram('a b c \t\n 1 2 3 \t\n ', '123abc\t\n')) 16 | print('') 17 | # False 18 | print(is_anagram('abc', 'abd')) 19 | print(is_anagram('play', 'pray')) 20 | print(is_anagram('string', 'sting')) 21 | 22 | -------------------------------------------------------------------------------- /ch04/ch04_base36encode.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' 4 | def base36encode(number, alphabet=alphabet): 5 | result = [] 6 | base = len(alphabet) 7 | sign = '' 8 | if number < 0: 9 | sign = '-' 10 | number = -number 11 | 12 | while number >= base: 13 | number, i = divmod(number, base) 14 | result.append(alphabet[i]) 15 | result.append(alphabet[number]) 16 | if sign == '-': 17 | result.append(sign) 18 | 19 | return ''.join(reversed(result)) 20 | 21 | print(base36encode(int('0', 36))) 22 | print(base36encode(int('ZZ', 36))) 23 | print(base36encode(int('ZYXW', 36))) 24 | print(base36encode(int('-ABCDEF', 36))) 25 | print(base36encode(int('-GHIJKLMNOPQ', 36))) 26 | 27 | 28 | -------------------------------------------------------------------------------- /ch04/ch04_comb.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | li0 = ['a', 'b', 'c'] 4 | li1 = ['.jpg', '.png', '.bmp'] 5 | result = [] 6 | for x in li0: 7 | if x != 'a': 8 | for y in li1: 9 | if y != '.jpg': 10 | result.append(x + y) 11 | 12 | print(result) 13 | 14 | #### 15 | 16 | result = [x+y for x in li0 if x != 'a' for y in li1 if y != '.jpg'] 17 | 18 | print(result) 19 | -------------------------------------------------------------------------------- /ch04/ch04_cumulative_sum.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def cumulative_sum(iterable, start=0): 4 | result = [] 5 | acc = start 6 | for x in iterable: 7 | acc += x 8 | result.append(acc) 9 | return result 10 | 11 | 12 | print(cumulative_sum(range(10+1))) 13 | print(cumulative_sum(range(0, 1000, 100))) 14 | 15 | -------------------------------------------------------------------------------- /ch04/ch04_duplicate.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def duplicate(iterable): 4 | fst = [] 5 | snd = [] 6 | for x in iterable: 7 | if x not in fst: 8 | fst.append(x) 9 | elif x not in snd: 10 | snd.append(x) 11 | else: 12 | pass 13 | return snd 14 | 15 | print(duplicate([1, 2, 6, 1, 3, 2, 5])) 16 | print(duplicate(range(10))) 17 | print(duplicate([1, 1, 3, 1, 3, 3, 1, 2, 1, 5, 2])) 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ch04/ch04_flatten.py: -------------------------------------------------------------------------------- 1 | 2 | def flatten(iterable): 3 | result = [] 4 | for x in iterable: 5 | result.extend(x) 6 | return result 7 | 8 | 9 | print(flatten([[0, 1, 2], [3, 4, 5], [6], [7, 8], [9]])) 10 | print(flatten([[0, 1], [3, 5], [6], [7, 8], [9]])) 11 | -------------------------------------------------------------------------------- /ch04/ch04_ft_to_ct.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | ft = [32, 212, 10, 55, 78, 110, 178] 4 | def ftoc(ft): 5 | ct = [] 6 | for x in ft: 7 | ct.append((x - 32) * 5 / 9) 8 | return ct 9 | 10 | ct = ftoc(ft) 11 | print(list(zip(ft, ct))) 12 | 13 | #### 14 | 15 | ft = [32, 212, 10, 55, 78, 110, 178] 16 | ct = [(x - 32) * 5 / 9 for x in ft] 17 | print(list(zip(ft, ct))) 18 | 19 | -------------------------------------------------------------------------------- /ch04/ch04_group.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def group(iterable, size): 4 | result = [] 5 | li = list(iterable) 6 | length = len(li) 7 | for i in range(0, length, size): 8 | result.append(li[i:i+size]) 9 | return result 10 | 11 | print(group([1, 2, 3, 4, 5, 6, 7, 8, 9], 3)) 12 | # [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 13 | 14 | print(group([1, 2, 3, 4, 5, 6, 7, 8, 9], 4)) 15 | # [[1, 2, 3, 4], [5, 6, 7, 8], [9]] 16 | 17 | print(group(range(20), 5)) 18 | -------------------------------------------------------------------------------- /ch04/ch04_hamming.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def hamming(s1, s2): 4 | lens = (len(s1), len(s2)) 5 | minlen = min(lens) 6 | maxlen = max(lens) 7 | h = maxlen - minlen 8 | 9 | for i in range(minlen): 10 | if(s1[i] != s2[i]): 11 | h += 1 12 | 13 | return h 14 | 15 | print(hamming('abcde', 'edcba')) # 4 16 | print(hamming('abc', 'abcde')) # 2 17 | print(hamming('1011101', '1001001')) # 2 18 | print(hamming('karolin', 'kathrin')) # 3 19 | 20 | -------------------------------------------------------------------------------- /ch04/ch04_my_factorial.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def product(iterable, start=1): 4 | result = start 5 | for x in iterable: 6 | result *= x 7 | return result 8 | 9 | def my_factorial(n): 10 | return product(range(2, n+1)) 11 | 12 | from math import factorial 13 | print('6! is ' + str(my_factorial(6))) 14 | print('math.factorial: ' + str(factorial(6))) 15 | print('10! is ' + str(my_factorial(10))) 16 | print('math.factorial: ' + str(factorial(10))) 17 | print('15! is ' + str(my_factorial(15))) 18 | print('math.factorial: ' + str(factorial(15))) 19 | -------------------------------------------------------------------------------- /ch04/ch04_my_sum.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def my_sum(iterable, start=0): 4 | result = start 5 | for x in iterable: 6 | result += x 7 | return result 8 | 9 | a = ('a', 'b', 'c', 'd') 10 | b = range(1, 10+1) 11 | c = ['abc', 'def', 'gh', 'i'] 12 | print(my_sum(a, '')) 13 | print(my_sum(b)) 14 | print(my_sum(c, '')) 15 | -------------------------------------------------------------------------------- /ch04/ch04_product.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def product(iterable, start=1): 4 | result = start 5 | for x in iterable: 6 | result *= x 7 | return result 8 | 9 | a = range(1, 10+1) 10 | b = [2, 3, 4, 5] 11 | c = [1.1, 3.5, 5.6] 12 | print(product(a, 0.1)) 13 | print(product(b)) 14 | print(product(c)) 15 | -------------------------------------------------------------------------------- /ch04/ch04_unique.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def unique(iterable): 4 | result = [] 5 | for x in iterable: 6 | if x not in result: 7 | result.append(x) 8 | return result 9 | 10 | 11 | print(unique([1, 2, 1, 3, 2, 5, 5, 6, 1])) # [1, 2, 3, 5, 6] 12 | print(unique([1, 2, 1, 3, 2, 5])) # [1, 2, 3, 5] 13 | print(unique(range(10))) 14 | 15 | -------------------------------------------------------------------------------- /ch04/ch04_while_iteration.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | li = [30, 41, 52] 4 | itb = iter(li) 5 | while True: 6 | try: 7 | x = next(itb) 8 | print(x) 9 | except StopIteration: 10 | break 11 | 12 | -------------------------------------------------------------------------------- /ch04ex/ch04ex4.18_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def is_palindrome(n): 4 | ns = str(n) 5 | a, b = 0, len(ns)-1 6 | while a < b: 7 | if ns[a] != ns[b]: 8 | return False 9 | else: 10 | a += 1 11 | b -= 1 12 | return True 13 | 14 | def is_palindrome_2(n): 15 | ns = str(n) 16 | ns_r = ''.join(reversed(ns)) 17 | return ns == ns_r 18 | 19 | print(sum([1 for i in range(10, 99+1) if is_palindrome(i)])) 20 | print(sum([1 for i in range(100, 999+1) if is_palindrome(i)])) 21 | print(sum([1 for i in range(1000, 9999+1) if is_palindrome(i)])) 22 | 23 | -------------------------------------------------------------------------------- /ch04ex/ch04ex4.1_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def find_once(li): 4 | result = [] 5 | for i, e in enumerate(li): 6 | if e not in li[:i] and e not in li[i+1:]: 7 | result.append(e) 8 | return result 9 | 10 | if __name__ == '__main__': 11 | # simple tests 12 | li = [9, 5, 5, -4, 7, 6, 4, 1, -2, 0, 10, 9, 7] 13 | if find_once(li) != [-4, 6, 4, 1, -2, 0, 10]: 14 | print('Failed') 15 | 16 | li = [1, 1, -3, -3] 17 | if find_once(li) != []: 18 | print('Failed') 19 | 20 | li = [5, 6, 8, -3] 21 | if find_once(li) != [5, 6, 8, -3]: 22 | print('Failed') 23 | 24 | li = [-3, 8, 5, 6, 8, -3] 25 | if find_once(li) != [5, 6]: 26 | print('Failed') 27 | 28 | -------------------------------------------------------------------------------- /ch04ex/ch04ex4.2_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def split_a(li, n): 4 | result = [] 5 | for i in range(0, len(li), n): 6 | result.append(li[i:i+n]) 7 | 8 | return result 9 | 10 | def split_b(li, n): 11 | return [li[i:i+n] for i in range(0, len(li), n)] 12 | 13 | if __name__ == '__main__': 14 | # simple tests 15 | li = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 16 | if split_a(li, 3) != [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]: 17 | print('Failed') 18 | if split_a(li, 4) != [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]]: 19 | print('Failed') 20 | if split_a(li, 1) != [[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]]: 21 | print('Failed') 22 | 23 | if split_b(li, 3) != [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]: 24 | print('Failed') 25 | if split_b(li, 4) != [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]]: 26 | print('Failed') 27 | if split_b(li, 1) != [[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]]: 28 | print('Failed') 29 | -------------------------------------------------------------------------------- /ch04ex/ch04ex4.3_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def f(li): 4 | result = [] 5 | for i, e in enumerate(li): 6 | result.append(e+i) 7 | 8 | return result 9 | 10 | if __name__ == '__main__': 11 | # simple tests 12 | li = [8, 4, 1, 7] 13 | if f(li) != [8, 5, 3, 10]: 14 | print('Failed') 15 | 16 | li = [10, 11, 12, 13] 17 | if f(li) != [10, 12, 14, 16]: 18 | print('Failed') 19 | 20 | -------------------------------------------------------------------------------- /ch04ex/ch04ex4.4_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | s = 'abcde' 4 | print(s) 5 | 6 | sr0 = ''.join(reversed(s)) 7 | print(sr0) # edcba, ok 8 | 9 | sr1 = s[::-1] 10 | print(sr1) # edcba, ok 11 | 12 | sr2 = s[-1:0:-1] 13 | print(sr2) # edcb, not ok 14 | 15 | sr3 = s[-1::-1] 16 | print(sr3) # edcba, ok 17 | 18 | 19 | -------------------------------------------------------------------------------- /ch04ex/ch04ex4.5_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | data = [('John', 40, 174, 65), ('Amy', 28, 165, 44), ('Jessie', 32, 158, 45)] 4 | 5 | data_sorted = sorted(data, key=lambda x: x[1]) 6 | 7 | print(data_sorted) 8 | 9 | -------------------------------------------------------------------------------- /ch04ex/ch04ex4.6_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def cumulative_product(iterable, start=1): 4 | result = [] 5 | acc = start 6 | for x in iterable: 7 | acc *= x 8 | result.append(acc) 9 | return result 10 | 11 | # print(cumulative_product(range(1, 9+1))) 12 | -------------------------------------------------------------------------------- /ch04ex/ch04ex4.7_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # def group(iterable, size): 4 | # result = [] 5 | # li = list(iterable) 6 | # length = len(li) 7 | # for i in range(0, length, size): 8 | # result.append(li[i:i+size]) 9 | # return result 10 | 11 | def group(iterable, size): 12 | result = [] 13 | it = iter(iterable) 14 | while True: 15 | temp = [] 16 | try: 17 | for _ in range(size): 18 | temp.append(next(it)) 19 | result.append(temp) 20 | except StopIteration: 21 | if temp != []: 22 | result.append(temp) 23 | break 24 | return result 25 | 26 | 27 | if __name__ == '__main__': 28 | # simple tests 29 | li = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 30 | if group(li, 3) != [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]: 31 | print('Failed') 32 | if group(li, 4) != [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]]: 33 | print('Failed') 34 | if group(li, 1) != [[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]]: 35 | print('Failed') 36 | 37 | if group(li, 3) != [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]: 38 | print('Failed') 39 | if group(li, 4) != [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]]: 40 | print('Failed') 41 | if group(li, 1) != [[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]]: 42 | print('Failed') 43 | 44 | 45 | -------------------------------------------------------------------------------- /ch05/ch05_dict_invert.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | d = {'Amy': 45, 'Bob': 50, 'Cathy': 62, 'David': 45, 4 | 'Eason': 63, 'Fred': 78, 'George': 72, 'Helen': 82, 5 | 'Ivan': 100, 'Jason': 98, 'Kevin': 0, 'Laura': 100} 6 | 7 | d2 = {v:k for k,v in d.items()} 8 | 9 | d3 = {} 10 | for k, v in d.items(): 11 | r = v // 10 12 | if r not in d3: 13 | d3[r] = [] 14 | d3[r].append(k) 15 | print(d3) 16 | 17 | #### output: #### 18 | # {0: ['Kevin'], 4: ['David', 'Amy'], 5: ['Bob'], 6: ['Cathy', 'Eason'], 19 | # 7: ['Fred', 'George'], 8: ['Helen'], 9: ['Jason'], 10: ['Ivan', 'Laura']} 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ch05/ch05_dict_sort.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | d = {'Amy': (45, 60, 33), 'Bob': (50, 62, 78), 4 | 'Cathy': (62, 98, 87), 'David': (45, 22, 12), 5 | 'Eason': (63, 55, 71), 'Fred': (78, 79, 32)} 6 | 7 | for k in sorted(d.keys()): 8 | print(k, d[k]) 9 | 10 | def foo(item): 11 | return item[1][2] 12 | for item in sorted(d.items(), key=foo): 13 | print(item) 14 | 15 | def bar(item): 16 | return sum(item[1]) 17 | for item in sorted(d.items(), key=bar): 18 | print(item) 19 | 20 | 21 | -------------------------------------------------------------------------------- /ch05/ch05_powerset.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | #### powerset, all subsets of a set #### 4 | def powerset(s): 5 | li = list(s) 6 | ps = set() 7 | for n in range(0, 2**len(s)): 8 | sub = set() 9 | x = n 10 | for i in range(len(s)): 11 | if x & 0x1: 12 | sub.add(li[i]) 13 | x >>= 1 14 | ps.add(frozenset(sub)) 15 | return ps 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch05/ch05_prime_sieve.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | #### generate a set containing prime numbers from 2 to n #### 4 | def prime_sieve(n): 5 | primes = set(range(2, n+1)) 6 | for i in range(2, (n+1+1) // 2): 7 | if i in primes: 8 | m = 2 9 | while i*m <= n: 10 | primes.discard(i*m) 11 | m += 1 12 | return primes 13 | 14 | #### this is not a good algorithm to check prime numbers #### 15 | def is_prime(n): 16 | for i in range(2, n): 17 | if n % i == 0: 18 | return False 19 | return True 20 | 21 | 22 | -------------------------------------------------------------------------------- /ch05/ch05_symbol_table.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | a = 1 4 | b = 2 5 | c = 3 6 | 7 | def foo(x, y): 8 | a = 'aaa' 9 | b = 'bbb' 10 | print(locals()) 11 | 12 | print(globals()) 13 | print('*' * 10) 14 | foo(80, 91) 15 | -------------------------------------------------------------------------------- /ch05/ch05ex5.5.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | friends = [ 4 | {'first':'Amy', 'last':'Wallace', 'email':'plunk@service.com.ru'}, 5 | {'first':'John', 'last':'Dickson', 'email':'john@edu.com.tw'}, 6 | {'first':'Amy', 'last':'Obama', 'email':'amy@whitehouse.gov'}, 7 | {'first':'Bob', 'last':'Banks', 'email':'bob@service.com.ru'}, 8 | {'first':'Amy', 'last':'Southward', 'email':'amys@service.com.ru'}, 9 | {'first':'Bob', 'last':'Wilkson', 'email':'bobwilkson@service.com.ru'}] 10 | 11 | -------------------------------------------------------------------------------- /ch05/ch05ex5.6.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # I Have a Dream 4 | # Martin Luther King, Jr. 5 | # http://www.americanrhetoric.com/speeches/mlkihaveadream.htm 6 | speech = ( 7 | """I am happy to join with you today in what will go down in history as the greatest demonstration for freedom in the history of our nation. 8 | 9 | Five score years ago, a great American, in whose symbolic shadow we stand today, signed the Emancipation Proclamation. This momentous decree came as a great beacon light of hope to millions of Negro slaves who had been seared in the flames of withering injustice. It came as a joyous daybreak to end the long night of their captivity. 10 | 11 | But one hundred years later, the Negro still is not free. One hundred years later, the life of the Negro is still sadly crippled by the manacles of segregation and the chains of discrimination. One hundred years later, the Negro lives on a lonely island of poverty in the midst of a vast ocean of material prosperity. One hundred years later, the Negro is still languished in the corners of American society and finds himself an exile in his own land. And so we've come here today to dramatize a shameful condition. 12 | 13 | In a sense we've come to our nation's capital to cash a check. When the architects of our republic wrote the magnificent words of the Constitution and the Declaration of Independence, they were signing a promissory note to which every American was to fall heir. This note was a promise that all men, yes, black men as well as white men, would be guaranteed the "unalienable Rights" of "Life, Liberty and the pursuit of Happiness." It is obvious today that America has defaulted on this promissory note, insofar as her citizens of color are concerned. Instead of honoring this sacred obligation, America has given the Negro people a bad check, a check which has come back marked "insufficient funds." 14 | 15 | But we refuse to believe that the bank of justice is bankrupt. We refuse to believe that there are insufficient funds in the great vaults of opportunity of this nation. And so, we've come to cash this check, a check that will give us upon demand the riches of freedom and the security of justice. 16 | """) 17 | 18 | 19 | -------------------------------------------------------------------------------- /ch05/ch05ex5.7.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # date, name, fruit, number 4 | data = (""" 5 | 2014/05/06, Amy, apple, 50, 6 | 2014/05/06, Bob, banana, 35, 7 | 2014/05/06, Cathy, grape, 40, 8 | 2014/05/07, Amy, apple, 42, 9 | 2014/05/07, Cathy, banana, 30, 10 | 2014/05/07, David, banana, 33, 11 | 2014/05/07, Bob, grape, 44, 12 | 2014/05/08, Amy, apple, 55, 13 | 2014/05/08, Bob, grape, 56, 14 | 2014/05/08, David, banana, 51, 15 | 2014/05/10, David, grape, 25, 16 | 2014/05/10, Cathy, grape, 26, 17 | 2014/05/10, David, banana, 51, 18 | 2014/05/10, Amy, grape, 23, 19 | 2014/05/10, David, apple, 11, 20 | """) 21 | 22 | # fruit : price 23 | prices = {'apple': 30, 'banana': 22, 'grape': 25} 24 | 25 | -------------------------------------------------------------------------------- /ch05ex/ch05ex5.1_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | d = {1: 'January', 2: 'February', 3: 'March', 4 | 4: 'April', 5: 'May', 6: 'June', 5 | 7: 'July', 8: 'August', 9: 'September', 6 | 10: 'October', 11: 'November', 12: 'December'} 7 | 8 | print(d[9]) 9 | -------------------------------------------------------------------------------- /ch05ex/ch05ex5.2_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | stock = { 4 | 'Apple': 655.95, 'IBM': 202.13, 'HP': 45.51, 'Facebook': 12.11, 5 | 'Intel': 40.51, 'Atmel': 10.23, 'Amazon': 305.35, 'Google': 535.81 6 | } 7 | 8 | stock_new0 = {} 9 | for k, v in stock.items(): 10 | if v >= 100: 11 | stock_new0[k] = v 12 | 13 | print(stock_new0) 14 | 15 | 16 | stock_new1 = {k: v for k, v in stock.items() if v >= 100} 17 | 18 | print(stock_new1) 19 | 20 | 21 | -------------------------------------------------------------------------------- /ch05ex/ch05ex5.3_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def caesar_dict(n): 4 | alphabet_lower = 'abcdefghijklmnopqrstuvwxyz' 5 | alphabet_upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 6 | 7 | result = {} 8 | for i, e in enumerate(alphabet_lower): 9 | i = (i + n) % len(alphabet_lower) 10 | result[e] = alphabet_lower[i] 11 | 12 | for i, e in enumerate(alphabet_upper): 13 | i = (i + n) % len(alphabet_upper) 14 | result[e] = alphabet_upper[i] 15 | 16 | return result 17 | 18 | 19 | if __name__ == '__main__': 20 | print(caesar_dict(13)) 21 | -------------------------------------------------------------------------------- /ch05ex/ch05ex5.5_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | friends = [ 4 | {'first':'Amy', 'last':'Wallace', 'email':'plunk@service.com.ru'}, 5 | {'first':'John', 'last':'Dickson', 'email':'john@edu.com.tw'}, 6 | {'first':'Amy', 'last':'Obama', 'email':'amy@whitehouse.gov'}, 7 | {'first':'Bob', 'last':'Banks', 'email':'bob@service.com.ru'}, 8 | {'first':'Amy', 'last':'Southward', 'email':'amys@service.com.ru'}, 9 | {'first':'Bob', 'last':'Wilkson', 'email':'bobwilkson@service.com.ru'}] 10 | 11 | def key_func(x): 12 | return x['first'] + ' ' + x['last'] 13 | friends_sorted = sorted(friends, key=key_func) 14 | 15 | print(friends_sorted) 16 | 17 | -------------------------------------------------------------------------------- /ch05ex/ch05ex5.6_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from __future__ import print_function 4 | 5 | # I Have a Dream 6 | # Martin Luther King, Jr. 7 | # http://www.americanrhetoric.com/speeches/mlkihaveadream.htm 8 | speech = ( 9 | """I am happy to join with you today in what will go down in history as the greatest demonstration for freedom in the history of our nation. 10 | 11 | Five score years ago, a great American, in whose symbolic shadow we stand today, signed the Emancipation Proclamation. This momentous decree came as a great beacon light of hope to millions of Negro slaves who had been seared in the flames of withering injustice. It came as a joyous daybreak to end the long night of their captivity. 12 | 13 | But one hundred years later, the Negro still is not free. One hundred years later, the life of the Negro is still sadly crippled by the manacles of segregation and the chains of discrimination. One hundred years later, the Negro lives on a lonely island of poverty in the midst of a vast ocean of material prosperity. One hundred years later, the Negro is still languished in the corners of American society and finds himself an exile in his own land. And so we've come here today to dramatize a shameful condition. 14 | 15 | In a sense we've come to our nation's capital to cash a check. When the architects of our republic wrote the magnificent words of the Constitution and the Declaration of Independence, they were signing a promissory note to which every American was to fall heir. This note was a promise that all men, yes, black men as well as white men, would be guaranteed the "unalienable Rights" of "Life, Liberty and the pursuit of Happiness." It is obvious today that America has defaulted on this promissory note, insofar as her citizens of color are concerned. Instead of honoring this sacred obligation, America has given the Negro people a bad check, a check which has come back marked "insufficient funds." 16 | 17 | But we refuse to believe that the bank of justice is bankrupt. We refuse to believe that there are insufficient funds in the great vaults of opportunity of this nation. And so, we've come to cash this check, a check that will give us upon demand the riches of freedom and the security of justice. 18 | """) 19 | 20 | import string 21 | from collections import defaultdict 22 | 23 | d = defaultdict(int) 24 | 25 | for w in speech.split(): 26 | w2 = w.strip(string.punctuation + string.whitespace).lower() 27 | d[w2] += 1 28 | 29 | print('Totally there are %d words.' % len(d)) 30 | 31 | data = [] 32 | for k, v in d.items(): 33 | data.append((k, v)) 34 | 35 | data_sorted = sorted(data, key=lambda x: x[1]) 36 | 37 | print('Top 5 least frequent words: ') 38 | for i in range(5): 39 | print(data_sorted[i]) 40 | 41 | data_sorted2 = list(reversed(data_sorted)) 42 | 43 | print('Top 5 most frequent words: ') 44 | for i in range(5): 45 | print(data_sorted2[i]) 46 | -------------------------------------------------------------------------------- /ch05ex/ch05ex5.8_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def main(words): 4 | d = {} 5 | for w in words: 6 | ws = ''.join(sorted(w)) ## not use set or hash 7 | if ws not in d: 8 | d[ws] = [w] 9 | else: 10 | d[ws].append(w) 11 | return list(d.values()) 12 | 13 | data = ['eat', 'ate', 'done', 'tea', 14 | 'opus', 'soup', 'node', 'quick'] 15 | print(main(data)) 16 | 17 | # [['eat', 'ate', 'tea'], ['done', 'node'], ['opus', 'soup'], ['quick']] 18 | 19 | -------------------------------------------------------------------------------- /ch06/ch06_8queen_basic.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def queen(n): 4 | answers = [] 5 | 6 | def is_safe(ans, col): 7 | for i, c in enumerate(ans): 8 | if len(ans)-i == abs(c-col): 9 | return False 10 | return True 11 | 12 | def sub(ans, n): 13 | if len(ans) == n: 14 | answers.append(ans) 15 | else: 16 | for col in range(n): 17 | if col not in ans and is_safe(ans, col): 18 | sub(ans + (col,), n) 19 | 20 | sub((), n) 21 | return answers 22 | -------------------------------------------------------------------------------- /ch06/ch06_8queen_hettingers.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Raymond Hettingers 4 | # http://code.activestate.com/recipes/576647/ 5 | from itertools import permutations 6 | 7 | def queen(n): 8 | answers = [] 9 | cols = range(n) 10 | for ans in permutations(cols): 11 | if (n == 12 | len(set([ans[i]+i for i in cols])) == 13 | len(set([ans[i]-i for i in cols]))): 14 | answers.append(ans) 15 | return answers 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch06/ch06_8queen_hettingers_gf.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Raymond Hettingers 4 | # http://code.activestate.com/recipes/576647/ 5 | from itertools import permutations 6 | 7 | def queen_gf(n): 8 | cols = range(n) 9 | for ans in permutations(cols): 10 | if (n == len(set(ans[i]+i for i in cols)) == 11 | len(set(ans[i]-i for i in cols))): 12 | yield ans 13 | -------------------------------------------------------------------------------- /ch06/ch06_8queen_howell.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Steve Howell 4 | # http://wiki.python.org/moin/SimplePrograms 5 | 6 | def queen(n): 7 | answers = [()] 8 | 9 | def under_attack(col, ans): 10 | return (col in ans or 11 | any([abs(col - x) == len(ans)-i 12 | for i,x in enumerate(ans)])) 13 | 14 | for row in range(n): 15 | answers = [ans + (col,) 16 | for ans in answers 17 | for col in range(n) 18 | if not under_attack(col, ans)] 19 | return answers 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ch06/ch06_8queen_test.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import ch06_8queen_hettingers as het 4 | import ch06_8queen_howell as how 5 | import ch06_8queen_basic as ba 6 | import ch06_8queen_hettingers_gf as het_gf 7 | 8 | n = 8 9 | 10 | het_answers = het.queen(n) 11 | print(len(het_answers)) 12 | print(het_answers) 13 | 14 | how_answers = how.queen(n) 15 | # for answer in answers: 16 | # print(list(enumerate(answer, start=1))) 17 | #print(answer) 18 | 19 | print(len(how_answers)) 20 | print(how_answers) 21 | 22 | ba_answers = ba.queen(n) 23 | print(len(ba_answers)) 24 | print(ba_answers) 25 | 26 | queen_het_g = het_gf.queen_gf(n) 27 | het_g_answers = [x for x in queen_het_g] 28 | 29 | #if set(iter(het_answers)) == set(iter(how_answers)): 30 | if set(het_answers) == set(how_answers) == set(ba_answers) == set(het_g_answers): 31 | print('yes') 32 | else: 33 | print('no') 34 | 35 | -------------------------------------------------------------------------------- /ch06/ch06_counter.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # not work 4 | # def counter(n): 5 | # def bar(x): 6 | # n += x 7 | # return n 8 | # return bar 9 | 10 | def counter(n): 11 | def bar(x): 12 | nonlocal n 13 | n += x 14 | return n 15 | return bar 16 | 17 | c0 = counter(0) 18 | c100 = counter(100) 19 | print(c0(1)) 20 | print(c100(10)) 21 | print(c0(1)) 22 | print(c0(3)) 23 | print(c100(20)) 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /ch06/ch06_env.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | def fact(n): 5 | if n <= 1: 6 | return n 7 | else: 8 | return n * fact(n-1) 9 | 10 | print(fact(3)) 11 | 12 | def counter(n): 13 | li = [n] 14 | def bar(x): 15 | li[0] += x 16 | return li[0] 17 | return bar 18 | 19 | c0 = counter(0) 20 | c100 = counter(100) 21 | print(c0(1)) 22 | print(c100(10)) 23 | print(c0(1)) 24 | print(c0(3)) 25 | print(c100(20)) 26 | 27 | 28 | -------------------------------------------------------------------------------- /ch06/ch06_fact.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def fact_i(n): 4 | result = 1 5 | for i in range(1, n+1): 6 | result *= i 7 | return result 8 | #### 9 | def fact_r(n): 10 | if n == 1 or n == 0: 11 | return 1 12 | else: 13 | return n * fact_r(n-1) 14 | 15 | if __name__ == '__main__': 16 | for n in range(10): 17 | fi = fact_i(n) 18 | fr = fact_r(n) 19 | if fi != fr: 20 | print('error: %d, %d, %d' % (n, fi, fr)) -------------------------------------------------------------------------------- /ch06/ch06_fib.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def fib_r(n): 4 | if n == 0 or n == 1: 5 | return n 6 | else: 7 | return fib_r(n-1) + fib_r(n-2) 8 | #### 9 | def fib_i(n): 10 | a, b = 0, 1 11 | for i in range(n): 12 | a, b = b, a+b 13 | return a 14 | #### 15 | memo = {0: 0, 1: 1} 16 | def fib_m(n): 17 | if n not in memo: 18 | memo[n] = fib_m(n-1) + fib_m(n-2) 19 | return memo[n] 20 | 21 | for x in range(20): 22 | fr = fib_r(x) 23 | fi = fib_i(x) 24 | fm = fib_m(x) 25 | if fr != fi or fi != fm: 26 | print('error: fib(%d) %d %d %d' % (x, fr, fi, fm)) 27 | 28 | 29 | -------------------------------------------------------------------------------- /ch06/ch06_fib_gf.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def fib_gf(): 4 | a, b = 0, 1 5 | while True: 6 | yield a 7 | a, b = b, a+b 8 | fib_g = fib_gf() 9 | 10 | def fib_memo(): 11 | memo = {0: 0, 1: 1} 12 | def sub(n): 13 | if n not in memo: 14 | memo[n] = sub(n-1) + sub(n-2) 15 | return memo[n] 16 | return sub 17 | fib_m = fib_memo() 18 | 19 | for x in range(40): 20 | fg = next(fib_g) 21 | fm = fib_m(x) 22 | if fg != fm: 23 | print('error: fib(%d) %d %d' % (x, fg, fm)) 24 | 25 | -------------------------------------------------------------------------------- /ch06/ch06_fib_hf.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def fib_i(n): 4 | a, b = 0, 1 5 | for i in range(n): 6 | a, b = b, a+b 7 | return a 8 | #### 9 | def fib_memo(): 10 | memo = {0: 0, 1: 1} 11 | def sub(n): 12 | if n not in memo: 13 | memo[n] = sub(n-1) + sub(n-2) 14 | return memo[n] 15 | return sub 16 | fib_m = fib_memo() 17 | 18 | for x in range(30): 19 | fi = fib_i(x) 20 | fm = fib_m(x) 21 | if fi != fm: 22 | print('error: fib(%d) %d %d' % (x, fi, fm)) 23 | 24 | -------------------------------------------------------------------------------- /ch06/ch06_frange.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def frange_g(start, end=None, inc=None): 4 | if end is None: 5 | end = start 6 | start = 0.0 7 | if inc is None: 8 | inc = 0.1 9 | while True: 10 | if inc > 0 and start >= end: 11 | break 12 | elif inc < 0 and start <= end: 13 | break 14 | yield start 15 | start += inc 16 | 17 | for i in frange_g(0, -1, -0.1): 18 | print(i) 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /ch06/ch06_gcd.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def gcd_i(a, b): 4 | while b: 5 | a, b = b, a%b 6 | return a 7 | #### 8 | def gcd_r(a, b): 9 | if b == 0: 10 | return a 11 | else: 12 | return gcd_r(b, a%b) 13 | 14 | if __name__ == '__main__': 15 | for a in range(1, 100): 16 | for b in range(1, 100): 17 | x = gcd_i(a, b) 18 | y = gcd_r(a, b) 19 | if x != y: 20 | print('error: gcd(%d,%d), %d, %d' % (a, b, x, y)) -------------------------------------------------------------------------------- /ch06/ch06_generator_send.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def gf(): 4 | n = 0 5 | while True: 6 | from_send = yield n 7 | n += 1 if from_send is None else from_send 8 | 9 | g = gf() 10 | print(next(g)) 11 | print(g.send(3)) 12 | print(g.send(5)) 13 | print(next(g)) 14 | print(g.send(10)) 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ch06/ch06_hanoi.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def hanoi(n): 4 | steps = [] 5 | def sub(n, pfrom, pto, pbuf): 6 | if n == 1: 7 | steps.append((pfrom, pto)) 8 | else: 9 | sub(n-1, pfrom, pbuf, pto) 10 | steps.append((pfrom, pto)) 11 | sub(n-1, pbuf, pto, pfrom) 12 | sub(n, 'A', 'C', 'B') 13 | return steps 14 | 15 | steps = hanoi(3) 16 | print(steps) 17 | 18 | def simulate_hanoi(n, pfrom, pto, pbuf, steps): 19 | pillars = {pfrom: list(range(n)), pto: [], pbuf: []} 20 | for s in steps: 21 | disk = pillars[s[0]].pop() 22 | pillars[s[1]].append(disk) 23 | print(pillars[pfrom]) 24 | print(pillars[pto]) 25 | print(pillars[pbuf]) 26 | if (pillars[pfrom] == [] and 27 | pillars[pbuf] == [] and 28 | pillars[pto] == list(range(n))): 29 | return True 30 | else: 31 | return False 32 | 33 | print(simulate_hanoi(3, 'A', 'C', 'B', steps)) 34 | -------------------------------------------------------------------------------- /ch06/ch06_hf_sum.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def sum_number(start, end): 4 | result = 0 5 | while start <= end: 6 | result += start 7 | start += 1 8 | return result 9 | 10 | def sum_square(start, end): 11 | result = 0 12 | while start <= end: 13 | result += start**2 14 | start += 1 15 | return result 16 | 17 | # pi/8 18 | def sum_pi(start, end): 19 | result = 0 20 | while start <= end: 21 | result += 1.0 / (start * (start+2)) 22 | start += 4 23 | return result 24 | 25 | def sum_hf(item, start, next, end): 26 | result = 0 27 | while start <= end: 28 | result += item(start) 29 | start = next(start) 30 | return result 31 | 32 | 33 | def sum_number_r(start, end): 34 | if start > end: 35 | return 0 36 | else: 37 | return start + sum_number_r(start+1, end) 38 | def sum_square_r(start, end): 39 | if start > end: 40 | return 0 41 | else: 42 | return start**2 + sum_square_r(start+1, end) 43 | def sum_pi_r(start, end): 44 | if start > end: 45 | return 0 46 | else: 47 | return (1.0 / (start * (start+2))) + sum_pi_r(start+4, end) 48 | 49 | def sum_hf_r(item, start, next, end): 50 | if start > end: 51 | return 0 52 | else: 53 | return item(start) + sum_hf_r(item, next(start), next, end) 54 | 55 | if __name__ == '__main__': 56 | tests = [(0, 10), (100, 200), (2000, 2500)] 57 | for t in tests: 58 | fa = sum(range(t[0], t[1]+1)) 59 | fb = sum_number(t[0], t[1]) 60 | fc = sum_hf(lambda x: x, t[0], lambda i: i+1, t[1]) 61 | fd = sum_number_r(t[0], t[1]) 62 | fe = sum_hf_r(lambda x: x, t[0], lambda i: i+1, t[1]) 63 | if fa == fb == fc == fd == fe: 64 | print('pass') 65 | for t in tests: 66 | fa = sum([x**2 for x in range(t[0], t[1]+1)]) 67 | fb = sum_square(t[0], t[1]) 68 | fc = sum_hf(lambda x: x**2, t[0], lambda i: i+1, t[1]) 69 | fd = sum_square_r(t[0], t[1]) 70 | fe = sum_hf_r(lambda x: x**2, t[0], lambda i: i+1, t[1]) 71 | if fa == fb == fc == fd == fe: 72 | print('pass') 73 | for end in range(200, 205): 74 | print(sum_pi(1, end) * 8) 75 | print(sum_pi_r(1, end) * 8) 76 | print(sum_hf(lambda x: 1.0 / (x * (x+2)), 1, lambda i: i+4, end) * 8) 77 | print(sum_hf_r(lambda x: 1.0 / (x * (x+2)), 1, lambda i: i+4, end) * 8) 78 | print('---') 79 | 80 | 81 | -------------------------------------------------------------------------------- /ch06/ch06_int_from.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def int_from(n, inc=1): 4 | while True: 5 | yield n 6 | n += inc 7 | 8 | ix = int_from(1) 9 | iy = int_from(100, -2) 10 | 11 | for i in range(5): 12 | print(next(ix)) 13 | print(next(iy)) 14 | 15 | -------------------------------------------------------------------------------- /ch06/ch06_lambda_long.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | li = [30, 41, 52, 63] 4 | 5 | def sum(li): 6 | result = 0 7 | for x in li: 8 | result += x 9 | return result 10 | print(sum(li)) 11 | 12 | def sum(li): 13 | if not li: 14 | return 0 15 | else: 16 | return li[0] + sum(li[1:]) 17 | print(sum(li)) 18 | 19 | (lambda li: [print(x) for x in li])(li) 20 | 21 | print((lambda li: 22 | (lambda f, r, li: f(f, r, li)) 23 | (lambda f, r, li: f(f, r+li[0], li[1:]) if li else r, 0, li)) 24 | (li)) 25 | 26 | print((lambda li: 27 | (lambda f, r, i: f(f, r, i)) 28 | (lambda f, r, i: f(f, r+li[i], i+1) if i < len(li) else r, 0, 0)) 29 | (li)) 30 | 31 | -------------------------------------------------------------------------------- /ch06/ch06_lambda_sorted.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | li = [('apple', 25), ('orange', 10), ('fig', 12), ('apricot', 20)] 4 | 5 | def by_name(item): 6 | return item[0] 7 | def by_name_len(item): 8 | return len(item[0]) 9 | def by_value(item): 10 | return item[1] 11 | 12 | print(sorted(li, key=by_name)) 13 | print(sorted(li, key=by_name_len)) 14 | print(sorted(li, key=by_value)) 15 | 16 | #### #### 17 | #[('apple', 25), ('apricot', 20), ('fig', 12), ('orange', 10)] 18 | #[('fig', 12), ('apple', 25), ('orange', 10), ('apricot', 20)] 19 | #[('orange', 10), ('fig', 12), ('apricot', 20), ('apple', 25)] 20 | 21 | print(sorted(li, key=lambda item: item[0])) 22 | print(sorted(li, key=lambda item: len(item[0]))) 23 | print(sorted(li, key=lambda item: item[1])) 24 | 25 | -------------------------------------------------------------------------------- /ch06/ch06_multipliers.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def make_multipliers(): 4 | result = [] 5 | for i in range(3): 6 | def m(x): 7 | return i * x 8 | result.append(m) 9 | return result 10 | for m in make_multipliers(): 11 | print(m(5)) 12 | print('-' * 20) 13 | 14 | def make_multipliers(): 15 | result = [] 16 | for i in range(3): 17 | m = lambda x: i * x 18 | result.append(m) 19 | return result 20 | for m in make_multipliers(): 21 | print(m(5)) 22 | print('-' * 20) 23 | 24 | def make_multipliers(): 25 | return [lambda x: i*x for i in range(3)] 26 | for m in make_multipliers(): 27 | print(m(5)) 28 | print('-' * 20) 29 | 30 | def make_multipliers(): 31 | result = [] 32 | for i in range(3): 33 | m = lambda x, y=i: y * x 34 | result.append(m) 35 | return result 36 | for m in make_multipliers(): 37 | print(m(5)) 38 | print('-' * 20) 39 | 40 | for m in [lambda x, n=n: n*x for n in range(3)]: 41 | print(m(5)) 42 | print('-' * 20) 43 | -------------------------------------------------------------------------------- /ch06/ch06_mutable_default.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | ALPHA_DEFAULT = 1.0 4 | def color(red, green, blue, alpha=ALPHA_DEFAULT): 5 | # alpha = ... 6 | # ... 7 | print (red, green, blue, alpha) 8 | 9 | def foo(x, y=[]): 10 | y.append(x) 11 | print(y) 12 | 13 | foo(1) 14 | foo(2) 15 | foo(3) 16 | 17 | def foo(x, y=None): 18 | if y is None: 19 | y = [] 20 | y.append(x) 21 | print(y) 22 | 23 | foo(1) 24 | foo(2) 25 | foo(3, [90, 91]) -------------------------------------------------------------------------------- /ch06/ch06_perm.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from itertools import permutations 4 | p = permutations 5 | 6 | def perm(iterable, r=None): 7 | items = tuple(iterable) 8 | r = len(items) if r is None else r 9 | answers = [] 10 | def sub(items, k, p): 11 | if k == 0: 12 | answers.append(p) 13 | else: 14 | # for i in range(k): # wrong 15 | for i in range(len(items)): 16 | # sub(list_del(items, i), k-1, p+(items[i],)) 17 | sub(items[:i] + items[i+1:], k-1, p+(items[i],)) 18 | sub(items, r, ()) 19 | return answers 20 | 21 | if __name__ == '__main__': 22 | tests = (list(range(3)), ['a','b','c','d'], list(range(100, 106))) 23 | for t in tests: 24 | pa = list(p(t)) 25 | pb = perm(t) 26 | if set(pa) == set(pb): 27 | print('yes') 28 | else: 29 | print('no') 30 | for t in tests: 31 | for r in range(1, len(t)): 32 | pa = list(p(t, r)) 33 | pb = perm(t, r) 34 | if set(pa) == set(pb): 35 | print('yes') 36 | else: 37 | print('no') 38 | -------------------------------------------------------------------------------- /ch06/ch06_pi_cesaro.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from math import sqrt 4 | from random import randint 5 | 6 | def estimate_pi(n): 7 | N = 10**100 8 | def gcd(a, b): 9 | while b: 10 | a, b = b, a%b 11 | return a 12 | def montecarlo(n, experiment): 13 | passed = 0 14 | for i in range(n): 15 | if experiment(): 16 | passed += 1 17 | return float(passed) / n 18 | def cesaro(): 19 | return gcd(randint(1, N), randint(1, N)) == 1 20 | return sqrt(6.0 / montecarlo(n, cesaro)) 21 | 22 | if __name__ == '__main__': 23 | for i in range(10, 101, 10): 24 | print(estimate_pi(i)) 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /ch06/ch06_powerset.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def powerset(s): 4 | li = list(s) 5 | ps = set() 6 | for n in range(0, 2**len(s)): 7 | sub = set() 8 | x = n 9 | for i in range(len(s)): 10 | if x & 0x1: 11 | sub.add(li[i]) 12 | x >>= 1 13 | ps.add(frozenset(sub)) 14 | return ps 15 | #### 16 | 17 | def powerset_r(iterable): 18 | def set_add(ps, item): 19 | if len(ps) == 0: 20 | return [] 21 | else: 22 | return [ps[0] + [item]] + set_add(ps[1:], item) 23 | def sub(s): 24 | if len(s) == 1: 25 | return [s, []] 26 | else: 27 | ps = sub(s[1:]) 28 | return ps + set_add(ps, s[0]) 29 | return sub(list(iterable)) 30 | 31 | test = [1,2,3,4] 32 | print(powerset(test)) 33 | print(sorted(powerset_r(test), key=lambda x: len(x))) 34 | 35 | -------------------------------------------------------------------------------- /ch06/ch06_range.py: -------------------------------------------------------------------------------- 1 | 2 | def range_g(start, end=None, inc=None): 3 | if end is None: 4 | end = start 5 | start = 0 6 | if inc is None: 7 | inc = 1 8 | while True: 9 | if inc > 0 and start >= end: 10 | break 11 | elif inc < 0 and start <= end: 12 | break 13 | yield start 14 | start += inc 15 | 16 | def range2x(start, end=None, inc=None): 17 | if end is None: 18 | end = start 19 | start = 0 20 | if inc is None: 21 | inc = 1 22 | result = [] 23 | while True: 24 | if inc > 0 and start >= end: 25 | break 26 | elif inc < 0 and start <= end: 27 | break 28 | result.append(start) 29 | start += inc 30 | return result 31 | 32 | # not work 33 | def range3x(start, end=None, inc=None): 34 | if end is None: 35 | end = start 36 | start = 0 37 | if inc is None: 38 | inc = 1 39 | s = [start] 40 | def sub(): 41 | while s[0] < end: 42 | if inc > 0 and s[0] >= end: 43 | break 44 | elif inc < 0 and s[0] <= end: 45 | break 46 | s[0] += inc 47 | return (s[0] - inc) 48 | return sub 49 | 50 | if __name__ == '__main__': 51 | tests = (0, 10, 30, -100, 1, 2) 52 | for a in tests: 53 | x0 = list(range(a)) 54 | x1 = range2x(a) 55 | x2 = list(range_g(a)) 56 | if x0 != x1 or x0 != x2: 57 | print('error') 58 | tests = ((0, 10), (10, 30), (-100, 20), (1, 2)) 59 | for a,b in tests: 60 | x0 = list(range(a, b)) 61 | x1 = range2x(a, b) 62 | x2 = list(range_g(a, b)) 63 | if x0 != x1 or x0 != x2: 64 | print('error') 65 | tests = ((0, 10, 1), (10, 30, 2), (-10, -20, -1), (0, -31, -3)) 66 | for a,b,c in tests: 67 | x0 = list(range(a, b, c)) 68 | x1 = range2x(a, b, c) 69 | x2 = list(range_g(a, b, c)) 70 | if x0 != x1 or x0 != x2: 71 | print('error %s %s' % (x0, x1)) 72 | # xx = range3x(10, -3, -1) 73 | # for i in range(20): 74 | # print(xx()) 75 | 76 | 77 | -------------------------------------------------------------------------------- /ch06/ch06_yield_from.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def fg(n): 4 | for i in range(1, n): 5 | yield i 6 | for i in range(-1, -n, -1): 7 | yield i 8 | 9 | print(list(fg(5))) 10 | 11 | def sub_fg(n): 12 | i = 1 if n > 0 else -1 13 | inc = i 14 | while i != n: 15 | yield i 16 | i += inc 17 | def fg(n): 18 | yield from sub_fg(n) 19 | yield from sub_fg(-n) 20 | 21 | print(list(fg(5))) 22 | 23 | def fg(n): 24 | yield from range(1, n) 25 | yield from range(-1, -n, -1) 26 | 27 | print(list(fg(5))) 28 | -------------------------------------------------------------------------------- /ch06ex/ch06ex6.12_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def coin_sum_r(total, coins): 4 | if len(coins) == 1: 5 | return 1 6 | elif total < coins[-1]: 7 | return coin_sum_r(total, coins[:-1]) 8 | else: 9 | return coin_sum_r(total-coins[-1], coins) + coin_sum_r(total, coins[:-1]) 10 | 11 | coins_a = (1, 5, 10, 25) 12 | print(coin_sum_r(100, coins_a)) # 242 13 | 14 | coins_england = (1, 2, 5, 10, 20, 50, 100, 200) 15 | print(coin_sum_r(200, coins_england)) # 73682 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /ch06ex/ch06ex6.15_answer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 4 | def prime_gf(): 5 | primes = [2] 6 | def is_prime(n): 7 | for i in primes: 8 | if n % i == 0: 9 | return False 10 | return True 11 | while True: 12 | p = primes[-1] 13 | yield p 14 | while True: 15 | p += 1 16 | if is_prime(p): 17 | primes.append(p) 18 | break 19 | prime_f = prime_gf() 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ch07/ch07_big5_uao.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | from __future__ import print_function 4 | import codecs 5 | # import big5uao 6 | import big5uao_3 7 | 8 | # a煊b喆c凜凛 9 | test = b'a\x95\x4Fb\x95\xEDc\xBB\xFE\x81\x60' 10 | 11 | dec = codecs.getdecoder('big5uao') 12 | enc = codecs.getencoder('big5uao') 13 | 14 | d0, d1 = dec(test) 15 | print(d0, d1) 16 | 17 | test = b'\x95\x4F\x80\x80' 18 | d0, d1 = dec(test, errors='replace') 19 | print(d0, d1) 20 | 21 | # 應是Big5+UAO的 0xa7 0x41 0xa6 0x6e 22 | s = '你好' # 2.x u'你好' 3.x '你好' 23 | 24 | e = enc(s) 25 | for b in e[0]: 26 | print('%x ' % b, end='') 27 | print(e[1]) 28 | 29 | s = '\uEEEE\uDDDD' 30 | e = enc(s, errors='strict') 31 | for b in e[0]: 32 | print('%x ' % b, end='') 33 | print(e[1]) 34 | -------------------------------------------------------------------------------- /ch07/ch07_big5_uao_test.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | from __future__ import print_function 4 | import codecs 5 | import big5ext 6 | import big5uao 7 | 8 | def getregentry(codec_name): 9 | if codec_name == 'big5ext': 10 | return codecs.CodecInfo( 11 | name='big5ext', 12 | encode=big5ext.Codec().encode, 13 | decode=big5ext.Codec().decode, 14 | incrementalencoder=big5ext.IncrementalEncoder, 15 | incrementaldecoder=big5ext.IncrementalDecoder, 16 | streamreader=big5ext.StreamReader, 17 | streamwriter=big5ext.StreamWriter, 18 | ) 19 | elif codec_name == 'big5uao': 20 | return codecs.CodecInfo( 21 | name='big5uao', 22 | encode=big5uao.Codec().encode, 23 | decode=big5uao.Codec().decode, 24 | incrementalencoder=big5uao.IncrementalEncoder, 25 | incrementaldecoder=big5uao.IncrementalDecoder, 26 | streamreader=big5uao.StreamReader, 27 | streamwriter=big5uao.StreamWriter, 28 | ) 29 | 30 | codecs.register(getregentry) 31 | 32 | ################# 33 | print(codecs.lookup('big5uao')) 34 | print(codecs.lookup('big5ext')) 35 | 36 | 37 | test = b'a\x95\x4Fb\x95\xEDc\xBB\xFE\x81\x60' 38 | print(len(test)) 39 | dec1 = codecs.getdecoder('big5ext') 40 | dec2 = codecs.getdecoder('big5uao') 41 | 42 | d1 = dec1(test) 43 | d2 = dec2(test) 44 | print(d1[0], d1[1]) 45 | print(d2[0], d2[1]) 46 | 47 | for b1 in range(0x81, 0xFE+1): 48 | for b2 in range(0x40, 0x7E+1): 49 | big5 = chr(b1) + chr(b2) 50 | d1 = dec1(big5) 51 | d2 = dec2(big5) 52 | if d1[0] != d2[0]: 53 | print(d1, d2) 54 | for b2 in range(0xA1, 0xFE+1): 55 | big5 = chr(b1) + chr(b2) 56 | d1 = dec1(big5) 57 | d2 = dec2(big5) 58 | if d1[0] != d2[0]: 59 | print(d1, d2) 60 | 61 | ss = u'你好' # a7 41 a6 6e 62 | enc2 = codecs.getencoder('big5uao') 63 | e2 = enc2(ss) 64 | for b in e2[0]: 65 | print('%x ' % ord(b), end='') 66 | print(e2[1]) 67 | 68 | -------------------------------------------------------------------------------- /ch07/ch07_caesar.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | from io import open 4 | import string 5 | 6 | # 回傳轉換表,shift是偏移量,可正可負,encrypt代表要加密還是解密 7 | def caesar_table(shift, encrypt=True): 8 | lowers = string.ascii_lowercase # 小寫英文字母 9 | uppers = string.ascii_uppercase # 大寫英文字母 10 | lowers_new = lowers[shift:] + lowers[:shift] 11 | uppers_new = uppers[shift:] + uppers[:shift] 12 | # 若是2.x版,請把str.maketrans改成string.maketrans 13 | # maketrans的功能是製作轉換表,供str.translate使用 14 | if encrypt: 15 | return str.maketrans(lowers+uppers, lowers_new+uppers_new) 16 | else: 17 | return str.maketrans(lowers_new+uppers_new, lowers+uppers) 18 | # 凱撒密碼,shift是偏移量,encrypt代表要加密還是解密 19 | def caesar(file_in, file_out, shift, encrypt=True): 20 | table = caesar_table(shift, encrypt) 21 | with open(file_in, mode='r', encoding='ascii') as fin: 22 | with open(file_out, mode='w', encoding='ascii') as fout: 23 | for line in fin: 24 | # 呼叫translate,傳入轉換表 25 | fout.write(line.translate(table)) 26 | 27 | caesar('test.txt', 'encrypt.txt', 3, True) 28 | caesar('encrypt.txt', 'decrypt.txt', 3, False) 29 | 30 | -------------------------------------------------------------------------------- /ch07/ch07_csv.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | # Python 3.x 4 | import csv 5 | 6 | with open('csv.txt', 'r', encoding='utf-8') as fin: 7 | with open('csv_out.txt', 'w', encoding='utf-8') as fout: 8 | csvreader = csv.reader(fin, delimiter=',') 9 | csvwriter = csv.writer(fout, delimiter=' ') 10 | header = next(csvreader) 11 | csvwriter.writerow(header) 12 | for row in csvreader: 13 | row[0] = row[0].replace('/', '-') 14 | row[-1] += '%' 15 | print(','.join(row)) 16 | csvwriter.writerow(row) 17 | 18 | 19 | -------------------------------------------------------------------------------- /ch07/ch07_enc_change.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | from io import open 4 | 5 | def enc_change(file_in, enc_in, file_out, enc_out): 6 | with open(file_in, mode='r', encoding=enc_in) as fin: 7 | with open(file_out, mode='w', encoding=enc_out) as fout: 8 | for line in fin: 9 | fout.write(line) 10 | 11 | 12 | 13 | enc_change('test_big5.txt', 'big5', 'test_utf8.txt', 'utf8') 14 | -------------------------------------------------------------------------------- /ch07/ch07_json.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | from __future__ import print_function 4 | from io import open 5 | import json 6 | 7 | with open('json.txt', 'r', encoding='ascii') as fin: 8 | data = json.loads(fin.read()) 9 | print(data['menu']['hello']) 10 | print(data['menu']['flag']) 11 | print(data['menu']['count']) 12 | with open('json_out1.txt', 'w', encoding='ascii') as fout: 13 | fout.write(json.dumps(data, separators=(',', ':'))) 14 | with open('json_out2.txt', 'w', encoding='ascii') as fout: 15 | fout.write(json.dumps(data, sort_keys=True, 16 | indent=4, separators=(',', ':'))) 17 | 18 | -------------------------------------------------------------------------------- /ch07/ch07_line_count.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | from io import open 4 | import os 5 | import os.path 6 | 7 | # 計算文字檔有幾行 8 | def line_count(filepath, enc='utf8'): 9 | count = 0 10 | with open(filepath, mode='r', encoding=enc) as fin: 11 | for line in fin: 12 | if line.strip(): # 空白行不算 13 | count += 1 14 | return count 15 | # 判斷文字編碼系統,從檔案開頭的前幾個位元組 16 | def what_encoding_by_head(filepath): 17 | enc = None 18 | with open(filepath, 'rb') as fin: 19 | data = fin.read(3) 20 | if len(data) == 3: # Windows會在UTF-8檔案開頭加上BOM 21 | if data[0] == 0xEF and data[1] == 0xBB and data[2] == 0xBF: 22 | enc = 'utf8' 23 | if len(data) >= 2: # UTF-16 BE與LE 24 | if data[0] == 0xFE and data[1] == 0xFF: 25 | enc = 'UTF-16BE' 26 | elif data[0] == 0xFF and data[1] == 0xFE: 27 | enc = 'UTF-16LE' 28 | return enc 29 | # 判斷文字編碼系統,從第一行或第二行,若含有'coding'字樣的話 30 | def what_encoding_by_mark(filepath): 31 | enc = 'ascii' # 預設為ASCII 32 | mark = 'coding' # 編碼標記字樣 33 | def extract_enc(line): 34 | chars = ' :=-*' # 編碼標記字樣周圍無用的字元 35 | return line.strip().lstrip(chars).rstrip(chars) 36 | with open(filepath, mode='r', encoding=enc, errors='ignore') as fin: 37 | for i in range(2): # 只讀兩行 38 | line = fin.readline() 39 | idx = line.find(mark) # 若含有編碼標記字樣 40 | if idx != -1: 41 | enc = extract_enc(line[idx+len(mark):]) 42 | break 43 | return enc 44 | # 判斷文字編碼系統 45 | def what_encoding(filepath): 46 | return what_encoding_by_head(filepath) or what_encoding_by_mark(filepath) 47 | 48 | lc_total = 0 # 總行數 49 | file_count = 0 # 被計算行數的檔案個數 50 | for p in os.listdir('.'): # 2.x版應使用u'.' 51 | if os.path.isfile(p) and p[-3:] == '.py': 52 | try: 53 | enc = what_encoding(p) 54 | lc = line_count(p, enc) 55 | lc_total += lc 56 | file_count += 1 57 | print(p, enc, lc) 58 | except: 59 | print(p, "can't count lines") 60 | 61 | print('%d .py files totally have %d lines ' % (file_count, lc_total)) 62 | 63 | -------------------------------------------------------------------------------- /ch07/ch07_line_count_test/a no.py: -------------------------------------------------------------------------------- 1 | a 2 | b 3 | c 4 | -------------------------------------------------------------------------------- /ch07/ch07_line_count_test/aaa big5.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch07/ch07_line_count_test/aaa big5.py -------------------------------------------------------------------------------- /ch07/ch07_line_count_test/aaa utf16be.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch07/ch07_line_count_test/aaa utf16be.py -------------------------------------------------------------------------------- /ch07/ch07_line_count_test/empty.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch07/ch07_line_count_test/empty.py -------------------------------------------------------------------------------- /ch07/ch07_line_count_test/test ascii.py: -------------------------------------------------------------------------------- 1 | 2 | fin = open('test.txt') 3 | print(fin.readline()) 4 | for line in fin: 5 | print(line) 6 | fin.close() 7 | 8 | #### 9 | fin = open('test.txt') 10 | fout = open('testw.txt', 'w') 11 | for line in fin: 12 | print(line) 13 | fout.write(line) 14 | fin.close() 15 | fout.close() 16 | 17 | #### 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ch07/ch07_line_count_test/wrong utf8.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch07/ch07_line_count_test/wrong utf8.py -------------------------------------------------------------------------------- /ch07/ch07_line_number.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | from io import open 4 | 5 | # 計算文字檔有幾行 6 | def line_count(filepath, enc='utf8'): 7 | count = 0 8 | with open(filepath, mode='r', encoding=enc) as fin: 9 | for line in fin: 10 | count += 1 11 | return count 12 | 13 | # 計算文字檔有幾行,另一種作法 14 | def line_count_2(filepath, enc='utf8'): 15 | return sum(1 for line in open(filepath, mode='r', encoding=enc)) 16 | 17 | # 為文字檔加上行號,參數:輸入檔路徑、輸出檔路徑、編碼 18 | def line_number(fin_path, fout_path, enc='utf8'): 19 | lc = line_count(fin_path) # 知道行數才能對齊 20 | lcw = len(str(lc)) # 該佔幾格 21 | with open(fin_path, mode='r', encoding=enc) as fin: 22 | with open(fout_path, mode='w', encoding=enc) as fout: 23 | for i, line in enumerate(fin): 24 | fout.write(u'{:0{width}d} {}'.format(i+1, line, width=lcw)) 25 | 26 | -------------------------------------------------------------------------------- /ch07/ch07_pickle.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | 4 | from __future__ import print_function 5 | from io import open 6 | import pickle 7 | 8 | data = {'a': [1, 2, 3, 4], 9 | 'John': 'abcdef', 10 | 334455: 778899, 11 | 'default': None} 12 | 13 | with open('pickle.bin', 'wb') as fout: 14 | pickle.dump(data, fout, 0) 15 | 16 | with open('pickle.bin', 'rb') as fin: 17 | d = pickle.load(fin) 18 | print(d['John']) 19 | print(d[334455]) 20 | 21 | 22 | -------------------------------------------------------------------------------- /ch07/ch07_print_self.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | with open('ch07_print_self.py') as fin: 4 | for line in fin: 5 | print(line) 6 | -------------------------------------------------------------------------------- /ch07/ch07_print_self_big5.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch07/ch07_print_self_big5.py -------------------------------------------------------------------------------- /ch07/ch07_print_self_utf8.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | # 你好 4 | from __future__ import print_function 5 | from io import open 6 | 7 | print('你好Python') 8 | with open('ch07_print_self_utf8.py', encoding='utf8') as fin: 9 | for line in fin: 10 | print(line, end='') 11 | print('再見Python') 12 | -------------------------------------------------------------------------------- /ch07/ch07_redirect.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | from __future__ import print_function 4 | from io import open 5 | import sys 6 | 7 | with open('test.txt', 'w', encoding='utf-8') as fout: 8 | stdout_backup = sys.stdout 9 | sys.stdout = fout 10 | print(u'Hello Python') 11 | sys.stdout = stdout_backup 12 | 13 | -------------------------------------------------------------------------------- /ch07/ch07_redirect_stdin.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch07/ch07_redirect_stdin.py -------------------------------------------------------------------------------- /ch07/ch07_struct.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct { 4 | char a; 5 | unsigned long b; 6 | int c; 7 | float d; 8 | char e; 9 | double f; 10 | } Data; 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | Data d = {'a', 0x12AB34CD, 100, 3.4, 'b', 5.6}; 15 | FILE *fp = fopen("test.bin", "wb"); 16 | fwrite(&d, 1, sizeof(Data), fp); 17 | fclose(fp); 18 | return 0; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /ch07/ch07_struct.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | 4 | from __future__ import print_function 5 | from io import open 6 | import struct 7 | 8 | with open ('test.bin', 'rb') as fin: 9 | a = struct.unpack(' 2 | 3 | typedef struct { 4 | char a; 5 | unsigned long c; 6 | int b; 7 | float d; 8 | char e; 9 | double f; 10 | } Data; 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | printf("sizeof(char) = %d\n", sizeof(char)); 15 | printf("sizeof(int) = %d\n", sizeof(int)); 16 | printf("sizeof(unsigned long) = %d\n", sizeof(unsigned long)); 17 | printf("sizeof(float) = %d\n", sizeof(float)); 18 | printf("sizeof(double) = %d\n", sizeof(double)); 19 | printf("sizeof(Data) = %d\n", sizeof(Data)); 20 | return 0; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /ch07/ch07_test.py: -------------------------------------------------------------------------------- 1 | 2 | fin = open('test.txt') 3 | print(fin.readline()) 4 | for line in fin: 5 | print(line) 6 | fin.close() 7 | 8 | #### 9 | fin = open('test.txt') 10 | fout = open('testw.txt', 'w') 11 | for line in fin: 12 | print(line) 13 | fout.write(line) 14 | fin.close() 15 | fout.close() 16 | 17 | #### 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ch07/ch07_test_context.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from __future__ import print_function 4 | from io import open 5 | 6 | with open('test.txt') as fin: 7 | for line in fin: 8 | print(line, end='') 9 | 10 | #### 11 | with open('test.txt', 'r') as fin: 12 | with open('testw.txt', 'w') as fout: 13 | for line in fin: 14 | print(line, end='') 15 | fout.write(line) 16 | 17 | #### 18 | with open('test.txt', 'r') as fin, open('testw.txt', 'w') as fout: 19 | for line in fin: 20 | print(line, end='') 21 | fout.write(line) 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ch07/ch07ex7.1_answer.txt: -------------------------------------------------------------------------------- 1 | ch07ex7.1_testdata_0.txt,UTF-8 2 | ch07ex7.1_testdata_1.txt,ISO-8859-15 3 | ch07ex7.1_testdata_2.txt,Windows-1252 4 | 5 | -------------------------------------------------------------------------------- /ch07/ch07ex7.1_testdata_0.txt: -------------------------------------------------------------------------------- 1 | The symbol € is a euro sign. 2 | -------------------------------------------------------------------------------- /ch07/ch07ex7.1_testdata_1.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch07/ch07ex7.1_testdata_1.txt -------------------------------------------------------------------------------- /ch07/ch07ex7.1_testdata_2.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch07/ch07ex7.1_testdata_2.txt -------------------------------------------------------------------------------- /ch07/ch07ex7.2_answer.txt: -------------------------------------------------------------------------------- 1 | ch07ex7.2_testdata_0.txt,UTF-8 2 | ch07ex7.2_testdata_1.txt,Big5+UAO 3 | ch07ex7.2_testdata_2.txt,GBK 4 | 5 | -------------------------------------------------------------------------------- /ch07/ch07ex7.2_testdata_0.txt: -------------------------------------------------------------------------------- 1 | 你好PYTHON榮荣栄 2 | -------------------------------------------------------------------------------- /ch07/ch07ex7.2_testdata_1.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch07/ch07ex7.2_testdata_1.txt -------------------------------------------------------------------------------- /ch07/ch07ex7.2_testdata_2.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch07/ch07ex7.2_testdata_2.txt -------------------------------------------------------------------------------- /ch07/ch07ex7.3_testdata.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch07/ch07ex7.3_testdata.txt -------------------------------------------------------------------------------- /ch07/ch07ex7.4.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch07/ch07ex7.4.py -------------------------------------------------------------------------------- /ch07/ch07ex7.5_testdata.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 煊堃喆凜凛遙遥阪坂齊斉齐齋斎榮荣栄富冨樫堅島嶋崎﨑邊边辺絕绝對对対涉澀渋瑠鹽塩盐汙污汚櫻樱桜鐮镰鎌高髙癡痴劍剑剣龍龙竜氣气気單单単 4 | 5 | -------------------------------------------------------------------------------- /ch07/csv.txt: -------------------------------------------------------------------------------- 1 | date,time,temperature,humidity 2 | 2014/01/01,08:00,15.3,30 3 | 2014/01/02,11:00,23.5,40 4 | 2014/01/03,14:00,25.5,36 5 | 2014/01/04,15:00,22.1,33 6 | -------------------------------------------------------------------------------- /ch07/csv_out.txt: -------------------------------------------------------------------------------- 1 | date time temperature humidity 2 | 2014-01-01 08:00 15.3 30% 3 | 2014-01-02 11:00 23.5 40% 4 | 2014-01-03 14:00 25.5 36% 5 | 2014-01-04 15:00 22.1 33% 6 | -------------------------------------------------------------------------------- /ch07/i_have_a_dream.txt: -------------------------------------------------------------------------------- 1 | # I Have a Dream 2 | # Martin Luther King, Jr. 3 | # http://www.americanrhetoric.com/speeches/mlkihaveadream.htm 4 | 5 | I am happy to join with you today in what will go down in history as the greatest demonstration for freedom in the history of our nation. 6 | 7 | Five score years ago, a great American, in whose symbolic shadow we stand today, signed the Emancipation Proclamation. This momentous decree came as a great beacon light of hope to millions of Negro slaves who had been seared in the flames of withering injustice. It came as a joyous daybreak to end the long night of their captivity. 8 | 9 | But one hundred years later, the Negro still is not free. One hundred years later, the life of the Negro is still sadly crippled by the manacles of segregation and the chains of discrimination. One hundred years later, the Negro lives on a lonely island of poverty in the midst of a vast ocean of material prosperity. One hundred years later, the Negro is still languished in the corners of American society and finds himself an exile in his own land. And so we've come here today to dramatize a shameful condition. 10 | 11 | In a sense we've come to our nation's capital to cash a check. When the architects of our republic wrote the magnificent words of the Constitution and the Declaration of Independence, they were signing a promissory note to which every American was to fall heir. This note was a promise that all men, yes, black men as well as white men, would be guaranteed the "unalienable Rights" of "Life, Liberty and the pursuit of Happiness." It is obvious today that America has defaulted on this promissory note, insofar as her citizens of color are concerned. Instead of honoring this sacred obligation, America has given the Negro people a bad check, a check which has come back marked "insufficient funds." 12 | 13 | But we refuse to believe that the bank of justice is bankrupt. We refuse to believe that there are insufficient funds in the great vaults of opportunity of this nation. And so, we've come to cash this check, a check that will give us upon demand the riches of freedom and the security of justice. 14 | 15 | We have also come to this hallowed spot to remind America of the fierce urgency of Now. This is no time to engage in the luxury of cooling off or to take the tranquilizing drug of gradualism. Now is the time to make real the promises of democracy. Now is the time to rise from the dark and desolate valley of segregation to the sunlit path of racial justice. Now is the time to lift our nation from the quicksands of racial injustice to the solid rock of brotherhood. Now is the time to make justice a reality for all of God's children. 16 | 17 | It would be fatal for the nation to overlook the urgency of the moment. This sweltering summer of the Negro's legitimate discontent will not pass until there is an invigorating autumn of freedom and equality. Nineteen sixty-three is not an end, but a beginning. And those who hope that the Negro needed to blow off steam and will now be content will have a rude awakening if the nation returns to business as usual. And there will be neither rest nor tranquility in America until the Negro is granted his citizenship rights. The whirlwinds of revolt will continue to shake the foundations of our nation until the bright day of justice emerges. 18 | 19 | But there is something that I must say to my people, who stand on the warm threshold which leads into the palace of justice: In the process of gaining our rightful place, we must not be guilty of wrongful deeds. Let us not seek to satisfy our thirst for freedom by drinking from the cup of bitterness and hatred. We must forever conduct our struggle on the high plane of dignity and discipline. We must not allow our creative protest to degenerate into physical violence. Again and again, we must rise to the majestic heights of meeting physical force with soul force. 20 | 21 | The marvelous new militancy which has engulfed the Negro community must not lead us to a distrust of all white people, for many of our white brothers, as evidenced by their presence here today, have come to realize that their destiny is tied up with our destiny. And they have come to realize that their freedom is inextricably bound to our freedom. 22 | 23 | We cannot walk alone. 24 | 25 | And as we walk, we must make the pledge that we shall always march ahead. 26 | 27 | We cannot turn back. 28 | 29 | There are those who are asking the devotees of civil rights, "When will you be satisfied?" We can never be satisfied as long as the Negro is the victim of the unspeakable horrors of police brutality. We can never be satisfied as long as our bodies, heavy with the fatigue of travel, cannot gain lodging in the motels of the highways and the hotels of the cities. We cannot be satisfied as long as the negro's basic mobility is from a smaller ghetto to a larger one. We can never be satisfied as long as our children are stripped of their self-hood and robbed of their dignity by signs stating: "For Whites Only." We cannot be satisfied as long as a Negro in Mississippi cannot vote and a Negro in New York believes he has nothing for which to vote. No, no, we are not satisfied, and we will not be satisfied until "justice rolls down like waters, and righteousness like a mighty stream." 30 | 31 | I am not unmindful that some of you have come here out of great trials and tribulations. Some of you have come fresh from narrow jail cells. And some of you have come from areas where your quest -- quest for freedom left you battered by the storms of persecution and staggered by the winds of police brutality. You have been the veterans of creative suffering. Continue to work with the faith that unearned suffering is redemptive. Go back to Mississippi, go back to Alabama, go back to South Carolina, go back to Georgia, go back to Louisiana, go back to the slums and ghettos of our northern cities, knowing that somehow this situation can and will be changed. 32 | 33 | Let us not wallow in the valley of despair, I say to you today, my friends. 34 | 35 | And so even though we face the difficulties of today and tomorrow, I still have a dream. It is a dream deeply rooted in the American dream. 36 | 37 | I have a dream that one day this nation will rise up and live out the true meaning of its creed: "We hold these truths to be self-evident, that all men are created equal." 38 | 39 | I have a dream that one day on the red hills of Georgia, the sons of former slaves and the sons of former slave owners will be able to sit down together at the table of brotherhood. 40 | 41 | I have a dream that one day even the state of Mississippi, a state sweltering with the heat of injustice, sweltering with the heat of oppression, will be transformed into an oasis of freedom and justice. 42 | 43 | I have a dream that my four little children will one day live in a nation where they will not be judged by the color of their skin but by the content of their character. 44 | 45 | I have a dream today! 46 | 47 | I have a dream that one day, down in Alabama, with its vicious racists, with its governor having his lips dripping with the words of "interposition" and "nullification" -- one day right there in Alabama little black boys and black girls will be able to join hands with little white boys and white girls as sisters and brothers. 48 | 49 | I have a dream today! 50 | 51 | I have a dream that one day every valley shall be exalted, and every hill and mountain shall be made low, the rough places will be made plain, and the crooked places will be made straight; "and the glory of the Lord shall be revealed and all flesh shall see it together." 52 | 53 | This is our hope, and this is the faith that I go back to the South with. 54 | 55 | With this faith, we will be able to hew out of the mountain of despair a stone of hope. With this faith, we will be able to transform the jangling discords of our nation into a beautiful symphony of brotherhood. With this faith, we will be able to work together, to pray together, to struggle together, to go to jail together, to stand up for freedom together, knowing that we will be free one day. 56 | 57 | And this will be the day -- this will be the day when all of God's children will be able to sing with new meaning: 58 | 59 | My country 'tis of thee, sweet land of liberty, of thee I sing. 60 | 61 | Land where my fathers died, land of the Pilgrim's pride, 62 | 63 | From every mountainside, let freedom ring! 64 | 65 | And if America is to be a great nation, this must become true. 66 | 67 | And so let freedom ring from the prodigious hilltops of New Hampshire. 68 | 69 | Let freedom ring from the mighty mountains of New York. 70 | 71 | Let freedom ring from the heightening Alleghenies of Pennsylvania. 72 | 73 | Let freedom ring from the snow-capped Rockies of Colorado. 74 | 75 | Let freedom ring from the curvaceous slopes of California. 76 | 77 | But not only that: 78 | 79 | Let freedom ring from Stone Mountain of Georgia. 80 | 81 | Let freedom ring from Lookout Mountain of Tennessee. 82 | 83 | Let freedom ring from every hill and molehill of Mississippi. 84 | 85 | From every mountainside, let freedom ring. 86 | 87 | And when this happens, and when we allow freedom ring, when we let it ring from every village and every hamlet, from every state and every city, we will be able to speed up that day when all of God's children, black men and white men, Jews and Gentiles, Protestants and Catholics, will be able to join hands and sing in the words of the old Negro spiritual: 88 | 89 | Free at last! Free at last! 90 | 91 | Thank God Almighty, we are free at last! 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /ch07/json.txt: -------------------------------------------------------------------------------- 1 | {"menu": { 2 | "hello": "hi", 3 | "flag": true, 4 | "count": 123, 5 | "id": "icjowiieh", 6 | "value": "File", 7 | "popup": { 8 | "menuitem": [ 9 | {"value": "New", "onclick": "CreateNewDoc()"}, 10 | {"value": "Open", "onclick": "OpenDoc()"}, 11 | {"value": "Close", "onclick": "CloseDoc()"} 12 | ] 13 | } 14 | }} 15 | -------------------------------------------------------------------------------- /ch07/json_out1.txt: -------------------------------------------------------------------------------- 1 | {"menu":{"count":123,"popup":{"menuitem":[{"onclick":"CreateNewDoc()","value":"New"},{"onclick":"OpenDoc()","value":"Open"},{"onclick":"CloseDoc()","value":"Close"}]},"value":"File","id":"icjowiieh","flag":true,"hello":"hi"}} -------------------------------------------------------------------------------- /ch07/json_out2.txt: -------------------------------------------------------------------------------- 1 | { 2 | "menu":{ 3 | "count":123, 4 | "flag":true, 5 | "hello":"hi", 6 | "id":"icjowiieh", 7 | "popup":{ 8 | "menuitem":[ 9 | { 10 | "onclick":"CreateNewDoc()", 11 | "value":"New" 12 | }, 13 | { 14 | "onclick":"OpenDoc()", 15 | "value":"Open" 16 | }, 17 | { 18 | "onclick":"CloseDoc()", 19 | "value":"Close" 20 | } 21 | ] 22 | }, 23 | "value":"File" 24 | } 25 | } -------------------------------------------------------------------------------- /ch07/pickle.bin: -------------------------------------------------------------------------------- 1 | (dp0 2 | S'a' 3 | p1 4 | (lp2 5 | I1 6 | aI2 7 | aI3 8 | aI4 9 | asS'default' 10 | p3 11 | NsS'John' 12 | p4 13 | S'abcdef' 14 | p5 15 | sI334455 16 | I778899 17 | s. -------------------------------------------------------------------------------- /ch07/stdin_test.txt: -------------------------------------------------------------------------------- 1 | Amy 2 | John 3 | David 4 | -------------------------------------------------------------------------------- /ch07/test.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch07/test.bin -------------------------------------------------------------------------------- /ch07/test.txt: -------------------------------------------------------------------------------- 1 | Hello Python! 2 | How are you? 3 | abc 123 4 | -------------------------------------------------------------------------------- /ch07/test_big5.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch07/test_big5.txt -------------------------------------------------------------------------------- /ch07/test_utf8.txt: -------------------------------------------------------------------------------- 1 | 你好嗎? 2 | 我很好。 3 | 學習Python 4 | 床前明月光 5 | -------------------------------------------------------------------------------- /ch08/ch08_counter.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from __future__ import print_function 4 | from collections import Counter 5 | from io import open 6 | 7 | with open('i_have_a_dream.txt', 'r', encoding='ascii') as fin: 8 | c = Counter() 9 | for line in fin: 10 | if line[0] == '#': 11 | continue 12 | c.update(line.split()) 13 | print(sorted(c.items(), key=lambda x: x[1])) 14 | 15 | -------------------------------------------------------------------------------- /ch08/ch08_namedtuple_csv.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from __future__ import print_function 4 | from io import open 5 | from collections import namedtuple 6 | import csv 7 | 8 | with open('csv.txt', 'r', encoding='ascii') as fin: 9 | csvreader = csv.reader(fin, delimiter=',') 10 | header = next(csvreader) 11 | Data = namedtuple('Header', ','.join(header)) 12 | for row in csvreader: 13 | d = Data._make(row) 14 | print(d.name, d.eng, d.history, d.math) 15 | 16 | 17 | -------------------------------------------------------------------------------- /ch08/ch08ex8.5_testdata.bin: -------------------------------------------------------------------------------- 1 | hello python.abc 123.bye bye. -------------------------------------------------------------------------------- /ch08/ch08ex8.6_testdata.ini: -------------------------------------------------------------------------------- 1 | 2 | [user] 3 | name=(none) 4 | organization=Python User Group 5 | 6 | [database] 7 | server=192.168.1.1 8 | port=143 9 | file="no.dat" 10 | 11 | -------------------------------------------------------------------------------- /ch08/ch08ex8.6_testdata2.ini: -------------------------------------------------------------------------------- 1 | 2 | [user] 3 | name=john 4 | organization=Python User Group 5 | 6 | [database] 7 | server=192.0.2.62 8 | port=143 9 | file="somefile.dat" 10 | 11 | -------------------------------------------------------------------------------- /ch08/ch08ex8.7_testdata.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | username 6 | john 7 | ip 8 | 192.168.1.1 9 | port 10 | 143 11 | 12 | 13 | -------------------------------------------------------------------------------- /ch08/ch08ex8.7_testdata2.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | username 6 | sys 7 | ip 8 | 192.0.0.1 9 | port 10 | 255 11 | 12 | 13 | -------------------------------------------------------------------------------- /ch08/csv.txt: -------------------------------------------------------------------------------- 1 | name,eng,history,math 2 | John,67,85,43 3 | Amy,32,89,91 4 | David,90,76,55 5 | -------------------------------------------------------------------------------- /ch08/csv_out.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch08/csv_out.txt -------------------------------------------------------------------------------- /ch08/i_have_a_dream.txt: -------------------------------------------------------------------------------- 1 | # I Have a Dream 2 | # Martin Luther King, Jr. 3 | # http://www.americanrhetoric.com/speeches/mlkihaveadream.htm 4 | 5 | I am happy to join with you today in what will go down in history as the greatest demonstration for freedom in the history of our nation. 6 | 7 | Five score years ago, a great American, in whose symbolic shadow we stand today, signed the Emancipation Proclamation. This momentous decree came as a great beacon light of hope to millions of Negro slaves who had been seared in the flames of withering injustice. It came as a joyous daybreak to end the long night of their captivity. 8 | 9 | But one hundred years later, the Negro still is not free. One hundred years later, the life of the Negro is still sadly crippled by the manacles of segregation and the chains of discrimination. One hundred years later, the Negro lives on a lonely island of poverty in the midst of a vast ocean of material prosperity. One hundred years later, the Negro is still languished in the corners of American society and finds himself an exile in his own land. And so we've come here today to dramatize a shameful condition. 10 | 11 | In a sense we've come to our nation's capital to cash a check. When the architects of our republic wrote the magnificent words of the Constitution and the Declaration of Independence, they were signing a promissory note to which every American was to fall heir. This note was a promise that all men, yes, black men as well as white men, would be guaranteed the "unalienable Rights" of "Life, Liberty and the pursuit of Happiness." It is obvious today that America has defaulted on this promissory note, insofar as her citizens of color are concerned. Instead of honoring this sacred obligation, America has given the Negro people a bad check, a check which has come back marked "insufficient funds." 12 | 13 | But we refuse to believe that the bank of justice is bankrupt. We refuse to believe that there are insufficient funds in the great vaults of opportunity of this nation. And so, we've come to cash this check, a check that will give us upon demand the riches of freedom and the security of justice. 14 | 15 | We have also come to this hallowed spot to remind America of the fierce urgency of Now. This is no time to engage in the luxury of cooling off or to take the tranquilizing drug of gradualism. Now is the time to make real the promises of democracy. Now is the time to rise from the dark and desolate valley of segregation to the sunlit path of racial justice. Now is the time to lift our nation from the quicksands of racial injustice to the solid rock of brotherhood. Now is the time to make justice a reality for all of God's children. 16 | 17 | It would be fatal for the nation to overlook the urgency of the moment. This sweltering summer of the Negro's legitimate discontent will not pass until there is an invigorating autumn of freedom and equality. Nineteen sixty-three is not an end, but a beginning. And those who hope that the Negro needed to blow off steam and will now be content will have a rude awakening if the nation returns to business as usual. And there will be neither rest nor tranquility in America until the Negro is granted his citizenship rights. The whirlwinds of revolt will continue to shake the foundations of our nation until the bright day of justice emerges. 18 | 19 | But there is something that I must say to my people, who stand on the warm threshold which leads into the palace of justice: In the process of gaining our rightful place, we must not be guilty of wrongful deeds. Let us not seek to satisfy our thirst for freedom by drinking from the cup of bitterness and hatred. We must forever conduct our struggle on the high plane of dignity and discipline. We must not allow our creative protest to degenerate into physical violence. Again and again, we must rise to the majestic heights of meeting physical force with soul force. 20 | 21 | The marvelous new militancy which has engulfed the Negro community must not lead us to a distrust of all white people, for many of our white brothers, as evidenced by their presence here today, have come to realize that their destiny is tied up with our destiny. And they have come to realize that their freedom is inextricably bound to our freedom. 22 | 23 | We cannot walk alone. 24 | 25 | And as we walk, we must make the pledge that we shall always march ahead. 26 | 27 | We cannot turn back. 28 | 29 | There are those who are asking the devotees of civil rights, "When will you be satisfied?" We can never be satisfied as long as the Negro is the victim of the unspeakable horrors of police brutality. We can never be satisfied as long as our bodies, heavy with the fatigue of travel, cannot gain lodging in the motels of the highways and the hotels of the cities. We cannot be satisfied as long as the negro's basic mobility is from a smaller ghetto to a larger one. We can never be satisfied as long as our children are stripped of their self-hood and robbed of their dignity by signs stating: "For Whites Only." We cannot be satisfied as long as a Negro in Mississippi cannot vote and a Negro in New York believes he has nothing for which to vote. No, no, we are not satisfied, and we will not be satisfied until "justice rolls down like waters, and righteousness like a mighty stream." 30 | 31 | I am not unmindful that some of you have come here out of great trials and tribulations. Some of you have come fresh from narrow jail cells. And some of you have come from areas where your quest -- quest for freedom left you battered by the storms of persecution and staggered by the winds of police brutality. You have been the veterans of creative suffering. Continue to work with the faith that unearned suffering is redemptive. Go back to Mississippi, go back to Alabama, go back to South Carolina, go back to Georgia, go back to Louisiana, go back to the slums and ghettos of our northern cities, knowing that somehow this situation can and will be changed. 32 | 33 | Let us not wallow in the valley of despair, I say to you today, my friends. 34 | 35 | And so even though we face the difficulties of today and tomorrow, I still have a dream. It is a dream deeply rooted in the American dream. 36 | 37 | I have a dream that one day this nation will rise up and live out the true meaning of its creed: "We hold these truths to be self-evident, that all men are created equal." 38 | 39 | I have a dream that one day on the red hills of Georgia, the sons of former slaves and the sons of former slave owners will be able to sit down together at the table of brotherhood. 40 | 41 | I have a dream that one day even the state of Mississippi, a state sweltering with the heat of injustice, sweltering with the heat of oppression, will be transformed into an oasis of freedom and justice. 42 | 43 | I have a dream that my four little children will one day live in a nation where they will not be judged by the color of their skin but by the content of their character. 44 | 45 | I have a dream today! 46 | 47 | I have a dream that one day, down in Alabama, with its vicious racists, with its governor having his lips dripping with the words of "interposition" and "nullification" -- one day right there in Alabama little black boys and black girls will be able to join hands with little white boys and white girls as sisters and brothers. 48 | 49 | I have a dream today! 50 | 51 | I have a dream that one day every valley shall be exalted, and every hill and mountain shall be made low, the rough places will be made plain, and the crooked places will be made straight; "and the glory of the Lord shall be revealed and all flesh shall see it together." 52 | 53 | This is our hope, and this is the faith that I go back to the South with. 54 | 55 | With this faith, we will be able to hew out of the mountain of despair a stone of hope. With this faith, we will be able to transform the jangling discords of our nation into a beautiful symphony of brotherhood. With this faith, we will be able to work together, to pray together, to struggle together, to go to jail together, to stand up for freedom together, knowing that we will be free one day. 56 | 57 | And this will be the day -- this will be the day when all of God's children will be able to sing with new meaning: 58 | 59 | My country 'tis of thee, sweet land of liberty, of thee I sing. 60 | 61 | Land where my fathers died, land of the Pilgrim's pride, 62 | 63 | From every mountainside, let freedom ring! 64 | 65 | And if America is to be a great nation, this must become true. 66 | 67 | And so let freedom ring from the prodigious hilltops of New Hampshire. 68 | 69 | Let freedom ring from the mighty mountains of New York. 70 | 71 | Let freedom ring from the heightening Alleghenies of Pennsylvania. 72 | 73 | Let freedom ring from the snow-capped Rockies of Colorado. 74 | 75 | Let freedom ring from the curvaceous slopes of California. 76 | 77 | But not only that: 78 | 79 | Let freedom ring from Stone Mountain of Georgia. 80 | 81 | Let freedom ring from Lookout Mountain of Tennessee. 82 | 83 | Let freedom ring from every hill and molehill of Mississippi. 84 | 85 | From every mountainside, let freedom ring. 86 | 87 | And when this happens, and when we allow freedom ring, when we let it ring from every village and every hamlet, from every state and every city, we will be able to speed up that day when all of God's children, black men and white men, Jews and Gentiles, Protestants and Catholics, will be able to join hands and sing in the words of the old Negro spiritual: 88 | 89 | Free at last! Free at last! 90 | 91 | Thank God Almighty, we are free at last! 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /ch09/ch09_coin_sum.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Problem 31: Coin sums 4 | # https://projecteuler.net/problem=31 5 | 6 | # dynamic programming 7 | def coin_sum(total, coins): 8 | ways = [1] + ([0] * total) 9 | for coin in coins: 10 | for i in range(coin, total+1): 11 | ways[i] += ways[i - coin] 12 | return ways[total] 13 | 14 | def coin_sum_r(total, coins): 15 | if len(coins) == 1: 16 | return 1 17 | elif total < coins[-1]: 18 | return coin_sum_r(total, coins[:-1]) 19 | else: 20 | return (coin_sum_r(total-coins[-1], coins) + 21 | coin_sum_r(total, coins[:-1])) 22 | 23 | # coins_a = (1, 5, 10, 25) 24 | # print(coin_sum(100, coins_a)) # 242 25 | 26 | # coins_b = (1, 5, 10, 25, 50, 100) 27 | # print(coin_sum(100000, coins_b)) # 13398445413854501 28 | 29 | coins_england = (1, 2, 5, 10, 20, 50, 100, 200) 30 | # print(coin_sum(100, coins_england)) # 73682 31 | # print(coin_sum(600, coins_england)) # 73682 32 | # print(coin_sum_r(600, coins_england)) # 73682 33 | 34 | coins_x = (1, 2) 35 | for i in range(1, 12+1): 36 | print(coin_sum(i, coins_x)) 37 | 38 | 39 | -------------------------------------------------------------------------------- /ch09/ch09_ctof_side_effetcs.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | temps = [0, 100, 30.2, 22.5, -15.8, 23.7, -22.5] 4 | 5 | def ctof(): 6 | for i in range(len(temps)): 7 | temps[i] = temps[i] * 9.0 / 5.0 + 32 8 | 9 | print(temps) 10 | ctof() 11 | print(temps) 12 | 13 | #### 14 | 15 | def ctof(temps): 16 | result = [] 17 | for i in range(len(temps)): 18 | result.append(temps[i] * 9.0 / 5.0 + 32) 19 | return result 20 | 21 | temps = [0, 100, 30.2, 22.5, -15.8, 23.7, -22.5] 22 | print(ctof(temps)) 23 | print(ctof(temps)) 24 | 25 | #### 26 | 27 | def ctof(temps): 28 | if temps == []: 29 | return [] 30 | else: 31 | return [temps[0] * 9.0 / 5.0 + 32] + ctof(temps[1:]) 32 | 33 | temps = [0, 100, 30.2, 22.5, -15.8, 23.7, -22.5] 34 | print(ctof(temps)) 35 | 36 | 37 | -------------------------------------------------------------------------------- /ch09/ch09_dec_memo.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def dec_memo(func): 4 | cache = func.cache = {} 5 | def wrapper(*args, **kwargs): 6 | key = str(args) + str(kwargs) 7 | if key not in cache: 8 | cache[key] = func(*args, **kwargs) 9 | return cache[key] 10 | return wrapper 11 | 12 | @dec_memo 13 | def fib_r(n): 14 | if n == 0 or n == 1: 15 | return n 16 | else: 17 | return fib_r(n-1) + fib_r(n-2) 18 | 19 | def fib_r2(n): 20 | if n == 0 or n == 1: 21 | return n 22 | else: 23 | return fib_r2(n-1) + fib_r2(n-2) 24 | 25 | def dec_time(func): 26 | def wrapper(*args, **kwargs): 27 | import time 28 | t_start = time.clock() 29 | res = func(*args, **kwargs) 30 | t_end = time.clock() 31 | print(func.__name__, t_end-t_start) 32 | return res 33 | return wrapper 34 | @dec_time 35 | def foo1(): 36 | for i in range(6000): 37 | fib_r(i) 38 | @dec_time 39 | def foo2(): 40 | for i in range(33): 41 | fib_r2(i) 42 | 43 | foo1() 44 | foo2() 45 | -------------------------------------------------------------------------------- /ch09/ch09_dec_memo_limit.py: -------------------------------------------------------------------------------- 1 | 2 | import pickle 3 | def dec_memo_limit(func, limit=None): 4 | if isinstance(func, int): 5 | def wrapper(f): 6 | return dec_memo_limit(f, func) 7 | return wrapper 8 | 9 | d = {} 10 | li = [] 11 | def wrapper(*args, **kwargs): 12 | key = pickle.dumps((args, kwargs)) 13 | try: 14 | li.append(li.pop(li.index(key))) 15 | except ValueError: 16 | d[key] = func(*args, **kwargs) 17 | li.append(key) 18 | if limit is not None and len(li) > limit: 19 | del d[li.pop(0)] 20 | return d[key] 21 | 22 | wrapper._memoize_dict = d 23 | wrapper._memoize_list = li 24 | wrapper._memoize_limit = limit 25 | wrapper._memoize_origfunc = func 26 | wrapper.__name__ = func.__name__ 27 | return wrapper 28 | 29 | @dec_memo_limit(200) 30 | def fib_r(n): 31 | if n == 0 or n == 1: 32 | return n 33 | else: 34 | return fib_r(n-1) + fib_r(n-2) 35 | print(fib_r._memoize_limit) 36 | 37 | @dec_memo_limit(100) 38 | def fib_r2(n): 39 | if n == 0 or n == 1: 40 | return n 41 | else: 42 | return fib_r2(n-1) + fib_r2(n-2) 43 | print(fib_r2._memoize_limit) 44 | 45 | def dec_time(func): 46 | def wrapper(*args, **kwargs): 47 | import time 48 | t_start = time.clock() 49 | res = func(*args, **kwargs) 50 | t_end = time.clock() 51 | print(func.__name__, t_end-t_start) 52 | return res 53 | return wrapper 54 | @dec_time 55 | def foo1(): 56 | for i in range(1000): 57 | fib_r(i) 58 | @dec_time 59 | def foo2(): 60 | for i in range(1000): 61 | fib_r2(i) 62 | 63 | foo1() 64 | foo2() 65 | 66 | import functools 67 | @functools.lru_cache(maxsize=100) 68 | def fib_r3(n): 69 | if n == 0 or n == 1: 70 | return n 71 | else: 72 | return fib_r3(n-1) + fib_r3(n-2) 73 | 74 | @dec_time 75 | def foo3(): 76 | for i in range(1000): 77 | fib_r3(i) 78 | foo3() 79 | 80 | # @functools.lru_cache(maxsize=300) 81 | # def bar(li): 82 | # return sum(li) 83 | 84 | # print(bar([1,2,3])) 85 | # print(bar([22,22,22])) 86 | 87 | @dec_memo_limit 88 | def fib_r4(n): 89 | if n == 0 or n == 1: 90 | return n 91 | else: 92 | return fib_r4(n-1) + fib_r4(n-2) 93 | print(fib_r4) 94 | 95 | 96 | -------------------------------------------------------------------------------- /ch09/ch09_dec_natural.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def dec_natural(func): 4 | def wrapper(n): 5 | if type(n) == int and n >= 0: 6 | return func(n) 7 | else: 8 | raise TypeError('Argument is not a natural number') 9 | return wrapper 10 | 11 | @dec_natural 12 | def fact_i(n): 13 | result = 1 14 | for i in range(1, n+1): 15 | result *= i 16 | return result 17 | 18 | print(fact_i(3)) 19 | # print(fact_i(-1)) 20 | -------------------------------------------------------------------------------- /ch09/ch09_dec_notfunc.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def dec_notfunc(n): 4 | def wrapper(func): 5 | return [func(i) for i in range(n)] 6 | return wrapper 7 | 8 | @dec_notfunc(5) 9 | def foo(n): 10 | return n**2 11 | 12 | print(foo) 13 | -------------------------------------------------------------------------------- /ch09/ch09_dec_time.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def dec_time(func): 4 | def wrapper(*args, **kwargs): 5 | import time 6 | t_start = time.clock() 7 | res = func(*args, **kwargs) 8 | t_end = time.clock() 9 | print(func.__name__, t_end-t_start) 10 | return res 11 | return wrapper 12 | 13 | def fact_i(n): 14 | result = 1 15 | for i in range(1, n+1): 16 | result *= i 17 | return result 18 | 19 | @dec_time 20 | def foo(n): 21 | for i in range(n): 22 | fact_i(i) 23 | foo(1000) 24 | -------------------------------------------------------------------------------- /ch09/ch09_dec_wraps.py: -------------------------------------------------------------------------------- 1 | 2 | import functools 3 | 4 | def dec(func): 5 | @functools.wraps(func) 6 | def wrapper(): 7 | return func() 8 | return wrapper 9 | 10 | @dec 11 | def foo(): 12 | pass 13 | 14 | print(foo.__name__) 15 | 16 | -------------------------------------------------------------------------------- /ch09/ch09_fact_i_r.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def fact_i(n): 4 | result = 1 5 | for i in range(1, n+1): 6 | result *= i 7 | return result 8 | #### 9 | def fact_r(n): 10 | if n == 1 or n == 0: 11 | return 1 12 | else: 13 | return n * fact_r(n-1) 14 | 15 | print(fact_i(999)) 16 | print(fact_r(999)) 17 | 18 | 19 | -------------------------------------------------------------------------------- /ch09/ch09_fact_tail.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def fact_i(n): 4 | result = 1 5 | for i in range(1, n+1): 6 | result *= i 7 | return result 8 | #### 9 | def fact_r(n): 10 | if n == 1 or n == 0: 11 | return 1 12 | else: 13 | return n * fact_r(n-1) 14 | #### 15 | def fact_r_tail(n, result=1): 16 | if n == 1 or n == 0: 17 | return result 18 | else: 19 | return fact_r_tail(n-1, n*result) 20 | 21 | for i in range(2, 50): 22 | x = fact_i(i) 23 | y = fact_r(i) 24 | z = fact_r_tail(i) 25 | if x == y == z: 26 | pass 27 | else: 28 | print('error') 29 | 30 | -------------------------------------------------------------------------------- /ch09/ch09_fact_tco.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def fact_i(n): 4 | result = 1 5 | for i in range(1, n+1): 6 | result *= i 7 | return result 8 | #### 9 | def fact_r(n): 10 | if n == 1 or n == 0: 11 | return 1 12 | else: 13 | return n * fact_r(n-1) 14 | #### 15 | def fact_r_tail(n, result=1): 16 | if n == 1 or n == 0: 17 | return result 18 | else: 19 | return fact_r_tail(n-1, n*result) 20 | #### 21 | 22 | import sys 23 | 24 | class TailRecurseException(BaseException): 25 | def __init__(self, args, kwargs): 26 | self.args = args 27 | self.kwargs = kwargs 28 | 29 | def tail_call_optimized(g): 30 | def func(*args, **kwargs): 31 | f = sys._getframe() 32 | if (f.f_back and f.f_back.f_back and 33 | f.f_back.f_back.f_code == f.f_code): 34 | raise TailRecurseException(args, kwargs) 35 | else: 36 | while 1: 37 | try: 38 | return g(*args, **kwargs) 39 | except TailRecurseException as e: 40 | args = e.args 41 | kwargs = e.kwargs 42 | return func 43 | 44 | # @tail_call_optimized 45 | # def fact_tco(n, result=1): 46 | # if n == 1 or n == 0: 47 | # return result 48 | # else: 49 | # return fact_tco(n-1, n*result) 50 | def fact_tco(n, result=1): 51 | if n == 1 or n == 0: 52 | return result 53 | else: 54 | return fact_tco(n-1, n*result) 55 | 56 | fact_tco = tail_call_optimized(fact_tco) 57 | 58 | for i in range(2, 50): 59 | x = fact_i(i) 60 | y = fact_r(i) 61 | z = fact_r_tail(i) 62 | w = fact_tco(i) 63 | if x == y == z == w: 64 | pass 65 | else: 66 | print('error') 67 | 68 | # print(fact_i(980)) 69 | sys.setrecursionlimit(2000) 70 | print(fact_r_tail(1000)) 71 | sys.setrecursionlimit(100) 72 | print(fact_tco(1000)) 73 | for i in range(1000, 1050, 3): 74 | x = fact_i(i) 75 | w = fact_tco(i) 76 | if x == w: 77 | pass 78 | else: 79 | print('error') 80 | -------------------------------------------------------------------------------- /ch09/ch09_forest.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | tree_a = ['-', 6, 2] 4 | tree_b = ['/', 10, 2] 5 | tree_c = ['+', 3, tree_a, tree_b] 6 | tree_d = ['-', 5, 2, 1] 7 | tree_e = ['*', tree_d, tree_c] 8 | 9 | import operator 10 | 11 | ops = {'+': operator.add, 12 | '-': operator.sub, 13 | '*': operator.mul, 14 | '/': operator.floordiv} 15 | 16 | def cal_tree(tree): 17 | if type(tree) == int: 18 | return tree 19 | else: 20 | return cal_forest(tree[1:], tree[0]) 21 | 22 | def cal_forest(forest, op): 23 | if len(forest) == 2: 24 | return ops[op](cal_tree(forest[0]), cal_tree(forest[1])) 25 | else: 26 | hsr = cal_forest(forest[:-1], op) 27 | return ops[op](hsr, cal_tree(forest[-1])) 28 | 29 | print(cal_tree(tree_e)) 30 | 31 | -------------------------------------------------------------------------------- /ch09/ch09_i_to_r.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def my_sum(li): 4 | if li == []: 5 | return 0 6 | else: 7 | return li[0] + my_sum(li[1:]) 8 | 9 | print(my_sum(list(range(100+1)))) 10 | print(my_sum([])) 11 | print(my_sum([1, 2, 3])) 12 | 13 | def my_len(li): 14 | if li == []: 15 | return 0 16 | else: 17 | return 1 + my_len(li[1:]) 18 | print(my_len(list(range(100+1)))) 19 | print(my_len([])) 20 | print(my_len([1, 2, 3])) 21 | 22 | def gcd(a, b): 23 | while b: 24 | a, b = b, a%b 25 | return a 26 | def gcd_r(a, b): 27 | if a%b == 0: 28 | return b 29 | else: 30 | return gcd(b, a%b) 31 | for i in range(2, 100, 3): 32 | for j in range(3, 100, 4): 33 | if gcd(i, j) != gcd_r(i, j): 34 | print('error', i, j) 35 | 36 | def ctof2(temp): 37 | n = my_len(temp) 38 | i = 0 39 | while i < n: 40 | temp[i] = temp[i] * 9.0 / 5.0 + 32 41 | i += 1 42 | data2 = [-30.2, -22.5, 15.8, 23.7, 35.2] 43 | ctof2(data2) 44 | data = [-30.2, -22.5, 15.8, 23.7, 35.2] 45 | def ctof(li): 46 | if li == []: 47 | return [] 48 | else: 49 | return [li[0]*9.0/5.0+32] + ctof(li[1:]) 50 | if ctof(data) != data2: 51 | print('error') 52 | print(ctof(data)) 53 | print(data2) 54 | -------------------------------------------------------------------------------- /ch09/ch09_map.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def sq(n): return n**2 4 | def even(n): return n % 2 == 0 5 | def sum_sq_even(n): 6 | result = 0 7 | for i in range(1, n): 8 | if even(i): 9 | result += sq(i) 10 | return result 11 | 12 | print(sum_sq_even(10)) 13 | 14 | #### 15 | 16 | def sum_sq_even(n): 17 | return sum(map(sq, filter(even, range(1, n)))) 18 | 19 | print(sum_sq_even(10)) 20 | 21 | #### 22 | 23 | def dec_memo(func): 24 | cache = func.cache = {} 25 | def wrapper(*args, **kwargs): 26 | key = str(args) + str(kwargs) 27 | if key not in cache: 28 | cache[key] = func(*args, **kwargs) 29 | return cache[key] 30 | return wrapper 31 | 32 | @dec_memo 33 | def fib_r(n): 34 | if n == 0 or n == 1: 35 | return n 36 | else: 37 | return fib_r(n-1) + fib_r(n-2) 38 | fib = fib_r 39 | 40 | def odd(n): 41 | return n % 2 != 0 42 | 43 | def odd_fibs(n): 44 | result = [] 45 | i = 0 46 | while i < n: 47 | temp = fib(i) 48 | if odd(temp): 49 | result.append(temp) 50 | i += 1 51 | return result 52 | 53 | print(odd_fibs(10)) 54 | 55 | #### 56 | 57 | def odd_fibs(n): 58 | return list(filter(odd, map(fib, range(n)))) 59 | 60 | print(odd_fibs(10)) 61 | 62 | #### 63 | 64 | def my_map(func, iterable): 65 | result = [] 66 | for e in iterable: 67 | result.append(func(e)) 68 | return result 69 | def my_filter(func, iterable): 70 | result = [] 71 | for e in iterable: 72 | if func(e): 73 | result.append(e) 74 | return result 75 | 76 | def sum_sq_even(n): 77 | return sum(my_map(sq, my_filter(even, range(1, n)))) 78 | 79 | print(sum_sq_even(10)) 80 | 81 | def odd_fibs(n): 82 | return list(my_filter(odd, my_map(fib, range(n)))) 83 | 84 | print(odd_fibs(10)) 85 | 86 | #### 87 | 88 | def sum_sq_even(n): 89 | return sum(my_map(sq, 90 | my_filter(even, 91 | range(1, n)))) 92 | 93 | def odd_fibs(n): 94 | return list(my_filter(odd, 95 | my_map(fib, 96 | range(n)))) 97 | 98 | #### 99 | print('-' * 20) 100 | from operator import add 101 | def sum_sq_even(n): 102 | return reduce(add, 103 | map(sq, 104 | filter(even, 105 | range(1, n)))) 106 | 107 | def odd_fibs(n): 108 | return reduce(lambda x, y: x+[y], 109 | filter(odd, 110 | map(fib, 111 | range(n))), 112 | []) 113 | 114 | 115 | print(sum_sq_even(10)) 116 | print(odd_fibs(10)) 117 | -------------------------------------------------------------------------------- /ch09/ch09_odd_even.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def is_odd(n): 4 | if n == 0: 5 | return False 6 | else: 7 | return is_even(n-1) 8 | def is_even(n): 9 | if n == 0: 10 | return True 11 | else: 12 | return is_odd(n-1) 13 | 14 | 15 | 16 | if __name__ == '__main__': 17 | for i in range(0, 100): 18 | if is_odd(i) != (i%2 == 1): 19 | print('error odd', i) 20 | if is_even(i) != (i%2 == 0): 21 | print('error even', i) 22 | 23 | 24 | -------------------------------------------------------------------------------- /ch09/ch09_odd_fibs.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def dec_memo(func): 4 | cache = func.cache = {} 5 | def wrapper(*args, **kwargs): 6 | key = str(args) + str(kwargs) 7 | if key not in cache: 8 | cache[key] = func(*args, **kwargs) 9 | return cache[key] 10 | return wrapper 11 | 12 | @dec_memo 13 | def fib_r(n): 14 | if n == 0 or n == 1: 15 | return n 16 | else: 17 | return fib_r(n-1) + fib_r(n-2) 18 | fib = fib_r 19 | 20 | def odd(n): 21 | return n % 2 != 0 22 | 23 | def odd_fibs(n): 24 | result = [] 25 | i = 0 26 | while i < n: 27 | temp = fib(i) 28 | if odd(temp): 29 | result.append(temp) 30 | i += 1 31 | return result 32 | 33 | print(odd_fibs(10)) 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /ch09/ch09_sum_is_prime.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # from itertools import imap as map 4 | from itertools import repeat, chain 5 | 6 | def prime_sieve(n): 7 | primes = set(range(2, n+1)) 8 | for i in range(2, (n+1+1) // 2): 9 | if i in primes: 10 | m = 2 11 | while i*m <= n: 12 | primes.discard(i*m) 13 | m += 1 14 | return primes 15 | 16 | def gen_pairs(i): 17 | return map(lambda i,j: (i,j), repeat(i), range(1, i)) 18 | 19 | def gen_allpairs(n): 20 | return chain(*map(gen_pairs, range(2, n+1))) 21 | 22 | def pair_sum(p): 23 | return (p[0], p[1], p[0]+p[1]) 24 | 25 | def is_prime(ps): 26 | return ps[2] in prime_sieve(ps[2]) 27 | 28 | def sum_is_prime(n): 29 | return filter(is_prime, map(pair_sum, gen_allpairs(n))) 30 | 31 | print(list(sum_is_prime(6))) 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /ch09/ch09_sum_of_primes.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from itertools import imap as map 4 | 5 | def prime_sieve(n): 6 | primes = set(range(2, n+1)) 7 | for i in range(2, (n+1+1) // 2): 8 | if i in primes: 9 | m = 2 10 | while i*m <= n: 11 | primes.discard(i*m) 12 | m += 1 13 | return primes 14 | 15 | def is_prime(n): 16 | return n in prime_sieve(n) 17 | def sum_of_primes(n): 18 | return sum(filter(is_prime, range(2, n+1))) 19 | 20 | print(sum_of_primes(20)) 21 | print(sum_of_primes(2 * 1000)) 22 | -------------------------------------------------------------------------------- /ch09/ch09_sum_sq_even.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def sq(n): return n**2 4 | def even(n): return n % 2 == 0 5 | def sum_sq_even(n): 6 | result = 0 7 | for i in range(1, n): 8 | if even(i): 9 | result += sq(i) 10 | return result 11 | 12 | print(sum_sq_even(10)) 13 | 14 | 15 | -------------------------------------------------------------------------------- /ch09/ch09_tph.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Problem 45: Triangular, pentagonal, and hexagonal 4 | # https://projecteuler.net/problem=45 5 | 6 | from itertools import count 7 | from itertools import imap as map 8 | 9 | def filter_equal(ita, itb): 10 | a = next(ita) 11 | b = next(itb) 12 | while True: 13 | if a < b: 14 | a = next(ita) 15 | elif a > b: 16 | b = next(itb) 17 | else: 18 | yield a 19 | a = next(ita) 20 | 21 | def tph_gf(): 22 | t = map(lambda n: n * (n+1) // 2, count(1)) 23 | p = map(lambda n: n * (3*n - 1) // 2, count(1)) 24 | h = map(lambda n: n * (2*n - 1), count(1)) 25 | filter_tph = filter_equal(filter_equal(t, p), h) 26 | while True: 27 | yield next(filter_tph) 28 | 29 | tph = tph_gf() 30 | print(next(tph)) # 1 31 | print(next(tph)) # 40755 32 | print(next(tph)) # 1533776805 33 | -------------------------------------------------------------------------------- /ch09/ch09_tree.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | tree_a = ['-', 4, 1] 4 | tree_b = ['/', 10, 2] 5 | tree_c = ['+', tree_a, tree_b] 6 | tree_d = ['+', 3, tree_c] 7 | tree_e = ['-', 4, 2] 8 | tree_f = ['*', tree_e, tree_d] 9 | 10 | import operator 11 | 12 | ops = {'+': operator.add, 13 | '-': operator.sub, 14 | '*': operator.mul, 15 | '/': operator.floordiv} 16 | 17 | def cal(tree): 18 | if type(tree) == int: 19 | return tree 20 | else: 21 | return ops[tree[0]](cal(tree[1]), cal(tree[2])) 22 | 23 | print(cal(tree_f)) 24 | 25 | -------------------------------------------------------------------------------- /ch09/ch09ex9.10_flatten_list.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def flatten_list(a, result=None): 4 | if result is None: 5 | result = [] 6 | for x in a: 7 | if isinstance(x, list): 8 | else: 9 | result.append(x) 10 | return result 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ch09/ch09ex9.7_hamming.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def hamming(a, b): 4 | return sum(x != y for x, y in map(None, a, b)) 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ch09/ch09ex9.xzy_accept.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # from PEP 318 4 | # https://www.python.org/dev/peps/pep-0318/#current-syntax 5 | 6 | def accepts(*types): 7 | def check_accepts(f): 8 | assert len(types) == f.func_code.co_argcount 9 | def new_f(*args, **kwds): 10 | for (a, t) in zip(args, types): 11 | assert isinstance(a, t), \ 12 | "arg %r does not match %s" % (a,t) 13 | return f(*args, **kwds) 14 | new_f.func_name = f.func_name 15 | return new_f 16 | return check_accepts 17 | 18 | def returns(rtype): 19 | def check_returns(f): 20 | def new_f(*args, **kwds): 21 | result = f(*args, **kwds) 22 | assert isinstance(result, rtype), \ 23 | "return value %r does not match %s" % (result,rtype) 24 | return result 25 | new_f.func_name = f.func_name 26 | return new_f 27 | return check_returns 28 | 29 | @accepts(int, (int,float)) 30 | @returns((int,float)) 31 | def func(arg1, arg2): 32 | return arg1 * arg2 33 | -------------------------------------------------------------------------------- /ch10/ch10_ns_package.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import sys 4 | # sys.path.append('/cygdrive/d/yehnan/wr_python_drmaster/python_book_yehnan/ch10/path1') 5 | # sys.path.append('/cygdrive/d/yehnan/wr_python_drmaster/python_book_yehnan/ch10/path2') 6 | sys.path.append(r'D:\yehnan\wr_python_drmaster\python_book_yehnan\ch10\path1') 7 | sys.path.append(r'D:\yehnan\wr_python_drmaster\python_book_yehnan\ch10\path2') 8 | 9 | # import mymodule 10 | # print(mymodule.__name__) 11 | # print(mymodule.__file__) 12 | # print(mymodule.__path__) 13 | 14 | import mymodule.sub1 15 | import mymodule.sub2 16 | 17 | print(mymodule.sub1.foo()) 18 | print(mymodule.sub2.bar()) 19 | -------------------------------------------------------------------------------- /ch10/ch10_package_example.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # import package_example.gui.menu 5 | # import package_example.gui.canvas 6 | # from package_example.gui import * 7 | 8 | # print(display()) 9 | # print(draw()) 10 | # print(menu.__name__) 11 | # print(canvas.__name__) 12 | 13 | 14 | # print(canvas.__name__) 15 | # print(menu.__name__) 16 | 17 | # import package_example.formats.foo 18 | # print(type(package_example.formats.foo)) 19 | 20 | # from package_example.formats import foo 21 | # print(type(foo)) 22 | 23 | # import package_example.tools 24 | # print(package_example.tools.foo()) 25 | # print(package_example.tools.bar()) 26 | 27 | # from package_example.tools import rotate 28 | # print(rotate.rotate()) 29 | 30 | # import package_example.formats.jpg 31 | # import package_example.formats.bar 32 | # print(package_example.formats.bar.__name__) 33 | 34 | # import package_example 35 | 36 | # import package_example.tools.xyz 37 | 38 | # from . import info 39 | # print(info.__name__) 40 | 41 | import package_example.formats.foo 42 | print(package_example.formats.foo.sos(3, 4)) 43 | print(package_example.__path__) 44 | -------------------------------------------------------------------------------- /ch10/ch10_reload.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | # from importlib import reload # 3.4版 4 | from imp import reload # 3.4版之前 5 | # # 2.x版直接使用內建函式reload 6 | from time import sleep 7 | 8 | import ch10_reload_module 9 | 10 | while True: 11 | print('-' * 20) 12 | print(ch10_reload_module.pi) 13 | print(ch10_reload_module.data) 14 | print(ch10_reload_module.foo(3, 4)) 15 | sleep(5) 16 | reload(ch10_reload_module) 17 | 18 | -------------------------------------------------------------------------------- /ch10/ch10_reload_2.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | # from importlib import reload # 3.4版 4 | from imp import reload # 3.4版之前 5 | # # 2.x版直接使用內建函式reload 6 | from time import sleep 7 | 8 | import ch10_reload_module 9 | from ch10_reload_module import pi 10 | from ch10_reload_module import data 11 | from ch10_reload_module import foo 12 | 13 | while True: 14 | print('-' * 20) 15 | print(pi) 16 | print(data) 17 | print(foo(3, 4)) 18 | sleep(5) 19 | reload(ch10_reload_module) 20 | 21 | -------------------------------------------------------------------------------- /ch10/ch10_reload_module.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | 4 | pi = 3.14 5 | data = [30, 41, 52, 63, 74] 6 | z = 100 7 | 8 | def foo(x, y): 9 | return x + y + z 10 | 11 | -------------------------------------------------------------------------------- /ch10/myhello.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | a = 26 4 | b = 16 5 | 6 | import mymath 7 | 8 | def main(): 9 | print('Hello Python') 10 | print('pi is ' + str(mymath.pi)) 11 | print('gcd(%d, %d) is %d' % (a, b, mymath.gcd(a, b))) 12 | print('factorial(%d) is %d' % (6, mymath.factorial(6))) 13 | print('Bye Python') 14 | 15 | if __name__ == '__main__': 16 | print('%s as main program' % __name__) 17 | print('mymath.__name__ is %s ' % mymath.__name__) 18 | main() 19 | 20 | 21 | -------------------------------------------------------------------------------- /ch10/myhello2.py: -------------------------------------------------------------------------------- 1 | 2 | # import mymath2 3 | # print(mymath2._x) 4 | 5 | # from mymath2 import _x 6 | # print(_x) 7 | 8 | # from mymath3 import * 9 | # print(pi) 10 | # print(x) 11 | 12 | # from mymath3 import * 13 | # print(pi) 14 | # print(x) 15 | # print(y) 16 | 17 | from mymath3 import x 18 | print(x) 19 | -------------------------------------------------------------------------------- /ch10/mymath.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | pi = 3.14 4 | 5 | def gcd(a, b): 6 | while b: 7 | a, b = b, a%b 8 | return a 9 | 10 | def factorial(n): 11 | result = 1 12 | for i in range(1, n+1): 13 | result *= i 14 | return result 15 | 16 | if __name__ == '__main__': 17 | print('%s as main program' % __name__) 18 | 19 | 20 | -------------------------------------------------------------------------------- /ch10/mymath2.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | _x = 'xxx' 5 | _y = 3 6 | pi = 3.14 7 | def gcd(a, b): pass 8 | def factorial(n): pass 9 | def _z(): pass 10 | -------------------------------------------------------------------------------- /ch10/mymath3.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | __all__ = ['pi', 'gcd', 'factorial'] 4 | x = 'xxx' 5 | y = 3 6 | pi = 3.14 7 | def gcd(a, b): pass 8 | def factorial(n): pass 9 | def z(): pass 10 | -------------------------------------------------------------------------------- /ch10/package_example/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # from .. import * # error 5 | 6 | -------------------------------------------------------------------------------- /ch10/package_example/formats/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | def foo(): 3 | return 'foo' 4 | -------------------------------------------------------------------------------- /ch10/package_example/formats/bar.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def square(x): 4 | return x * x 5 | -------------------------------------------------------------------------------- /ch10/package_example/formats/bmp.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch10/package_example/formats/bmp.py -------------------------------------------------------------------------------- /ch10/package_example/formats/foo.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import sys 4 | sys.path.append('/cygdrive/d/yehnan/wr_python_drmaster/python_book_yehnan/ch10') 5 | 6 | # import package_example.formats.bar 7 | # square = package_example.formats.bar.square 8 | 9 | # from bar import square 10 | 11 | from . import bar 12 | square = bar.square 13 | 14 | # from .bar import square 15 | 16 | 17 | def sos(a, b): 18 | return square(a) + square(b) 19 | 20 | 21 | if __name__ == '__main__': 22 | if sos(3, 4) != 25: 23 | print('error') 24 | else: 25 | print('ok') 26 | 27 | 28 | -------------------------------------------------------------------------------- /ch10/package_example/formats/jpg.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from . import bar 4 | from .. import info 5 | from ..gui import display 6 | from ..gui import menu 7 | from ..gui.canvas import * 8 | 9 | print(bar.__name__) 10 | print(info.__name__) 11 | print(display()) 12 | print(menu.__name__) 13 | print(clear()) 14 | 15 | -------------------------------------------------------------------------------- /ch10/package_example/formats/png.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch10/package_example/formats/png.py -------------------------------------------------------------------------------- /ch10/package_example/gui/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | __all__= ['menu', 'canvas', 'display', 'draw'] 4 | 5 | def display(): 6 | return 'display' 7 | def draw(): 8 | return 'draw' 9 | 10 | 11 | -------------------------------------------------------------------------------- /ch10/package_example/gui/canvas.py: -------------------------------------------------------------------------------- 1 | 2 | def clear(): 3 | return 'clear' 4 | -------------------------------------------------------------------------------- /ch10/package_example/gui/menu.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch10/package_example/gui/menu.py -------------------------------------------------------------------------------- /ch10/package_example/info.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/ch10/package_example/info.py -------------------------------------------------------------------------------- /ch10/package_example/tools/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # from foo import * # 2.x 4 | # from bar import * # 2.x 5 | 6 | # from package_example.tools.foo import * 7 | # from package_example.tools.bar import * 8 | 9 | from .foo import * 10 | from .bar import * 11 | 12 | -------------------------------------------------------------------------------- /ch10/package_example/tools/bar.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def bar(): 4 | return 'bar' 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ch10/package_example/tools/foo.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def foo(): 4 | return 'foo' 5 | 6 | -------------------------------------------------------------------------------- /ch10/package_example/tools/rotate.py: -------------------------------------------------------------------------------- 1 | 2 | def rotate(): 3 | return 'rotate' 4 | 5 | -------------------------------------------------------------------------------- /ch10/package_example/tools/xyz/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | from ... import info 5 | 6 | print(info.__name__) 7 | -------------------------------------------------------------------------------- /ch10/path1/mymodule/sub1.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def foo(): 4 | return 'foo' 5 | -------------------------------------------------------------------------------- /ch10/path2/mymodule/sub2.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def bar(): 4 | return 'bar' 5 | -------------------------------------------------------------------------------- /ch11/ch11_abc.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from abc import ABCMeta, abstractmethod 4 | 5 | class S(metaclass=ABCMeta): 6 | # __metaclass__ = ABCMeta 7 | @abstractmethod 8 | def method_1(self, arg1): pass 9 | def method_2(self, arg1, arg2): pass 10 | 11 | # s = S() 12 | 13 | class Sub(S): 14 | def method_1(self, arg1): 15 | print(arg1) 16 | def method_2(self, arg1, arg2): 17 | print(arg1, arg2) 18 | 19 | s = Sub() 20 | s.method_1(3) 21 | s.method_2(3, 4) 22 | 23 | -------------------------------------------------------------------------------- /ch11/ch11_bankaccount.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class BankAccount(): 4 | def __init__(self): 5 | self.balance = 0 6 | def deposit(self, amount): 7 | self.balance += amount 8 | def withdraw(self, amount): 9 | self.balance -= amount 10 | def get_balance(self): 11 | return self.balance 12 | 13 | ac0 = BankAccount() 14 | print(ac0.balance) 15 | ac0.deposit(100) 16 | ac0.withdraw(30) 17 | print(ac0.get_balance()) 18 | ac1 = BankAccount() 19 | ac1.deposit(1000) 20 | print(ac1.get_balance()) 21 | 22 | print(type(BankAccount.deposit)) 23 | print(BankAccount.__init__) 24 | 25 | print(type(ac0.deposit)) 26 | print(type(ac0.__init__)) 27 | print(BankAccount) 28 | print(callable(BankAccount)) 29 | 30 | 31 | -------------------------------------------------------------------------------- /ch11/ch11_class_generator.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class FromNtoM(): 4 | def __init__(self, n, m): 5 | self.n = n 6 | self.m = m 7 | def __iter__(self): 8 | return self 9 | def __next__(self): 10 | if self.n < self.m: 11 | tmp, self.n = self.n, self.n+1 12 | return tmp 13 | else: 14 | raise StopIteration 15 | 16 | print(sum(FromNtoM(1, 100+1))) 17 | print(sum(range(1, 100+1))) 18 | 19 | 20 | -------------------------------------------------------------------------------- /ch11/ch11_foo.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class Foo(object): 4 | pass 5 | 6 | Foo.pi = 3.14 7 | print(Foo.pi) 8 | 9 | def gcd(a, b): # Greatest Common Divisor 10 | while b: 11 | a, b = b, a%b 12 | return a 13 | 14 | Foo.gcd = gcd 15 | print(Foo.gcd) 16 | 17 | 18 | class Bar(): 19 | def __init__(self): 20 | self.x = 3 21 | def xxx(): 22 | print('hello') 23 | def yyy(aa): 24 | print('hello', aa.x) 25 | Bar.xxx() 26 | b = Bar() 27 | # b.xxx() 28 | b.yyy() 29 | -------------------------------------------------------------------------------- /ch11/ch11_frange.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class Frange(): 4 | def __init__(self, start, stop=None, step=None): 5 | self.start = start + 0.0 6 | self.stop = stop 7 | self.step = step 8 | if self.stop is None: 9 | self.stop = self.start + 0.0 10 | self.start = 0.0 11 | if self.step is None: 12 | self.step = 1.0 13 | def __iter__(self): 14 | return self 15 | def __next__(self): 16 | next = self.start 17 | self.start += self.step 18 | if abs(next) < abs(self.stop): 19 | return next 20 | else: 21 | raise StopIteration 22 | 23 | for x in Frange(3): 24 | print(x) 25 | print([i for i in Frange(2.55, 3.7, 0.1)]) 26 | print([i for i in Frange(0, 1, 0.1)]) 27 | -------------------------------------------------------------------------------- /ch11/ch11_inherit.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class A(): 4 | x, y = 3, 4 5 | def __init__(self, a, b): 6 | self.a = a 7 | self.b = b 8 | def foo(self): 9 | print(self.a + self.b + self.x + self.y) 10 | class B(A): 11 | ww = 1000 12 | x = 1003 13 | def bar(self): 14 | self.foo() 15 | print(self.x + self.ww) 16 | 17 | a0 = A(13, 14) 18 | a0.foo() 19 | b0 = B(103, 104) 20 | b0.foo() 21 | b0.bar() 22 | 23 | -------------------------------------------------------------------------------- /ch11/ch11_mi.py: -------------------------------------------------------------------------------- 1 | 2 | class S(): 3 | def foo(self): pass 4 | class A(S): 5 | def foo(self): print('A foo') 6 | class B(S): 7 | def foo(self): print('B foo') 8 | class C(A, B): 9 | pass 10 | C().foo() 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ch11/ch11_mi2.py: -------------------------------------------------------------------------------- 1 | 2 | class A(object): pass 3 | class B(object): pass 4 | class X(A, B): pass 5 | class Y(B, A): pass 6 | class Z(X, Y): pass 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ch11/ch11_myclass.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class Person(): 4 | def __init__(self, name, age, height, weight): 5 | self.name = name 6 | self.age = age 7 | self.height = height 8 | self.weight = weight 9 | 10 | # p1 = Person() 11 | p2 = Person('John', 22, 170, 60) 12 | p3 = Person('Amy', 17, 160, 42) 13 | 14 | 15 | class Book(): 16 | def __init__(self, title, cover_price, discount=1.0): 17 | self.title = title 18 | self.cover_price = cover_price 19 | self.discount = discount 20 | def get_title(self): return self.title 21 | def get_cover_price(self): return self.cover_price 22 | def get_discount(self): return self.discount 23 | def set_discount(self, discount): self.discount = discount 24 | def get_price(self): return int(self.cover_price * self.discount) 25 | 26 | b1 = Book('Make Wishes', 300) 27 | b2 = Book('Fun of cooking', 500, 0.79) 28 | print(b2.get_price()) 29 | print('-' * 20) 30 | 31 | class MyClass(): 32 | x, y, z = 3, 4, 5 33 | def sfoo(): 34 | # print(z) 35 | print(MyClass.z) 36 | def __init__(self, x, y): 37 | self.x = x 38 | self.y = y 39 | def foo(self): print(self.x + self.z) 40 | def bar(self): 41 | # print(self.y - z) 42 | print(self.y - MyClass.z) 43 | 44 | c0 = MyClass(33, 44) 45 | MyClass.sfoo() # 5 46 | # c0.sfoo() 47 | c0.foo() # 38 48 | c0.bar() # 39 49 | 50 | 51 | -------------------------------------------------------------------------------- /ch11/ch11_myclass_scope.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def foo(): 4 | x = 3 5 | def bar(): 6 | print(x) 7 | bar() 8 | foo() 9 | 10 | class MyClass(): 11 | x = 3 12 | def foo(): 13 | print(x) 14 | def bar(self): 15 | # print(x) 16 | print(self.x) 17 | # MyClass.foo() 18 | MyClass().bar() 19 | -------------------------------------------------------------------------------- /ch11/ch11_orderedset.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # http://code.activestate.com/recipes/576694-orderedset/ 4 | import collections 5 | 6 | class OrderedSet(collections.MutableSet): 7 | def __init__(self, iterable=None): 8 | self.end = end = [] 9 | end += [None, end, end] # sentinel node for doubly linked list 10 | self.map = {} # key --> [key, prev, next] 11 | if iterable is not None: 12 | self |= iterable 13 | 14 | def __len__(self): return len(self.map) 15 | 16 | def __contains__(self, key): return key in self.map 17 | 18 | def add(self, key): 19 | if key not in self.map: 20 | end = self.end 21 | curr = end[1] 22 | curr[2] = end[1] = self.map[key] = [key, curr, end] 23 | 24 | def discard(self, key): 25 | if key in self.map: 26 | key, prev, next = self.map.pop(key) 27 | prev[2] = next 28 | next[1] = prev 29 | 30 | def __iter__(self): 31 | end = self.end 32 | curr = end[2] 33 | while curr is not end: 34 | yield curr[0] 35 | curr = curr[2] 36 | 37 | def __reversed__(self): 38 | end = self.end 39 | curr = end[1] 40 | while curr is not end: 41 | yield curr[0] 42 | curr = curr[1] 43 | 44 | def pop(self, last=True): 45 | if not self: 46 | raise KeyError('set is empty') 47 | key = self.end[1][0] if last else self.end[2][0] 48 | self.discard(key) 49 | return key 50 | 51 | def __repr__(self): 52 | if not self: 53 | return '%s()' % (self.__class__.__name__,) 54 | return '%s(%r)' % (self.__class__.__name__, list(self)) 55 | 56 | def __eq__(self, other): 57 | if isinstance(other, OrderedSet): 58 | return len(self) == len(other) and list(self) == list(other) 59 | return set(self) == set(other) 60 | 61 | 62 | if __name__ == '__main__': 63 | s = OrderedSet('abracadaba') 64 | t = OrderedSet('simsalabim') 65 | print(s) 66 | print(t) 67 | print(s | t) 68 | print(s & t) 69 | print(s - t) 70 | -------------------------------------------------------------------------------- /ch11/ch11_private.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class A(): 4 | def bar(self): return 4 5 | def foo(self): return 3 + self.bar() 6 | class B(A): 7 | def bar(self): return 104 8 | 9 | b = B() 10 | print(b.foo()) 11 | 12 | class A(): 13 | def __bar(self): return 4 14 | def foo(self): return 3 + self.__bar() 15 | class B(A): 16 | def bar(self): return 104 17 | def bm(self): return self.bar() + 1000 18 | 19 | b = B() 20 | print(b.foo()) 21 | print(b.bm()) 22 | print(b._A__bar()) 23 | 24 | 25 | -------------------------------------------------------------------------------- /ch11/ch11_property.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class Person(): 4 | def __init__(self, name): 5 | self._name = name 6 | @property 7 | def name(self): 8 | # 9 | return self._name 10 | @name.setter 11 | def name(self, value): 12 | # 13 | self._name = value 14 | @name.deleter 15 | def name(self): 16 | # 17 | del self._name 18 | p = Person('John') 19 | print(p.name) 20 | p.name = 'Amy' 21 | print(p.name) 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /ch11/ch11_static_class_method.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class MyClass(): 4 | @staticmethod 5 | def foo(arg1, arg2): print(arg1, arg2) 6 | @classmethod 7 | def bar(cls, arg1): print(cls, arg1) 8 | MyClass.foo(3, 4) 9 | MyClass.bar(5) 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /ch11/ch11_test.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class A(object): 4 | x, y = 3, 4 5 | def __init__(self, a, b): 6 | self.a = a 7 | self.b = b 8 | def foo(self): 9 | print(self.a + self.b + self.x + self.y) 10 | class B(A): 11 | ww = 1000 12 | x = 1003 13 | def __init__(self): 14 | # self.__init__(13, 14) 15 | # A.__init__(self, 13, 14) 16 | # super(B, self).__init__(13, 14) 17 | super().__init__(13, 14) 18 | self.c = 15 19 | def bar(self): 20 | self.foo() 21 | print(self.x + self.ww) 22 | 23 | a0 = A(13, 14) 24 | a0.foo() 25 | b0 = B() 26 | b0.foo() 27 | b0.bar() 28 | -------------------------------------------------------------------------------- /ch11/ch11_test2.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class A(): 4 | x = 3 5 | def __init__(self): 6 | self.x = 33 7 | 8 | 9 | class B(A): 10 | x = 4 11 | def __init__(self): 12 | super().__init__() 13 | self.z = 1000 14 | b = B() 15 | print(b.x) 16 | -------------------------------------------------------------------------------- /ch11/ch11_test3.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class Animal(): 4 | def shout(self): print('Animal shout') 5 | class Dog(Animal): 6 | def shout(self): print('Dog shout') 7 | class Cat(Animal): 8 | def shout(self): print('Cat shout') 9 | def __str__(self): return 'I am a cat' 10 | 11 | d = Dog(); d.shout() 12 | c = Cat(); c.shout() 13 | print(c) 14 | 15 | class MyClass(): 16 | def __str__(self): return 'a MyClass instance' 17 | mc = MyClass() 18 | print(str(mc)) 19 | print(mc) 20 | 21 | 22 | -------------------------------------------------------------------------------- /ch11/ch11_test4.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class MyC(): 4 | def __init__(self): 5 | self.x = 3 6 | self.y = 4 7 | def __hash__(self): 8 | return 100 9 | a = MyC() 10 | b = MyC() 11 | print(hash(a)) 12 | print(hash(b)) 13 | 14 | from collections import Hashable 15 | 16 | print(issubclass(MyC, Hashable)) 17 | 18 | 19 | -------------------------------------------------------------------------------- /ch11/ch11_test5.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class MyClass(): 4 | x, y = 3, 4 5 | def foo(self): 6 | print(x + y) 7 | def bar(self): 8 | print(self.x + self.y) 9 | MyClass().foo() 10 | MyClass().bar() 11 | -------------------------------------------------------------------------------- /ch11/ch11_test6.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class A(object): 4 | def __init__(self): 5 | super(A, self).__init__() 6 | print('A') 7 | 8 | class B(object): 9 | def __init__(self): 10 | super(B, self).__init__() 11 | print('B') 12 | 13 | class C(A, B): 14 | def __init__(self): 15 | super(C, self).__init__() 16 | # super().__init__() 17 | print('C') 18 | C() 19 | -------------------------------------------------------------------------------- /ch12/ch12_2.x_old_syntax.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # different in 2.x and 3.x 4 | try: 5 | [0, 1, 2][999] 6 | except IndexError, ValueError: 7 | print('hi') 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /ch12/ch12_as_e.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | def f(): 5 | try: 6 | [0, 1, 2][999] 7 | except IndexError as e: 8 | print(e) 9 | finally: 10 | print(e) 11 | print(e) 12 | f() 13 | 14 | def f(): 15 | exc = None 16 | try: 17 | [0, 1, 2][999] 18 | except IndexError as e: 19 | exc = e 20 | print(exc) 21 | finally: 22 | print(exc) 23 | print(exc) 24 | f() 25 | 26 | -------------------------------------------------------------------------------- /ch12/ch12_assert.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | def fact(n): 5 | assert type(n) is int 6 | assert n < 0 7 | result = 1 8 | for i in range(1, n+1): 9 | result *= i 10 | return result 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ch12/ch12_fact.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def fact(n): 4 | result = 1 5 | for i in range(1, n+1): 6 | result *= i 7 | return result 8 | 9 | while True: 10 | s = input('input n: ') 11 | f = fact(int(s)) 12 | print('%s! = %d' % (s, f)) 13 | 14 | -------------------------------------------------------------------------------- /ch12/ch12_fact_2.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def fact(n): 4 | if type(n) is not int or n < 0: 5 | return None 6 | result = 1 7 | for i in range(1, n+1): 8 | result *= i 9 | return result 10 | 11 | while True: 12 | s = input('input n: ') 13 | f = fact(int(s)) 14 | if f is not None: 15 | print('%s! = %d' % (s, f)) 16 | else: 17 | print('n must be a non-negative integer') 18 | 19 | 20 | -------------------------------------------------------------------------------- /ch12/ch12_fact_exception.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | def fact(n): 4 | if type(n) is not int: 5 | raise TypeError 6 | if n < 0: 7 | raise ValueError('Argument must be non-negative') 8 | result = 1 9 | for i in range(1, n+1): 10 | result *= i 11 | return result 12 | 13 | while True: 14 | try: 15 | s = input('input n: ') # 2.x版改用raw_input 16 | f = fact(int(s)) 17 | except TypeError: 18 | print('%s is not an integer' % s) 19 | break 20 | except ValueError as e: 21 | print('%s can not be less than 0' % s) 22 | break 23 | print('%s! = %d' % (s, f)) 24 | 25 | 26 | -------------------------------------------------------------------------------- /ch12/ch12_fact_exception_2.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | def fact(n): 4 | if type(n) is not int: 5 | raise TypeError('Argument must be type int') 6 | if n < 0: 7 | raise ValueError('Argument must be non-negative') 8 | result = 1 9 | for i in range(1, n+1): 10 | result *= i 11 | return result 12 | 13 | while True: 14 | try: 15 | s = input('input n: ') # 2.x版改用raw_input 16 | f = fact(int(s)) 17 | except (EOFError, KeyboardInterrupt) as e: 18 | print('Bye') 19 | break 20 | except TypeError as e: 21 | print('Error: ' + str(e)) 22 | except ValueError as e: 23 | print('Error: ' + str(e)) 24 | except Exception: 25 | print('Error: unknown error') 26 | else: 27 | print('%s! = %d' % (s, f)) 28 | 29 | -------------------------------------------------------------------------------- /ch12/ch12_flow.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def foo(): 4 | try : 5 | raise ValueError 6 | except IndexError: 7 | print('IndexError') 8 | finally: 9 | print('foo finally') 10 | print('foo end') 11 | def bar(): 12 | try: 13 | foo() 14 | except ValueError: 15 | print('ValueError') 16 | finally: 17 | print('bar finally') 18 | print('bar end') 19 | bar() 20 | print('program end') 21 | 22 | -------------------------------------------------------------------------------- /ch12/ch12_foo_exception.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | class FooException(Exception): 5 | def __init__(self, msg, status): 6 | Exception.__init__(self, msg, status) 7 | self.msg = msg 8 | self.status = status 9 | 10 | try: 11 | raise FooException('hello', 'sta') 12 | except FooException as e: 13 | print(e) -------------------------------------------------------------------------------- /ch12/ch12_list_bound.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # def get(li, n): 4 | # try: 5 | # li[n] 6 | # except IndexError as e: 7 | # print('get IndexError') 8 | # raise 9 | 10 | def get(li, n): 11 | try: 12 | li[n] 13 | except IndexError as e: 14 | s = 'index %d, len of list is %d' % (n, len(li)) 15 | raise IndexError(s) from e 16 | 17 | li = [0, 1, 2] 18 | get(li, 99) 19 | 20 | -------------------------------------------------------------------------------- /ch12/ch12_no_with.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | from io import open 4 | 5 | try: 6 | fin = open('test.txt', 'r', encoding='utf-8') 7 | try: 8 | for line in fin: 9 | print(line) 10 | except UnicodeError as e: 11 | print('Error while reading file: ' + str(e)) 12 | except Exception as e: 13 | print('Error while reading file: ' + str(e)) 14 | finally: 15 | fin.close() 16 | except Exception as e: 17 | print('Error while opening file: ' + str(e)) 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /ch12/test.txt: -------------------------------------------------------------------------------- 1 | abc 2 | 123 3 | 你我他 4 | xyz 5 | -------------------------------------------------------------------------------- /ch13/ch13_argparse.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import argparse 4 | 5 | parser = argparse.ArgumentParser(description='Count lines in text files') 6 | 7 | parser.add_argument(dest='path', metavar='path') 8 | 9 | parser.add_argument('-e', dest='extensions', action='append', 10 | metavar='extension', required=True, 11 | help='filename extensions to process') 12 | 13 | parser.add_argument('-b', dest='blankline', action='store_true', 14 | help='blank line') 15 | 16 | parser.add_argument('-r', dest='recur', action='store_true', 17 | help='recursively into subdirectories') 18 | 19 | parser.add_argument('-o', dest='outfile', action='store', 20 | help='output file') 21 | 22 | parser.add_argument('--speed', dest='speed', action='store', 23 | choices={'slow','fast'}, default='fast', 24 | help='processing speed') 25 | 26 | args = parser.parse_args() 27 | 28 | print('path', args.path) 29 | print('extensions', args.extensions) 30 | print('blankline', args.blankline) 31 | print('recur', args.recur) 32 | print('outfile', args.outfile) 33 | print('speed', args.speed) 34 | 35 | -------------------------------------------------------------------------------- /ch13/ch13_argv.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import sys 4 | 5 | print(sys.argv) 6 | 7 | -------------------------------------------------------------------------------- /ch13/ch13_argv_basic.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import sys 4 | 5 | def main(infile, outfile): 6 | print(infile, outfile) 7 | 8 | def proc_argv(argv): 9 | infile, outfile = None, None 10 | infile = argv[0] 11 | try: 12 | outfile = argv[1] 13 | except Exception: 14 | outfile = infile + '.out' 15 | print("Warning: output filename defaults to " + outfile) 16 | return infile, outfile 17 | 18 | if __name__ == '__main__': 19 | try: 20 | inf, outf = proc_argv(sys.argv[1:]) 21 | except Exception: 22 | print("At least specify input filename") 23 | sys.exit() 24 | main(inf, outf) 25 | -------------------------------------------------------------------------------- /ch13/ch13_dining_ph.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import random 4 | import time 5 | import threading 6 | from contextlib import contextmanager 7 | 8 | # Thread-local state to stored information on locks already acquired 9 | _local = threading.local() 10 | 11 | @contextmanager 12 | def acquire(*locks): 13 | # Sort locks by object identifier 14 | locks = sorted(locks, key=lambda x: id(x)) 15 | # Make sure lock order of previously acquired locks is not violated 16 | acquired = getattr(_local, 'acquired', []) 17 | if acquired and max(id(lock) for lock in acquired) >= id(locks[0]): 18 | raise RuntimeError('Lock Order Violation') 19 | # Acquire all of the locks 20 | acquired.extend(locks) 21 | _local.acquired = acquired 22 | 23 | try: 24 | for lock in locks: 25 | lock.acquire() 26 | yield 27 | finally: 28 | # Release locks in reverse order of acquisition 29 | for lock in reversed(locks): 30 | lock.release() 31 | del acquired[-len(locks):] 32 | 33 | # The philosopher thread 34 | def philosopher(id, left, right): 35 | while True: 36 | with acquire(left, right): 37 | print(id, 'eating') 38 | time.sleep(random.random()) 39 | print(id, 'thinking') 40 | time.sleep(random.random()) 41 | 42 | # The sticks (represented by locks) 43 | num_sticks = 5 44 | sticks_lock = [threading.Lock() for n in range(num_sticks)] 45 | 46 | # Create all of the philosophers 47 | for n in range(num_sticks): 48 | t = threading.Thread(target=philosopher, 49 | args=(n, sticks_lock[n], 50 | sticks_lock[(n+1) % num_sticks])) 51 | t.start() 52 | 53 | 54 | -------------------------------------------------------------------------------- /ch13/ch13_ticket.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import random 4 | import time 5 | from threading import Thread, Lock 6 | 7 | num_agents = 10 8 | num_tickets = [100] 9 | 10 | def sell_tickets(agent_id, nt, lock): 11 | total = 0 12 | while True: 13 | with lock: 14 | if nt[0] > 0: 15 | print('Agent %d sells a ticket No. %d' % (agent_id, nt[0])) 16 | nt[0] -= 1 17 | total += 1 18 | elif nt[0] == 0: 19 | break; 20 | #time.sleep(random.randrange(1, 3)) 21 | time.sleep(random.random() * (1 + agent_id/2)) 22 | print('Agent %d done. Totally sells %d tickets' % (agent_id, total)) 23 | 24 | lock = Lock() 25 | for i in range(num_agents): 26 | t = Thread(target=sell_tickets, args=(i, num_tickets, lock)) 27 | t.start() 28 | 29 | -------------------------------------------------------------------------------- /ch13/ch13_tkinter.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from tkinter import * 4 | 5 | def fib(n): 6 | a, b = 0, 1 7 | for i in range(n): 8 | a, b = b, a+b 9 | return a 10 | 11 | class App(Frame): 12 | def __init__(self, master=None): 13 | Frame.__init__(self, master) 14 | self.pack() 15 | 16 | self.entry_n = Entry(self, width=10) 17 | self.entry_n.pack() 18 | 19 | self.fn = StringVar() 20 | self.label_fn = Label(self, textvariable=self.fn, 21 | width=50) 22 | self.fn.set('result') 23 | self.label_fn.pack() 24 | 25 | self.btn_cal = Button(self, text="Calculate", 26 | command=self.cal_fib) 27 | self.btn_cal.pack() 28 | 29 | self.btn_quit = Button(self, text="Quit", fg="red", 30 | command=root.destroy) 31 | self.btn_quit.pack(side=BOTTOM) 32 | 33 | def cal_fib(self): 34 | try: 35 | n = int(self.entry_n.get()) 36 | self.fn.set(str(fib(n))) 37 | except Exception: 38 | self.fn.set('Invalid input') 39 | 40 | root = Tk() 41 | app = App(root) 42 | app.mainloop() 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/cover.jpg -------------------------------------------------------------------------------- /misc/c_rw.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yehnan/python_book_yehnan/b1e1e0be5731160c36d53eaf7a1cee3ac03f30d9/misc/c_rw.py -------------------------------------------------------------------------------- /misc/c_ticket.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 電影院賣票 10個售票員(窗口) 共150張票 3 | # 每人負責15張 4 | # future: 有些售票員動作較慢,也有可能他的客人動作較慢,讓動作快的人負責賣較多張的票 5 | # future: 有些售票員可能突然肚子痛,關閉窗口;之後再回來賣票 6 | 7 | import random 8 | import time 9 | from threading import Thread 10 | 11 | print('main start') 12 | 13 | numAgents = 10 14 | numTickets = 150 15 | 16 | random.seed() 17 | 18 | def sellTickets(agentID, numTicketsToSell): 19 | while numTicketsToSell > 0: 20 | print('Agent ', agentID, ' sells a ticket ', numTicketsToSell) 21 | numTicketsToSell -= 1 22 | time.sleep(random.randrange(1, 3)) # simulating the time needed for selling a ticket 23 | print('Agent ', agentID, ' all down') 24 | 25 | ts = [] 26 | for i in range(numAgents): 27 | t = Thread(target=sellTickets, args=(i, numTickets//numAgents)) 28 | ts.append(t) 29 | 30 | for i in range(numAgents): 31 | ts[i].start() 32 | 33 | print('main end') 34 | 35 | -------------------------------------------------------------------------------- /misc/ch04_base26_aa_zz.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # A B C D... Z AA AB AZ BA 4 | # 1 26 27 28 52 53 5 | # note: there is no zero 6 | 7 | alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 8 | base = len(alphabet) 9 | 10 | # from int to str, number must >= 1 11 | def base26encode(number, width=0): 12 | result = [] 13 | while number-1 >= base: 14 | number, i = divmod(number-1, base) 15 | result.append(alphabet[i]) 16 | result.append(alphabet[number-1]) 17 | 18 | # padding 19 | result.extend([alphabet[0]] * (width - len(result))) 20 | 21 | return ''.join(reversed(result)) 22 | 23 | # from str to int, 'A', 'B', ...'Z', 'AA', ...'AZ', ... 24 | def base26decode(s): 25 | s = s.upper() 26 | number = 0 27 | for n in s: 28 | number *= base 29 | number += alphabet.index(n) + 1 30 | return number 31 | 32 | print('a ', base26decode('a')) 33 | print(base26encode(base26decode('a') + 1)) 34 | print('b ', base26decode('b')) 35 | print(base26encode(base26decode('b') + 1)) 36 | print('aa ', base26decode('aa')) 37 | print(base26encode(base26decode('aa') + 1)) 38 | print('ab ', base26decode('ab')) 39 | print(base26encode(base26decode('ab') + 1)) 40 | print('z ', base26decode('z')) 41 | print(base26encode(base26decode('z') + 1)) 42 | print('az ', base26decode('az')) 43 | print(base26encode(base26decode('az') + 1)) 44 | print('ba ', base26decode('ba')) 45 | print(base26encode(base26decode('ba') + 1)) 46 | print('bz ', base26decode('bz')) 47 | print(base26encode(base26decode('bz') + 1)) 48 | print('zz ', base26decode('zz')) 49 | print(base26encode(base26decode('zz') + 1)) 50 | print('------') 51 | print('at ', base26decode('at')) 52 | print(base26encode(base26decode('at') + 1, 2)) 53 | print('bzz ', base26decode('bzz')) 54 | print(base26encode(base26decode('bzz') + 1, 4)) 55 | print('zz ', base26decode('zz')) 56 | print(base26encode(base26decode('zz') + 1, 4)) 57 | print('-' * 40) 58 | 59 | 60 | -------------------------------------------------------------------------------- /misc/ch04_base26_aa_zz_no_padding.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # A B C D... Z AA AB AZ BA 4 | # 1 26 27 28 52 53 5 | # note: there is no zero 6 | 7 | alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 8 | base = len(alphabet) 9 | 10 | # from int to str, number must >= 1 11 | def base26encode(number): 12 | result = [] 13 | while number-1 >= base: 14 | number, i = divmod(number-1, base) 15 | result.append(alphabet[i]) 16 | result.append(alphabet[number-1]) 17 | 18 | return ''.join(reversed(result)) 19 | 20 | # from str to int, 'A', 'B', ...'Z', 'AA', ...'AZ', ... 21 | def base26decode(s): 22 | s = s.upper() 23 | number = 0 24 | for n in s: 25 | number *= base 26 | number += alphabet.index(n) + 1 27 | return number 28 | 29 | print('a ', base26decode('a')) 30 | print(base26encode(base26decode('a') + 1)) 31 | print('b ', base26decode('b')) 32 | print(base26encode(base26decode('b') + 1)) 33 | print('aa ', base26decode('aa')) 34 | print(base26encode(base26decode('aa') + 1)) 35 | print('ab ', base26decode('ab')) 36 | print(base26encode(base26decode('ab') + 1)) 37 | print('z ', base26decode('z')) 38 | print(base26encode(base26decode('z') + 1)) 39 | print('az ', base26decode('az')) 40 | print(base26encode(base26decode('az') + 1)) 41 | print('ba ', base26decode('ba')) 42 | print(base26encode(base26decode('ba') + 1)) 43 | print('bz ', base26decode('bz')) 44 | print(base26encode(base26decode('bz') + 1)) 45 | print('zz ', base26decode('zz')) 46 | print(base26encode(base26decode('zz') + 1)) 47 | print('bzz ', base26decode('bzz')) 48 | print(base26encode(base26decode('bzz') + 1)) 49 | print('------') 50 | print('-' * 40) 51 | 52 | 53 | -------------------------------------------------------------------------------- /misc/ch05_stu_d.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | name, id, age, score_math, score_eng = range(0, 4+1) 4 | amy = ['Amy Chen', 14001, 17, 92, 75] 5 | john = ['John Smith', 14009, 18, 81, 84] 6 | 7 | print(amy[name]) 8 | print(amy[age]) 9 | print(john[score_math]) 10 | print(john[score_eng]) 11 | 12 | amy = { 13 | 'name': 'Amy Chen', 14 | 'id': 14001, 15 | 'age': 17, 16 | 'score_math': 92, 17 | 'score_eng': 75, 18 | } 19 | john = { 20 | 'name': 'John Smith', 21 | 'id': 14009, 22 | 'age': 18, 23 | 'score_math': 81, 24 | 'score_eng': 84, 25 | } 26 | 27 | print(amy['name']) 28 | print(amy['age']) 29 | print(john['score_math']) 30 | print(john['score_eng']) 31 | 32 | 33 | -------------------------------------------------------------------------------- /misc/ch05_stu_data.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # dept is department 4 | name, id, age, dept, scores = range(0, 4+1) 5 | dept_phy = 'physics' 6 | dept_math = 'mathematics' 7 | dept_cs = 'computer science' 8 | # calculus, python, electromagnetism, history 9 | s_cal, s_ph, s_em, s_his = range(0, 3+1) 10 | students = [ 11 | ['Amy Chen', '14001', '21', dept_phy, [90, 82, 95, None]], 12 | ['John Smith', '14003', '20', dept_math, [92, 82, None, 71]], 13 | ['Elsa Iceman', '14007', '24', dept_math, [93, 92, None, 73]], 14 | ['Penny Kuan', '14012', '22', dept_cs, [81, 99, 82, None]] 15 | ] 16 | print(students) 17 | print(students[0][name]) 18 | print(students[1][id]) 19 | print(students[2][age]) 20 | print(students[3][dept]) 21 | print(students[3][scores]) 22 | print(students[3][scores][s_cal]) 23 | 24 | -------------------------------------------------------------------------------- /misc/scope_comprehension.py: -------------------------------------------------------------------------------- 1 | 2 | # i = 'abc' 3 | # print(i) 4 | # x = [i**2 for i in range(10)] 5 | # print(i) # 2.x 3.x different 6 | 7 | # i = 'abc' 8 | # print(i) 9 | # x = {i**2 for i in range(10)} 10 | # print(i) 11 | 12 | # i = 'abc' 13 | # print(i) 14 | # x = {i:i**2 for i in range(10)} 15 | # print(i) 16 | 17 | # i = 'abc' 18 | # print(i) 19 | # x = (i**2 for i in range(10)) 20 | # print(i) 21 | 22 | # i = 'abc' 23 | # print(i) 24 | # for i in range(10): 25 | # pass 26 | # print(i) 27 | 28 | # print(globals()) 29 | -------------------------------------------------------------------------------- /misc/u_to_enc.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | import big5uao 4 | import codecs 5 | 6 | enc_utf_16_be = codecs.getencoder('utf_16_be') 7 | enc_big5uao = codecs.getencoder('big5uao') 8 | enc_gbk = codecs.getencoder('gbk') 9 | 10 | encs = (enc_utf_16_be, enc_big5uao, enc_gbk) 11 | 12 | s = '煊喆凜凛遙遥阪坂齊斉齐齋斎榮荣栄富冨樫堅島嶋崎﨑邊边辺絕绝對对対涉澀渋瑠鹽塩盐汙污汚櫻桜鐮镰鎌高髙癡痴' 13 | 14 | for c in s: 15 | fs = [c, ' '] 16 | for enc in encs: 17 | d, e = enc(c) 18 | x = '%02X%02X' % (d[0], d[1]) 19 | fs.append(x) 20 | fs.append(' ') 21 | print(''.join(fs)) 22 | 23 | 24 | print(len(s)) 25 | --------------------------------------------------------------------------------