Re: one to many (passing variables)

2014-07-30 Thread Antoon Pardon
On 30-07-14 13:37, Peter Otten wrote:

> Antoon Pardon wrote:
>
>> Taking this in consideration I think the io.RawIOBase.read got it
>> backwards.
>>
>> The documentation says the following:
>>
>> | If 0 bytes are returned, and size was not 0, this indicates end of file.
>> | If the object is in non-blocking mode and no bytes are available, None
>> | is returned.
>>
>> But typically if you are reading in non-blocking mode, no bytes availabe
>> can be treated as if you receive an empty (byte)string. While reaching the
>> end of the stream is different. So it would have been more consistent if
>> an empty (byte)string was return in case of no bytes availabe and None or
>> io.EOF or something like that in case of end of file.
>>
>> Now I have to write things as follows:
>>
>> for block in iter(partial(RawStream.read, 1024), ''):
>> if block is not None:
>> for b in block
>> process(b)
> or
>
> for block in ...:
> for b in block or ():
> process(b)

No it obscures what is going on and is prone to problems if you have more code
that expects block to be a (byte)string. I think this is better:

for block in ...:
block = block or ''
for b in block:
process(b)
do_other_stuff_with(block) 

It is not that big a deal but you can't escape testing for an exceptional
value, whether you do it with an if or with an or. A test that wouldn't
be needed if they had done it the other way around. IMO they stayed too
close to how things are done in C. 

>> Otherwise I could write it more as follows:
>>
>> for block in iter(partial(RawStream.read, 1024), io.EOF):
>> for b in block
>> process(b)
>  
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: one to many (passing variables)

2014-07-30 Thread Peter Otten
Antoon Pardon wrote:

> Taking this in consideration I think the io.RawIOBase.read got it
> backwards.
> 
> The documentation says the following:
> 
> | If 0 bytes are returned, and size was not 0, this indicates end of file.
> | If the object is in non-blocking mode and no bytes are available, None
> | is returned.
> 
> But typically if you are reading in non-blocking mode, no bytes availabe
> can be treated as if you receive an empty (byte)string. While reaching the
> end of the stream is different. So it would have been more consistent if
> an empty (byte)string was return in case of no bytes availabe and None or
> io.EOF or something like that in case of end of file.
> 
> Now I have to write things as follows:
> 
> for block in iter(partial(RawStream.read, 1024), ''):
> if block is not None:
> for b in block
> process(b)

or

for block in ...:
for b in block or ():
process(b)

> Otherwise I could write it more as follows:
> 
> for block in iter(partial(RawStream.read, 1024), io.EOF):
> for b in block
> process(b)
 


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


Re: one to many (passing variables)

2014-07-30 Thread Antoon Pardon
On 28-07-14 21:29, Terry Reedy wrote:

> On 7/25/2014 9:47 PM, C.D. Reimer wrote:
>> On 7/24/2014 2:58 AM, Ben Finney wrote:
>>> Here is an article on good API design; the principles apply to Python
>>> http://blog.isnotworking.com/2007/05/api-design-guidelines.html>.
>>> You know your API and its requirements better than we; see whether that
>>> sheds any light on improvements to make.
>> Thank you for the link. I'm curious about one item mentioned in the
>> article: "Avoid return values that Demand Exceptional Processing: return
>> zero-length array or empty collection, not null"
>> Isn't a zero-length array, empty collection and null all the same thing?
> No. [] is an empty list, None is a null.
>> Or does the "Demand Exceptional Processing" comes from testing to see if
>> the object is empty versus being null?
> Testing whether null or not.
>> And does this apply to Python?
> Yes. If a function always returns a iterable, sometimes empty, it can be 
> used as follows:
> for item in f(): process(item)
> If the iterable is empty, nothing happens.  If the function returns None 
> instead of empty, then the use has to write the following to get the 
> same result.

Taking this in consideration I think the io.RawIOBase.read got it backwards.

The documentation says the following:

| If 0 bytes are returned, and size was not 0, this indicates end of file.
| If the object is in non-blocking mode and no bytes are available, None is 
returned.

But typically if you are reading in non-blocking mode, no bytes availabe can be
treated as if you receive an empty (byte)string. While reaching the end of the
stream is different. So it would have been more consistent if an empty 
(byte)string
was return in case of no bytes availabe and None or io.EOF or something like 
that
in case of end of file.

Now I have to write things as follows:

for block in iter(partial(RawStream.read, 1024), ''):
if block is not None:
for b in block
process(b)

Otherwise I could write it more as follows:

for block in iter(partial(RawStream.read, 1024), io.EOF):
for b in block
process(b)

-- 
Antoon Pardon

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


Re: one to many (passing variables)

2014-07-28 Thread CHIN Dihedral
On Tuesday, July 29, 2014 3:29:04 AM UTC+8, Terry Reedy wrote:
> On 7/25/2014 9:47 PM, C.D. Reimer wrote:
> 
> >
> 
> > On 7/24/2014 2:58 AM, Ben Finney wrote:
> 
> >> Here is an article on good API design; the principles apply to Python
> 
> >> http://blog.isnotworking.com/2007/05/api-design-guidelines.html>.
> 
> >> You know your API and its requirements better than we; see whether that
> 
> >> sheds any light on improvements to make.
> 
> > Thank you for the link. I'm curious about one item mentioned in the
> 
> > article: "Avoid return values that Demand Exceptional Processing: return
> 
> > zero-length array or empty collection, not null"
> 
> >
> 
> > Isn't a zero-length array, empty collection and null all the same thing?
> 
> 
> 
> No. [] is an empty list, None is a null.
> 
> 
> 
> > Or does the "Demand Exceptional Processing" comes from testing to see if
> 
> > the object is empty versus being null?
> 
> 
> 
> Testing whether null or not.
> 
> 
> 
> > And does this apply to Python?
> 
> 
> 
> Yes. If a function always returns a iterable, sometimes empty, it can be 
> 
> used as follows:
> 
> 
> 
> for item in f(): process(item)
> 
> 
> 
> If the iterable is empty, nothing happens.  If the function returns None 
> 
> instead of empty, then the use has to write the following to get the 
> 
> same result.
> 
> 
> 
> result = f()
> 
> if result is not None:
> 
>for item in f(): process(item)
> 
> 
> 
> The function user may *elect* to give special processing to empty 
> 
> iterables.  A None return *demands* special processing, even if not 
> 
> needed, as above.
> 
> 
> 
> -- 
> 
> Terry Jan Reedy

Oh, iterators are better to shoot 
targets in the L1 and L2 cache memory,
but it is not  the same as the old
 reading the whole list way.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: one to many (passing variables)

2014-07-28 Thread Terry Reedy

On 7/25/2014 9:47 PM, C.D. Reimer wrote:


On 7/24/2014 2:58 AM, Ben Finney wrote:

Here is an article on good API design; the principles apply to Python
http://blog.isnotworking.com/2007/05/api-design-guidelines.html>.
You know your API and its requirements better than we; see whether that
sheds any light on improvements to make.

Thank you for the link. I'm curious about one item mentioned in the
article: "Avoid return values that Demand Exceptional Processing: return
zero-length array or empty collection, not null"

Isn't a zero-length array, empty collection and null all the same thing?


No. [] is an empty list, None is a null.


Or does the "Demand Exceptional Processing" comes from testing to see if
the object is empty versus being null?


Testing whether null or not.


And does this apply to Python?


Yes. If a function always returns a iterable, sometimes empty, it can be 
used as follows:


for item in f(): process(item)

If the iterable is empty, nothing happens.  If the function returns None 
instead of empty, then the use has to write the following to get the 
same result.


result = f()
if result is not None:
  for item in f(): process(item)

The function user may *elect* to give special processing to empty 
iterables.  A None return *demands* special processing, even if not 
needed, as above.


--
Terry Jan Reedy

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


Re: one to many (passing variables)

2014-07-28 Thread Neil D. Cerutti

On 7/25/2014 9:47 PM, C.D. Reimer wrote:

Thank you for the link. I'm curious about one item mentioned in the
article: "Avoid return values that Demand Exceptional Processing: return
zero-length array or empty collection, not null"

Isn't a zero-length array, empty collection and null all the same thing?

Or does the "Demand Exceptional Processing" comes from testing to see if
the object is empty versus being null?


This seems like a specific application of a more general rule (I think I 
remember it from The C Programming Language by Kernighan and Ritchie): 
Whenever possible, manage special cases with data rather than with code. 
Doing so makes your data processing code simpler, and may help prevent 
errors.


This should apply to any programming language.

A mundane example is managing multi-line street addresses in a system 
storing addresses: most applications choose to store address lines as 
Street Address 1, through Street Address N, for some finite value of N, 
even though it results in special cases to handle. This is probably 
because it is more efficient: non-normalised data can be an efficiency 
win. Also, forgetting or refusing to handle the case of multi-line 
street addresses works "well enough" most of the time.


You could instead store multi-line street addresses as a list of 
components in the street address: Forgetting to handle the "special 
cases" would then be impossible. In order to do a cheesy job you'd have 
to explicitly retrieve street_address[0] and ignore the rest.


--
Neil Cerutti

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


Re: one to many (passing variables)

2014-07-25 Thread Steven D'Aprano
On Fri, 25 Jul 2014 18:47:55 -0700, C.D. Reimer wrote:

> On 7/24/2014 2:58 AM, Ben Finney wrote:
>> Here is an article on good API design; the principles apply to Python
>> http://blog.isnotworking.com/2007/05/api-design-guidelines.html>.
>> You know your API and its requirements better than we; see whether that
>> sheds any light on improvements to make.
> Thank you for the link. I'm curious about one item mentioned in the
> article: "Avoid return values that Demand Exceptional Processing: return
> zero-length array or empty collection, not null"
> 
> Isn't a zero-length array, empty collection and null all the same thing?

No.

Since an array is a kind of collection, a zero-length array is an empty
array, which is an empty collection. But null is not the same thing. In
Python terms, it is the difference between:

return []

return None


While I agree that in general it is better to return (say) a consistent list
result, sometimes you need an exceptional result that is different from
the "empty" or "zero" result. In that case, there are two obvious ways to
deal with exceptional circumstances:

- raise an exception, e.g. "spam".index("e") raises

- return a special result, e.g. "spam".find("e") returns -1


Raising an exception is the obvious way to handle it, but exception handling
is a little less convenient than testing for a special value. Hence the
find() convenience method. However, find() makes a silly mistake: it
returns -1 to indicate Not Found, and -1 is acceptable as an index. So if
you forget to test for the Not Found case, you might write this:

p = some_string.find(needle)
return another_string[p]


which is wrong. If find() returns -1, another_string[p] returns the *last*
character in the string, which is probably not what you want.

A better API is that of the regular expression module. re.search() and
re.match() return either a match object, or None if the regex doesn't match
at all. So if you forget to test for None, and blindly try to treat the
result as if it where a match object, you will immediately get an exception
instead of invalid results:

mo = re.search(text, needle)
return mo.group()  # will raise if mo is None

In summary:

* if you're returning a list of results, deal with no results 
  by returning an empty list [] rather than None;

* if you need to distinguish between the empty list case and 
  some exceptional situation, the best way is to raise an 
  exception;

* if you don't wish to raise an exception, it is better to 
  return some result which clearly cannot be mistaken for, or
  accidentally used as, a regular non-exceptional result;

* e.g. if your function normally returns an integer, better to
  return None as a "no result exists" than 0 or -1, since they
  are valid integers and None isn't.


-- 
Steven


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


Re: one to many (passing variables)

2014-07-25 Thread Chris Angelico
On Sat, Jul 26, 2014 at 11:47 AM, C.D. Reimer  wrote:
> Isn't a zero-length array, empty collection and null all the same thing?

Definitely not. In C++ and Java, which he's primarily looking at,
there's a definite difference in usage, and potentially in memory
usage/performance.

> Or does the "Demand Exceptional Processing" comes from testing to see if the
> object is empty versus being null?
>
> And does this apply to Python?

In Python, if you have something that might return a list of
somethings, but in certain circumstances won't have any to return,
don't have it return None in that case; just return an empty list.
Compare:

def func(args):
if condition: return None
return [1,2,3]

x = func(142857)
if x:
for i in x:
do_stuff(i)


With this:

def func(args):
if condition: return []
return [1,2,3]

x = func(142857)
for i in x:
do_stuff(i)


The second one will always return a list, ergo you can always iterate
over it. You can still use "if x" to see if you got the empty one.

The point he's making is distinctly stronger in Python than in C++ or
Java, to the extent that it's a complete non-issue. In lower-level
languages, returning a null pointer is cheaper than constructing a
zero-length array, and testing an array for contents is both slower
and more verbose than testing for null-ness; but in Python, the cost
difference between "return None" and "return []" is negligible (there
is a difference, of course, but honestly - if you're worried about
that, Python is the wrong language for you), and the difference
between "if x" and "if x" is... uhh, nonexistent. :) His point is that
it's better to make things simple and clear and understandable than to
save a little bit of memory by returning null rather than an empty
array; and I don't think any Python programmers will disagree.

(There are, of course, times when you need to distinguish between a
non-result and a result with no items in it, which would be done by
returning None and returning [], respectively. That's different. Then
it's part of your API, as a separate state.)

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: one to many (passing variables)

2014-07-25 Thread C.D. Reimer


On 7/24/2014 2:58 AM, Ben Finney wrote:

Here is an article on good API design; the principles apply to Python
http://blog.isnotworking.com/2007/05/api-design-guidelines.html>.
You know your API and its requirements better than we; see whether that
sheds any light on improvements to make.
Thank you for the link. I'm curious about one item mentioned in the 
article: "Avoid return values that Demand Exceptional Processing: return 
zero-length array or empty collection, not null"


Isn't a zero-length array, empty collection and null all the same thing?

Or does the "Demand Exceptional Processing" comes from testing to see if 
the object is empty versus being null?


And does this apply to Python?

Thank you,

Chris Reimer
--
https://mail.python.org/mailman/listinfo/python-list


Re: one to many (passing variables)

2014-07-24 Thread Ben Finney
Martin S  writes:

> I have functions A B and C. If data generated in A is useable in both
> B and C how do I ensure this data is passed as needed? Or is it a
> symptom of bad code?

This is very vague; an accurate answer is “it depends”.

You seem to be asking about how to design your data structures and APIs.
This is less a Python-specific question and more a matter of experience
and judgement.

Here is an article on good API design; the principles apply to Python
http://blog.isnotworking.com/2007/05/api-design-guidelines.html>.
You know your API and its requirements better than we; see whether that
sheds any light on improvements to make.

It sounds like you are needing to decide how to arrange the data
structures. You need to find natural divisions and groupings, such that
you can refer to groupings of properties that make sense and that are
not too unwieldy.

-- 
 \ “Religious faith is the one species of human ignorance that |
  `\ will not admit of even the *possibility* of correction.” —Sam |
_o__) Harris, _The End of Faith_, 2004 |
Ben Finney

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


Re: one to many (passing variables)

2014-07-24 Thread Steven D'Aprano
On Thu, 24 Jul 2014 09:27:10 +0200, Martin S wrote:

> Function A collects data and then calls function B with some, but also
> has data that should be passed to function C.

It might help if you give a bit more information. How does it collect 
data, how does it decide which bits of information should be passed to B 
and which to C, and what happens with the results returned from B and C?

But something like this should give you an idea:


def funca(values):
data_for_b = []
data_for_c = []
for value in values:
if 0 < value <= 100:
data_for_b.append(value)
elif 100 < value <= 200:
data_for_c.append(value)
# otherwise just discard it
result_from_b = funcb(data_for_b)
result_from_a = funcc(data_for_c)
return max(result_from_b, result_from_a)


def funcb(values):
return 5*sum(values)

def funcc(values):
return 2*sum(values) - 200


print(funca([2, 5, 107, 99, 1999, 2345, 84, 156, 23]))


If you run that code, it should print 1065.


If this is not what you mean, I'm afraid you're going to have to explain 
what exactly you do mean, because I have no other ideas :-)


-- 
Steven
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: one to many (passing variables)

2014-07-24 Thread Chris Angelico
On Thu, Jul 24, 2014 at 5:27 PM, Martin S  wrote:
> Function A collects data and then calls function B with some, but also has
> data that should be passed to function C.
>
> But ofc if nested functions are allowed then that might solve the issue. I
> don't think I've seen nested functions mentioned in a tutorial I've been
> looking at.

Nested functions shouldn't be necessary.

Just start writing code, then figure out what needs to go where. As
long as you give a name to everything you need to keep track of,
you'll find that pretty much everything 'just works'.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: one to many (passing variables)

2014-07-24 Thread Martin S
Function A collects data and then calls function B with some, but also has data 
that should be passed to function C. 

But ofc if nested functions are allowed then that might solve the issue. I 
don't think I've seen nested functions mentioned in a tutorial I've been 
looking at. 

/martin s

On 24 Jul 2014, Chris Angelico  wrote:
>On Thu, Jul 24, 2014 at 4:36 PM, Martin S  wrote:
>> How do you pass data from one function to many?
>>
>> I have functions A B and C. If data generated in A is useable in both
>> B and C how do I ensure this data is passed as needed? Or is it a
>> symptom of bad code?
>
>This is a little vague. Is there one function which calls A and then
>calls B and C? What's the relationship between them? Is it logical for
>A to itself call B and C? Are they all methods off one object?
>Top-level functions in a module?
>
>ChrisA

-- Sent with K-@ Mail - the evolution of emailing.-- 
https://mail.python.org/mailman/listinfo/python-list


Re: one to many (passing variables)

2014-07-24 Thread Chris Angelico
On Thu, Jul 24, 2014 at 4:36 PM, Martin S  wrote:
> How do you pass data from one function to many?
>
> I have functions A B and C. If data generated in A is useable in both
> B and C how do I ensure this data is passed as needed? Or is it a
> symptom of bad code?

This is a little vague. Is there one function which calls A and then
calls B and C? What's the relationship between them? Is it logical for
A to itself call B and C? Are they all methods off one object?
Top-level functions in a module?

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list