Re: one to many (passing variables)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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