Re: Intro to Pyparsing Article at ONLamp

2006-01-30 Thread Christopher Subich
Anton Vredegoor wrote:
 And pave the way for a natural language parser. Maybe there's even some
 (sketchy) path now to link computer languages and natural languages. In
 my mind Python has always been closer to human languages than other
 programming languages. From what I learned about it, language
 recognition is the easy part, language production is what is hard. But
 even the easy part has a long way to go, and since we're also using a

I think you're underestimating just how far a long way to go is, for 
natural language processing.  I daresay that no current 
computer-language parser will come even close to recognizing a 
significant fraction of human language.

Using English, because that's the only language I'm fluent in, consider 
the sentence:

The horse raced past the barn fell.

It's just one of many garden path sentences, where something that 
occurs late in the sentence needs to trigger a reparse of the entire 
sentence.  This is made even worse because of the semantic meanings of 
English words -- English, along with every other nonconstructed language 
that I know of, is grammatically ambiguous, in that semantic meanings 
are necessary to make 100% confident parses.

That's indeed the basis of a class of humour.

Generating human language -- turning concepts into words -- is the 
easy part.  A concept-English transformer would only need to 
transform into a subset of English, and nobody will notice the difference.

-- 
It's just an object; it's not what you think.
:wq
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Can a simple a==b 'hang' in and endless loop?

2006-01-19 Thread Christopher Subich
Claudio Grondi wrote:

 The Python tutorial '3.2 The standard type hierarchy' says:
 
 Ellipsis:  This type has a single value. There is a single object with 
 this value. This object is accessed through the built-in name Ellipsis. 
 It is used to indicate the presence of the ... syntax in a slice. Its 
 truth value is true.
 
 Not very helpful in understanding what it is, so it still belongs to the 
 dark unknown area of Python to me.
 Any hints towards enlightenment what this from the geometry known term 
 'ellipsis' mean in Python? Googling shows, that I am not the first who 
 doesn't know what it is in context of Python, so probably there is 
 already a good explanation somewhere, but where?

Ellipsis has a very well-known meaning -- but it's not geometry at all 
(that's ellipse).  From Webster online:

Ellipsis (noun):
1 a : the omission of one or more words that are obviously understood 
but that must be supplied to make a construction grammatically complete 
b : a sudden leap from one topic to another
2 : marks or a mark (as ... or · or --) indicating an omission (as of 
words) or a pause

 Does it mean you reject to try to give a solution because of the reason 
 why I seek for it, or do you want to say, that there is to your 
 knowledge no possible solution except those you have already given?

Your problem is badly specified.  It seems to boil down to:

Given a and b as some combination of builtin types, is it possible for 
the equality comparison (a==b) to hang?

The answer, so far as I know, is 'no'.  That said, the answer is useless.

Firstly, you ignore the possiblity that '==' raises some form of error. 
  I don't know of any builtins that raise TypeError or the like on 
comparison, but you've already seen examples that generate recursion 
errors.  In fact, since the situations likely to lead to looping in == 
constructs use recursion anyway (calling == on members of structure 
types), your infinite loop becomes a stack depth error.

Secondly, you also ignore objects with overloaded or otherwise custom 
__eq__ methods -- the default and well-documented way of supplying 
equality comparisons to custom objects, which are first-class citizens 
in a Python environment.  (In fact, (1).__cmp__(1) [which provides a 
general comparison] works.)  Since these methods can contain arbitrary 
Python code, comparison in Python *can* cause an infinite loop, IO, or 
your grandmother to find out just what you've been hiding on your computer.

If you want to find out something about the principles behind Python, 
ask about the principles flat-out; don't construct a contrived case like 
this and wonder when the community's response is mostly confusion.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OT: excellent book on information theory

2006-01-18 Thread Christopher Subich
Tim Peters wrote:
 Probably not, if Paul's American.  For example, here in the states we
 have Python Parks, where you go to look at scenery from inside your
 python.

As an American residing in Canada, I'll say that Python Parks are only 
fun if they spring for hydro -- otherwise it's kind of dark.

Parse that, non-Canadians. :)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: - E04 - Leadership! Google, Guido van Rossum, PSF

2006-01-11 Thread Christopher Subich
Fredrik Lundh wrote:
TAG.did.you.just.call.me.a.kook.questionmark
 
 
 TAG.no.dash.but.if.you.keep.replying.to.them.all.the.time.i.may.have.to.plonk.you.too.smiley

TAG.you're.it.exclamation.point.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Why keep identity-based equality comparison?

2006-01-10 Thread Christopher Subich
Antoon Pardon wrote:
 Op 2006-01-10, Peter Decker schreef [EMAIL PROTECTED]:

I don't see the two comparisons as equivalent at all. If two things
are different, it does not follow that they can be ranked.
 
 
 That a  b returns false doesn't imply that a and b can be ranked.
 take sets. set([1,2]) and set([1,3)) can't be ranked but 
 set([1,2])  set([1,3)) returns False just as set([1,2])  set([1,3))
 does.

Breaking my resolution already, but you're ignoring the fact that the 
set type uses the '' and '' operators from a set-theoretic, not 
number-theoretic point of view.  Saying set(1,3) is greater than 
set(1,2) is meaningless (and not false), because the mathematical basis 
of the operator in this context is superset -- set(1,3) is a superset 
of set(1,2) is well-defined and false.

Set uses '' and '' because the superset and subset symbols aren't on 
the keyboard.

In languages that allow operator overloading, there are always some 
well-defined cases where the operator is the simplest, clearest notation 
yet the operator has a meaning very distinct from the arithmetical 
operation.  As another example, Pyparsing uses '' to load a Forward 
declaration, for recursive grammars -- this obviously has nothing to do 
with bit-shifting.

Of course, cases like these two are fairly textbook examples for the 
argument that operator overloading is unclear; Python accepts the 
occasional ambiguity and allows (indeed encourages, to a reasonable 
degree) operator overloading for conciseness and expressiveness.


To reply to your other argument, Antoon:
 Maybe python should adopt both approaches and introduce a new family
 of comparators. Then one family will always succeed and the other
 family can throw an exception.
[snip]
 I think it is usefull because when I am looking for 1 in a list,
 I'm not necessarily happy when I find 1.0 or decimal(1).


I personally feel that the use cases for this other comparison (===?) 
are very restricted.  In fact, your example itself isn't even a use-case 
for this operator, because integer/float/decimal have well-defined 
equality comparisons already (that explicitly account for different 
types) -- the implicit not is implies !=, if __eq__ isn't defined 
behaviour isn't triggered.

The use-case for a === operator would seem to be restricted to when 
program behaviour is determined soley by a not equalling b.  If a 
wrong object is referenced by b, then the program might do a Bad 
Thing, because it expects b to be something else... except that the 
error would be caught later anyway -- probably by calling b.method() 
or somesuch.

In fact, even in more esoteric cases the behaviour of == as-is is 
useful; in the itertools.izip_longest discussion, this behaviour is 
implicitly used in the sentinel-stopping method 
(izip(chain(iter,sent),chain(iter,sent),...,stop=(sent,sent,sent,...)), 
to badly mangle the syntax).
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: inline function call

2006-01-05 Thread Christopher Subich
Diez B. Roggisch wrote:
 No. That is simply impossible in python as well as in java where functions
 are always virtual, meaning they are looked up at runtime. Because you'd
 never know _which_ code to insert of all the different foo()-methods that
 might be around there.

Not quite simply impossible -- inlining function/method calls could 
indeed be an optimization done (eventually) by PyPy or another 
Psyco-like optimizer.  In this case, function inlining is just something 
that You Can Do if you dynamically determine that the function is a 
constant object.

Since it is an optimization that makes an assumption about the constancy 
of an object, this wouldn't hold true in the general case; an 
interpreter which makes that dynamic optimization would need some degree 
if checks to make sure that the assumption remains valid.

So it's not technically impossible, at least in the majority of cases 
where functions are neither modified nor rebound, no current python 
interpreter makes that assumption.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Optimize function similiar to dict.update() but adds common values

2005-12-15 Thread Christopher Subich
Peter Otten wrote:
 
 def add_freqs3(freq1, freq2):
 total = dict(freq1)
 for key, value in freq2.iteritems():
 try:
 total[key] += value
 except KeyError:
 total[key] = value
 return total
 

Untested, but replacing the try/except pair with the following should be 
semantically equivalent and a bit faster:

total[key] = total.get(key,0) + value
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: const objects (was Re: Death to tuples!)

2005-12-14 Thread Christopher Subich
Gabriel Zachmann wrote:
 
 I was wondering why python doesn't contain a way to make things const?
 
 If it were possible to declare variables at the time they are bound to 
 objects that they should not allow modification of the object, then we 
 would have a concept _orthogonal_ to data types themselves and, as a 
 by-product, a way to declare tuples as constant lists.
.
.
.
 It seems to me that implementing that feature would be fairly easy.
 All that would be needed is a flag with each variable.

Nope, that's not all you need; in fact, your definition of 'const' 
conflates two sorts of constants.

Consider:

 const l = 1
 l = 2 # error?

And
 const l = []
 l.append(foo) # error?

with its more general:
 const foo = MyClass()
 foo.myMethod() # error?  myMethod might mutate.

And none of this can prevent:
 d = {}
 const foo=[d]
 d['bar']='baz'

The first constant is the only well-defined one in Python: a constant 
name.  A constant name would prohibit rebinding of the name for the 
scope of the name.  Of course, it can't prevent whatsoever mutation of 
the object which is referenced by the name.

Conceptually, a constant name would be possible in a python-like 
language, but it would require significant change to the language to 
implement; possibly something along the lines of name/attribute 
unification (because with properties it's possible to have 
nearly-constant[1] attributes on class instances).

The other form of constant, that of a frozen object, is difficult 
(probably impossible) to do for a general object: without knowing ahead 
of time the effects of any method invocation, it is very difficult to 
know whether the object will be mutated.  Combine this with exec/eval 
(as the most absurd level of generality), and I'd argue that it is 
probably theoretically impossible.

For more limited cases, and for more limited definitions of immutable, 
and ignoring completely the effects of extremely strange code, you might 
be able to hack something together with a metaclass (or do something 
along the lines of a frozenset).  I wouldn't recommend it just for 
general use.

Really, the single best purpose of constant names/objects is for 
compiler optimization, which CPython doesn't do as-of-yet.  When it 
does, possibly through the PyPy project, constants will more likely be 
discovered automatically from analysis of running code.

[1] -- barring straight modification of __dict__
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: OO in Python? ^^

2005-12-14 Thread Christopher Subich
Antoon Pardon wrote:
 Suppose we would add type declarations in python.
 So we could do things like
 
   int: a
   object: b
 
 Some people seem to think that this would introduce static
 typing, but the only effect those staments need to have
 is that each time a variable is rebound an assert statement
 would implicitly be executed, checking whether the variable is
 still an instance of the declared type.

Doesn't work; duck typing is emphatically not subclass-typing.  For this 
system to still work and be as general as Python is now (without having 
to make all variables 'object's), we'd need true interface checking. 
That is, we'd have to be able to say:

implements + like int: a

or somesuch.  This is a Hard problem, and not worth solving for the 
simple benefit of checking type errors in code.

It might be worth solving for dynamic code optimization, but that's 
still a ways off.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Newbie needs help with regex strings

2005-12-14 Thread Christopher Subich
Paul McGuire wrote:
 This isn't a regex solution, but uses pyparsing instead.  Pyparsing
 helps you construct recursive-descent parsers, and maintains a code
 structure that is easy to compose, read, understand, maintain, and
 remember what you did 6-months after you wrote it in the first place.
 
 Download pyparsing at http://pyparsing.sourceforge.net.


For the example listed, pyparsing is even overkill; the OP should 
probably use the csv module.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: lambda (and reduce) are valuable

2005-12-13 Thread Christopher Subich
Chris Mellon wrote:
 functions with real names is crucial to maintainable code. The only
 reason to ever use a lamdba in Python is because you don't want to
 give a function a name, and that is just not a compelling use case for
 GUI events.

Ah, but that neglects the sheer utility of delayed-evaluation 
expressions.  Consider the key= parameter to list.sort, et. al:

complicated_list.sort(key=lambda x: x[3])

Decorate-sort-undecorate is another way of doing this, but it's also 
boilerplate, involves list copies that have nothing to do with the flow 
of the program itself, and can possibly error (if done naively: key is 
comparable, but complex_list[i][0] isn't comparable, such as sorting a 
list of complex numbers by the real part, if two or more items have the 
same real).

The key= parameter was implemented just to make this sort of thing 
clearer and easier (and, in an odd way, actually more semantically 
explicit).  The utility of a full function for the key= is nice and 
necessary, but simultaneously a lot of the uses are going to be for 
one-off expressions (like item[3]).  There, the idea of a named function 
seems conceptual overkill.

The most significant problem with Python's lambda is that it's billed as 
an anonymous function, when it's really an encapsulated expression.  My 
preferred solution is to replace lambda with something along the lines 
of an 'expression comprehension,' with similar syntax to list and 
generator comprehensions as-is:

lambda param1, param2: stuff_with(param2,param1) would become

(param1, param2): stuff_with(param2, param1)
or, to become even more similar to comprehension syntax:
stuff_with(param2, param1) with (param1, param2)

The only real problem, parsing-wise, with this syntax is that it can 
sometimes conflict with the  or  operators if used without 
whitespace near comparisons.

The scope of what can be contained in the expression comprehension 
(lambda currently) is exactly the same as what can be contained in a 
list/generator comprehension, so why not capitalize on the parallelism?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Overloading

2005-12-09 Thread Christopher Subich
Johannes Reichel wrote:
 Hi!
 
 In C++ you can overload functions and constructors. For example if I have a
 class that represents a complex number, than it would be nice if I can
 write two seperate constructors
 
 class Complex:

Please do note, if you want this for the exact use of a Complex class, 
Python does have complex arithmetic built-in:

print (0 + 1j)

The other posted points are still valid (and generally applicable).
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Bitching about the documentation...

2005-12-07 Thread Christopher Subich
Fredrik Lundh wrote:
 Steven D'Aprano wrote:
 
 
Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo.
 
 
 Did you mean: Badger badger Badger badger badger badger Badger badger 
 Mushroom! Mushroom!

Thank you, I really needed that stuck in my head. :)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Calculating Elapsed Time

2005-12-07 Thread Christopher Subich
Peter Hansen wrote:
 A few things.
 
 1. Precision is probably the wrong word there.  Resolution seems 
 more correct.
 
 2. If your system returns figures after the decimal point, it probably 
 has better resolution than one second (go figure).  Depending on what 
 system it is, your best bet to determine why is to check the 
 documentation for your system (also go figure), since the details are 
 not really handled by Python.  Going by memory, Linux will generally be 
 1ms resolution (I might be off by 10 there...), while Windows XP has 
 about 64 ticks per second, so .015625 resolution...

One caevat: on Windows systems, time.clock() is actually the 
high-precision clock (and on *nix, it's an entirely different 
performance counter).  Its semantics for time differential, IIRC, are 
exactly the same, so if that's all you're using it for it might be worth 
wrapping time.time / time.clock as a module-local timer function 
depending on sys.platform.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Calculating Elapsed Time

2005-12-07 Thread Christopher Subich
Fredrik Lundh wrote:

 if I run this on the Windows 2K box I'm sitting at right now, it settles
 at 100 for time.time, and 1789772 for time.clock.  on linux, I get 100
 for time.clock instead, and 262144 for time.time.

Aren't the time.clock semantics different on 'nix?  I thought, at least 
on some 'nix systems, time.clock returned a cpu time value that 
measured actual computation time, rather than wall-clock time [meaning 
stalls in IO don't count].

This is pretty easily confirmed, at least on one particular system 
(interactive prompt, so the delay is because of typing):

Python 2.2.3 (#1, Nov 12 2004, 13:02:04)
[GCC 3.2.3 20030502 (Red Hat Linux 3.2.3-42)] on linux2
Type help, copyright, credits or license for more information.
  import time
  (c,t) = (time.clock, time.time)
  (nowc, nowt) = (c(), t())
  print (c() - nowc, t() - nowt)
(0.00195199989, 7.6953330039978027)

So caevat programmer when using time.clock; its meaning is different on 
different platforms.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Bitching about the documentation...

2005-12-07 Thread Christopher Subich
Steven D'Aprano wrote:

 S
 P
 O
 I
 L
 E
 R
  
 S
 P
 A
 C
 E
 
 
 
 Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo.
 
 Buffalo from the city of Buffalo, which are intimidated by buffalo
 from Buffalo, also intimidate buffalo from Buffalo.

And to do a small simplification on it, to illustrate just how painful 
that sentence really is, the semantically equivalent version:

N = buffalo from Buffalo

(N [that] N buffalo) buffalo N.

The dropping of the [that] is legal, if sometimes ambiguous, in English.

 I didn't say it was *good* English, but it is *legal* English.

Which is why natural language programming's never going to take off. :)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Bitching about the documentation...

2005-12-07 Thread Christopher Subich
Steven D'Aprano wrote:
 On Wed, 07 Dec 2005 11:45:04 +0100, Fredrik Lundh wrote:
 
Did you mean: Badger badger Badger badger badger badger Badger badger 
Mushroom! Mushroom!
 
 
 Er... no, I can't parse that. I suffered a Too Much Recursion error about
 the third Badger (I only have a limited runtime stack).

http://www.badgerbadgerbadger.com/

And now back to your regularly scheduled newsgroup, already in progress.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Is there no compression support for large sized strings in Python?

2005-12-05 Thread Christopher Subich
Fredrik Lundh wrote:
 Christopher Subich wrote:


I have access to an itanium system with a metric ton of memory.  I
-think- that the Python version is still only a 32-bit python
 
 
 an ILP64 system is a system where int, long, and pointer are all 64 bits,
 so a 32-bit python on a 64-bit platform doesn't really qualify.
 

Did a quick check, and int is 32 bits, while long and pointer are each 64:
Python 2.2.3 (#1, Nov 12 2004, 13:02:04)
[GCC 3.2.3 20030502 (Red Hat Linux 3.2.3-42)] on linux2
Type help, copyright, credits or license for more information.
  import struct
  struct.calcsize('i'),struct.calcsize('l'),struct.calcsize('P')
(4, 8, 8)

So, as of 2.2.3, there might still be a problem.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANN: Dao Language v.0.9.6-beta is release!

2005-12-05 Thread Christopher Subich
Paul McNett wrote:

 Having .NET and Java in the world makes me into more of a hero when I
 can swoop in and get the real business problem solved using Python.

+1QOTW
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: hash()

2005-12-05 Thread Christopher Subich
John Marshall wrote:

 I was actually interested in the mathematical/probability
 side rather than the empirical w/r to the current
 hash function in python. Although I imagine I could do
 a brute force test for x-character strings.

Hah.  No.

At least on the version I have handy (Py 2.2.3 on Itanium2), hash 
returns a 64-bit value.  Brute-forcing that in any reasonable length of 
time is rather impossible.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANN: Dao Language v.0.9.6-beta is release!

2005-12-05 Thread Christopher Subich
[EMAIL PROTECTED] wrote:
 
From The Design of Everyday Things, docs are a sign of poor design.
 Even a single word, such as the word Push on the face of a door, is
 an indication that the design can be improved.  Please, rethink the
 design instead of trying to compensate with more documentation.  

This quote, with a naive reading, would seem to imply that needing 
documentation is evidence of bad design.  I think we can all agree that 
this interpretation is ludicrous: the only programming language, for 
example, which does not need documentation is the natural language, and 
that contains so many ambiguities that humans often get instructions wrong.

If nothing else, documentation is necessary to explain why X instead of 
Y, when both X and Y are perfectly valid, but mutually exclusive 
choices (CamelCase versus underscore_names).

IMO, the correct interpretation of this reduces exactly to the principle 
of least surprise.  If a door needs to have a sign that says push, it 
means that a fair number of people have looked at the door and thought 
it was a pull-door.  But they expect it to be a pull-door based on 
/experience with other doors,/ not some odd Platonic ideal of door-osity.

Some surprise, however, (especially in Python) is necessary because the 
same feature can be seen more than one way: see the ever-present 
discussion about func(arg=default) scoping of default arguments.  While 
that's the way it is shouldn't cover up true design flaws, arbitrary 
replacement with another behaviour doesn't work either: the other way 
will, ultimately, need the same order of documentation to catch 
surprises coming from the other way.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Is there no compression support for large sized strings in Python?

2005-12-02 Thread Christopher Subich
Fredrik Lundh wrote:
 Harald Karner wrote:

python -c print len('m' * ((2048*1024*1024)-1))

2147483647
 
 
 the string type uses the ob_size field to hold the string length, and
 ob_size is an integer:
 
 $ more Include/object.h
 ...
 int ob_size; /* Number of items in variable part */
 ...
 
 anyone out there with an ILP64 system?

I have access to an itanium system with a metric ton of memory.  I 
-think- that the Python version is still only a 32-bit python, though 
(any easy way of checking?).  Old version of Python, but I'm not the 
sysadmin and I want to play around with python isn't a good enough 
reason for an upgrade. :)


Python 2.2.3 (#1, Nov 12 2004, 13:02:04)
[GCC 3.2.3 20030502 (Red Hat Linux 3.2.3-42)] on linux2
Type help, copyright, credits or license for more information.
  str = 'm'*2047*1024*1024 + 'n'*2047*1024*1024
  len(str)
-2097152

Yes, that's a negative length.  And I don't really care about rebinding 
str for this demo. :)

  str[0]
Traceback (most recent call last):
   File stdin, line 1, in ?
IndexError: string index out of range
  str[1]
Traceback (most recent call last):
   File stdin, line 1, in ?
IndexError: string index out of range
  str[-1]
Traceback (most recent call last):
   File stdin, line 1, in ?
SystemError: error return without exception set
  len(str[:])
-2097152
  l = list(str)
  len(l)
0
  l
[]

The string is actually created -- top reports 4.0GB of memory usage.

-- 
http://mail.python.org/mailman/listinfo/python-list


Unifying Attributes and Names (was: Re: Death to tuples!)

2005-11-29 Thread Christopher Subich
Bengt Richter wrote:

 If we had a way to effect an override of a specific instance's attribute 
 accesses
 to make certain attribute names act as if they were defined in 
 type(instance), and
 if we could do this with function instances, and if function local accesses 
 would
 check if names were one of the ones specified for the function instance being 
 called,
 then we could define locally named constants etc like properties.
 
 The general mechanism would be that instance.__classvars__ if present would 
 make

Nah... you're not nearly going far enough with this.  I'd suggest a full 
unification of names and attributes.  This would also enhance 
lexical scoping and allow an outer keyword to set values in an outer 
namespace without doing royally weird stuff.

In general, all lexical blocks which currently have a local namespace 
(right now, modules and functions) would have a __namespace__ variable, 
containing the current namespace object.  Operations to get/set/delete 
names would be exactly translated to getattr/setattr/delattrs.  Getattrs 
on a namespace that does not contain the relevant name recurse up the 
chain of nested namespaces, to the global (module) namespace, which will 
raise an AttributeError if not found.

This allows exact replication of current behaviour, with a couple 
interesting twists:
1) i = i+1 with i in only an outer scope acutally works now; it uses 
the outer scope i and creates a local i binding.
2) global variables are easily defined by a descriptor:
def global_var(name):
   return property(
lambda self: getattr(self.global,name),
lambda (self, v): setattr(self.global,name,v),
lambda self: delattr(self.global,name),
Global variable %s % name)
3) outer variables under write access (outer x, x = 1) are also 
well-defined by descriptor (exercise left for reader).  No more weird 
machinations involving a list in order to build an accumulator function, 
for example.  Indeed, this is probably the primary benefit.
4) Generally, descriptor-based names become possible, allowing some 
rather interesting features[*]:
i) True constants, which cannot be rebound (mutable objects aside)
   ii) Aliases, such that 'a' and 'b' actually reference the same bit, 
so a = 1 - b == 1
  iii) Deep references, such that 'a' could be a reference to my_list[4].
   iv) Dynamic variables, such as a now_time that implicitly expands 
to some function.
5) With redefinition of the __namespace__ object, interesting run-time 
manipulations become possible, such as redefining a variable used by a 
function to be local/global/outer.  Very dangerous, of course, but 
potentially very flexible.  One case that comes to mind is a profiling 
namespace, which tracks how often variables are accessed -- 
over-frequented variables might lead to better-optimized code, and 
unaccessed variables might indicate dead code.

[*] -- I'm not saying that any of these examples are particularly good 
ideas; indeed, abuse of them would be incredibly ugly.  It's just that 
these are the first things that come to mind, because they're also so 
related to the obvious use-cases of properties.

The first reaction to this is going to be a definite ew, and I'd 
agree; this would make Python names be non-absolute [then again, the 
__classvars__ suggestion goes nearly as far anyway].  But this 
unification does bring all the power of instance.attribute down to the 
level of local_name.

The single biggest practical benefit is an easy definiton of an outer 
keyword: lexical closures in Python would then become truly on-par with 
use of global variables.  The accumulator example would become:
def make_accum(init):
i = init
def adder(j):
   outer i #[1]
   i += j
   return i
return adder

[1] -- note, this 'outer' check will have to require that 'i' be defined 
in an outer namespace -at the time the definition is compiled-. 
Otherwise, the variable might have to be created at runtime (as can be 
done now with 'global'), but there's no obvious choice on which 
namespace to create it in: global, or the immediately-outer one?  This 
implies the following peculiar behaviour (but I think it's for the best):

  # no i exists
  def f(): # will error on definition
   outer i
   print i
  def g(): # won't error
   print i
  i = 1
  f()
  g()

Definitely a Py3K proposal, though.
-- 
http://mail.python.org/mailman/listinfo/python-list


Unifying Attributes and Names (was: Re: Death to tuples!)

2005-11-29 Thread Christopher Subich
Bengt Richter wrote:

 If we had a way to effect an override of a specific instance's
attribute accesses
 to make certain attribute names act as if they were defined in
type(instance), and
 if we could do this with function instances, and if function local
accesses would
 check if names were one of the ones specified for the function
instance being called,
 then we could define locally named constants etc like properties.
 
 The general mechanism would be that instance.__classvars__ if
present would make
 
Nah... you're not nearly going far enough with this.  I'd suggest a
full 
unification of names and attributes.  This would also enhance 
lexical scoping and allow an outer keyword to set values in an outer

namespace without doing royally weird stuff.

In general, all lexical blocks which currently have a local namespace 
(right now, modules and functions) would have a __namespace__
variable, 
containing the current namespace object.  Operations to get/set/delete

names would be exactly translated to getattr/setattr/delattrs. 
Getattrs 
on a namespace that does not contain the relevant name recurse up the 
chain of nested namespaces, to the global (module) namespace, which
will 
raise an AttributeError if not found.

This allows exact replication of current behaviour, with a couple 
interesting twists:
1) i = i+1 with i in only an outer scope acutally works now; it uses

the outer scope i and creates a local i binding.
2) global variables are easily defined by a descriptor:
def global_var(name):
   return property(
lambda self: getattr(self.global,name),
lambda (self, v): setattr(self.global,name,v),
lambda self: delattr(self.global,name),
Global variable %s % name)
3) outer variables under write access (outer x, x = 1) are also 
well-defined by descriptor (exercise left for reader).  No more weird 
machinations involving a list in order to build an accumulator
function, 
for example.  Indeed, this is probably the primary benefit.
4) Generally, descriptor-based names become possible, allowing some 
rather interesting features[*]:
i) True constants, which cannot be rebound (mutable objects
aside)
   ii) Aliases, such that 'a' and 'b' actually reference the same bit,

so a = 1 - b == 1
  iii) Deep references, such that 'a' could be a reference to
my_list[4].
   iv) Dynamic variables, such as a now_time that implicitly expands

to some function.
5) With redefinition of the __namespace__ object, interesting run-time

manipulations become possible, such as redefining a variable used by a

function to be local/global/outer.  Very dangerous, of course, but 
potentially very flexible.  One case that comes to mind is a
profiling 
namespace, which tracks how often variables are accessed -- 
over-frequented variables might lead to better-optimized code, and 
unaccessed variables might indicate dead code.

[*] -- I'm not saying that any of these examples are particularly good

ideas; indeed, abuse of them would be incredibly ugly.  It's just that

these are the first things that come to mind, because they're also so 
related to the obvious use-cases of properties.

The first reaction to this is going to be a definite ew, and I'd

agree; this would make Python names be non-absolute [then again, the 
__classvars__ suggestion goes nearly as far anyway].  But this 
unification does bring all the power of instance.attribute down to
the 
level of local_name.

The single biggest practical benefit is an easy definiton of an
outer 
keyword: lexical closures in Python would then become truly on-par
with 
use of global variables.  The accumulator example would become:
def make_accum(init):
i = init
def adder(j):
   outer i #[1]
   i += j
   return i
return adder

[1] -- note, this 'outer' check will have to require that 'i' be
defined 
in an outer namespace -at the time the definition is compiled-. 
Otherwise, the variable might have to be created at runtime (as can be

done now with 'global'), but there's no obvious choice on which 
namespace to create it in: global, or the immediately-outer one?  This

implies the following peculiar behaviour (but I think it's for the
best):

 # no i exists
 def f(): # will error on definition
 outer i
   print i
 def g(): # won't error
 print i
 i = 1
 f()
 g()
 
Definitely a Py3K proposal, though.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ncurses' Dark Devilry

2005-11-29 Thread Christopher Subich
Jeremy Moles wrote:
In article [EMAIL PROTECTED],
 Jeremy Moles [EMAIL PROTECTED] wrote:
I have a focus wheel of sorts that allows the user to do input on
various wigets and windows and whatnot. However, if I want to quickly
call addstr somewhere else in the application I have to:

 1. Store the YX coords of the cursor currently
 2. Use the cursor in the current action
 3. Restore the old cursor location


 
 All of the routines I can find in the ncurses library want to take
 control of the cursor object. That is: they either want to advance
 it's position (addstr) or not (addchstr), but they both certainly grab
 control of it; at least, visually.
 
 Basically what I'm looking for is a way to refresh a portion of a
 curses-controlled window without affecting the current location of the
 cursor or having to manually move it and move it back.

Why not wrap your 1-3 in a function of your own?  More generally, build 
a 'cursor location stack', probably using a list.  Add utility functions 
push_cur and pop_cur to push and pop the current location of the cursor 
from that stack (pop_cur actually resets the current cursor location for 
future printing).  Then your write over there becomes:

push_cur()
move_cursor(location)
write(text)
pop_cur()

which can be pretty easily wrapped in a single function.

Mind you, I don't use curses myself, but what would prevent this from 
working?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Class Variable Access and Assignment

2005-11-07 Thread Christopher Subich
Antoon Pardon wrote:
 Op 2005-11-04, Christopher Subich schreef [EMAIL PROTECTED]:
it's the Python 
idiosyncracy about operations on mutable types.  In this case, += 
mutates an object, while + returns a new one -- as by definition, for 
mutables.
 
 
 It is the combination of the two.
 
 If python had chosen for an approach like function namespaces, the
 problem wouldn't have occured either. What would have happened then
 is that the compilor would have noticed the a.x on the right hand
 side and based on that fact would then have deciced that all a.x
 references should be instance reference (at least in that function
 block). The a.x += ... would then result in an AttributeError being raised. 

Problem:

class B:
x = 1
classx = b()
instx = b()
instx.x = 5

def addtox(o):
o.x += 1

addtox(instx)
print B.x # 1
print instx.x # 6; we both agree on this one
addtox(classx) # You argue this should AttributeError
print B.x # ?! -- 1 currently, you argue 2 if no error
print class.x # we both agree 2, if no error


a.x is /not/ a namespace issue at all; it's an attribute issue.

.x is not a name, it is an attribute.  Python namespaces are lexically 
scoped, not dynamically scoped; if, as you argue, .x should be a name in 
a namespace, then you argue above that addtox in the above should work 
on instx but fail on classx.  But this /cannot be determined at compile 
time/, because the attribute space is attached to the object passed in 
as the parameter.

I repeat: this is not a name issue at all, it is an attribute issue. 
Python's behaviour is counterintuitive from some angles, but it is the 
only behaviour that is consistent with attributes in general, given the 
signature of __iadd__ as-is.

 
 You may prefer the current behaviour over this, but that is not the
 point. The point is that resolution of name spaces does play its
 role in this problem.

There are no name spaces.

 
 
 It also has little to do with mutable vs immutable types.
 Someone could implement an immutable type, but take advantage
 of some implemtation details to change the value inplace
 in the __iadd__ method. Such an immutable type would show
 the same problems.

Immutable? I do not think that word means what you think it means.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Class Variable Access and Assignment

2005-11-06 Thread Christopher Subich
Bengt Richter wrote:
 On Fri, 04 Nov 2005 10:28:52 -0500, Christopher Subich [EMAIL PROTECTED] 
 wrote:

is very much within the language specification.  Indeed, the language 
specification dictates that an instance variable b.a is created if one 
didn't exist before; this is true no matter if type(b.a) == int, or if 
b.a is some esoteric mutable object that just happens to define 
__iadd__(self,type(other) == int).
 
 But if it is an esoteric descriptor (or even a simple property, which is
 a descriptor), the behaviour will depend on the descriptor, and an instance
 variable can be created or not, as desired, along with any side effect you 
 like.

Right, and that's also language-specification.  Voodoo, yes, but 
language specification nonetheless. :)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Class Variable Access and Assignment

2005-11-04 Thread Christopher Subich
Antoon Pardon wrote:
 Op 2005-11-03, Stefan Arentz schreef [EMAIL PROTECTED]:
The model makes sense in my opinion. If you don't like it then there are
plenty of other languages to choose from that have decided to implement
things differently.
 
 
 And again this argument. Like it or leave it, as if one can't in general
 like the language, without being blind for a number of shortcomings.
 
 It is this kind of recations that make me think a number of people is
 blindly devoted to the language to the point that any criticism of
 the language becomes intollerable.

No, it's just that a goodly number of people actually -like- the 
relatively simple conceputal model of Python.

Why /shouldn't/

 a.x = foo

correspond exactly to

 setattr(a,'x',foo) #?

Similarly, why shouldn't

 foo = a.x

correspond exactly to

 foo = getattr(a,'x') #?

With that in mind, the logical action for

 a.x = f(a.x)

is

 setattr(a,'x',f(a,'x')) #,

and since

 a.x += foo

is equal to

 a.x = A.__iadd__(a.x,foo) # (at least for new-style classes
  # that have __iadd__ defined.  Otherwise, it falls back on
  # __add__(self,other) to return a new object, making this
  # evern more clear),

why shouldn't this translate into

 setattr(a,'x',A.__iadd__(getattr(a,'x'),foo)) #?

Looking at it this way, it's obvious that the setattr and getattr may do 
different things, if the programmer understands that instances (can) 
look up object attributes, and (always) set instance attributes.  In 
fact, it is always the case (so far as I can quickly check) that += ends 
up setting an instance attribute.  Consider this code:

  class foo:
x = [5]
  a = foo()
  a += [6]
  a.x
[5,6]
  foo.x
[5,6]
  foo.x = [7]
  a.x
[5,6]

In truth, this all does make perfect sense -- if you consider class 
variables mostly good for setting defaults on instances.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Class Variable Access and Assignment

2005-11-04 Thread Christopher Subich
Steven D'Aprano wrote:
 On Thu, 03 Nov 2005 14:13:13 +, Antoon Pardon wrote:
 
 
Fine, we have the code:

  b.a += 2

We found the class variable, because there is no instance variable,
then why is the class variable not incremented by two now?
 
 
 Because b.a += 2 expands to b.a = b.a + 2. Why would you want b.a =
 something to correspond to b.__class__.a = something?

Small correction, it expands to b.a = B.a.__class__.__iadd__(b.a,2), 
assuming all relevant quantities are defined.  For integers, you're 
perfectly right.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Class Variable Access and Assignment

2005-11-04 Thread Christopher Subich
Antoon Pardon wrote:
Since ints are immutable objects, you shouldn't expect the value of b.a
to be modified in place, and so there is an assignment to b.a, not A.a.
 
 
 You are now talking implementation details. I don't care about whatever
 explanation you give in terms of implementation details. I don't think
 it is sane that in a language multiple occurence of something like b.a
 in the same line can refer to different objects
 

This isn't an implementation detail; to leading order, anything that 
impacts the values of objects attached to names is a specification issue.

An implementation detail is something like when garbage collection 
actually happens; what happens to:

b.a += 2

is very much within the language specification.  Indeed, the language 
specification dictates that an instance variable b.a is created if one 
didn't exist before; this is true no matter if type(b.a) == int, or if 
b.a is some esoteric mutable object that just happens to define 
__iadd__(self,type(other) == int).
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Class Variable Access and Assignment

2005-11-04 Thread Christopher Subich
Antoon Pardon wrote:
 Well I wonder. Would the following code be considered a name binding
 operation:
 
   b.a = 5

Try it, it's not.

Python 2.2.3 (#1, Nov 12 2004, 13:02:04)
[GCC 3.2.3 20030502 (Red Hat Linux 3.2.3-42)] on linux2
Type help, copyright, credits or license for more information.
  a
Traceback (most recent call last):
   File stdin, line 1, in ?
NameError: name 'a' is not defined
  b = object()
  b.a
Traceback (most recent call last):
   File stdin, line 1, in ?
AttributeError: 'object' object has no attribute 'a'

Once it's attached to an object, it's an attribute, not a base name. 
The distinction is subtle and possibly something that could (should?) be 
unified for Py3k, but in cases like this the distinction is important.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Class Variable Access and Assignment

2005-11-04 Thread Christopher Subich
Antoon Pardon wrote:

 Except when your default is a list
 
 class foo:
   x = [] # default
 
 a = foo()
 a.x += [3]
 
 b = foo()
 b.x
 
 This results in [3]. So in this case using a class variable x to
 provide a default empty list doesn't work out in combination
 with augmented operators.

This has nothing to do with namespacing at all, it's the Python 
idiosyncracy about operations on mutable types.  In this case, += 
mutates an object, while + returns a new one -- as by definition, for 
mutables.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Class Variable Access and Assignment

2005-11-04 Thread Christopher Subich
Antoon Pardon wrote:
 Well maybe because as far as I understand the same kind of logic
 can be applied to something like
 
 lst[f()] += foo
 
 In order to decide that this should be equivallent to
 
 lst[f()] = lst[f()] + foo.
 
 But that isn't the case.

Because, surprisingly enough, Python tends to evaluate expressions only 
once each time they're invoked.

In this case, [] is being used to get an item and set an item -- 
therefore, it /has/ to be invoked twice -- once for __getitem__, and 
once for __setitem__.

Likewises, lst appears once, and it is used once -- the name gets looked 
up once (which leads to a += 1 problems if a is in an outer scope).

f() also appears once -- so to evaluate it more trhan one time is odd, 
at best.

If you know very much about modern lisps, it's similar to the difference 
between a defun and a defmacro.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Class Variable Access and Assignment

2005-11-04 Thread Christopher Subich
Bengt Richter wrote:
 
 It might be interesting to have a means to push and pop objects
 onto/off-of a name-space-shadowing stack (__nsstack__), such that the first 
 place
 to look up a bare name would be as an attribute of the top stack object, i.e.,

 name = name + 1
 

Don't be that specific; just unify Attributes and Names.

Instead of the 'name' X referring to locals()['X'] or globals()['X'], 
have a hidden namespace object/class, with lookups functioning akin 
to class inheritence.

This would allow, in theory, more uniform namespace behaviour with outer 
scoping:

x = 1
def f():
x += 1 # would work, as it becomes 
setattr(namespace,'x',getattr(namespace,'x')+1), just like attribute loookup

Also, with a new keyword outer, more rational closures would work:

def makeincr(start=0):
i = start
def inc():
   outer i
   j = i
   i += 1
   return j
return inc

 From a namespace object point of view, 'outer i' would declare i to 
be a descriptor on the namespace object, such that setting actions would 
set the variable in the inherited scope (getting actions wouldn't 
actually need modification, since it already falls-through).  At the 
first level, 'outer' would be exactly the same as 'global' -- indeed, it 
would be reasonable for the outer keyword to entirely replace global 
(which is actually module-scope).

As it stands, the different behaviours of names and attributes is only a 
minor quirk, and the fix would definitely break backwards compatibility 
in the language -- it'd have to be punted to Py3k.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Would there be support for a more general cmp/__cmp__

2005-10-28 Thread Christopher Subich
Antoon Pardon wrote:
 If you are concerned about sorting times, I think you should
 be more concerned about Guido's idea of doing away with __cmp__.
 Sure __lt__ is faster. But in a number of cases writing __cmp__
 is of the same complexity as writing __lt__. So if you then
 need a __lt__, __le__, __eq__, __ne__, __gt__ and __ge__ it
 would be a lot easier to write a __cmp__ and have all rich
 comparisons methods call this instead of duplicating the code
 about six times. So you would be more or less forced to write
 your class as class cld or cle. This would have a bigger
 impact on sorting times than my suggestion.

Honestly, I don't really mind the idea of __cmp__ going away; for 
classes that behave Normally with respect to a single __cmp__ value, 
it's easily possible to write a CompareMixin that defines __lt__, 
__gt__, etc. for suitable __cmp__ values.

Much like DictMixin is part of the standard library.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: syntax question - if 1:print 'a';else:print 'b'

2005-10-28 Thread Christopher Subich
Steve Holden wrote:

 On Thu, 2005-10-27 at 14:00, Gregory Piñero wrote:

 Not quite because if something(3) fails, I still want something(4) to
 run.  
 Then the obvious extension:
 
 for i in range(20):
...
 
 but I get the idea that Gregory was thinking of different statements 
 rather than calls to the same function with different arguments.


Sorry for the descendant-reply, but the original hasn't hit my news 
server yet (I think).

It sounds like Gregory wants a Python equivalent of on error continue 
next, which is really a bad idea almost everywhere.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Would there be support for a more general cmp/__cmp__

2005-10-26 Thread Christopher Subich
Antoon Pardon wrote:
 Op 2005-10-25, Christopher Subich schreef [EMAIL PROTECTED]:

My biggest complaint here is about returning None or IncomparableValue; 
if that happens, then all code that relies on cmp returning a numeric 
result will have to be rewritten.
 
 
 I don't know. There are two possibilities.
 
 1) The user is working with a total order. In that case the None
 or IncomparableValues won't be returned anyway so nothing about
 his code has to change.
 
 2) The user is working with a partial order. In that case cmp
 doesn't provide consistent results so the use of cmp in this
 case was a bug anyway.

Case 3) The user is working with an unknown class, using duck typing, 
and expects a total order.  If cmp suddenly returned Incomparable or 
None, the code would break in Unexpected Ways, with Undefined Behavior.

This is a classic exception versus error code argument; in this case, 
returning None would be the error flag.  It's almost always better to 
just throw the exception, because then this allows error-checking at a 
more natural level.

As for saying that cmp should return some times and raise an exception 
other times, I just find it squicky.
 
 
 But cmp already behaves this way. The only difference would be that
 the decision would be made based on the values of the objects instead
 of only their class.
 
 
Admittedly, this is entirely up to 
the class designer, and your proposed guideline wouldn't change cmp's 
behavior for clases that /are/ totally ordered.

Then again, sets excepted, your guideline doesn't seem very applicable 
in standard library code.
 
 
 Well AFAIAC this isn't specific about library code.

A change that cmp return a 4th possible value (None or Incomparable) 
is a fundamental language change.  Because this would break large 
amounts of existing code, it's a bad idea.

A change that cmp throw an exception iff the two objects, rather than 
the two classes, were incomparable (allowing comparisons of( 1+0j and 
2+0j) and ({a} and {a,b}) but not (1+1j and 2+0j) and ({a} and {b})) is 
a stylistic guideline, since it's already possible to write your own 
classes this way.  The only place this change would matter is in the 
standard library code, and in just a few places at that.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: textwidget.tag_bind(name, Any-KeyPress, self.donothing) not working

2005-10-26 Thread Christopher Subich
shannonl wrote:
 Hi all,
 
 For some reason this bind is calling the donothing function, like it
 should, but is then allowing the text to be inserted into the Text
 widget.
[...]
 This bind does work on the text widget as a whole, but on a individual
 tag, it does not.

You're trying to prevent a user from editing the text -within- a single 
tag.  Does Tk even support this?

Is your bind-applied-to-tag even firing, when the user presses a key 
within a tag?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Would there be support for a more general cmp/__cmp__

2005-10-25 Thread Christopher Subich
Antoon Pardon wrote:
 It *is* a definition of an ordering.
 
 For something to be an ordering it has to be anti symmetric and transitive.
 
 The subset relationships on sets conform to these conditions so it is a 
 (partial)
 ordering. Check your mathematic books, Why you would think this is abuse is 
 beyond me

Which is exactly why a  b on sets returns True xor False, but cmp(a,b) 
throws an exception.

a COMPARE b is a local comparison, asking only for the relationship 
between two elements.  In some bases, like the complex numbers, some 
comparisons are ill-defined.; in others, like sets, they're well-defined 
  but don't give a total ordering.

cmp(a,b) asks for their relative rankings in some total ordering.  For a 
space that does not have a total ordering, cmp(a,b) is meaningless at 
best and dangerous at worst.  It /should/ throw an exception when the 
results of cmp aren't well-defined, consistent, antisymmetric, and 
transitive.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Would there be support for a more general cmp/__cmp__

2005-10-25 Thread Christopher Subich
Antoon Pardon wrote:

 I also think there is the problem that people aren't used to partial
 ordering. There is an ordering over sets, it is just not a total
 ordering. But that some pairs are uncomparable (meaning that neither
 one is smaller or greater) doesn't imply that comparing them is
 ill defined.

It depends on your definition of comparison.  Admittedly, , =, !=, 
and  can be defined for a partial ordering, but classical mathematics, 
as understood by most people (even programmers), assumes that unless a 
== b, a  b or a  b.

The comparisons, as defined this way, are done on a totally ordered set, 
yes.  But since most comparisons ever done -are- done on a totally 
ordered set (namely the integers or reals), it's entirely fair to say 
that a programmer's expectation is that comparisons should work more 
or less like a totally ordered list.


With that caevat in mind, comparison on a partially ordered domain /is/ 
ill-defined; it can give inconsistent results from the a  b or a  b 
or a == b rule.

 
 Well it is a wrong assumption is general. There is nothing impure about
 partial ordering. 

Impure? Probably not.  Useless from many perspective when comparisons 
are needed, to the point where it's probably safer to throw an exception 
than define results.

 That is IMO irrelevant. The subset relationship is an ordering and as
 such has all characteristics of other orderings like less than,
 except that the subset relationship is partial and the less than
 relationship is total. How it is called subset vs less than is
 IMO irrelevant. It is about mathematical characteristics.

Still accident.   wouldn't be used for sets if we had a subset symbol 
on the standard keyboard, APL fans notwithstanding.  Simce programmers 
familiar with Python understand that  on sets isn't a real comparison 
(i.e. provide a total order), they don't expect unique, consistent 
results from something like sort (or a tree, for that matter).

 
 
By analogy, one can ask, is the cat inside the box? and get the answer
No, but this does not imply that therefore the box must be inside the
cat.
 
 
 Bad analogy, this doesn't define a mathematical ordering, the subset
 relationship does.

Yes, it does.  Consider in as a mathematical operator:

For the set (box, cat-in-box)

box in box: False
box in cat-in-box: False
cat-in-box in box: True
cat-in-box in cat-in-box: False

For the set (box, smart-cat) # cat's too smart to get in the box

box in box: False
box in smart-cat: False
smart-cat in box: False
smart-cat in smart-cat: False

In both these cases, the in operator is irreflexive, asymmetric, and 
transitive (extend to mouse-in-cat if you really care about transitive), 
so in is a partial order sans equality.  A useless one, but a partial 
order nonetheless.


Notice that L1 and L2 contain the same elements, just in different orders.
Sorting those two lists should give the same order, correct?
 
 
 No. Since we don't have a total ordering, sorting doesn't has to give
 the same result. For as far as sorting is defined on this kind of
 object, the only thing I would expect is that after a sort the
 following condition holds.
 
 for all i,j if i  j then not L[i]  L[j]

Highly formal, aren't you?  Again, common programming allows for not a 
   b == a = b, so your condition becomes the more familiar:

for all i,j in len(list), if i  j then L[i] = L[j]

This condition is also assumed implicitly by many other assumed rules 
of sorted lists, namely their uniqueness:

If L is a list of unique keys, then sort(L) is a unique list of keys in 
sorted order.

Yes, this assumes that L has a total order.  Big whoop -- this is a 
matter of programming practiciality rather than mathematical purity.

Personally, I argue that sorting is something that you do to lists, and
that all lists should be sortable regardless of whether the objects within
them have a total order or not. If not, the list should impose a sensible
ordering on them, such as (perhaps) lexicographical order (dictionary
order).

To reply to the grandparent poster here: that's not always easy to do. 
A sensible order isn't always easy to define on a set where a partial 
order exists, if it includes that order already.  Adding 
comparison-pairs to a partially ordered set (where incomparable elements 
throw an exception, rather than just return False which is confusing 
from sort's perspective) can easily result in a graph that isn't 
actually transitive and antisymmetric, i.e.:

A  B  C, but
C  D  A for some operator 

With this in mind, the only sensible thing for .sort to do when it 
encounters an exception is to fall back to its backup comparator (id, 
for example), and resort /the entire list/ using that comparator.  The 
results returned will then be valid by sort's comparison, but a subset 
of that list containing only good objects (like integers) may not (and 
probably won't be) sorted itself using the object's comparison.

The difficulty arises because while we may consider 

Re: Would there be support for a more general cmp/__cmp__

2005-10-25 Thread Christopher Subich
Antoon Pardon wrote:
 Op 2005-10-25, Christopher Subich schreef [EMAIL PROTECTED]:
 

Which is exactly why a  b on sets returns True xor False, but cmp(a,b) 
throws an exception.
 
 
 I don't see the conection.
 
 The documentation states that cmp(a,b) will return a negative value if
 a  b. So why should it throw an exception?

Because it's useful that cmp(a1, a2) should either (return a value) or 
(throw an exception) for any element a1, a2 within type(a1) cross 
type(a2).  If cmp sometimes is okay and sometimes throws an exception, 
then it leads to weird borkage in things like trees.

With that in mind, not all sets are comparable.  {a} and {b} have no 
comparison relationship, as you've pointed out, aside from not-equal. 
I'll get to why not-equal is a bad idea below.

cmp(a,b) asks for their relative rankings in some total ordering.
 
 
 The documentation doesn't state that. I also didn't find anything in
 the documentation on how the programmer should code in order to
 enforce this.

Most programmers are simply programmers; they haven't had the benefit of 
a couple years' pure-math education, so the distinction between partial 
order and total order is esoteric at best.

With that in mind, compare should conform, as best as possible, to 
intuitive behavior of comparison.  Since comparisons are mostly done 
on numbers, an extension of comparisons should behave as much like 
numbers as possible.

 
 So someone who just use the rich comparisons to implement his
 partial order will screw up this total order that cmp is somehow
 providing.
 
 And cmp doesn't provide a total ordering anyway. Sets are clearly
 uncomparable using cmp, so cmp doesn't provide a total order.

Cmp isn't supposed to provide a total order, it's supposed to reflect 
relative standing in one if one already exists for P1 x P2.  If one 
doesn't exist, I'd argue that it's the best course of action to throw an 
exception.

After all, rich comparisons were put in precisely to allow support of 
limited comparisons when a total order (or indeed full comparison) isn't 
appropriate.

 
 Maybe the original idea was that cmp provided some total ordering,
 maybe the general idea is that cmp should provide a total ordering,
 but that is not documented, nor is there any documentation in
 helping the programmer in this. 

I doubt that anyone was thinking about it in such depth.  My bet is that 
the thought process goes this way:

Og compare numbers.  Numbers good, compare good.  Grunt grunt.
some aeons pass
Language designers: Wouldn't it be nice if we could allow user-defined 
objects, such as numbers with units, to compare properly with each 
other?  This would let us say (1 m)  (.5 mile) pretty easily, eh?

Guido: Let's let classes override a __cmp__ function for comparisons.

In programming language theory, comparisons were firstly about numbers, 
and their leading-order behaviour has always stayed about numbers. 
Comparing entities which are best represented in an... interesting 
formal mathematical way (i.e. partial orders, objects for which some 
comparisons are Just Plain Weird) works only as a side-effect of 
number-like behavior.

The lesson to take home from this: the less a custom class behaves like 
a number, the less intutitively meaningful (or even valid) comparisons 
will be on it.

 
 And even if we leave sets aside it still isn't true.
 
 
from decimal import Decimal
Zero = Decimal(0)
cmp( ( ) , Zero)
 
 -1
 
cmp(Zero, 1)
 
 -1
 
cmp(1, ( ) )
 
 -1

I'd argue that the wart here is that cmp doesn't throw an exception, not 
that it returns inconsistent results.  This is a classic case of 
incomparable objects, and saying that 1  an empty tuple is bordering on 
meaningless.


 
For a 
space that does not have a total ordering, cmp(a,b) is meaningless at 
best and dangerous at worst.
 
 
 The current specs and implemantation are.
 
 I see nothing wrong with a function that would provide four kinds of
 results when given two elements. The same results as cmp gives now
 when it applies and None or other appropiate value or a raised
 exception when not.
 
 Given how little this functionality differs from the current cmp,
 I don't see why it couldn't replace the current cmp.

My biggest complaint here is about returning None or IncomparableValue; 
if that happens, then all code that relies on cmp returning a numeric 
result will have to be rewritten.

Comparing incomparables is an exceptional case, and hence it should 
raise an exception.

As for saying that cmp should return some times and raise an exception 
other times, I just find it squicky.  Admittedly, this is entirely up to 
the class designer, and your proposed guideline wouldn't change cmp's 
behavior for clases that /are/ totally ordered.

Then again, sets excepted, your guideline doesn't seem very applicable 
in standard library code.

It /should/ throw an exception when the 
results of cmp aren't well-defined, consistent, antisymmetric, and 
transitive.
 
 
 That an order

Re: Would there be support for a more general cmp/__cmp__

2005-10-21 Thread Christopher Subich
Antoon Pardon wrote:
 It would be better if cmp would give an indication it
 can't compare two objects instead of giving incorrect
 and inconsistent results.

If two objects aren't totally comparable, then using 'cmp' on them is 
ill-defined to begin with.  The Standard Thing To Do is throw an 
exception; see the Highly Obscure Case of the Complex Numbers.

 1 == 1j
False
 1 != 1j
True
 1  1j
Traceback (most recent call last):
   File stdin, line 1, in ?
TypeError: cannot compare complex numbers using , =, , =
 cmp(1j,1j)
0
 cmp(1,1j)
Traceback (most recent call last):
   File stdin, line 1, in ?
TypeError: cannot compare complex numbers using , =, , =

So using the well-known case of complex numbers, the semantics are 
already well-defined.

  class Incomparable:
... def __cmp__(self,other):
... raise TypeError(cannot compare Incomparables using , 
=, , =)
... def __eq__(self,other):
... return self is other
... def __neq__(self,other):
... return self is not other
  a1 = Incomparable()
  a2 = Incomparable()
  a1 == a1
1 # I'm running on python 2.2.3 at the moment, so hence the 1.
  a2 == a2
1
  a1 == a2
0
  a1  a2
Traceback (most recent call last):
   File stdin, line 1, in ?
   File stdin, line 3, in __cmp__
TypeError: cannot compare Incomparables using , =, , =
  cmp(a1,a2)
Traceback (most recent call last):
   File stdin, line 1, in ?
   File stdin, line 3, in __cmp__
TypeError: cannot compare Incomparables using , =, , =


So your use-case is already well-defined, and rather simple.  Make 
__cmp__ raise an exception of your choice, and define rich comparators 
only for the comparisons that are supported.  If, as you say in another 
post, some pairs in D cross D are comparable on an operator but not 
all of them (and further that this graph is not transitive), then your 
_ONLY_ choices, no matter your implementation, is to return some 
possibly inconsistent result (a  b == 1, b  c == 1, a  c == 0) or 
raise an exception for unapplicable comparisons.

This isn't a Python problem; this is a problem from formal mathematics.

Personally, I'd favor the raise an exception case, which is exactly 
what will happen if you define rich comparisons and let cmp throw an 
exception.  Operators that assume comparable objects, like sort, also 
almost always assume a total order -- inconsistent operations can give 
weird results, while throwing an exception will at least (usually) give 
some sort of error that can be caught.

Another poster mentioned the B-tree example, and that isn't solvable in 
this case -- B-trees assume a total order, but by their nature aren't 
explicit about checking for it; inserting a partial plus exception 
order might result in tree failure at weird times.  An inconsistent 
order, however, is even worse -- it would corrupt the tree at the same 
times.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Yes, this is a python question, and a serious one at that (moving to Win XP)

2005-10-19 Thread Christopher Subich
Chris Lambacher wrote:
 The shell that comes with MSys (from the MinGW guys). Is pretty good, although
 it does have a bit of a problem with stdout output before a process exits, ie
 it will hold back output until the process exits.
 
 As a bonus, the file system is a little more sane, and if you are interested
 in compiling software that is not open source, you are not tied to the Cygwin
 DLL which is GPLed.

Worth mentioning here that cygwin's gcc does allow a -mno-cygwin 
compile-time flag to not link against the cygwin dll.  Cygwin's 
packaging system also includes the MinGW development libraries as an 
easily installable option, for compiling against mingw's stuff; I've 
done it for Python extensions, in fact.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Can't extend function type

2005-10-07 Thread Christopher Subich
Diez B. Roggisch wrote:
 Paul Rubin wrote:
 
 Oh well.  I had wanted to be able to define two functions f and g, and
 have f*g be the composition of f and g.

  func_type = type(lambda: None)
  class composable_function(func_type):
 ...   def __mult__(f,g):
 ... def c(*args, **kw):
 ...   return f(g(*args, **kw))
 ... return c
 ...
 Traceback (most recent call last):
   File stdin, line 1, in ?
 TypeError: Error when calling the metaclass bases
 type 'function' is not an acceptable base type
 

 Seems like a wart to me.
 
 So the only way to achieve this with current semantics is to make f anf 
 g objects with a call methods. In that very moment, you're done - as 
 extending from object is no problem :)
 
 
 class ComposeableFunction(object):
 
 def __call__(self, *args, **kwargs):
 return self.second(self.first(*args, **kwargs))

Note, with a little bit of massaging, you can turn ComposableFunction 
into a decorator, for more natural function definition:

(Untested, I'm not on a system with Py2.4 at the moment):
class Composable(object):
 def __init__(self,f):
 self.callable = f
 def __call__(self,*args, **kwargs):
 return self.callable(*args, **kwargs)
 def __mul__(self,other):
 return Composable(lambda (*a, **kwa): self.callable(other(*a, 
**kwa)))

Usage:

@Composable
def f(x):
 return x**2

@Composable
def g(x):
 return x+1

# And we shouldn't even need a @Composable on the last in the sequence
def h(x):
 return x/2.0

 f(1)
1
 (f*g)(1)
4
 (f*g*h)(2)
4

This might not combine neatly with methods, however; the bound/unbound 
method magic is still mostly voodoo to me.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python interpreter bug

2005-10-07 Thread Christopher Subich
[EMAIL PROTECTED] wrote:
 No doubt you're right but common sense dictates that membership testing
 would test identity not equality.
 This is one of the rare occasions where Python defeats my common sense

But object identity is almost always a fairly ill-defined concept. 
Consider this (Python 2.2, 'cuz that's what I have right now):

Python 2.2.3 (#1, Nov 12 2004, 13:02:04)
[GCC 3.2.3 20030502 (Red Hat Linux 3.2.3-42)] on linux2
Type help, copyright, credits or license for more information.
  al = ab
  alp = al+c
  alphabet = abc
  al
'ab'
  alp
'abc'
  alphabet
'abc'
  alp is alphabet
0
  alp == alphabet
1 # True on Py2.4


The only reliable thing that object identity tells you is these two 
foos occupy the same memory location.  Even for identical, immutable 
objects, this may not be true (see case above) -- some immutables do end 
up occupying the same memory location (try i=1;j=2;k=j-1;i is k), but 
this is by no means guraranteed, and indeed only happens sometimes 
because of optimizations.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: socketServer questions

2005-10-07 Thread Christopher Subich
Paul Rubin wrote:
 rbt [EMAIL PROTECTED] writes:
 
1. Do I need to use threads to handle requests, if so, how would I
incorporate them?  The clients are light and fast never sending more
than 270 bytes of data and never connecting for more than 10 seconds
at a time. There are currently 500 clients and potentially there
could be a few thousand... how high does the current version scale?
 
 open for very long.  If you want to have longer-running connections
 open simultaneously, you need some type of concurrency such as threads.
 But then you have to write the code differently, to serialize the
 log recording.  
 
 You probably should get a copy of Python Cookbook which explains the
 basics of multi-threaded programming, if you have to ask a question

Or take a look at non-threaded ways of doing non-blocking IO; I've 
personally used the Twisted libraries and they work decently without 
manual thread overhead [indeed, the default reactor uses select, and 
there's a version for 'nix systems that uses poll].

Either way will work, it just depends on how deeply you want to 
integrate the network functionality into the code.  As someone else said 
(paraphrased, an apologies for stealing the quote; a Google search isn't 
bringing it up), You don't use Twisted, you provide Twisted callbacks 
to use you.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Overloading __init__ Function overloading

2005-09-30 Thread Christopher Subich
Iyer, Prasad C wrote:
 Thanks a lot for the reply.
 But I want to do something like this
 
 class BaseClass:
   def __init__(self):
   # Some code over here
   def __init__(self, a, b):
   # Some code over here
   def __init__(self, a, b, c):
   # some code here
 
 baseclass1=BaseClass()
 baseclass2=BaseClass(2,3)
 baseclass3=BaseClass(4,5,3)

In my experience, the vast majority of cases where you want function 
overloading, you really just want sensible default parameters.  Since 
Python is dynamically typed, the other common use case in static-typed 
language (to provide f(int,int), f(float,float), f(double,complex), 
f(Momma,Poppa) equivalents) is entirely unnecessary.

Try:

class BaseClass:
def __init__(self, a = None, b = None, c = None):
   if a == None:
  etc

or (if you want to take any number of parameters)

class BaseClass:
def __init__(self, *args):
   if len(args) == 0:
  etc

Of course, this is assuming that the behaviour is radically different 
based on the number of arguments, which is generally Poor Design.  You 
probably _REALLY_ want:

class BaseClass:
def __init__(self, a=SensibleDefault1, b=SensibleDefault2, 
c=SensibleDefault3):
   etc

As a concrete example of this, consider:

class Point:
def __init__(self, x=0, y=0, z=0):
   etc

Then you can call it with:
originPoint = Point()
pointInX = Point(xloc)
pointInXYPlane = Point(xloc,yloc)
pointIn3DSpace = Point(xloc,yloc,zloc)
note, normally I loathe CaMeLcAsE, but it's readable in this context

Or if the Defaults aren't quite so simple, and sensible defaults depend 
on previous values, use:

class BaseClass:
def __init__(self, a=SensibleDefault1, b=None, c=None):
   if b==None:
  b = stuff_involving(a)
   if c==None:
  c = stuff_involving(a,b)
   etc
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Single type for __builtins__ in Py3.0

2005-09-23 Thread Christopher Subich
Collin Winter wrote:
 Hallo all,
 I'd like to propose that in Py3.0 (if not earlier), __builtins__ will
 be the same type regardless of which namespace you're in. Tim Peters
 has said [1] that the reason __builtins__ in __main__ is a module so
 that the curious don't get flooded with output when doing vars() at
 the prompt. Based on this, I propose that __builtins__ be a module
 (really, an alias for the __builtin__ module as it is now) in all
 namespaces.
 
 If possible, I'd like to see this go in before 3.0. The reference
 manual currently states [2] that __builtins__ can be either a dict or
 a module, so changing it to always be a module would still be in
 keeping with this. However, I realise that there's probably code out
 there that hasn't been written to deal with both types, so this would
 result in some minor breakage (though it would be easily fixable).
 
 If this gets a good response, I'll kick it up to python-dev.

A few questions:

How would this change, if made in a minimal way, impact the provide 
alternate globals() and locals() to eval and exec feature?  Altering 
__builtins__ is a half-assed way of providing some sort of security, but 
it's probably useful in preventing user-supplied code from shooting 
itself in the foot without aiming first.

Secondly, wouldn't this also be a good time to implement modules as 
actual objects, so (e.g) modules could provide a __getattribute__ for 
references of the form modname.thing?

If the change can't be made without breaking the altering of 
__builtins__ for exec/eval, then I'm -0.5.  Otherwise, +1, and the 
second bit is probably good for further debate.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Writing a parser the right way?

2005-09-21 Thread Christopher Subich
beza1e1 wrote:
 Well, a declarative sentence is essentially subject-predicate-object,
 while a question is predicate-subject-object. This is important in
 further processing. So perhaps i should code this order into the
 classes? I need to think a little bit more about this.

A question is subject-predicate-object?

That was unknown by me.

Honestly, if you're trying a general English parser, good luck.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Proposal: add sys to __builtins__

2005-09-06 Thread Christopher Subich
Michael J. Fromberger wrote:

  While I'm mildly uncomfortable with the precedent that would be set 
by including the contents of sys as built-ins, I must confess my 
objections are primarily aesthetic:  I don't want to see the built-in 
namespace any more cluttered than is necessary -- or at least, any more 
than it already is.


I agree with this sentiment, and I'll also additionally say that 'import 
sys' doesn't seem to be needed when writing sufficiently high-level 
code.  My python mud client (forever in development, but the 
structure-code is mostly done) uses TKinter, Twisted, and glue code for 
just about everything.

In currently 1,080 lines of Python code (reported by wc -l, so it 
includes a few blank lines) in 9 files, I needed import sys once. [1]

After I import sys, I use it exactly once -- I check the platform so I 
can use the higher resolution time.clock on win32 [time.time on win32 
(win2k) seems to have a resolution of 10ms, while on a 'nix I tested 
with time.time has at least ms resolution].  I'll probably use sys again 
somewhere to build an automagic version/platform string, but uses for it 
seem to be very limited.

I also have 0 imports of 'os', and the only immediately useful case that 
comes to mind is implementation of a #dir scripting command -- providing 
a minimal shell functionality, and this is certainly not a core 
component of the program.

In my opinion, using 'sys' and 'os' are extreme examples of low-level 
Python programming.  This sort of thing is probably very useful for 
writing actual scripts that replace the sort of work done by shell 
scripts, but as programs get more complicated I think they'd be used 
(proportionally) less and less.

I'm -0.9 on sys (really don't like the idea but it wouldn't be awful to 
see it included in __builtins__, provided it's namespaced appropriately) 
and -1 on os.

[1] Actually, it's in there three times, but they're all in the same 
file -- I'd just left a legacy 'import sys' in a couple local scopes and 
forgot to remove them.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Spaces and tabs again

2005-08-13 Thread Christopher Subich
[EMAIL PROTECTED] wrote:

 Are you kidding? You are going to MANDATE spaces?

Actually, future whitespace rules will be extensive.  See:
http://64.233.187.104/search?q=cache:k1w9oZr767QJ:www.artima.com/weblogs/viewpost.jsp%3Fthread%3D101968
(google cache of 
http://www.artima.com/weblogs/viewpost.jsp?thread=101968 because it 
seems to be down at the moment)

The only change from April 1, 2005 is that the enforcement is punted 
until Python 3.0, because of the source-incompatible nature of the change.

Lrf, vg'f na Ncevy Sbbyf' wbxr..decode('rot13')
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: thread limit in python

2005-08-12 Thread Christopher Subich
[EMAIL PROTECTED] wrote:
 i modified my C test program (included below) to explicitly set the
 default thread stack size, and i'm still running into the same
 problem.  can you think of any other thing that would possibly be
 limiting me?

Hrm, you're on an A64, so that might very well mean you're dealing with 
4MB pages.  If each thread gets its own page of memory for stack space 
regardless of how small you've set it, then ~1k threads * 4MB ~= 4GB of 
virtual memory.
-- 
http://mail.python.org/mailman/listinfo/python-list


Unicode regular expressions -- buggy?

2005-08-11 Thread Christopher Subich
I don't think the python regular expression module correctly handles 
combining marks; it gives inconsistent results between equivalent forms 
of some regular expressions:

  sys.version
'2.4.1 (#65, Mar 30 2005, 09:13:57) [MSC v.1310 32 bit (Intel)]'
 re.match('\w',unicodedata.normalize('NFD',u'\xf1'),re.UNICODE).group(0)
u'n'
 re.match('\w',unicodedata.normalize('NFC',u'\xf1'),re.UNICODE).group(0)
u'\xf1'

In the above example, u'\xf1' is n-with-tilde (ñ).  NFC happens to be a 
no-op, and NFD decomposes it into u'n\u0303', which splits out the tilde 
as a combining mark.

Is this a limitation-by-design, or a bug?  If the latter, is it already 
known/to-be-fixed?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Does any one recognize this binary data storage format

2005-08-10 Thread Christopher Subich
Calvin Spealman wrote:
 
 Original Poster should send this off to thedailywtf.com

I absolutely agree.  This is a terrible programming practice.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Help with Regular Expressions

2005-08-10 Thread Christopher Subich
Paul McGuire wrote:
 If your re demands get more complicated, you could take a look at
 pyparsing.  The code is a bit more verbose, but many find it easier to
 compose their expressions using pyparsing's classes, such as Literal,
 OneOrMore, Optional, etc., plus a number of built-in helper functions
 and expressions, including delimitedList, quotedString, and
 cStyleComment.  Pyparsing is intended for writing recursive-descent
 parsers, but can also be used (and is best learned) with simple
 applications such as this one.

As a slightly unrelated pyparsing question, is there a good set of API 
documentation around for pyparsing?

I've looked into it for my mud client, but for now have gone with 
DParser because I need (desire) custom token generation sometimes. 
Pyparsing looks easier to internationalize, though.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: PEP 328, absolute/relative import

2005-08-10 Thread Christopher Subich
Ben Finney wrote:
 Once PEP 328 is fully implemented, all bare 'import foo' statements
 specify absolute imports (i.e. from sys.path only). To perform a
 relative import (e.g. from current directory) will require different
 syntax.

I'm not completely familiar with either, but how will that influence the 
__import__ function?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: regex help

2005-08-10 Thread Christopher Subich
jeff sacksteder wrote:
 Regex questions seem to be rather resistant to googling.
 
 My regex currently looks like - 'FOO:.*\n\n'
 
 The chunk of text I am attempting to locate is a line beginning with
 FOO:, followed by an unknown number of lines, terminating with a
 blank line. Clearly the .* phrase does not match the single newlines
 occuring inside the block.

Include the re.DOTALL flag when you compile the regular expression.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: don't understand instanse creation

2005-08-09 Thread Christopher Subich
Maksim Kasimov wrote:

 
  Hello,
 
  i have a class, such as below.
  when i try to make instances of the class,
  fields __data1 and __data2 gets different values: __data1 behaves 
like private field, __data2 - like static
  which is the thing i've missed?


Firstly, you get interesting behaviour of data1 and data2 because 
they're defined as mutable objects in the class sitself.  All instances 
of that class then share the same binding to the list, so appending to 
it in one instance will show up in other instances.

(Incidentally, be sure what you really want is name-mangled private 
variables, it's fairly uncommon for instance variables and methods to be 
private in Python code).

Your second issue is why data1 behaves differently.  This line:

  self.__data1 = self.__data2[:]


is the culprit.  Here, you assing __data1 to a *new* list, generated by 
copying __data2 (the : slice -- slices create a shallow copy, not a 
reference, of lists).  This rebinds the name __data1 to a new object, so 
the __data1 in the class definition is never modified like __data2 (with 
the .append).  You can demonstrate this by looking at the 'address' of 
the lists.  Modify the constructor thusly:

class my:

 __data1 = []
 __data2 = []

 def __init__(self):

 print __data1: , self.__data1, object.__repr__(self.__data1)
 print __data2: , self.__data2, object.__repr__(self.__data1)

 for i in time.localtime():
 self.__data2.append(i)
 self.__data1 = self.__data2[:]

 print __data1: , self.__data1, object.__repr__(self.__data1)
 print __data2: , self.__data2, object.__repr__(self.__data1)

And your tests now become:
  m1 = my()
__data1:  [] list object at 0x00EF2A80
__data2:  [] list object at 0x00A99620
__data1:  [2005, 8, 9, 10, 5, 54, 1, 221, 1] list object at 0x00A9AFD0
__data2:  [2005, 8, 9, 10, 5, 54, 1, 221, 1] list object at 0x00A99620
  m2 = my()
__data1:  [] list object at 0x00EF2A80
__data2:  [2005, 8, 9, 10, 5, 54, 1, 221, 1] list object at 0x00A99620
__data1:  [2005, 8, 9, 10, 5, 54, 1, 221, 1, 2005, 8, 9, 10, 5, 56, 1, 
221, 1] list object at 0x00A9D1C0
__data2:  [2005, 8, 9, 10, 5, 54, 1, 221, 1, 2005, 8, 9, 10, 5, 56, 1, 
221, 1] list object at 0x00A99620

Notice how the 'address' of __data1 changes after executing the 
constructor.  This change, made in __init__, is reflected only in that 
instance's copy of the name.  Also notice how __data2 in both m1 and m2 
share the same address; this is why changes in one instance are 
reflected in the others.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Passing arguments to function - (The fundamentals are confusing me)

2005-08-09 Thread Christopher Subich
Gregory Piñero wrote:
 Hey guys, would someone mind giving me a quick rundown of how
 references work in Python when passing arguments into functions?  The
 code below should highlight my specific confusion:

All arguments are passed by reference, but in Python equality rebinds 
the name.

 
 code
 
 bool1=True
 lst1=[1,2,3]
 
 def func1(arg1): arg1.append(4)

In C++, pretending it had dynamic typing, this would be equivalent to:
void func1( * arg1){
arg1-append(4);
}

 
 def func2(arg1): arg1=False
void func2 ( * arg2) {
arg2 = (False);

 Why does my list variable get changed for the rest of the program, but
 my boolean variable doesn't.  What am I not understanding?

In Python, x = y has a very definite meaning of y is assigned to the 
name of x.  This change does not affect whatever was in x to start 
with, and it certainly would not affect anything else which holds a 
reference to the object formerly known as x.

In contrast, calling a function which mutates the object (like .append 
on lists, or assignment by lst[index]=something) actually changes the 
object itself, which is of course reflected by all other names that hold 
a reference to the object.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Passing arguments to function - (The fundamentals are confusing me)

2005-08-09 Thread Christopher Subich
Dennis Lee Bieber wrote:
   In a more simplistic view, I'd reverse the phrasing... The name
 x is assigned to the object y (implying it is no longer attached to
 whatever used to have the name)

No, because that'd imply that the object 'y' somehow keeps track of the 
names assigned to it, which is only true from a refcount perspective -- 
and only on some Python implementations at that.  The object is the 
property of the name, not vice versa.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Does any one recognize this binary data storage format

2005-08-09 Thread Christopher Subich
[EMAIL PROTECTED] wrote:
 I am hoping someone can help me solve a bit of a puzzle.
 
 We are working on a data file reader and extraction tool for an old
 MS-DOS accounting system dating back to the mid 80's.
 
 In the data files, the text information is stored in clearly readable
 ASCII text, so I am comfortable that this file isn't EBCIDIC, however,
 the some of the numbers are stored in a format that we can't seem to
 recognize or unpack using the standard python tools (struct, binascii)
 ... or or atleast our understanding of how these tools work !
 
 
 Any assistance would be appreciated.
 
 Here are a few examples of telephone numbers;
 
 Exmaple 1:
 
 Phone 1: 5616864700
 Hex On Disk: C0DBA8ECF441
 
 Phone 2: 5616885403
 Hex on Disk: B0E9ADECF4F1

Is this value a typo instead of ...F441?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Does any one recognize this binary data storage format

2005-08-09 Thread Christopher Subich
Dejan Rodiger wrote:
 8003346488(10)=1DD096038(16)
 1D D0 96 03 8
 80 03 96 D0 1D 00
 80 03 96 d0 fd 41 Add E041

I'm pretty sure that the last full byte is a parity check of some sort. 
  I still thing that Phone2 (..F1) is a typo and should be 41.  Even if 
it's not, it could be a more detailed parity (crc-like?) check.

If the F1/41 is a typo, the last byte is ..41 if the parity of the other 
40 bits is odd, and ..42 if the parity is even. (Since ..41 and ..42 
each have two 1s, it does not change the parity of the entire string). 
If not, Lucy has some 'splaining to do.

Taking the last byte out of ther equation entirely, 40 bytes for 10 
decimal numbers is 4 bytes / number, meaning there is some redundancy 
still in the remainder (the full 10-digit number can be expressed with 
room to spare in 36 bits).

Thinking like an 80s Mess-Dos programmer, 32-bit math is out of the 
question since the CPU doesn't support it.  Five decimal digits already 
pushes the 16-bit boundary, so thinking of using the full phone number 
or any computation is insane.

#1/#2 and #4/#5 share both the first five digits of the real phone 
number and the last 16 bits of the remaining expression.  Both pairs 
*also* share bits 5-8 (the second hex digit).

Therefore, we may possibly conclude that digits 5-10 are stored in bits 
5-8 and 21-36.  This is an even 20 of the 40 data-bits.  In fact, bits 
6-8 of all expamples given were all 0, but since I can't find an 
equivalent always-x set for the other 5 digits I'm not sure that this is 
significant.

Therefore:
95442 = 8c701 = 1 + c701 (?)
56168 = 0ECF4 = 0 + ecf4 (?)

I'm not coming up with a terribly useful algorithm from this, though. :/ 
  My guess is that somewhere, there's a boolean check based on whether a 
digit is = 6 [maybe 3?] (to prevent running afoul of 16-bitness).  I'm 
also 90% sure that the first and second halves of the phone number are 
processed separately, at mostly, for the same reason.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Does any one recognize this binary data storage format

2005-08-09 Thread Christopher Subich
Grant Edwards wrote:
 That would just be sick.  I can't imagine anybody on an 8-bit
 CPU using FP for a phone number.

Nobody on an 8-bit CPU would have a FPU, so I'll guarantee that this is 
done using only 8 or 16-bit (probably 8) integer math.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Proposed new collection methods

2005-08-07 Thread Christopher Subich
Jeff Schwab wrote:
 Robert Kern wrote:
 Now, if I were to do

   item = g(self, test).next()

 the generator would execute the code until it reached the yield 
 statement which happens when it finds the first item that passes the 
 test. That item will get returned, and execution does not return to 
 the generator again.
[snip]
 Wow, that's cool!  Very reminiscent of C++ input iterators, but a lot 
 cleaner and shorter.  Thanks.

Read up on the __iter__ and __next__ methods that can be implemented by 
objects; Python objects have a very nice way of becoming (and returning) 
iterators.  Generator functions and expressions are magic ways of doing 
some Really Common Things as iterators.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Proposed new collection methods

2005-08-06 Thread Christopher Subich
Mike Meyer wrote:
 Another thread pointed out a couple of methods that would be nice to
 have on Python collections: find and inject. These are taken from
 URL: http://martinfowler.com/bliki/CollectionClosureMethod.html .
 
 find can be defined as:
 
  def find(self, test = None):
  for item in self:
  if test:
 if test(item):
return item
  elif item:
return item
  return ValueError, '%s.index(): no matching items in list' \
 % self.__class__.__name__

Dear Zeus no.  Find can be defined as:
def find(self, test=lambda x:1):
try:
   item = (s for s in iter(self) if test(s)).next()
except StopIteration:
   raise ValueError('No matching items in list')

Let's use generators, people. And given the simplicity of writing this, 
I'm not sure we need it in the standard library -- especially since the 
default test is arbitrary.  This recipe can also be useful for 
dictionaries, where the syntax would be slightly different, and 
lists-of-immutables, in which case returning the index in the list might 
be better.  Too much customization.

 inject is basically an OO version of reduce. You can define it in
 terms of reduce:

Except that if it's exactly reduce, we don't need to call it inject. 
The problem with reduce in python isn't that it's functional rather than 
OO, it's that it's limited to a function call or lambda -- one 
expression rather than an anonymous block.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Proposed new collection methods

2005-08-06 Thread Christopher Subich
Robert Kern wrote:
 Jeff Schwab wrote:
 Why are you retarded?  Isn't the above code O(n)?

 Forgive me for not understanding, I'm still awfully new to Python 
 (having come from Perl  C++), and I didn't see an explanation in the 
 FAQ.

 (s for s in iter(self) is test(s)) is a generator expression. It is 
 roughly equivalent to
[snip]
 That implementation does indeed return as soon as it locates the first 
 item, so yes, I was being retarded.

Thank you for the best programming-language related laugh I've had 
today. :)  I know just the kind of synapse-misfires that lead to 
completely obvious, yet also completely wrong conclusions like that -- 
I've done well more than my own share.

For the grandparent poster: generators and its baby brother generator 
expressions are the kind of really neat feature that you're never told 
about in CS101.  Generators themselves are relatively well-covered in 
the Python documentation, which should serve as a decent introduction to 
the topic.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Metaclasses and class variables

2005-08-04 Thread Christopher Subich
Jan-Ole Esleben wrote:
 class Meta(type):
   def __new__(cls, name, bases, d):
 d['classvar'] = []
 return type.__new__(cls, name, bases, d)

The problem is that __new__ is called upon object construction, not 
class definition, but you're trying to set the class variables at 
definition-time.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: cut paste text between tkinter widgets

2005-08-04 Thread Christopher Subich
Repton wrote:
This poses a small problem.  I'm not sure whether this is a
Win32-related issue, or it's because the PRIMARY selection isn't fully
configured.
 
 
 You need to select something first :-)
 

That doesn't work for inter-process communication, though, at least not 
with win32 native programs.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: 2-player game, client and server at localhost

2005-08-03 Thread Christopher Subich
Michael Rybak wrote:

 As stated above, that's how I'm trying it right now. Still, if doing
 it turn-base, I would have to create a new thread every time.
I have some other questions though - please see below.

No, you should never need to create a new thread upon receiving input. 
What you want is inter-thread communication, a synchronous queue.

A synchronous queue is a thread-safe queue.  You'd push event updates to 
it from the communication thread, and in the update thread, WHICH IS 
ALWAYS RUNNING, you'd check the queue each loop to see if there was 
anything new.

 Now, few questions. Do I need to time.sleep(0.xxx) in any of these
 while True: loops, not to overwhelm CPU? I can measure the time at
 beginning and end of each iteration to make things happen fixed number
 of times per second, but should I? And another: do I get it right that
 instead of lock global you mean:
   while global.locked:
   time.sleep(0.001)
   lock global
 And I also wonder how do I make sure that 2 threads don't pass this
 while loop simultaneously and both try locking global. There is a
 probability, not?

You have the right idea, that locking's important, but when the 
grandparent poster said lock global, he meant lock global.  Locks 
are low-level primitives in any threading system, they can also be 
called mutexes.

Attempting to acquire a lock returns immediate if the lock can be 
acquired; if it can't (and it's set to block, which is the default) the 
thread will wait until it -can- acquire the lock -- the entire thrust of 
your 'time.sleep' loop, only good.

See thread.acquire and threading.Lock for python built-in locks.

 In my yesterday experiment, I have a separate thread for each of 2
 clients, and what I do there is:
 
 def thr_send_status(player_sock):
 while 1:
 t, sub_addr = player_sock.recvfrom(128) #player ready to accept
 player_sock.sendto(encode_status(g.get_status()), sub_addr)
 
 I'm reading 1 byte from client every time before sending new update to
 him. OK, Ok, I know that's not good, ok. Now, I like your idea much
 more, where you say we first measure the processing speed of each
 client, and send data to every client as often as he can process it:

Just how much data are you sending in each second? Testing client speed 
and managing updates that way is relatively advanced, and I'd argue that 
it's only necessary when your data has the potential to swamp a network 
connection.

  While thinking about this, I've decided to go the wrong way, and to
 wait for confirmation from client before sending next pack.

No, you definitely don't need to do this.  TCP is a reliable protocol, 
and so long as the connection stays up your client will receive data 
in-order with guaranteed arrival.

If you were using UDP, then yes you'd need (possibly) to send 
confirmation, but you'd probably need a more advanced version to handle 
missing / out-of-order packets.

  I'm also almost sure it's wrong to have separate sockets and threads
 for each player, you say I should select()/dispatch instead, but I'm
 afraid of that some *thing* being wrong with select() for Windows.
 Somehow, I'm doing a lot of thins the wrong way :(

Just use the Twisted library.  It abstracts that away, and not touching 
sockets is really much nicer.

 Before describing another problem I've encountered, I thought I'd
 remind you of what my test game is: each player controls it's ball by
 moving mouse pointer, towards which his ball starts moving; that's it.

What's the nature of your evend update? Do you say mouse moved N or 
mouse moved to (123,456)?  If it's the latter, then without motion 
prediction there's no way that either simulation should have the ball 
overshoot the mouse.  Synchronization, however, will still be an issue.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: HELP:sorting list of outline numbers

2005-08-03 Thread Christopher Subich
Felix Collins wrote:
 Using Decorate, Sort , Undecorate...
 
 works like a charm.

As a one-liner, you can also deconstruct and rebuild the outline numbers:

new_outline = ['.'.join(v) for v in (sorted([k.split('.') for k in
old_outline]))]
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: cut paste text between tkinter widgets

2005-08-03 Thread Christopher Subich
William Gill wrote:
 Is there a simple way to cut and paste from a tkinter text widget to an 
 entry widget?  I know I could create a mouse button event that triggers 
 a popup (message widget) prompting for cut/paste in each of the widgets 
 using a temp variable to hold the text, but I don't wnat to reinvent the 
 wheel if there already is something that does the job.

1) TKinter text and entry widgets should already have proper event 
bindings for cut/copy/paste.  Test first with your system-default 
keyboard shortcuts (^C, ^X, ^V on Windows).  I haven't tried it myself, 
but I think those events bind to 'Cut', 'Copy', and 'Paste', 
so generating them should Do The Right Thing with selected text.

2) If you need to do any processing on the clipboard data, look at 
widget.selection_get [so named because of the way that X handles its 
clipboard]
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: cut paste text between tkinter widgets

2005-08-03 Thread Christopher Subich
Apologies in advance to anyone who has this post mangled, I use a couple 
Unicode characters at the end and Thunderbird wants to use UTF8 for the 
message encoding.  Unless it does something weird, this post should 
still be legible... but I'm not going to rely on that. :)

William Gill wrote:
 2) If you need to do any processing on the clipboard data, look at 
 widget.selection_get [so named because of the way that X handles its 
 clipboard]
 
  From my reading, w.selection_get will return the selected text in w, 
 and  places it on the clipboard.   I didn't see any way to get data from 
 the clipboard.

Not exactly.  The docs for selection_get say:

Return the contents of the current X selection.

A keyword parameter selection specifies the name of
the selection and defaults to PRIMARY.  A keyword
parameter displayof specifies a widget on the display
to use.

The X selection is another way of saying clipboard, again because of 
the way that X manages the clipboard.

In experimenting with this, I found a slight... fun issue involved in 
this.  Selection_get is the correct method to call, but it doesn't quite 
work out of the box.
  g.selection_get()
Traceback (most recent call last):
   File stdin, line 1, in ?
   File C:\Python24\Lib\lib-tk\Tkinter.py, line 574, in selection_get
 return self.tk.call(('selection', 'get') + self._options(kw))
_tkinter.TclError: PRIMARY selection doesn't exist or form STRING not 
defined

This poses a small problem.  I'm not sure whether this is a 
Win32-related issue, or it's because the PRIMARY selection isn't fully 
configured.  Regardless, even if it worked it still wouldn't be what we 
wanted; the selection we want is CLIPBOARD.  See this code:

  g.clipboard_clear()
  g.clipboard_append('I just love the wonderful clipboard management 
functions
  of Tk!')
  g.selection_get(selection='CLIPBOARD')
'I just love the wonderful clipboard management functions of Tk!'

And then, copying some text from this compose window...
  g.selection_get(selection='CLIPBOARD')
'And then, copying some text from this compose window...'

In theory, the clipboard will support more than text.  This support is 
nontrivial, which is code for saying that I have no idea how to get it 
to work.

Also, despite ICCCM standards, it looks like this clipboard management 
on win32 works as-is with unicode data -- under Tkinter, it returns a 
unicode string. (α β γ δ -- and good luck with -that- going through 
unmangled)
-- 
http://mail.python.org/mailman/listinfo/python-list

Re: Python's CSV reader

2005-08-03 Thread Christopher Subich
Stephan wrote:
 Can the CSV module be coerced to read two line formats at once or am I
 better off using read and split?

Well, readlines/split really isn't bad.  So long as the file fits 
comfortably in memory:

fi = open(file)
lines = fi.readlines()
evens = iter(lines[0::2])
odds = iter(lines[1::2])
csv1 = csv.reader(evens)
csv2 = csv.reader(odds)

The trick is that the csvfile in the CSV object doesn't have to be a 
real file, it just has to be an iterator that returns strings.  If the 
file's too big to fit in memory, you could piece together a pair of 
iterators that execute read() on the file appropriately.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: 2-player game, client and server at localhost

2005-08-02 Thread Christopher Subich
Michael Rybak wrote:
  That's the problem - or a player input comes in. As I've explained,
 this happens a dozen of times per second :(. I've even tried not
 checking for player's input after every frame, but do it 3 times more
 rare (if framecount % 3 == 0 : process_players_input()). Well, I've
 already got it that I shouldn't tie this around framerate, but
 nevertheless...

There's the key.  How are you processing network input, specifically 
retrieving it from the socket?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: 2-player game, client and server at localhost

2005-08-02 Thread Christopher Subich
Michael Rybak wrote:
 CS There's the key.  How are you processing network input, specifically 
 CS retrieving it from the socket?
 
 A sock class has a socket with 0.1 timeout, and every time I
 want anything, I call it's read_command() method until it returns
 anything. read_command() and send_command() transfer user's actions in
 special format so that it takes 10 bytes per transfer.

So when you want player input, you explicitly halt the program until you 
receive it, inside a while loop?  No wonder your programs aren't 
behaving well, then.

Network processing Is Not Slow.  Unless you're sending near the maximum 
capacity of your line, which you're obviously not[1], the slowness is 
architectural.

[1] - The TCP packet contains at most 28 bytes of overhead, so combine 
that with 10 bytes of data and you're looking at 38 bytes/packet.  A 
33.6 modem can handle 4.2kB/sec, cut that in half for a safety margin 
for 2.1kB/sec.  That will handle about 55 updates/second, which you 
shouldn't be reaching if you're just sending updates when a player does 
something.

Why are you messing with sockets directly, to begin with?  It looks like 
you want an asynchronous socket interface, so that you don't explicitly 
loop and wait for data from the nyetwork for updates.

In addition to making Julienne fries, Twisted is an excellent framework 
for asynchronous network IO.  For a naive, non-threaded implementation, 
you'd schedule your update code as a timed event, and you'd define a 
Protocol for handling your network stuff.  When you receive data, the 
protocl would update your application's state, and that would be picked 
up automagically the next time your update event ran.

In a threaded implementation, you'd run your update code to a thread 
(DeferToThread), and your network code would post updates to a 
synchronous queue, read by your update code.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Wheel-reinvention with Python

2005-08-01 Thread Christopher Subich
Paul Rubin wrote:
 I think my approach is in some sense completely typical: I don't want
 to install ANYTHING, EVER.  I've described this before.  I want to buy
 a new computer and have all the software I'll ever need already on the
 hard drive, and use it from that day forward.  By the time the

With all due respect, if you're allergic to installing software then why 
are you a developer?  To me, your view is somewhat akin to that of a 
woodworker who doesn't want to buy tools, or a painter who doesn't want 
to buy brushes.

Computers can be merely appliances, sure, but that's wasting the general 
purpose part of computation.  Software as separate packaging exists 
because we (collectively) don't always know what we want the first (or 
second, or third, or...) time around.  And when we do know what we want, 
we often muck it up when we try it.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Standard Threads vs Weightless Threads

2005-08-01 Thread Christopher Subich
yoda wrote:
 1)What is the difference (in terms of performance, scalability,[insert
 relevant metric here]) between microthreads and system threads?

System-level threads are relatively heavyweight.  They come with a full 
call stack, and they take up some level of kernel resources [generally 
less than a process].  In exchange, they're scheduled by the OS, with 
the primary benefit (on uniprocessor systems) that if one thread 
executes a blocking task (like IO writes) another thread will receive 
CPU attention.

The primary disadvantage is that they're scheduled by the CPU.  This 
leads to the concurrency nightmare, where the developer needs to keep 
track of what blocks of code (and data) need locks to prevent deadlock 
and race conditions.

 
 2)If microthreads really are superior then why aren't they the standard
 Python implementation (or at least within the standard library)? (where
 my assumption is that they are not the standard implementation and are
 not contained within the standard library).

Microthreads are very different; they're entirely internal to the Python 
process, and they're not seen at all by the operating system. 
Scheduling is done explicitly by the microthread implementation -- 
multitasking is not preemptive, as with system threads.

They're not in the standard library because implementing microthreads 
has thus far required a very large rewrite of the CPython architecture 
-- see Stackless Python.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Thaughts from an (almost) Lurker.

2005-07-31 Thread Christopher Subich
Robert Kern wrote:
 My experience with USENET suggests that there is always a steady stream 
 of newbies, trolls, and otherwise clueless people. In the absence of 
 real evidence (like traceable headers), I don't think there's a reason 
 to suspect that there's someone performing psychological experiments on 
 the denizens of c.l.py.

Er... yes! Exactly!

These are not the trolls you're looking for, move along. :)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: A replacement for lambda

2005-07-30 Thread Christopher Subich
Paul Rubin wrote:
 Christopher Subich [EMAIL PROTECTED] writes:
 
My personal favourite is to replace lambda entirely with an
expression comprehension, using  and  delimeters.
 
 
 But how does that let you get more than one expression into the
 anonymous function?

It doesn't.  Functionally, it's a direct replacement of lambda as-is.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: A replacement for lambda

2005-07-30 Thread Christopher Subich
Scott David Daniels wrote:

 What kind of shenanigans must a parser go through to translate:
 x**2 with(x)x**3 with(x)
 
 this is the comparison of two functions, but it looks like a left-
 shift on a function until the second with is encountered.  Then
 you need to backtrack to the shift and convert it to a pair of
 less-thans before you can successfully translate it.

I hadn't thought of that, but after much diving into the Python grammar, 
the grammar would still work with a greedy tokenizer if  (and also 
, for identical reasons) were replaced in 'shift_expr with   
and  .

That, of course, introduces some weirdness of '''a = 5   3''' being 
valid.  I'm not sure whether that is a wart big enough to justify a 
special-case rule regarding '' and '' tokens.  We do allow
'def  f() :'
as-is, so I'm not sure this is too big of a problem.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: A replacement for lambda

2005-07-30 Thread Christopher Subich
Paolino wrote:
 why (x**2 with(x))(x**3 with(x)) is not taken in consideration?

Looks too much like a generator expression for my taste.  Also, expr 
.. syntax could be used with 'for' instead of 'with' if PEP343 poses a 
problem, whereas (expr for params) is identically a generator expression.

 If 'with' must be there (and substitue 'lambda:') then at least the 
 syntax is clear.IMO Ruby syntax is also clear.

I haven't used Ruby myself, but as I understand it that language allows 
for full anonymous blocks.  Python probably doesn't want to do that.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: A replacement for lambda

2005-07-30 Thread Christopher Subich
Paddy wrote:
 Christopher Subich [EMAIL PROTECTED] writes:
 
Basically, I'd rewrite the Python grammar such that:
lambda_form ::=  expression with parameter_list 
 
 
 I do prefer my parameter list to come before the expression. It would
 remain consistant with simple function definitions.

Stylistic choice; I can appreciate your sentiment, but remember that 
this isn't exactly a function definition.  It's a form of 'delayed 
expression.'  Also, ... with ... is nearly identical (identical if you 
replace 'with' with 'for') to existing list and generator 
comprehensions, so we'd get to stretch that idiom.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: A replacement for lambda

2005-07-29 Thread Christopher Subich
Mike Meyer wrote:
 My choice for the non-name token is @. It's already got magic
 powers, so we'll give it more rather than introducing another token
 with magic powers, as the lesser of two evils.

Doesn't work.  The crux of your change isn't introducing a meaning to @ 
(and honestly, I prefer _), it's that you change the 'define block' from 
a compound_stmt (funcdef) (see 
www.python.org/doc/current/ref/compound.html) to an expression_stmt 
(expresion).  This change would allow some really damn weird things, like:

if def _(x,y):
   return x**2 - y**2
(5,-5): # ?!  How would you immediately call this 'lambda-like'?[1]
print 'true'
else:
print 'false'

[1] -- yes, it's generally stupid to, but I'm just pointing out what has 
to be possible.

Additionally, Python's indenting Just Doesn't Work Like That; mandating 
an indent after where the def came on the previous line (as you do in 
your example, I don't know if you intend for it to hold in your actual 
syntax) wouldn't parse right -- the tokenizer generates INDENT and 
DEDENT tokens for whitespace, as I understand it.

My personal favourite is to replace lambda entirely with an 
expression comprehension, using  and  delimeters.  It just looks 
like our existing list and generator comprehensions, and it doesn't use 
'lambda' terminology which will confuse any newcomer to Python that has 
experience in Lisp (at least it did me).

g = x**2 with (x)
g(1) == 1

Basically, I'd rewrite the Python grammar such that:
lambda_form ::=  expression with parameter_list 

Biggest change is that parameter_list is no longer optional, so 
zero-argument expr-comps would be written as expr with (), which makes 
a bit more sense than expr with.

Since  and  aren't ambiguous inside the expression state, this 
shouldn't make the grammar ambiguous.  The with magic word does 
conflict with PEP-343 (semantically, not syntactically), so for might 
be appropriate if less precise in meaning.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: can list comprehensions replace map?

2005-07-28 Thread Christopher Subich
Andrew Dalke wrote:
 Steven Bethard wrote:
 
Here's one possible solution:

py import itertools as it
py def zipfill(*lists):
...   max_len = max(len(lst) for lst in lists)
 
 
 A limitation to this is the need to iterate over the
 lists twice, which might not be possible if one of them
 is a file iterator.
 
 Here's a clever, though not (in my opinion) elegant solution
 
 import itertools
 
 def zipfill(*seqs):
 count = [len(seqs)]
 def _forever(seq):
 for item in seq: yield item
 count[0] -= 1
 while 1: yield None
 seqs = [_forever(seq) for seq in seqs]
 while 1:
 x = [seq.next() for seq in seqs]
 if count == [0]:
 break
 yield x

I like this solution best (note, it doesn't actually use itertools).  My 
naive solution:
def lzip(*args):
ilist = [iter(a) for a in args]
while 1:
   res = []
   count = 0
   for i in ilist:
  try:
 g = i.next()
 count += 1
  except StopIteration: # End of iter
 g = None
  res.append(g)
   if count  0: # At least one iter wasn't finished
  yield tuple(res)
   else: # All finished
  raise StopIteration
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: consistency: extending arrays vs. multiplication ?

2005-07-24 Thread Christopher Subich
Soeren Sonnenburg wrote:
 On Sat, 2005-07-23 at 23:35 +0200, Marc 'BlackJack' Rintsch wrote:
Both operate on the lists themselves and not on their contents.  Quite
consistent if you ask me.

 But why ?? Why not have them operate on content, like is done on
 *arrays ?

Because they're lists, not arrays.  What do you propose that the 
following do:

[1,2,3] + [4,5,6]
[1,2] + [3,4,5]
[1,2] + [{3:4,5:6}]
dict_var_1.keys() + dict_var_2.keys()
[g(3) for g in [f1 f2 f3] + [f4 f5 f6]]

I point out that the idiom is list + list, not numbers + 
numbers.  Operations on lists must deal with them as lists, not lists 
of any specific type.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: return None

2005-07-24 Thread Christopher Subich
Repton wrote:
 'Well, there's your payment.' said the Hodja. 'Take it and go!'

+1: the koan of None

Upon hearing that, the man was enlightened.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: return None

2005-07-23 Thread Christopher Subich
Grant Edwards wrote:
 Personally, I don't really like the idea that falling off the
 botton of a function implicitly returns None.  It's just not
 explicit enough for me.  My preference would be that if the
 function didn't execute a return statement, then it didn't
 return anyting and attempting to use a return value would be an
 error.

This is a bad idea.  Classically, distinguishing between functions that 
return things and functions that don't return things explicitly divides 
the callable object space.  From my CS101 class with its incredibly 
exciting dive into the world of useless pseudocode, callables that 
returned things were called 'functions' and callables that didn't were 
called 'procedures'.

Some languages do make this distinction; QBASIC, for example, had 
'gosub' separate from function calls.

What do you do for an early break from a function that still returns 
not-even-None [ReallyNone], return?  That looks and acts like a 'real' 
return statement, and the distinction between 
return-without-a-value-so-maybe-except and return-with-a-value is 
suddenly magnified to real importance.

Further, and I consider this a truly damning case, look at decorater.  A 
naive logging decorator could be defined like this:

def logger(func):
def new_func(*args, **kwargs):
   print '%s called with:' % func.__name__, args, kwargs
   retval = func(*args,**kwargs)
   print '%s returns:', retval
   return retval
return new_func

This logger works without modification for both value and non-value 
returning functions.  Its output isn't quite as pretty for non-value 
functions, but it works and the implementation is both simple and flexible.

With a function-schism, to keep its simple implementation 'logger' would 
have to be rewritten as 'flogger' (same as current-logger, for use on 
functions), and 'plogger' (for use on procedures).  The downside here is 
that if the function/method changed to or from a procedure, the 
decorator would have to be switched.

Alternatively, the logger decorator could be longer and explicitly catch 
the possible exception.  But why should we have to write like that, for 
a use-case that doesn't even represent a true error -- arguably not even 
an exceptional case?  Python's definitely not a BD language, talk of 
floggers aside.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Aliasing an object's __str__ to a different method

2005-07-23 Thread Christopher Subich
Paolino wrote:
 Little less ugly:
 In [12]:class A(object):
: def __str__(self):return self.__str__()
: def str(self):return 'ciao'
: def setStr(self):self.__str__=self.str
:
 
 In [13]:a=A()
 
 In [14]:a.setStr()
 
 In [15]:str(a)
 Out[15]:'ciao'

Not quite bug-free, by my eye that'll infintely recur if you call str(A()).
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: return None

2005-07-23 Thread Christopher Subich
Christopher Subich wrote:
   print '%s returns:', retval
Not that it matters, but this line should be:
   print '%s returns:' % func.__name__, retval
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Help with regexp please

2005-07-22 Thread Christopher Subich
Scott David Daniels wrote:
 Felix Collins wrote:
 I have an outline number system like
 1
 1.2
 1.2.3
 I want to parse an outline number and return the parent.
 
 Seems to me regex is not the way to go:
 def parent(string):
 return string[: string.rindex('.')]

Absolutely, regex is the wrong solution for this problem.  I'd suggest 
using rsplit, though, since that will Do The Right Thing when a 
top-level outline number is passed:
def parent(string):
return string.rsplit('.',1)[0]

Your solution will throw an exception, which may or may not be the right 
behaviour.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: find a specified dictionary in a list

2005-07-22 Thread Christopher Subich


Odd-R. wrote:
 On 2005-07-22, John Machin [EMAIL PROTECTED] wrote:
  Odd-R. wrote:
  I have this list:
 
  [{'i': 'milk', 'oid': 1}, {'i': 'butter', 'oid': 2},{'i':'cake','oid':3}]
 
  All the dictionaries of this list are of the same form, and all the oids
  are distinct. If I have an oid and the list, how is the simplest way of
  getting the dictionary that holds this oid?
 
 
  Something like this:
 
  def oidfinder(an_oid, the_list):
   for d in the_list:
  if d['oid'] == an_oid:
   return d
   return None
   # These are not the oids you are looking for.

 Thank you for your help, but I was hoping for an even simpler
 solution, as I am suppose to use it in a
 tal:block tal:define=p python: sentence.

 Is there a simpler way of doing it? What if I assume that the
 oid I'm searching for really exists?

If you really, really, really don't care about proper error handling,
both of these expressions should work: (warning, untested since I'm at
work)
right_oid = [d for d in dictlist if d['oid']==the_oid][0]
right_oid = (d for d in dictlist if d['oid']==the_oid).next()

The last one more efficient as a generator expression, but requires
Python2.4.  Both of these error in Really Bad Ways (range error and
StopIteration exceptions, respectively) if the right dictionary isn't
in the list.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Help with regexp please

2005-07-22 Thread Christopher Subich
Terry Hancock wrote:
 I think this is the regexes can't count problem.  When the repetition
 count matters, you usually need something else.  Usually some
 combination of string and list methods will do the trick, as here.

Not exactly, regexes are just fine at doing things like first and
last.  The regexes can't count saying applies mostly to activities
that reduce to parentheses matching at arbitrary nesting.

The OP's problem could easily be written as a regex substitution, it's
just that there's no need to; I believe that the sub would be
(completely untested, and I'm probably going to use the wrong call to
re.sub anyway since I don't have the docs open):

re.sub(outline_value,'([0-9.]+)\.[0-9]+','\1')

It's just that the string.rsplit call is much more legible, much more
intutitive, doesn't do strange things if it's accidentally called on a
top-level outline value, and also extends immediately to handle
outlines of the form I.1.a.i.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Aliasing an object's __str__ to a different method

2005-07-22 Thread Christopher Subich
ncf wrote:
 Well, suffice to say, having the class not inherit from object solved
 my problem, as I suspect it may solve yours. ;)

Actually, I did a bit of experimenting.  If the __str__ reassignment 
worked as intended, it would just cause an infinite recursion.

To paste the class definition again:
 class MyClass(object):
 
 def Edit(self):
 return I, %s, am being edited % (self)
 
 def View(self):
 return I, %s, am being viewed % (self)
 
 def setEdit(self):
 self.__str__ = self.__repr__ = self.Edit
 
 def setView(self):
 self.__str__ = self.__repr__ = self.View

Notice the % (self) in Edit and View -- those recursively call 
str(self), which causes infinite recursion.

In the spirit of getting the class working, though, the class-method 
behavior of __str__ for new-style classes can be fixed with an extremely 
ugly hack:
class MyClass(object):
def __init__(self):
self.__str__ = lambda : object.__str__(self)
 def Edit(self):
 return I, %s, am being edited

 def View(self):
 return I, %s, am being viewed

 def setEdit(self):
 self.__str__ = self.__repr__ = self.Edit

 def setView(self):
 self.__str__ = self.__repr__ = self.View
 def __str__(self):
return self.__str__()

(Notice that I've removed the string substitution in Edit and View. 
This also does not change the __repr__ method; it also acts as a class 
method.  But that's also easy enough to change in the same way.)

I also would be interested in knowing why new-style classes treat 
__str__ as a class method.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Location of tk.h

2005-07-22 Thread Christopher Subich
none wrote:
 Probably a stupid question, but...
 
 I was attempting to install the Tkinter 3000 WCK.  It blew up trying to 
 build _tk3draw.  The first error is a 'No such file or directory' for 
 tk.h.  I can import and use Tkinter just fine, so I'm not sure what is 
 what here.

You can import and user Tkinter, sure, but the WCK setup is trying to 
-build- itself.  Have you installed the relevant Tk development libraries?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Need to interrupt to check for mouse movement

2005-07-21 Thread Christopher Subich
Paul Rubin wrote:
 Huh?  It's pretty normal, the gui blocks while waiting for events
 from the window system.  I expect that Qt and Tk work the same way.

Which is why I recommended Twisted for the networking; it integrates 
with the toolkit event loops so it automagically works: 
http://twistedmatrix.com/projects/core/documentation/howto/choosing-reactor.html#auto15

I agree, though, that basic socket programming in the same thread as the 
gui's probably a bad idea.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: main window in tkinter app

2005-07-20 Thread Christopher Subich
William Gill wrote:
 O.K. I tried from scratch, and the following snippet produces an 
 infinite loop saying:
 
   File C:\Python24\lib\lib-tk\Tkinter.py, line 1647, in __getattr__
   return getattr(self.tk, attr)
 
 If I comment out the __init__ method, I get the titled window, and print 
 out self.var ('1')
 
 
 import  os
 from Tkinter import *
 
 class MyApp(Tk):
 var=1
 def __init__(self):
   pass
 def getval(self):
   return self.var
 
 
 app = MyApp()
 
 app.title(An App)
 print app.getval()
 app.mainloop()

You're not calling the parent's __init__ inside your derived class.  I 
would point out where the Python Tutorial points out that you should do 
this, but it's not in the obvious place (Classes: Inheritance).

Python does -not- automagically call parent-class __init__s for derived 
classes, you must do that explicitly.  Changing the definition of your 
class to the following works:
  class MyApp(Tk):
 var=1
 def __init__(self):
   Tk.__init__(self)
   pass
 def getval(self):
   return self.var

It works when you comment out __init__ because of a quirk in Python's 
name resolution.  As you'd logically expect, if you don't define a 
function in a derived class but call it (such as instance.method()), it 
will call the method from the base class.

You just proved that this works for __init__ methods also.  When you 
didn't define __init__ for your derived class, MyApp() called 
Tk.__init__(), which Does the Right Thing in terms of setting up all the 
specific Tkinter-specific members.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: main window in tkinter app

2005-07-20 Thread Christopher Subich
William Gill wrote:
 That does it!, thanks.
 
 Thinking about it, when I created a derived class with an  __init__ 
 method, I  overrode the base class's init.  It should have been 
 intuitive that I needed to explicitly call baseclass.__init(self), it 
 wasn't.  It might have hit me if the fault was related to someting in 
 baseclass.__init() not taking place, but the recursion loop didn't give 
 me a clue.  Any idea why failing to init the base class caused the loop?

You never pasted the first part of the traceback:

   File pyshell#204, line 1, in -toplevel-
 app.title('frob')
   File C:\Python24\Lib\lib-tk\Tkinter.py, line 1531, in wm_title
 return self.tk.call('wm', 'title', self._w, string)
   File C:\Python24\Lib\lib-tk\Tkinter.py, line 1654, in __getattr__
 return getattr(self.tk, attr)
   File C:\Python24\Lib\lib-tk\Tkinter.py, line 1654, in __getattr__
 return getattr(self.tk, attr)

When you didn't call Tk.__init__(self), self.tk was never initialized. 
Further, it's obvious from the traceback that Tk implements a 
__getattr__ method; from the python docs:

__getattr__(self,name): Called when an attribute lookup has not found 
the attribute in the usual places

Since self.tk doesn't exist, __getattr__(self,tk) was called.  Without 
looking at the TKinter source code, we can surmise that there's a 
default behavior of if self doesn't have it, return the relevant 
attribute from within self.tk.  The problem, of course, arises when 
self.tk doesn't exist -- this causes the self.tk reference to call 
self.__getattr__('tk'), which is recursive.

The infinite recursion, then, is a mild bug in TKinter that doesn't show 
itself during normal use.  The proper solution should be to replace the 
self.tk call with either self.__dict__['tk'], or to make Tk a new-style 
class and use object.__getattribute__(self,'tk'). (Note: there are 
probably some fine details that I'm missing in this 'solution', so take 
it with a potato-sized grain of salt.  The general principle still 
applies though.)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Need to interrupt to check for mouse movement

2005-07-20 Thread Christopher Subich
Peter Hansen wrote:
 stringy wrote:
 
 I have a program that shows a 3d representation of a cell, depending on
 some data that it receives from some C++. It runs with wx.timer(500),
 and on wx.EVT_TIMER, it updates the the data, and receives it over the
 socket.
 
 
 It's generally inappropriate to have a GUI program do network 
 communications in the main GUI thread.  You should create a worker 
 thread and communicate with it using Queues and possibly the 
 AddPendingEvent() or PostEvent() methods in wx.  There should be many 
 easily accessible examples of how to do such things.  Post again if you 
 need help finding them.

I'd argue that point; it's certainly inappropriate to do 
(long-)/blocking/ network communications in a main GUI thread, but 
that's just the same as any blocking IO.  If the main thread is blocked 
on IO, it can't respond to the user which is Bad.

However, instead of building threads (possibly needlessly) and dealing 
with synchronization issues, I'd argue that the solution is to use a 
nonblocking network IO package that integrates with the GUI event loop. 
  Something like Twisted is perfect for this task, although it might 
involve a significant application restructuring for the grandparent poster.

Since blocking network IO is generally slow, this should help the 
grandparent poster -- I am presuming that the program updating itself 
is an IO-bound, rather than processor-bound process.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Need to interrupt to check for mouse movement

2005-07-20 Thread Christopher Subich
Jp Calderone wrote:

 In the particular case of wxWidgets, it turns out that the *GUI* blocks 
 for long periods of time, preventing the *network* from getting 
 attention.  But I agree with your position for other toolkits, such as 
 Gtk, Qt, or Tk.

Wow, I'm not familiar with wxWidgets; how's that work?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Help - Classes and attributes

2005-07-14 Thread Christopher Subich
rh0dium wrote:
 Hi all,
 
 I believe I am having a fundamental problem with my class and I can't
 seem to figure out what I am doing wrong.  Basically I want a class
 which can do several specific ldap queries.  So in my code I would have
 multiple searches.  But I can't figure out how to do it without it
 barfing..
[snip]
   File ./ldap-nsc.py, line 40, in search
 ldap_result_id = l.search_s(baseDN, searchScope, searchAttrs,
 retrieveAttrs)
 AttributeError: NSCLdap instance has no attribute 'search_s'
 
 
 The code is also I believe straight forward..

You're going to kick yourself when you see the mistake.

 
 import ldap
 
 class NSCLdap:
 
 def __init__(self,server=sc-ldap.nsc.com):
 who=; cred=
 self.server=server
 try:
 print LDAP Version, ldap.__version__
 l=ldap.open(server)
   ^^
[big snip]
 if __name__ == '__main__':
 
 l = NSCLdap()
 l.search()

 I would love some pointers - clearly my code thinks that search_s is an
 attribute of my class but it's not..

Ah, but l -is- an instance of your class.  You want l to refer to the 
ldap connection, but you forgot do assign it to self.l -- in __init__, 
you assign l to simply a local variable, which goes poof as soon as 
__init__ returns.  You forgot the self.l throughout both __init__ and 
search.

You get the slighty misleading traceback because there is an l defined 
-- it just happens to be the one in globals(), the l = NSCLdap() that 
got assigned when you imported/ran the module.

Replace l = NSCLdap() with q = NSCLdap() (and l.search with q.search), 
and you'll get a NameError instead.
-- 
http://mail.python.org/mailman/listinfo/python-list


  1   2   >