Re: [Tutor] MemoryError

2004-12-08 Thread Jeff Shannon
Liam Clarke wrote:
Hi all, 

I'm playing with a file, and attempting to replace a section with a
string, and using the following command -
seg=codeSt[element:endInd+len(endStr]
codeSt=codeSt.replace(seg, hrefString)
At the replace, I get a MemoryError. It's part of a for loop, but it
gives the error the first time around.

I'm not sure why you're getting the MemoryError, but it'd be easier to 
figure out if you posted the entire text of the traceback.

A few other pointers --
You'll probably get better performance if you put all of this code 
inside of a function.  Even if you're only running it once, putting it 
in a function allows the interpreter to do some optimization tricks on 
locals() which can't be done at the module-global level (where you're 
running now).  It's just barely possible that just doing this will 
help with your MemoryError problem.  (You would probably benefit from 
splitting it into multiple functions, actually.  I'd have the code 
that finds text and url values each in their own function, for example.)

Try adding a line in between those two that prints out the value of 
element and endInd, and then check that those numbers really are valid 
indexes into codeSt.  While you're at it, print out hrefString and 
make sure it looks like it's supposed to.

At the start of your program, you have the following:
inp=file("toolkit.txt","r")
codeSt=inp.readlines()
inp.close()
codeSt="".join(codeSt)
Since you're not processing by lines, and are explicitly joining all 
the lines together, why have Python separate them for you?  It would 
be much more efficient to simply use 'codeSt = inp.read()', with no 
need to join() afterwards.  The readlines() method effectively does a 
read() followed by splitting the result into lines; for your purposes, 
there's no point in splitting the lines if you're just going to join() 
them immediately.

Instead of finding the start and end index of the segment you want to 
replace, making a copy of that segment, and then scanning your 
original string to replace that segment with a new chunk, it would 
probably make more sense to simply grab codeSt before the segment and 
after the segment and concatenate them with the new chunk.  Thus, your 
two lines above become

codeSt = codeSt[:element] + hrefString \
 + codeSt[endInd+len(endStr)]
Once again, this would avoid doing the same work twice.
Now, I had imagined that codeSt=codeSt+10 would destroy the old codeSt
in memory and create a new codeSt. Am I right?
Actually, this will probably raise a TypeError (cannot concatenate 
'str' and 'int' objects).  ;)  But yes, rebinding codeSt to a new 
string should allow the old string to be destroyed (if there are no 
other references to it).

Hope that this helps.
Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  [EMAIL PROTECTED]
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] MemoryError

2004-12-08 Thread Jeff Shannon
Liam Clarke wrote:
I'm not sure why you're getting the MemoryError, but it'd be easier to
figure out if you posted the entire text of the traceback.
Traceback: 
Line 39: seg=codeSt[element:endInd+len(endStr]
MemoryError
Hehe. Helpful, no?
Actually, it was the "usual bit about in module" that might *be* 
helpful. ;)  Often, something can be determined by the sequence of 
function calls listed there.  Though I suppose, now that I think of 
it, that since your code is all module-level, there wouldn't be any 
function stack in this case...   Still, in general, when asking for 
help with something that throws an exception, it's always best to copy 
& paste the entire text of the exception.

One thing that I've noticed, which I thought was just a typo in your 
original email but which is duplicated again here (it's not present on 
the web page you linked to) -- you have a mismatched parenthesis in 
your len() call.  It's "[ ... len(endstr]" -- there's no ')' to close 
the function call.  Given that this typo isn't on the web page, I'm 
not sure whether it's actually there in the code you're running or 
not.  I'd have *thought*, however, that if it *is* present, you'd get 
a syntax error rather than a memory error, so it's probably not there 
but you should check it anyhow.  :)

Jeff Shannon
Technician/Programmer
Credit International

___
Tutor maillist  -  [EMAIL PROTECTED]
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Please help matching elements from two lists and printing them

2004-12-09 Thread Jeff Shannon
kumar s wrote:
On top of this this process is VERY SLOW on high end
server too. 
That's because, for each line in spot_cor, you're examining every item 
in spot_int, and if there's a match, you examine every element in 
spot_int again!  If I'm remembering my big-O notation correctly, that 
makes this O(n*m + m) -- even if it simplifies to O(n*m) (which I 
think it may), that's still quadratic time -- as the length of your 
lists grows, your performance will degrade *very* rapidly.

Here's a simplified version of your code.  I've changed the for loops 
so that they iterate over the lists directly, instead of iterating 
over a range and then using that number to index into the list -- the 
result is the same, but this way is less extra work and easier to read.

out = open('sa_int_2.txt','w')
for cor_ele in spot_cor:
for int_ele in spot_int:
cols = split(int_ele, '\t')
y = cols[0] + '\t' + cols[1]
if x == y:
for int_ele2 in spot_int:
if y in int_ele2:
out.write(int_ele2 + '\n')
Remember, every time you use 'in', it means traversing the entire 
list.  Multiple levels of nesting statements that use 'in' causes a 
polynomial expansion of work.

Now, here's how I'd rewrite your code.
out = open('sa_int_2.txt','w')
element_dict = {}
for line in spot_int:
cols = split(line,'\t')
key = '\t'.join(cols[:2])
element_dict[key] = line
for cor in spot_cor:
try:
value = element_dict[cor]
out.write(value + '\n')
except KeyError:
pass
out.close()
Note that I iterate through each list only once, so my timing should 
be O(n + m).  First, I preprocess spot_int by putting it into a 
dictionary.  I create keys for the dictionary that are identical to 
what will be in spot_cor.  Then I iterate through spot_cor, and match 
each element with what's in the dictionary I've made.  If I find 
something that matches, I write it out; if I don't, then I simply move 
on to the next item in spot_cor.

This does make several assumptions.  First, it assumes that every line 
in spot_int will be unique in the first two columns -- that is, I'm 
assuming that nowhere in the file would you find lines like the following:

 5 0 123
 5 0 456
If these cases *do* happen, then all but the last such line would be 
lost, and only the last one would be left in the dictionary (and thus 
found and written out).  In your version, all lines whose first two 
columns match will be written out.  (This may be the source of your 
"extra" results.)

If you *do* need to handle lines like this, then it wouldn't be hard 
to modify my code for it.  Each value in the dictionary would become a 
list, and matching lines are appended to that list.  The line 
'element_dict[key] = line' becomes 'element_dict.setdefault(key, 
[]).append(line)', and writing to the file becomes a for-loop instead 
of a single write.

The other assumption that I make is that these files are all of 
reasonable size to fit into memory.  Your code makes this same 
assumption, too, of course.  This assumption should be valid for up to 
a few tens of thousands (maybe even hundreds of thousands, depending 
on your hardware) of items.  If you have more than this, then your 
best bet would be to start using a real database.  (I've heard good 
things about mysql and sqlite support in Python...)

Jeff Shannon
Technician/Programmer
Credit International

___
Tutor maillist  -  [EMAIL PROTECTED]
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] MemoryError

2004-12-09 Thread Jeff Shannon
Liam Clarke wrote:
So, I'm going to throw caution to the wind, and try an re approach. It
can't be any more unwieldy and ugly than what I've got going at the
moment.
If you're going to try a new approach, I'd strongly suggest using a 
proper html/xml parser instead of re's.  You'll almost certainly have 
an easier time using a tool that's designed for your specific problem 
domain than you will trying to force a more general tool to work. 
Since you're specifically trying to find (and replace) certain html 
tags and attributes, and that's exactly what html parsers *do*, well, 
the conclusions seems obvious (to me at least). ;)

There are lots of html parsing tools available in Python (though I've 
never needed one myself). I've heard lots of good things about 
BeautifulSoup...

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  [EMAIL PROTECTED]
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Difference between for i in range(len(object)) and for i in object

2004-12-09 Thread Jeff Shannon
kumar s wrote:
 > Here is my code:

spot_cor=[]
Create an empty list...
for m in cor:
Now, for each element in some other list from somewhere else,
... cols = split(cor,'\t')
Ignore the element we've just isolated and try to split the entire 
list on '\t' ...

Traceback (most recent call last):
  File "", line 2, in ?
  File "/usr/local/lib/python2.3/string.py", line 121,
in split
return s.split(sep, maxsplit)
AttributeError: 'list' object has no attribute 'split'
Yup, the list 'cor' doesn't have a split() method.  The string that 
presumably should be in 'm' would have such a method, though.


Here is 2nd way:

test_cor=[]
for m in cor:
... cols = split(cor,'\t')
Once again, you're operating on the list, not the element of the list.
Here is my 3rd way of doing this thing:
for m in range(len(cor)):
... cols = split(cor[m],'\t')
Here, you *are* operating on an element of the list.  But if I were to 
write this segment to be parallel to your previous two attempts, it 
would be:

cols = split(cor[cor],'\t')
which probably wouldn't surprise you when it doesn't work...

My question:
 Many people suggested me to avoid  iteration over  a
object using (range(len)) its index and use instead
'Python's power' by using for i in object, instead. 

However, when I tried that using some data, as
demonstrated above, I get error because append method
does not work on list.
No -- look carefully at the tracebacks, and you'll see that nowhere 
does it complain about append(), nor does it give the line numbers in 
which the append() takes place.  It complains about split(), and tells 
you exactly which line the problem is on ('File "", line 2, in 
?' -- since you're doing this in an interpreter, there's no filename 
or function name).

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  [EMAIL PROTECTED]
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Problem with python2.4.

2004-12-09 Thread Jeff Shannon
Orri Ganel wrote:
On Thu, 9 Dec 2004 19:31:22 -0500, Jacob S. <[EMAIL PROTECTED]> wrote:
[...]  It appears as though pythonw.exe is
not working properly in the python 2.4 distribution. 

I had a similar problem with some of the early versions of 2.4 (beta,
release candidate), and it seems to me, looking back, that some of the
other programs I had running simultaneously blocked the sockets or
something . . . 
Seeing this comment reminded me of some conversations I've seen in 
comp.lang.python recently.  Apparently newer versions of IDLE create a 
subprocess to run user-code in (so that IDLE runs in a different 
interpreter than the code you type into IDLE), and communicates with 
that subprocess through sockets on the loopback interface (that is, 
the 'network connection' that connects only to itself).  Overly 
aggressive firewall programs may block those socket operations.

I'd check whether XP's built-in firewall is enabled, and if so, check 
whether it might be blocking connections to loopback / localhost / 
127.0.0.1 (all of these indicate the same thing).

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  [EMAIL PROTECTED]
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] check_range

2004-12-14 Thread Jeff Shannon
Jeff Shannon wrote:
if myrange in range(10,90):  # "in" is the key word here
return True
else
return False

This is, however, the correct solution. :)  
Or I *should* say, rather, that this is *a* correct solution, in that 
it will yield the expected answer.  Kent Johnson's '10 < x < 90' is a 
better solution, however -- 'if x in range(...)' creates a list of 
numbers, and then steps through that list comparing x to each one in 
turn, while Kent's version makes only two comparisons and no object 
creations.  While one should never prematurely optimize, it's also 
good to be aware of how much work is done by different options, and in 
this case 'if x in range()' isn't any clearer than the direct 
comparisons.  I'd think nothing of the extra cost of using range() if 
it *did* make the code easier to read, but there's no sense in going 
to extra work for no benefit.  :)

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  [EMAIL PROTECTED]
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] am I missing another simpler structure?

2004-12-16 Thread Jeff Shannon
Blake Winton wrote:
def is_leap_year(year):
is_leap = True
try:
datetime.date(year, 2, 29)
except ValueError:
is_leap = False
return is_leap

I would write
def is_leap_year(year):
try:
datetime.date(year, 2, 29)
return True
except ValueError:
return False
If one insists on single-return style, then I'd prefer to do it this way:
def is_leap_year(year):
try:
datetime.date(year, 2, 29)
is_leap = True
except ValueError:
is_leap = False
return is_leap
You still have to type 'is_leap' multiple times, but at least it's a 
little bit more clear which conditions will result in it being True or 
False.

[...]  Only having one
return point from a function is a long-standing convention that is 
supposed to make programs easier to read/debug/optimize/prove correct.
Indeed, it is supposed (by some) to be better, and is thought by 
others to sometimes make things more complicated.  In the above code, 
a single return point gives you one place to set breakpoints during 
debugging, etc, but it also means that you introduce a new variable 
that you must type at least three times, introducing multiple 
opportunities for typos.  As with most programming choices, 
single-return has both a benefit and a cost.  In some situations the 
cost can be very large relative to the benefit; in others the cost is 
very small.  I find it best not to be too dogmatic about most such 
stylistic questions -- I try to stay aware of the costs of a 
particular approach, but I'll happily use it when the net effect is to 
make the code simpler and more understandable.

Similar to the example that Kent later points out, in my work life I 
often find myself writing functions (to use as the body of a loop) 
where a number of unrelated tests must be done before proceeding with 
processing.  (This is actually in an old, crufty dialect of Basic, but 
the same principle applies)  I have a few choices in this case.  I can 
 simply write the loop body in-line and use gotos to skip segments if 
the tests fail (ew).  I can write the loop body in-line and use 
multiply nested if/else statements, but it can get difficult to track 
what nesting level I'm at.  I can use nested functions, each with just 
one test in it, something like this:

def func1(data):
result = None
if test1:
result = func2(data)
return result
def func2(data):
result = None
if test2:
result = func3(data)
return result
def func3(data):
[...]
This gets pretty darn ugly to trace through, especially when I've got 
six or eight different tests.  Or, I can simply use multiple returns:

def func(data)
if not test1:
return
if not test2:
return
if not test3:
return
# do stuff with data...
It really does make it much simpler to track through the code, since I 
don't care, later in the function, about the specific results of each 
test, only about whether I should continue afterwards or not.  In this 
case, I'm weighing the cost of multiple returns against the cost of 
multiple nestings or of using flag variables, and I find multiple 
returns to be the lowest-cost option.

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  [EMAIL PROTECTED]
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Python structure advice ?

2004-12-17 Thread Jeff Shannon
Dave S wrote:
Kent Johnson wrote:
Why do you say this is 'cheaty'? A class is basically a collection of 
data (state) and functions to operate on that state.

Sorry for the delay, real world work got in the way ...
Well I understand classes to be used when multiple instances are 
required, I will only need one instance and as such it seemed a bit of a 
cheat, The trouble is I now pretty well understand the tools, but don't 
know how you guys use them in the real world.
For what it's worth, it seems to me to be perfectly normal to have 
classes that are only ever intended to have a single instance.  For 
example, you're never likely to need more than one HTML parser, and 
yet htmllib.HTMLParser is a class...

As Kent said, the main point of a class is that you have a collection 
of data and operations on that data bundled together.  Whether you 
have one set of data to operate on, or many such sets, is mostly 
irrelevant (though classes are even more valuable when there *are* 
many sets of data).  Defining a class isn't so much a statement that 
"I want lots of things like this", as it is a declaration of 
modularity -- "This stuff all belongs together as a unit".

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  [EMAIL PROTECTED]
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] About Perl's Integer module

2004-12-17 Thread Jeff Shannon
refix) + domain
...
.>>
So, let's see how this works:
.>> complex('site.company.com')
'X3/32/site.company.com'
.>> complex('site2.company.com')
'6U/zv/site2.company.com'
.>> complex('www.python.org')
'ZF/4R/www.python.org'
.>>
So, each character is generated by looking at the hash (h), grabbing 
the least-significant six bits, and using the resulting number (which 
will be 0-63) to look up a character in conv.  The hash is then 
shifted six bits to drop the 'used' bits before grabbing the next 
chunk.  Two of these generated characters are used for each of two 
directory names.  Any given sitename will consistently produce the 
same four characters.

Now, here's a 'batteries-included' function that does much the same 
thing (though it'll be different characters).

.>> def complex2(domain):
... import md5
... digest = md5.new(domain)
... digeststring = digest.hexdigest()
... names = (digeststring[:2], digeststring[2:4], domain)
... return '/'.join(names)
...
.>> complex2('site.company.com')
'b2/37/site.company.com'
.>> complex2('site2.company.com')
'75/5c/site2.company.com'
.>> complex2('www.python.org')
'16/95/www.python.org'
.>>
This uses the md5 module to generate a 'fingerprint' for each domain 
name.  It gets that fingerprint as a long hexadecimal number, and then 
slices off the first few characters to make the directory names.  Now, 
this method is going to be heavily weighted towards numbers instead of 
letters, and it can create a maximum of 16^4 (65,536) different 
directories instead of 64^4 (16,777,216), so you're somewhat more 
likely to have collisions (multiple sites in a single directory), but 
it's still not very likely.  (That chance can be reduced by using 
longer names, too.  Using three-character directory names gives 16^6 
possibilities -- which is equal to 64^4, the same as your perl script.)

Jeff Shannon
Technician/Programmer
Credit International

___
Tutor maillist  -  [EMAIL PROTECTED]
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] check_range

2004-12-14 Thread Jeff Shannon
R. Alan Monroe wrote:
def check_range(myrange):
   if range(myrange) != range(10,89):
   return "False"
   else:
   return "True"

For this to work out, the user's input would have to be a giant string
containing 10, 11, 12, 13, etc.
Not quite, actually.
Presuming that myrange is an integer, range(myrange) will generate a 
list of integers starting with 0 and continuing up to (but not 
including) myrange, while range(10,89) generates a list of integers 
starting with 10 and continuing up to (but not including) 89.  These 
lists can never be equal, because range(10,89) will never include the 
integers 0-9 but range(myrange) will (unless myrange is less than 10).

Unless I mistunderstood your requirements, what you're probably looking for is:
if myrange in range(10,90):  # "in" is the key word here
return True
else
return False
This is, however, the correct solution. :)  Presuming again, of 
course, that myrange is an integer -- but be aware that user input 
normally comes in the form of strings, so it will be necessary, at 
some point, to create an integer from that string using int().

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  [EMAIL PROTECTED]
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Comments appreciated

2004-12-21 Thread Jeff Shannon
Luis N wrote:
This is the most meaningful thing this newbie has ever done. Comments
are appreciated:
Okay, here's a few thoughts...
junk = []
for arg in sys.argv:
junk.append(arg)
junk = junk[1:]
You can write these four lines much simpler as:
junk = sys.argv[1:]

if len(junk) is 0 and empty == False:
sys.exit()
else:
if len(junk) > 0:
trash(junk)
if empty == True:
can()
You can simplify this, too.
If empty is True, then you want to call can() regardless of whether 
you're doing anything else.  You can handle that first, and *then* see 
whether there's junk to delete.  This also means that, if you don't 
have junk to delete, you can simply do nothing, instead of explicitly 
calling sys.exit().  In addition, you don't need to explicitly test 
against True -- empty will already be true or false on its own, so 
comparing it inside an if statement doesn't gain you anything.

if empty:
can()
if len(junk) > 0:
trash(junk)
Also, even though this is intended to be a quick shell script, it's 
not a bad idea to make everything except function defs into a little 
main() function, and call it in a script-only section.  This gives you 
a bit more modularity, pulls all of your actions into a single place, 
and lets you avoid using global variables.

def main(junk):
trashcan = os.path.expanduser("~/.trashcan")
empty = False
if "-e" in junk:
empty = True
junk.remove("-e")
if not os.path.exists(trashcan):
os.mkdir(trashcan)
if empty:
can()
if len(junk) > 0:
trash(junk)
if __name__ == '__main__':
main(sys.argv[1:])
Notice that I've also changed your trashcan from explicitly stating a 
home directory to getting the home directory for whoever the current 
user is.

You can refine main() further, too -- for instance, instead of setting 
an empty flag, you could just call can() as soon as you find the -e 
option.

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  [EMAIL PROTECTED]
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] O.T.

2004-12-29 Thread Jeff Shannon
I'm 36, unmarried, male, and live in Seattle, Washington (USA).  I've 
dabbled with computers and programming on and off since junior high 
(around 1980), but have only gotten serious about it in the last 10 
years or so (almost entirely self-taught), and have only been employed 
in the field for about 5 years.  I had two years of college (nominally 
majoring in chemistry) at the University of Alaska (the state where I 
grew up) before dropping out, moving to Seattle, and frittering away 
my young adulthood. ;)

I work for a small company that does electronic payment processing and 
check management.  Our system is built around an old Pick database 
(ugh), and most of my programming is in Pick Proc (a 
shell-script-like, but truly horrible, language) and Pick's dialect of 
Basic (which is only 20 years out of date...).  As we're moving more 
towards integrating our server with desktop PCs, though, I've been 
able to use Python for a few projects, and I often use it for 
interactively exploring data files and doing sysadmin-type work.

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to put my functions in an array

2004-12-29 Thread Jeff Shannon
Mohamed Lrhazi wrote:
def addvirt():
pass
def remvirt():
pass
PROVISION_ACTIONS=[('addvirt','Add Virt'),('remvirt','Remove Virt'),]
formhandlers={}
# this works
formhandlers["addvirt"]=addvirt
formhandlers["remvirt"]=remvirt
# this does not work:
for verb,verb_desc in PROVISION_ACTIONS:
if callable(verb):
formhandlers[verb]=verb
I tried a few different syntaxes but to no avail... do I need things
like: getattr()? 
You don't say how this fails, which would be very helpful to know. 
But I think I can guess what's happening.

When you're calling 'callable(verb)', at this point verb contains a 
string which is a function's name.  It is *not* the function itself. 
The string is, of course, not callable, so nothing gets added to 
formhandlers.

Even if you took out that test, though, you'd end up with a dictionary 
 where for a given key, the value is the same string that was used 
for the key, because verb is only a string.

For this to work, you need to have two separate things -- a string by 
which to identify the function, and a reference to the function object 
itself.  In the working code, you do this.  By putting the name (that 
you're using as the dictionary key) in quotes, you're specifying a 
string, and by *not* putting the value (on the right of the = sign) in 
quotes, you're referring to the function object.

There's a couple of ways you can do this.  One is by adding a 
reference to the function to your list, something like this:

PROVISION_ACTIONS = [('addvirt', "Add Virt", addvirt), ...]
for verb, verb_desc, func in PROVISION_ACTIONS:
if callable(func):
formhandlers[verb] = func
If you can't make that change to PROVISION_ACTIONS, then you may be 
able to use the name strings to pull function references from your 
module's global dictionary --

for verb, verb_desc in PROVISION_ACTIONS:
func = globals()[verb]
if callable(func):
formhandlers[verb] = func
though you'd probably want to put that globals() lookup in a 
try/except block to catch any KeyErrors.

Note that if the functions were in a different module, you could 
retrieve them from that module with getattr(), rather than using the 
globals() dict.

import func_module
# ...
for ...
func = getattr(func_module, verb)
# ...
Once again, you should probably wrap that in a try/except block (this 
time looking for AttributeErrors).

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] My best GUI app so far.

2005-01-11 Thread Jeff Shannon
 so I'm not sure 
offhand.)  Then your button bindings can simply be

self.bl = [ self.make_adddigit_callback('0'),
self.make_adddigit_callback('1'),
self.make_adddigit_callback('2'),
... ]
Or even --
self.bl = [self.make_adddigit_callback(digit) \
   for digit in '0123456789']
Remember, there's nothing particularly special about lambdas -- you 
can create and pass around regular named functions, too.  Each time 
that make_adddigit_callback() is called, it creates and returns a new 
function object which captures the current value of 'digit', in 
exactly the same way that lambda does.  A function object (whether 
named with def, or lambda) like this, which captures a variable's 
current state, is called a closure.  Closures are indispensible for 
GUI callbacks like this, and many people automatically turn to lambda 
when they want a closure.  For me, though, having a proper def 
statement somewhere feels clearer.  (The merits of lambda vs. def'd 
functions are a frequent subject of heated debate on comp.lang.python, 
so if you prefer to stick with the lambdas in this case, I'm sure 
you'd be able to find plenty of people to support you... ;) )

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class instance with identity crisis

2005-01-12 Thread Jeff Shannon
Barnaby Scott wrote:
class Damson:
def __str__(self):
return 'damson'
def dry(self):
self = Prune()
class Prune:
def __str__(self):
return 'prune'
weapon = Damson()
weapon.dry()
print weapon
[...]
but something in me suggests it should produce
prune
After all, 'self' refers to the instance 'weapon'.
Ah, but 'self' is a method-local name.  You're re-binding that name, 
not affecting the object (previously) pointed to by the name.  And of 
course, when the method returns, those local bindings go away.

Obviously one could reassign weapon to a Prune outside the class definition,
but I was hoping to write something in which, given certain circustances
arising, the instance would change itself into something else.
As others have mentioned, you can change the type of the object by 
assigning to self.__class__, but this can get a bit hairy.  Your 
class/instance knows nothing about what names it may be bound to, so 
it can't rebind those names to a different object (i.e. class Damson, 
and any instances you create, know nothing of the name 'weapon').

I tend to favor the explicit approach of having weapon.dry() *return* 
a different object,  and then using 'weapon = weapon.dry()'.  But if 
you really need to have objects that change their type as a 
side-effect of a method call, you can use a proxy or adapter -- in 
essence, you have a class that can *contain* either a Damson or a 
Prune, and which forwards method calls / attribute accesses to its 
contained object.

Jeff Shannon
Technician/Programmer
Credit International

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to create a key-value pairs with alternative elements in a list ... please help.

2005-01-12 Thread Jeff Shannon
kumar s wrote:
Problem:
How do i capture every alternative element in list a:
I am unable to pump the a,b, and c into keys list
and apple, boy,cat into vals list.
In a sufficiently recent version of Python, you should be able to use 
an extended slice with a stride --

keys = a[::2]
vals = a[1::2]
(Note that this is untested, as I don't have a recent version of 
Python handy at the moment; I'm on 2.2 here, which doesn't have 
extended slices.)

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Regular expression re.search() object . Please help

2005-01-13 Thread Jeff Shannon
Liam Clarke wrote:
openFile=file("probe_pairs.txt","r")
probe_pairs=openFile.readlines()
openFile.close()
indexesToRemove=[]
for lineIndex in range(len(probe_pairs)):
   if probe_pairs[lineIndex].startswith("Name="):
 probe_pairs[lineIndex]=''
If the intent is simply to remove all lines that begin with "Name=", 
and setting those lines to an empty string is just shorthand for that, 
it'd make more sense to do this with a filtering list comprehension:

openfile = open("probe_pairs.txt","r")
probe_pairs = openfile.readlines()
openfile.close()
probe_pairs = [line for line in probe_pairs \
  if not line.startswith('Name=')]
(The '\' line continuation isn't strictly necessary, because the open 
list-comp will do the same thing, but I'm including it for 
readability's sake.)

If one wants to avoid list comprehensions, you could instead do:
openfile = open("probe_pairs.txt","r")
probe_pairs = []
for line in openfile.readlines():
if not line.startswith('Name='):
    probe_pairs.append(line)
openfile.close()
Either way, lines that start with 'Name=' get thrown away, and all 
other lines get kept.

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Re: communication between java and python?

2005-01-13 Thread Jeff Shannon
Lee Harr wrote:
I'm trying to communicate between Python and Java and using
os.popen(). But thing dont work...The Java program reads strings from
stdin and the python program just writes to stdout.
[...]
"""
popen(command[, mode[, bufsize]])
Open a pipe to or from command. The return value is an open file
object connected to the pipe, which can be read or written
depending on whether mode is 'r' (default) or 'w'.
"""
So, I do not believe that you can both write to and read from
a file handle opened with popen.
Not only that, but access to the file-like pipe objects is probably 
buffered.  You'll want to call pipe.flush() after writing to it, or 
the child process won't actually see what you've written.

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Regular expression re.search() object . Please help

2005-01-14 Thread Jeff Shannon
Jacob S. wrote:
I assume that both you and Liam are using previous-er versions of python?
Now files are iterators by line and you can do this.
openFile = open("probe_pairs.txt","r")
indexesToRemove = []
for line in openFile:
# [...]
My version of Python isn't *that* old (IIRC this works since 2.2, 
which is what I usually use), I'm just in the habit of using 
readlines().  I suppose that, in a case like this where the filesize 
is not insignificant, it *would* be worthwhile to take advantage of 
the file iterator to avoid having that fairly large list in-memory...

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] file-like object

2005-01-14 Thread Jeff Shannon
Terry Carroll wrote:
On Fri, 14 Jan 2005, Chad Crabtree wrote:

class _macroString(object):
   def __init__(self,s):
   self.macro=s
   self.list=self.macro.split("\n")
   for n,v in enumerate(self.list):
   self.list[n]=v+'\n'

Is this for loop a safe technique, where the list you're enumerating over
in the for statement is the same as the one being updated in the loop
body?  I always avoid things like that.
In this case it should be safe.  This changes the string at each index 
in the list, but it doesn't change the length or ordering of the list. 
 That's where the problems come in, because the for loop doesn't know 
that the list "shape" has changed.

But your caution is generally a good idea.  :)  I'd have probably 
written the above as:

self.list = [line+'\n' for line in self.list]
Well, actually, I'd have avoided saving the intermediary state and 
simply done all the list processing at once:

self.list = [line+'\n' for line in self.macro.split('\n')]
Either way, though, I'm creating a new list rather than modifying the 
old list in-place, which avoids the risk of accidentally changing the 
list's "shape" and throwing off the loop.

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Re: glob or filter help

2005-01-24 Thread Jeff Shannon
Barnaby Scott wrote:
For anyone who doesn't like lambda, how about
import os
def get_fles(exts, upd_dir):
return [i for i in os.listdir(upd_dir) if i.split('.')[-1] in exts]
Better would be:
def get_fles(exts, upd_dir):
return [fname for fname in os.listdir(upd_dir) if \
   os.path.splitext(fname)[-1] in exts \
   and not fname.islink() ]
(This is split into three lines for readability, but can be entered as 
a single line.  Also, the '\' line-continuation is optional, as Python 
will see that the list comp is still open and automatically continue 
the line...)

Using os.path.splitext() to get the extension is safer and more 
portable than simply splitting on '.', and it's self-documenting too! 
 (A month from now, you might need to think a moment to figure out 
why you're splitting on '.', but the very name os.path.splitext() 
tells you about the intent.)

Note that there's a slight difference here, in that exts will need to 
list extensions *with* the leading '.' because splitext() will leave 
it on --

>>> os.path.splitext('filename.txt')
('filename', '.txt')
>>>
I've also added a second clause to ensure that returned files are not 
links, as per the rest of the O.P.'s spec.

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Syntax Check

2005-01-27 Thread Jeff Shannon
Chad Crabtree wrote:
I'm trying to make a macro system that's work by just doing this
import macro
# [...]
Perhaps you could turn things around, and make your macro preprocessor 
into an import hook?  I.E., you'd use it like --

import macro
module = macro.import("module_with_macros"[, macro_list])
module.do_stuff()
Not sure if you'd need to have a list of macros in the module to be 
imported, or not.  Perhaps the macro module would hold a list of 
currently active macros, instead...

In any case, this (I think) gives you a chance to interrupt the import 
process and modify the target module before the Python parser gets it, 
which should enable you to avoid the SyntaxError problems.

(Of course, I've never messed around with hooking __import__(), so I 
could just be talking out of my ...)

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Better structure?

2005-02-01 Thread Jeff Shannon
Jacob S. wrote:
I don't know who's going crazy here... but I checked that straight from 
the python 2.4 interpreter...
>>> a = "go on long buddy"
>>> a.lstrip('gonl')
' on long buddy'
>>> a.lstrip('gonl ')
'buddy'
>>>
Note that in the second case, I've included a space in the lstrip() 
parameter.  lstrip() is essentially saying "remove all leading 
characters until you find a character that's not in this sequence" -- 
a space counts as a character.  (Took me trying it out before I saw 
this, so don't feel bad. ;) )

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Better structure?

2005-02-01 Thread Jeff Shannon
Jacob S. wrote:
So, how would one go about this in a non broken code way? Don't they 
have something like what I'm requesting.
No, but it's pretty easy to do:
def exact_lstrip(astring, stripstring):
if astring.startswith(stripstring):
astring = astring[len(stripstring):]
return astring

[...] Also why 
shouldn't string methods include stuff like lstrip which do precisely 
what I request?
Maybe it's because other people would have different expectations?
The current implementation of strip() (including lstrip() and 
rstrip()) seems to work well for the most common case, and I'm not 
sure that your expectation is necessarily more generally useful than 
the current behavior.  Especially given that your behavior is the one 
that's easier to hand-code if it's desired.

Jeff Shannon
Technician/Programmer
Credit International

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Are you allowed to shoot camels? [kinda OT]

2005-02-03 Thread Jeff Shannon
Max Noel wrote:
On Feb 3, 2005, at 09:48, Alan Gauld wrote:
Pythons lambda feature is a bare minimum (and Guido wants to remove
it!).
Does he? Damn, just when I was learning functional programming! (in 
Haskell, if you're curious ^^)

However, Python doesn't need lambdas to be able to write in a 
functional style.  Functions are first-class objects and can be passed 
around quite easily, and IIRC Python's list comprehensions were 
borrowed (though probably with notable modification) from Haskell.

Keep in mind that both lambdas and named functions are created at 
runtime, so the creation of both is fully dynamic.  Indeed, there are 
only a few differences between lambdas and named functions in Python:

  - Anonymous vs named
  - Single expression vs suite of statements
  - Inline vs. pre-created
Note that the second of these is a consequence of the third -- given 
Python's block-indentation-based structure, there's no good way to 
inline a multi-statement suite (how many of those statements belong to 
that 'if' suite?).  Statements need to have a clear indentation level, 
and while one can sometimes fudge that for a single statement, it gets 
exponentially messier as the number of statements goes up.

I'd also argue that the inline nature is the *true* differentiating 
feature of lambdas -- the fact that they're anonymous is relatively 
minor.  Consider, also, that if they weren't inline then you'd need a 
name to refer to them by... and at that point, you *have* a 'normal' 
function.

So, while there are some advantages to having single-use callables be 
defined inline (i.e. lambdas), their removal from Python (which 
wouldn't happen before the mythical Python 3k anyhow) isn't likely to 
be as devastating as some might lead you to believe. ;)  It certainly 
won't prevent you from using Python for functional programming...

(And personally, I suspect that if lambdas *are* removed, they will be 
replaced with a different construct that will fill the same needs in a 
more Pythonic way...)

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Are you allowed to shoot camels? [kinda OT]

2005-02-03 Thread Jeff Shannon
Alan Gauld wrote:
There is no perfect language, and very few truly bad
languages - they never get out of the lab - they all
have something that they are good at and from which
we can learn!
Heh, I'd look at that a bit differently -- I think that there's a 
*lot* of bad languages, it's just that we're spared ever hearing about 
the majority of them because they don't ever get very far. ;)

(But then, at my job I'm stuck using a horrible Frankenstein's monster 
of a proprietary language on a daily basis, so I can't help but 
believe that there's plenty more awful languages around that didn't 
happen to be "rescued" from oblivion by an accident of history...)

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Are you allowed to shoot camels? [kinda OT]

2005-02-03 Thread Jeff Shannon
Alan Gauld wrote:

However, Python doesn't need lambdas to be able to write in a
functional style.
I disagree Jeff. It does need lambdas to do FP properly, and
better lambdas than we have currently. What it doesn't need
is the lambda keyword and syntax - although pesonally I like
lambda since it is descriptive!
Well, we'll have to continue to disagree on that. ;)  Personally, I 
can't help but think that 'lambda' is descriptive only to people 
who've experienced it elsewhere, and that that does *not* include the 
majority of the programming community, but I could be mistaken. :)

Functions are first-class objects and can be passed
around quite easily,
Yes, but lambdas are more than first class functions, they
are anonymous functions! In fact really just callable code
blocks, not necessarily functions in the strictest sense
(except that every callable in FP is a function...! ;-)
Well, given that in Python a function is just a callable code block 
that's bound to a name... ;)  Personally, I fail to see why having an 
anonymous function is such a huge conceptual advantage, no matter how 
many times this is proclaimed as truth by lambda-users, but again this 
is just my own impression.

Having to define every function before using it would
be a big hassle and make code less readable IMHO.
Here, ISTM that you're emphasizing the in-line nature of lambdas as 
being their key usage point...  And personally, I prefer to have a 
glossary of terms rather than having to decipher jargon by context. ;)

only a few differences between lambdas and named functions in
Python:
  - Anonymous vs named
the key feature
Again, I fail to see why this is such an advantage -- I've seen 
assertions that it is, over and over again, but never any convincing 
evidence

  - Single expression vs suite of statements
A python restriction.
Well, I *did* specify that I was talking about 'in Python'... ;)

I'd also argue that the inline nature is the *true* differentiating
feature of lambdas -- the fact that they're anonymous is relatively
minor.
I agree, if I had an inline mechanism that forced me to
provide a name I could just use 'f' over and over and
not feel too cheated, but its nicer not to have an artificial
name when theres no need.
Personally, I prefer to have the opportunity to provide a meaningful 
name, and don't see where a generic name is any more restrictive than 
having no name, but again, maybe that's just me.

So, while there are some advantages to having single-use callables
be defined inline
The other advantage is the huge conceptial advantage that
real lambdas confer. The breakthrough idea of
def f(x): return x+x
being the same as
f = lambda x: x+x
is only possible to demonstrate if you have lambda to start with.
And yet that concept of a function name being just another variable
and the callable code being an object in its own right becomes
much more obvious in my opinion. lambda is a learning tool which
shows what is really happening whereas def is just syntactic sugar.
Hm, I understood the idea of functions being just code objects that 
were bound to a name, and could be passed around, stored in 
collections, and effectively renamed, well before I really got a hold 
on lambdas as anything more than some confusing bit of magic.  Of 
course, I started in C, where I was fairly comfortable with the idea 
of function pointers; function objects are a pretty simple step up, 
abstraction-wise, from that.

I suppose that one might argue that I *still* just don't really get 
lambdas (and I wouldn't argue with that).  I can see some advantages 
to small inline functions, though I suspect that a more-explicit 
currying mechanism (such as the proposed partial() higher-order 
function) could easily replace such uses.  I'm sorry to say, though, 
that the supposed advantages of anonymity come across as little more 
than handwaving assertions to me, no matter how sincerely they're 
intended.  (I've just started to read through SICP, to pick up some 
lisp/scheme, in hopes of understanding the appeal a bit better, so 
maybe there's hope for me yet. ;) )

Jeff Shannon
Technician/Programmer
Credit International

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Are you allowed to shoot camels? [kinda OT]

2005-02-03 Thread Jeff Shannon
Max Noel wrote:
On Feb 3, 2005, at 23:41, Jeff Shannon wrote:
(But then, at my job I'm stuck using a horrible Frankenstein's monster 
of a proprietary language on a daily basis, so I can't help but 
believe that there's plenty more awful languages around that didn't 
happen to be "rescued" from oblivion by an accident of history...)
Yeah. Sometimes I read a little bit of Wikipedia's "Esoteric 
Programming Languages" page, and some of them just leave me in awe. 
Brainfuck (and its variant Ook!) and INTERCAL ("GOTO is considered 
harmful, so we removed it -- INTERCAL uses COME FROM instead") are 
already quite impressive, but the very idea of Befunge makes my brain 
want to explode. Especially that extension to the language that allows 
one to write N-dimensional programs. :D
The difference here is that those are languages that were *intended* 
to be brain-melting.  The language I'm talking about (Pick Proc, aka 
UHL) was intended to do real work with -- though at times I think it 
was designed by a brain-damaged lemur that was huffing paint fumes.

For example, every line (except flow-control statements i.e. 'if' and 
'go' (there's a few other exceptions as well, but anyhow...)) must 
begin with a single character that denotes what the line does - 'c' 
for comment, 'o' for output (print to terminal), 'h' to build a 
command, 'p' to execute that command... empty lines are forbidden. 
Note also that the position *after* the final newline character is 
considered a line, and therefore a file cannot end with a newline.

Especially when combined with several of the utilities that it's 
commonly used to script for, it begins to approach Perl in 
indecipherability, without even having the excuse of being largely 
non-alpha characters.

I'd consider writing a Python extension that would interact with the 
system such that I wouldn't need to use this awful little scripting 
language, but that would require more effort and thought than I'm 
willing to invest in learning the details of this system.

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Are you allowed to shoot camels? [kinda OT]

2005-02-04 Thread Jeff Shannon
Smith, Jeff wrote:
IMHO, if/elif/else statements are far more abused than either switch or
ternary but I certainly wouldn't argue they should be removed from the
language.
IMHO, if it's true that if/elif/else statements are more abused than 
ternaries, then it's only because they're *used* far more often than 
ternaries.  I'd say that the percentage of uses which could count as 
abuse is *far* higher for ternary than for if/elif/else.

And I avoid (and recommend against) Python's "a and b or c" trick for 
similar reasons -- it *is* a trick.  A 'real' ternary operator is 
confusing enough; this trick is more readable (words instead of opaque 
symbols) but more difficult to write correctly given the constraints 
on 'a'...

Maybe I'm just weird, but I just don't find so much benefit to putting 
*everything* in-line.  Occassionally it improves readability, but more 
often it obscures and obfuscates.

Jeff Shannon
Technician/Programmer
Credit International
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Are you allowed to shoot camels? [kinda OT]

2005-02-07 Thread Jeff Shannon
Alan Gauld wrote:
As an aside, I did try to create a lambda based solution but was
unable.  Let me know what's wrong:
ftable = { 'a' : lambda: print 'a',
SyntaxError: invalid syntax
I did say "if Python had *proper* lambdas..."
Unfortunately Python insists on only having *expressions* as
lambdas and since print is a command not a function you can't
use it in Python lambdas! Dumb or what??!
So you are stuck with predefining a bunch of one liner
functions and then creating a dictionary or going back
to if/elif chains, which is where we came in... :-)
Well, in this particular case, if one really wants to use lambdas then 
one could (after importing sys, of course) replace the print statement 
with a call to sys.stdout.write() --

ftable = { 'a': lambda: sys.stdout.write('a\n'), ... }
Note that sys.stdout.write() will *not* automatically add the newline 
that print does (which is why I've specified it in the above sample). 
 Indeed, print can do all sorts of odd things with whitespace, 
leaving sys.stdout.write() as the best way to have real control over 
your output anyhow...

Jeff Shannon
Technician/Programmer
Credit International

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Are you allowed to shoot camels? [kinda OT]

2005-02-08 Thread Jeff Shannon
Smith, Jeff wrote:
Jeff,
It looks like that finally is the simplest expression of the original
switch statement:
import sys
def p():
pass
ftable = { 'a' : lambda: sys.stdout.write('a\n'),
   'b' : lambda: sys.stdout.write('b or c\n'),
   'c' : lambda: sys.stdout.write('b or c\n'),
   'd' : p }
ftable.get(var, lambda: sys.stdout.write('default case\n'))()
I do note that it took this group of experienced programmers several
tries to impliment this simple switch statement without actually using
switch.  I dare say with standard switch syntax we would've had it right
the first time :-)
I wasn't following this thread all the way through, but to be honest,
I'd have solved this differently -- that may be the best "direct
translation" of some switch statement, but that doesn't mean it's the
best-fit solution here.  ISTM that, given the desire to print some
text (or nothing) based on the contents of a variable, I would *not*
handle the output inside the "switch" -- that is, I'd (conditionally)
print a value from a string-containing dictionary, rather than use a
table of functions that print strings.
table = { 'a': 'a', 'b': 'b or c', 'c': 'b or c', 'd': None }
result = table.get(var, 'default case')
if result:
print result
This, to my mind, is much cleaner -- you're factoring out the repeated
code, whether print statement or call to sys.stdout.write(), reducing
the complexity of the dict.  You're making flow control much more
straightforward.  You're making the whole thing easier to read.
The key, here, is that instead of saying "I want a switch, how can I
implement that in Python?", I've taken the approach of "The end result
I want is ***; what tools does Python offer to achieve that?"  This
conceptual shift is, IMHO, *the* most important mental hurdle in
learning a [second/third/n-th] language.
Jeff Shannon
Technician/Programmer
Credit International

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] dictionary dispatch for object instance attributes question

2005-02-15 Thread Jeff Shannon
On Tue, 15 Feb 2005 17:19:37 -0500, Brian van den Broek
<[EMAIL PROTECTED]> wrote:

> My Node class defines a _parse method which separates out the node
> header, and sends those lines to a _parse_metadata method. This is
> where the elif chain occurs -- each line of the metadata starts with a
> tag like "dt=" and I need to recognize each tag and set the
> appropriate Node object attribute, such as .document_type. (I do not
> want to rely on the unhelpful names for the tags in the file format,
> preferring more self-documenting attribute names.)

In addition to using setattr(), I'd take a slightly different approach
to this.  (This may just be a matter of personal style, and is not as
clearly advantageous as using setattr() instead of exec, but...)


.class Node(object):
.metadata = {'dt': 'document_type', 'something': 'some_other_field', ...}
.def __init__(self):  # 
.def update(self, **kwargs):
.for key, value in kwargs.items():
.try:
.attr_name = self.metadata[key]
.except KeyError:
.raise ValueError("Invalid field type '%s'" % key)
.setattr(self, attr_name, value)

For starters, I've made metadata a class attribute rather than an
unconnected dictionary.  This seems conceptually nicer to me.

In addition, update() can now modify several attributes at once, at
the cost of a bit of extra parsing up front.

Supposing that your node header looks like this:

.header = "dt=text/plain;something=some_value;last=some_other_thing_here"

Now, we can break that into fields, and then split the fields into a
name and a value --

.tags = {}
.for field in header.split(';'):
.name, value = field.split('=')
.tags[name] = value
.
.n = Node()
.n.update(**tags)

You can even simplify this a bit more, by rewriting the __init__():

.def __init__(self, **kwargs):
.if kwargs:
.self.update(**kwargs)

Now you can create and update in a single step:

.n = Node(**tags)

You could also put all of the splitting into fields in a method, and
when __init__ gets a single string as its argument simply pass it to
that method and update with the results...

--Jeff Shannon
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Queued threads

2005-02-16 Thread Jeff Shannon
On Wed, 16 Feb 2005 16:50:07 +1300, Liam Clarke <[EMAIL PROTECTED]> wrote:
> Oops, you probably want to do this then-
> 
> for i in range( 0, 3 ):
>  oThread = Thread( target=mainFunction ).start()
> 
> while oThread:
>  print 'sleeping 3 seconds'
>  time.sleep( 3 )

Probably not.  Note that, since oThread's value is not changed in the
body of this while loop, you will either never execute the body (if
oThread is false) or execute it infintely many times (if oThread is
true).  I doubt that's the desired behavior. ;)

In this case, since Thread.start() apparently always returns None, the
while loop is effectively a no-op.  However, if it *did* get
triggered, it would do so immediately after the first thread [which
returned a true value from start()] was started -- preventing later
threads from being started because the main program is stuck in this
endless loop.

You could perhaps rewrite the whole thing like this:

.for i in range(3):
.mythread = Thread(target=mainFunction)
.mythread.start()
.while mythread.isAlive():
.print "sleeping 3 seconds [main thread]"
.time.sleep(3)

Though as others have said, if you're not starting the second thread
until the first is finished, then you might as well just make it
explicitly sequental and not bother with threads:

.for i in range(3):
.mainFunction()

If you actually want the threads to process concurrently, and simply
wait until all of them are done, you could do this:

.threadlist = []
.for i in range (3):
.mythread = Thread(target=mainFunction)
.mythread.start()
.threadlist.append(mythread)
.for thread in threadlist:
.thread.join()

The join() method will wait until that thread is finished, and then
return.  If the thread is already finished when it's called, it
returns immediately.

Jeff Shannon
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] dictionary dispatch for object instance attributes question

2005-02-16 Thread Jeff Shannon
On Tue, 15 Feb 2005 23:48:31 -0500, Brian van den Broek
<[EMAIL PROTECTED]> wrote:
> Jeff Shannon said unto the world upon 2005-02-15 21:20:
> > On Tue, 15 Feb 2005 17:19:37 -0500, Brian van den Broek
> > <[EMAIL PROTECTED]> wrote:
> >
> > For starters, I've made metadata a class attribute rather than an
> > unconnected dictionary.  This seems conceptually nicer to me.
> 
> The problem is that my Node instance live in a TP_file class instance,
> and the way my code is now, the TP_file instance also needs to see the
> metadata dict. There are a few tags, which if present in any Node of
> the file make me want to treat the entire file a bit differently. (Of
> course, here is the place where my novice-designer status is most
> likely to be bitting me.) So, that's why I have it as a module level
> object, rather than within a class. (I do, however, see your point
> about it being neater.)

Okay, that makes sense.  You have two different classes (the TP_file
class and the Node class) that need access to the same information, so
yes, having it at the module level lets them share it more
effectively.  (Alternately, since it sounds like the TP_file class is
where all of the Node instances are created, you *could* decide that
the metadata belongs as part of the TP_file, which would then actively
share it with Node... but what you've got sounds like a very
reasonable plan, so at this point I wouldn't worry about it.)

> > In addition, update() can now modify several attributes at once, at
> > the cost of a bit of extra parsing up front.
> 
> The metadata all occurs one element to a line in my original file.
> [...] Maybe I'm still missing a better way, but as I am processing
> line by line, each line with one element, I don't see how to use this
> cool looking multiple elements at once approach. 

Yes, if you know that you will only have one header per line, then
it's reasonable to process them one line at a time.  You could
alternatively have the TP_file gather all the header lines for a given
node into a list, and then process that list to create the Node
instance, but given the specifics of your case you probably wouldn't
gain anything over your current approach by doing so.

This is what makes programming so interesting -- there's so many
different choices possible, and which one is best depends on a large
number of factors.  When writing a program for some task, the best
design for a particular set of circumstances may be completely
different than the best design for a somewhat different particular set
of circumstances -- and the best design for general usage is probably
an altogether different thing still.

Good luck!

Jeff Shannon
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Help needed with script to batch-create shapefiles

2005-02-16 Thread Jeff Shannon
On Wed, 16 Feb 2005 21:37:10 +, Chris Bromley
<[EMAIL PROTECTED]> wrote:

> Any help would be greatly appreciated!

Others have already pointed out that we will have a hard time helping
without a bit more information.  But I've noticed something odd in
your code -- it probably doesn't have anything to do with your
problem, but it seems like an awkward idiom to me.

> fc = fcs.next()
> 
> while fc:
> # [...]
> fc = fcs.next()

This, it seems to me, is equivalent to (but less readable than) the following:

.for fc in fcs:
.# [...]

If you're going to do something with every member of a list, then it's
much more straightforward to use a for loop (which automatically
tracks the iteration) than to use a while loop and manually adjusting
the loop-controlling expression.

Actually, it occurs to me that this *might* cause a confusing result
in your code.  Presuming that fcs is a standard iterator (as your
usage of next() suggests), then calling next() on an exhausted
iterator will raise a StopIteration exception.  The for loop will
automatically handle that, but with your while loop it would be caught
by the following bare except statement.  That means that you'll run
(what I presume to be) your error-handling code even when you
successfully convert every member of fcs...

Jeff Shannon
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Active Python

2005-02-17 Thread Jeff Shannon
On Thu, 17 Feb 2005 15:54:43 -0800 (PST), Terry Carroll <[EMAIL PROTECTED]> 
wrote:
> On Wed, 16 Feb 2005, Robert Campbell wrote:
> 
> > I am not a programmer, but have decided to learn Python.  I am wondering
> > if anyone has used the Activestate ActivePython and what are the
> > advantages/disadvantages of using it rather than the standard Python
> > tools.
> 
> If you're on Windows, I recommend it.
> 
> It is the full Python, plus some Windows extensions.

I fully agree.  ActivePython contains everything that you'd get from
the standard distribution, plus extra tools that are especially useful
under Windows.  (I like PythonWin a lot more than IDLE...)
 
> The only downside I've encountered is that, as of 2.4, it no longer
> includes the Help files in their original HTML format.  Instead, there's
> just one big help file in Windows Help format.
> 
> I prefer the HTML, because I can then run searches against it from
> outside the help system.  

Interesting -- I prefer the CHM (Windows helpfile), because it's
internally indexed.  I feel that the internal search is more
convenient than external searches would be.  But I suppose that
there's room for reasonable people to disagree, here. :)

Jeff Shannon
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] SubClassing

2005-02-27 Thread Jeff Shannon
On Fri, 25 Feb 2005 05:54:39 -0200, Ismael Garrido
<[EMAIL PROTECTED]> wrote:
> def __init__(self, this, that, new):
> Parent.__init__(self, this, that)  #note self
> self.new = new

If the paren's init t has a lot of possible arguments, it may be
easier to do things this way:

class Child(Parent):
def __init__(self, new, *args, **kwargs):
Parent.__init__(self, *args, **kwargs)
self.new = new

This way, the Child class doesn't need to know or care about what
parameters get passed on to Parent; it uses the ones it needs, and
passes all the rest on.

Jeff Shannon
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Re: How do you share a method (function) among several objects?

2005-02-27 Thread Jeff Shannon
On Sun, 27 Feb 2005 20:20:19 +0200, Xif <[EMAIL PROTECTED]> wrote:
> There are two major classes:
> 
> 1) an Excel class, that represents of the whole Excel program
> 2) a Cells class, that abstracts retrieval  and editing of cells.
> 
> [...]
> 
> The difference between the 2 classes is that a Cells instance just
> converts the generator into a list and returns it:
> 
> #
> return list(getCells(self.sheet, cells))
> #
> 
> while an Excel instance returns the values of the cells:
> 
> #
> return [cell.Value for cell in getCells(self.sheet, cells)]
> #

Why not have the Excel class make use of the Cells class?  That is,
you construct a Cells object with the appropriate parameters, use it
to get the list of cells, and then iterate over that list getting
values?  You could probably find many other places in the Excel class
where it could be simplified by delegating to a Cells instance, too...

Jeff Shannon
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] sys.argv[1: ] help

2005-02-27 Thread Jeff Shannon
On Sun, 27 Feb 2005 17:55:54 +, Richard gelling
<[EMAIL PROTECTED]> wrote:
> 
> No What I get if I was to type in
> ./arg1.py a  b c
> 
> All I get is
> []

It sounds as though the command shell is not passing along the
additional parameters.  Try opening Windows Explorer, and go to the
Folder Options (in the Tools menu, IIRC).  Go to the "File Types" tab,
find PY (Python File), and click the "Advanced" button.  In the
resulting dialog, select the "open" action and click "edit", then look
at the command line that it's using.  You want something that looks
like:

"C:\Python23\python.exe" "%1" %*

The '%*' bit at the end is what I suspect may be missing in your settings.

(There's some chance that cmd.exe uses a different set of settings
than Windows Explorer does, in which case you'll have to research that
independently.  I know that you can use the "assoc" command to
associate the .py extension with the Python.File filetype, but I'm not
sure how to create filetypes or change actions that are taken upon
filetypes if it's different from the Explorer settings)

Jeff Shannon
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Criticism / Suggestions

2005-03-01 Thread Jeff Shannon
On Wed, 02 Mar 2005 01:17:28 -0500, Bill Kranec <[EMAIL PROTECTED]> wrote:

> [...] I wanted to be able to define
> multiple tournament objects off of the same roundlist, to avoid
> generating the list every time a new object is created.  I think what I
> really want to do is have a separate Round class, from which Tournament
> inherits the list of rounds.  I have started to implement something like
> this in my most recent version, but haven't finished it yet.  ( I need
> to understand class inheritance better. )

This sounds like a good idea, but inheritance is probably not the
right way to solve it.  Every Tournament contains a list of Rounds,
but it's probably not accurate to say that a Tournament is a type of
Round.  (Inheritance works best when it describes an "is-a"
relationship, not a "has-a" relationship.)

It's probably better to have Tournament and Round be independent
classes, but have Tournament instances hold a list of Rounds (which
may be passed in during initialization, or may be added later).  This
is called "composition", and is just as important (or perhaps more
important) of an idea as inheritance, even though inheritance gets all
the press.  ;)

Jeff Shannon
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Linked List

2005-03-06 Thread Jeff Shannon
On Sat, 5 Mar 2005 06:20:40 -0800 (PST), Shitiz Bansal
<[EMAIL PROTECTED]> wrote:

> In order to explain wat my problem is, here is an
> example code. Its not exactly what I am doing, I am
> using multiple threads and a rather complicated code
> so  try and understand the sense rather than the code
> itself.
> 
> >>> myls=range(50)
> >>> for i in myls:
> print i
> if i==20:
> myls.insert(5,5)
> 
> The point is, the list(both size and elements) is
> changing even as it is being operated upon.

My first thought was to say, "Use a queue.Queue."  But it appears that
you need to be able to do more than just add items at the end of the
queue.

I suspect that what you need is along the lines of a "priority queue".
 That is, something that works approximately like a queue, but when
you add items to it, you also specify a priority for them.  Then, when
you retrieve an item from the queue, what you get is not necessarily
the first-inserted item, but rather the item with highest priority.

You might want to check the Cookbook to see if there's a priority
queue recipe there.  If not, I suspect that Google can be convinced to
yield something...

Jeff Shannon
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] 2d list matrix 7 x 75 problem

2005-03-06 Thread Jeff Shannon
On Sun, 06 Mar 2005 09:49:43 +, Dave S <[EMAIL PROTECTED]> wrote:

> I need to generate a list 2d matrix of the kind ...
> 
> [['', '', '', '', ''], ['', '', '', '', ''], ['', '', '', '', ''], ['',
> '', '', '', ''], ['', '', '', '', '']]
> 
> except its dimensions need to be 7 x 75. I thought I had it sorted with
> 
> map2 = [ [''] *7 ] *75
> 
> until the coding screwed up & I realised I had 75 references to the same
> list :-(

Try:

map2 = [['']*7 for n in range(75)]

The list comprehension will execute ['']*7 each iteration, creating a
new list instead of just creating new references to the same list.


> Oh PS
> 
> Is there a more elegant solution to
> 
> if string == 'sun' or string == 'mon' or string == 'tue' or string ==
> 'wed' or string == 'thu' or string == 'fri' or string == 'sat':

Try:

if string in ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']:

(Or perhaps look into using the datetime module, depending on how
detailed your needs are.)

Jeff Shannon
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] unhashable objects (unrelated to previous topic)

2005-03-27 Thread Jeff Shannon
On Sun, 27 Mar 2005 18:08:41 -0500, Orri Ganel <[EMAIL PROTECTED]> wrote:
> Hello all,
> 
> I am attempting to implement a LinkedList in Python, and in doing so,
> have created a Node class which represents the elements of the
> LinkedList.  However, since these Nodes have custom-defined __lt__(),
> __gt__(), __le__(), __ge__(), __eq__(), and __ne__() methods, they
> are, for some reason, unhashable.  When I comment out these methods,
> Python makes no complaint. But when they are present, 'TypeError:
> unhashable instance' is raised when attempting to use a Node as a key
> in a dictionary. 

When you don't define __eq__(), Python will use an object's ID as its
hash value.  However, the standard usage of hashes implies that
objects which compare as equal should hash identically.  This means
that objects which define __eq__() and which are intended to be hashed
need to define a __hash__() method.  Be very careful if you're doing
this with mutable objects, though -- you need to either hash by object
identity or by object equality, and for mutable objects either choice
will leave you breaking an implied promise.  (Either a single object
will not hash the same at different points in its life, or objects
which are equal will not hash identically.)

Jeff Shannon
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] If elif not working in comparison

2005-03-28 Thread Jeff Shannon
On Mon, 28 Mar 2005 09:27:11 -0500, orbitz <[EMAIL PROTECTED]> wrote:
> Floats are inherintly inprecise.  So if thigns arn't working like you
> expect don't be surprised if 0.15, 0.12, and 0.1 are closer to the same
> number than you think.

However, the imprecision of floats is in the 10-12 precision digit
range.  That is, it's precise up to about 0.01 (or slightly
fewer decimal places if the integer part is large).  Given the
precision with which those constants are specified, I doubt that float
imprecision will be an issue here, unless there's a *lot* of repeated
operations, e.g. a loop with many (i.e. hundreds to thousands of)
iterations.

Jeff Shannon
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Launching a file browser

2005-03-30 Thread Jeff Shannon
On Mon, 28 Mar 2005 18:53:39 -0800, Mike Hall
<[EMAIL PROTECTED]> wrote:

> I my case the gui will be comprised of html and javascript, talking to
> python through system calls. I basically want to know if there's an
> equivalent of the "webbrowser()" module (which launches my browser) for
> file dialogs. This is what EasyDialogs should do, but does not.

If you're using html and browser scripting for your GUI, then you'll
probably need to use html and browser scripting for your file dialog
too.  A file dialog is just another GUI segment, so it should work the
same as the rest of your GUI.

Jeff Shannon
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Float precision untrustworthy~~~

2005-03-30 Thread Jeff Shannon
On Mon, 28 Mar 2005 22:13:10 -0500, Jacob S. <[EMAIL PROTECTED]> wrote:
> I've already deleted the recent thread--
> 
> But sometimes I agree with he who said that you can't trust floats at all.
> 
> The scientific theory suggests that if an output is not what it should be,
> then the hypothesis is untrue.
> In this case, the hypothesis is the fact that float division should always
> produce the same output as our decimal division used in common schools
> today. Since that is not always true, then floats are not trustworthy~~~
> frankly, the mere fact that floats are difficult to check with equality has
> bitten me more than anything I've met yet in python.

The scientific method is also quite well aware of the limits of
precision.  *EVERY* tool that you use to make measurements has
precision limits.  In most of those cases, the imprecision due to
measuring tools will overwhelmingly swamp the tiny bit of imprecision
involved with floating-point arithmetic.

It's also worth pointing out that most of the float imprecision isn't
anything inherent in the floats themselves -- it's due to converting
between binary and decimal representation.  Just as a phrase that's
translated from English into Russian and then back to English again
can have its meaning shifted, translating between different numerical
bases can create error -- but it's usually *much* less error than the
natural language translations cause.

Really, all this talk about floating-point imprecision is *way*
overblown.  It's important to be aware of it, yes, because in some
cases it can be relevant... but it's a *long* way from making floats
unusable or unreliable.

> >>> 64**(1/3) == 4
> False
> >>> 64**-3 == 4
> False
> >>> a = 1/3
> >>> a
> 0.1

Note that you'll have the same problems if you use a Decimal number
type, because there's also an imprecision with Decimals.  The problem
is that you're expecting a digital variable with a limited discrete
set of possible values to be equivalent to a rational number -- but no
binary or decimal floating-point number can exactly represent 1/3.  A
Decimal approximation would have a 3 as the final digit rather than a
1, but there *would* be a final digit, and *that* is why this can't
work.

> Why not just implement decimal or some equivalent and
> get rid of hidden, hard to debug headaches?   

Well, a Decimal type *has* been implemented... but it's just trading
one set of headaches for another.  What your code is apparently
expecting is a Rational type, which has been discussed ad infinitum
(and probably implemented several times, though not (yet) accepted
into the standard library); Rationals have the problem, though, that
any given operation may take an unpredictable amount of time to
execute.  Would you consider it an improvement if, instead of
wondering why you're not getting an equality, you were wondering
whether your machine had frozen?

There's always a trade-off.  It's important to be aware of the
weaknesses of the tools that you use, but *every* tool has weaknesses,
and it doesn't make sense to discard a tool just because you've
learned what those weaknesses are.

Jeff Shannon
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Launching a file browser

2005-04-01 Thread Jeff Shannon
On Mar 31, 2005 2:14 PM, Mike Hall <[EMAIL PROTECTED]> wrote:
> 
> >> It's been too long since I used Python on MacOSX, but IIRC you can't
> >> just run a Python GUI program from the shell. Or something like
> >> that...you should ask this one on the python-mac SIG mailing list:
> >> http://www.python.org/sigs/pythonmac-sig/
> >>
> >> Kent
> 
> I'm unclear on why a command like webbrowser.open() will comfortably
> launch your default web browser (in my case Safari), but something as
> ubiquitous to an OS as a file browser has special needs to launch.

At the OS level, these two actions are *completely* different.  The
webbrowser module launches an entirely separate program in its own
independent process, where the "file browser" is opening a standard
dialog inside of the current process and dependent upon the current
process' message loop.  (AFAIK, every GUI environment uses some sort
of message/event loop...)

I don't know Macs, but on Windows, the closest "file browser" parallel
to what the webbrowser module is doing would be
os.system("explorer.exe"), which launches a separate program in an
independent process.  However, if you're trying to get the results of
the file selection back into your own app, you need to do the file
browsing within your own process (or explicitly use some form of
inter-process communication).  In order to use a GUI file-browsing
dialog, you need to follow all the rules for a GUI program.

Jeff Shannon
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] random import errors?

2005-04-01 Thread Jeff Shannon
On Apr 1, 2005 3:20 PM, Jay Loden <[EMAIL PROTECTED]> wrote:
> I have a python script that runs on my webserver every fifteen minutes.  It
> has run for several months with absolutely no problems.  Suddenly, yesterday
> morning I got an email from cron with an import error for sre_constants (see
> below)

Since you're able to import these files manually, it's unlikely to be
a problem with your Python installation.  I'd suggest trying to figure
out what changed between the day before yesterday and yesterday.  I'm
just guessing here, but I'd expect that this is probably related to
either permissions or environment variables.

Jeff Shannon
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


[Tutor] odd behavior within __init__

2005-04-15 Thread Jeff Shannon
(Oops, forgot to change this to go to the list...)

On 4/14/05, Orri Ganel <[EMAIL PROTECTED]> wrote:
> On 4/14/05, Rich Krauter <[EMAIL PROTECTED]> wrote:
>
> On 4/14/05, Max Noel <[EMAIL PROTECTED]> wrote:
> >Well, if you want b and a to refer to the same object, just use b = 
> > a.
>
> If you'll look at my code, you'll see that I *did* try that approach,
> and it did not persist past __init__ for some reason:

That's because you re-bound the local name 'self', but that doesn't
affect anything outside the local namespace.  Remember, __init__()
returns None; the object has already been allocated before __init__()
is called, and while __init__() can mutate the object it can't affect
the reference that the interpreter has created.  (Unless you resort to
hacking the contents of the parent frame, but we won't get into that.
You *don't* want to do this.)

In this case, I agree that a factory is your best bet.

Jeff Shannon


>
> class Node:
> ...
> def __init__(self, cargo=None, prev=None, next=None, nod=False):
>   """x.__init__(...) initializes x; see
> x.__class__.__doc__ for signature"""
>   if not isinstance(cargo, Node) or nod:
>   self.cargo = cargo
>   self.prev = prev
>   self.next = next
>   else:
> #
>   self = cargo  ## see?
> #
>   print id(self), id(cargo)
>   print self.cargo
>
> >>> a = Node(1)
> >>> b = Node(a)
> 12932600 12932600
> 1
> >>> id(b)
> 12960632
>
> --
> Email: singingxduck AT gmail DOT com
> AIM: singingxduck
> Programming Python for the fun of it.
> ___
> Tutor maillist  -  Tutor@python.org
> http://mail.python.org/mailman/listinfo/tutor
>
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor