Re: pydoc preference for triple double over triple single quotes -- any reason?

2005-04-16 Thread Thomas Rast
Brian van den Broek <[EMAIL PROTECTED]> writes:

> It turns out that I was using '''triple single quotes''' and pydoc
> only pulls a description out from module docstrings that are formatted
> in """triple double quotes""". I've poked about with google, and
> cannot find any explanation of why pydoc should treat the two cases
> differently. Anyone have an idea?

Maybe because some editors, e.g. Emacs, do not (cannot) properly
handle triple quotes in syntax analysis and highlighting.  Instead,
the quotes are treated as ordinary quotes, which breaks

  '''This doesn't work'''

but not

  """This'll work"""

due to the apostrophe.  pydoc then probably decided to follow PEP 257
which says

  For consistency, always use """triple double quotes""" around
  docstrings.
  [http://www.python.org/peps/pep-0257.html]

- Thomas

-- 
If you want to reply by mail, substitute my first and last name for
'foo' and 'bar', respectively, and remove '.invalid'.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Name of IDLE on Linux

2005-04-02 Thread Thomas Rast
Edward Diener <[EMAIL PROTECTED]> writes:

> It is a pity the Python Linux binary installations do not
> create folders on the desktop or in the Gnome menu system with links
> to the Python to the documentation and a readme telling me what
> executables were installed.

Imagine they did, and the other 1392 packages (on my system) too :-)

Documentation usually resides in /usr/share/doc/,
/usr/share/doc/packages/ or similiar.  You're on an RPM-based
system, so

$ rpm -ql 

lists all files belonging to that package.  You should have little
trouble spotting the documentation files there.

- Thomas

-- 
If you want to reply by mail, substitute my first and last name for
'foo' and 'bar', respectively, and remove '.invalid'.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Performance issue

2005-04-02 Thread Thomas Rast
Tom Carrick <[EMAIL PROTECTED]> writes:

> In my attempted learning of python, I've decided to recode an old
> anagram solving program I made in C++. The C++ version runs in less
> than a second, while the python takes 30 seconds.

Indeed, your program can be improved to run about ten times as fast,
which (on my system, with 96274 entries in /usr/share/dict/words) is
below a second.

In general you should try to move the loops into C code, i.e. use
built-in functions instead of long 'for' blocks.

Some comments on your version:

> import string
>
> # Need a function to convert a string to a list to be
> # able to use the sort() function
> def string2list(s): [snipped]

list() achieves the same thing a lot faster.

> words = []

You do not need to initialize 'words' here, as you're overwriting it a
few lines afterwards.

> found = []
>
> anagram = raw_input("Find anagrams of word: ")
>
> f = open('words.txt', 'r')
> file = f.read()
> f.close()
>
> words = file.splitlines()

Try to avoid assigning to the names of built-in functions if you can.
Names like 'file', 'list', 'dict', 'map' etc. are often an obvious
choice, but overwriting them means that you don't "just" know what a
later use refers to.

> sorted_anagram = anagram.lower()
> sorted_anagram = string2list(anagram)
> sorted_anagram.sort(lambda x, y: cmp(x, y))

Unless you *really* have to, don't use comparison functions with
sort(), as they slow the operation considerably.  In this (as in most)
cases, a plain sorted_anagram.sort() does the trick, and in version
2.4 you can achieve custom sort orders with the optional 'key'
argument.  The sorted() built-in also comes in handy here.

> while words:
> if len(words[0]) == len(sorted_anagram):
> wordlist = string2list(words[0])
> wordlist.sort(lambda x, y: cmp(x, y))
> sorted_wordlist = wordlist
> if sorted_anagram == sorted_wordlist:
> found.append(words[0])
> del words[0]

Avoid this style of looping at all times!  Removing the first element
of a list is O(n), so looping through the whole list as above is
O(n**2).  In most cases you should use a for loop:

for word in words:
  # do something

which is O(n) of course.  If you do have to loop destructively, pop()
from the end (which is the default) like so:

while words:
  word = words.pop()
  # do something

This is also O(n), because removing the *last* element of a list is
O(1) (amortized; I suppose the implementation will occasionally shrink
the underlying array at linear cost).

> print "Anagrams of " + anagram + ": "
> while found:
> print found[0] + " "
> del found[0]

I assume you meant not to print a newline between the words, which
'print' does by default.  The best solution in that case is "
".join(found).

A better version (2.4+ only):

-- 8< -- 8< --
anagram = raw_input("Find anagrams of word: ")

words = open('words.txt', 'r')

sorted_anagram = sorted(anagram.lower())

found = []

for word in words.read().splitlines():
if len(word) == len(anagram) and sorted(word) == sorted_anagram:
found.append(word)

print "Anagrams of %s: %s" % (anagram, ' '.join(found))
-- >8 -- >8 --

Interestingly, the length comparison makes quite a difference!  I
removed it at first, thinking it was unnecessary.  Here are some
timings:

* Your original version (for comparison):

  $ time echo stop | python2.4 anagram_slow.py
  [...]
  real0m9.090s
  user0m8.790s
  sys 0m0.013s

* Your version, but with the O(n**2) loop replaced by an O(n) 'for':

  $ time echo stop | python2.4 anagram_forloop.py
  [...]
  real0m0.221s
  user0m0.134s
  sys 0m0.014s

* My version but with the length comparison removed:

  $ time echo stop | python2.4 anagram_no_lencmp.py
  [...]
  real0m0.408s
  user0m0.353s
  sys 0m0.010s

* My version as above:

  $ time echo stop | python2.4 anagram_fast.py
  [...]
  real0m0.144s
  user0m0.099s
  sys 0m0.008s

Hope that helps :-)

- Thomas

-- 
If you want to reply by mail, substitute my first and last name for
'foo' and 'bar', respectively, and remove '.invalid'.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python equivalent of script(1)

2005-01-01 Thread Thomas Rast
[EMAIL PROTECTED] writes:

> I would love to have a record of all what I've done, so I can edit
> this record into final script.

You can save the current input history with

>>> import readline
>>> readline.write_history_file("python.log")

If you want to log your whole session, including output, try using the
'screen' utility.

HTH
- Thomas

-- 
If you want to reply by mail, substitute my first and last name for
'foo' and 'bar', respectively, and remove '.invalid'.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: calling functions across threads

2004-12-29 Thread Thomas Rast
Steven Bethard <[EMAIL PROTECTED]> writes:

> I get the correct output, but if you run this yourself, you'll see
> that the numbers 1 through 10 aren't printed in sync with the writes
> (i.e. every half second); they're all printed at the end.  Could
> someone explain to me why this happens, and how (if possible) I can
> get the numbers printed in sync with the appends to the list?

I tried your code, and got the expected behaviour, i.e. the numbers
are printed every half second.  Maybe you have a buffering problem?

$ python2.4 -V
Python 2.4
$ uname -a
Linux thomas 2.6.9 #6 Sun Dec 19 17:45:53 CET 2004 i686 GNU/Linux

- Thomas

-- 
If you want to reply by mail, substitute my first and last name for
'foo' and 'bar', respectively, and remove '.invalid'.
-- 
http://mail.python.org/mailman/listinfo/python-list


getattr() woes

2004-12-28 Thread Thomas Rast
Hello

I've found out about a fundamental problem of attribute lookup, the
hard way.

asyncore.py uses the following code:

class dispatcher:
# ...
def __getattr__(self, attr):
return getattr(self.socket, attr)

Now suppose that I'm asking for some attribute not provided by
dispatcher: The lookup mechanism will apparently try to find it
directly and fail, generating an AttributeError; next it will call
__getattr__ to find the attribute.  So far, no problems.

But I used a property much like this:

>>> import asyncore
>>> class Peer(asyncore.dispatcher):
... def _get_foo(self):
... # caused by a bug, several stack levels deeper
... raise AttributeError('hidden!')
... foo = property(_get_foo)
...

and as the error message suggests, the original AttributeError is
hidden by the lookup mechanism:

>>> Peer().foo
Traceback (most recent call last):
  File "", line 1, in ?
  File "/usr/lib/python2.4/asyncore.py", line 366, in __getattr__
return getattr(self.socket, attr)
AttributeError: 'NoneType' object has no attribute 'foo'

Is there anything that can be done about this?  If there are no better
solutions, perhaps the documentation for property() could point out
this pitfall?

- Thomas

-- 
If you want to reply by mail, substitute my first and last name for
'foo' and 'bar', respectively, and remove '.invalid'.
-- 
http://mail.python.org/mailman/listinfo/python-list