473,378 Members | 1,354 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

Re-thinking my if-thens - a software engineering question

Ok, I have a module called textgen.py. The point of this module is to
generate a csv file from an array of dictionaries. As I iterate through
each dictionary, I "massage" the dictionary values before writing them
out to csv. Now, for one dictionary entry, I have the following code:

if dict_key == 'PCN':
fields = dict_val.split("/")
mo = re.match( '(\w{2})(\d{2})(\d{2})' , fields[1] )
if mo:
dict_val = "%s/%s%s/%s" % (fields[0], mo.group(1), mo.group(3),
fields[2][1:])
else:
dict_val = dict_val

Ok, so now here is what has happened. This code was based on the
assumption that dict_val would have 2 forward slashes in it. It turns
out that I need to follow a different process of massaging when no
slashes are present. A naive solution would be something like:

if dict_key == 'PCN':
fields = dict_val.split("/")
if fields == 3:
dict_val = pcn_three(fields) # where pcn_three
is the code above
else:
# new logic

But I am wondering if I should abstract the flow of control into a
class or something.

Ideas welcome.

Jan 24 '07 #1
3 1038
metaperl a écrit :
Ok, I have a module called textgen.py. The point of this module is to
generate a csv file from an array of dictionaries.
Err... You know there's a csv module in the stdlib, don't you ?
As I iterate through
each dictionary, I "massage" the dictionary values before writing them
out to csv. Now, for one dictionary entry, I have the following code:

if dict_key == 'PCN':
fields = dict_val.split("/")
mo = re.match( '(\w{2})(\d{2})(\d{2})' , fields[1] )
if mo:
dict_val = "%s/%s%s/%s" % (fields[0], mo.group(1), mo.group(3),
fields[2][1:])
else:
dict_val = dict_val
FWIW, you could as well skip this else clause
Ok, so now here is what has happened. This code was based on the
assumption that dict_val would have 2 forward slashes in it. It turns
out that I need to follow a different process of massaging when no
slashes are present. A naive solution would be something like:

if dict_key == 'PCN':
fields = dict_val.split("/")
if fields == 3:
if len(fields) == 3:
dict_val = pcn_three(fields) # where pcn_three
is the code above
else:
# new logic

But I am wondering if I should abstract the flow of control into a
class or something.
Depends... If your code is starting to smell, then yes, it's probably
time to refactor a bit. Note that you don't necessarily needs OO to
clean up a mess. Python functions are objects on their own, so you can
use them like any other variable. A common idiom is to use a dict as a
dispatch table:

def test1(arg):
print "test1", arg

def test2(arg):
print "test2", arg

def test3(arg):
print "test3", arg

dispatch = {
'TEST_ONE': test1,
'TEST_TWO': test2,
'TEST_THREE': test3,
}
default = lambda arg: arg

#...

func = dispatch(dict_key)
dict_val = func(fields)

And using lambdas you can even come close to Perl !-)

dispatch = {
'PCN' : lambda arg: \
(new_logic, pcn_three)[arg.count('/') == 2](arg.split('/')),
'XXX' : code_here,
...
}

Or you could write some "dispatcher helper" functions, like:

def dispatch_on_arg_count(default, *funcs):
def _dispatcher(*args):
try:
func = funcs[len(args)]
except IndexError:
func =default
return func(*args)
return _dispatcher

dispatch = {
'PCN': dispatch_on_arg_count(
default,
default,
pcn_one,
pcn_two,
pcn_three
),
'XXX' : code_here,
}
Or you could check Philip Eby's dispatch package...

And of course, since Python classes are themselves callables (no 'new'
operator, you just call the class to instanciate it), and instances can
be callable too (just define a __call__(self, ...) method), you can
throw OO in the mix too !-)

Now weither it will make your code more readable is another question...
Ideas welcome.
HTH
Jan 24 '07 #2
On 2007-01-24, metaperl <me******@gmail.comwrote:
if dict_key == 'PCN':
fields = dict_val.split("/")
mo = re.match( '(\w{2})(\d{2})(\d{2})' , fields[1] )
if mo:
dict_val = "%s/%s%s/%s" % (fields[0], mo.group(1), mo.group(3),
fields[2][1:])
else:
dict_val = dict_val

Ok, so now here is what has happened. This code was based on
the assumption that dict_val would have 2 forward slashes in
it. It turns out that I need to follow a different process of
massaging when no slashes are present. A naive solution would
be something like:

if dict_key == 'PCN':
fields = dict_val.split("/")
if fields == 3:
dict_val = pcn_three(fields) # where pcn_three
is the code above
else:
# new logic

But I am wondering if I should abstract the flow of control
into a class or something.
This is what I do in Python when a new requirement pops up:

1. Write the simplest/first thing that comes to mind to fix it.
1. a) Am I done? Probably. But maybe not.
2. Now I examine what I've written to see the lay of the code.
Only after writing something new once do I usually have
enough information to write it better. In other words,
writing the code organizes my thoughts. I usually have to
fully understand something, even to get a kludgey solution to
work. The Kludgey solution informs the design of something
better.
2. a) Got to 1. a)

In the case above, I've tried to figure out what you're
specifically doing, and failed. So I don't have more specific
advice.

--
Neil Cerutti
Jan 24 '07 #3
On Wed, 24 Jan 2007 11:51:27 -0800, metaperl wrote:
Ok, I have a module called textgen.py. The point of this module is to
generate a csv file from an array of dictionaries.
You probably should use the csv module to do the grunt work, leaving your
module just to massage the dicts into a form that csv can handle.

As I iterate through
each dictionary, I "massage" the dictionary values before writing them
out to csv. Now, for one dictionary entry, I have the following code:

if dict_key == 'PCN':
fields = dict_val.split("/")
mo = re.match( '(\w{2})(\d{2})(\d{2})' , fields[1] )
if mo:
dict_val = "%s/%s%s/%s" % (fields[0], mo.group(1), mo.group(3),
fields[2][1:])
else:
dict_val = dict_val
Your indentation seems very inconsistent -- the lines starting with
"fields = ..." and "mo = ..." should have the same indentation.

The line "dict_val = dict_val" is a no-op. You could just as easily write
that as "pass", or even better, leave out the entire else clause.

Reading between the lines, it sounds like you have a mass of if...elif
clauses, like this:

if dict_key == 'PCN':
# some processing
elif dict_key == 'NCP':
# some different processing
elif ...
# blah blah blah
else:
# default processing
This is an excellent candidate for dictionary-based dispatching. First,
write a function for each processing block:

def process_PCN(value):
# do stuff to value
return result

and then create a dispatch table:

dispatcher = {"PCN": process_PCN, "NCP": process_NCP, ...}

Now your huge if...elif block becomes one line:

# no default processing
dispatcher[dict_key](dict_value)

# with default processing
dispatcher.get(dict_key, process_default)(dict_value)

Ok, so now here is what has happened. This code was based on the
assumption that dict_val would have 2 forward slashes in it. It turns
out that I need to follow a different process of massaging when no
slashes are present. A naive solution would be something like:

if dict_key == 'PCN':
fields = dict_val.split("/")
if fields == 3:
That can't possibly work. fields is a list, not an integer.

I think you want if len(fields) == 3.
dict_val = pcn_three(fields) # where pcn_three
is the code above
else:
# new logic

But I am wondering if I should abstract the flow of control into a
class or something.
Nope. Abstract it into functions.

--
Steven.

Jan 24 '07 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: joost | last post by:
Hello, I'm kind of new to mySQL but more used to Sybase/PHP What is illegal about this query or can i not use combined query's in mySQL? DELETE FROM manufacturers WHERE manufacturers_id ...
2
by: sky2070 | last post by:
i have two file with jobapp.html calling jobapp_action.php <HTML> <!-- jobapp.html --> <BODY> <H1>Phop's Bicycles Job Application</H1> <P>Are you looking for an exciting career in the world of...
1
by: Clarice Almeida Hughes | last post by:
tenho um index onde tenho o link pro arq css, como sao visualizados pelo include todas as paginas aderem ao css linkado no index. so q eu preciso de alguns links com outras cores no css, o q devo...
6
by: Chris Krasnichuk | last post by:
Hello every one, Does anyone know how to make php work on your computer? please reply I need help Chris
2
by: Frans Schmidt | last post by:
I want to make a new database with several tables, so I did the following: <?php CREATE DATABASE bedrijf; CREATE TABLE werknemers (voornaam varchar(15), achternaam varchar(20), leeftijd...
2
by: sky2070 | last post by:
Parse error: parse error, unexpected T_OBJECT_OPERATOR, expecting ')' in c:\inetpub\wwwroot\session.php on line 19 can anyone tell me what is wrong with this code??? <? // Define the Session...
5
by: lawrence | last post by:
I've waited 6 weeks for an answer to my other question and still no luck, so let me rephrase the question. I know I can do this: <form method="post" action="$self"> <input type="text"...
1
by: Randell D. | last post by:
Folks, I use Apache/PHP with Webazlier to view the log files. I get a number of user agents (web browsers?) that visit the website - For example: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT...
5
by: Dan Foster | last post by:
Hi, this is my first post to this ng, so please be nice to me! :) ok we're running redhat 7.2 with apache 1.3.26. I had/have php 4.2.1, i need to use some cms package that needs 4.2.2 or...
1
by: lawrence | last post by:
I just switched error_reporting to ALL so I could debug my site. I got a huge page full of errors. One of the most common was that in my arrays I'm using undefined offsets and indexes. These still...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.