[Tutor] Using a dictionary to map functions
I am a novice self taught programmer learning with Python. I am working on a program to calculate coordinate geometry. The input file is a list of commands. A number is assigned to each command and followed by various inputs required to make the calculation. The input has the following format: 5 201 1496.0423 1234.5678 (this command stores the last two numbers as the coordinates for point 201; 5 = store point command) comments lines begin with # Each command can take 3 to 7 arguments depending on the calculation. Currently I am building each command as a separate module that I can import into the main program. My main program reads the input file and separates the commands from blank and comment lines. As it reads the input file, it splits the command and appends it to a list. I'm thinking of having a dictionary that maps the commands/functions to each number. My conundrum is how to use the dictionary mapping to call the functions and pass the arguments. In the case below, I would pass the arguments pt_table and line. In the function store_point, I break the list, line, into components to make the calculation. By passing the entire line, I can validate the command in the corresponding function. import re from store_point import store_point try: infile = open(raw_input("Enter input file name; name.txt:"),'r') except: print "Invalid filename" exit() templist = [] pt_table = {} cmd_table = {5:"store_point", 19: "line_line_int"} count = 0 for line in infile: #print line line = line.rstrip() if re.search('^[0-9]+', line): a = line.split() templist.append(a) for line in templist: #use dictionary to call and pass arguments to function As a novice programmer, I am also open to suggestions to do this more effectively. Thank you Colby ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Using a dictionary to map functions
Thank you! This is what I was hoping to accomplish. > To: tutor@python.org > From: __pete...@web.de > Date: Tue, 26 Apr 2016 14:13:56 +0200 > Subject: Re: [Tutor] Using a dictionary to map functions > > Colby Christensen wrote: > > > templist = [] > > pt_table = {} > > cmd_table = {5:"store_point", 19: "line_line_int"} > > As Alan says, the values should be functions rather than function names. > You could use string keys to save both the re.search() check and the > conversion to integer. > > > count = 0 > > > > for line in infile: > > #print line > > line = line.rstrip() > > if re.search('^[0-9]+', line): > > a = line.split() > > templist.append(a) > > > > for line in templist: > > #use dictionary to call and pass arguments to function > > You could put parsing and evaluation into the same loop, and avoid the > temporary list: > > cmd_table = {"5": store_point, ...} > for line in infile: > args = line.split() > cmd = args.pop(0) # remove the first item from args > if cmd in cmd_table: > func = cmd_table[cmd] > func(*args) # see below > else: > # optional, but may help with debugging > print("Command {!r} not recognized. " > "Skipping line {!r}.".format(cmd, line), file=sys.stderr) > > > Given a list 'args' with N items the expression > > func(*args) > > is equivalent to > > func(args[0], args[1], ..., args[N-1]) > > e. g. > > foo = ["one", "two"] > bar(*foo) > > passes the same arguments as > > bar("one", "two") > > > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Using a dictionary to map functions
Thank you for your input. You have given me some more to consider. > Date: Tue, 26 Apr 2016 22:17:53 +1000 > From: st...@pearwood.info > To: tutor@python.org > Subject: Re: [Tutor] Using a dictionary to map functions > > Hi Colby, and welcome! > > On Tue, Apr 26, 2016 at 12:30:38AM -0400, Colby Christensen wrote: > > > try: > > infile = open(raw_input("Enter input file name; name.txt:"),'r') > > except: > > print "Invalid filename" > > exit() > > I'm afraid that code is misleading: your error message lies. > > It may not be an "invalid filename". It could be any of the following: > > - an invalid file name (a file name prohibited by the operating system); > - a valid file name that just doesn't exist; > - a valid file name that you don't have permission to access; > - a valid file name that you can access, but a disk error occurred; > - a valid file name on a network drive, but a network error occurred; > > and probably more. There are few things more frustrating than dealing > with programs that lie to you: > > "What do you mean, invalid filename? The file is right there, I > can see it! How can this stupid program not find it? I've tried > a dozen times, double and triple checked that the file name is > correct, and it still says the file is invalid." > > Because the real error is *permission denied*, not invalid file name. > > Python spends a lot of effort to give detailed and useful error messages > when an error occurs. For example, if you try to open a file that > doesn't exist, Python reports: > > IOError: [Errno 2] No such file or directory > > and tells you the name of the file that you tried to open. If you don't > have permission to access it, it reports: > > IOError: [Errno 13] Permission denied > > and again reports exactly what went wrong. > > Python provides you with a detailed error message telling you exactly > what went wrong, and you throw that away, replacing it with a generic > message which will be wrong more often than right. Please don't do that > -- trust me, you will come to regret it. > > In this case, the right way to deal with errors opening the file is... > not to deal with them at all. Instead of this: > > try: > infile = open(raw_input("Enter input file name; name.txt:"),'r') > except: > print "Invalid filename" > exit() > > just write this: > > infile = open(raw_input("Enter input file name; name.txt:"),'r') > > (There are alternatives that are even better, but you probably haven't > learned about them yet.) > > > > -- > Steve > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Study Tips
I completely agree with what's been said. I also have used online learning sites like Coursera, Udacity and Lynda. There's something about being able see, hear and do that clicks for me. Good Luck Colby > From: david.r...@gmail.com > Date: Mon, 30 May 2016 18:07:57 -0500 > To: tutor@python.org > Subject: Re: [Tutor] Study Tips > > * Alan Gauld via Tutor [2016-05-30 22:11]: >> On 30/05/16 06:45, Steve Lett wrote: >> >> write code., lots of it. >> >> Don't just settle for the examples/exercises in your book. >> Use them as a start but extend them. Add extra features. >> Change the output format or the sort order. >> Combine examples to make bigger programs. >> >> Writing code means making mistakes and, in finding the solution, >> you learn far more than from just reading code. > > And a corollary to this: have a purpose for why you are writing it. > > Learning code for the sake of learning it will get old quickly. You will get a > lot further if you are trying to solve a problem that you care about. Think of > something you would like to automate, or calculate, or process. Do you have > data you would like to analyze? As you learn different elements and apply them > to a practical use that does something for you, it will be more satisfying and > more likely to stick in your brain. > > -- > David Rock > da...@graniteweb.com > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] iterators
I'm sure this is something simple but I'm missing it. When I check the statement with two values, the if statement works. However, for the statement with one value I get an error. keycode = event.GetKeyCode() if keycode in (13, 370): self.enter() elif keycode in (43, 388): self.add() elif keycode in (45, 390): self.sub() elif keycode in (42, 387): self.mult() elif keycode in (47, 392): self.div() elif keycode in (27): self.clear_all() elif keycode in (67, 99): self.display.SetValue('') else: event.Skip()This is the error message. Traceback (most recent call last): File "/home/colby/Calculator/Calculator_betaV3.py", line 110, in OnKeyPress elif keycode in (27): TypeError: argument of type 'int' is not iterable I then tried using elif keycode == 27: but this statement didn't work. I'm pretty sure it's something simple that I've overlooked due to my inexperience. Thanks in advance. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] data storage question
I'm a novice programmer. I have a decent understanding of algorithms but I don't have a lot of computer science/software engineering experience. As a way to help me learn, I've begun a coordinate geometry program similar to the COGO program developed years ago at MIT. Currently, I store the points in a dictionary in the format point_number : [North, East]. I eventually will add a Z component to the points and possibly a description after I get enough of the horizontal geometry worked through. I would like to be able to save the point table so that I can have multiple projects. My main python script is below. It reads in a text file that contains commands to create/calculate the location of the various points. My question is what is a good method to store the point data outside of python? I eventually will also add the capability to define a baseline that consists of multiple points with some attributes to define relative locations along the baseline (stationing). I use enthought canopy express with python 2.7.11 on windows 10 64 bit. """ Coordinate geometry program """ import sys from store_point import store_point from clear_points import clear_points from dump_points import dump_points from redefine import redefine from dist import dist from locate_azimuth import locate_azimuth from locate_bearing import locate_bearing from locate_line import locate_line from line_line_int import line_line_int from parallel_line import parallel_line from arc_line_pts import arc_line_pts from divide_line import divide_line try: infile = open(raw_input("Enter input file name; name.txt:"),'r') except: print "Invalid filename" exit() pt_table = {} cmd_table = {"5":store_point, "7":clear_points, "8":dump_points, "9":redefine, "10":dist, "11":locate_azimuth, "12":locate_bearing, "15":locate_line, "18":parallel_line, "19":line_line_int, "22":arc_line_pts, "40":divide_line} count = 0 for line in infile: #print line args = line.split() cmd = args.pop(0) if cmd in cmd_table: func = cmd_table[cmd] func(pt_table, *args) infile.close() Thanks, Colby ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] data storage question
> Date: Tue, 2 Aug 2016 12:14:04 +1000 > From: st...@pearwood.info > To: tutor@python.org > Subject: Re: [Tutor] data storage question > > On Mon, Aug 01, 2016 at 04:47:32PM -0400, Colby Christensen wrote: > >> I'm a novice programmer. I have a decent understanding of algorithms >> but I don't have a lot of computer science/software engineering >> experience. As a way to help me learn, I've begun a coordinate >> geometry program similar to the COGO program developed years ago at >> MIT. Currently, I store the points in a dictionary in the format >> point_number : [North, East]. I eventually will add a Z component to >> the points and possibly a description after I get enough of the >> horizontal geometry worked through. I would like to be able to save >> the point table so that I can have multiple projects. > > For external storage, you have lots of options. Two very common or > popular suitable standards are JSON or PList. > > Suppose you have a point table: > > pt_table = {25: [30.1, 42.5, 2.8, 'The Shire'], > 37: [17.2, 67.2, 11.6, 'Mt Doom'], > 84: [124.0, 93.8, 65.2, 'Rivendell'], > } > > I can save that table out to a JSON file, then read it back in, like > this: > > py> import json > py> with open('/tmp/data.json', 'w') as f: # save to table to disk > ... json.dump(pt_table, f) > ... > py> with open('/tmp/data.json', 'r') as f: # read it back in > ... new_table = json.load(f) > ... > py> print new_table > {u'25': [30.1, 42.5, 2.8, u'The Shire'], u'37': [17.2, 67.2, 11.6, u'Mt > Doom'], u'84': [124.0, 93.8, 65.2, u'Rivendell']} > > > You'll see that the JSON format has made two changes to the point table: > > (1) All strings are Unicode strings instead of "byte strings" (sometimes > called "ASCII strings"). > > (2) The keys were numbers (25, 37, 84) but have now been turned into > Unicode strings too. Based on both replies I got, JSON is what I will use. I do need the keys in the dictionary to be numerals, specifically they are integers. I believe after I load a stored pt_table, I can use this script to convert the keys back to integers. pt_table = dict((int(key), value) for key, value in pt_table.items()) Please correct me if there is something wrong with that or if there's something else I should now about converting the keys to ints after reading the stored data. Thanks for your input! > > We can advise you how to deal with these changes. Nevertheless, JSON is > probably the most common standard used today, and you can see how easy > the writing and reading of the data is. > > Here is an alternative: Plists. Like JSON, Plist requires the keys to be > strings, but unlike JSON, it won't convert them for you. So you have to > use strings in the first place, or write a quick converter: > > py> pt_table = dict((str(key), value) for key, value in > pt_table.items()) > py> print pt_table > {'25': [30.1, 42.5, 2.8, 'The Shire'], '37': [17.2, 67.2, 11.6, 'Mt > Doom'], '84': [124.0, 93.8, 65.2, 'Rivendell']} > > > Notice that now the keys (which were numbers) are now strings. Now we > can write to a plist, and read it back: > > py> plistlib.writePlist(pt_table, '/tmp/data.plist') > py> new_table = plistlib.readPlist('/tmp/data.plist') > py> new_table == pt_table > True > > > Again, if you need to work with numeric keys, there are ways to work > around that. > > If anything is unclear, please feel free to ask questions on the mailing > list, and somebody will try to answer them. > > > -- > Steve > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor