Python help
    Cole Tuininga 
    colet at code-energy.com
       
    Thu Feb  5 18:14:03 EST 2004
    
    
  
First things first - bravo to you Erik for offering up some more general
(and IMHO) quite correct advice on approaching python scripts rather
than giving "quickie" advice like I did.
That said, there are two things in your post I wanted to respond to.
> A dict is a more straightforward way to use a 
> simple struct-like object, as Cole suggested.  The overhead of using 
> a class over a dict is not very significant, though, since Python's 
> classes are really just customized dict types behind the scenes.  
This may appear to be true for simple situations.  However, take a look
at http://www.bagley.org/~doug/shootout/bench/objinst/  This is
admittedly old data, using python 2.2, but should still give a general
idea.  Python is quite slow for object instantiation with large numbers
of objects.  Far less true for dictionaries.  
But it all depends on what your needs are, of course.
> But you don't need to know that.  And because dicts are used so 
> extensively in Python, they are ultra-opt!
> imized by the Python developers.  
Very true.  Paul - when you get a little more used to all things
pythonic, check out the setdefault and getdefault methods for
dictionaries.  Very slick.
[snip]
> #!/sw/bin/python
> 
> import os, sys
> 
> 
> class Group:
Next point - the following line has a bug:
    
>     def __init__(self, name="", gid="", members=[]):
This is a very subtle one.  The point is that in a method definition
within an object, you never want to assign a mutable type (namely, the
empty list) to an argument.  Weird behavior will occur.
Example:
#!/usr/bin/python
class bob:
	def __init__( self, list_ref = [] ):
		self.list_ref = list_ref
	def printListRef( self ):
		print str( self.list_ref )
b1 = bob()
b2 = bob()
b1.list_ref.append( "data" )
print "b1:",
b1.printListRef()
print "b2:",
b2.printListRef()
# End of script
When this is run, you will see:
./test.py
b1: ['data']
b2: ['data']
Hey, wait a minute?  We only assigned "data" into b1!  Why did this
happen?  The answer is again due to python's heavy use of references.
When you instantiate an object, you are copying a lot of items from the
class definition - including references to arguments.  
When I do b1 = bob(), I'm getting a reference to that empty list defined
in the __init__ method's signature.  When I do b2 = bob(), I'm getting a
reference to the exact *same* list.  So from then on, any instantiated
object will be sharing that list.
Instead, what you want is something like this:
	def __init__(self, name="", gid="", members=None):
		self.name = name
		self.gid = gid
		if members is None:
			self.members = []
		else:
			self.members = members
>         self.name = name
>         self.gid = gid
>         self.members = members
>         
>     def setValuesFromFileLine(self, line):
Can I recommend changing the following to
	record = line.strip().split(":")
>         record = line.split(":")
>         self.name = record[0]
>         self.gid = record[2]
>         self.members = record[3].split(",")
>         
>     def toLdifFormat(self):
>         self.members.sort()
>         output = ",".join(members)
>         return "%s:%s:%s" % (self.name, self.gid, output)
> 
> 
> 
> def main(args=sys.argv):
One point about the above line - if you're testing from a python prompt,
you'll need to pass your arguments in as a list.  So for instance,
>>> main( ["/etc/group"] )
rather than just
>>> main ( "/etc/group" )
Otherwise, the next line would generate some rather peculiar behavior.
>     f = file(args[1], "r")
Also, below, it looks like you started out wanting to use a list, but
switched to a dict:
>     groups = []
>     
>     for line in f:
>         g = Group()
>         g.setValuesFromFileLine(line)
>         groups_dict[g.name] = g
>     
>     f.close()
>     
>     for group in groups:
>         print group.toLdifFormat()
Instead, to pick a list which seems reasonable appropriate to me:
	groups = []
	for line in f:
		g = Group()
		g.setValuesFromFileLine( line )
		groups.append( g )
	f.close()
	for group in groups:
		print group.toLdifFormat()
> if __name__ == "__main__":
>     main()
These items aren't meant as bashing - I know you said you wrote it
without testing.  I'm just trying to clarify.  8)
-- 
"... one of the main causes of the fall of the Roman Empire was that,
 lacking zero, they had no way to indicate successful termination of
 their C programs."  --  Robert Firth
Cole Tuininga
Lead Developer
Code Energy, Inc
colet at code-energy.com
PGP Key ID: 0x43E5755D
    
    
More information about the gnhlug-discuss
mailing list