Re: Coding style

2006-07-18 Thread Volker Grabsch
Bruno Desthuilliers [EMAIL PROTECTED] schrieb:
 Carl Banks wrote:
 Bruno Desthuilliers wrote:
 
 I'm well aware of Python's semantics, and it's irrelvant to my
 argument.
[...]
 If the language
 were designed differently, then the rules would be different.

 Totally true - and totally irrelevant IMHO.

I strongly advise not to treat each others thoughts as irrelevant.
Assuming the opposite is a base of every public dicussion forum.


I assume here is a flaw in Python. To explain this, I'd like to
make Bruno's point clearer. As usually, code tells more then
thousand words (an vice versa :-)).

Suppose you have two functions which somehow depend on the emptyness
of a sequence. This is a stupid example, but it demonstrates at
least the two proposed programming styles:

--
 def test1(x): 
... if x:
... print Non-Empty
... else:
... print Empty
... 
 def test2(x):
... if len(x)  0:
... print Non-Empty
... else:
... print Empty
--

Bruno pointed out a subtle difference in the behaviour of those
functions:

--
 a = [] 
 test1(a)
Empty
 test1(iter(a))
Non-Empty
 test2(a)
Empty
 test2(iter(a))
Traceback (most recent call last):
  File stdin, line 1, in ?
  File stdin, line 2, in test2
TypeError: len() of unsized object
--


While test1() returns a wrong/random result when called with an
iterator, the test2() function breaks when beeing called wrongly.

So if you accidently call test1() with an iterator, the program
will do something unintended, and the source of that bug will be
hard to find. So Bruno is IMHO right in calling that the source
of a suptle bug.

However, if you call test2() with an iterator, the program will
cleanly break early enough with an exception. That is generally
wanted in Python. You can see this all over the language, e.g.
with dictionaries:

--
 d = { 'one': 1 }
 print d['one']
1
 print d['two']
Traceback (most recent call last):
  File stdin, line 1, in ?
KeyError: 'two'
--

Python could have been designed to return None when d['two'] has been
called, as some other (bad) programming languages would. This would
mean that the problem will occur later in the program, making it easy
to produce a subtle bug. It would be some effort to figure out the
real cause, i.e. that d had no entry for 'two'.

Luckily, Python throws an exception (KeyError) just at the original
place where the initial mistake occured. If you *want* to get None in
case of a missing key, you'll have to say this explicitly:

--
 print d.get('two', None)
None
--

So maybe bool() should also break with an exception if an object
has neither a __nonzero__ nor a __len__ method, instead of defaulting
to True. Or a more strict variant of bool() called nonempty() should
exist.

Iterators don't have a meaningful Boolean representation, because
phrases like is zero or is empty don't make sense for them. So
instead of answering false, an iterator should throw an exception
when beeing asked whether he's empty.

If a function expects an object to have a certain protocol (e.g.
sequence), and the given object doesn't support that protocol,
an exception should be raised. This usually happens automatically
when the function calls a non-existing method, and it plays very
well with duck typing.

test2() behaves that way, but test1() doesn't. The reason is a
sluttery of Python. Python should handle that problem as strict
as it handles a missing key in a dictionary. Unfortunately, it
doesn't.

I don't agree with Bruno that it's more natural to write
if len(a)  0:
...
instead of
if a:
...

But I think that this is a necessary kludge you need to write
clean code. Otherwise you risk to create subtle bugs. This advise,
however, only applies when your function wants a sequence, because
only in that can expect len(a) to work.

I also agree with Carl that if len(a)  0 is less universal than
if a, because the latter also works with container-like objects
that have a concept of emptiness, but not of length.

However, this case is less likely to happen than shooting yourself
in the foot by passing accidently an iterator to the function
without getting an exception. I think, this flaw in Python is deep
enough to justify the len()  0 kludge.


IMHO, that flaw of Python should be documented in a PEP as it violates
Python's priciple of beeing explicit. It also harms duck typing.


Greets,

Volker

-- 
Volker Grabsch
---(())---
Administrator
NotJustHosting GbR
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Coding style

2006-07-18 Thread Volker Grabsch
Bruno Desthuilliers [EMAIL PROTECTED] schrieb:
 PTY wrote:
 I was asking whether it was better style to
 use len() or not.

 FWIW, it's also more generic (you could have an object supporting
 pop() but not __len__()), less error-prone,

While I agree with all other points, I don't think that it's less
error-prone. See my other posting where I worked out this a flaw
of Python.


Greets,

Volker

-- 
Volker Grabsch
---(())---
Administrator
NotJustHosting GbR
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: triple quoted strings as comments

2006-02-06 Thread Volker Grabsch
Jorgen Grahn wrote:
 [...] developer had 
 commented out about 50 lines of C++ code by just putting a /* at the top 
 and a */ at the bottom.
[...]
 (#if 0 in C and C++ are better choices, but only marginally. Best is to
 remove the code unless you are sure it's needed again soon. Works in all
 languages.)

However, I'd only advise to do this if you are using a revision control.
Otherwise, you'll end up having a lot of backup files hanging around
which are even worse than multi-row comments. Or, even worse: If you
don't create backup files before removing code ...


Greets,

Volker

-- 
Volker Grabsch
---(())---
\frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt
[G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}}
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: dynamic class instantiation

2006-02-03 Thread Volker Grabsch
Kent Johnson wrote:
 Ognen Duzlevski wrote:
 I appreciate your comments. Basically, the reason why this code generator
 exists is the fact that I do not want to hard-code the resulting xml in 
 any way. The users of the web/db framework of which this solution is part of
 might like the web page definition I offer them, but, some might want to 
 extend it.
 While dom allows me to traverse an xml hierarchy - it does not allow me to
 give meaning to the tags. The only way to do that (for me) is to represent
 the tags as classes with containers containing other classes (tags) and so 
 on. Since
 I do not know ahead of time what the tags will be - I need to generate the 
 code
 to actually handle them.
 
 Can you suggest a better approach or did you already do that and I just 
 missed 
 it? :)

 Instead of generating Python code and importing it, you could create the 
 classes directly. You would still have your own language but no code 
 generator.

While I agree that this is much better than code generation, why not go
a step further?

Your description language could be as well a subset of the Python language.
So you could get rid of the parser, too. Add the meaning simply by creating
subclasses in Python.

This approach has the disadvantage of a slightly more complicated syntax of
the definition files. However, the advantage is that this syntax would be
valid Python code, so everyone who's learning it will also learn a small piece
of Python, and thus reusable knowlege. Learning a special newly invented
language (so-called DSL - domain specific language) is *not* resuable
knowledge.

The second advantage is a greater flexibility. You can use real Python code
to model some more complex definition files. Otherwise, you'll have to
enhance your definition language for every new feature or meta-feature
you introduce. In this case, your own language would become more and more
messy over time. Why don't you take a great, well-designed, simple, general
purpose language which already exist? ... such as Python ;-)

However, this is a completely different strategy: You wouldn't parse the
defintion files. Instead, your definition files are Python modules which
your application imports. This can be a security risk if you want these
modules to be edited online. However, if your definition files are only
put into a directory of the server, i.e. if you handle them just as your
Python sources anyway, this won't be a disadvantage. (Instead, if would be
a great advantage!)

So you have to decide yourself: Do you really need the description files
to be read in on-the-fly? Then stick with your own language. Are your
definition files more like modules/extensions which are installes together
with the source files? Then just *make* them source files, too, i.e.
realize your description files simply as Python modules.


Greets,

Volker

-- 
Volker Grabsch
---(())---
\frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt
[G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}}
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: dynamic class instantiation

2006-01-31 Thread Volker Grabsch
Ognen Duzlevski wrote:
 Kent Johnson [EMAIL PROTECTED] wrote:
 Ognen Duzlevski wrote:
  Say I got page as a string. How do I go about 
  instantiating a class from this piece of information? To make it 
  more obvious how do I create the page() class based on the page 
  string I have? 

 Use getattr().

 Hi Kent, this is exactly what I was looking for. I can't believe I didn't 
 think
 of getattr() myself! ;(

However, remember that this solves your problem just temporarily.

Your main problem is still a deep design failure. Code generators are
relicts, hard to maintain, and usually just plain ugly. Your application
isn't that special.

I'm sure you could replace 2/3 of your code with something much simpler
(and shorter!) just by not inventing a new language and using the power
of Python instead.

People often think that a new language simplifies their problem, and that
code generation saves work. However, a the code of the code generator has
to be maintained, too! That's what most people are realizing too late.
Also, simple class inheritance, closures and similar mechanisms save a
lot of work, too, they do their job even better than a code generator,
and they are a charm to maintain.

Even the magic (AKA meta-classes :-)) may be hard, but it's usually a
much simpler and cleaner approach than a code generator.

Don't generate Python code. Python is neither Java nor C, it's dynamic!


Greets,

Volker

-- 
Volker Grabsch
---(())---
\frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt
[G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}}
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python vs C for a mail server

2006-01-29 Thread Volker Grabsch
Jens Theisen wrote:
 What do you do when you want to no if a certain method or function is  
 actually used from somewhere, say foobar, it a language which allows  
 (and even encourages) that it could be called by:

 getattr(obj, foo + bar)()

No. The recommended way to do it is:

obj.foobar()

 There is no systematic way to find this call.

 In C++, just commend out the definition and the compiler will tell you.

In such a case I normally just grep for foobar. I did so (and I'll do so)
in C/C++, Python, and any other language.


Any programming language allows you to do strange/stupid stuff. But none
of them encourages it. So I can't see your point in any way.



Greets,

Volker

-- 
Volker Grabsch
---(())---
\frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt
[G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}}
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: psexec and os.popen help

2006-01-08 Thread Volker Grabsch
[EMAIL PROTECTED] wrote:
 popen3 did the trick. 

Use the modules subprocess ... it solves many problems, including
the problem of too many similar functions. :-)

These functions (execl, execv, popen, popen2, popen3, ...) are relicts
from C and very unpythonic. It's IMHO always a better programming style
to use subprocess.


Greets,

Volker

-- 
Volker Grabsch
---(())---
\frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt
[G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}}
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python linear algebra module -- requesting comments on interface

2005-09-09 Thread Volker Grabsch
C. Barnes wrote:
 Hi, I'm in the process of writing a Python linear
 algebra module.
 
 The current targeted interface is:
   http://oregonstate.edu/~barnesc/temp/linalg/

Is this going to become free software. If yes, what license
will you use?


So my suggestions:

In cases like these ones:

random_matrix(m, n=-1)
zero_matrix(m, n=-1)

.. I think it's better to set the default value to None
instead of a number:

random_matrix(m, n=None)
zero_matrix(m, n=None)

IMHO, this is more intuitive and more pythonic.

I also suggest to make the random function choosable:

random_matrix(m, n=None, randfunc=random.random)
random_vector(n, randfunc=random.random)

This way it's more easy for those who want another range
of numbers, or want another kind of distribution of the
random numbers.


At the top of your documentation, there is a link overview,
which is broken:

See _overview_ for a quick start.


Greets,

Volker

-- 
Volker Grabsch
---(())---
\frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt
[G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}}
-- 
http://mail.python.org/mailman/listinfo/python-list


What license to choose for Python programs? (PSF License vs. GPL/LGPL)

2005-07-25 Thread Volker Grabsch
Hi!

I noticed that many packages in the PyPI are using the PSF License.
Does this have a special reason? Is this the common standard license
for Python libraries?

I'm just asking because I'll release some bigger pieces of Python code 
to the Open Source Community. In my many projects before I just used
GPL or LGPL. This didn't have a special reason. They are just standard
OS licenses. I could also have used the BSD License, but I personally
like the GPL/LGPL more.

Of course I know that there are many, many other licenses out there.
I'm not interested in comparing them all for their slight differences.
I don't choose the license primarily for protecting my code. I want to
choose the license according to the most common/appropriate way of the
community.

So if it is complicated to include an LGPL'ed Python library in the
Python standard libraries, I'd release it under PSF License. I'd like
to hear some opinions about that. What licenses do you use, and what's
your personal reason for doing so?

Also, a quick overview about the various licenses would be nice. Not
a legal comparison, but a list about what type of code/programs/libs
is usually released under which license.


Thanks for your help,

Volker

-- 
Volker Grabsch
---(())---
\frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt
[G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}}
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: idiom for constructor?

2005-06-04 Thread Volker Grabsch
Peter Dembinski wrote:
 This is not a good use case for exec.  Use setattr:
 
 OK, true.
 From the other side: what are the usual uses of 'exec'?

An interactive Python interpreter. :-)

No, seriously: Introspection is always better than exec.
It is far less error phrone, especially because you don't need
to deal with quoting issues, and because you have an initial
syntax check of your Python code which is bypassed when using exec.

Similarly, try to avoid system() whenever possible.


Greets,

-- 
Volker Grabsch
---(())---
\frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt
[G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}}
-- 
http://mail.python.org/mailman/listinfo/python-list


Multiple cmps chained one after another

2005-05-14 Thread Volker Grabsch
Hello!

Ich just found a very nice 'pythonic' solution for an often appearing
problem. I didn't find it documented anywhere, so I'm posting it here.
If this isn't new in any way, I'd really like to get to know it.

Example problem:
I have some datetime objects and want to sort them, as here:

birthdays = [d1,d2,d3,d4]
birthdays.sort()

However, I don't want to sort them the default way. These are birthdays,
so only the month and day do matter, not the year. E.g.:

2003-01-01  should be smaller than  1984-05-01

So I have to write the comparison on my own, e.g.

def cmp_birthdays(d1,d2):
if d1.month  d2.month: return 1
if d1.month  d2.month: return -1
if d1.day  d2.day: return 1
if d1.day  d2.day: return -1
return 0

...
birthdays.sort(cmp_birthdays)

This implementation of cmp_birthdays is very ugly. Image you want to
chain more than 2 values in that cmp_birthdays. I also want to use the
builtin cmp function, not  and .

After thinking some minutes about it, I found a very nice solution:
I have some cmps one aftter another. If one if them return 1 oder -1,
it sould be returned. If it returns 0, the next cmp is used. In other
words: I have a sequence of numbers, and want to get the first one that
is not 0. (or return 0, if all numbers were 0)

But this is exactly what the or operator does, due to short-circuit
evaluation. In this example, that means:

def cmp_bithdays(d1,d2):
return cmp(d1.month,d2.month) or cmp(d1.day,d2.day)

The generic pattern is:

return cmp(...) or cmp (...) or cmp(...) or ...

I'm not sure whether this pattern is already a common recipe, but
I found it to be a very nice idea. :-)

Any opinions?


Greets,

Volker

-- 
Volker Grabsch
---(())---
\frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt
[G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}}
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Multiple cmps chained one after another

2005-05-14 Thread Volker Grabsch
Steven Bethard wrote:
 Robert Kern wrote:
  def mykey(d):
  return (d.month, d.day)
 
 The point here is that rather than chaining cmp() calls with ors, you 
 should just use a tuple -- the standard comparison order in tuples is 
 exactly what you're looking for.

That's an excellent idea! Thanks a lot. I really didn't think of the key=
argument.


Greets,

-- 
Volker Grabsch
---(())---
\frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt
[G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}}
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Multiple cmps chained one after another

2005-05-14 Thread Volker Grabsch
vincent wehren wrote:
 
 If you don't care about the year, why not just normalize the year
 to all be the same using the replace method of the date instance?

That's a very bad idea. In my example, this would work, but in reality
I don't sort datetime objects, of course! (Is there any real application
where you want to do that?)

Instead, I'm sorting Person objects using a birthday attribute.
Since I use these Person objects also in other places, they should never
be modified without just to be sorted. In general, the number side effects
should always be minimized.

 datesNorm = [obj.replace(year=1900) for obj in (dates)]
 datesNorm.sort()

This code would go bad especially in my situation, where my Person
objects are SQLObjects, thus the normalisation would be written into
the database. Okay, one could use transactions and rollback, but I
think, my point is clear now.

Nevertheless, I think you idea is very interesting. Is there any real
application where normalizing just for sorting would be reasonable?


Greets,

-- 
Volker Grabsch
---(())---
\frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt
[G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}}
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Multiple cmps chained one after another

2005-05-14 Thread Volker Grabsch
Peter Hansen wrote:
 
 Or just use the .timetuple() method on datetime objects and sort on the 
 8th element of the 9-element tuple, which is the day-of-the-year.

An interesting idea. But wouldn't sorting by (dd.month,dd.day) be more
effective?

In other words: Does .timetuple() create a tuple, or does it just return
a tuple which is present anyway?


Greets,

-- 
Volker Grabsch
---(())---
\frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt
[G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}}
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Multiple cmps chained one after another

2005-05-14 Thread Volker Grabsch
vincent wehren wrote:
 
|  If you don't care about the year, why not just normalize the year
|  to all be the same using the replace method of the date instance?
|
| That's a very bad idea. In my example, this would work, but in reality
| I don't sort datetime objects, of course! (Is there any real application
| where you want to do that?)
|
| Instead, I'm sorting Person objects using a birthday attribute.
| Since I use these Person objects also in other places, they should never
| be modified without just to be sorted. In general, the number side effects
| should always be minimized.
 
 Can you explain where you see a modification to the orginal object 
 happening?
 (or in any of the other solutions proposed for that matter...)

Sorry, my fault. I didn't read carefully enough.  X-)

 Not here I hope:
 
|  datesNorm = [obj.replace(year=1900) for obj in (dates)]
|  datesNorm.sort()

While you don't change the original objects, there's still a problem since
you're sorting the normalized values. However, I want to sort the original
list (i.e. the list of Person objects).

But that's not a real problem if one normalizes in a key function:

def key_birthday(d):
return d.replace(year=1900)
...
dates.sort(key=key_birthday)

..as suggested in other followups of my posting.

| Nevertheless, I think you idea is very interesting. Is there any real
| application where normalizing just for sorting would be reasonable?
 
 How about a case-insensitive sort of strings? (uppering being the 
 normalization step)
 Or getting rid of accented / special characters before sorting.
 These sound like fairly straight-forward use cases to me ;)

For your solution these are good examples. But my question was, whether
normalizing first, and just sorting the normalized values (not the original
values) is reasonable.

I.e., when I sort some strings case-insensitive, I don't want my resulting
(sorted) list to contain only lowercase string. But that's what I would
get if I used the algorithm you described above.


Greets,

-- 
Volker Grabsch
---(())---
\frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt
[G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}}
-- 
http://mail.python.org/mailman/listinfo/python-list