├── README.md ├── __admin__ ├── __pycache__ │ ├── dirdiff.cpython-33.pyc │ └── visitor.cpython-33.pyc ├── cleanpyc-run.txt ├── cleanpyc.py ├── diffall-run-full.txt ├── diffall-run.txt ├── diffall.py ├── dirdiff.py ├── visitor.py ├── visitor_sloc-run.txt └── visitor_sloc.py ├── __pycache__ ├── access.cpython-33.pyo ├── access_builtins.cpython-33.pyo ├── dicts.cpython-33.pyc ├── factorials.cpython-33.pyc ├── mymod.cpython-33.pyc ├── mymod2.cpython-33.pyc ├── rangetest.cpython-33.pyo ├── rangetest1.cpython-33.pyo └── reversals.cpython-33.pyc └── code ├── Certificate.html ├── Certificate.txt ├── PythonPoweredSmall.gif ├── __pycache__ ├── access.cpython-33.pyo ├── access_builtins.cpython-33.pyo ├── dicts.cpython-33.pyc ├── factorials.cpython-33.pyc ├── mymod.cpython-33.pyc ├── mymod2.cpython-33.pyc ├── rangetest.cpython-33.pyo ├── rangetest1.cpython-33.pyo └── reversals.cpython-33.pyc ├── a.py ├── a1 └── b │ ├── a1.py │ └── mod.py ├── access-desc-test.py ├── access-test.py ├── access.py ├── access1.py ├── access2.py ├── access2_builtins0.py ├── access2_builtins1.py ├── access2_builtins2.py ├── access2_builtins2b.py ├── access2_builtins3.py ├── access2_builtins3b.py ├── access2_builtins4.py ├── access2_inserts.py ├── access_builtins.py ├── access_builtins_desc.py ├── access_desc.py ├── adder.py ├── adder2.py ├── adders.py ├── alls.py ├── argtest.py ├── argtest_testmeth.py ├── asserter.py ├── attrs1.py ├── b.py ├── bad.py ├── badly.exc ├── badly.py ├── bothmethods.py ├── bothmethods_decorators.py ├── brian ├── c.py ├── callables.py ├── calltracer-descr.py ├── calltracer.py ├── certificate.py ├── changer.py ├── classexc.py ├── classexc2.py ├── classscope.py ├── classtools.py ├── classtree.py ├── collector.py ├── commuter.py ├── contains.py ├── contains_yield.py ├── converters.py ├── countdown.py ├── csvdata.txt ├── data.bin ├── data.txt ├── datafile.pkl ├── decoall-deco-any.py ├── decoall-deco-any2.py ├── decoall-deco-any3.py ├── decoall-manual.py ├── decoall-meta-any.py ├── decoall-meta-any2.py ├── decoall-meta-any3.py ├── decoall-meta.py ├── decoargs-vs-annotations.py ├── decorator1.py ├── decorator2.py ├── decorator3.py ├── decorator4.py ├── decorator5.py ├── decotools.py ├── desc-computed.py ├── desc-person-nested.py ├── desc-person.py ├── desc-powers.py ├── desc-state-desc.py ├── desc-state-inst.py ├── dicts.py ├── dicttable.py ├── dir1 ├── __init__.py └── dir2 │ ├── __init__.py │ └── mod.py ├── divbad.py ├── docstr.py ├── docstrings.py ├── domparse.py ├── dualpkg ├── m1.py ├── m2.py └── results.txt ├── main.py ├── makedb.py ├── makeopen.py ├── makeopen_class.py ├── maker.py ├── manage-inst-deco.py ├── manage-inst-meta.py ├── manynames.py ├── mapattrs-lister.py ├── mapattrs-slots.py ├── mapattrs.py ├── mapattrs_getattr.py ├── mapattrs_noslots.py ├── mergedexc.py ├── metaclass1-2x-nosuper.py ├── metaclass1-2x.py ├── metaclass1.py ├── metaclass2.py ├── metaclass3.py ├── metaclass4-super.py ├── metaclass4.py ├── metaclass5-hmm.py ├── metaclass5.py ├── metaclass5b.py ├── metainstance.py ├── minmax.py ├── minmax2.py ├── mins.py ├── mod.py ├── mod1.py ├── mod2.py ├── mod3.py ├── moda.py ├── modb.py ├── module1.py ├── module2.py ├── multiset.py ├── mybooks.xml ├── myclient.py ├── mydir.py ├── myfile ├── myfile.py ├── mylist.py ├── mymap.py ├── mymod.py ├── mymod2.py ├── mypkg ├── __init__.py └── mymod.py ├── mypydoc.py ├── mysub.py ├── nested1.py ├── nested2.py ├── nested3.py ├── nestexc.py ├── ns ├── dir1 │ └── sub │ │ ├── mod1.py │ │ └── pkg │ │ └── __init__.py └── dir2 │ └── sub │ ├── lower │ └── mod3.py │ └── mod2.py ├── ns3 └── dir │ └── ns2.py ├── number.py ├── oops.py ├── oops2.py ├── ora-lp.jpg ├── otherfile.py ├── parrot.py ├── patternparse.py ├── permute.py ├── person-composite.py ├── person-department.py ├── person.py ├── persondb.bak ├── persondb.dat ├── persondb.dir ├── pizzashop.py ├── pkg ├── eggs.py ├── main.py └── spam.py ├── primes.py ├── print3.py ├── print3_alt1.py ├── print3_alt2.py ├── printnest.py ├── private0.py ├── prop-computed.py ├── prop-desc-equiv.py ├── prop-person-deco.py ├── prop-person.py ├── prop-powers.py ├── pseudoprivate.py ├── py2x └── script0.py ├── py3x └── script0.py ├── pybench.py ├── pybench2.py ├── pybench2_cases-results-a-t.txt ├── pybench2_cases-results-a.txt ├── pybench2_cases-results.txt ├── pybench2_cases.py ├── pybench_cases-results.txt ├── pybench_cases.py ├── pybench_cases0-results.txt ├── pybench_cases0.py ├── pybench_cases2-results-a-t.txt ├── pybench_cases2-results-a.txt ├── pybench_cases2-results.txt ├── pybench_cases2.py ├── pydoc-py33.py ├── pydoc ├── pydoc.html └── timeit.html ├── python_snake_ora.gif ├── rangetest.py ├── rangetest1.py ├── rangetest1_test.py ├── rangetest_test.py ├── reader.py ├── recur1.py ├── recur2.py ├── registry-deco.py ├── reloadall.py ├── reloadall2.py ├── reloadall3.py ├── reversals.py ├── robin2.py ├── robin3.py ├── runme.py ├── saveit.txt ├── savetree.txt ├── saxparse.py ├── scramble.py ├── script.py ├── script0.py ├── script1.py ├── script2.py ├── setcolor.py ├── setsubclass.py ├── setwrapper.py ├── shopfile.pkl ├── showargs.py ├── simple.py ├── singletons.py ├── skipper.py ├── skipper_2x.py ├── skipper_yield.py ├── slots-test.py ├── small.py ├── spam.txt ├── spam_class.py ├── spam_class2.py ├── spam_static.py ├── spam_static_deco.py ├── specialize.py ├── squares.py ├── squares_manual.py ├── squares_nonyield.py ├── squares_yield.py ├── streams.py ├── sumtree.py ├── sumtree2.py ├── temp.py ├── temp2 ├── temp3 ├── test.txt ├── testjson.txt ├── testmixin.py ├── testmixin0.py ├── testprint3.py ├── testseqs.py ├── text.py ├── threenames.py ├── timer.py ├── timer0.py ├── timer2.py ├── timer3.py ├── timerdeco-test.py ├── timerdeco.py ├── timerdeco1.py ├── timerdeco2.py ├── timeseqs-results.txt ├── timeseqs.py ├── timeseqs2.py ├── timeseqs2B.py ├── timeseqs3.py ├── timeseqs_timer2.py ├── timeseqs_timer3.py ├── timesqrt.py ├── trace.py ├── trace_ns.py ├── tracer0.py ├── tracer1.py ├── tracer2.py ├── trispam.txt ├── trispamup.txt ├── typesubclass.py ├── unders.py ├── uni2x.txt ├── unidata.txt ├── uppdatedb.py ├── upper.py ├── utf8data ├── utfdata ├── validate_descriptors1.py ├── validate_descriptors2.py ├── validate_getattr.py ├── validate_getattribute.py ├── validate_properties.py ├── validate_tester.py ├── validate_tester2.py ├── what.py ├── withas.py └── zoo.py /README.md: -------------------------------------------------------------------------------- 1 | # Learning_Python_5thE 2 | Learning Python 5th edition Code (Mark Lutz) 3 | 4 | Added the code examples for Learning Python 5th edition by Mark Lutz 5 | 6 | Source: http://learning-python.com/about-lp5e.html 7 | -------------------------------------------------------------------------------- /__admin__/__pycache__/dirdiff.cpython-33.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/__admin__/__pycache__/dirdiff.cpython-33.pyc -------------------------------------------------------------------------------- /__admin__/__pycache__/visitor.cpython-33.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/__admin__/__pycache__/visitor.cpython-33.pyc -------------------------------------------------------------------------------- /__admin__/cleanpyc.py: -------------------------------------------------------------------------------- 1 | """ 2 | delete all .pyc bytecode files in a directory tree: use the 3 | command line arg as root if given, else current working dir 4 | """ 5 | 6 | import os, sys 7 | rootdir = os.getcwd() if len(sys.argv) < 2 else sys.argv[1] 8 | findonly = False if len(sys.argv) < 3 else int(sys.argv[2]) 9 | 10 | found = removed = 0 11 | for (thisDirLevel, subsHere, filesHere) in os.walk(rootdir): 12 | for filename in filesHere: 13 | if filename.endswith('.pyc'): 14 | fullname = os.path.join(thisDirLevel, filename) 15 | print('=>', fullname) 16 | if not findonly: 17 | try: 18 | os.remove(fullname) 19 | removed += 1 20 | except: 21 | type, inst = sys.exc_info()[:2] 22 | print('*'*4, 'Failed:', filename, type, inst) 23 | found += 1 24 | 25 | print('Found', found, 'files, removed', removed) 26 | -------------------------------------------------------------------------------- /__admin__/diffall-run-full.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/__admin__/diffall-run-full.txt -------------------------------------------------------------------------------- /__admin__/visitor_sloc.py: -------------------------------------------------------------------------------- 1 | """ 2 | Count lines among all program source files in a tree named on the command 3 | line, and report totals grouped by file types (extension). A simple SLOC 4 | (source lines of code) metric: skip blank and comment lines if desired. 5 | """ 6 | 7 | import sys, pprint, os 8 | from visitor import FileVisitor 9 | 10 | class LinesByType(FileVisitor): 11 | srcExts = [] # define in subclass 12 | 13 | def __init__(self, trace=1): 14 | FileVisitor.__init__(self, trace=trace) 15 | self.srcLines = self.srcFiles = 0 16 | self.extSums = {ext: dict(files=0, lines=0) for ext in self.srcExts} 17 | 18 | def visitsource(self, fpath, ext): 19 | if self.trace > 0: print(os.path.basename(fpath)) 20 | lines = len(open(fpath, 'rb').readlines()) 21 | self.srcFiles += 1 22 | self.srcLines += lines 23 | self.extSums[ext]['files'] += 1 24 | self.extSums[ext]['lines'] += lines 25 | 26 | def visitfile(self, filepath): 27 | FileVisitor.visitfile(self, filepath) 28 | for ext in self.srcExts: 29 | if filepath.endswith(ext): 30 | self.visitsource(filepath, ext) 31 | break 32 | 33 | class PyLines(LinesByType): 34 | srcExts = ['.py', '.pyw'] # just python files 35 | 36 | class SourceLines(LinesByType): 37 | srcExts = ['.py', '.pyw', '.cgi', '.html', '.c', '.cxx', '.h', '.i'] 38 | 39 | if __name__ == '__main__': 40 | walker = SourceLines() 41 | walker.run(sys.argv[1]) 42 | print('Visited %d files and %d dirs' % (walker.fcount, walker.dcount)) 43 | print('-'*80) 44 | print('Source files=>%d, lines=>%d' % (walker.srcFiles, walker.srcLines)) 45 | print('By Types:') 46 | pprint.pprint(walker.extSums) 47 | 48 | print('\nCheck sums:', end=' ') 49 | print(sum(x['lines'] for x in walker.extSums.values()), end=' ') 50 | print(sum(x['files'] for x in walker.extSums.values())) 51 | 52 | print('\nPython only walk:') 53 | walker = PyLines(trace=0) 54 | walker.run(sys.argv[1]) 55 | pprint.pprint(walker.extSums) 56 | -------------------------------------------------------------------------------- /__pycache__/access.cpython-33.pyo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/__pycache__/access.cpython-33.pyo -------------------------------------------------------------------------------- /__pycache__/access_builtins.cpython-33.pyo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/__pycache__/access_builtins.cpython-33.pyo -------------------------------------------------------------------------------- /__pycache__/dicts.cpython-33.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/__pycache__/dicts.cpython-33.pyc -------------------------------------------------------------------------------- /__pycache__/factorials.cpython-33.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/__pycache__/factorials.cpython-33.pyc -------------------------------------------------------------------------------- /__pycache__/mymod.cpython-33.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/__pycache__/mymod.cpython-33.pyc -------------------------------------------------------------------------------- /__pycache__/mymod2.cpython-33.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/__pycache__/mymod2.cpython-33.pyc -------------------------------------------------------------------------------- /__pycache__/rangetest.cpython-33.pyo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/__pycache__/rangetest.cpython-33.pyo -------------------------------------------------------------------------------- /__pycache__/rangetest1.cpython-33.pyo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/__pycache__/rangetest1.cpython-33.pyo -------------------------------------------------------------------------------- /__pycache__/reversals.cpython-33.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/__pycache__/reversals.cpython-33.pyc -------------------------------------------------------------------------------- /code/Certificate.html: -------------------------------------------------------------------------------- 1 |

2 |


3 |

4 |

Official Certificate

5 |

6 | Date: Fri Jan 25 15:04:09 2013 7 |

8 | This certifies that: 9 |

10 | Bob Smith 11 |

12 | has survived the massive tome: 13 |

14 | Learning Python 5th Edition 15 |

16 | and is now entitled to all privileges thereof, including 17 | the right to proceed on to learning how to develop Web 18 | sites, desktop GUIs, scientific models, and assorted Apps, 19 | with the possible assistance of follow-up applications 20 | books such as Programming Python (shameless plug intended). 21 |

22 | --Mark Lutz, Instructor 23 |

24 | (Note: certificate void where obtained by skipping ahead.) 25 |

26 |


27 |

28 |
29 | Book support site 30 |
31 | 32 | -------------------------------------------------------------------------------- /code/Certificate.txt: -------------------------------------------------------------------------------- 1 | 2 | ************************************************************ 3 | 4 | ===> Official Certificate <=== 5 | 6 | Date: Fri Jan 25 15:04:09 2013 7 | 8 | This certifies that: 9 | 10 | Bob Smith 11 | 12 | has survived the massive tome: 13 | 14 | Learning Python 5th Edition 15 | 16 | and is now entitled to all privileges thereof, including 17 | the right to proceed on to learning how to develop Web 18 | sites, desktop GUIs, scientific models, and assorted Apps, 19 | with the possible assistance of follow-up applications 20 | books such as Programming Python (shameless plug intended). 21 | 22 | --Mark Lutz, Instructor 23 | 24 | (Note: certificate void where obtained by skipping ahead.) 25 | 26 | ************************************************************ 27 | 28 | -------------------------------------------------------------------------------- /code/PythonPoweredSmall.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/code/PythonPoweredSmall.gif -------------------------------------------------------------------------------- /code/__pycache__/access.cpython-33.pyo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/code/__pycache__/access.cpython-33.pyo -------------------------------------------------------------------------------- /code/__pycache__/access_builtins.cpython-33.pyo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/code/__pycache__/access_builtins.cpython-33.pyo -------------------------------------------------------------------------------- /code/__pycache__/dicts.cpython-33.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/code/__pycache__/dicts.cpython-33.pyc -------------------------------------------------------------------------------- /code/__pycache__/factorials.cpython-33.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/code/__pycache__/factorials.cpython-33.pyc -------------------------------------------------------------------------------- /code/__pycache__/mymod.cpython-33.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/code/__pycache__/mymod.cpython-33.pyc -------------------------------------------------------------------------------- /code/__pycache__/mymod2.cpython-33.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/code/__pycache__/mymod2.cpython-33.pyc -------------------------------------------------------------------------------- /code/__pycache__/rangetest.cpython-33.pyo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/code/__pycache__/rangetest.cpython-33.pyo -------------------------------------------------------------------------------- /code/__pycache__/rangetest1.cpython-33.pyo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/code/__pycache__/rangetest1.cpython-33.pyo -------------------------------------------------------------------------------- /code/__pycache__/reversals.cpython-33.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/code/__pycache__/reversals.cpython-33.pyc -------------------------------------------------------------------------------- /code/a.py: -------------------------------------------------------------------------------- 1 | import b # File a.py 2 | X = 111 3 | -------------------------------------------------------------------------------- /code/a1/b/a1.py: -------------------------------------------------------------------------------- 1 | print('module a1!') 2 | -------------------------------------------------------------------------------- /code/a1/b/mod.py: -------------------------------------------------------------------------------- 1 | print('mod.py') 2 | -------------------------------------------------------------------------------- /code/access-test.py: -------------------------------------------------------------------------------- 1 | """ 2 | File: access-test.py 3 | Test code: separate file to allow decorator reuse. 4 | """ 5 | import sys 6 | from access import Private, Public 7 | 8 | print('---------------------------------------------------------') 9 | # Test 1: names are public if not pivate 10 | 11 | @Private('age') # Person = Private('age')(Person) 12 | class Person: # Person = onInstance with state 13 | def __init__(self, name, age): 14 | self.name = name 15 | self.age = age # Inside accesses run normally 16 | def __add__(self, N): 17 | self.age += N # Bultins caught by mix-in in 3.X 18 | def __str__(self): 19 | return '%s: %s' % (self.name, self.age) 20 | 21 | X = Person('Bob', 40) 22 | print(X.name) # Outside accesses validated 23 | X.name = 'Sue' 24 | print(X.name) 25 | X + 10 26 | print(X) 27 | 28 | try: t = X.age # FAILS unless "python -O" 29 | except: print(sys.exc_info()[1]) 30 | try: X.age = 999 # ditto 31 | except: print(sys.exc_info()[1]) 32 | 33 | print('---------------------------------------------------------') 34 | # Test 2: names are private if not public 35 | # Operators must be non-Private or Public in BuiltinMixin used 36 | 37 | @Public('name', '__add__', '__str__', '__coerce__') 38 | class Person: 39 | def __init__(self, name, age): 40 | self.name = name 41 | self.age = age 42 | def __add__(self, N): 43 | self.age += N # Bultins caught by mix-in in 3.X 44 | def __str__(self): 45 | return '%s: %s' % (self.name, self.age) 46 | 47 | X = Person('bob', 40) # X is an onInstance 48 | print(X.name) # onInstance embeds Person 49 | X.name = 'sue' 50 | print(X.name) 51 | X + 10 52 | print(X) 53 | 54 | try: t = X.age # FAILS unless "python -O" 55 | except: print(sys.exc_info()[1]) 56 | try: X.age = 999 # ditto 57 | except: print(sys.exc_info()[1]) 58 | -------------------------------------------------------------------------------- /code/access.py: -------------------------------------------------------------------------------- 1 | """ 2 | File access.py (3.X + 2.X) 3 | Class decorator with Private and Public attribute declarations. 4 | Controls external access to attributes stored on an instance, or 5 | inherited by it from its classes in any fashion. 6 | 7 | Private declares attribute names that cannot be fetched or assigned 8 | outside the decorated class, and Public declares all the names that can. 9 | 10 | Caveats: in 3.X catches built-ins coded in BuiltinMixins only (expand me); 11 | as coded, Public may be less useful than Private for operator overloading. 12 | """ 13 | from access_builtins import BuiltinsMixin # A partial set! 14 | 15 | traceMe = False 16 | def trace(*args): 17 | if traceMe: print('[' + ' '.join(map(str, args)) + ']') 18 | 19 | def accessControl(failIf): 20 | def onDecorator(aClass): 21 | if not __debug__: 22 | return aClass 23 | else: 24 | class onInstance(BuiltinsMixin): 25 | def __init__(self, *args, **kargs): 26 | self.__wrapped = aClass(*args, **kargs) 27 | 28 | def __getattr__(self, attr): 29 | trace('get:', attr) 30 | if failIf(attr): 31 | raise TypeError('private attribute fetch: ' + attr) 32 | else: 33 | return getattr(self.__wrapped, attr) 34 | 35 | def __setattr__(self, attr, value): 36 | trace('set:', attr, value) 37 | if attr == '_onInstance__wrapped': 38 | self.__dict__[attr] = value 39 | elif failIf(attr): 40 | raise TypeError('private attribute change: ' + attr) 41 | else: 42 | setattr(self.__wrapped, attr, value) 43 | return onInstance 44 | return onDecorator 45 | 46 | def Private(*attributes): 47 | return accessControl(failIf=(lambda attr: attr in attributes)) 48 | 49 | def Public(*attributes): 50 | return accessControl(failIf=(lambda attr: attr not in attributes)) 51 | -------------------------------------------------------------------------------- /code/access2.py: -------------------------------------------------------------------------------- 1 | """ 2 | File access2.py (3.X + 2.X) 3 | Class decorator with Private and Public attribute declarations. 4 | 5 | Controls external access to attributes stored on an instance, or 6 | Inherited by it from its classes. Private declares attribute names 7 | that cannot be fetched or assigned outside the decorated class, 8 | and Public declares all the names that can. 9 | 10 | Caveat: this works in 3.X for explicitly named attributes only: __X__ 11 | operator overloading methods implicitly run for built-in operations 12 | do not trigger either __getattr__ or __getattribute__ in new-style 13 | classes. Add __X__ methods here to intercept and delegate built-ins. 14 | """ 15 | 16 | traceMe = False 17 | def trace(*args): 18 | if traceMe: print('[' + ' '.join(map(str, args)) + ']') 19 | 20 | def accessControl(failIf): 21 | def onDecorator(aClass): 22 | class onInstance: 23 | def __init__(self, *args, **kargs): 24 | self.__wrapped = aClass(*args, **kargs) 25 | 26 | def __getattr__(self, attr): 27 | trace('get:', attr) 28 | if failIf(attr): 29 | raise TypeError('private attribute fetch: ' + attr) 30 | else: 31 | return getattr(self.__wrapped, attr) 32 | 33 | def __setattr__(self, attr, value): 34 | trace('set:', attr, value) 35 | if attr == '_onInstance__wrapped': 36 | self.__dict__[attr] = value 37 | elif failIf(attr): 38 | raise TypeError('private attribute change: ' + attr) 39 | else: 40 | setattr(self.__wrapped, attr, value) 41 | return onInstance 42 | return onDecorator 43 | 44 | def Private(*attributes): 45 | return accessControl(failIf=(lambda attr: attr in attributes)) 46 | 47 | def Public(*attributes): 48 | return accessControl(failIf=(lambda attr: attr not in attributes)) 49 | -------------------------------------------------------------------------------- /code/access_builtins.py: -------------------------------------------------------------------------------- 1 | """ 2 | File access_builtins.py (from access2_builtins2b.py) 3 | Route some built-in operations back to proxy class __getattr__, so they 4 | work same in 3.X as direct by-name calls and 2.X's default classic classes. 5 | Expand me as needed to include other __X__ names used by proxied objects. 6 | """ 7 | 8 | class BuiltinsMixin: 9 | def reroute(self, attr, *args, **kargs): 10 | return self.__class__.__getattr__(self, attr)(*args, **kargs) 11 | 12 | def __add__(self, other): 13 | return self.reroute('__add__', other) 14 | def __str__(self): 15 | return self.reroute('__str__') 16 | def __getitem__(self, index): 17 | return self.reroute('__getitem__', index) 18 | def __call__(self, *args, **kargs): 19 | return self.reroute('__call__', *args, **kargs) 20 | 21 | # Plus any others used by wrapped objects in 3.X only 22 | -------------------------------------------------------------------------------- /code/access_builtins_desc.py: -------------------------------------------------------------------------------- 1 | """ 2 | File access_builtins_desc.py (from access_builtins.py) 3 | Route some built-in operations back to proxy class __getattr__, so they 4 | work same in 3.X as direct by-name calls and 2.X's default classic classes. 5 | Expand me as needed to include other __X__ names used by proxied objects. 6 | 7 | This version auto creates class-level descriptors to intercept builtins, 8 | and assumes a _wrapped in the instaces referencing the proxied object. 9 | It responds to attribute access, not the actual built-in oeration call. 10 | """ 11 | 12 | """ 13 | original... 14 | 15 | class BuiltinsMixin: 16 | def reroute(self, attr, *args, **kargs): 17 | return self.__class__.__getattr__(self, attr)(*args, **kargs) 18 | 19 | def __add__(self, other): 20 | return self.reroute('__add__', other) 21 | def __str__(self): 22 | return self.reroute('__str__') 23 | def __getitem__(self, index): 24 | return self.reroute('__getitem__', index) 25 | def __call__(self, *args, **kargs): 26 | return self.reroute('__call__', *args, **kargs) 27 | 28 | # Plus any others used by wrapped objects in 3.X only 29 | """ 30 | 31 | 32 | 33 | class BuiltinsMixin: 34 | class ProxyDesc(object): # object for 2.X 35 | def __init__(self, attrname): 36 | self.attrname = attrname 37 | def __get__(self, instance, owner): 38 | return getattr(instance._wrapped, self.attrname) # Assume a _wrapped 39 | 40 | builtins = ['add', 'str', 'getitem', 'call'] # Plus others 41 | for attr in builtins: 42 | exec('__%s__ = ProxyDesc("__%s__")' % (attr, attr)) 43 | 44 | 45 | # The loop does: 46 | # __add__ = ProxyDesc("__add__") 47 | # __str__ = ProxyDesc("__str__") 48 | # ... -------------------------------------------------------------------------------- /code/access_desc.py: -------------------------------------------------------------------------------- 1 | """ 2 | File access_desc.py (3.X + 2.X) 3 | See access.py: this version uses the descriptor-based BuiltinsMixin. 4 | """ 5 | from access_builtins_desc import BuiltinsMixin # A partial set! 6 | 7 | traceMe = False 8 | def trace(*args): 9 | if traceMe: print('[' + ' '.join(map(str, args)) + ']') 10 | 11 | def accessControl(failIf): 12 | def onDecorator(aClass): 13 | if not __debug__: 14 | return aClass 15 | else: 16 | class onInstance(BuiltinsMixin): 17 | def __init__(self, *args, **kargs): 18 | self._wrapped = aClass(*args, **kargs) 19 | 20 | def __getattr__(self, attr): 21 | trace('get:', attr) 22 | if failIf(attr): 23 | raise TypeError('private attribute fetch: ' + attr) 24 | else: 25 | return getattr(self._wrapped, attr) 26 | 27 | def __setattr__(self, attr, value): 28 | trace('set:', attr, value) 29 | if attr == '_wrapped': 30 | self.__dict__[attr] = value 31 | elif failIf(attr): 32 | raise TypeError('private attribute change: ' + attr) 33 | else: 34 | setattr(self._wrapped, attr, value) 35 | return onInstance 36 | return onDecorator 37 | 38 | def Private(*attributes): 39 | return accessControl(failIf=(lambda attr: attr in attributes)) 40 | 41 | def Public(*attributes): 42 | return accessControl(failIf=(lambda attr: attr not in attributes)) 43 | -------------------------------------------------------------------------------- /code/adder.py: -------------------------------------------------------------------------------- 1 | class Adder: 2 | def add(self, x, y): 3 | print('not implemented!') 4 | def __init__(self, start=[]): 5 | self.data = start 6 | def __add__(self, other): # Or in subclasses? 7 | return self.add(self.data, other) # Or return type? 8 | 9 | class ListAdder(Adder): 10 | def add(self, x, y): 11 | return x + y 12 | 13 | class DictAdder(Adder): 14 | def add(self, x, y): 15 | new = {} 16 | for k in x.keys(): new[k] = x[k] 17 | for k in y.keys(): new[k] = y[k] 18 | return new 19 | -------------------------------------------------------------------------------- /code/adder2.py: -------------------------------------------------------------------------------- 1 | class Adder: 2 | def __init__(self, start=[]): 3 | self.data = start 4 | def __add__(self, other): # Pass a single argument 5 | return self.add(other) # The left side is in self 6 | def add(self, y): 7 | print('not implemented!') 8 | 9 | class ListAdder(Adder): 10 | def add(self, y): 11 | return self.data + y 12 | 13 | class DictAdder(Adder): 14 | def add(self, y): 15 | d = self.data.copy() # Change to use self.data instead of x 16 | d.update(y) # Or "cheat" by using quicker built-ins 17 | return d 18 | 19 | x = ListAdder([1, 2, 3]) 20 | y = x + [4, 5, 6] 21 | print(y) # Prints [1, 2, 3, 4, 5, 6] 22 | 23 | z = DictAdder(dict(name='Bob')) + {'a':1} 24 | print(z) # Prints {'name': 'Bob', 'a': 1} 25 | -------------------------------------------------------------------------------- /code/adders.py: -------------------------------------------------------------------------------- 1 | def adder1(*args): 2 | print('adder1', end=' ') 3 | if type(args[0]) == type(0): # Integer? 4 | sum = 0 # Init to zero 5 | else: # else sequence: 6 | sum = args[0][:0] # Use empty slice of arg1 7 | for arg in args: 8 | sum = sum + arg 9 | return sum 10 | 11 | def adder2(*args): 12 | print('adder2', end=' ') 13 | sum = args[0] # Init to arg1 14 | for next in args[1:]: 15 | sum += next # Add items 2..N 16 | return sum 17 | 18 | for func in (adder1, adder2): 19 | print(func(2, 3, 4)) 20 | print(func('spam', 'eggs', 'toast')) 21 | print(func(['a', 'b'], ['c', 'd'], ['e', 'f'])) 22 | -------------------------------------------------------------------------------- /code/alls.py: -------------------------------------------------------------------------------- 1 | __all__ = ['a', '_c'] 2 | a, b, _c, _d = 1, 2, 3, 4 -------------------------------------------------------------------------------- /code/argtest_testmeth.py: -------------------------------------------------------------------------------- 1 | from argtest import rangetest, typetest 2 | 3 | class C: 4 | @rangetest(a=(1, 10)) 5 | def meth1(self, a): 6 | return a * 1000 7 | 8 | @typetest(a=int) 9 | def meth2(self, a): 10 | return a * 1000 11 | 12 | """ 13 | >>> from argtest_testmeth import C 14 | >>> X = C() 15 | >>> X.meth1(5) 16 | 5000 17 | >>> X.meth1(20) 18 | TypeError: meth1 argument "a" not (1, 10) 19 | >>> X.meth2(20) 20 | 20000 21 | >>> X.meth2(20.9) 22 | TypeError: meth2 argument "a" not 23 | """ -------------------------------------------------------------------------------- /code/asserter.py: -------------------------------------------------------------------------------- 1 | def f(x): 2 | assert x < 0, 'x must be negative' 3 | return x ** 2 4 | -------------------------------------------------------------------------------- /code/attrs1.py: -------------------------------------------------------------------------------- 1 | class Person: 2 | def __init__(self, name): # On [Person()] 3 | self._name = name # Triggers __setattr__! 4 | 5 | # def __getattr__(self, attr): # On [obj.undefined] 6 | # print('get: ' + attr) 7 | # if attr == 'name': # Intercept name: not stored 8 | # return self._name # Does not loop: real attr 9 | # else: # Others are errors 10 | # raise AttributeError(attr) 11 | 12 | def __getattribute__(self, attr): # On [obj.any] 13 | print('get: ' + attr) 14 | if attr == 'name': # Intercept all names 15 | attr = '_name' # Map to internal name 16 | return object.__getattribute__(self, attr) # Avoid looping here 17 | 18 | def __setattr__(self, attr, value): # On [obj.any = value] 19 | print('set: ' + attr) 20 | if attr == 'name': 21 | attr = '_name' # Set internal name 22 | self.__dict__[attr] = value # Avoid looping here 23 | 24 | def __delattr__(self, attr): # On [del obj.any] 25 | print('del: ' + attr) 26 | if attr == 'name': 27 | attr = '_name' # Avoid looping here too 28 | del self.__dict__[attr] # but much less common 29 | 30 | bob = Person('Bob Smith') # bob has a managed attribute 31 | print(bob.name) # Runs __getattr__ 32 | bob.name = 'Robert Smith' # Runs __setattr__ 33 | print(bob.name) 34 | del bob.name # Runs __delattr__ 35 | 36 | print('-'*20) 37 | sue = Person('Sue Jones') # sue inherits property too 38 | print(sue.name) 39 | #print(Person.name.__doc__) # No equivalent here 40 | -------------------------------------------------------------------------------- /code/b.py: -------------------------------------------------------------------------------- 1 | import c # File b.py 2 | Y = 222 3 | -------------------------------------------------------------------------------- /code/bad.py: -------------------------------------------------------------------------------- 1 | def gobad(x, y): 2 | return x / y 3 | 4 | def gosouth(x): 5 | print(gobad(x, 0)) 6 | 7 | gosouth(1) 8 | -------------------------------------------------------------------------------- /code/badly.exc: -------------------------------------------------------------------------------- 1 | Traceback (most recent call last): 2 | File "badly.py", line 7, in 3 | inverse(0) 4 | File "badly.py", line 4, in inverse 5 | return 1 / x 6 | ZeroDivisionError: division by zero 7 | -------------------------------------------------------------------------------- /code/badly.py: -------------------------------------------------------------------------------- 1 | import traceback 2 | 3 | def inverse(x): 4 | return 1 / x 5 | 6 | try: 7 | inverse(0) 8 | except Exception: 9 | traceback.print_exc(file=open('badly.exc', 'w')) 10 | print('Bye') 11 | -------------------------------------------------------------------------------- /code/bothmethods.py: -------------------------------------------------------------------------------- 1 | # File bothmethods.py 2 | 3 | class Methods: 4 | def imeth(self, x): # Normal instance method: passed a self 5 | print([self, x]) 6 | 7 | def smeth(x): # Static: no instance passed 8 | print([x]) 9 | 10 | def cmeth(cls, x): # Class: gets class, not instance 11 | print([cls, x]) 12 | 13 | smeth = staticmethod(smeth) # Make smeth a static method (or @: ahead) 14 | cmeth = classmethod(cmeth) # Make cmeth a class method (or @: ahead) 15 | -------------------------------------------------------------------------------- /code/bothmethods_decorators.py: -------------------------------------------------------------------------------- 1 | # File bothmethods_decorators.py 2 | 3 | class Methods(object): # object needed in 2.X for property setters 4 | def imeth(self, x): # Normal instance method: passed a self 5 | print([self, x]) 6 | 7 | @staticmethod 8 | def smeth(x): # Static: no instance passed 9 | print([x]) 10 | 11 | @classmethod 12 | def cmeth(cls, x): # Class: gets class, not instance 13 | print([cls, x]) 14 | 15 | @property # Property: computed on fetch 16 | def name(self): 17 | return 'Bob ' + self.__class__.__name__ 18 | -------------------------------------------------------------------------------- /code/brian: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python 2 | print('The Bright Side ' + 'of Life...') # + means concatenate for strings 3 | -------------------------------------------------------------------------------- /code/c.py: -------------------------------------------------------------------------------- 1 | Z = 333 # File c.py -------------------------------------------------------------------------------- /code/calltracer.py: -------------------------------------------------------------------------------- 1 | # A call tracer decorator for both functions and methods 2 | 3 | def tracer(func): # Use function, not class with __call__ 4 | calls = 0 # Else "self" is decorator instance only! 5 | def onCall(*args, **kwargs): # Or in 2.X+3.X: use [onCall.calls += 1] 6 | nonlocal calls 7 | calls += 1 8 | print('call %s to %s' % (calls, func.__name__)) 9 | return func(*args, **kwargs) 10 | return onCall 11 | 12 | 13 | if __name__ == '__main__': 14 | 15 | # Applies to simple functions 16 | @tracer 17 | def spam(a, b, c): # spam = tracer(spam) 18 | print(a + b + c) # onCall remembers spam 19 | 20 | @tracer 21 | def eggs(N): 22 | return 2 ** N 23 | 24 | spam(1, 2, 3) # Runs onCall(1, 2, 3) 25 | spam(a=4, b=5, c=6) 26 | print(eggs(32)) 27 | 28 | # Applies to class method functions too! 29 | class Person: 30 | def __init__(self, name, pay): 31 | self.name = name 32 | self.pay = pay 33 | 34 | @tracer 35 | def giveRaise(self, percent): # giveRaise = tracer(giveRaise) 36 | self.pay *= (1.0 + percent) # onCall remembers giveRaise 37 | 38 | @tracer 39 | def lastName(self): # lastName = tracer(lastName) 40 | return self.name.split()[-1] 41 | 42 | print('methods...') 43 | bob = Person('Bob Smith', 50000) 44 | sue = Person('Sue Jones', 100000) 45 | print(bob.name, sue.name) 46 | sue.giveRaise(.10) # Runs onCall(sue, .10) 47 | print(int(sue.pay)) 48 | print(bob.lastName(), sue.lastName()) # Runs onCall(bob), lastName in scopes 49 | -------------------------------------------------------------------------------- /code/changer.py: -------------------------------------------------------------------------------- 1 | message = "First version" 2 | def printer(): 3 | print(message) 4 | -------------------------------------------------------------------------------- /code/classexc.py: -------------------------------------------------------------------------------- 1 | class General(Exception): pass 2 | class Specific1(General): pass 3 | class Specific2(General): pass 4 | 5 | def raiser0(): 6 | X = General() # Raise superclass instance 7 | raise X 8 | 9 | def raiser1(): 10 | X = Specific1() # Raise subclass instance 11 | raise X 12 | 13 | def raiser2(): 14 | X = Specific2() # Raise different subclass instance 15 | raise X 16 | 17 | for func in (raiser0, raiser1, raiser2): 18 | try: 19 | func() 20 | except General: # Match General or any subclass of it 21 | import sys 22 | print('caught: %s' % sys.exc_info()[0]) 23 | -------------------------------------------------------------------------------- /code/classexc2.py: -------------------------------------------------------------------------------- 1 | class General(Exception): pass 2 | class Specific1(General): pass 3 | class Specific2(General): pass 4 | 5 | def raiser0(): raise General() 6 | def raiser1(): raise Specific1() 7 | def raiser2(): raise Specific2() 8 | 9 | for func in (raiser0, raiser1, raiser2): 10 | try: 11 | func() 12 | except General as X: # X is the raised instance 13 | print('caught: %s' % X.__class__) # Same as sys.exc_info()[0 14 | -------------------------------------------------------------------------------- /code/classscope.py: -------------------------------------------------------------------------------- 1 | # File classscope.py 2 | 3 | X = 1 4 | 5 | def nester(): 6 | print(X) # Global: 1 7 | class C: 8 | print(X) # Global: 1 9 | def method1(self): 10 | print(X) # Global: 1 11 | def method2(self): 12 | X = 3 # Hides gobal 13 | print(X) # Local: 3 14 | I = C() 15 | I.method1() 16 | I.method2() 17 | 18 | print(X) # Global: 1 19 | nester() # Rest: 1, 1, 1, 3 20 | print('-'*40) 21 | 22 | 23 | 24 | X = 1 25 | 26 | def nester(): 27 | X = 2 # Hides global 28 | print(X) # Local: 2 29 | class C: 30 | print(X) # In enclosing def (nester): 2 31 | def method1(self): 32 | print(X) # In enclosing def (nester): 2 33 | def method2(self): 34 | X = 3 # Hides enclosing (nester) 35 | print(X) # Local: 3 36 | I = C() 37 | I.method1() 38 | I.method2() 39 | 40 | print(X) # Global: 1 41 | nester() # Rest: 2, 2, 2, 3 42 | print('-'*40) 43 | 44 | 45 | 46 | X = 1 47 | 48 | def nester(): 49 | X = 2 # Hides global 50 | print(X) # Local: 2 51 | class C: 52 | X = 3 # Class local hides nester's: C.X or I.X (not scoped) 53 | print(X) # Local: 3 54 | def method1(self): 55 | print(X) # In enclosing def (not class!): 2 56 | print(self.X) # Inherited class local: 3 57 | def method2(self): 58 | X = 4 # Hides enclosing (nester, not class) 59 | print(X) # Local: 4 60 | self.X = 5 # Hides class 61 | print(self.X) # Located in instance: 5 62 | I = C() 63 | I.method1() 64 | I.method2() 65 | 66 | print(X) # Global: 1 67 | nester() # Rest: 2, 3, 2, 3, 4, 5 68 | print('-'*40) 69 | -------------------------------------------------------------------------------- /code/classtools.py: -------------------------------------------------------------------------------- 1 | # File classtools.py (new) 2 | "Assorted class utilities and tools" 3 | 4 | class AttrDisplay: 5 | """ 6 | Provides an inheritable display overload method that shows 7 | instances with their class names and a name=value pair for 8 | each attribute stored on the instance itself (but not attrs 9 | inherited from its classes). Can be mixed into any class, 10 | and will work on any instance. 11 | """ 12 | def gatherAttrs(self): 13 | attrs = [] 14 | for key in sorted(self.__dict__): 15 | attrs.append('%s=%s' % (key, getattr(self, key))) 16 | return ', '.join(attrs) 17 | 18 | def __repr__(self): 19 | return '[%s: %s]' % (self.__class__.__name__, self.gatherAttrs()) 20 | 21 | if __name__ == '__main__': 22 | 23 | class TopTest(AttrDisplay): 24 | count = 0 25 | def __init__(self): 26 | self.attr1 = TopTest.count 27 | self.attr2 = TopTest.count+1 28 | TopTest.count += 2 29 | 30 | class SubTest(TopTest): 31 | pass 32 | 33 | X, Y = TopTest(), SubTest() # Make two instances 34 | print(X) # Show all instance attrs 35 | print(Y) # Show lowest class name 36 | -------------------------------------------------------------------------------- /code/classtree.py: -------------------------------------------------------------------------------- 1 | #!python 2 | """ 3 | classtree.py: Climb inheritance trees using namespace links, 4 | displaying higher superclasses with indentation for height 5 | """ 6 | 7 | def classtree(cls, indent): 8 | print('.' * indent + cls.__name__) # Print class name here 9 | for supercls in cls.__bases__: # Recur to all superclasses 10 | classtree(supercls, indent+3) # May visit super > once 11 | 12 | def instancetree(inst): 13 | print('Tree of %s' % inst) # Show instance 14 | classtree(inst.__class__, 3) # Climb to its class 15 | 16 | def selftest(): 17 | class A: pass 18 | class B(A): pass 19 | class C(A): pass 20 | class D(B,C): pass 21 | class E: pass 22 | class F(D,E): pass 23 | instancetree(B()) 24 | instancetree(F()) 25 | 26 | if __name__ == '__main__': selftest() 27 | -------------------------------------------------------------------------------- /code/collector.py: -------------------------------------------------------------------------------- 1 | ## This code is abstract and will not run as is: 2 | ## you must code your own mod1.py, mod2.py, mod3.py 3 | 4 | 5 | # File collector.py 6 | from mod1 import * # Collect lots of names here 7 | from mod2 import * # from assigns to my names 8 | from mod3 import * 9 | 10 | 11 | >>> from collector import somename -------------------------------------------------------------------------------- /code/commuter.py: -------------------------------------------------------------------------------- 1 | #!python 2 | from __future__ import print_function # 2.X/3.X compatibility 3 | 4 | class Commuter1: 5 | def __init__(self, val): 6 | self.val = val 7 | def __add__(self, other): 8 | print('add', self.val, other) 9 | return self.val + other 10 | def __radd__(self, other): 11 | print('radd', self.val, other) 12 | return other + self.val 13 | 14 | class Commuter2: 15 | def __init__(self, val): 16 | self.val = val 17 | def __add__(self, other): 18 | print('add', self.val, other) 19 | return self.val + other 20 | def __radd__(self, other): 21 | return self.__add__(other) # Call __add__ explicitly 22 | 23 | class Commuter3: 24 | def __init__(self, val): 25 | self.val = val 26 | def __add__(self, other): 27 | print('add', self.val, other) 28 | return self.val + other 29 | def __radd__(self, other): 30 | return self + other # Swap order and readd 31 | 32 | class Commuter4: 33 | def __init__(self, val): 34 | self.val = val 35 | def __add__(self, other): 36 | print('add', self.val, other) 37 | return self.val + other 38 | __radd__ = __add__ # Alias: cut out the middleman 39 | 40 | class Commuter5: # Propagate class type in results 41 | def __init__(self, val): 42 | self.val = val 43 | def __add__(self, other): 44 | if isinstance(other, Commuter5): # Type test to avoid object nesting 45 | other = other.val 46 | return Commuter5(self.val + other) # Else + result is another Commuter 47 | def __radd__(self, other): 48 | return Commuter5(other + self.val) 49 | def __str__(self): 50 | return '' % self.val 51 | 52 | 53 | if __name__ == '__main__': 54 | for klass in (Commuter1, Commuter2, Commuter3, Commuter4, Commuter5): 55 | print('-' * 60) 56 | x = klass(88) 57 | y = klass(99) 58 | print(x + 1) 59 | print(1 + y) 60 | print(x + y) 61 | -------------------------------------------------------------------------------- /code/contains.py: -------------------------------------------------------------------------------- 1 | # File contains.py 2 | from __future__ import print_function # 2.X/3.X compatibility 3 | 4 | class Iters: 5 | def __init__(self, value): 6 | self.data = value 7 | def __getitem__(self, i): # Fallback for iteration 8 | print('get[%s]:' % i, end='') # Also for index, slice 9 | return self.data[i] 10 | def __iter__(self): # Preferred for iteration 11 | print('iter=> ', end='') # Allows only 1 active iterator 12 | self.ix = 0 13 | return self 14 | def __next__(self): 15 | print('next:', end='') 16 | if self.ix == len(self.data): raise StopIteration 17 | item = self.data[self.ix] 18 | self.ix += 1 19 | return item 20 | def __contains__(self, x): # Preferred for 'in' 21 | print('contains: ', end='') 22 | return x in self.data 23 | next = __next__ # 2.X/3.X compatibility 24 | 25 | if __name__ == '__main__': 26 | X = Iters([1, 2, 3, 4, 5]) # Make instance 27 | print(3 in X) # Membership 28 | for i in X: # for loops 29 | print(i, end=' | ') 30 | 31 | print() 32 | print([i ** 2 for i in X]) # Other iteration contexts 33 | print( list(map(bin, X)) ) 34 | 35 | I = iter(X) # Manual iteration (what other contexts do) 36 | while True: 37 | try: 38 | print(next(I), end=' @ ') 39 | except StopIteration: 40 | break 41 | -------------------------------------------------------------------------------- /code/contains_yield.py: -------------------------------------------------------------------------------- 1 | # File contains_yield.py 2 | from __future__ import print_function # 2.X/3.X compatibility 3 | 4 | class Iters: 5 | def __init__(self, value): 6 | self.data = value 7 | def __getitem__(self, i): # Fallback for iteration 8 | print('get[%s]:' % i, end='') # Also for index, slice 9 | return self.data[i] 10 | def __iter__(self): # Preferred for iteration 11 | print('iter=> next:', end='') # Allows multiple active iterators 12 | for x in self.data: # no __next__ to alias to next 13 | yield x 14 | print('next:', end='') 15 | def __contains__(self, x): # Preferred for 'in' 16 | print('contains: ', end='') 17 | return x in self.data 18 | 19 | if __name__ == '__main__': 20 | X = Iters([1, 2, 3, 4, 5]) # Make instance 21 | print(3 in X) # Membership 22 | for i in X: # for loops 23 | print(i, end=' | ') 24 | 25 | print() 26 | print([i ** 2 for i in X]) # Other iteration contexts 27 | print( list(map(bin, X)) ) 28 | 29 | I = iter(X) # Manual iteration (what other contexts do) 30 | while True: 31 | try: 32 | print(next(I), end=' @ ') 33 | except StopIteration: 34 | break 35 | -------------------------------------------------------------------------------- /code/converters.py: -------------------------------------------------------------------------------- 1 | from streams import Processor 2 | 3 | class Uppercase(Processor): 4 | def converter(self, data): 5 | return data.upper() 6 | 7 | if __name__ == '__main__': 8 | import sys 9 | obj = Uppercase(open('trispam.txt'), sys.stdout) 10 | obj.process() 11 | -------------------------------------------------------------------------------- /code/countdown.py: -------------------------------------------------------------------------------- 1 | def countdown(N): 2 | if N == 0: 3 | print('stop') # 2.X: print 'stop' 4 | else: 5 | print(N, end=' ') # 2.X: print N, 6 | countdown(N-1) 7 | 8 | 9 | def countdown2(N): # Generator function, recursive 10 | if N == 0: 11 | yield 'stop' 12 | else: 13 | yield N 14 | for x in countdown2(N-1): yield x # 3.3+: yield from countdown2(N-1) -------------------------------------------------------------------------------- /code/csvdata.txt: -------------------------------------------------------------------------------- 1 | a,bbb,cc,dddd 2 | 11,22,33,44 -------------------------------------------------------------------------------- /code/data.bin: -------------------------------------------------------------------------------- 1 | spam -------------------------------------------------------------------------------- /code/data.txt: -------------------------------------------------------------------------------- 1 | Hello 2 | world 3 | -------------------------------------------------------------------------------- /code/datafile.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/code/datafile.pkl -------------------------------------------------------------------------------- /code/decoall-deco-any.py: -------------------------------------------------------------------------------- 1 | # Class decorator factory: apply any decorator to all methods of a class 2 | 3 | from types import FunctionType 4 | from decotools import tracer, timer 5 | 6 | def decorateAll(decorator): 7 | def DecoDecorate(aClass): 8 | for attr, attrval in aClass.__dict__.items(): 9 | if type(attrval) is FunctionType: 10 | setattr(aClass, attr, decorator(attrval)) # Not __dict__ 11 | return aClass 12 | return DecoDecorate 13 | 14 | @decorateAll(tracer) # Use a class decorator 15 | class Person: # Applies func decorator to methods 16 | def __init__(self, name, pay): # Person = decorateAll(..)(Person) 17 | self.name = name # Person = DecoDecorate(Person) 18 | self.pay = pay 19 | def giveRaise(self, percent): 20 | self.pay *= (1.0 + percent) 21 | def lastName(self): 22 | return self.name.split()[-1] 23 | 24 | bob = Person('Bob Smith', 50000) 25 | sue = Person('Sue Jones', 100000) 26 | print(bob.name, sue.name) 27 | sue.giveRaise(.10) 28 | print('%.2f' % sue.pay) 29 | print(bob.lastName(), sue.lastName()) 30 | -------------------------------------------------------------------------------- /code/decoall-deco-any2.py: -------------------------------------------------------------------------------- 1 | # Class decorator factory: apply any decorator to all methods of a class 2 | 3 | from types import FunctionType 4 | from decotools import tracer, timer 5 | 6 | def decorateAll(decorator): 7 | def DecoDecorate(aClass): 8 | for attr, attrval in aClass.__dict__.items(): 9 | if type(attrval) is FunctionType: 10 | setattr(aClass, attr, decorator(attrval)) # Not __dict__ 11 | return aClass 12 | return DecoDecorate 13 | 14 | #@decorateAll(tracer) # Use a class decorator 15 | 16 | @decorateAll(timer(label='@@')) 17 | class Person: # Applies func decorator to methods 18 | def __init__(self, name, pay): # Person = decorateAll(..)(Person) 19 | self.name = name # Person = DecoDecorate(Person) 20 | self.pay = pay 21 | def giveRaise(self, percent): 22 | self.pay *= (1.0 + percent) 23 | def lastName(self): 24 | return self.name.split()[-1] 25 | 26 | bob = Person('Bob Smith', 50000) 27 | sue = Person('Sue Jones', 100000) 28 | print(bob.name, sue.name) 29 | sue.giveRaise(.10) 30 | print('%.2f' % sue.pay) 31 | print(bob.lastName(), sue.lastName()) 32 | 33 | # If using timer: total time per method 34 | 35 | print('-'*40) 36 | print('%.5f' % Person.__init__.alltime) 37 | print('%.5f' % Person.giveRaise.alltime) 38 | print('%.5f' % Person.lastName.alltime) 39 | -------------------------------------------------------------------------------- /code/decoall-deco-any3.py: -------------------------------------------------------------------------------- 1 | # Class decorator factory: apply any decorator to all methods of a class 2 | 3 | from types import FunctionType 4 | from decotools import tracer, timer 5 | 6 | def decorateAll(decorator): 7 | def DecoDecorate(aClass): 8 | for attr, attrval in aClass.__dict__.items(): 9 | if type(attrval) is FunctionType: 10 | setattr(aClass, attr, decorator(attrval)) # Not __dict__ 11 | return aClass 12 | return DecoDecorate 13 | 14 | #@decorateAll(tracer) # Use a class decorator 15 | #@decorateAll(tracer(timer(label='@@'))) 16 | 17 | #@decorateAll(timer(label='@@')(tracer)) # Times applying the tracer! 18 | #@decorateAll(tracer(timer(label='@@'))) # Traces applying the timer! 19 | 20 | #@decorateAll(tracer) # Traces onCall wrapper, times methods 21 | #@decorateAll(timer(label='@@')) 22 | 23 | #@decorateAll(timer(label='@@')) 24 | #@decorateAll(tracer) # Times onCall wrapper, traces methods 25 | 26 | 27 | @decorateAll(timer(label='@@')) 28 | @decorateAll(tracer) # Times onCall wrapper, traces methods 29 | class Person: # Applies func decorator to methods 30 | def __init__(self, name, pay): # Person = decorateAll(..)(Person) 31 | self.name = name # Person = DecoDecorate(Person) 32 | self.pay = pay 33 | def giveRaise(self, percent): 34 | self.pay *= (1.0 + percent) 35 | def lastName(self): 36 | return self.name.split()[-1] 37 | 38 | bob = Person('Bob Smith', 50000) 39 | sue = Person('Sue Jones', 100000) 40 | print(bob.name, sue.name) 41 | sue.giveRaise(.10) 42 | print('%.2f' % sue.pay) 43 | print(bob.lastName(), sue.lastName()) 44 | 45 | # If using timer: total time per method 46 | """ 47 | print('-'*40) 48 | print('%.5f' % Person.__init__.alltime) 49 | print('%.5f' % Person.giveRaise.alltime) 50 | print('%.5f' % Person.lastName.alltime) 51 | """ -------------------------------------------------------------------------------- /code/decoall-manual.py: -------------------------------------------------------------------------------- 1 | from decotools import tracer 2 | 3 | class Person: 4 | @tracer 5 | def __init__(self, name, pay): 6 | self.name = name 7 | self.pay = pay 8 | 9 | @tracer 10 | def giveRaise(self, percent): # giveRaise = tracer(giverRaise) 11 | self.pay *= (1.0 + percent) # onCall remembers giveRaise 12 | 13 | @tracer 14 | def lastName(self): # lastName = tracer(lastName) 15 | return self.name.split()[-1] 16 | 17 | bob = Person('Bob Smith', 50000) 18 | sue = Person('Sue Jones', 100000) 19 | print(bob.name, sue.name) 20 | sue.giveRaise(.10) # Runs onCall(sue, .10) 21 | print('%.2f' % sue.pay) 22 | print(bob.lastName(), sue.lastName()) # Runs onCall(bob), remembers lastName 23 | -------------------------------------------------------------------------------- /code/decoall-meta-any.py: -------------------------------------------------------------------------------- 1 | # Metaclass factory: apply any decorator to all methods of a class 2 | 3 | from types import FunctionType 4 | from decotools import tracer, timer 5 | 6 | def decorateAll(decorator): 7 | class MetaDecorate(type): 8 | def __new__(meta, classname, supers, classdict): 9 | for attr, attrval in classdict.items(): 10 | if type(attrval) is FunctionType: 11 | classdict[attr] = decorator(attrval) 12 | return type.__new__(meta, classname, supers, classdict) 13 | return MetaDecorate 14 | 15 | class Person(metaclass=decorateAll(tracer)): # Apply a decorator to all 16 | def __init__(self, name, pay): 17 | self.name = name 18 | self.pay = pay 19 | def giveRaise(self, percent): 20 | self.pay *= (1.0 + percent) 21 | def lastName(self): 22 | return self.name.split()[-1] 23 | 24 | bob = Person('Bob Smith', 50000) 25 | sue = Person('Sue Jones', 100000) 26 | print(bob.name, sue.name) 27 | sue.giveRaise(.10) 28 | print('%.2f' % sue.pay) 29 | print(bob.lastName(), sue.lastName()) 30 | -------------------------------------------------------------------------------- /code/decoall-meta-any2.py: -------------------------------------------------------------------------------- 1 | # Metaclass factory: apply any decorator to all methods of a class 2 | 3 | from types import FunctionType 4 | from decotools import tracer, timer 5 | 6 | def decorateAll(decorator): 7 | class MetaDecorate(type): 8 | def __new__(meta, classname, supers, classdict): 9 | for attr, attrval in classdict.items(): 10 | if type(attrval) is FunctionType: 11 | classdict[attr] = decorator(attrval) 12 | return type.__new__(meta, classname, supers, classdict) 13 | return MetaDecorate 14 | 15 | #class Person(metaclass=decorateAll(tracer)): # Apply a decorator to all 16 | #class Person(metaclass=decorateAll(timer())): 17 | 18 | class Person(metaclass=decorateAll(timer(label='**'))): 19 | def __init__(self, name, pay): 20 | self.name = name 21 | self.pay = pay 22 | def giveRaise(self, percent): 23 | self.pay *= (1.0 + percent) 24 | def lastName(self): 25 | return self.name.split()[-1] 26 | 27 | bob = Person('Bob Smith', 50000) 28 | sue = Person('Sue Jones', 100000) 29 | print(bob.name, sue.name) 30 | sue.giveRaise(.10) 31 | print('%.2f' % sue.pay) 32 | print(bob.lastName(), sue.lastName()) 33 | 34 | # If using timer: total time per method 35 | 36 | print('-'*40) 37 | print('%.5f' % Person.__init__.alltime) 38 | print('%.5f' % Person.giveRaise.alltime) 39 | print('%.5f' % Person.lastName.alltime) 40 | -------------------------------------------------------------------------------- /code/decoall-meta-any3.py: -------------------------------------------------------------------------------- 1 | # Metaclass factory: apply any decorator to all methods of a class 2 | 3 | from types import FunctionType 4 | from decotools import tracer, timer 5 | 6 | def decorateAll(decorator): 7 | class MetaDecorate(type): 8 | def __new__(meta, classname, supers, classdict): 9 | for attr, attrval in classdict.items(): 10 | if type(attrval) is FunctionType: 11 | classdict[attr] = decorator(attrval) 12 | return type.__new__(meta, classname, supers, classdict) 13 | return MetaDecorate 14 | 15 | #class Person(metaclass=decorateAll(tracer)): # Apply a decorator to all 16 | #class Person(metaclass=decorateAll(timer())): 17 | #class Person(metaclass=decorateAll(timer(label='**'))): 18 | 19 | #class Person(metaclass=decorateAll(timer(label='**')(tracer))): 20 | #class Person(metaclass=decorateAll(tracer(timer(label='**')))): 21 | 22 | class Person(metaclass=decorateAll(tracer(timer(label='**')))): 23 | def __init__(self, name, pay): 24 | self.name = name 25 | self.pay = pay 26 | def giveRaise(self, percent): 27 | self.pay *= (1.0 + percent) 28 | def lastName(self): 29 | return self.name.split()[-1] 30 | 31 | bob = Person('Bob Smith', 50000) 32 | sue = Person('Sue Jones', 100000) 33 | print(bob.name, sue.name) 34 | sue.giveRaise(.10) 35 | print('%.2f' % sue.pay) 36 | print(bob.lastName(), sue.lastName()) 37 | 38 | 39 | -------------------------------------------------------------------------------- /code/decoall-meta.py: -------------------------------------------------------------------------------- 1 | # Metaclass that adds tracing decorator to every method of a client class 2 | 3 | from types import FunctionType 4 | from decotools import tracer 5 | 6 | class MetaTrace(type): 7 | def __new__(meta, classname, supers, classdict): 8 | for attr, attrval in classdict.items(): 9 | if type(attrval) is FunctionType: # Method? 10 | classdict[attr] = tracer(attrval) # Decorate it 11 | return type.__new__(meta, classname, supers, classdict) # Make class 12 | 13 | class Person(metaclass=MetaTrace): 14 | def __init__(self, name, pay): 15 | self.name = name 16 | self.pay = pay 17 | def giveRaise(self, percent): 18 | self.pay *= (1.0 + percent) 19 | def lastName(self): 20 | return self.name.split()[-1] 21 | 22 | bob = Person('Bob Smith', 50000) 23 | sue = Person('Sue Jones', 100000) 24 | print(bob.name, sue.name) 25 | sue.giveRaise(.10) 26 | print('%.2f' % sue.pay) 27 | print(bob.lastName(), sue.lastName()) 28 | -------------------------------------------------------------------------------- /code/decoargs-vs-annotations.py: -------------------------------------------------------------------------------- 1 | # Using decorator arguments (3.X + 2.X) 2 | 3 | def rangetest(**argchecks): 4 | def onDecorator(func): 5 | def onCall(*pargs, **kargs): 6 | print(argchecks) 7 | for check in argchecks: 8 | pass # Add validation code here 9 | return func(*pargs, **kargs) 10 | return onCall 11 | return onDecorator 12 | 13 | @rangetest(a=(1, 5), c=(0.0, 1.0)) 14 | def func(a, b, c): # func = rangetest(...)(func) 15 | print(a + b + c) 16 | 17 | func(1, 2, c=3) # Runs onCall, argchecks in scope 18 | 19 | # Using function annotations (3.X only) 20 | 21 | def rangetest(func): 22 | def onCall(*pargs, **kargs): 23 | argchecks = func.__annotations__ 24 | print(argchecks) 25 | for check in argchecks: 26 | pass # Add validation code here 27 | return func(*pargs, **kargs) 28 | return onCall 29 | 30 | @rangetest 31 | def func(a:(1, 5), b, c:(0.0, 1.0)): # func = rangetest(func) 32 | print(a + b + c) 33 | 34 | func(1, 2, c=3) # Runs onCall, annotations on func 35 | -------------------------------------------------------------------------------- /code/decorator1.py: -------------------------------------------------------------------------------- 1 | # File decorator1.py 2 | 3 | class tracer: 4 | def __init__(self, func): # On @ decoration: save original func 5 | self.calls = 0 6 | self.func = func 7 | def __call__(self, *args): # On later calls: run original func 8 | self.calls += 1 9 | print('call %s to %s' % (self.calls, self.func.__name__)) 10 | self.func(*args) 11 | 12 | @tracer 13 | def spam(a, b, c): # spam = tracer(spam) 14 | print(a + b + c) # Wraps spam in a decorator object 15 | -------------------------------------------------------------------------------- /code/decorator2.py: -------------------------------------------------------------------------------- 1 | class tracer: # State via instance attributes 2 | def __init__(self, func): # On @ decorator 3 | self.calls = 0 # Save func for later call 4 | self.func = func 5 | def __call__(self, *args, **kwargs): # On call to original function 6 | self.calls += 1 7 | print('call %s to %s' % (self.calls, self.func.__name__)) 8 | return self.func(*args, **kwargs) 9 | 10 | @tracer 11 | def spam(a, b, c): # Same as: spam = tracer(spam) 12 | print(a + b + c) # Triggers tracer.__init__ 13 | 14 | @tracer 15 | def eggs(x, y): # Same as: eggs = tracer(eggs) 16 | print(x ** y) # Wraps eggs in a tracer object 17 | 18 | spam(1, 2, 3) # Really calls tracer instance: runs tracer.__call__ 19 | spam(a=4, b=5, c=6) # spam is an instance attribute 20 | 21 | eggs(2, 16) # Really calls tracer instance, self.func is eggs 22 | eggs(4, y=4) # self.calls is per-decoration here 23 | -------------------------------------------------------------------------------- /code/decorator3.py: -------------------------------------------------------------------------------- 1 | calls = 0 2 | def tracer(func): # State via enclosing scope and global 3 | def wrapper(*args, **kwargs): # Instead of class attributes 4 | global calls # calls is global, not per-function 5 | calls += 1 6 | print('call %s to %s' % (calls, func.__name__)) 7 | return func(*args, **kwargs) 8 | return wrapper 9 | 10 | @tracer 11 | def spam(a, b, c): # Same as: spam = tracer(spam) 12 | print(a + b + c) 13 | 14 | @tracer 15 | def eggs(x, y): # Same as: eggs = tracer(eggs) 16 | print(x ** y) 17 | 18 | spam(1, 2, 3) # Really calls wrapper, assigned to spam 19 | spam(a=4, b=5, c=6) # wrapper calls spam 20 | 21 | eggs(2, 16) # Really calls wrapper, assigned to eggs 22 | eggs(4, y=4) # Global calls is not per-decoration here! 23 | -------------------------------------------------------------------------------- /code/decorator4.py: -------------------------------------------------------------------------------- 1 | def tracer(func): # State via enclosing scope and nonlocal 2 | calls = 0 # Instead of class attrs or global 3 | def wrapper(*args, **kwargs): # calls is per-function, not global 4 | nonlocal calls 5 | calls += 1 6 | print('call %s to %s' % (calls, func.__name__)) 7 | return func(*args, **kwargs) 8 | return wrapper 9 | 10 | @tracer 11 | def spam(a, b, c): # Same as: spam = tracer(spam) 12 | print(a + b + c) 13 | 14 | @tracer 15 | def eggs(x, y): # Same as: eggs = tracer(eggs) 16 | print(x ** y) 17 | 18 | spam(1, 2, 3) # Really calls wrapper, bound to func 19 | spam(a=4, b=5, c=6) # wrapper calls spam 20 | 21 | eggs(2, 16) # Really calls wrapper, bound to eggs 22 | eggs(4, y=4) # Nonlocal calls _is_ per-decoration here 23 | -------------------------------------------------------------------------------- /code/decorator5.py: -------------------------------------------------------------------------------- 1 | def tracer(func): # State via enclosing scope and func attr 2 | def wrapper(*args, **kwargs): # calls is per-function, not global 3 | wrapper.calls += 1 4 | print('call %s to %s' % (wrapper.calls, func.__name__)) 5 | return func(*args, **kwargs) 6 | wrapper.calls = 0 7 | return wrapper 8 | 9 | @tracer 10 | def spam(a, b, c): # Same as: spam = tracer(spam) 11 | print(a + b + c) 12 | 13 | @tracer 14 | def eggs(x, y): # Same as: eggs = tracer(eggs) 15 | print(x ** y) 16 | 17 | spam(1, 2, 3) # Really calls wrapper, assigned to spam 18 | spam(a=4, b=5, c=6) # wrapper calls spam 19 | 20 | eggs(2, 16) # Really calls wrapper, assigned to eggs 21 | eggs(4, y=4) # wrapper.calls _is_ per-decoration here 22 | -------------------------------------------------------------------------------- /code/decotools.py: -------------------------------------------------------------------------------- 1 | # File decotools.py: assorted decorator tools 2 | import time 3 | 4 | def tracer(func): # Use function, not class with __call__ 5 | calls = 0 # Else self is decorator instance only 6 | def onCall(*args, **kwargs): 7 | nonlocal calls 8 | calls += 1 9 | print('call %s to %s' % (calls, func.__name__)) 10 | return func(*args, **kwargs) 11 | return onCall 12 | 13 | def timer(label='', trace=True): # On decorator args: retain args 14 | def onDecorator(func): # On @: retain decorated func 15 | def onCall(*args, **kargs): # On calls: call original 16 | start = time.clock() # State is scopes + func attr 17 | result = func(*args, **kargs) 18 | elapsed = time.clock() - start 19 | onCall.alltime += elapsed 20 | if trace: 21 | format = '%s%s: %.5f, %.5f' 22 | values = (label, func.__name__, elapsed, onCall.alltime) 23 | print(format % values) 24 | return result 25 | onCall.alltime = 0 26 | return onCall 27 | return onDecorator 28 | -------------------------------------------------------------------------------- /code/desc-computed.py: -------------------------------------------------------------------------------- 1 | class DescSquare: 2 | def __init__(self, start): # Each desc has own state 3 | self.value = start 4 | def __get__(self, instance, owner): # On attr fetch 5 | return self.value ** 2 6 | def __set__(self, instance, value): # On attr assign 7 | self.value = value # No delete or docs 8 | 9 | class Client1: 10 | X = DescSquare(3) # Assign descriptor instance to class attr 11 | 12 | class Client2: 13 | X = DescSquare(32) # Another instance in another client class 14 | # Could also code 2 instances in same class 15 | c1 = Client1() 16 | c2 = Client2() 17 | 18 | print(c1.X) # 3 ** 2 19 | c1.X = 4 20 | print(c1.X) # 4 ** 2 21 | print(c2.X) # 32 ** 2 (1024) 22 | -------------------------------------------------------------------------------- /code/desc-person-nested.py: -------------------------------------------------------------------------------- 1 | class Person: 2 | def __init__(self, name): 3 | self._name = name 4 | 5 | class Name: # Using a nested class 6 | "name descriptor docs" 7 | def __get__(self, instance, owner): 8 | print('fetch...') 9 | return instance._name 10 | def __set__(self, instance, value): 11 | print('change...') 12 | instance._name = value 13 | def __delete__(self, instance): 14 | print('remove...') 15 | del instance._name 16 | name = Name() 17 | 18 | bob = Person('Bob Smith') # bob has a managed attribute 19 | print(bob.name) # Runs Name.__get__ 20 | bob.name = 'Robert Smith' # Runs Name.__set__ 21 | print(bob.name) 22 | del bob.name # Runs Name.__delete__ 23 | 24 | print('-'*20) 25 | sue = Person('Sue Jones') # sue inherits descriptor too 26 | print(sue.name) 27 | print(Person.Name.__doc__) 28 | -------------------------------------------------------------------------------- /code/desc-person.py: -------------------------------------------------------------------------------- 1 | class Name: # Use (object) in 2.X 2 | "name descriptor docs" 3 | def __get__(self, instance, owner): 4 | print('fetch...') 5 | return instance._name 6 | def __set__(self, instance, value): 7 | print('change...') 8 | instance._name = value 9 | def __delete__(self, instance): 10 | print('remove...') 11 | del instance._name 12 | 13 | class Person: # Use (object) in 2.X 14 | def __init__(self, name): 15 | self._name = name 16 | name = Name() # Assign descriptor to attr 17 | 18 | bob = Person('Bob Smith') # bob has a managed attribute 19 | print(bob.name) # Runs Name.__get__ 20 | bob.name = 'Robert Smith' # Runs Name.__set__ 21 | print(bob.name) 22 | del bob.name # Runs Name.__delete__ 23 | 24 | print('-'*20) 25 | sue = Person('Sue Jones') # sue inherits descriptor too 26 | print(sue.name) 27 | print(Name.__doc__) # Or help(Name) 28 | -------------------------------------------------------------------------------- /code/desc-powers.py: -------------------------------------------------------------------------------- 1 | # Same, but with descriptors (per-instance state) 2 | 3 | class DescSquare(object): 4 | def __get__(self, instance, owner): 5 | return instance._square ** 2 6 | def __set__(self, instance, value): 7 | instance._square = value 8 | 9 | class DescCube(object): 10 | def __get__(self, instance, owner): 11 | return instance._cube ** 3 12 | 13 | class Powers(object): # Need all (object) in 2.X only 14 | square = DescSquare() 15 | cube = DescCube() 16 | def __init__(self, square, cube): 17 | self._square = square # "self.square = square" works too, 18 | self._cube = cube # because it triggers desc __set__! 19 | 20 | X = Powers(3, 4) 21 | print(X.square) # 3 ** 2 = 9 22 | print(X.cube) # 4 ** 3 = 64 23 | X.square = 5 24 | print(X.square) # 5 ** 2 = 25 25 | -------------------------------------------------------------------------------- /code/desc-state-desc.py: -------------------------------------------------------------------------------- 1 | class DescState: # Use descriptor state, (object) in 2.X 2 | def __init__(self, value): 3 | self.value = value 4 | def __get__(self, instance, owner): # On attr fetch 5 | print('DescState get') 6 | return self.value * 10 7 | def __set__(self, instance, value): # On attr assign 8 | print('DescState set') 9 | self.value = value 10 | 11 | # Client class 12 | class CalcAttrs: 13 | X = DescState(2) # Descriptor class attr 14 | Y = 3 # Class attr 15 | def __init__(self): 16 | self.Z = 4 # Instance attr 17 | 18 | obj = CalcAttrs() 19 | print(obj.X, obj.Y, obj.Z) # X is computed, others are not 20 | obj.X = 5 # X assignment is intercepted 21 | CalcAttrs.Y = 6 # Y reassigned in class 22 | obj.Z = 7 # Z assigned in instance 23 | print(obj.X, obj.Y, obj.Z) 24 | 25 | obj2 = CalcAttrs() # But X uses shared data, like Y! 26 | print(obj2.X, obj2.Y, obj2.Z) 27 | -------------------------------------------------------------------------------- /code/desc-state-inst.py: -------------------------------------------------------------------------------- 1 | class InstState: # Using instance state, (object) in 2.X 2 | def __get__(self, instance, owner): 3 | print('InstState get') # Assume set by client class 4 | return instance._X * 10 5 | def __set__(self, instance, value): 6 | print('InstState set') 7 | instance._X = value 8 | 9 | # Client class 10 | class CalcAttrs: 11 | X = InstState() # Descriptor class attr 12 | Y = 3 # Class attr 13 | def __init__(self): 14 | self._X = 2 # Instance attr 15 | self.Z = 4 # Instance attr 16 | 17 | obj = CalcAttrs() 18 | print(obj.X, obj.Y, obj.Z) # X is computed, others are not 19 | obj.X = 5 # X assignment is intercepted 20 | CalcAttrs.Y = 6 # Y reassigned in class 21 | obj.Z = 7 # Z assigned in instance 22 | print(obj.X, obj.Y, obj.Z) 23 | 24 | obj2 = CalcAttrs() # But X differs now, like Z! 25 | print(obj2.X, obj2.Y, obj2.Z) 26 | -------------------------------------------------------------------------------- /code/dicts.py: -------------------------------------------------------------------------------- 1 | def copyDict(old): 2 | new = {} 3 | for key in old.keys(): 4 | new[key] = old[key] # Or D.copy() today 5 | return new 6 | 7 | def addDict(d1, d2): 8 | new = {} 9 | for key in d1.keys(): 10 | new[key] = d1[key] # Or D1.update(D2) today 11 | for key in d2.keys(): 12 | new[key] = d2[key] 13 | return new 14 | 15 | 16 | """ 17 | % python 18 | >>> from dicts import * 19 | >>> d = {1: 1, 2: 2} 20 | >>> e = copyDict(d) 21 | >>> d[2] = '?' 22 | >>> d 23 | {1: 1, 2: '?'} 24 | >>> e 25 | {1: 1, 2: 2} 26 | 27 | >>> x = {1: 1} 28 | >>> y = {2: 2} 29 | >>> z = addDict(x, y) 30 | >>> z 31 | {1: 1, 2: 2} 32 | """ -------------------------------------------------------------------------------- /code/dicttable.py: -------------------------------------------------------------------------------- 1 | D = {} 2 | D = {'name': 'Bob', 'age': 40.0} 3 | print(D) 4 | E = {'cto': {'name': 'Bob', 'age': 40}} 5 | print(E) 6 | D = dict(name='Bob', age=40) 7 | print(D) 8 | D = dict([['name', 'Bob'], ['age', 40]]) 9 | print(D) 10 | #D = dict(zip(keyslist, valslist)) 11 | D = dict.fromkeys(['name', 'age']) 12 | print(D) 13 | print(D['name']) 14 | print(E['cto']['age']) 15 | print('age' in D) 16 | D.keys() 17 | D.values() 18 | D.items() 19 | D.copy() 20 | #D.update(D2) 21 | #D.get(key, default?) 22 | #D.pop(key, default?) 23 | #D.setdefault(key, default?) 24 | D.popitem() 25 | """ 26 | len(D) 27 | D[key] = 42 28 | del D[key] 29 | list(D.keys()) 30 | D1.keys() & D2.keys() 31 | D.viewkeys(), D.viewvalues() 32 | """ 33 | 34 | L = [] 35 | L = [123, 'abc', 1.23, {}] 36 | print(L) 37 | L = ['Bob', 40.0, ['dev', 'mgr']] 38 | print(L) 39 | L = list('spam') 40 | print(L) 41 | L = list(range(-4, 4)) 42 | print(L) 43 | """ 44 | L[i] 45 | L[i][j] 46 | L[i:j] 47 | len(L) 48 | L1 + L2 49 | """ 50 | L * 3 51 | for x in L: print(x) 52 | 3 in L 53 | L.append(4) 54 | L.extend([5,6,7]) 55 | print(L) 56 | """ 57 | L.insert(I, X) 58 | L.index(1) 59 | L.count(X) 60 | L.sort() 61 | L.reverse() 62 | L.copy() 63 | L.pop(i) 64 | L.remove(2) 65 | del L[k] 66 | del L[i:j] 67 | L[i:j] = [] 68 | L[i] = 3 69 | L[i:j] = [4,5,6] 70 | """ 71 | L = [x**2 for x in range(5)] 72 | print(L) 73 | print(list(map(ord, 'spam'))) 74 | -------------------------------------------------------------------------------- /code/dir1/__init__.py: -------------------------------------------------------------------------------- 1 | print('dir1 init') 2 | x = 1 3 | -------------------------------------------------------------------------------- /code/dir1/dir2/__init__.py: -------------------------------------------------------------------------------- 1 | print('dir2 init') 2 | y = 2 3 | -------------------------------------------------------------------------------- /code/dir1/dir2/mod.py: -------------------------------------------------------------------------------- 1 | print('in mod.py') 2 | z = 3 3 | -------------------------------------------------------------------------------- /code/divbad.py: -------------------------------------------------------------------------------- 1 | X = 0 2 | print(1 / X) 3 | -------------------------------------------------------------------------------- /code/docstr.py: -------------------------------------------------------------------------------- 1 | "I am: docstr.__doc__" 2 | 3 | def func(args): 4 | "I am: docstr.func.__doc__" 5 | pass 6 | 7 | class spam: 8 | "I am: spam.__doc__ or docstr.spam.__doc__ or self.__doc__" 9 | def method(self): 10 | "I am: spam.method.__doc__ or self.method.__doc__" 11 | print(self.__doc__) 12 | print(self.method.__doc__) 13 | -------------------------------------------------------------------------------- /code/docstrings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Module documentation 3 | Words Go Here 4 | """ 5 | 6 | spam = 40 7 | 8 | def square(x): 9 | """ 10 | function documentation 11 | can we have your liver then? 12 | """ 13 | return x ** 2 # square 14 | 15 | class Employee: 16 | "class documentation" 17 | pass 18 | 19 | print(square(4)) 20 | print(square.__doc__) 21 | -------------------------------------------------------------------------------- /code/domparse.py: -------------------------------------------------------------------------------- 1 | from xml.dom.minidom import parse, Node 2 | xmltree = parse('mybooks.xml') 3 | for node1 in xmltree.getElementsByTagName('title'): 4 | for node2 in node1.childNodes: 5 | if node2.nodeType == Node.TEXT_NODE: 6 | print(node2.data) 7 | -------------------------------------------------------------------------------- /code/dualpkg/m1.py: -------------------------------------------------------------------------------- 1 | def somefunc(): 2 | print('m1.somefunc') 3 | -------------------------------------------------------------------------------- /code/dualpkg/m2.py: -------------------------------------------------------------------------------- 1 | # Try to Import module in same directory as me, but: 2 | 3 | #from . import m1 # <==OK in package, not allowed in non-package mode in 2.X + 3.X 4 | #import m1 # <==OK in program, fails to check package's own dir in 3.X 5 | 6 | # set PYTHONPATH=c:\code 7 | import dualpkg.m1 as m1 # <==works in both modes if sys.path includes pks root 8 | 9 | def somefunc(): 10 | m1.somefunc() 11 | print('m2.somefunc') 12 | 13 | if __name__ == '__main__': 14 | somefunc() # Self-test or top-level script code -------------------------------------------------------------------------------- /code/main.py: -------------------------------------------------------------------------------- 1 | # code\main.py 2 | #import string 3 | from . import string 4 | print(string) 5 | 6 | -------------------------------------------------------------------------------- /code/makedb.py: -------------------------------------------------------------------------------- 1 | # File makedb.py: store Person objects on a shelve database 2 | 3 | from person import Person, Manager # Load our classes 4 | bob = Person('Bob Smith') # Re-create objects to be stored 5 | sue = Person('Sue Jones', job='dev', pay=100000) 6 | tom = Manager('Tom Jones', 50000) 7 | 8 | import shelve 9 | db = shelve.open('persondb') # Filename where objects are stored 10 | for object in (bob, sue, tom): # Use object's name attr as key 11 | db[object.name] = object # Store object on shelve by key 12 | db.close() # Close after making changes 13 | -------------------------------------------------------------------------------- /code/makeopen.py: -------------------------------------------------------------------------------- 1 | import builtins 2 | 3 | def makeopen(id): 4 | original = builtins.open 5 | def custom(*kargs, **pargs): 6 | print('Custom open call %r:' % id , kargs, pargs) 7 | return original(*kargs, **pargs) 8 | builtins.open = custom 9 | -------------------------------------------------------------------------------- /code/makeopen_class.py: -------------------------------------------------------------------------------- 1 | import builtins 2 | 3 | class makeopen: 4 | def __init__(self, id): # See Part 6: __call__ catches self() 5 | self.id = id 6 | self.original = builtins.open 7 | builtins.open = self 8 | def __call__(self, *kargs, **pargs): 9 | print('Custom open call %r:' % self.id, kargs, pargs) 10 | return self.original(*kargs, **pargs) 11 | -------------------------------------------------------------------------------- /code/maker.py: -------------------------------------------------------------------------------- 1 | # File: maker.py 2 | file = open('myfile.txt', 'w') 3 | file.write('Hello file world!\n') # Or: open().write() 4 | file.close() -------------------------------------------------------------------------------- /code/manage-inst-deco.py: -------------------------------------------------------------------------------- 1 | # Class decorator to trace external instance attribute fetches 2 | 3 | def Tracer(aClass): # On @ decorator 4 | class Wrapper: 5 | def __init__(self, *args, **kargs): # On instance creation 6 | self.wrapped = aClass(*args, **kargs) # Use enclosing scope name 7 | def __getattr__(self, attrname): 8 | print('Trace:', attrname) # Catches all but .wrapped 9 | return getattr(self.wrapped, attrname) # Delegate to wrapped object 10 | return Wrapper 11 | 12 | @Tracer 13 | class Person: # Person = Tracer(Person) 14 | def __init__(self, name, hours, rate): # Wrapper remembers Person 15 | self.name = name 16 | self.hours = hours 17 | self.rate = rate # In-method fetch not traced 18 | def pay(self): 19 | return self.hours * self.rate 20 | 21 | bob = Person('Bob', 40, 50) # bob is really a Wrapper 22 | print(bob.name) # Wrapper embeds a Person 23 | print(bob.pay()) # Triggers __getattr__ 24 | -------------------------------------------------------------------------------- /code/manage-inst-meta.py: -------------------------------------------------------------------------------- 1 | # Manage instances like the prior example, but with a metaclass 2 | 3 | def Tracer(classname, supers, classdict): # On class creation call 4 | aClass = type(classname, supers, classdict) # Make client class 5 | class Wrapper: 6 | def __init__(self, *args, **kargs): # On instance creation 7 | self.wrapped = aClass(*args, **kargs) 8 | def __getattr__(self, attrname): 9 | print('Trace:', attrname) # Catches all but .wrapped 10 | return getattr(self.wrapped, attrname) # Delegate to wrapped object 11 | return Wrapper 12 | 13 | class Person(metaclass=Tracer): # Make Person with Tracer 14 | def __init__(self, name, hours, rate): # Wrapper remembers Person 15 | self.name = name 16 | self.hours = hours 17 | self.rate = rate # In-method fetch not traced 18 | def pay(self): 19 | return self.hours * self.rate 20 | 21 | bob = Person('Bob', 40, 50) # bob is really a Wrapper 22 | print(bob.name) # Wrapper embeds a Person 23 | print(bob.pay()) # Triggers __getattr__ 24 | -------------------------------------------------------------------------------- /code/manynames.py: -------------------------------------------------------------------------------- 1 | X = 11 # Global (module) name/attribute (X, or manynames.X) 2 | 3 | def f(): 4 | print(X) # Access global X (11) 5 | 6 | def g(): 7 | X = 22 # Local (function) variable (X, hides module X) 8 | print(X) 9 | 10 | class C: 11 | X = 33 # Class attribute (C.X) 12 | def m(self): 13 | X = 44 # Local variable in method (X) 14 | self.X = 55 # Instance attribute (instance.X) 15 | 16 | if __name__ == '__main__': 17 | print(X) # 11: module (a.k.a. manynames.X outside file) 18 | f() # 11: global 19 | g() # 22: local 20 | print(X) # 11: module name unchanged 21 | 22 | obj = C() # Make instance 23 | print(obj.X) # 33: class name inherited by instance 24 | 25 | obj.m() # Attach attribute name X to instance now 26 | print(obj.X) # 55: instance 27 | print(C.X) # 33: class (a.k.a. obj.X if no X in instance) 28 | 29 | #print(C.m.X) # FAILS: only visible in method 30 | #print(g.X) # FAILS: only visible in function 31 | -------------------------------------------------------------------------------- /code/mapattrs-lister.py: -------------------------------------------------------------------------------- 1 | # Code here was run interactively 2 | # tests in Chapter 31's lister example 3 | 4 | from mapattr import * 5 | from testmixin0 import Sub 6 | I = Sub() 7 | #trace(I.__dict__.keys()) # in instance 8 | 9 | trace(dflr(I.__class__)) # 2.X search order 10 | trace(inheritance(I)) # inheritance class order 11 | 12 | trace(mapattrs(I)) 13 | 14 | trace(mapattrs(I, bysource=True)) 15 | 16 | trace(mapattrs(I, withobject=True)) 17 | 18 | amap = mapattrs(I, withobject=True, bysource=True) 19 | trace(amap) 20 | 21 | -------------------------------------------------------------------------------- /code/mapattrs-slots.py: -------------------------------------------------------------------------------- 1 | # mapattrs-slots.py: test __slots__ attribute inheritance 2 | from mapattrs import mapattrs, trace 3 | 4 | class A(object): __slots__ = ['a', 'b']; x = 1; y = 2 5 | class B(A): __slots__ = ['b', 'c'] 6 | class C(A): x = 2 7 | class D(B, C): 8 | z = 3 9 | def __init__(self): self.name = 'Bob'; 10 | 11 | I = D() 12 | trace(mapattrs(I, bysource=True)) # Also: trace(mapattrs(I)) 13 | 14 | -------------------------------------------------------------------------------- /code/mergedexc.py: -------------------------------------------------------------------------------- 1 | # File mergedexc.py (Python 3.X + 2.X) 2 | sep = '-' * 45 + '\n' 3 | 4 | 5 | print(sep + 'EXCEPTION RAISED AND CAUGHT') 6 | try: 7 | x = 'spam'[99] 8 | except IndexError: 9 | print('except run') 10 | finally: 11 | print('finally run') 12 | print('after run') 13 | 14 | 15 | print(sep + 'NO EXCEPTION RAISED') 16 | try: 17 | x = 'spam'[3] 18 | except IndexError: 19 | print('except run') 20 | finally: 21 | print('finally run') 22 | print('after run') 23 | 24 | 25 | print(sep + 'NO EXCEPTION RAISED, WITH ELSE') 26 | try: 27 | x = 'spam'[3] 28 | except IndexError: 29 | print('except run') 30 | else: 31 | print('else run') 32 | finally: 33 | print('finally run') 34 | print('after run') 35 | 36 | 37 | print(sep + 'EXCEPTION RAISED BUT NOT CAUGHT') 38 | try: 39 | x = 1 / 0 40 | except IndexError: 41 | print('except run') 42 | finally: 43 | print('finally run') 44 | print('after run') 45 | -------------------------------------------------------------------------------- /code/metaclass1-2x-nosuper.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | class MetaOne(type): 4 | def __new__(meta, classname, supers, classdict): 5 | print('In MetaOne.new:', meta, classname, supers, classdict, sep='\n...') 6 | return type.__new__(meta, classname, supers, classdict) 7 | 8 | print('making class') 9 | class Spam: # Inherits from none, instance of MetaOne 10 | __metaclass__ = MetaOne 11 | data = 1 # Class data attribute 12 | def meth(self, arg): # Class method attribute 13 | return self.data + arg 14 | 15 | print('making instance') 16 | X = Spam() 17 | print('data:', X.data, X.meth(2)) 18 | print(Spam.__bases__, X.__getattribute__, Spam.__mro__) -------------------------------------------------------------------------------- /code/metaclass1-2x.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | class MetaOne(type): 4 | def __new__(meta, classname, supers, classdict): 5 | print('In MetaOne.new:', meta, classname, supers, classdict, sep='\n...') 6 | return type.__new__(meta, classname, supers, classdict) 7 | 8 | class Eggs(object): 9 | pass 10 | 11 | print('making class') 12 | class Spam(Eggs, object): # Inherits from Eggs, instance of MetaOne 13 | __metaclass__ = MetaOne 14 | data = 1 # Class data attribute 15 | def meth(self, arg): # Class method attribute 16 | return self.data + arg 17 | 18 | print('making instance') 19 | X = Spam() 20 | print('data:', X.data, X.meth(2)) 21 | -------------------------------------------------------------------------------- /code/metaclass1.py: -------------------------------------------------------------------------------- 1 | class MetaOne(type): 2 | def __new__(meta, classname, supers, classdict): 3 | print('In MetaOne.new:', meta, classname, supers, classdict, sep='\n...') 4 | return type.__new__(meta, classname, supers, classdict) 5 | 6 | class Eggs: 7 | pass 8 | 9 | print('making class') 10 | class Spam(Eggs, metaclass=MetaOne): # Inherits from Eggs, instance of MetaOne 11 | data = 1 # Class data attribute 12 | def meth(self, arg): # Class method attribute 13 | return self.data + arg 14 | 15 | print('making instance') 16 | X = Spam() 17 | print('data:', X.data, X.meth(2)) 18 | -------------------------------------------------------------------------------- /code/metaclass2.py: -------------------------------------------------------------------------------- 1 | class MetaTwo(type): 2 | def __new__(meta, classname, supers, classdict): 3 | print('In MetaTwo.new: ', classname, supers, classdict, sep='\n...') 4 | return type.__new__(meta, classname, supers, classdict) 5 | 6 | def __init__(Class, classname, supers, classdict): 7 | print('In MetaTwo.init:', classname, supers, classdict, sep='\n...') 8 | print('...init class object:', list(Class.__dict__.keys())) 9 | 10 | class Eggs: 11 | pass 12 | 13 | print('making class') 14 | class Spam(Eggs, metaclass=MetaTwo): # Inherits from Eggs, instance of MetaTwo 15 | data = 1 # Class data attribute 16 | def meth(self, arg): # Class method attribute 17 | return self.data + arg 18 | 19 | print('making instance') 20 | X = Spam() 21 | print('data:', X.data, X.meth(2)) 22 | -------------------------------------------------------------------------------- /code/metaclass3.py: -------------------------------------------------------------------------------- 1 | # A simple function can serve as a metaclass too 2 | 3 | def MetaFunc(classname, supers, classdict): 4 | print('In MetaFunc: ', classname, supers, classdict, sep='\n...') 5 | return type(classname, supers, classdict) 6 | 7 | class Eggs: 8 | pass 9 | 10 | print('making class') 11 | class Spam(Eggs, metaclass=MetaFunc): # Run simple function at end 12 | data = 1 # Function returns class 13 | def meth(self, arg): 14 | return self.data + arg 15 | 16 | print('making instance') 17 | X = Spam() 18 | print('data:', X.data, X.meth(2)) 19 | -------------------------------------------------------------------------------- /code/metaclass4-super.py: -------------------------------------------------------------------------------- 1 | # A normal superclass can provide __call__ for instance metaclass too 2 | # Instances inherit from classes and their supers normally 3 | 4 | class SuperMetaObj: 5 | def __call__(self, classname, supers, classdict): 6 | print('In SuperMetaObj.call: ', classname, supers, classdict, sep='\n...') 7 | Class = self.__New__(classname, supers, classdict) 8 | self.__Init__(Class, classname, supers, classdict) 9 | return Class 10 | 11 | class SubMetaObj(SuperMetaObj): 12 | def __New__(self, classname, supers, classdict): 13 | print('In SubMetaObj.new: ', classname, supers, classdict, sep='\n...') 14 | return type(classname, supers, classdict) 15 | 16 | def __Init__(self, Class, classname, supers, classdict): 17 | print('In SubMetaObj.init:', classname, supers, classdict, sep='\n...') 18 | print('...init class object:', list(Class.__dict__.keys())) 19 | 20 | class Eggs: 21 | pass 22 | 23 | print('making class') 24 | class Spam(Eggs, metaclass=SubMetaObj()): # meta is a normal class instance 25 | data = 1 # Called at end of statement 26 | def meth(self, arg): 27 | return self.data + arg 28 | 29 | print('making instance') 30 | X = Spam() 31 | print('data:', X.data, X.meth(2)) 32 | -------------------------------------------------------------------------------- /code/metaclass4.py: -------------------------------------------------------------------------------- 1 | # A normal class instance can serve as a metaclass too 2 | 3 | class MetaObj: 4 | def __call__(self, classname, supers, classdict): 5 | print('In MetaObj.call: ', classname, supers, classdict, sep='\n...') 6 | Class = self.__New__(classname, supers, classdict) 7 | self.__Init__(Class, classname, supers, classdict) 8 | return Class 9 | 10 | def __New__(self, classname, supers, classdict): 11 | print('In MetaObj.new: ', classname, supers, classdict, sep='\n...') 12 | return type(classname, supers, classdict) 13 | 14 | def __Init__(self, Class, classname, supers, classdict): 15 | print('In MetaObj.init:', classname, supers, classdict, sep='\n...') 16 | print('...init class object:', list(Class.__dict__.keys())) 17 | 18 | class Eggs: 19 | pass 20 | 21 | print('making class') 22 | class Spam(Eggs, metaclass=MetaObj()): # MetaObj is normal class instance 23 | data = 1 # Called at end of statement 24 | def meth(self, arg): 25 | return self.data + arg 26 | 27 | print('making instance') 28 | X = Spam() 29 | print('data:', X.data, X.meth(2)) 30 | -------------------------------------------------------------------------------- /code/metaclass5-hmm.py: -------------------------------------------------------------------------------- 1 | # __call__ can be redefined, metas can have metas 2 | 3 | class SuperMeta(type): 4 | def __call__(meta, classname, supers, classdict): 5 | print('In SuperMeta.call: ', meta, classname, supers, classdict, sep='\n...') 6 | return type.__call__(meta, classname, supers, classdict) 7 | 8 | class SubMeta(SuperMeta):#, metaclass=SuperMeta): 9 | def __new__(meta, classname, supers, classdict): 10 | print('In SubMeta.new: ', meta, classname, supers, classdict, sep='\n...') 11 | return type.__new__(meta, classname, supers, classdict) 12 | 13 | def __init__(Class, classname, supers, classdict): 14 | print('In SubMeta init:', classname, supers, classdict, sep='\n...') 15 | print('...init class object:', list(Class.__dict__.keys())) 16 | 17 | print(SubMeta.__class__) 18 | print(SubMeta.__mro__) 19 | print(SubMeta.__call__) 20 | print(SubMeta.__call__(SubMeta, 'xxx', (),{})) # Explicit calls work 21 | print(SubMeta('xxx', (),{})) # But implict built-in calls do not 22 | 23 | """ 24 | class Eggs: 25 | pass 26 | 27 | print('making class') 28 | class Spam(Eggs, metaclass=SubMeta): 29 | data = 1 30 | def meth(self, arg): 31 | pass 32 | 33 | print('making instance') 34 | X = Spam() 35 | print('data:', X.data) 36 | """ -------------------------------------------------------------------------------- /code/metaclass5.py: -------------------------------------------------------------------------------- 1 | # Classes can catch calls too (but built-ins look in metas, not supers!) 2 | 3 | class SuperMeta(type): 4 | def __call__(meta, classname, supers, classdict): 5 | print('In SuperMeta.call: ', classname, supers, classdict, sep='\n...') 6 | return type.__call__(meta, classname, supers, classdict) 7 | 8 | def __init__(Class, classname, supers, classdict): 9 | print('In SuperMeta init:', classname, supers, classdict, sep='\n...') 10 | print('...init class object:', list(Class.__dict__.keys())) 11 | 12 | print('making metaclass') 13 | class SubMeta(type, metaclass=SuperMeta): 14 | def __new__(meta, classname, supers, classdict): 15 | print('In SubMeta.new: ', classname, supers, classdict, sep='\n...') 16 | return type.__new__(meta, classname, supers, classdict) 17 | 18 | def __init__(Class, classname, supers, classdict): 19 | print('In SubMeta init:', classname, supers, classdict, sep='\n...') 20 | print('...init class object:', list(Class.__dict__.keys())) 21 | 22 | class Eggs: 23 | pass 24 | 25 | print('making class') 26 | class Spam(Eggs, metaclass=SubMeta): # Invoke SubMeta, via SuperMeta.__call__ 27 | data = 1 28 | def meth(self, arg): 29 | return self.data + arg 30 | 31 | print('making instance') 32 | X = Spam() 33 | print('data:', X.data, X.meth(2)) 34 | -------------------------------------------------------------------------------- /code/metaclass5b.py: -------------------------------------------------------------------------------- 1 | class SuperMeta(type): 2 | def __call__(meta, classname, supers, classdict): # By name, not built-in 3 | print('In SuperMeta.call:', classname) 4 | return type.__call__(meta, classname, supers, classdict) 5 | 6 | class SubMeta(SuperMeta): # Created by type default 7 | def __init__(Class, classname, supers, classdict): # Overrides type.__init__ 8 | print('In SubMeta init:', classname) 9 | 10 | print(SubMeta.__class__) 11 | print([n.__name__ for n in SubMeta.__mro__]) 12 | print() 13 | print(SubMeta.__call__) # Not a data descriptor if found by name 14 | print() 15 | SubMeta.__call__(SubMeta, 'xxx', (), {}) # Explicit calls work: class inheritance 16 | print() 17 | SubMeta('yyy', (), {}) # But implicit built-in calls do not: type 18 | -------------------------------------------------------------------------------- /code/metainstance.py: -------------------------------------------------------------------------------- 1 | # File metainstance.py 2 | 3 | class MetaOne(type): 4 | def __new__(meta, classname, supers, classdict): # Redefine type method 5 | print('In MetaOne.new:', classname) 6 | return type.__new__(meta, classname, supers, classdict) 7 | def toast(self): 8 | return 'toast' 9 | 10 | class Super(metaclass=MetaOne): # Metaclass inherited by subs too 11 | def spam(self): # MetaOne run twice for two classes 12 | return 'spam' 13 | 14 | class Sub(Super): # Superclass: inheritance versus instance 15 | def eggs(self): # Classes inherit from superclasses 16 | return 'eggs' # But not from metclasses 17 | -------------------------------------------------------------------------------- /code/minmax.py: -------------------------------------------------------------------------------- 1 | def minmax(test, *args): 2 | res = args[0] 3 | for arg in args[1:]: 4 | if test(arg, res): 5 | res = arg 6 | return res 7 | 8 | def lessthan(x, y): return x < y # See also: lambda 9 | def grtrthan(x, y): return x > y 10 | 11 | print(minmax(lessthan, 4, 2, 1, 5, 6, 3)) # Self-test code 12 | print(minmax(grtrthan, 4, 2, 1, 5, 6, 3)) 13 | -------------------------------------------------------------------------------- /code/minmax2.py: -------------------------------------------------------------------------------- 1 | print('I am:', __name__) 2 | 3 | def minmax(test, *args): 4 | res = args[0] 5 | for arg in args[1:]: 6 | if test(arg, res): 7 | res = arg 8 | return res 9 | 10 | def lessthan(x, y): return x < y 11 | def grtrthan(x, y): return x > y 12 | 13 | if __name__ == '__main__': 14 | print(minmax(lessthan, 4, 2, 1, 5, 6, 3)) # Self-test code 15 | print(minmax(grtrthan, 4, 2, 1, 5, 6, 3)) 16 | -------------------------------------------------------------------------------- /code/mins.py: -------------------------------------------------------------------------------- 1 | def min1(*args): 2 | res = args[0] 3 | for arg in args[1:]: 4 | if arg < res: 5 | res = arg 6 | return res 7 | 8 | def min2(first, *rest): 9 | for arg in rest: 10 | if arg < first: 11 | first = arg 12 | return first 13 | 14 | def min3(*args): 15 | tmp = list(args) # Or, in Python 2.4+: return sorted(args)[0] 16 | tmp.sort() 17 | return tmp[0] 18 | 19 | print(min1(3, 4, 1, 2)) 20 | print(min2("bb", "aa")) 21 | print(min3([2,2], [1,1], [3,3])) 22 | -------------------------------------------------------------------------------- /code/mod.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function # 2.X 2 | 3 | 4 | def adder(good=1, bad=2, ugly=3): 5 | return good + bad + ugly 6 | 7 | print(adder()) 8 | print(adder(5)) 9 | print(adder(5, 6)) 10 | print(adder(5, 6, 7)) 11 | print(adder(ugly=7, good=6, bad=5)) 12 | 13 | """ 14 | % python mod.py 15 | 6 16 | 10 17 | 14 18 | 18 19 | 18 20 | """ 21 | 22 | 23 | # Second part solutions 24 | 25 | def adder1(*args): # Sum any number of positional args 26 | tot = args[0] 27 | for arg in args[1:]: 28 | tot += arg 29 | return tot 30 | 31 | def adder2(**args): # Sum any number of keyword args 32 | argskeys = list(args.keys()) # list needed in 3.X! 33 | tot = args[argskeys[0]] 34 | for key in argskeys[1:]: 35 | tot += args[key] 36 | return tot 37 | 38 | def adder3(**args): # Same, but convert to list of values 39 | args = list(args.values()) # list needed to index in 3.X! 40 | tot = args[0] 41 | for arg in args[1:]: 42 | tot += arg 43 | return tot 44 | 45 | def adder4(**args): # Same, but reuse positional version 46 | return adder1(*args.values()) 47 | 48 | print(adder1(1, 2, 3), adder1('aa', 'bb', 'cc')) 49 | print(adder2(a=1, b=2, c=3), adder2(a='aa', b='bb', c='cc')) 50 | print(adder3(a=1, b=2, c=3), adder3(a='aa', b='bb', c='cc')) 51 | print(adder4(a=1, b=2, c=3), adder4(a='aa', b='bb', c='cc')) 52 | -------------------------------------------------------------------------------- /code/mod1.py: -------------------------------------------------------------------------------- 1 | X = 1 2 | import mod2 3 | 4 | print(X, end=' ') # My global X 5 | print(mod2.X, end=' ') # mod2's X 6 | print(mod2.mod3.X) # Nested mod3's X 7 | -------------------------------------------------------------------------------- /code/mod2.py: -------------------------------------------------------------------------------- 1 | X = 2 2 | import mod3 3 | 4 | print(X, end=' ') # My global X 5 | print(mod3.X) # mod3's X 6 | -------------------------------------------------------------------------------- /code/mod3.py: -------------------------------------------------------------------------------- 1 | X = 3 -------------------------------------------------------------------------------- /code/moda.py: -------------------------------------------------------------------------------- 1 | X = 88 # My X: global to this file only 2 | def f(): 3 | global X # Change this file's X 4 | X = 99 # Cannot see names in other modules 5 | -------------------------------------------------------------------------------- /code/modb.py: -------------------------------------------------------------------------------- 1 | X = 11 # My X: global to this file only 2 | 3 | import moda # Gain access to names in moda 4 | moda.f() # Sets moda.X, not this file's X 5 | print(X, moda.X) 6 | -------------------------------------------------------------------------------- /code/module1.py: -------------------------------------------------------------------------------- 1 | def printer(x): # Module attribute 2 | print(x) 3 | -------------------------------------------------------------------------------- /code/module2.py: -------------------------------------------------------------------------------- 1 | print('starting to load...') 2 | import sys 3 | name = 42 4 | 5 | def func(): pass 6 | 7 | class klass: pass 8 | 9 | print('done loading.') 10 | -------------------------------------------------------------------------------- /code/multiset.py: -------------------------------------------------------------------------------- 1 | from setwrapper import Set 2 | 3 | class MultiSet(Set): 4 | """ 5 | Inherits all Set names, but extends intersect and union to support 6 | multiple operands; note that "self" is still the first argument 7 | (stored in the *args argument now); also note that the inherited 8 | & and | operators call the new methods here with 2 arguments, but 9 | processing more than 2 requires a method call, not an expression; 10 | intersect doesn't remove duplicates here: the Set constructor does; 11 | """ 12 | def intersect(self, *others): 13 | res = [] 14 | for x in self: # Scan first sequence 15 | for other in others: # For all other args 16 | if x not in other: break # Item in each one? 17 | else: # No: break out of loop 18 | res.append(x) # Yes: add item to end 19 | return Set(res) 20 | 21 | def union(*args): # self is args[0] 22 | res = [] 23 | for seq in args: # For all args 24 | for x in seq: # For all nodes 25 | if not x in res: 26 | res.append(x) # Add new items to result 27 | return Set(res) 28 | -------------------------------------------------------------------------------- /code/mybooks.xml: -------------------------------------------------------------------------------- 1 | 2 | 1995~2013 3 | Learning Python 4 | Programming Python 5 | Python Pocket Reference 6 | O'Reilly Media 7 | 8 | -------------------------------------------------------------------------------- /code/myclient.py: -------------------------------------------------------------------------------- 1 | from mymod import countLines, countChars 2 | print(countLines('mymod.py'), countChars('mymod.py')) 3 | -------------------------------------------------------------------------------- /code/mydir.py: -------------------------------------------------------------------------------- 1 | #!python 2 | """ 3 | mydir.py: a module that lists the namespaces of other modules 4 | """ 5 | from __future__ import print_function # 2.X compatibility 6 | 7 | seplen = 60 8 | sepchr = '-' 9 | 10 | def listing(module, verbose=True): 11 | sepline = sepchr * seplen 12 | if verbose: 13 | print(sepline) 14 | print('name:', module.__name__, 'file:', module.__file__) 15 | print(sepline) 16 | 17 | count = 0 18 | for attr in sorted(module.__dict__): # Scan namespace keys (or enumerate) 19 | print('%02d) %s' % (count, attr), end = ' ') 20 | if attr.startswith('__'): 21 | print('') # Skip __file__, etc. 22 | else: 23 | print(getattr(module, attr)) # Same as .__dict__[attr] 24 | count += 1 25 | 26 | if verbose: 27 | print(sepline) 28 | print(module.__name__, 'has %d names' % count) 29 | print(sepline) 30 | 31 | if __name__ == '__main__': 32 | import mydir 33 | listing(mydir) # Self-test code: list myself 34 | -------------------------------------------------------------------------------- /code/myfile: -------------------------------------------------------------------------------- 1 | aaa 2 | bbb 3 | ccc 4 | -------------------------------------------------------------------------------- /code/myfile.py: -------------------------------------------------------------------------------- 1 | title = "The Meaning of Life" 2 | -------------------------------------------------------------------------------- /code/mylist.py: -------------------------------------------------------------------------------- 1 | class MyList: 2 | def __init__(self, start): 3 | #self.wrapped = start[:] # Copy start: no side effects 4 | self.wrapped = list(start) # Make sure it's a list here 5 | def __add__(self, other): 6 | return MyList(self.wrapped + other) 7 | def __mul__(self, time): 8 | return MyList(self.wrapped * time) 9 | def __getitem__(self, offset): # Also passed a slice in 3.X 10 | return self.wrapped[offset] # For iteration if no __iter__ 11 | def __len__(self): 12 | return len(self.wrapped) 13 | def __getslice__(self, low, high): # Ignored in 3.X: uses __getitem__ 14 | return MyList(self.wrapped[low:high]) 15 | def append(self, node): 16 | self.wrapped.append(node) 17 | def __getattr__(self, name): # Other methods: sort/reverse/etc 18 | return getattr(self.wrapped, name) 19 | def __repr__(self): # Catchall display method 20 | return repr(self.wrapped) 21 | 22 | if __name__ == '__main__': 23 | x = MyList('spam') 24 | print(x) 25 | print(x[2]) 26 | print(x[1:]) 27 | print(x + ['eggs']) 28 | print(x * 3) 29 | x.append('a') 30 | x.sort() 31 | print(' '.join(c for c in x)) 32 | -------------------------------------------------------------------------------- /code/mymod.py: -------------------------------------------------------------------------------- 1 | # The file's size varies from that show in the book's solution! 2 | 3 | def countLines(name): 4 | file = open(name) 5 | return len(file.readlines()) 6 | 7 | def countChars(name): 8 | return len(open(name).read()) 9 | 10 | def test(name): # Or pass file object 11 | return countLines(name), countChars(name) # Or return a dictionary 12 | 13 | if __name__ == '__main__': 14 | print(test('mymod.py')) 15 | 16 | 17 | """ 18 | ALTERNATIVES (also mymod2.py) 19 | ---- 20 | 21 | def countLines(name): 22 | tot = 0 23 | for line in open(name): tot += 1 24 | return tot 25 | 26 | def countChars(name): 27 | tot = 0 28 | for line in open(name): tot += len(line) 29 | return tot 30 | 31 | ---- 32 | 33 | def countlines(name): return sum(+1 for line in open(name)) 34 | def countchars(name): return sum(len(line) for line in open(name)) 35 | 36 | ---- 37 | """ 38 | 39 | -------------------------------------------------------------------------------- /code/mymod2.py: -------------------------------------------------------------------------------- 1 | def countLines(file): 2 | file.seek(0) # Rewind to start of file 3 | return len(file.readlines()) 4 | 5 | def countChars(file): 6 | file.seek(0) # Ditto (rewind if needed) 7 | return len(file.read()) 8 | 9 | def test(name): 10 | file = open(name) # Pass file object 11 | return countLines(file), countChars(file) # Open file only once 12 | -------------------------------------------------------------------------------- /code/mypkg/__init__.py: -------------------------------------------------------------------------------- 1 | print('initializing mypkg') -------------------------------------------------------------------------------- /code/mypkg/mymod.py: -------------------------------------------------------------------------------- 1 | def countLines(name): 2 | file = open(name) 3 | return len(file.readlines()) 4 | 5 | def countChars(name): 6 | return len(open(name).read()) 7 | 8 | def test(name): # Or pass file object 9 | return countLines(name), countChars(name) # Or return a dictionary 10 | 11 | if __name__ == '__main__': 12 | print(test('mymod.py')) 13 | -------------------------------------------------------------------------------- /code/mysub.py: -------------------------------------------------------------------------------- 1 | from mylist import MyList 2 | 3 | class MyListSub(MyList): 4 | calls = 0 # Shared by instances 5 | def __init__(self, start): 6 | self.adds = 0 # Varies in each instance 7 | MyList.__init__(self, start) 8 | 9 | def __add__(self, other): 10 | print('add: ' + str(other)) 11 | MyListSub.calls += 1 # Class-wide counter 12 | self.adds += 1 # Per-instance counts 13 | return MyList.__add__(self, other) 14 | 15 | def stats(self): 16 | return self.calls, self.adds # All adds, my adds 17 | 18 | if __name__ == '__main__': 19 | x = MyListSub('spam') 20 | y = MyListSub('foo') 21 | print(x[2]) 22 | print(x[1:]) 23 | print(x + ['eggs']) 24 | print(x + ['toast']) 25 | print(y + ['bar']) 26 | print(x.stats()) 27 | -------------------------------------------------------------------------------- /code/nested1.py: -------------------------------------------------------------------------------- 1 | X = 99 2 | def printer(): print(X) 3 | -------------------------------------------------------------------------------- /code/nested2.py: -------------------------------------------------------------------------------- 1 | from nested1 import X, printer # Copy names out 2 | X = 88 # Changes my "X" only! 3 | printer() # nested1's X is still 99 4 | -------------------------------------------------------------------------------- /code/nested3.py: -------------------------------------------------------------------------------- 1 | import nested1 # Get module as a whole 2 | nested1.X = 88 # OK: change nested1's X 3 | nested1.printer() 4 | -------------------------------------------------------------------------------- /code/nestexc.py: -------------------------------------------------------------------------------- 1 | def action2(): 2 | print(1 + []) # Generate TypeError 3 | 4 | def action1(): 5 | try: 6 | action2() 7 | except TypeError: # Most recent matching try 8 | print('inner try') 9 | 10 | try: 11 | action1() 12 | except TypeError: # Here, only if action1 re-raises 13 | print('outer try') 14 | -------------------------------------------------------------------------------- /code/ns/dir1/sub/mod1.py: -------------------------------------------------------------------------------- 1 | from . import mod2 # And "from . import string" still fails 2 | print(r'dir1\sub\mod1') 3 | 4 | -------------------------------------------------------------------------------- /code/ns/dir1/sub/pkg/__init__.py: -------------------------------------------------------------------------------- 1 | print(r'dir1\sub\pkg\__init__.py') -------------------------------------------------------------------------------- /code/ns/dir2/sub/lower/mod3.py: -------------------------------------------------------------------------------- 1 | print(r'dir2\sub\lower\mod3') -------------------------------------------------------------------------------- /code/ns/dir2/sub/mod2.py: -------------------------------------------------------------------------------- 1 | print(r'dir2\sub\mod2') -------------------------------------------------------------------------------- /code/ns3/dir/ns2.py: -------------------------------------------------------------------------------- 1 | print(r'ns3\dir\ns2.py!') -------------------------------------------------------------------------------- /code/number.py: -------------------------------------------------------------------------------- 1 | class Number: 2 | def __init__(self, start): # On Number(start) 3 | self.data = start 4 | def __sub__(self, other): # On instance - other 5 | return Number(self.data - other) # Result is a new instance 6 | -------------------------------------------------------------------------------- /code/oops.py: -------------------------------------------------------------------------------- 1 | def oops(): 2 | raise IndexError() 3 | 4 | def doomed(): 5 | try: 6 | oops() 7 | except IndexError: 8 | print('caught an index error!') 9 | else: 10 | print('no error caught...') 11 | 12 | if __name__ == '__main__': doomed() 13 | -------------------------------------------------------------------------------- /code/oops2.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function # 2.X 2 | 3 | class MyError(Exception): pass 4 | 5 | def oops(): 6 | raise MyError('Spam!') 7 | 8 | def doomed(): 9 | try: 10 | oops() 11 | except IndexError: 12 | print('caught an index error!') 13 | except MyError as data: 14 | print('caught error:', MyError, data) 15 | else: 16 | print('no error caught...') 17 | 18 | if __name__ == '__main__': 19 | doomed() 20 | -------------------------------------------------------------------------------- /code/ora-lp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/code/ora-lp.jpg -------------------------------------------------------------------------------- /code/otherfile.py: -------------------------------------------------------------------------------- 1 | import manynames 2 | 3 | X = 66 4 | print(X) # 66: the global here 5 | print(manynames.X) # 11: globals become attributes after imports 6 | 7 | manynames.f() # 11: manynames's X, not the one here! 8 | manynames.g() # 22: local in other file's function 9 | 10 | print(manynames.C.X) # 33: attribute of class in other module 11 | I = manynames.C() 12 | print(I.X) # 33: still from class here 13 | I.m() 14 | print(I.X) # 55: now from instance! 15 | -------------------------------------------------------------------------------- /code/parrot.py: -------------------------------------------------------------------------------- 1 | class Actor: 2 | def line(self): print(self.name + ':', repr(self.says())) 3 | 4 | class Customer(Actor): 5 | name = 'customer' 6 | def says(self): return "that's one ex-bird!" 7 | 8 | class Clerk(Actor): 9 | name = 'clerk' 10 | def says(self): return "no it isn't..." 11 | 12 | class Parrot(Actor): 13 | name = 'parrot' 14 | def says(self): return None 15 | 16 | class Scene: 17 | def __init__(self): 18 | self.clerk = Clerk() # Embed some instances 19 | self.customer = Customer() # Scene is a composite 20 | self.subject = Parrot() 21 | 22 | def action(self): 23 | self.customer.line() # Delegate to embedded 24 | self.clerk.line() 25 | self.subject.line() 26 | -------------------------------------------------------------------------------- /code/patternparse.py: -------------------------------------------------------------------------------- 1 | import re 2 | text = open('mybooks.xml').read() 3 | found = re.findall('(.*)', text) 4 | for title in found: print(title) 5 | -------------------------------------------------------------------------------- /code/permute.py: -------------------------------------------------------------------------------- 1 | # File permute.py 2 | 3 | def permute1(seq): 4 | if not seq: # Shuffle any sequence: list 5 | return [seq] # Empty sequence 6 | else: 7 | res = [] 8 | for i in range(len(seq)): 9 | rest = seq[:i] + seq[i+1:] # Delete current node 10 | for x in permute1(rest): # Permute the others 11 | res.append(seq[i:i+1] + x) # Add node at front 12 | return res 13 | 14 | def permute2(seq): 15 | if not seq: # Shuffle any sequence: generator 16 | yield seq # Empty sequence 17 | else: 18 | for i in range(len(seq)): 19 | rest = seq[:i] + seq[i+1:] # Delete current node 20 | for x in permute2(rest): # Permute the others 21 | yield seq[i:i+1] + x # Add node at front 22 | -------------------------------------------------------------------------------- /code/person-composite.py: -------------------------------------------------------------------------------- 1 | class Person: 2 | def __init__(self, name, job=None, pay=0): 3 | self.name = name 4 | self.job = job 5 | self.pay = pay 6 | def lastName(self): 7 | return self.name.split()[-1] 8 | def giveRaise(self, percent): 9 | self.pay = int(self.pay * (1 + percent)) 10 | def __repr__(self): 11 | return '[Person: %s, %s]' % (self.name, self.pay) 12 | 13 | class Manager: 14 | def __init__(self, name, pay): 15 | self.person = Person(name, 'mgr', pay) # Embed a Person object 16 | def giveRaise(self, percent, bonus=.10): 17 | self.person.giveRaise(percent + bonus) # Intercept and delegate 18 | def __getattr__(self, attr): 19 | return getattr(self.person, attr) # Delegate all other attrs 20 | def __repr__(self): 21 | return str(self.person) # Must overload again (in 3.X) 22 | 23 | if __name__ == '__main__': 24 | bob = Person('Bob Smith') 25 | sue = Person('Sue Jones', job='dev', pay=100000) 26 | print(bob) 27 | print(sue) 28 | print(bob.lastName(), sue.lastName()) 29 | sue.giveRaise(.10) 30 | print(sue) 31 | tom = Manager('Tom Jones', 50000) # Job name not needed: 32 | tom.giveRaise(.10) # Implied/set by class 33 | print(tom.lastName()) 34 | print(tom) 35 | -------------------------------------------------------------------------------- /code/person-department.py: -------------------------------------------------------------------------------- 1 | class Person: 2 | def __init__(self, name, job=None, pay=0): 3 | self.name = name 4 | self.job = job 5 | self.pay = pay 6 | def lastName(self): 7 | return self.name.split()[-1] 8 | def giveRaise(self, percent): 9 | self.pay = int(self.pay * (1 + percent)) 10 | def __repr__(self): 11 | return '[Person: %s, %s]' % (self.name, self.pay) 12 | 13 | class Manager(Person): 14 | def __init__(self, name, pay): # Redefine constructor 15 | Person.__init__(self, name, 'mgr', pay) # Run original with 'mgr' 16 | def giveRaise(self, percent, bonus=.10): 17 | Person.giveRaise(self, percent + bonus) 18 | 19 | class Department: 20 | def __init__(self, *args): 21 | self.members = list(args) 22 | def addMember(self, person): 23 | self.members.append(person) 24 | def giveRaises(self, percent): 25 | for person in self.members: 26 | person.giveRaise(percent) 27 | def showAll(self): 28 | for person in self.members: 29 | print(person) 30 | 31 | if __name__ == '__main__': 32 | bob = Person('Bob Smith') 33 | sue = Person('Sue Jones', job='dev', pay=100000) 34 | tom = Manager('Tom Jones', 50000) 35 | 36 | development = Department(bob, sue) # Embed objects in a composite 37 | development.addMember(tom) 38 | development.giveRaises(.10) # Runs embedded objects' giveRaise 39 | development.showAll() # Runs embedded objects' __repr__ 40 | -------------------------------------------------------------------------------- /code/person.py: -------------------------------------------------------------------------------- 1 | # File person.py (final) 2 | """ 3 | Record and process information about people. 4 | Run this file directly to test its classes. 5 | """ 6 | from classtools import AttrDisplay # Use generic display tool 7 | 8 | class Person(AttrDisplay): # Mix in a repr at this level 9 | """ 10 | Create and process person records 11 | """ 12 | def __init__(self, name, job=None, pay=0): 13 | self.name = name 14 | self.job = job 15 | self.pay = pay 16 | 17 | def lastName(self): # Assumes last is last 18 | return self.name.split()[-1] 19 | 20 | def giveRaise(self, percent): # Percent must be 0..1 21 | self.pay = int(self.pay * (1 + percent)) 22 | 23 | class Manager(Person): 24 | """ 25 | A customized Person with special requirements 26 | """ 27 | def __init__(self, name, pay): 28 | Person.__init__(self, name, 'mgr', pay) # Job name is implied 29 | 30 | def giveRaise(self, percent, bonus=.10): 31 | Person.giveRaise(self, percent + bonus) 32 | 33 | if __name__ == '__main__': 34 | bob = Person('Bob Smith') 35 | sue = Person('Sue Jones', job='dev', pay=100000) 36 | print(bob) 37 | print(sue) 38 | print(bob.lastName(), sue.lastName()) 39 | sue.giveRaise(.10) 40 | print(sue) 41 | tom = Manager('Tom Jones', 50000) 42 | tom.giveRaise(.10) 43 | print(tom.lastName()) 44 | print(tom) 45 | -------------------------------------------------------------------------------- /code/persondb.bak: -------------------------------------------------------------------------------- 1 | 'Bob Smith', (0, 80) 2 | 'Tom Jones', (1024, 91) 3 | 'Sue Jones', (512, 92) 4 | -------------------------------------------------------------------------------- /code/persondb.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/code/persondb.dat -------------------------------------------------------------------------------- /code/persondb.dir: -------------------------------------------------------------------------------- 1 | 'Bob Smith', (0, 80) 2 | 'Tom Jones', (1024, 91) 3 | 'Sue Jones', (512, 92) 4 | -------------------------------------------------------------------------------- /code/pizzashop.py: -------------------------------------------------------------------------------- 1 | # File pizzashop.py (2.X + 3.X) 2 | from __future__ import print_function 3 | from employees import PizzaRobot, Server 4 | 5 | class Customer: 6 | def __init__(self, name): 7 | self.name = name 8 | def order(self, server): 9 | print(self.name, "orders from", server) 10 | def pay(self, server): 11 | print(self.name, "pays for item to", server) 12 | 13 | class Oven: 14 | def bake(self): 15 | print("oven bakes") 16 | 17 | class PizzaShop: 18 | def __init__(self): 19 | self.server = Server('Pat') # Embed other objects 20 | self.chef = PizzaRobot('Bob') # A robot named bob 21 | self.oven = Oven() 22 | 23 | def order(self, name): 24 | customer = Customer(name) # Activate other objects 25 | customer.order(self.server) # Customer orders from server 26 | self.chef.work() 27 | self.oven.bake() 28 | customer.pay(self.server) 29 | 30 | if __name__ == "__main__": 31 | scene = PizzaShop() # Make the composite 32 | scene.order('Homer') # Simulate Homer's order 33 | print('...') 34 | scene.order('Shaggy') # Simulate Shaggy's order 35 | -------------------------------------------------------------------------------- /code/pkg/eggs.py: -------------------------------------------------------------------------------- 1 | print('Eggs' * 4) -------------------------------------------------------------------------------- /code/pkg/main.py: -------------------------------------------------------------------------------- 1 | import spam -------------------------------------------------------------------------------- /code/pkg/spam.py: -------------------------------------------------------------------------------- 1 | import pkg.eggs 2 | -------------------------------------------------------------------------------- /code/primes.py: -------------------------------------------------------------------------------- 1 | #from __future__ import division 2 | 3 | def prime(y): 4 | if y <= 1: # For some y > 1 5 | print(y, 'not prime') 6 | else: 7 | x = y // 2 # 3.X / fails 8 | while x > 1: 9 | if y % x == 0: # No remainder? 10 | print(y, 'has factor', x) 11 | break # Skip else 12 | x -= 1 13 | else: 14 | print(y, 'is prime') 15 | 16 | prime(13); prime(13.0) 17 | prime(15); prime(15.0) 18 | prime(3); prime(2) 19 | prime(1); prime(-3) 20 | 21 | -------------------------------------------------------------------------------- /code/print3.py: -------------------------------------------------------------------------------- 1 | #!python 2 | """ 3 | Emulate most of the 3.X print function for use in 2.X (and 3.X). 4 | Call signature: print3(*args, sep=' ', end='\n', file=sys.stdout) 5 | """ 6 | import sys 7 | 8 | def print3(*args, **kargs): 9 | sep = kargs.get('sep', ' ') # Keyword arg defaults 10 | end = kargs.get('end', '\n') 11 | file = kargs.get('file', sys.stdout) 12 | output = '' 13 | first = True 14 | for arg in args: 15 | output += ('' if first else sep) + str(arg) 16 | first = False 17 | file.write(output + end) 18 | -------------------------------------------------------------------------------- /code/print3_alt1.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | "Use 3.X only keyword-only args" 3 | import sys 4 | 5 | def print3(*args, sep=' ', end='\n', file=sys.stdout): 6 | output = '' 7 | first = True 8 | for arg in args: 9 | output += ('' if first else sep) + str(arg) 10 | first = False 11 | file.write(output + end) 12 | -------------------------------------------------------------------------------- /code/print3_alt2.py: -------------------------------------------------------------------------------- 1 | #!python 2 | "Use 2.X/3.X keyword args deletion with defaults" 3 | import sys 4 | 5 | def print3(*args, **kargs): 6 | sep = kargs.pop('sep', ' ') 7 | end = kargs.pop('end', '\n') 8 | file = kargs.pop('file', sys.stdout) 9 | if kargs: raise TypeError('extra keywords: %s' % kargs) 10 | output = '' 11 | first = True 12 | for arg in args: 13 | output += ('' if first else sep) + str(arg) 14 | first = False 15 | file.write(output + end) 16 | -------------------------------------------------------------------------------- /code/printnest.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | print(1, 2, 3) -------------------------------------------------------------------------------- /code/private0.py: -------------------------------------------------------------------------------- 1 | class PrivateExc(Exception): pass # More on exceptions in Part VII 2 | 3 | class Privacy: 4 | def __setattr__(self, attrname, value): # On self.attrname = value 5 | if attrname in self.privates: 6 | raise PrivateExc(attrname, self) # Make, raise user-define except 7 | else: 8 | self.__dict__[attrname] = value # Avoid loops by using dict key 9 | 10 | class Test1(Privacy): 11 | privates = ['age'] 12 | 13 | class Test2(Privacy): 14 | privates = ['name', 'pay'] 15 | def __init__(self): 16 | self.__dict__['name'] = 'Tom' # To do better, see Chapter 39! 17 | 18 | if __name__ == '__main__': 19 | x = Test1() 20 | y = Test2() 21 | 22 | x.name = 'Bob' # Works 23 | #y.name = 'Sue' # Fails 24 | print(x.name) 25 | 26 | y.age = 30 # Works 27 | #x.age = 40 # Fails 28 | print(y.age) 29 | 30 | -------------------------------------------------------------------------------- /code/prop-computed.py: -------------------------------------------------------------------------------- 1 | class PropSquare: 2 | def __init__(self, start): 3 | self.value = start 4 | def getX(self): # On attr fetch 5 | return self.value ** 2 6 | def setX(self, value): # On attr assign 7 | self.value = value 8 | X = property(getX, setX) # No delete or docs 9 | 10 | P = PropSquare(3) # 2 instances of class with property 11 | Q = PropSquare(32) # Each has different state information 12 | 13 | print(P.X) # 3 ** 2 14 | P.X = 4 15 | print(P.X) # 4 ** 2 16 | print(Q.X) # 32 ** 2 (1024) 17 | -------------------------------------------------------------------------------- /code/prop-desc-equiv.py: -------------------------------------------------------------------------------- 1 | class Property: 2 | def __init__(self, fget=None, fset=None, fdel=None, doc=None): 3 | self.fget = fget 4 | self.fset = fset 5 | self.fdel = fdel # Save unbound methods 6 | self.__doc__ = doc # or other callables 7 | 8 | def __get__(self, instance, instancetype=None): 9 | if instance is None: 10 | return self 11 | if self.fget is None: 12 | raise AttributeError("can't get attribute") 13 | return self.fget(instance) # Pass instance to self 14 | # in property accessors 15 | def __set__(self, instance, value): 16 | if self.fset is None: 17 | raise AttributeError("can't set attribute") 18 | self.fset(instance, value) 19 | 20 | def __delete__(self, instance): 21 | if self.fdel is None: 22 | raise AttributeError("can't delete attribute") 23 | self.fdel(instance) 24 | 25 | class Person: 26 | def getName(self): print('getName...') 27 | def setName(self, value): print('setName...') 28 | name = Property(getName, setName) # Use like property() 29 | 30 | x = Person() 31 | x.name 32 | x.name = 'Bob' 33 | del x.name 34 | -------------------------------------------------------------------------------- /code/prop-person-deco.py: -------------------------------------------------------------------------------- 1 | class Person: 2 | def __init__(self, name): 3 | self._name = name 4 | 5 | @property 6 | def name(self): # name = property(name) 7 | "name property docs" 8 | print('fetch...') 9 | return self._name 10 | 11 | @name.setter 12 | def name(self, value): # name = name.setter(name) 13 | print('change...') 14 | self._name = value 15 | 16 | @name.deleter 17 | def name(self): # name = name.deleter(name) 18 | print('remove...') 19 | del self._name 20 | 21 | bob = Person('Bob Smith') # bob has a managed attribute 22 | print(bob.name) # Runs name getter (name 1) 23 | bob.name = 'Robert Smith' # Runs name setter (name 2) 24 | print(bob.name) 25 | del bob.name # Runs name deleter (name 3) 26 | 27 | print('-'*20) 28 | sue = Person('Sue Jones') # sue inherits property too 29 | print(sue.name) 30 | print(Person.name.__doc__) # Or help(Person.name) 31 | -------------------------------------------------------------------------------- /code/prop-person.py: -------------------------------------------------------------------------------- 1 | class Person: # Add (object) in 2.X 2 | def __init__(self, name): 3 | self._name = name 4 | def getName(self): 5 | print('fetch...') 6 | return self._name 7 | def setName(self, value): 8 | print('change...') 9 | self._name = value 10 | def delName(self): 11 | print('remove...') 12 | del self._name 13 | name = property(getName, setName, delName, "name property docs") 14 | 15 | bob = Person('Bob Smith') # bob has a managed attribute 16 | print(bob.name) # Runs getName 17 | bob.name = 'Robert Smith' # Runs setName 18 | print(bob.name) 19 | del bob.name # Runs delName 20 | 21 | print('-'*20) 22 | sue = Person('Sue Jones') # sue inherits property too 23 | print(sue.name) 24 | print(Person.name.__doc__) # Or help(Person.name) 25 | -------------------------------------------------------------------------------- /code/prop-powers.py: -------------------------------------------------------------------------------- 1 | # 2 dynamically computed attributes with properties 2 | 3 | class Powers(object): # Need (object) in 2.X only 4 | def __init__(self, square, cube): 5 | self._square = square # _square is the base value 6 | self._cube = cube # square is the property name 7 | 8 | def getSquare(self): 9 | return self._square ** 2 10 | def setSquare(self, value): 11 | self._square = value 12 | square = property(getSquare, setSquare) 13 | 14 | def getCube(self): 15 | return self._cube ** 3 16 | cube = property(getCube) 17 | 18 | X = Powers(3, 4) 19 | print(X.square) # 3 ** 2 = 9 20 | print(X.cube) # 4 ** 3 = 64 21 | X.square = 5 22 | print(X.square) # 5 ** 2 = 25 23 | -------------------------------------------------------------------------------- /code/pseudoprivate.py: -------------------------------------------------------------------------------- 1 | class C1: 2 | def meth1(self): self.__X = 88 # Now X is mine 3 | def meth2(self): print(self.__X) # Becomes _C1__X in I 4 | class C2: 5 | def metha(self): self.__X = 99 # Me too 6 | def methb(self): print(self.__X) # Becomes _C2__X in I 7 | 8 | class C3(C1, C2): pass 9 | I = C3() # Two X names in I 10 | 11 | I.meth1(); I.metha() 12 | print(I.__dict__) 13 | I.meth2(); I.methb() 14 | -------------------------------------------------------------------------------- /code/py2x/script0.py: -------------------------------------------------------------------------------- 1 | print('hello world') 2 | print(2 ** 100) 3 | -------------------------------------------------------------------------------- /code/py3x/script0.py: -------------------------------------------------------------------------------- 1 | print('hello world') 2 | print(2 ** 100) 3 | -------------------------------------------------------------------------------- /code/pybench2_cases-results.txt: -------------------------------------------------------------------------------- 1 | 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17) [MSC v.1600 64 bit (AMD64)] 2 | 0.5017 ['[x ** 2 for x in range(1000)]'] 3 | 0.5636 ['res=[]\nfor x in range(1000): res.append(x ** 2)'] 4 | 0.6005 ['list(map(lambda x: x ** 2, range(1000)))'] 5 | 0.5392 ['list(x ** 2 for x in range(1000))'] 6 | 1.5258 ["[f(x) for x in 'spam' * 2500]"] 7 | 2.0554 ["res=[]\nfor x in 'spam' * 2500:\n\tres.append(f(x))"] 8 | 0.0012 ['for i in range(len(L)): L[i] += 1'] 9 | 0.0014 ['i=0\nwhile i < len(L):\n\tL[i] += 1\n\ti += 1'] 10 | 11 | 12 | 13 | 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] 14 | 0.0701 ['[x ** 2 for x in range(1000)]'] 15 | 0.1279 ['res=[]\nfor x in range(1000): res.append(x ** 2)'] 16 | 0.1662 ['(map(lambda x: x ** 2, range(1000)))'] 17 | 0.0968 ['list(x ** 2 for x in range(1000))'] 18 | 1.2358 ["[f(x) for x in 'spam' * 2500]"] 19 | 1.8213 ["res=[]\nfor x in 'spam' * 2500:\n\tres.append(f(x))"] 20 | 0.0008 ['for i in range(len(L)): L[i] += 1'] 21 | 0.0010 ['i=0\nwhile i < len(L):\n\tL[i] += 1\n\ti += 1'] 22 | 23 | 24 | 25 | 2.7.2 (341e1e3821ff, Jun 07 2012, 15:43:00) 26 | [PyPy 1.9.0 with MSC v.1500 32 bit] 27 | 0.0059 ['[x ** 2 for x in range(1000)]'] 28 | 0.0102 ['res=[]\nfor x in range(1000): res.append(x ** 2)'] 29 | 0.0098 ['(map(lambda x: x ** 2, range(1000)))'] 30 | 0.0159 ['list(x ** 2 for x in range(1000))'] 31 | 0.1029 ["[f(x) for x in 'spam' * 2500]"] 32 | 0.2047 ["res=[]\nfor x in 'spam' * 2500:\n\tres.append(f(x))"] 33 | 0.0001 ['for i in range(len(L)): L[i] += 1'] 34 | 0.0000 ['i=0\nwhile i < len(L):\n\tL[i] += 1\n\ti += 1'] 35 | -------------------------------------------------------------------------------- /code/pybench2_cases.py: -------------------------------------------------------------------------------- 1 | """ 2 | pybench2_cases.py: Run pybench2 on a set of pythons and statements. 3 | 4 | Select modes by editing this script or using command-line arguments (in 5 | sys.argv): e.g., run a "C:\python27\python pybench_cases.py" to test just 6 | one specific version on stmts, "pybench_cases.py -a" to test all pythons 7 | listed, or a "py -3 pybench_cases.py -a -t" to trace command lines too. 8 | """ 9 | 10 | import pybench2, sys 11 | 12 | pythons = [ # (ispy3?, path) 13 | (1, 'C:\python33\python'), 14 | (0, 'C:\python27\python'), 15 | (0, 'C:\pypy\pypy-1.9\pypy') 16 | ] 17 | 18 | stmts = [ # (num,rpt,setup,stmt) 19 | (0, 0, "", "[x ** 2 for x in range(1000)]"), 20 | (0, 0, "", "res=[]\nfor x in range(1000): res.append(x ** 2)"), # \n=multistmt 21 | (0, 0, "", "$listif3(map(lambda x: x ** 2, range(1000)))"), # \n\t=indent 22 | (0, 0, "", "list(x ** 2 for x in range(1000))"), # $=list or '' 23 | 24 | # (0, 0, "", "s = 'spam' * 2500\nx = [s[i] for i in range(10000)]"), 25 | # (0, 0, "", "s = '?'\nfor i in range(10000): s += '?'"), 26 | 27 | (0, 0, "def f(x):\n\treturn x", 28 | "[f(x) for x in 'spam' * 2500]"), 29 | (0, 0, "def f(x):\n\treturn x", 30 | "res=[]\nfor x in 'spam' * 2500:\n\tres.append(f(x))"), 31 | 32 | (0, 0, "L = [1, 2, 3, 4, 5]", "for i in range(len(L)): L[i] += 1"), 33 | (0, 0, "L = [1, 2, 3, 4, 5]", "i=0\nwhile i < len(L):\n\tL[i] += 1\n\ti += 1"), 34 | ] 35 | 36 | tracecmd = '-t' in sys.argv # -t: trace commmand lines? 37 | pythons = pythons if '-a' in sys.argv else None # -a: all in list, else one? 38 | pybench2.runner(stmts, pythons, tracecmd) 39 | -------------------------------------------------------------------------------- /code/pybench_cases.py: -------------------------------------------------------------------------------- 1 | """ 2 | pybench_cases.py: Run pybench on a set of pythons and statements. 3 | 4 | Select modes by editing this script or using command-line arguments (in 5 | sys.argv): e.g., run a "C:\python27\python pybench_cases.py" to test just 6 | one specific version on stmts, "pybench_cases.py -a" to test all pythons 7 | listed, or a "py -3 pybench_cases.py -a -t" to trace command lines too. 8 | """ 9 | 10 | import pybench, sys 11 | 12 | pythons = [ # (ispy3?, path) 13 | (1, 'C:\python33\python'), 14 | (0, 'C:\python27\python'), 15 | (0, 'C:\pypy\pypy-1.9\pypy') 16 | ] 17 | 18 | stmts = [ # (num,rpt,stmt) 19 | (0, 0, "[x ** 2 for x in range(1000)]"), # Iterations 20 | (0, 0, "res=[]\nfor x in range(1000): res.append(x ** 2)"), # \n=multistmt 21 | (0, 0, "$listif3(map(lambda x: x ** 2, range(1000)))"), # \n\t=indent 22 | (0, 0, "list(x ** 2 for x in range(1000))"), # $=list or '' 23 | (0, 0, "s = 'spam' * 2500\nx = [s[i] for i in range(10000)]"), # String ops 24 | (0, 0, "s = '?'\nfor i in range(10000): s += '?'"), 25 | ] 26 | 27 | tracecmd = '-t' in sys.argv # -t: trace commmand lines? 28 | pythons = pythons if '-a' in sys.argv else None # -a: all in list, else one? 29 | pybench.runner(stmts, pythons, tracecmd) 30 | -------------------------------------------------------------------------------- /code/pybench_cases0-results.txt: -------------------------------------------------------------------------------- 1 | c:\code>py -3 pybench_cases0.py 2 | 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17) [MSC v.1600 64 bit (AMD64)] 3 | 0.7237 ["[ord(x) for x in 'spam' * 2500]"] 4 | 1.3471 ["res=[]\nfor x in 'spam' * 2500: res.append(ord(x))"] 5 | 0.6160 ["list(map(ord, 'spam' * 2500))"] 6 | 1.1244 ["list(ord(x) for x in 'spam' * 2500)"] 7 | 0.5446 ['{x ** 2 for x in range(1000)}'] 8 | 0.6053 ['s=set()\nfor x in range(1000): s.add(x ** 2)'] 9 | 0.5278 ['{x: x ** 2 for x in range(1000)}'] 10 | 0.5414 ['d={}\nfor x in range(1000): d[x] = x ** 2'] 11 | 1.8933 ['len(str(2**1000000))'] 12 | 13 | c:\code>py -2 pybench_cases0.py 14 | 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] 15 | 0.6623 ["[ord(x) for x in 'spam' * 2500]"] 16 | 1.2251 ["res=[]\nfor x in 'spam' * 2500: res.append(ord(x))"] 17 | 0.6082 ["(map(ord, 'spam' * 2500))"] 18 | 0.9026 ["list(ord(x) for x in 'spam' * 2500)"] 19 | 0.0966 ['{x ** 2 for x in range(1000)}'] 20 | 0.1600 ['s=set()\nfor x in range(1000): s.add(x ** 2)'] 21 | 0.0924 ['{x: x ** 2 for x in range(1000)}'] 22 | 0.1037 ['d={}\nfor x in range(1000): d[x] = x ** 2'] 23 | 1.8538 ['len(str(2**1000000))'] 24 | 25 | c:\code>C:\pypy\pypy-1.9\pypy pybench_cases0.py 26 | 2.7.2 (341e1e3821ff, Jun 07 2012, 15:43:00) 27 | [PyPy 1.9.0 with MSC v.1500 32 bit] 28 | 0.0849 ["[ord(x) for x in 'spam' * 2500]"] 29 | 0.1299 ["res=[]\nfor x in 'spam' * 2500: res.append(ord(x))"] 30 | 0.1291 ["(map(ord, 'spam' * 2500))"] 31 | 0.1877 ["list(ord(x) for x in 'spam' * 2500)"] 32 | 0.0268 ['{x ** 2 for x in range(1000)}'] 33 | 0.0257 ['s=set()\nfor x in range(1000): s.add(x ** 2)'] 34 | 0.0251 ['{x: x ** 2 for x in range(1000)}'] 35 | 0.0238 ['d={}\nfor x in range(1000): d[x] = x ** 2'] 36 | 15.5875 ['len(str(2**1000000))'] 37 | -------------------------------------------------------------------------------- /code/python_snake_ora.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/code/python_snake_ora.gif -------------------------------------------------------------------------------- /code/rangetest1.py: -------------------------------------------------------------------------------- 1 | def rangetest(*argchecks): # Validate positional arg ranges 2 | def onDecorator(func): 3 | if not __debug__: # True if "python -O main.py args..." 4 | return func # No-op: call original directly 5 | else: # Else wrapper while debugging 6 | def onCall(*args): 7 | for (ix, low, high) in argchecks: 8 | if args[ix] < low or args[ix] > high: 9 | errmsg = 'Argument %s not in %s..%s' % (ix, low, high) 10 | raise TypeError(errmsg) 11 | return func(*args) 12 | return onCall 13 | return onDecorator 14 | -------------------------------------------------------------------------------- /code/rangetest1_test.py: -------------------------------------------------------------------------------- 1 | # File rangetest1_test.py 2 | from __future__ import print_function # 2.X 3 | from rangetest1 import rangetest 4 | print(__debug__) # False if "python -O main.py" 5 | 6 | @rangetest((1, 0, 120)) # persinfo = rangetest(...)(persinfo) 7 | def persinfo(name, age): # age must be in 0..120 8 | print('%s is %s years old' % (name, age)) 9 | 10 | @rangetest([0, 1, 12], [1, 1, 31], [2, 0, 2009]) 11 | def birthday(M, D, Y): 12 | print('birthday = {0}/{1}/{2}'.format(M, D, Y)) 13 | 14 | class Person: 15 | def __init__(self, name, job, pay): 16 | self.job = job 17 | self.pay = pay 18 | 19 | @rangetest([1, 0.0, 1.0]) # giveRaise = rangetest(...)(giveRaise) 20 | def giveRaise(self, percent): # Arg 0 is the self instance here 21 | self.pay = int(self.pay * (1 + percent)) 22 | 23 | # Comment lines raise TypeError unless "python -O" used on shell command line 24 | 25 | persinfo('Bob Smith', 45) # Really runs onCall(...) with state 26 | #persinfo('Bob Smith', 200) # Or person if -O cmd line argument 27 | 28 | birthday(5, 31, 1963) 29 | #birthday(5, 32, 1963) 30 | 31 | sue = Person('Sue Jones', 'dev', 100000) 32 | sue.giveRaise(.10) # Really runs onCall(self, .10) 33 | print(sue.pay) # Or giveRaise(self, .10) if -O 34 | #sue.giveRaise(1.10) 35 | #print(sue.pay) 36 | -------------------------------------------------------------------------------- /code/rangetest_test.py: -------------------------------------------------------------------------------- 1 | """ 2 | File rangetest_test.py (3.X + 2.X) 3 | Comment lines raise TypeError unless "python -O" used on shell command line 4 | """ 5 | from __future__ import print_function # 2.X 6 | from rangetest import rangetest 7 | 8 | # Test functions, positional and keyword 9 | 10 | @rangetest(age=(0, 120)) # persinfo = rangetest(...)(persinfo) 11 | def persinfo(name, age): 12 | print('%s is %s years old' % (name, age)) 13 | 14 | @rangetest(M=(1, 12), D=(1, 31), Y=(0, 2013)) 15 | def birthday(M, D, Y): 16 | print('birthday = {0}/{1}/{2}'.format(M, D, Y)) 17 | 18 | persinfo('Bob', 40) 19 | persinfo(age=40, name='Bob') 20 | birthday(5, D=1, Y=1963) 21 | #persinfo('Bob', 150) 22 | #persinfo(age=150, name='Bob') 23 | #birthday(5, D=40, Y=1963) 24 | 25 | # Test methods, positional and keyword 26 | 27 | class Person: 28 | def __init__(self, name, job, pay): 29 | self.job = job 30 | self.pay = pay 31 | # giveRaise = rangetest(...)(giveRaise) 32 | @rangetest(percent=(0.0, 1.0)) # percent passed by name or position 33 | def giveRaise(self, percent): 34 | self.pay = int(self.pay * (1 + percent)) 35 | 36 | bob = Person('Bob Smith', 'dev', 100000) 37 | sue = Person('Sue Jones', 'dev', 100000) 38 | bob.giveRaise(.10) 39 | sue.giveRaise(percent=.20) 40 | print(bob.pay, sue.pay) 41 | #bob.giveRaise(1.10) 42 | #bob.giveRaise(percent=1.20) 43 | 44 | # Test omitted defaults: skipped 45 | 46 | @rangetest(a=(1, 10), b=(1, 10), c=(1, 10), d=(1, 10)) 47 | def omitargs(a, b=7, c=8, d=9): 48 | print(a, b, c, d) 49 | 50 | omitargs(1, 2, 3, 4) 51 | omitargs(1, 2, 3) 52 | omitargs(1, 2, 3, d=4) 53 | omitargs(1, d=4) 54 | omitargs(d=4, a=1) 55 | omitargs(1, b=2, d=4) 56 | omitargs(d=8, c=7, a=1) 57 | 58 | #omitargs(1, 2, 3, 11) # Bad d 59 | #omitargs(1, 2, 11) # Bad c 60 | #omitargs(1, 2, 3, d=11) # Bad d 61 | #omitargs(11, d=4) # Bad a 62 | #omitargs(d=4, a=11) # Bad a 63 | #omitargs(1, b=11, d=4) # Bad b 64 | #omitargs(d=8, c=7, a=11) # Bad a 65 | -------------------------------------------------------------------------------- /code/reader.py: -------------------------------------------------------------------------------- 1 | # File: reader.py 2 | file = open('myfile.txt') # 'r' is default open mode 3 | print(file.read()) # Or print(open().read()) 4 | -------------------------------------------------------------------------------- /code/recur1.py: -------------------------------------------------------------------------------- 1 | X = 1 2 | import recur2 # Run recur2 now if it doesn't exist 3 | Y = 2 4 | -------------------------------------------------------------------------------- /code/recur2.py: -------------------------------------------------------------------------------- 1 | from recur1 import X # OK: "X" already assigned 2 | from recur1 import Y # Error: "Y" not yet assigned 3 | -------------------------------------------------------------------------------- /code/registry-deco.py: -------------------------------------------------------------------------------- 1 | # Registering decorated objects to an API 2 | from __future__ import print_function # 2.X 3 | 4 | registry = {} 5 | def register(obj): # Both class and func decorator 6 | registry[obj.__name__] = obj # Add to registry 7 | return obj # Return obj itself, not a wrapper 8 | 9 | @register 10 | def spam(x): 11 | return(x ** 2) # spam = register(spam) 12 | 13 | @register 14 | def ham(x): 15 | return(x ** 3) 16 | 17 | @register 18 | class Eggs: # Eggs = register(Eggs) 19 | def __init__(self, x): 20 | self.data = x ** 4 21 | def __str__(self): 22 | return str(self.data) 23 | 24 | print('Registry:') 25 | for name in registry: 26 | print(name, '=>', registry[name], type(registry[name])) 27 | 28 | print('\nManual calls:') 29 | print(spam(2)) # Invoke objects manually 30 | print(ham(2)) # Later calls not intercepted 31 | X = Eggs(2) 32 | print(X) 33 | 34 | print('\nRegistry calls:') 35 | for name in registry: 36 | print(name, '=>', registry[name](2)) # Invoke from registry 37 | -------------------------------------------------------------------------------- /code/reloadall.py: -------------------------------------------------------------------------------- 1 | #!python 2 | """ 3 | reloadall.py: transitively reload nested modules (2.X + 3.X). 4 | Call reload_all with one or more imported module module objects. 5 | """ 6 | 7 | import types 8 | from imp import reload # from required in 3.X 9 | 10 | def status(module): 11 | print('reloading ' + module.__name__) 12 | 13 | def tryreload(module): 14 | try: 15 | reload(module) # 3.3 (only?) fails on some 16 | except: 17 | print('FAILED: %s' % module) 18 | 19 | def transitive_reload(module, visited): 20 | if not module in visited: # Trap cycles, duplicates 21 | status(module) # Reload this module 22 | tryreload(module) # And visit children 23 | visited[module] = True 24 | for attrobj in module.__dict__.values(): # For all attrs 25 | if type(attrobj) == types.ModuleType: # Recur if module 26 | transitive_reload(attrobj, visited) 27 | 28 | def reload_all(*args): 29 | visited = {} # Main entry point 30 | for arg in args: # For all passed in 31 | if type(arg) == types.ModuleType: 32 | transitive_reload(arg, visited) 33 | 34 | def tester(reloader, modname): # Self-test code 35 | import importlib, sys # Import on tests only 36 | if len(sys.argv) > 1: modname = sys.argv[1] # command line (or passed) 37 | module = importlib.import_module(modname) # Import by name string 38 | reloader(module) # Test passed-in reloader 39 | 40 | if __name__ == '__main__': 41 | tester(reload_all, 'reloadall') # Test: reload myself? 42 | -------------------------------------------------------------------------------- /code/reloadall2.py: -------------------------------------------------------------------------------- 1 | """ 2 | reloadall2.py: transitively reload nested modules (alternative coding) 3 | """ 4 | 5 | import types 6 | from imp import reload # from required in 3.X 7 | from reloadall import status, tryreload, tester 8 | 9 | def transitive_reload(objects, visited): 10 | for obj in objects: 11 | if type(obj) == types.ModuleType and obj not in visited: 12 | status(obj) 13 | tryreload(obj) # Reload this, recur to attrs 14 | visited.add(obj) 15 | transitive_reload(obj.__dict__.values(), visited) 16 | 17 | def reload_all(*args): 18 | transitive_reload(args, set()) 19 | 20 | if __name__ == '__main__': 21 | tester(reload_all, 'reloadall2') # Test code: reload myself? 22 | -------------------------------------------------------------------------------- /code/reloadall3.py: -------------------------------------------------------------------------------- 1 | """ 2 | reloadall3.py: transitively reload nested modules (explicit stack) 3 | """ 4 | 5 | import types 6 | from imp import reload # from required in 3.X 7 | from reloadall import status, tryreload, tester 8 | 9 | def transitive_reload(modules, visited): 10 | while modules: 11 | next = modules.pop() # Delete next item at end 12 | status(next) # Reload this, push attrs 13 | tryreload(next) 14 | visited.add(next) 15 | modules.extend(x for x in next.__dict__.values() 16 | if type(x) == types.ModuleType and x not in visited) 17 | 18 | def reload_all(*modules): 19 | transitive_reload(list(modules), set()) 20 | 21 | if __name__ == '__main__': 22 | tester(reload_all, 'reloadall3') # Test code: reload myself? 23 | -------------------------------------------------------------------------------- /code/reversals.py: -------------------------------------------------------------------------------- 1 | def rev1(S): 2 | if len(S) == 1: 3 | return S 4 | else: 5 | return S[-1] + rev1(S[:-1]) # Recursive: 10x slower in CPython today 6 | 7 | def rev2(S): 8 | return ''.join(reversed(S)) # Nonrecursive iterable: simpler, faster 9 | 10 | def rev3(S): 11 | return S[::-1] # Even better?: sequence reversal by slice 12 | 13 | 14 | """ 15 | >>> from reversals import * 16 | >>> from timeit import repeat 17 | >>> for func in (rev1, rev2, rev3): # Beware 1k recursion depth limit! 18 | ... print('%.10f' % 19 | ... min(repeat(stmt=lambda: func('spam' * 200), number=20, repeat=3))) 20 | ... 21 | 0.0112213924 22 | 0.0004075886 23 | 0.0000361649 24 | """ -------------------------------------------------------------------------------- /code/robin2.py: -------------------------------------------------------------------------------- 1 | #!python2 2 | print 'Run', 'away more!...' # 2.x statement -------------------------------------------------------------------------------- /code/robin3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | print('Run', 'away!...') # 3.X function -------------------------------------------------------------------------------- /code/runme.py: -------------------------------------------------------------------------------- 1 | def tester(): 2 | print("It's Christmas in Heaven...") 3 | 4 | if __name__ == '__main__': # Only when run 5 | tester() # Not when imported 6 | -------------------------------------------------------------------------------- /code/saveit.txt: -------------------------------------------------------------------------------- 1 | win32 2 | 1267650600228229401496703205376 3 | Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam! 4 | -------------------------------------------------------------------------------- /code/saxparse.py: -------------------------------------------------------------------------------- 1 | import xml.sax.handler 2 | class BookHandler(xml.sax.handler.ContentHandler): 3 | def __init__(self): 4 | self.inTitle = False 5 | def startElement(self, name, attributes): 6 | if name == 'title': 7 | self.inTitle = True 8 | def characters(self, data): 9 | if self.inTitle: 10 | print(data) 11 | def endElement(self, name): 12 | if name == 'title': 13 | self.inTitle = False 14 | 15 | import xml.sax 16 | parser = xml.sax.make_parser() 17 | handler = BookHandler() 18 | parser.setContentHandler(handler) 19 | parser.parse('mybooks.xml') 20 | -------------------------------------------------------------------------------- /code/scramble.py: -------------------------------------------------------------------------------- 1 | # file scramble.py 2 | 3 | def scramble(seq): 4 | for i in range(len(seq)): # Generator function 5 | yield seq[i:] + seq[:i] # Yield one item per iteration 6 | 7 | scramble2 = lambda seq: (seq[i:] + seq[:i] for i in range(len(seq))) 8 | -------------------------------------------------------------------------------- /code/script.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | print('I am script.py') # code a program here -------------------------------------------------------------------------------- /code/script0.py: -------------------------------------------------------------------------------- 1 | print('hello world') 2 | print(2 ** 100) 3 | -------------------------------------------------------------------------------- /code/script1.py: -------------------------------------------------------------------------------- 1 | # A first Python script 2 | import sys # Load a library module 3 | print(sys.platform) 4 | print(2 ** 32) # Raise 2 to a power 5 | x = 'Spam!' 6 | print(x * 8) # String repetition 7 | -------------------------------------------------------------------------------- /code/script2.py: -------------------------------------------------------------------------------- 1 | import sys 2 | print(sys.path) 3 | x = 2 4 | print(x ** 32) 5 | -------------------------------------------------------------------------------- /code/setcolor.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | """ 3 | GUI script borrowed from Programming Python to map 4 | colors to and from RGB hex string values displayed 5 | on stadndard output. See also int(X, 16) builtin 6 | to convert to hex from decimal. 7 | """ 8 | from tkinter import * 9 | from tkinter.colorchooser import askcolor 10 | 11 | def setBgColor(): 12 | (triple, hexstr) = askcolor() 13 | if hexstr: 14 | print(hexstr) 15 | push.config(bg=hexstr) 16 | 17 | root = Tk() 18 | push = Button(root, text='Set Background Color', command=setBgColor) 19 | push.config(height=3, font=('times', 20, 'bold')) 20 | push.pack(expand=YES, fill=BOTH) 21 | root.mainloop() 22 | -------------------------------------------------------------------------------- /code/setsubclass.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function # 2.X compatibility 2 | 3 | class Set(list): 4 | def __init__(self, value = []): # Constructor 5 | list.__init__([]) # Customizes list 6 | self.concat(value) # Copies mutable defaults 7 | 8 | def intersect(self, other): # other is any sequence 9 | res = [] # self is the subject 10 | for x in self: 11 | if x in other: # Pick common items 12 | res.append(x) 13 | return Set(res) # Return a new Set 14 | 15 | def union(self, other): # other is any sequence 16 | res = Set(self) # Copy me and my list 17 | res.concat(other) 18 | return res 19 | 20 | def concat(self, value): # value: list, Set, etc. 21 | for x in value: # Removes duplicates 22 | if not x in self: 23 | self.append(x) 24 | 25 | def __and__(self, other): return self.intersect(other) 26 | def __or__(self, other): return self.union(other) 27 | def __repr__(self): return 'Set:' + list.__repr__(self) 28 | 29 | if __name__ == '__main__': 30 | x = Set([1,3,5,7]) 31 | y = Set([2,1,4,5,6]) 32 | print(x, y, len(x)) 33 | print(x.intersect(y), y.union(x)) 34 | print(x & y, x | y) 35 | x.reverse(); print(x) 36 | -------------------------------------------------------------------------------- /code/setwrapper.py: -------------------------------------------------------------------------------- 1 | class Set: 2 | def __init__(self, value = []): # Constructor 3 | self.data = [] # Manages a list 4 | self.concat(value) 5 | 6 | def intersect(self, other): # other is any sequence 7 | res = [] # self is the subject 8 | for x in self.data: 9 | if x in other: # Pick common items 10 | res.append(x) 11 | return Set(res) # Return a new Set 12 | 13 | def union(self, other): # other is any sequence 14 | res = self.data[:] # Copy of my list 15 | for x in other: # Add items in other 16 | if not x in res: 17 | res.append(x) 18 | return Set(res) 19 | 20 | def concat(self, value): # value: list, Set... 21 | for x in value: # Removes duplicates 22 | if not x in self.data: 23 | self.data.append(x) 24 | 25 | def __len__(self): return len(self.data) # len(self), if self 26 | def __getitem__(self, key): return self.data[key] # self[i], self[i:j] 27 | def __and__(self, other): return self.intersect(other) # self & other 28 | def __or__(self, other): return self.union(other) # self | other 29 | def __repr__(self): return 'Set:' + repr(self.data) # print(self),... 30 | def __iter__(self): return iter(self.data) # for x in self,... 31 | -------------------------------------------------------------------------------- /code/shopfile.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/code/shopfile.pkl -------------------------------------------------------------------------------- /code/showargs.py: -------------------------------------------------------------------------------- 1 | # File showargs.py 2 | import sys 3 | print(sys.argv) 4 | -------------------------------------------------------------------------------- /code/simple.py: -------------------------------------------------------------------------------- 1 | print('hello') 2 | spam = 1 # Initialize variable 3 | -------------------------------------------------------------------------------- /code/skipper.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | # File skipper.py 3 | 4 | class SkipObject: 5 | def __init__(self, wrapped): # Save item to be used 6 | self.wrapped = wrapped 7 | def __iter__(self): 8 | return SkipIterator(self.wrapped) # New iterator each time 9 | 10 | class SkipIterator: 11 | def __init__(self, wrapped): 12 | self.wrapped = wrapped # Iterator state information 13 | self.offset = 0 14 | def __next__(self): 15 | if self.offset >= len(self.wrapped): # Terminate iterations 16 | raise StopIteration 17 | else: 18 | item = self.wrapped[self.offset] # else return and skip 19 | self.offset += 2 20 | return item 21 | 22 | if __name__ == '__main__': 23 | alpha = 'abcdef' 24 | skipper = SkipObject(alpha) # Make container object 25 | I = iter(skipper) # Make an iterator on it 26 | print(next(I), next(I), next(I)) # Visit offsets 0, 2, 4 27 | 28 | for x in skipper: # for calls __iter__ automatically 29 | for y in skipper: # Nested fors call __iter__ again each time 30 | print(x + y, end=' ') # Each iterator has its own state, offset 31 | -------------------------------------------------------------------------------- /code/skipper_2x.py: -------------------------------------------------------------------------------- 1 | #!python 2 | from __future__ import print_function # 2.X/3.X compatibility 3 | 4 | class SkipObject: 5 | def __init__(self, wrapped): # Save item to be used 6 | self.wrapped = wrapped 7 | def __iter__(self): 8 | return SkipIterator(self.wrapped) # New iterator each time 9 | 10 | class SkipIterator: 11 | def __init__(self, wrapped): 12 | self.wrapped = wrapped # Iterator state information 13 | self.offset = 0 14 | def __next__(self): 15 | if self.offset >= len(self.wrapped): # Terminate iterations 16 | raise StopIteration 17 | else: 18 | item = self.wrapped[self.offset] # else return and skip 19 | self.offset += 2 20 | return item 21 | next = __next__ # 2.X/3.X compatibility 22 | 23 | if __name__ == '__main__': 24 | alpha = 'abcdef' 25 | skipper = SkipObject(alpha) # Make container object 26 | I = iter(skipper) # Make an iterator on it 27 | print(next(I), next(I), next(I)) # Visit offsets 0, 2, 4 28 | 29 | for x in skipper: # for calls __iter__ automatically 30 | for y in skipper: # Nested fors call __iter__ again each time 31 | print(x + y, end=' ') # Each iterator has its own state, offset 32 | -------------------------------------------------------------------------------- /code/skipper_yield.py: -------------------------------------------------------------------------------- 1 | # File skipper_yield.py 2 | 3 | class SkipObject: # Another __iter__ + yield generator 4 | def __init__(self, wrapped): # Instance scope retained normally 5 | self.wrapped = wrapped # Local scope state saved auto 6 | def __iter__(self): 7 | offset = 0 8 | while offset < len(self.wrapped): 9 | item = self.wrapped[offset] 10 | offset += 2 11 | yield item 12 | -------------------------------------------------------------------------------- /code/slots-test.py: -------------------------------------------------------------------------------- 1 | # File slots-test.py 2 | from __future__ import print_function 3 | import timeit 4 | base = """ 5 | Is = [] 6 | for i in range(1000): 7 | X = C() 8 | X.a = 1; X.b = 2; X.c = 3; X.d = 4 9 | t = X.a + X.b + X.c + X.d 10 | Is.append(X) 11 | """ 12 | 13 | stmt = """ 14 | class C: 15 | __slots__ = ['a', 'b', 'c', 'd'] 16 | """ + base 17 | print('Slots =>', end=' ') 18 | print(min(timeit.repeat(stmt, number=1000, repeat=3))) 19 | 20 | stmt = """ 21 | class C: 22 | pass 23 | """ + base 24 | print('Nonslots=>', end=' ') 25 | print(min(timeit.repeat(stmt, number=1000, repeat=3))) 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /code/small.py: -------------------------------------------------------------------------------- 1 | x = 1 2 | y = [1, 2] 3 | -------------------------------------------------------------------------------- /code/spam.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/code/spam.txt -------------------------------------------------------------------------------- /code/spam_class.py: -------------------------------------------------------------------------------- 1 | class Spam: 2 | numInstances = 0 # Trace class passed in 3 | def __init__(self): 4 | Spam.numInstances += 1 5 | def printNumInstances(cls): 6 | print("Number of instances: %s %s" % (cls.numInstances, cls)) 7 | printNumInstances = classmethod(printNumInstances) 8 | 9 | class Sub(Spam): 10 | def printNumInstances(cls): # Override a class method 11 | print("Extra stuff...", cls) # But call back to original 12 | Spam.printNumInstances() 13 | printNumInstances = classmethod(printNumInstances) 14 | 15 | class Other(Spam): pass # Inherit class method verbatim 16 | -------------------------------------------------------------------------------- /code/spam_class2.py: -------------------------------------------------------------------------------- 1 | class Spam: 2 | numInstances = 0 3 | def count(cls): # Per-class instance counters 4 | cls.numInstances += 1 # cls is lowest class above instance 5 | def __init__(self): 6 | self.count() # Passes self.__class__ to count 7 | count = classmethod(count) 8 | 9 | class Sub(Spam): 10 | numInstances = 0 11 | def __init__(self): # Redefines __init__ 12 | Spam.__init__(self) 13 | 14 | class Other(Spam): # Inherits __init__ 15 | numInstances = 0 16 | -------------------------------------------------------------------------------- /code/spam_static.py: -------------------------------------------------------------------------------- 1 | class Spam: 2 | numInstances = 0 # Use static method for class data 3 | def __init__(self): 4 | Spam.numInstances += 1 5 | def printNumInstances(): 6 | print("Number of instances: %s" % Spam.numInstances) 7 | printNumInstances = staticmethod(printNumInstances) 8 | 9 | class Sub(Spam): 10 | def printNumInstances(): # Override a static method 11 | print("Extra stuff...") # But call back to original 12 | Spam.printNumInstances() 13 | printNumInstances = staticmethod(printNumInstances) 14 | -------------------------------------------------------------------------------- /code/spam_static_deco.py: -------------------------------------------------------------------------------- 1 | class Spam: 2 | numInstances = 0 3 | def __init__(self): 4 | Spam.numInstances = Spam.numInstances + 1 5 | 6 | @staticmethod 7 | def printNumInstances(): 8 | print("Number of instances created: %s" % Spam.numInstances) 9 | -------------------------------------------------------------------------------- /code/specialize.py: -------------------------------------------------------------------------------- 1 | class Super: 2 | def method(self): 3 | print('in Super.method') # Default behavior 4 | def delegate(self): 5 | self.action() # Expected to be defined 6 | 7 | class Inheritor(Super): # Inherit method verbatim 8 | pass 9 | 10 | class Replacer(Super): # Replace method completely 11 | def method(self): 12 | print('in Replacer.method') 13 | 14 | class Extender(Super): # Extend method behavior 15 | def method(self): 16 | print('starting Extender.method') 17 | Super.method(self) 18 | print('ending Extender.method') 19 | 20 | class Provider(Super): # Fill in a required method 21 | def action(self): 22 | print('in Provider.action') 23 | 24 | if __name__ == '__main__': 25 | for klass in (Inheritor, Replacer, Extender): 26 | print('\n' + klass.__name__ + '...') 27 | klass().method() 28 | print('\nProvider...') 29 | x = Provider() 30 | x.delegate() 31 | -------------------------------------------------------------------------------- /code/squares.py: -------------------------------------------------------------------------------- 1 | # File squares.py 2 | 3 | class Squares: 4 | def __init__(self, start, stop): # Save state when created 5 | self.value = start - 1 6 | self.stop = stop 7 | def __iter__(self): # Get iterator object on iter 8 | return self 9 | def __next__(self): # Return a square on each iteration 10 | if self.value == self.stop: # Also called by next built-in 11 | raise StopIteration 12 | self.value += 1 13 | return self.value ** 2 14 | -------------------------------------------------------------------------------- /code/squares_manual.py: -------------------------------------------------------------------------------- 1 | class Squares: # manual generator function calls 2 | def __init__(self, start, stop): # __next__ is automatic/implied 3 | self.start = start 4 | self.stop = stop 5 | def gen(self): 6 | for value in range(self.start, self.stop + 1): 7 | yield value ** 2 8 | -------------------------------------------------------------------------------- /code/squares_nonyield.py: -------------------------------------------------------------------------------- 1 | # File squares_nonyield.py 2 | 3 | class Squares: 4 | def __init__(self, start, stop): # Non-yield generator 5 | self.start = start # Multi scans: extra object 6 | self.stop = stop 7 | def __iter__(self): 8 | return SquaresIter(self.start, self.stop) 9 | 10 | class SquaresIter: 11 | def __init__(self, start, stop): 12 | self.value = start - 1 13 | self.stop = stop 14 | def __next__(self): 15 | if self.value == self.stop: 16 | raise StopIteration 17 | self.value += 1 18 | return self.value ** 2 19 | -------------------------------------------------------------------------------- /code/squares_yield.py: -------------------------------------------------------------------------------- 1 | # File squares_yield.py 2 | 3 | class Squares: # __iter__ + yield generator 4 | def __init__(self, start, stop): # __next__ is automatic/implied 5 | self.start = start 6 | self.stop = stop 7 | def __iter__(self): 8 | for value in range(self.start, self.stop + 1): 9 | yield value ** 2 10 | -------------------------------------------------------------------------------- /code/streams.py: -------------------------------------------------------------------------------- 1 | class Processor: 2 | def __init__(self, reader, writer): 3 | self.reader = reader 4 | self.writer = writer 5 | 6 | def process(self): 7 | while True: 8 | data = self.reader.readline() 9 | if not data: break 10 | data = self.converter(data) 11 | self.writer.write(data) 12 | 13 | def converter(self, data): 14 | assert False, 'converter must be defined' # Or raise exception 15 | -------------------------------------------------------------------------------- /code/sumtree.py: -------------------------------------------------------------------------------- 1 | def sumtree(L): 2 | tot = 0 3 | for x in L: # For each item at this level 4 | if not isinstance(x, list): 5 | tot += x # Add numbers directly 6 | else: 7 | tot += sumtree(x) # Recur for sublists 8 | return tot 9 | 10 | L = [1, [2, [3, 4], 5], 6, [7, 8]] # Arbitrary nesting 11 | print(sumtree(L)) # Prints 36 12 | 13 | # Pathological cases 14 | print(sumtree([1, [2, [3, [4, [5]]]]])) # Prints 15 (right-heavy) 15 | print(sumtree([[[[[1], 2], 3], 4], 5])) # Prints 15 (left-heavy) 16 | -------------------------------------------------------------------------------- /code/temp.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | class MetaOne(type): 4 | def __new__(meta, classname, supers, classdict): 5 | print('In MetaOne.new:', classname, supers, classdict, sep='\n...') 6 | return type.__new__(meta, classname, supers, classdict) 7 | 8 | print('making class') 9 | class Spam: # Inherits from Eggs, instance of Meta 10 | __metaclass__ = MetaOne 11 | data = 1 # Class data attribute 12 | def meth(self, arg): # Class method attribute 13 | pass 14 | 15 | print('making instance') 16 | X = Spam() 17 | print('data: ', X.data) 18 | -------------------------------------------------------------------------------- /code/temp2: -------------------------------------------------------------------------------- 1 | $54,321.99 54,321.99 2 | £54,321.99 ¥54,321.99 3 | £54,321.99 4 | €54,321.99 €54,321.99 5 | ¤54,321.99 6 | -------------------------------------------------------------------------------- /code/temp3: -------------------------------------------------------------------------------- 1 | $54,321.99 54,321.99 2 | £54,321.99 ¥54,321.99 3 | £54,321.99 4 | €54,321.99 €54,321.99 5 | ¤54,321.99 6 | -------------------------------------------------------------------------------- /code/test.txt: -------------------------------------------------------------------------------- 1 | aaaaaa 2 | bbbbbb 3 | cccccc 4 | -------------------------------------------------------------------------------- /code/testjson.txt: -------------------------------------------------------------------------------- 1 | { 2 | "job": [ 3 | "dev", 4 | "mgr" 5 | ], 6 | "name": { 7 | "last": "Smith", 8 | "first": "Bob" 9 | }, 10 | "age": 40.5 11 | } -------------------------------------------------------------------------------- /code/testmixin.py: -------------------------------------------------------------------------------- 1 | #!python 2 | # File testmixin.py (2.X + 3.X) 3 | """ 4 | Generic lister mixin tester: similar to transitive reloader in 5 | Chapter 25, but passes a class object to tester (not function), 6 | and testByNames adds loading of both module and class by name 7 | strings here, in keeping with Chapter 31's factories pattern. 8 | """ 9 | import importlib 10 | 11 | def tester(listerclass, sept=False): 12 | 13 | class Super: 14 | def __init__(self): # Superclass __init__ 15 | self.data1 = 'spam' # Create instance attrs 16 | def ham(self): 17 | pass 18 | 19 | class Sub(Super, listerclass): # Mix in ham and a __str__ 20 | def __init__(self): # Listers have access to self 21 | Super.__init__(self) 22 | self.data2 = 'eggs' # More instance attrs 23 | self.data3 = 42 24 | def spam(self): # Define another method here 25 | pass 26 | 27 | instance = Sub() # Return instance with lister's __str__ 28 | print(instance) # Run mixed-in __str__ (or via str(x)) 29 | if sept: print('-' * 80) 30 | 31 | def testByNames(modname, classname, sept=False): 32 | modobject = importlib.import_module(modname) # Import by namestring 33 | listerclass = getattr(modobject, classname) # Fetch attr by namestring 34 | tester(listerclass, sept) 35 | 36 | if __name__ == '__main__': 37 | testByNames('listinstance', 'ListInstance', True) # Test all 3 here 38 | testByNames('listinherited', 'ListInherited', True) 39 | testByNames('listtree', 'ListTree', False) 40 | -------------------------------------------------------------------------------- /code/testmixin0.py: -------------------------------------------------------------------------------- 1 | # File testmixin0.py 2 | from listinstance import ListInstance # Get lister tool class 3 | 4 | class Super: 5 | def __init__(self): # Superclass __init__ 6 | self.data1 = 'spam' # Create instance attrs 7 | def ham(self): 8 | pass 9 | 10 | class Sub(Super, ListInstance): # Mix in ham and a __str__ 11 | def __init__(self): # Listers have access to self 12 | Super.__init__(self) 13 | self.data2 = 'eggs' # More instance attrs 14 | self.data3 = 42 15 | def spam(self): # Define another method here 16 | pass 17 | 18 | if __name__ == '__main__': 19 | X = Sub() 20 | print(X) # Run mixed-in __str__ 21 | -------------------------------------------------------------------------------- /code/testprint3.py: -------------------------------------------------------------------------------- 1 | from print3_alt2 import print3 2 | print3(1, 2, 3) 3 | print3(1, 2, 3, sep='') # Suppress separator 4 | print3(1, 2, 3, sep='...') 5 | print3(1, [2], (3,), sep='...') # Various object types 6 | 7 | print3(4, 5, 6, sep='', end='') # Suppress newline 8 | print3(7, 8, 9) 9 | print3() # Add newline (or blank line) 10 | 11 | import sys 12 | print3(1, 2, 3, sep='??', end='.\n', file=sys.stderr) # Redirect to file 13 | -------------------------------------------------------------------------------- /code/testseqs.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from timerdeco2 import timer 3 | force = list if sys.version_info[0] == 3 else (lambda X: X) 4 | 5 | @timer(label='[CCC]==>') 6 | def listcomp(N): # Like listcomp = timer(...)(listcomp) 7 | return [x * 2 for x in range(N)] # listcomp(...) triggers Timer.__call__ 8 | 9 | @timer(trace=True, label='[MMM]==>') 10 | def mapcall(N): 11 | return force(map((lambda x: x * 2), range(N))) 12 | 13 | for func in (listcomp, mapcall): 14 | result = func(5) # Time for this call, all calls, return value 15 | func(50000) 16 | func(500000) 17 | func(1000000) 18 | print(result) 19 | print('allTime = %s\n' % func.alltime) # Total time for all calls 20 | 21 | print('**map/comp = %s' % round(mapcall.alltime / listcomp.alltime, 3)) 22 | -------------------------------------------------------------------------------- /code/text.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vgangaprasad/Learning_Python_5thE/730c7256a7c259b55e3b93714660386a95007eff/code/text.py -------------------------------------------------------------------------------- /code/threenames.py: -------------------------------------------------------------------------------- 1 | a = 'dead' # Define three attributes 2 | b = 'parrot' # Exported to other files 3 | c = 'sketch' 4 | print(a, b, c) # Also used in this file 5 | -------------------------------------------------------------------------------- /code/timer.py: -------------------------------------------------------------------------------- 1 | # File timer.py 2 | """ 3 | Homegrown timing tools for function calls. 4 | Does total time, best-of time, and best-of-totals time 5 | """ 6 | 7 | import time, sys 8 | timer = time.clock if sys.platform[:3] == 'win' else time.time 9 | 10 | def total(reps, func, *pargs, **kargs): 11 | """ 12 | Total time to run func() reps times. 13 | Returns (total time, last result) 14 | """ 15 | repslist = list(range(reps)) # Hoist out, equalize 2.x, 3.x 16 | start = timer() # Or perf_counter/other in 3.3+ 17 | for i in repslist: 18 | ret = func(*pargs, **kargs) 19 | elapsed = timer() - start 20 | return (elapsed, ret) 21 | 22 | def bestof(reps, func, *pargs, **kargs): 23 | """ 24 | Quickest func() among reps runs. 25 | Returns (best time, last result) 26 | """ 27 | best = 2 ** 32 # 136 years seems large enough 28 | for i in range(reps): # range usage not timed here 29 | start = timer() 30 | ret = func(*pargs, **kargs) 31 | elapsed = timer() - start # Or call total() with reps=1 32 | if elapsed < best: best = elapsed # Or add to list and take min() 33 | return (best, ret) 34 | 35 | def bestoftotal(reps1, reps2, func, *pargs, **kargs): 36 | """ 37 | Best of totals: 38 | (best of reps1 runs of (total of reps2 runs of func)) 39 | """ 40 | return bestof(reps1, total, reps2, func, *pargs, **kargs) 41 | -------------------------------------------------------------------------------- /code/timer0.py: -------------------------------------------------------------------------------- 1 | # File timer0.py 2 | import time 3 | def timer(func, *args): # Simplistic timing function 4 | start = time.clock() 5 | for i in range(1000): 6 | func(*args) 7 | return time.clock() - start # Total Elapsed time in seconds 8 | -------------------------------------------------------------------------------- /code/timer2.py: -------------------------------------------------------------------------------- 1 | # File timer2.py (2.X and 3.X) 2 | """ 3 | total(spam, 1, 2, a=3, b=4, _reps=1000) calls and times spam(1, 2, a=3, b=4) 4 | _reps times, and returns total time for all runs, with final result. 5 | 6 | bestof(spam, 1, 2, a=3, b=4, _reps=5) runs best-of-N timer to attempt to 7 | filter out system load variation, and returns best time among _reps tests. 8 | 9 | bestoftotal(spam 1, 2, a=3, b=4, _rep1=5, reps=1000) runs best-of-totals 10 | test, which takes the best among _reps1 runs of (the total of _reps runs); 11 | """ 12 | 13 | import time, sys 14 | timer = time.clock if sys.platform[:3] == 'win' else time.time 15 | 16 | def total(func, *pargs, **kargs): 17 | _reps = kargs.pop('_reps', 1000) # Passed-in or default reps 18 | repslist = list(range(_reps)) # Hoist range out for 2.6 lists 19 | start = timer() 20 | for i in repslist: 21 | ret = func(*pargs, **kargs) 22 | elapsed = timer() - start 23 | return (elapsed, ret) 24 | 25 | def bestof(func, *pargs, **kargs): 26 | _reps = kargs.pop('_reps', 5) 27 | best = 2 ** 32 28 | for i in range(_reps): 29 | start = timer() 30 | ret = func(*pargs, **kargs) 31 | elapsed = timer() - start 32 | if elapsed < best: best = elapsed 33 | return (best, ret) 34 | 35 | def bestoftotal(func, *pargs, **kargs): 36 | _reps1 = kargs.pop('_reps1', 5) 37 | return min(total(func, *pargs, **kargs) for i in range(_reps1)) 38 | -------------------------------------------------------------------------------- /code/timer3.py: -------------------------------------------------------------------------------- 1 | # File timer3.py (3.X only) 2 | """ 3 | Same usage as timer2.py, but uses 3.X keyword-only default arguments 4 | instead of dict pops for simpler code. No need to hoist range() out 5 | of tests in 3.X: always a generator in 3.X, and this can't run on 2.X. 6 | """ 7 | import time, sys 8 | timer = time.clock if sys.platform[:3] == 'win' else time.time 9 | 10 | def total(func, *pargs, _reps=1000, **kargs): 11 | start = timer() 12 | for i in range(_reps): 13 | ret = func(*pargs, **kargs) 14 | elapsed = timer() - start 15 | return (elapsed, ret) 16 | 17 | def bestof(func, *pargs, _reps=5, **kargs): 18 | best = 2 ** 32 19 | for i in range(_reps): 20 | start = timer() 21 | ret = func(*pargs, **kargs) 22 | elapsed = timer() - start 23 | if elapsed < best: best = elapsed 24 | return (best, ret) 25 | 26 | def bestoftotal(func, *pargs, _reps1=5, **kargs): 27 | return min(total(func, *pargs, **kargs) for i in range(_reps1)) 28 | -------------------------------------------------------------------------------- /code/timerdeco-test.py: -------------------------------------------------------------------------------- 1 | """ 2 | File timerdeco-test.py 3 | """ 4 | from __future__ import print_function # 2.X 5 | from timerdeco import timer 6 | import sys 7 | force = list if sys.version_info[0] == 3 else (lambda X: X) 8 | 9 | print('---------------------------------------------------') 10 | # Test on functions 11 | 12 | @timer(trace=True, label='[CCC]==>') 13 | def listcomp(N): # Like listcomp = timer(...)(listcomp) 14 | return [x * 2 for x in range(N)] # listcomp(...) triggers onCall 15 | 16 | @timer('[MMM]==>') 17 | def mapcall(N): 18 | return force(map((lambda x: x * 2), range(N))) # list() for 3.X views 19 | 20 | for func in (listcomp, mapcall): 21 | result = func(5) # Time for this call, all calls, return value 22 | func(5000000) 23 | print(result) 24 | print('allTime = %s\n' % func.alltime) # Total time for all calls 25 | 26 | print('---------------------------------------------------') 27 | # Test on methods 28 | 29 | class Person: 30 | def __init__(self, name, pay): 31 | self.name = name 32 | self.pay = pay 33 | 34 | @timer() 35 | def giveRaise(self, percent): # giveRaise = timer()(giveRaise) 36 | self.pay *= (1.0 + percent) # tracer remembers giveRaise 37 | 38 | @timer(label='**') 39 | def lastName(self): # lastName = timer(...)(lastName) 40 | return self.name.split()[-1] # alltime per class, not instance 41 | 42 | bob = Person('Bob Smith', 50000) 43 | sue = Person('Sue Jones', 100000) 44 | bob.giveRaise(.10) 45 | sue.giveRaise(.20) # runs onCall(sue, .10) 46 | print(int(bob.pay), int(sue.pay)) 47 | print(bob.lastName(), sue.lastName()) # runs onCall(bob), remembers lastName 48 | print('%.5f %.5f' % (Person.giveRaise.alltime, Person.lastName.alltime)) 49 | 50 | -------------------------------------------------------------------------------- /code/timerdeco.py: -------------------------------------------------------------------------------- 1 | """ 2 | File timerdeco.py (3.X + 2.X) 3 | Call timer decorator for both functions and methods. 4 | """ 5 | import time 6 | 7 | def timer(label='', trace=True): # On decorator args: retain args 8 | def onDecorator(func): # On @: retain decorated func 9 | def onCall(*args, **kargs): # On calls: call original 10 | start = time.clock() # State is scopes + func attr 11 | result = func(*args, **kargs) 12 | elapsed = time.clock() - start 13 | onCall.alltime += elapsed 14 | if trace: 15 | format = '%s%s: %.5f, %.5f' 16 | values = (label, func.__name__, elapsed, onCall.alltime) 17 | print(format % values) 18 | return result 19 | onCall.alltime = 0 20 | return onCall 21 | return onDecorator 22 | -------------------------------------------------------------------------------- /code/timerdeco1.py: -------------------------------------------------------------------------------- 1 | # File timer-deco1.py 2 | # Caveat: range still differs - a list in 2.X, an iterable in 3.X 3 | # Caveat: timer won't work on methods as coded (see quiz solution) 4 | 5 | import time, sys 6 | force = list if sys.version_info[0] == 3 else (lambda X: X) 7 | 8 | class timer: 9 | def __init__(self, func): 10 | self.func = func 11 | self.alltime = 0 12 | def __call__(self, *args, **kargs): 13 | start = time.clock() 14 | result = self.func(*args, **kargs) 15 | elapsed = time.clock() - start 16 | self.alltime += elapsed 17 | print('%s: %.5f, %.5f' % (self.func.__name__, elapsed, self.alltime)) 18 | return result 19 | 20 | @timer 21 | def listcomp(N): 22 | return [x * 2 for x in range(N)] 23 | 24 | @timer 25 | def mapcall(N): 26 | return force(map((lambda x: x * 2), range(N))) 27 | 28 | result = listcomp(5) # Time for this call, all calls, return value 29 | listcomp(50000) 30 | listcomp(500000) 31 | listcomp(1000000) 32 | print(result) 33 | print('allTime = %s' % listcomp.alltime) # Total time for all listcomp calls 34 | 35 | print('') 36 | result = mapcall(5) 37 | mapcall(50000) 38 | mapcall(500000) 39 | mapcall(1000000) 40 | print(result) 41 | print('allTime = %s' % mapcall.alltime) # Total time for all mapcall calls 42 | 43 | print('\n**map/comp = %s' % round(mapcall.alltime / listcomp.alltime, 3)) 44 | -------------------------------------------------------------------------------- /code/timerdeco2.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | def timer(label='', trace=True): # On decorator args: retain args 4 | class Timer: 5 | def __init__(self, func): # On @: retain decorated func 6 | self.func = func 7 | self.alltime = 0 8 | def __call__(self, *args, **kargs): # On calls: call original 9 | start = time.clock() 10 | result = self.func(*args, **kargs) 11 | elapsed = time.clock() - start 12 | self.alltime += elapsed 13 | if trace: 14 | format = '%s %s: %.5f, %.5f' 15 | values = (label, self.func.__name__, elapsed, self.alltime) 16 | print(format % values) 17 | return result 18 | return Timer 19 | -------------------------------------------------------------------------------- /code/timeseqs-results.txt: -------------------------------------------------------------------------------- 1 | # all using abs() 2 | 3 | c:\code>py -3 timeseqs.py 4 | 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17) [MSC v.1600 64 bit (AMD64)] 5 | forLoop : 1.27880 => [0...9999] 6 | listComp : 0.70435 => [0...9999] 7 | mapCall : 0.55856 => [0...9999] 8 | genExpr : 1.09031 => [0...9999] 9 | genFunc : 1.08384 => [0...9999] 10 | 11 | c:\code>py -2 timeseqs.py 12 | 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] 13 | forLoop : 1.23458 => [0...9999] 14 | listComp : 0.65007 => [0...9999] 15 | mapCall : 0.60083 => [0...9999] 16 | genExpr : 0.89129 => [0...9999] 17 | genFunc : 0.88493 => [0...9999] 18 | 19 | c:\code>c:\PyPy\pypy-1.9\pypy.exe timeseqs.py 20 | 2.7.2 (341e1e3821ff, Jun 07 2012, 15:43:00) 21 | [PyPy 1.9.0 with MSC v.1500 32 bit] 22 | forLoop : 0.11305 => [0...9999] 23 | listComp : 0.05677 => [0...9999] 24 | mapCall : 0.11151 => [0...9999] 25 | genExpr : 0.18550 => [0...9999] 26 | genFunc : 0.17161 => [0...9999] 27 | 28 | 29 | # all doing x + 10 (map requires lambda) 30 | 31 | c:\code>py -3 timeseqs2.py 32 | 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17) [MSC v.1600 64 bit (AMD64)] 33 | forLoop : 1.33106 => [10...10009] 34 | listComp : 0.72086 => [10...10009] 35 | mapCall : 1.66331 => [10...10009] 36 | genExpr : 1.08869 => [10...10009] 37 | genFunc : 1.09644 => [10...10009] 38 | 39 | 40 | # all using user-defined f() 41 | 42 | c:\code>py -3 timeseqs2B.py 43 | 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17) [MSC v.1600 64 bit (AMD64)] 44 | forLoop : 1.88374 => [0...9999] 45 | listComp : 1.44383 => [0...9999] 46 | mapCall : 1.19976 => [0...9999] 47 | genExpr : 1.55637 => [0...9999] 48 | genFunc : 1.56062 => [0...9999] 49 | -------------------------------------------------------------------------------- /code/timeseqs.py: -------------------------------------------------------------------------------- 1 | # File timeseqs.py 2 | "Test the relative speed of iteration tool alternatives." 3 | 4 | import sys, timer # Import timer functions 5 | reps = 10000 6 | repslist = list(range(reps)) # Hoist out, list in both 2.X/3.X 7 | 8 | def forLoop(): 9 | res = [] 10 | for x in repslist: 11 | res.append(abs(x)) 12 | return res 13 | 14 | def listComp(): 15 | return [abs(x) for x in repslist] 16 | 17 | def mapCall(): 18 | return list(map(abs, repslist)) # Use list() here in 3.X only! 19 | # return map(abs, repslist) 20 | 21 | def genExpr(): 22 | return list(abs(x) for x in repslist) # list() required to force results 23 | 24 | def genFunc(): 25 | def gen(): 26 | for x in repslist: 27 | yield abs(x) 28 | return list(gen()) # list() required to force results 29 | 30 | print(sys.version) 31 | for test in (forLoop, listComp, mapCall, genExpr, genFunc): 32 | (bestof, (total, result)) = timer.bestoftotal(5, 1000, test) 33 | print ('%-9s: %.5f => [%s...%s]' % 34 | (test.__name__, bestof, result[0], result[-1])) 35 | -------------------------------------------------------------------------------- /code/timeseqs2.py: -------------------------------------------------------------------------------- 1 | # File timeseqs2.py 2 | """ 3 | See the effect of function call in map only. 4 | """ 5 | 6 | import sys, timer # Import timer functions 7 | reps = 10000 8 | repslist = list(range(reps)) # Hoist out, list in both 2.X/3.X 9 | 10 | #... 11 | 12 | def forLoop(): 13 | res = [] 14 | for x in repslist: 15 | res.append(x + 10) 16 | return res 17 | 18 | def listComp(): 19 | return [x + 10 for x in repslist] 20 | 21 | def mapCall(): 22 | return list(map((lambda x: x + 10), repslist)) # list() in 3.X only 23 | # return map(((lambda x: x + 10), repslist) 24 | 25 | def genExpr(): 26 | return list(x + 10 for x in repslist) # list() in 2.X + 3.X 27 | 28 | def genFunc(): 29 | def gen(): 30 | for x in repslist: 31 | yield x + 10 32 | return list(gen()) # list() in 2.X + 3.X 33 | 34 | #... 35 | 36 | print(sys.version) 37 | for test in (forLoop, listComp, mapCall, genExpr, genFunc): 38 | (bestof, (total, result)) = timer.bestoftotal(5, 1000, test) 39 | print ('%-9s: %.5f => [%s...%s]' % 40 | (test.__name__, bestof, result[0], result[-1])) 41 | -------------------------------------------------------------------------------- /code/timeseqs2B.py: -------------------------------------------------------------------------------- 1 | # File timeseqs2.py 2 | """ 3 | See the effect of function call in all. 4 | """ 5 | 6 | import sys, timer # Import timer functions 7 | reps = 10000 8 | repslist = list(range(reps)) # Hoist out, list in both 2.X/3.X 9 | 10 | #... 11 | 12 | def F(x): return x 13 | 14 | def forLoop(): 15 | res = [] 16 | for x in repslist: 17 | res.append(F(x)) 18 | return res 19 | 20 | def listComp(): 21 | return [F(x) for x in repslist] 22 | 23 | def mapCall(): 24 | return list(map(F, repslist)) # list in 3.X only 25 | # return map(F, repslist) 26 | 27 | def genExpr(): 28 | return list(F(x) for x in repslist) # list in 2.X + 3.X 29 | 30 | def genFunc(): 31 | def gen(): 32 | for x in repslist: 33 | yield F(x) 34 | return list(gen()) 35 | 36 | #... 37 | 38 | print(sys.version) 39 | for test in (forLoop, listComp, mapCall, genExpr, genFunc): 40 | (bestof, (total, result)) = timer.bestoftotal(5, 1000, test) 41 | print ('%-9s: %.5f => [%s...%s]' % 42 | (test.__name__, bestof, result[0], result[-1])) 43 | -------------------------------------------------------------------------------- /code/timeseqs3.py: -------------------------------------------------------------------------------- 1 | # File timeseqs3.py 2 | """ 3 | See how this compares to later timeit results. 4 | Now very similar to pybench.py's timeit total, but 5 | still not identical: adds function call per total loop, 6 | uses prebuilt list for range instead of generator. 7 | """ 8 | 9 | import sys, timer 10 | reps = 1000 # <== to match pybench (1000 inner) 11 | repslist = list(range(reps)) # <== differs from pybench 12 | 13 | def forLoop(): 14 | res = [] 15 | for x in repslist: 16 | res.append(x ** 2) # <== to match pybench (x **2 all) 17 | return res 18 | 19 | def listComp(): 20 | return [x ** 2 for x in repslist] 21 | 22 | def mapCall(): 23 | return list(map((lambda x: x ** 2), repslist)) # list() in 3.X only 24 | # return map(((lambda x: x ** 2), repslist) 25 | 26 | def genExpr(): 27 | return list(x ** 2 for x in repslist) # list() in 2.X + 3.X 28 | 29 | def genFunc(): 30 | def gen(): 31 | for x in repslist: 32 | yield x ** 2 33 | return list(gen()) # list() in 2.X + 3.X 34 | 35 | print(sys.version) 36 | for test in (forLoop, listComp, mapCall, genExpr, genFunc): 37 | (bestof, (total, result)) = timer.bestoftotal(5, 1000, test) 38 | print ('%-9s: %.5f => [%s...%s]' % 39 | (test.__name__, bestof, result[0], result[-1])) 40 | -------------------------------------------------------------------------------- /code/timeseqs_timer2.py: -------------------------------------------------------------------------------- 1 | # File timeseqs_timer2.py 2 | "Test the relative speed of iteration tool alternatives: timer2 version" 3 | 4 | import sys, timer2 # <==differs 5 | reps = 10000 6 | repslist = list(range(reps)) # Hoist out, list in both 2.X/3.X 7 | 8 | def forLoop(): 9 | res = [] 10 | for x in repslist: 11 | res.append(abs(x)) 12 | return res 13 | 14 | def listComp(): 15 | return [abs(x) for x in repslist] 16 | 17 | def mapCall(): 18 | return list(map(abs, repslist)) # Use list here in 3.0 only! 19 | # return map(abs, repslist) 20 | 21 | def genExpr(): 22 | return list(abs(x) for x in repslist) # list required to force results 23 | 24 | def genFunc(): 25 | def gen(): 26 | for x in repslist: 27 | yield abs(x) 28 | return list(gen()) # list required to force results 29 | 30 | print(sys.version) 31 | for test in (forLoop, listComp, mapCall, genExpr, genFunc): 32 | (total, result) = timer2.bestoftotal(test, _reps1=5, _reps=1000) 33 | # Or: 34 | # (total, result) = timer2.bestoftotal(test) 35 | # (total, result) = timer2.bestof(test, _reps=5) 36 | # (total, result) = timer2.total(test, _reps=1000) 37 | # (bestof, (total, result)) = timer2.bestof(timer2.total, test, _reps=5) 38 | 39 | print ('%-9s: %.5f => [%s...%s]' % 40 | (test.__name__, total, result[0], result[-1])) 41 | -------------------------------------------------------------------------------- /code/timeseqs_timer3.py: -------------------------------------------------------------------------------- 1 | # File timeseqs_timer2.py 2 | "Test the relative speed of iteration tool alternatives: timer2 version" 3 | 4 | import sys, timer3 # <==differs 5 | reps = 10000 6 | repslist = list(range(reps)) # Hoist out, list in both 2.X/3.X 7 | 8 | def forLoop(): 9 | res = [] 10 | for x in repslist: 11 | res.append(abs(x)) 12 | return res 13 | 14 | def listComp(): 15 | return [abs(x) for x in repslist] 16 | 17 | def mapCall(): 18 | return list(map(abs, repslist)) # Use list here in 3.0 only! 19 | # return map(abs, repslist) 20 | 21 | def genExpr(): 22 | return list(abs(x) for x in repslist) # list required to force results 23 | 24 | def genFunc(): 25 | def gen(): 26 | for x in repslist: 27 | yield abs(x) 28 | return list(gen()) # list required to force results 29 | 30 | print(sys.version) 31 | for test in (forLoop, listComp, mapCall, genExpr, genFunc): 32 | (total, result) = timer3.bestoftotal(test, _reps1=5, _reps=1000) 33 | # Or: 34 | # (total, result) = timer3.bestoftotal(test) 35 | # (total, result) = timer3.bestof(test, _reps=5) 36 | # (total, result) = timer3.total(test, _reps=1000) 37 | # (bestof, (total, result)) = timer3.bestof(timer2.total, test, _reps=5) 38 | 39 | print ('%-9s: %.5f => [%s...%s]' % 40 | (test.__name__, total, result[0], result[-1])) 41 | -------------------------------------------------------------------------------- /code/timesqrt.py: -------------------------------------------------------------------------------- 1 | # File timesqrt.py 2 | import sys, timer2 3 | reps = 10000 4 | repslist = range(reps) # Pull out range list time for 2.6 5 | 6 | from math import sqrt # Not math.sqrt: adds attr fetch time 7 | def mathMod(): 8 | for i in repslist: 9 | res = sqrt(i) 10 | return res 11 | 12 | def powCall(): 13 | for i in repslist: 14 | res = pow(i, .5) 15 | return res 16 | 17 | def powExpr(): 18 | for i in repslist: 19 | res = i ** .5 20 | return res 21 | 22 | print(sys.version) 23 | for test in (mathMod, powCall, powExpr): 24 | elapsed, result = timer2.bestoftotal(test, _reps1=3, _reps=1000) 25 | print ('%s: %.5f => %s' % (test.__name__, elapsed, result)) 26 | -------------------------------------------------------------------------------- /code/trace.py: -------------------------------------------------------------------------------- 1 | class Wrapper: 2 | def __init__(self, object): 3 | self.wrapped = object # Save object 4 | def __getattr__(self, attrname): 5 | print('Trace: ' + attrname) # Trace fetch 6 | return getattr(self.wrapped, attrname) # Delegate fetch 7 | -------------------------------------------------------------------------------- /code/trace_ns.py: -------------------------------------------------------------------------------- 1 | class Wrapper(object): 2 | def __init__(self, object): 3 | self.wrapped = object # Save object 4 | def __getattr__(self, attrname): 5 | print('Trace: ' + attrname) # Trace fetch 6 | return getattr(self.wrapped, attrname) # Delegate fetch 7 | -------------------------------------------------------------------------------- /code/tracer0.py: -------------------------------------------------------------------------------- 1 | def tracer(func, *pargs, **kargs): # Accept arbitrary arguments 2 | print('calling:', func.__name__) 3 | return func(*pargs, **kargs) # Pass along arbitrary arguments 4 | 5 | def func(a, b, c, d): 6 | return a + b + c + d 7 | 8 | print(tracer(func, 1, 2, c=3, d=4)) 9 | -------------------------------------------------------------------------------- /code/tracer1.py: -------------------------------------------------------------------------------- 1 | class tracer: 2 | def __init__(self, func): # Remember original, init counter 3 | self.calls = 0 4 | self.func = func 5 | def __call__(self, *args): # On later calls: add logic, run original 6 | self.calls += 1 7 | print('call %s to %s' % (self.calls, self.func.__name__)) 8 | return self.func(*args) 9 | 10 | @tracer # Same as spam = tracer(spam) 11 | def spam(a, b, c): # Wrap spam in a decorator object 12 | return a + b + c 13 | 14 | print(spam(1, 2, 3)) # Really calls the tracer wrapper object 15 | print(spam('a', 'b', 'c')) # Invokes __call__ in class 16 | -------------------------------------------------------------------------------- /code/tracer2.py: -------------------------------------------------------------------------------- 1 | def tracer(func): # Remember original 2 | def oncall(*args): # On later calls 3 | oncall.calls += 1 4 | print('call %s to %s' % (oncall.calls, func.__name__)) 5 | return func(*args) 6 | oncall.calls = 0 7 | return oncall 8 | 9 | class C: 10 | @tracer 11 | def spam(self,a, b, c): return a + b + c 12 | 13 | x = C() 14 | print(x.spam(1, 2, 3)) 15 | print(x.spam('a', 'b', 'c')) # Same output as tracer1 (in tracer2.py) 16 | -------------------------------------------------------------------------------- /code/trispam.txt: -------------------------------------------------------------------------------- 1 | spam 2 | Spam 3 | SPAM! 4 | -------------------------------------------------------------------------------- /code/trispamup.txt: -------------------------------------------------------------------------------- 1 | SPAM 2 | SPAM 3 | SPAM! 4 | -------------------------------------------------------------------------------- /code/typesubclass.py: -------------------------------------------------------------------------------- 1 | # Subclass built-in list type/class 2 | # Map 1..N to 0..N-1; call back to built-in version. 3 | 4 | class MyList(list): 5 | def __getitem__(self, offset): 6 | print('(indexing %s at %s)' % (self, offset)) 7 | return list.__getitem__(self, offset - 1) 8 | 9 | if __name__ == '__main__': 10 | print(list('abc')) 11 | x = MyList('abc') # __init__ inherited from list 12 | print(x) # __repr__ inherited from list 13 | 14 | print(x[1]) # MyList.__getitem__ 15 | print(x[3]) # Customizes list superclass method 16 | 17 | x.append('spam'); print(x) # Attributes from list superclass 18 | x.reverse(); print(x) 19 | -------------------------------------------------------------------------------- /code/unders.py: -------------------------------------------------------------------------------- 1 | a, _b, c, _d = 1, 2, 3, 4 -------------------------------------------------------------------------------- /code/uni2x.txt: -------------------------------------------------------------------------------- 1 | spÄm1 2 | eggs1 3 | ham 4 | -------------------------------------------------------------------------------- /code/unidata.txt: -------------------------------------------------------------------------------- 1 | spÄm -------------------------------------------------------------------------------- /code/uppdatedb.py: -------------------------------------------------------------------------------- 1 | # File updatedb.py: update Person object on database 2 | 3 | import shelve 4 | db = shelve.open('persondb') # Reopen shelve with same filename 5 | 6 | for key in sorted(db): # Iterate to display database objects 7 | print(key, '\t=>', db[key]) # Prints with custom format 8 | 9 | sue = db['Sue Jones'] # Index by key to fetch 10 | sue.giveRaise(.10) # Update in memory using class method 11 | db['Sue Jones'] = sue # Assign to key to update in shelve 12 | db.close() # Close after making changes 13 | -------------------------------------------------------------------------------- /code/upper.py: -------------------------------------------------------------------------------- 1 | IMPORT SYS 2 | PRINT(SYS.PATH) 3 | X = 2 4 | PRINT(X ** 32) 5 | -------------------------------------------------------------------------------- /code/utf8data: -------------------------------------------------------------------------------- 1 | AÄBèC -------------------------------------------------------------------------------- /code/utfdata: -------------------------------------------------------------------------------- 1 | AÄBèC -------------------------------------------------------------------------------- /code/validate_descriptors1.py: -------------------------------------------------------------------------------- 1 | # File validate_descriptors1.py: using shared descriptor state 2 | 3 | class CardHolder(object): # Need all "(object)" in 2.X only 4 | acctlen = 8 # Class data 5 | retireage = 59.5 6 | 7 | def __init__(self, acct, name, age, addr): 8 | self.acct = acct # Instance data 9 | self.name = name # These trigger __set__ calls too! 10 | self.age = age # __X not needed: in descriptor 11 | self.addr = addr # addr is not managed 12 | # remain has no data 13 | class Name(object): 14 | def __get__(self, instance, owner): # Class names: CardHolder locals 15 | return self.name 16 | def __set__(self, instance, value): 17 | value = value.lower().replace(' ', '_') 18 | self.name = value 19 | name = Name() 20 | 21 | class Age(object): 22 | def __get__(self, instance, owner): 23 | return self.age # Use descriptor data 24 | def __set__(self, instance, value): 25 | if value < 0 or value > 150: 26 | raise ValueError('invalid age') 27 | else: 28 | self.age = value 29 | age = Age() 30 | 31 | class Acct(object): 32 | def __get__(self, instance, owner): 33 | return self.acct[:-3] + '***' 34 | def __set__(self, instance, value): 35 | value = value.replace('-', '') 36 | if len(value) != instance.acctlen: # Use instance class data 37 | raise TypeError('invald acct number') 38 | else: 39 | self.acct = value 40 | acct = Acct() 41 | 42 | class Remain(object): 43 | def __get__(self, instance, owner): 44 | return instance.retireage - instance.age # Triggers Age.__get__ 45 | def __set__(self, instance, value): 46 | raise TypeError('cannot set remain') # Else set allowed here 47 | remain = Remain() 48 | -------------------------------------------------------------------------------- /code/validate_getattr.py: -------------------------------------------------------------------------------- 1 | # File validate_getattr.py 2 | 3 | class CardHolder: 4 | acctlen = 8 # Class data 5 | retireage = 59.5 6 | 7 | def __init__(self, acct, name, age, addr): 8 | self.acct = acct # Instance data 9 | self.name = name # These trigger __setattr__ too 10 | self.age = age # _acct not mangled: name tested 11 | self.addr = addr # addr is not managed 12 | # remain has no data 13 | def __getattr__(self, name): 14 | if name == 'acct': # On undefined attr fetches 15 | return self._acct[:-3] + '***' # name, age, addr are defined 16 | elif name == 'remain': 17 | return self.retireage - self.age # Doesn't trigger __getattr__ 18 | else: 19 | raise AttributeError(name) 20 | 21 | def __setattr__(self, name, value): 22 | if name == 'name': # On all attr assignments 23 | value = value.lower().replace(' ', '_') # addr stored directly 24 | elif name == 'age': # acct mangled to _acct 25 | if value < 0 or value > 150: 26 | raise ValueError('invalid age') 27 | elif name == 'acct': 28 | name = '_acct' 29 | value = value.replace('-', '') 30 | if len(value) != self.acctlen: 31 | raise TypeError('invald acct number') 32 | elif name == 'remain': 33 | raise TypeError('cannot set remain') 34 | self.__dict__[name] = value # Avoid looping (or via object) 35 | -------------------------------------------------------------------------------- /code/validate_getattribute.py: -------------------------------------------------------------------------------- 1 | # File validate_getattribute.py 2 | 3 | class CardHolder(object): # Need "(object)" in 2.X only 4 | acctlen = 8 # Class data 5 | retireage = 59.5 6 | 7 | def __init__(self, acct, name, age, addr): 8 | self.acct = acct # Instance data 9 | self.name = name # These trigger __setattr__ too 10 | self.age = age # acct not mangled: name tested 11 | self.addr = addr # addr is not managed 12 | # remain has no data 13 | def __getattribute__(self, name): 14 | superget = object.__getattribute__ # Don't loop: one level up 15 | if name == 'acct': # On all attr fetches 16 | return superget(self, 'acct')[:-3] + '***' 17 | elif name == 'remain': 18 | return superget(self, 'retireage') - superget(self, 'age') 19 | else: 20 | return superget(self, name) # name, age, addr: stored 21 | 22 | def __setattr__(self, name, value): 23 | if name == 'name': # On all attr assignments 24 | value = value.lower().replace(' ', '_') # addr stored directly 25 | elif name == 'age': 26 | if value < 0 or value > 150: 27 | raise ValueError('invalid age') 28 | elif name == 'acct': 29 | value = value.replace('-', '') 30 | if len(value) != self.acctlen: 31 | raise TypeError('invald acct number') 32 | elif name == 'remain': 33 | raise TypeError('cannot set remain') 34 | self.__dict__[name] = value # Avoid loops, orig names 35 | -------------------------------------------------------------------------------- /code/validate_properties.py: -------------------------------------------------------------------------------- 1 | # File validate_properties.py 2 | 3 | class CardHolder(object): # Need "(object)" for setter in 2.X 4 | acctlen = 8 # Class data 5 | retireage = 59.5 6 | 7 | def __init__(self, acct, name, age, addr): 8 | self.acct = acct # Instance data 9 | self.name = name # These trigger prop setters too! 10 | self.age = age # __X mangled to have class name 11 | self.addr = addr # addr is not managed 12 | # remain has no data 13 | def getName(self): 14 | return self.__name 15 | def setName(self, value): 16 | value = value.lower().replace(' ', '_') 17 | self.__name = value 18 | name = property(getName, setName) 19 | 20 | def getAge(self): 21 | return self.__age 22 | def setAge(self, value): 23 | if value < 0 or value > 150: 24 | raise ValueError('invalid age') 25 | else: 26 | self.__age = value 27 | age = property(getAge, setAge) 28 | 29 | def getAcct(self): 30 | return self.__acct[:-3] + '***' 31 | def setAcct(self, value): 32 | value = value.replace('-', '') 33 | if len(value) != self.acctlen: 34 | raise TypeError('invald acct number') 35 | else: 36 | self.__acct = value 37 | acct = property(getAcct, setAcct) 38 | 39 | def remainGet(self): # Could be a method, not attr 40 | return self.retireage - self.age # Unless already using as attr 41 | remain = property(remainGet) 42 | -------------------------------------------------------------------------------- /code/validate_tester.py: -------------------------------------------------------------------------------- 1 | # File validate_tester.py 2 | from __future__ import print_function # 2.X 3 | 4 | def loadclass(): 5 | import sys, importlib 6 | modulename = sys.argv[1] # Module name in command line 7 | module = importlib.import_module(modulename) # Import module by name string 8 | print('[Using: %s]' % module.CardHolder) # No need for getattr() here 9 | return module.CardHolder 10 | 11 | def printholder(who): 12 | print(who.acct, who.name, who.age, who.remain, who.addr, sep=' / ') 13 | 14 | if __name__ == '__main__': 15 | CardHolder = loadclass() 16 | bob = CardHolder('1234-5678', 'Bob Smith', 40, '123 main st') 17 | printholder(bob) 18 | bob.name = 'Bob Q. Smith' 19 | bob.age = 50 20 | bob.acct = '23-45-67-89' 21 | printholder(bob) 22 | 23 | sue = CardHolder('5678-12-34', 'Sue Jones', 35, '124 main st') 24 | printholder(sue) 25 | try: 26 | sue.age = 200 27 | except: 28 | print('Bad age for Sue') 29 | 30 | try: 31 | sue.remain = 5 32 | except: 33 | print("Can't set sue.remain") 34 | 35 | try: 36 | sue.acct = '1234567' 37 | except: 38 | print('Bad acct for Sue') 39 | -------------------------------------------------------------------------------- /code/validate_tester2.py: -------------------------------------------------------------------------------- 1 | # File validate_tester2.py 2 | from __future__ import print_function # 2.X 3 | 4 | from validate_tester import loadclass 5 | CardHolder = loadclass() 6 | 7 | bob = CardHolder('1234-5678', 'Bob Smith', 40, '123 main st') 8 | print('bob:', bob.name, bob.acct, bob.age, bob.addr) 9 | 10 | sue = CardHolder('5678-12-34', 'Sue Jones', 35, '124 main st') 11 | print('sue:', sue.name, sue.acct, sue.age, sue.addr) # addr differs: client data 12 | print('bob:', bob.name, bob.acct, bob.age, bob.addr) # name,acct,age overwritten? 13 | -------------------------------------------------------------------------------- /code/what.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | import sys 3 | print(sys.version.split()[0]) # First part of string 4 | -------------------------------------------------------------------------------- /code/withas.py: -------------------------------------------------------------------------------- 1 | class TraceBlock: 2 | def message(self, arg): 3 | print('running ' + arg) 4 | def __enter__(self): 5 | print('starting with block') 6 | return self 7 | def __exit__(self, exc_type, exc_value, exc_tb): 8 | if exc_type is None: 9 | print('exited normally\n') 10 | else: 11 | print('raise an exception! ' + str(exc_type)) 12 | return False # Propagate 13 | 14 | if __name__ == '__main__': 15 | with TraceBlock() as action: 16 | action.message('test 1') 17 | print('reached') 18 | 19 | with TraceBlock() as action: 20 | action.message('test 2') 21 | raise TypeError 22 | print('not reached') 23 | -------------------------------------------------------------------------------- /code/zoo.py: -------------------------------------------------------------------------------- 1 | class Animal: 2 | def reply(self): self.speak() # Back to subclass 3 | def speak(self): print('spam') # Custom message 4 | 5 | class Mammal(Animal): 6 | def speak(self): print('huh?') 7 | 8 | class Cat(Mammal): 9 | def speak(self): print('meow') 10 | 11 | class Dog(Mammal): 12 | def speak(self): print('bark') 13 | 14 | class Primate(Mammal): 15 | def speak(self): print('Hello world!') 16 | 17 | class Hacker(Primate): pass # Inherit from Primate 18 | --------------------------------------------------------------------------------