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: 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: 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: 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: 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:


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
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: 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: 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: 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: 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: 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: 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
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: 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: 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 "", line 1, in ?
IndexError: string index out of range
 >>> str[1]
Traceback (most recent call last):
   File "", line 1, in ?
IndexError: string index out of range
 >>> str[-1]
Traceback (most recent call last):
   File "", 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


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


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: 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
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: 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
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 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 "", line 1, in ?
NameError: name 'a' is not defined
 >>> b = object()
 >>> b.a
Traceback (most recent call last):
   File "", 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:
>>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
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 =
>  to correspond to b.__class__.a = ?

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:
> 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: 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-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: textwidget.tag_bind("name", "", 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-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: 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.

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

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

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  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-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 "", line 1, in ?
TypeError: cannot compare complex numbers using <, <=, >, >=
 >>>cmp(1j,1j)
0
 >>>cmp(1,1j)
Traceback (most recent call last):
   File "", 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 "", line 1, in ?
   File "", line 3, in __cmp__
TypeError: cannot compare Incomparables using <, <=, >, >=
 >>> cmp(a1,a2)
Traceback (most recent call last):
   File "", line 1, in ?
   File "", 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: 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: 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: 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 "", 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: 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:
  

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

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

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):
   

As a concrete example of this, consider:

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

Then you can call it with:
originPoint = Point()
pointInX = Point(xloc)
pointInXYPlane = Point(xloc,yloc)
pointIn3DSpace = Point(xloc,yloc,zloc)


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)
   
-- 
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


Re: Catching stderr output from graphical apps

2005-08-12 Thread Christopher Subich
Bryan Olson wrote:
> 
> Thanks.
> 
> Yeah, guess I was naive to test on Windows and expect that kind
> of process stuff to be portable. I'll be away from Linux for a
> week or so, so this will take me a while.
> 
> Further bulletins as events warrant.

If you can get a cross-platform solution, please re-annoucne it; this 
sounds like a really neat module to have handy for graphical programs.
-- 
http://mail.python.org/mailman/listinfo/python-list


Unicode regular expressions -- buggy?

2005-08-10 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: 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: 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: wxPython and threads again

2005-08-10 Thread Christopher Subich
David E. Konerding DSD staff wrote:
> The easiest approach, though, is to use the threadedselectreactor in Twisted 
> (you need
> to check the HEAD branch out with subversion, because that reactor isn't 
> included in any releases).
> With threadedselectreactor, it's easy to incorporate both the GUI event loop 
> and the twisted reactor.
> Twisted already includes lots of code for doing asynchronous callback-style 
> IO for
> IO bound processes like downloading.  Further, you don't even think in an 
> explicitly threaded way-
> createing a whole thread just to manage a download process which is motly IO 
> and a little bookkeeping is
> silly.  Twisted's approach just makes a lot more sense and simplifies the 
> code too.

Or, don't use threadedselectreactor, but instead just use normal 
threading and reactor.callFromThread.
-- 
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: 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: Import question

2005-08-09 Thread Christopher Subich
ncf wrote:
> Hmm...thanks for the replies. Judging by this, it looks like I might
> still be in a slight perdiciment with doing it all, but time will tell.
> I wish there were a way I could reference across multiple modules.
> 
> Well, thanks for your help. Hopefully I'll be able to work out some
> *simple* solution for all of this.

What exactly is it that you're trying to do?  You don't need access to 
the class definition (which would be in a module) if you just want to 
manipulate a particular _instance_.  Advantage of dynamic typing and all.

For example:

module1:
def function(x):
x.method(1)

module2:
class foobar:
def method(x):
   print 'I received', x, ', aren't I happy?!'

import module1
obj = foobar()
module1.function(obj)
-- 
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:
> And I'll guarantee that the difference between 333- and
> 666- has to be more than 1-bit.  There's no way that can be
> the correct data unless it's something like an index into a
> different table or a pointer or something along those lines.

Absolutely.  I hadn't even taken a good look at those datapoints yet.

The dataset that I'd like to see:
000-000-0001
000-000-0010
(etc)
000-000-0002
000-000-0004
000-000-0008
000-000-0016
(etc)

I also wonder if the last 8-16 bits involves, at least in part, a count 
of the length of the phone number, or at least a flag to distinguish 7 
from 10 digits.
-- 
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: Passing arguments to function - (The fundamentals are confusing me)

2005-08-09 Thread Christopher Subich
Gregory Piñero wrote:
> So what if I do want to share a boolean variable like so:

Well, the easiest way is to wrap it in a list:

mybool = [True]
mybool[0] = False
mybool[0] = True

and so on.

Alternately, what is this boolean attached to that's so significant? 
Sharing an arbitrary boolean, without any context, is rather strange -- 
perhaps it would be best to include both the boolean and associated 
context in a single, larger object.

Also, remember that Python functions can return more than one value, 
through implicit tuple packing and unpacking.  This greatly reduces the 
need for C-like result = function(&other_result) - isms.

def myfunc():
return 1,2,3
(a,b,c) = myfunc()
a == 1
b == 2
c == 3
-- 
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
[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: Passing arguments to function - (The fundamentals are confusing me)

2005-08-09 Thread Christopher Subich
Rocco Moretti wrote:
> Variables in Python are names. They aren't the cubbyholes into which you 
> put values, they are sticky notes on the front of the cubby hole.

+1 MOTW (Metaphor of the Week)
-- 
http://mail.python.org/mailman/listinfo/python-list


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

2005-08-09 Thread Christopher Subich
infidel wrote:
>>in Python equality rebinds the name
> 
> 
> Assignment (=) rebinds the name.  Equality (==) is something else
> entirely.

Good catch.  I was thinking of it as the "equals" operator.
-- 
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: 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.

> 
> 
> 
> 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: 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:  [] 
__data2:  [] 
__data1:  [2005, 8, 9, 10, 5, 54, 1, 221, 1] 
__data2:  [2005, 8, 9, 10, 5, 54, 1, 221, 1] 
 >>> m2 = my()
__data1:  [] 
__data2:  [2005, 8, 9, 10, 5, 54, 1, 221, 1] 
__data1:  [2005, 8, 9, 10, 5, 54, 1, 221, 1, 2005, 8, 9, 10, 5, 56, 1, 
221, 1] 
__data2:  [2005, 8, 9, 10, 5, 54, 1, 221, 1, 2005, 8, 9, 10, 5, 56, 1, 
221, 1] 

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: 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
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: 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
> 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: Replacement for keyword 'global' good idea? (e.g. 'modulescope' or 'module' better?)

2005-08-06 Thread Christopher Subich
John Roth wrote:
> 
> "Mike Meyer" <[EMAIL PROTECTED]> wrote in message 
> news:[EMAIL PROTECTED]
>>
>> So the only way to remove the global statement would be to have some
>> way to mark the other interpretation, with say a "local"
>> decleration. I thik that would be much worse than "global". For one
>> thing, most variables would be local whether or not they are
>> declared. Second, having an indication that you need to check module
>> globals in the function is a better than not having that clue there.
> 
> 
> You've got half of the answer. The other half is to have the editor/ide
> translate the lexical cues into color coding and hide the lexical cues.

Yes... let's make color a syntactically important feature of the 
language; Python can follow the massive success of colorForth.

There are three principles that together mandate the use of a 'global' 
keyword:
1) Implicit variable definition:  If all variables had to be declared 
ahead of time, then "var x" versus "global var x" wouldn't be an issue 
at all.  Even though you'd still want to make the latter red and the 
former blue or something.  Removing this from Python would also forbid 
things like locals()['a'] = 1, and it would also have great impact on 
the class syntax (namely instance variables).
2) Lexical scoping: If variable references didn't go beyond the 
immediate scope, then there would be no global variables and thus no 
need for a global keyword.  Lexical scoping, though, is a fundamental 
feature of Python and every other block-scoping procedural language that 
I know of, so no-can-do there.
3) Default local scroping: Changing this, as already pointed out, would 
just require replacing a 'global' keyword with a 'local' one.  In 
procedural languages that derive in spirit from Algol-likes, local 
variables are the far more common case than global ones, and so by 
Huffman/Morse principles should have the shorter syntax.  (As a side 
note, the 'local first' assumption isn't universal; see some FORTRAN and 
BASICs.)

Personally, I don't consider the global keyword a misfeature or even a 
wart; for Py3k I'd rather see more explicit namespacing (which would 
make it clear that namespaces end at the module-level) rather than 
changing even the name of the keyword.
-- 
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: 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: 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: 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 "", 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: 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 '<>', '<>', and '<>', 
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: 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: 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: 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: 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: 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: 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: 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
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-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,  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
Scott David Daniels wrote:

> What kind of shenanigans must a parser go through to translate:
> <
> 
> 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
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-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 = 
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 , which makes 
a bit more sense than .

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: 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: 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  + , not  + 
.  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-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: "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
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 B&D language, talk of 
floggers aside.
-- 
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: "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: 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


  1   2   >