├── 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 |
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 |
--------------------------------------------------------------------------------