Procedures

J. Cliff Dyer jcd at sdf.lonestar.org
Tue Jun 23 16:59:50 CEST 2009


Please keep the discussion on-list. (Reply-all, rather than just
replying to me.) 

On Mon, 2009-06-22 at 15:36 -0700, Greg Reyna wrote:
> It's not the error that concerned me.  The fact that there is an 
> error of this type makes clear that there's something wrong with the 
> way the scripts are structured.  I was trying to communicate that I 
> recognized this fact.  Clearly, I was not successful.  Thought I'd 
> try to save bandwidth, too.
> ...
> I had tried running this previously with only one Class header: 
> "LineReader", the others were just defs.  I changed the short defs 
> into sub-classes out of desperation, since I don't understand why the 
> main script is not recognizing functions that are in the same file.
> 
> First is the shell input/output, then "ParseWork.py", the entire text 
> file that contains the scripts.
> 
> Thanks for your interest, Cliff,
> Greg
> ---
> >>>  import ParseWork
> >>>  avar = ParseWork.LineReader()
> >>>  xstring = 'scene 1, pnl 1, 3+8, pnl 2, 1+12, pnl 3, 12, pnl 4, 2+4,'
> >>>  avar.parseLine(xstring)
> Traceback (most recent call last):
>    File "<stdin>", line 1, in <module>
>    File "ParseWork.py", line 13, in parseLine
>      xreturn = advanceSearch(xstring)  #shorten the part of string to 
> be searched
> NameError: global name 'advanceSearch' is not defined
> >>>
> ---
> class LineReader:   
>      def parseLine(self, xstring):
>          global sc_info,scnum,pnlnum,prev_pos,cur_pos
>          sc_info = { 'sc':{0:0}}  #dict to store scene num; pnl num(s), ftge
>          prev_pos = 0
>          cur_pos = xstring.find(',')     #defaults to length of string
>          while xstring.find(',',(prev_pos+1))  !=  -1: 
>              temp = xstring[prev_pos:cur_pos]   #pull out the part btwn commas
>              section = temp.strip()   
>              if section[0:1] == 's':
>                  scnum = int(section[5:])  #get the number(s) off the 
> end of scene block
>                  sc_info['sc',scnum] = scnum  #store scnum-which is 
> both key and value
>                  xreturn = advanceSearch(xstring)  #shorten the part 
> of string to be searched
>                  continue
>              if section[0:1] == 'p':
>                  pnlnum = int(section[3:])
>                  sc_info['sc',scnum,pnlnum] = pnlnum  #store pnlnum & 
> temp value for pnlnum
>                  xreturn = advanceSearch(xstring)  #the return value 
> is to move flow back here
>                  continue
>              if section[0:1] != 's' or 'p':
>                  xnum = section[0:]   #section must contain the footage
>                  if section.find('+'):   #the + exists
>                      ftge = parseFtge(section) 
>                      sc_info['sc',scnum,pnlnum] = ftge  #store ftge in pnlnum
>                      xreturn = advanceSearch(xstring)
>                      continue
>                  else:
>                      ftge = (section/16.0)  #section is frames-convert 
> to decimal
>                      sc_info['sc',scnum,pnlnum] = ftge  #store ftge in pnlnum
>                      xreturn = advanceSearch(xstring)
>                      continue
>          else:
>              print sc_info
> 
> class ContRead(LineReader):           
>      def advanceSearch(xstring):
>          prev_pos = (cur_pos +1) 
>          cur_pos = xstring.find(',',prev_pos)  #find the next comma  
>          return
> 
> class Footage(LineReader):                       
>      def parseFtge(section):
>          xplus = section.find('+')  #find position of '+'
>          xfeet = int(section[0:xplus])
>          xframes = int(section[(xplus + 1):-1])  
>          xframes_d = (xframes/16.0)
>          return (xfeet + xframes_d)
> 
> 


>From what I can see you have no need for classes in your code.  This is
probably what is causing you trouble at the moment, so I would say just
remove them.  

def parse_line(line):
    """splits a line on commas"""
    return line.split(',')

def parse_footer(line):
    """Strips off leading four characters (maybe 'Ftr:'), and then
    parses the rest as above"""
    return parse_line([4:])

That should solve your problem.  Below I illustrate some of how classes
work, in case you are dead set on using them.  Learning Python should
address all of this as well.  I haven't read it, so I can't be more
specific.

To call a method from another method within a class, you need to prefix
it with self.  That looks like this:

class Spam(object):  ## {1}
    def parse_line(self, line):  ## {2}
        return line.split(',')

    def parse_footer(self, line):
        return self.parse_line(line[4:])  ## {3}

# {1} always subclass 'object' to use newstyle classes
# {2} Note that method declarations have an extra first argument, 
#     usually called "self", which refers to your instance of the class.
# {3} "self" finds parse_line within the current class
#     or superclasses of the current class.  Note that self has 
#     moved from inside the parentheses to before the method name.


To call a method from another class you need to instantiate that class
first.

class Spam(object):
    def parse_line(self, line):
        return line.split(',')

class Eggs(object):
    def parse_footer(self, line):
        parser = Spam()
        parser.parse_line(line[4:])  ## {4} 

# {4} The Spam instance "parser" is fed to the method "parse_line" as
#     its first argument (as "self").


If a class subclasses another class (by, e.g., replacing 'object' with
'Spam' in the class declaration of 'Eggs'), then methods in Eggs can
reference methods in Spam using 'self'.

class Spam(object):
    def parse_line(self, line):
        return line.split(',')

class Eggs(Spam):  ## {5}
    def parse_footer(self, line):
        return self.parse_line(line[4:])  ## {6}

# {5} Now Eggs is a subclass of Spam
# {6} "self" looks for a method called parse_line in Eggs, and
#     when it fails to find it, looks in Eggs' superclass, Spam
#     and finds it there.

Hope that helps

Cheers,
Cliff



> >On Mon, 2009-06-22 at 12:13 -0700, Greg Reyna wrote:
> >>  Learning Python (on a Mac), with the massive help of Mark Lutz's
> >>  excellent book, "Learning Python".
> >>
> >>  What I want to do is this:
> >>  I've got a Class Object that begins with a def.  It's designed to be
> >>  fed a string that looks like this:
> >>
> >>  "scene 1, pnl 1, 3+8, pnl 2, 1+12, pnl 3, 12, pnl 4, 2+4,"
> >>
> >>  I'm parsing the string by finding the commas, and pulling out the
> >>  data between them.
> >>  No problem so far (I think...)  The trouble is, there is a place
> >>  where code is repeated:
> >>
> >>  1. Resetting the start & end position and finding the next comma 
> >>in the string.
> >  >
> >
> >Have you looked at the split() method on string objects.  It works kind
> >of like this:
> >
> >>>>  s = "scene 1, pnl 1, 3+8, pnl 2, 1+12, pnl 3, 12, pnl 4, 2+4,"
> >>>>  s.split(",")
> >['scene 1', ' pnl 1', ' 3+8', ' pnl 2', ' 1+12', ' pnl 3', ' 12', ' pnl
> >4', ' 2+4', '']
> >>>>  elements = s.split(",")
> >>>>  elements
> >['scene 1', ' pnl 1', ' 3+8', ' pnl 2', ' 1+12', ' pnl 3', ' 12', ' pnl
> >4', ' 2+4', '']
> >>>>  elements[2]
> >' 3+8'
> >
> >
> >
> >>  In my previous experience (with a non-OOP language), I could create a
> >>  'procedure', which was a separate function.  With a call like:
> >>  var=CallProcedure(arg1,arg2) the flow control would go to the
> >>  procedure, run, then Return back to the main function.
> >>
> >
> >Python doesn't have procedures quite like this.  It has functions (the
> >things starting with "def"), which generally speaking take arguments and
> >return values.  For the most part, you do not want your functions to
> >operate on variables that aren't either defined in the function or
> >passed in as arguments.  That leads to difficult-to-debug code. 
> >
> >
> >>  In Python, when I create a second def in the same file as the first
> >>  it receives a "undefined" error.  I can't figure out how to deal with
> >>  this.  How do I set it up to have my function #1 call my function #2,
> >>  and return?
> >
> >Your problem description is confusing.  First of all, no class starts
> >with 'def'.  They all start with 'class'.  Perhaps you are talking about
> >a module (a python file)? 
> >
> >Also, telling us that you get an undefined error is not particularly
> >helpful.  Every Exception that python raises is accompanied by an
> >extensive stack trace which will help you (or us) debug the problem.  If
> >you don't show us this information, we can't tell you what's going
> >wrong.  It will tell you (in ways that are crystal clear once you have a
> >bit of practice reading them) exactly what went wrong.
> >
> >Can you show your code, as well as the complete error message you are
> >receiving?
> >
> >My suggestions here, are essentially a paraphrasing of Eric Raymond's
> >essay, "How to Ask Smart Questions."  It is freely available on the web,
> >and easily found via google.  I recommend reading that, in order to get
> >the most mileage out this news group.
> >
> >Cheers,
> >Cliff
> 




More information about the Python-list mailing list