Need advice on subclassing code
Hi -- We have some code that returns an object of a different class, depending on some parameters. For example: if param x is 1 and y is 1, we make an object of class C_1_1. if param x is 1 and y is 2, we make an object of class C_1_2. C_1_1 and C_1_2 share a common C ancestor, and in practice may be identical, but theoretically, could have the same function name with two different implementations underneath. We have a file where all the C_X_Y classes are defined. It looks sort of like this: class C_1_1(C): Creates a x=1 and y=1 class def __init__(self): C.__init__(self, 1, 1) class C_1_2(C): Creates a x=1 and y=2 class def __init__(self): C.__init__(self, 1, 2) 99% of the specific classes do the exact same thing. For a tiny few, the class definition looks like this: class C_3_5(C): Creates a x=3, y=5 class. def __init__(self): C.__init__(self, 3, 5) def foo(self): Redefine the default C.foo() function. return 99 The reason for this is that we want to allow different classes to do non-standard behavior. In practice, however, it turns out that most of the time, we don't need anything special. Is this the best solution? Is there some way of doing a default vs. non-default deal, without having to manually hardcode all the different possible subclasses? Thanks for the help. -- A better way of running series of SAS programs: http://overlook.homelinux.net/wilsonwiki/SasAndMakefiles -- http://mail.python.org/mailman/listinfo/python-list
Re: Need advice on subclassing code
Would the approach of using a switch to decide to instatite which class good for you, like: py class C: py. name = 'C' py. py class D: py. name = 'D' py. py switch = { (1, 1): C, (1,2): D } py x = 1 py y = 2 py c = switch[(x,y)]() py print c.name D py -- http://mail.python.org/mailman/listinfo/python-list
Re: Need advice on subclassing code
Rusty Shackleford wrote: Hi -- We have some code that returns an object of a different class, depending on some parameters. For example: if param x is 1 and y is 1, we make an object of class C_1_1. if param x is 1 and y is 2, we make an object of class C_1_2. C_1_1 and C_1_2 share a common C ancestor, and in practice may be identical, but theoretically, could have the same function name with two different implementations underneath. We have a file where all the C_X_Y classes are defined. It looks sort of like this: (snip) 99% of the specific classes do the exact same thing. For a tiny few, the class definition looks like this: (snip same code with minor differences...) The reason for this is that we want to allow different classes to do non-standard behavior. In practice, however, it turns out that most of the time, we don't need anything special. Is this the best solution? No, of course - but I guess you knew it already !-) Is there some way of doing a default vs. non-default deal, without having to manually hardcode all the different possible subclasses? Here are the pieces of the puzzle: - A dict is usually the best choice for lookups. - A tuple can serve as key for a dict. - A (reference to) a class object can be stored in a dict (or the name of the class, as a string). - the get() method of a dict allow for an optional default value to be use if the requested key is not found And here's a first go: def get_object(x, y): specials = { (1, 2): C_1_2, (33, 42): C_33_42, } # assume class C is the default class klass = specials.get((x, y), C) return klass() Now if you store the class names as strings, ie : specials = { (1, 2): C_1_2, (33, 42): C_33_42, } you can use a config file (ini, XML, Yaml, or even plain old python) to store the 'specials' mapping and the default class name, and have get_object() read from that config file. The trick is to get the class from the class's name, which is solved with getattr(): def get_object(x, y): specials = { (1, 2): C_1_2, (33, 42): C_33_42, } # assume class 'C' is the default class class_name = specials.get((x, y), C) # from class name to class: klass = getattr(module_where_classes_live, class_name) return klass() I think you should be able to solve your problem with this. A last thing: the name of the module storing the classes can also be stored in a conf file. Use __import__() to get the module object from it's name. HTH -- bruno desthuilliers python -c print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for p in '[EMAIL PROTECTED]'.split('@')]) -- http://mail.python.org/mailman/listinfo/python-list
Re: Need advice on subclassing code
Rusty Shackleford wrote: Hi -- We have some code that returns an object of a different class, depending on some parameters. For example: if param x is 1 and y is 1, we make an object of class C_1_1. if param x is 1 and y is 2, we make an object of class C_1_2. C_1_1 and C_1_2 share a common C ancestor, and in practice may be identical, but theoretically, could have the same function name with two different implementations underneath. We have a file where all the C_X_Y classes are defined. Is this the best solution? Is there some way of doing a default vs. non-default deal, without having to manually hardcode all the different possible subclasses? How are you instantiating the correct class? You should be able to provide a default behaviour. For example if the classes are all defined in module C you could have a factory like this: import C def makeC(x, y): subtype = 'C_%d_%d' % (x, y) cls = getattr(C, subtype, C.C) return cls(x, y) Then in module C just define the subtypes you need to specialize; all other values of x and y will get the base class C.C. Kent -- http://mail.python.org/mailman/listinfo/python-list
Re: Need advice on subclassing code
Kent Johnson wrote: Rusty Shackleford wrote: ... C_1_1 and C_1_2 share a common C ancestor, and in practice may be identical, but theoretically, could have the same function name with two different implementations underneath. ... How are you instantiating the correct class? You should be able to provide a default behaviour. For example if the classes are all defined in module C you could have a factory like this: import C def makeC(x, y): subtype = 'C_%d_%d' % (x, y) cls = getattr(C, subtype, C.C) return cls(x, y) Then in module C just define the subtypes you need to specialize; all other values of x and y will get the base class C.C. Kent Or, if you actually want different classes for each set of parameters (say for debugging or introspection), you could compose the default ones on the fly: import C def makeC(x, y): subtype = 'C_%d_%d' % (x, y) cls = getattr(C, subtype, None) if not cls: # No specialized class found, so compose a default # This requires C.C to be a new-style class cls = type(subtype, (C.C,), {__autogenerated__: True}) return cls(x, y) Michael -- http://mail.python.org/mailman/listinfo/python-list
Advice on this code
If this is the wrong place to post this, please advise better place. Otherwise, I have created the following python program and it works. Running on XP. I think I am now at that stage of learning python where I'm not quit a newbie and I am not really knowlegable. I know just enough to be dangerous and can really screw things up. Any suggestion on improving would be greatly appreciated. However my real question is I would like to run this program under a GUI interface and have the GUI have a start button to start this process running and the messages in the program placed in a multiline text field which when the stop button is pressed the text field would be copied to a logfile and the program exited. Below this program is the skeleton of the python gui program using wxPython (the gui program also works). I have a metal block on merging the two programs. I think part of the problem is the first is not really using object except for the database access and the gui is all object. Second, I'am getting all wrapped up with variable, object, etc scope issues. ** FIRST PROGRAM ** This program is an attempt to modularize the lmsface program. I also will try to document the logic of the program import os import glob import time import re import shutil from win32com.client import Dispatch from ADOConstants import * def cvtfiles(): cvtfiles is the driving routine for converting and/or changing the V1sta quote flat file being sent by QuotePro to Unique. The function gets a list of the files in the FTP directory path and opens each file one at a time and copies the data (with any necessary changes or additions to the output directory where V1sta's interface program picks it up and converts it into the V1sta's SQL quote files. Individual functions are called to process different segments of the flat file record. global novehflag novehflag = False global ofile list1 = glob.glob('*.dat') for f1 in list1: if f1.lower().startswith(unq): if f1.lower().rfind(void) 0: print f1 + is being processed now. input1 = open(cfdir + f1, 'r') output = open(ctdir + f1, 'w+') ifile = input1.readline() output.write(wrkpol(ifile)) output.write(wrkdrv(ifile,1406,6)) output.write(wrkveh(ifile,1784,6)) if novehflag == True: input1.close() output.close() shutil.copy2(cfdir + f1,cfdir + 'voided\\' + f1) os.remove(cfdir + f1) os.remove(ctdir + f1) novehflag = False else: output.write(wrkmisc(ifile,2582)) output.write(wrkviol(ifile,2774,16)) output.write(wrkaccid(ifile,3270,16)) output.write(wrkmisc2(ifile,3638)) output.write(wrkcov(ifile,3666,6)) output.write(wrklp(ifile,4314,7)) output.write(wrkai(ifile,4909,6)) output.write(wrkmisc3(ifile,5707)) output.close() input1.close() shutil.copy2(cfdir + f1,cfdir + 'processed\\' + f1) os.remove(cfdir + f1) print f1 + has been processed. else: shutil.copy2(cfdir + f1,cfdir + 'voided\\' + f1) os.remove(cfdir + f1) print f1 + is a VOIDED Quote from QuotePro. else: pass def wrkpol(ifile): wrkpol functions converts the policy information segment. Currently the only changes made to the policy segment is to change Current-Carrier-Type to 0 if it contains a 0 or 1 or change Current-Carrier-Type to 1 if it contains a 2 polwrk = '' polwrk = polwrk + ifile[0:577] polwrk = polwrk + ' ' polwrk = polwrk + ifile[588:653] if ifile[653:654] in ['0','1']: polwrk = polwrk + '0' else: polwrk = polwrk + '1' polwrk = polwrk + ifile[654:974] maxcnt = 6 cnt = 0 strstart = 974 while cnt maxcnt: if ifile[strstart + 41:strstart + 52] == ' ': polwrk = polwrk + ifile[strstart:strstart + 72] else: polwrk = polwrk + ifile[strstart:strstart + 41] polwrk = polwrk + ' ' polwrk = polwrk + ifile[strstart + 52:strstart + 72] strstart += 72 cnt += 1 return polwrk def wrkdrv(ifile,strstart,maxcnt): wrkdrv function at this point just moves the data as is. The driver segment is an occurs 6 cnt = 0 drvwrk = '' while cnt maxcnt: if ifile[strstart + 23:strstart + 31] '': drvwrk = drvwrk + ifile[strstart:strstart + 63] else: drvwrk = drvwrk + ifile[strstart:strstart + 63] strstart += 63
Re: Advice on this code
output.write(wrkmisc(ifile,2582)) output.write(wrkviol(ifile,2774,16)) output.write(wrkaccid(ifile,3270,16)) output.write(wrkmisc2(ifile,3638)) output.write(wrkcov(ifile,3666,6)) output.write(wrklp(ifile,4314,7)) output.write(wrkai(ifile,4909,6)) output.write(wrkmisc3(ifile,5707)) Ummm... yuck? First of all, this program is very hard to understand to somebody who hasn't written it. ALthough I've never heard of Quote Vista so maybe that's the problem. Anyway, if you want to integrate the first program with the second GUI program, you should convert the first program into a set of functions that can be called to do everything the first program does. So basically, take the first program and put everything that's not already in a function into one. That is, all the code that is at zero indentation, starting with creating the oConn connection, should be moved into functions. You can also write a big-mama function that calls those functions in such a way that it would have the exact same overall effect as the original script before you moved the code into functions. You can call this big-mama function 'main'. Now you can integrate it with the GUI program by importing the first module from the GUI program and binding the functions to the appropriate buttons. For example you could bind main to the Start button you described. Also, in the first file, you can put the following lines at the bottom, and it will allow you to run the original script directly to achieve the same result, while still being able to import it into a second program and re-use just the functions. if __name__ == '__main__': main() -- http://mail.python.org/mailman/listinfo/python-list