Re: Finding the instance reference of an object

2008-10-27 Thread Dale Roberts
On Oct 17, 5:39 pm, Joe Strout <[EMAIL PROTECTED]> wrote:
> On Oct 17, 2008, at 3:19 PM, Grant Edwards wrote:
>
> >> And my real point is that this is exactly the same as in every
> >> other modern language.
>
> > No, it isn't.  In many other languages (C, Pascal, etc.), a
> > "variable" is commonly thought of as a fixed location in memory
> > into which one can put values.  Those values may be references
> > to objects.
>
> Right, though not in languages like C and Pascal that don't HAVE the
> notion of objects.  We really ought to stop bringing up those
> dinosaurs and instead compare Python to any modern OOP language.
>
> >  In Python, that's not how it works.  There is no
> > "location in memory" that corresponds to a variable with a
> > particular name the way there is in C or Pascal or Fortran or
> > many other languages.
>
> No?  Is there any way to prove that, without delving into the Python
> source itself?
>
> If not, then I think you're talking about an internal implementation
> detail.


I think this "uncontrived" example addresses the (C/C++)/Python
difference fairly directly.
--
C:

struct {int a;} s1, s2;

int main()
{
   s1.a = 1;
   s2 = s1;

   printf("s1.a %d   s2.a %d\n", s1.a, s2.a);
   s1.a = 99;
   printf("s1.a %d   s2.a %d\n", s1.a, s2.a);
}

--
Python:

class mystruct:
pass

s1 = mystruct()
s1.a = 1
s2 = s1

print "s1.a %2d   s2.a %2d" % (s1.a,s2.a)
s1.a = 99
print "s1.a %2d   s2.a %2d" % (s1.a,s2.a)

---
C OUTPUT:
  s1.a  1   s2.a  1
  s1.a 99   s2.a  1

Python OUTPUT:
  s1.a  1   s2.a  1
  s1.a 99   s2.a 99

Note that in C (or C++) the value of s2.a remains unchanged, because
the VALUE of s1 (the contents of the memory where s1 resides) was
COPIED to the memory location of s2, and subsequently, only the VALUE
of s2.a was changed. In Python, s2.a is "changed" (but not really)
because it turns out that s2 is just another name for the object that
s1 pointed to.

So there is no programatically accessible "location in memory" that
corresponds to s1 or s2 in Python. There is only a location in memory
that corresponds to the object that s1 is currently pointing to. In C,
by contrast, there are definite locations in memory that correspond to
both variables s1 and s2, and those locations remain always separate,
distinct and unchanged throughout the execution of the program.

This is not an "implementation detail", it is a fundamental part of
each language. As C was an "improvement" on assembler, the variable
names have always just been aliases for memory locations (or
registers). You can see this in the output of any C/C++ compiler.

In Python, variables are just names/aliases for *references* to
objects, not names for the objects/values themselves. The variable
names themselves do not correspond directly to the objects' memory
locations. While yes, technically, it is true that those reference
values must be stored somewhere in memory, *that* is the
implementation detail. But is is not the *locations* of these
references (i.e., the locations of the Python *variables*) that are
copied around, it is the references themselves (the locations of the
Python *objects*) that are copied.

> > All that exists in Python is a name->object mapping.
>
> And what does that name->object mapping consist of?  At some level,
> there has to be a memory location that stores the reference to the
> object, right?

I think this is answered above, but just to drive it home, in Python
the memory locations of the variables themselves (an implementation
detail), which hold the references to the objects, are inaccessible .
In C/C++, by contrast, variable names correspond directly to memory
locations and objects, and you can easily find the addresses of
variables, and the addresses do not change, although the values can.

In C/C++, if you choose, you may have a variable that is itself a
reference/pointer to some other memory/object/array. In C, we would
say that the VALUE of that variable is the memory address of another
object. But you can, if you need to, get the address of the pointer
variable, which points to the *address* of the other object.

In Python, a variable is ONLY EVER a reference to an object. You
cannot get the address of a Python variable, only of a Python object.

Hope this clears things up.

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


Re: Finding the instance reference of an object

2008-10-27 Thread Dale Roberts
[I am actually enjoying this discussion, even though it does not address 
the OP's question. It is helping to solidify *my* understanding.]


Joe Strout wrote:

On Oct 27, 2008, at 12:19 PM, [EMAIL PROTECTED] wrote:


I think this "uncontrived" example addresses the C/Python difference
fairly directly (both were tested):


That's correct, but of course, C is a decades-old language barely a step 
above assembler.  For a fair comparison, pick any modern OOP language, 
including the C derivatives (C++, Objective-C, Java), and compare a 
Python object to an object in that language, rather than to a struct.


Okay, sorry, should have had C++ from the start. See my spiffed-up 
example here, where I magically convert to C++ by replacing "struct" 
with "class" and adding the word "public:". Still behaves the same, though.


I added the functions ByVal() and ByRef() to show that when you pass by 
value, the contents of the object cannot be changed. This is not 
possible in Python unless a copy of the object is made (which is what 
C++ does automatically for you in pass-by-value).


In Python, the contents of the object are changed, which is most similar 
to the pass by reference (or by pointer) construct in C++. But, yes, as 
you say, technically:


  passing the object by reference
   == passing the address of the object by value.

But I think that is, to most programmers, a surprising use of the term 
"pass by value".


And note in my example, nowhere do I explicitly take the address of s1. 
The compiler does this for me in the ByRef() case. And nowhere to I make 
a copy of s1. Again, the compiler does this for me in the ByVal() case. 
The calls to ByVal() and ByRef() are identical. You cannot tell from the 
calls which thing is going to happen.


---
class MyClass {public: int a;} s1, s2;

void ByVal(MyClass  obj) {obj.a=42;}
void ByRef(MyClass &obj) {obj.a=43;}

int main()
{
   s1.a = 1;
   s2 = s1;

   printf("s1.a %2d   s2.a %2d\n", s1.a, s2.a);

   s1.a = 99;
   printf("s1.a %2d   s2.a %2d\n", s1.a, s2.a);

   ByVal(s1);
   printf("s1.a %2d\n", s1.a);

   ByRef(s1);
   printf("s1.a %2d\n", s1.a);
}
--
class mystruct:
pass

def ByObject(obj): obj.a=42

s1 = mystruct()
s1.a = 1
s2 = s1

print "s1.a %2d   s2.a %2d" % (s1.a,s2.a)
s1.a = 99
print "s1.a %2d   s2.a %2d" % (s1.a,s2.a)

ByObject(s1)
print "s1.a %2d" % (s1.a)

--
C++ OUTPUT
s1.a  1   s2.a  1
s1.a 99   s2.a  1  # note s2.a does not change when s1.a is modified
s1.a 99# contents of s1.a does not change when passed by val
s1.a 43# it does change when passed by ref

Python OUTPUT
s1.a  1   s2.a  1
s1.a 99   s2.a 99  # s2.a "changes" because it's the same object as s1
s1.a 42# Contents of object does change with function call.

...and in Python, of course, as you say, what you call the "value" of 
s1, the address of the object, id(val), does not change.


>>
>> [skipping lots of stuff we agree on!]
>>

In C/C++, by contrast, variable names correspond directly to memory
locations and objects, and you can easily find the addresses of
variables.


Hmm, no, the C++ equivalent of an object reference would be:

 SomeClass* foo;


Whoah, nonsequitor there. Let's back up. I did not use the word 
"reference", and that is the point. And I am correct that C variable 
names correspond to memory locations (or sometimes CPU registers - 
optimizers can really mangle things). And you can get the addresses of 
the variables themselves using the & operator.


Have a look at my example code again. s1 and s2 ARE OBJECTS THEMSELVES, 
they are not references to objects. You can do this in C++ (not in 
Python). You can pass whole objects, by value (they are copied by the 
compiler), on the stack. And we both understand that you can't do that 
in Python. That is why we differentiate between "pass by reference" and 
"pass by value" in C++, and people generally understand what that means.


> ...

 void NiftyMethod2(SomeClassPtr &arg) {...}
 ...
 NiftyMethod2(foo);

Now, arg here is passed by reference (just like a ByRef parameter in RB 
or .NET).  That means that NiftyMethod2 could very well change the value 
that is passed in.  It could actually make foo point to something else.


No Python method can do that,


Yes, absolutely agreed. A Python method can never change *which* object 
the caller points to, it can only change the *contents* of that object.


But the same is true in C++ as well. In your example, the address of the 
foo variable itself can never be changed. You can change the *value* of 
foo (so it points to a different object), or you can change the contents 
of the object foo points to. foo is a variable with an address which you 
can usually see with a printf("%x", &foo), and that is different from 
the address of the object which you get when you say printf("%x", foo).


The value &foo cannot be changed.

because Python arguments are ALWAYS passed 
by value.  There is no call 

Re: Finding the instance reference of an object

2008-10-28 Thread Dale Roberts
On Oct 28, 2:33 am, "Gabriel Genellina" <[EMAIL PROTECTED]>
wrote:
> En Tue, 28 Oct 2008 01:16:04 -0200, Dale Roberts <[EMAIL PROTECTED]>  
> escribió:
>
>
>
> > So, then, what to tell a C++ programmer about how Python passes  
> > arguments? You say: tell them Python only passes by value. I disagree,  
> > because I think that would confuse them. Rather than try to map C++  
> > conventions onto Python, I think it is more useful to just tell them how  
> > it really works. Maybe a few statements like this:
>
> >    All values in Python are objects, from simple integers up to complex
> >    user-defined classes.
>
> >    An assignment in Python binds a variable name to an object. The
> >    internal "value" of the variable is the memory address of an object,
> >    and can be seen with id(var), but is rarely needed in practice.
>
> >    The "value" that gets passed in a Python function call is the address
> >    of an object (the id()).
>
> >    When making a function call, myfunc(var), the value of id(var) can
> >    never be changed by the function.
>
> > Not sure if these are the best. To get into much more detail, you have  
> > to start explaining mutable and immutable objects and such.
>
> I don't think the above explanation is desirable, nor needed. Objects in  
> Python don't have an "address" - it's just a CPython implementation  
> detail. The fact that id() returns that address is just an implementation  
> detail too. The calling mechanism should be explained without refering to  
> those irrelevant details.
>
> --
> Gabriel Genellina


I agree that it was a feeble and ill-advised attempt, and would like
to strike those lines from the record...

But the rest of the post is strong and accurate, I think, and coming
from a mainly C/C++ background, visualizing these object references
being passed around does help improve my understanding of Python's
*behavior* (and it apparently helps Joe too).

[May I refer to you as "Joe The Programmer" in my rhetoric? Are you a
"licensed" programmer making over $250K/year? ;-)]

If asked by a C++ programmer about Python's argument passing, I will
go with the Pass By Object explanation (which is why I called my
Python routine above ByObject()). Although there will be more
'splaining to do, at least it will give the C++ programmer pause, and
help them realize that there is something a little different that they
need to stop and try to understand.

If I just say "Python is Pass By Value, Period" without further
explanation, they will expect things to work as in my ByValue()
example above (where the caller's object contents cannot be changed),
and that is incorrect. And they may go and tell someone else, without
the detailed explanation, that "Dale says it's Pass By Value", and
I'll get blamed when their function surprisingly changes the contents
of the caller's object.

If I just say "Python is Pass By Reference", that is wrong too. As Joe
The Programmer points out, they will expect that the calling
*variable* itself can be changed, and that is wrong too.

They need to understand that Python does not map neatly, directly, and
completely to their C++ experience of Pass By Value (which involves
copying a variable), or Pass By Reference (which involves taking the
address of a variable).

The Key Concept in for a C++ programmer looking at Python is that,
unlike in C++, **Variables Cannot "Contain" Values**. All values in
Python are objects, and all variables in Python simply point to, or
are bound to, or refer to, these objects. The variables themselves do
not contain the objects - if you must (like Joe the Programmer), you
can say that all Python variables *contain* an object reference, and
it is these references that are passed around. Unlike C++, an object
reference is the ONLY thing that a Python variable can contain. A
function parameter is always passed as a reference to an object, not a
reference to a variable, or a copy of a variable or object.

And that is where the confusion arises. When people say ByRef or
ByVal, they usually mean by Reference to (address) or Value of (copy)
the *contents* of the passed variable. But, PYTHON VARIABLES DO NOT
"CONTAIN" VALUES (sorry for the shouting, but it is the most important
point here), so ByRef and ByVal lose their commonly accepted meanings.

In C++, ByValue requires a copy (and Python does not copy). In C++,
ByReference requires the address of a *variable* (an "lvalue"), and
variables do not have accessible addresses in Python.

ByObject, in contrast, requires neither (unless, like Joe The
Programmer, you consider the "value" of a variable to be the id(),
which is not what most

Re: Finding the instance reference of an object

2008-10-28 Thread Dale Roberts
On Oct 28, 11:59 am, Joe Strout <[EMAIL PROTECTED]> wrote:
> ...
>
> There are only the two cases, which Greg quite succinctly and  
> accurately described above.  One is by value, the other is by  
> reference.  Python quite clearly uses by value.  Parameters are  
> expressions that are evaluated, and the resulting value copied into  
> the formal parameter, pure and simple.  The continued attempts to  
> obfuscate this is pointless and wrong.
>
> Best,
> - Joe

5 + 3

What is the "value" of that expression in Python? Can you tell me?

99.99% of programmers (who do not have this thread as context) will
say that the value is 8. But you say the value is the memory address
of the resulting object created when the + operator is applied to the
5 object and the 3 object. That is the "value" that is copied.

Okay, you can have it that way, but every time you explain to someone
that Python passes "By Value", you will have to add the additional
baggage that, oh, by the way, there is a completely different meaning
for "value" in Python than what you are used to.

Then the questions and puzzled looks will start...

And when they tell their friend that Joe The Programmer said it's Pass
By Value, your additional context may not be present any longer, and
the friend will be very confused.

In my opinion, best just to head it off and call it something
different so as not to confuse.

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


Re: Finding the instance reference of an object

2008-10-29 Thread Dale Roberts
On Oct 28, 11:59 am, Joe Strout <[EMAIL PROTECTED]> wrote:
> ...
>
> There are only the two cases, which Greg quite succinctly and  
> accurately described above.  One is by value, the other is by  
> reference.  Python quite clearly uses by value.  Parameters are  
> expressions that are evaluated, and the resulting value copied into  
> the formal parameter, pure and simple.  The continued attempts to  
> obfuscate this is pointless and wrong.
>
> Best,
> - Joe

Joe, you are being too generous and expansive here.

[Play along with me for a minute here...]

Don't you know? There is really only *ONE* case, and, you are right,
it is Pass By Value. There is no such thing as Pass By Reference at
the physical CPU level at all, right? If there is, show it to me. Pass
By Reference is just a silly idiom developed by high-minded CS
academics to confuse the rest of us. It has no practical use and
should not be given its own name, when we already have a good an
proper name for it.

Let me demonstrate with 3 examples of a function definition, and the
appropriate calling syntax for that function in C++, all sharing the
common "int i" global variable:

int i = 5;

myfunc(int &val){}   /*CALL:*/ myfunc(i);// "ByRef" (ya, right!)
myfunc(int val){}/*CALL:*/ myfunc(i);// ByVal
myfunc(int *val){}   /*CALL:*/ myfunc(&i);   // Joe's ByVal

The first is what all the fakers call "Pass By Reference" - sheesh,
how naive. We all know that what *really* happens internally is that
the *address* of val (A VALUE itself, or course) is copied and passed
on the stack, right? There couldn't be a more straightforward example
of Pass By Value (unless it's an inline function, or optimized away,
or possibly when implemented in a VM, or...). It passes the *address*
of i by value, then we can access the *value* of i too via
indirection. Hmm, did we need to have two definitions of VALUE there?
Well, never mind, no one will notice...

The next is obviously pass by value. It's right out there. The value
of i (which is what we are talking about, right?) is copied out, and
passed right on the stack in plain daylight where we can all see it.

How about the third? Pass By Value, obviously, of course. This is the
version you are defending, right? The parameter's value, &i, is
evaluated and copied right onto the stack, just like in the first
example. In fact, if you compare the assembler output of the first and
third examples, you may not even see a difference. Never mind the
actual contents of that pesky "i" variable that most people are
referring to when they use the term "value". We don't need to dress up
example 3 and call it an "idiom" where we are really passing a so-
called "reference" of the variable "i". Indeed! Don't insult our
intelligence. We can all see that it's an address passed by value,
plain and simple.


Pass By Reference? So "postmodern". Who needs it. Show me a so-called
"reference". I've looked at the assembler output and have never seen
one. There is no such thing.

"The continued attempts to obfuscate this is pointless and wrong."


---
I hate to have to add this, but for those not paying close attention:

  ;-)

dale

(tongue back out of cheek now)
--
http://mail.python.org/mailman/listinfo/python-list


Re: Finding the instance reference of an object

2008-10-30 Thread Dale Roberts
On Oct 29, 9:13 pm, Joe Strout <[EMAIL PROTECTED]> wrote:
> On Oct 29, 2008, at 4:52 PM, Fuzzyman wrote:
>
> > You're pretty straightforwardly wrong. In Python the 'value' of a
> > variable is not the reference itself.
>
> That's the misconception that is leading some folks around here into  
> tangled nots of twisty mislogic, ultimately causing them to make up  
> new terms for what every other modern language is perfectly happy  
> calling Call-By-Value.

Doesn't this logic also apply to Call By Reference? Isn't that term
redundant too? (see my 3 C++ examples above). If not, why not? Are you
saying that C++ is capable of using the Call By Reference idiom, but C
is not, because C does not have a reference designation for formal
function parameters?

"Call By Object Reference" is an idiom, just like Call By Reference.
It is not a physical description of what is going on internally at the
register/stack level (which is always just shuffling values around -
or flipping bits, as Steven points out), it is a higher level concept
that helps people understand the *intention* (not necessarily the
implementation) of the mechanism.

You cannot look a C++ programmer straight in the eye and say that
"Python uses Call By Value, Period", without also informing them that
"Python variables can ONLY EVER hold object references - that is the
only "value" they can ever hold". Then the C++ programmer will go "Oh,
yea, that makes sense".

Instead of having to say all of that, we just give it a new name.
Instead of "Call By Value, Where Every Single Value Is Only Ever A
Reference To An Object Which Contains The Actual Value That
Programmers Usually Refer To", we just say "Call By Object Reference".

> ...
> 2. Because everything in Python is an object, you're not forced to  
> think clearly (and more generally) about references as values

I think we've shown that we are all in fact thinking clearly about it,
and we all (you included, of course!) understand what is going on.
It's just a matter of what words we choose to describe it.

Using your definition of value, though, I believe that if you want to
throw out Call By Object Reference, you also have to throw out Call By
Reference. See my 3 C++ examples above. And just for fun I did look at
the assembler output, and, indeed, the output for examples 1 and 3 is
absolutely identical. They are the same thing, as far as the CPU is
concerned.

Would you give them different names?

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


Re: Finding the instance reference of an object

2008-10-30 Thread Dale Roberts
On Oct 30, 11:03 am, Joe Strout <[EMAIL PROTECTED]> wrote:
> ...
>> Are you saying that C++ is capable of using the Call By Reference idiom,
>> but C is not, because C does not have a reference designation for formal
>> function parameters?
>
> It's been a LONG time since I did anything in C, but yes, I believe  
> that reference parameters were an addition that came with C++.

Okay, I completely understand you, and I think we will just have to
agree to disagree about the best term to use for Python's parameter
passing mechanism, and this will likely be my concluding post on this
topic (although I have enjoyed it very much and have solidified my own
understanding).

I even found a few web sites that very strongly support your viewpoint
(as it relates to Java):

  http://www.ibm.com/developerworks/library/j-praxis/pr1.html
  http://javadude.com/articles/passbyvalue.htm
  http://www.yoda.arachsys.com/java/passing.html

The difference is that I would say that C supports the Pass By
Reference idiom using this syntax:

  myfunc(int *val){}   /*CALL:*/ myfunc(&i);

which actually passes an address expression (not a variable) by value,
but "looks and feels" like a reference to the "i" variable, which
contains the real value that we care about - and allows modification
of that value.

C++ adds a syntactic change for this very commonly used C idiom, but
does not add any new capability - the results are absolutely
indistinguishable.

Python, likewise, in relation to the values we care about (the values
contained only in objects, never in variables) behaves like Call by
Object Reference.

If I tell someone that Python uses only Call By Value (and that is all
I tell them), they may come away with the impression that variables
contain the values they care about, and/or that the contents of
objects are copied, neither of which is the case, even for so-called
"simple", immutable objects (indeed, at the start of this thread, you
said you believed that, like Java, simple values were contained within
Python variables).

But Python, unlike Java or most other commonly used languages, can
ONLY EVER pass an object reference, and never an actual value I care
about, and I think that idiom deserves a different name which
distinguishes it from the commonly accepted notion of Pass By Value.

Thanks for a thoughtful discussion,
dale
--
http://mail.python.org/mailman/listinfo/python-list


Re: Finding the instance reference of an object

2008-10-30 Thread Dale Roberts
On Oct 30, 3:06 pm, Dale Roberts <[EMAIL PROTECTED]> wrote:
> ... that idiom deserves a different name which
> distinguishes it from the commonly accepted notion of Pass By Value.

Bah, what I meant to end with was:

Just as the Pass By Reference idiom deserves a unique name to
distinguish it from Pass By Value (even though it is often Pass By
(address) Value internally), so Pass By Object Reference deserves a
unique name (even though it too is Pass By (reference) Value
internally).

Again, thanks for the discussion,
dale
--
http://mail.python.org/mailman/listinfo/python-list


Re: Finding the instance reference of an object

2008-10-31 Thread Dale Roberts
On Oct 31, 3:15 am, greg <[EMAIL PROTECTED]> wrote:
> Dale Roberts wrote:
> > Just as the Pass By Reference idiom deserves a unique name to
> > distinguish it from Pass By Value (even though it is often Pass By
> > (address) Value internally), so Pass By Object Reference deserves a
> > unique name (even though it too is Pass By (reference) Value
> > internally).
>
> Since Python only has one parameter passing mechanism,
> there's no need to give it a name at all. If you're
> having to explain it, just explain it, and don't
> bother naming it!
>
> --
> Greg

On Oct 31, 3:15 am, greg <[EMAIL PROTECTED]> wrote:
> Dale Roberts wrote:
> > Just as the Pass By Reference idiom deserves a unique name to
> > distinguish it from Pass By Value (even though it is often Pass By
> > (address) Value internally), so Pass By Object Reference deserves a
> > unique name (even though it too is Pass By (reference) Value
> > internally).
>
> Since Python only has one parameter passing mechanism,
> there's no need to give it a name at all. If you're
> having to explain it, just explain it, and don't
> bother naming it!
>
> --
> Greg

But then why bother having any other names at all for other languages
that have only one calling mechanism, like Call By Name, Call By Macro
Expansion, etc.

If it is a different process, it needs a different name. OR, as you
suggest, no name at all, just an explanation.

But please don't give it the WRONG name!
--
http://mail.python.org/mailman/listinfo/python-list


Re: Finding the instance reference of an object

2008-10-31 Thread Dale Roberts
On Oct 31, 2:27 am, greg <[EMAIL PROTECTED]> wrote:
> Dale Roberts wrote:
> > Are you
> > saying that C++ is capable of using the Call By Reference idiom, but C
> > is not, because C does not have a reference designation for formal
> > function parameters?
>
> Call by reference is not an "idiom", it's a *language
> feature*.
> ...
> You can use an idiom in C to get the same effect, but this
> is not the same thing as the language having it as a feature.

Okay, I'll grant that, but is there a language other than Python that
uses the Call By Value feature that does not do it by assigning/
copying the result of an expression into the formal parameter?

The terms "result" and "value" are generally understood to refer to
the working data of the program, not the internal workings of the
interpreter, VM, or compiler.

So, yes, internally the C Python runtime does use Call By Value. It's
written in C after all - that's all it can do.

But Call By Value is not a feature of the Python language.

dale

[Somebody unplug my network cable! I can't stop!]
--
http://mail.python.org/mailman/listinfo/python-list


Re: any(), all() and empty iterable

2009-04-16 Thread Dale Roberts
On Apr 14, 8:33 am, Tim Chase  wrote:
> ...
> I still prefer "Return False if any element of the iterable is
> not true" or "Return False if any element in the iterable is
> false" because that describes exactly what the algorithm does.

I agree that the original doc comment is not helpful as it stands
(even though the behavior of any() is of course correct!), and prefer
Tim's alternative. Since Python is used by programmers (hopefully!),
the doc comment should be directed toward that audience. It should be
unambiguous, and should not assume everyone has perfect knowledge of
mathematical logic operations, or that Python necessarily follows the
rules that a logician would expect (take the varying behavior of
"modulo" operators in various languages as an example).

Pure logic aside, if I was presented with the original comment
('Return True if all elements of the iterable are true.') as a
specification, as a programmer I would immediately have to ask what to
do in the case of an empty list. It might be that the user hadn't
thought about it, or would want to throw an exception, or return
False.

The doc should speak to the intended audience: programmers, who like
to make sure all bases and cases are covered.

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


Re: any(), all() and empty iterable

2009-04-16 Thread Dale Roberts
On Apr 16, 2:27 pm, Tim Chase  wrote:
> Raymond Hettinger wrote:
> > I will not change the sentence to "return false if any element
> > of the iterable is false."  The negations make the sentence
> > hard to parse mentally
>
> Just as a ribbing, that "return X if any element of the iterable
> is X" is of the same form as the original.  The negation is only
> of the X, not of the sentence structure.
>
> > I will probably leave the lead-in sentence as-is but may
> > add another sentence specifically covering the case for
> > an empty iterable.
>
> as one of the instigators in this thread, I'm +1 on this solution.

Yes, I now appreciate the motivation for having the word "all" in the
text, and simply adding something like "or the iterable is empty"
might head off future confusion.

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


send() to a generator in a "for" loop with continue(val)??

2009-04-17 Thread Dale Roberts
I've started using generators for some "real" work (love them!), and I
need to use send() to send values back into the yield inside the
generator. When I want to use the generator, though, I have to
essentially duplicate the machinery of a "for" loop, because the "for"
loop does not have a mechanism to send into the generator. Here is a
toy example:

def TestGen1():
for i in xrange(3):
sendval = yield i
print "   got %s in TestGen()" % sendval

g = TestGen1()
sendval = None
try:
while True:
val = g.send(sendval)
print 'val in "while" loop %d' % val
sendval = val * 10
except StopIteration: pass

I have to explicitly create the generator with an assignment, send an
initial None to the generator on the first go, then have to catch the
StopIteration exception. In other words, replicate the "for"
mechanism, but use send() instead of next().

It would be nice if I could just do this instead:

for val in TestGen1():
print 'val in "for" loop %d' % val
continue(val*10)

...or something similar. Is this an old idea? Has it been shot down in
the past already? Or is it worth pursuing? I Googled around and saw
one hit here: 
http://mail.python.org/pipermail/python-ideas/2009-February/003111.html,
but not much follow-up.

I wonder if people want to keep the idea of an "iterator" style
generator (where send() is not used) separate from the idea of a "co-
routine" style generator (where send() is used). Maybe combining the
two idioms in this way would cause confusion?

What do folks think?

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


Re: send() to a generator in a "for" loop with continue(val)??

2009-04-19 Thread Dale Roberts
On Apr 17, 10:07 pm, Aaron Brady  wrote:
> You can do it with a wrapping generator.  I'm not sure if it
> interferes with your needs.  It calls 'next' the first time, then just
> calls 'send' on the parameter with the value you send it.

Aaron,

Thanks for the hint. I'd made a modified version of my generator that
was "for loop aware" and had two yields in it, but this seemed very
fragile and hackish to me, and left my generator only usable inside a
"for" loop.

The wrapper method seems to be a much better way to go.

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


Re: send() to a generator in a "for" loop with continue(val)??

2009-04-19 Thread Dale Roberts
On Apr 19, 6:10 am, Peter Otten <__pete...@web.de> wrote:
> ...
> I only just started reading Beazley's presentation, it looks interesting.
> Thanks for the hint!
>
> Are you currently using coroutines in Python? If so, what kind of practical
> problems do they simplify for you?

I thought I'd chime in with an application too. I am using this
mechanism to implement a state machine. I read through Beazley's
presentation too - wow, lots of ideas in there.

For my simple state machine, I am using a very simple "trampoline"
function (see his slides starting at about #172). My "run" routine is
a bit different, but the idea is similar.

I'm using this to present images to a test subject (a person looking
at a computer screen), and the person's responses guide the state
machine. So I need to get data in (the subject responses) and out (the
next image to be presented).

So I have violated The Beazley Principle of slide #195:

Keeping it Straight
  • If you are going to use coroutines, it is critically
important to not mix programming paradigms
together
  • There are three main uses of yield
 • Iteration (a producer of data)
 • Receiving messages (a consumer)
 • A trap (cooperative multitasking)
  • Do NOT write generator functions that try to
do more than one of these at once

...whoops!

But I think this is a valid use of the mechanism, in that it is very
localized and self contained to just the few routines that make up the
state machine. It works very well, makes it easy to implement the
state machine clearly, and is easy to understand and maintain.

I can see where it could get very confusing to use this mechanism in a
more general way.

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