concise code (beginner)

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Thu Sep 6 15:18:12 CEST 2007


On Thu, 06 Sep 2007 15:44:57 +1000, bambam wrote:

> First, thank you.
> 
> All of the suggestions match what we want to do much better than what we
> are doing. We have a script, written in python, which is doing testing.
> But the python script doesn't look anything like the test script,
> because the python script is written in python, and the test script is a
> series of instrument command macros.
> 
> By putting the script sequence into a collection that is separate from
> the python code, we will get script list that general engineering will
> find much easier to understand:
> 
> 
> def script(self)
>     def a0010(): global self; self.power_on([self.dev]); 
>     def a0020(): global self; self.dev.addLog([self.name, ' started']);
>     def a0030(): global self; self.resetMinuteReg([self.dev]); 
>     def a0040(): global self; self.disablePLmessages([self.dev]); 
>     def a0050(): global self; self.dev.testH.writePLram((PL.BCAL12<<8));

That's rather hideous code, and I'm not sure I understand what it's 
supposed to do. As far as I can tell, you have a function called "script" 
which takes a single argument. It then defines five functions, throws 
them away, and returns None.

"self" is not a reserved word in Python (although perhaps it should 
be...) but it has a VERY strong convention for when to use it: when 
defining instance methods, it is used for the automatically-supplied 
instance argument. The above functions look like they were written by 
somebody who has just copied some methods from another piece of code 
without understanding what they were seeing. (Sorry.)


> Most of these won't generate exceptions: exceptions are expected only on
> the calculations following the reads, but of course the problem is that
> the exceptions are unexpected... 

I don't think so. I think they are expected. You say so yourself.


> The semi-colons were already there,

Fine. Time to remove them.


> I've just stripped out the loops and exception handlers. The original
> code is a mixture of functions with internal and external [dev] loops.
> 
> Because of the sequence names, I have a choice of using generated call
> names (James), or a static list of some sort.
> 
> Other possibilities might be
> 1) Using dir(script) to get a list of line functions 2) Using
> frame.f_lineno instead of line functions 3) Use an expression list
> instead of line functions 4) Multiple script objects with yield on each
> line.

My brain hurts.


> The devices are in a list, and are removed by using pop(i). This messes
> up the loop iteration, so it is actually done by setting a flag on each
> device in the exception handler, with ANOTHER loop after each
> write/read/calculate sequence. I left that out also because I wanted to
> show the intended logic.

Try something like this: define a module holding the device functions. 
Rather than have the functions access a global variable, which is almost 
always a bad thing to do, have them take a single argument.

# module device

__all__ = [a0010, a002, a0030, a0040, a0050]

def a0010(obj):
    obj.power_on([obj.dev])
def a0020(obj):
    obj.dev.addLog([obj.name, ' started'])
def a0030(obj):
    obj.resetMinuteReg([obj.dev])
def a0040(obj):
    obj.disablePLmessages([obj.dev])
def a0050(obj):
    obj.dev.testH.writePLram((PL.BCAL12<<8))


Now define a second module to call those functions.

# module tester

import device
passed = device.__all__[:] # a copy of the list
some_object = Something() # I have no idea what this should be...

for function in device.__all__:
    try:
        function(some_object)
    except Exception, e:
        print e
        passed.remove(function)

print "The following functions passed:"
for function in passed:
    print function


And then I suggest you spend some time reading up about doc tests and 
unit tests.

Hope this helps,



-- 
Steven.




More information about the Python-list mailing list