Re: A gnarly little python loop
Steve Howell, 11.11.2012 04:03: > On Nov 10, 2:58 pm, Roy Smith wrote: >> I'm trying to pull down tweets with one of the many twitter APIs. The >> particular one I'm using (python-twitter), has a call: >> >> data = api.GetSearch(term="foo", page=page) >> >> The way it works, you start with page=1. It returns a list of tweets. >> If the list is empty, there are no more tweets. If the list is not >> empty, you can try to get more tweets by asking for page=2, page=3, etc. >> I've got: >> >> page = 1 >> while 1: >> r = api.GetSearch(term="foo", page=page) >> if not r: >> break >> for tweet in r: >> process(tweet) >> page += 1 >> >> It works, but it seems excessively fidgety. Is there some cleaner way >> to refactor this? > > I think your code is perfectly readable and clean, but you can flatten > it like so: > > def get_tweets(term, get_page): > page_nums = itertools.count(1) > pages = itertools.imap(api.getSearch, page_nums) > valid_pages = itertools.takewhile(bool, pages) > tweets = itertools.chain.from_iterable(valid_pages) > return tweets I'd prefer the original code ten times over this inaccessible beast. Stefan -- http://mail.python.org/mailman/listinfo/python-list
Re: KAJOL SEX VIDEOS'''''''''''''''''''
On Thursday, August 2, 2012 10:05:25 PM UTC+5:30, devi wrote: > KAJAL SEX VIDEOS > > http://maxworkerds.co.cc -- http://mail.python.org/mailman/listinfo/python-list
Re: A gnarly little python loop
On 11Nov2012 08:56, Stefan Behnel wrote: | Steve Howell, 11.11.2012 04:03: | > On Nov 10, 2:58 pm, Roy Smith wrote: | >> page = 1 | >> while 1: | >> r = api.GetSearch(term="foo", page=page) | >> if not r: | >> break | >> for tweet in r: | >> process(tweet) | >> page += 1 | >> | >> It works, but it seems excessively fidgety. Is there some cleaner way | >> to refactor this? | > | > I think your code is perfectly readable and clean, but you can flatten | > it like so: | > | > def get_tweets(term, get_page): | > page_nums = itertools.count(1) | > pages = itertools.imap(api.getSearch, page_nums) | > valid_pages = itertools.takewhile(bool, pages) | > tweets = itertools.chain.from_iterable(valid_pages) | > return tweets | | I'd prefer the original code ten times over this inaccessible beast. Me too. -- Cameron Simpson In an insane society, the sane man must appear insane. - Keith A. Schauer -- http://mail.python.org/mailman/listinfo/python-list
Re: A gnarly little python loop
Cameron Simpson writes: > | I'd prefer the original code ten times over this inaccessible beast. > Me too. Me, I like the itertools version better. There's one chunk of data that goes through a succession of transforms each of which is very straightforward. -- http://mail.python.org/mailman/listinfo/python-list
Re: Is there a simpler way to modify all arguments in a function before using the arguments?
Aahz wrote: > In article , > Peter Otten <__pete...@web.de> wrote: >>Miki Tebeka wrote: >> Is there a simpler way to modify all arguments in a function before using the arguments? >>> >>> You can use a decorator: >>> >>> from functools import wraps >>> >>> def fix_args(fn): >>> @wraps(fn) >>> def wrapper(*args): >>> args = (arg.replace('_', '') for arg in args) >>> return fn(*args) >>> >>> return wrapper >>> >>> @fix_args >>> def foo(x, y): >>> print(x) >>> print(y) >> >>I was tempted to post that myself, but he said /simpler/ ;) > > From my POV, that *is* simpler. When you change the parameters for foo, > you don't need to change the arg pre-processing. Also allows code reuse, > probably any program needing this kind of processing once will need it > again. Typical changes would be @fix_args def bar(x, y=None): print(x) print(y) @fix_args def baz(file, x, y): print(s, file=file) Do you find it obvious what bar("a_b") bar("a_b", y="c_d") print? Do you find the traceback produced by the latter helpful? Moving complexity into a helper function often makes client code simpler because if the helper is well-tested and preferrably maintained by someone else the part that you have to deal with becomes simpler, but the overall complexity still increases. A fix_args() decorator is worthwhile only if you need it more than once or twice, and because it is hard to generalise I expect that yagni. -- http://mail.python.org/mailman/listinfo/python-list
Re: A gnarly little python loop
Paul Rubin wrote: > Cameron Simpson writes: >> | I'd prefer the original code ten times over this inaccessible beast. >> Me too. > > Me, I like the itertools version better. There's one chunk of data > that goes through a succession of transforms each of which > is very straightforward. [Steve Howell] > def get_tweets(term, get_page): > page_nums = itertools.count(1) > pages = itertools.imap(api.getSearch, page_nums) > valid_pages = itertools.takewhile(bool, pages) > tweets = itertools.chain.from_iterable(valid_pages) > return tweets But did you spot the bug(s)? My itertools-based version would look like this def get_tweets(term): pages = (api.GetSearch(term, pageno) for pageno in itertools.count(1)) for page in itertools.takewhile(bool, pages): yield from page but I can understand that it's not everybody's cup of tea. -- http://mail.python.org/mailman/listinfo/python-list
Re: Printing characters outside of the ASCII range
On Friday, November 9, 2012 5:11:12 PM UTC-5, Ian wrote: > On Fri, Nov 9, 2012 at 2:46 PM, danielk wrote: > > > D:\home\python>pytest.py > > > Traceback (most recent call last): > > > File "D:\home\python\pytest.py", line 1, in > > > print(chr(253).decode('latin1')) > > > AttributeError: 'str' object has no attribute 'decode' > > > > > > Do I need to import something? > > > > Ramit should have written "encode", not "decode". But the above still > > would not work, because chr(253) gives you the character at *Unicode* > > code point 253, not the character with CP437 ordinal 253 that your > > terminal can actually print. The Unicode equivalents of those > > characters are: > > > > >>> list(map(ord, bytes([252, 253, 254]).decode('cp437'))) > > [8319, 178, 9632] > > > > So these are what you would need to encode to CP437 for printing. > > > > >>> print(chr(8319)) > > ⁿ > > >>> print(chr(178)) > > ² > > >>> print(chr(9632)) > > ■ > > > > That's probably not the way you want to go about printing them, > > though, unless you mean to be inserting them manually. Is the data > > you get from your database a string, or a bytes object? If the > > former, just do: > > > > print(data.encode('cp437')) > > > > If the latter, then it should be printable as is, unless it is in some > > other encoding than CP437. Ian's solution gives me what I need (thanks Ian!). But I notice a difference between '__str__' and '__repr__'. class Pytest(str): def __init__(self, data = None): if data == None: data = "" self.data = data def __repr__(self): return (self.data).encode('cp437') >>> import pytest >>> p = pytest.Pytest("abc" + chr(178) + "def") >>> print(p) abc²def >>> print(p.data) abc²def >>> print(type(p.data)) If I change '__repr__' to '__str__' then I get: >>> import pytest >>> p = pytest.Pytest("abc" + chr(178) + "def") >>> print(p) Traceback (most recent call last): File "", line 1, in TypeError: __str__ returned non-string (type bytes) Why is '__str__' behaving differently than '__repr__' ? I'd like to be able to use '__str__' because the result is not executable code, it's just a string of the record contents. The documentation for the 'encode' method says: "Return an encoded version of the string as a bytes object." Yet when I displayed the type, it said it was , which I'm taking to be 'type string', or can a 'string' also be 'a string of bytes' ? I'm trying to get my head around all this codecs/unicode stuff. I haven't had to deal with it until now but I'm determined to not let it get the best of me :-) My goals are: a) display a 'raw' database record with the delimiters intact, and b) allow the client to create a string that represents a database record. So, if they know the record format then they should be able to create a database object like it does above, but with the chr(25x) characters. I will handle the conversion of the chr(25x) characters internally. -- http://mail.python.org/mailman/listinfo/python-list
Re: Method default argument whose type is the class not yet defined
On 11 November 2012 02:47, Chris Angelico wrote: > On Sun, Nov 11, 2012 at 1:43 PM, Ian Kelly wrote: >> On Sat, Nov 10, 2012 at 7:13 PM, Chris Angelico wrote: >>> I would not assume that. The origin is a point, just like any other. >>> With a Line class, you could deem a zero-length line to be like a >>> zero-element list, but Point(0,0) is more like the tuple (0,0) which >>> is definitely True. >> >> It's more like the number 0 than the tuple (0,0). >> >> 0 is the origin on a 1-dimensional number line. >> (0,0) is the origin on a 2-dimensional number plane. >> >> In fact, it might be pointed out that Point(0, 0) is a generalization >> of 0+0j, which is equal to 0. > > Ah, good point. In any case, though, it'd be an utterly inconsequential bug. You were right the first time, Chris. A point that happens to coincide with the arbitrarily chosen origin is no more truthy or falsey than any other. A vector of length 0 on the other hand is a very different beast. The significance of zero in real algebra is not that it is the origin but rather that it is the additive and multiplicative zero: a + 0 = a for any real number a a * 0 = 0 for any real number a The same is true for a vector v0, of length 0: v + v0 = v for any vector v a * v0 = v0 for any scalar a There is however no meaningful sense in which points (as opposed to vectors) can be added to each other or multiplied by anything, so there is no zero point. The relationship between points and vectors is analogous to the relationship between datetimes and timedeltas. Having Vector(0, 0) evaluate to False is analogous to having timedelta(0) evaluate to False and is entirely sensible. Having Point(0, 0) evaluate to False is precisely the same conceptual folly that sees midnight evaluate as False. Oscar -- http://mail.python.org/mailman/listinfo/python-list
Re: Printing characters outside of the ASCII range
Am 09.11.2012 18:17 schrieb danielk: I'm using this character as a delimiter in my application. Then you probably use the *byte* 254 as opposed to the *character* 254. So it might be better to either switch to byte strings, or output the representation of the string instead of itself. So do print(repr(chr(254))) or, for byte strings, print(bytes([254])). Thomas -- http://mail.python.org/mailman/listinfo/python-list
Question about email.message_from_string() and Message objects
I'm a little confused about the relationship between the Python email.parser convenience function email.message_from_string() and the mailbox.Message objects. If I want an mailbox.mboxMessage given the message as a stream of text is the right way to do it as follows (or at least a reasonable way to do it):- msg = email.message_from_string(messageAsAString) mbxMsg = mailbox.mboxMessage(msg) Or can I go direct to mbox by doing:- mbxMsg = mailbox.mboxMessage(messageAsAString) -- Chris Green -- http://mail.python.org/mailman/listinfo/python-list
Re: Printing characters outside of the ASCII range
danielk writes: > Ian's solution gives me what I need (thanks Ian!). But I notice a > difference between '__str__' and '__repr__'. > > class Pytest(str): > def __init__(self, data = None): > if data == None: data = "" > self.data = data > > def __repr__(self): > return (self.data).encode('cp437') > The correct way of comparing with None (and in general with “singletons”) is with the “is” operator, not with “==”. > If I change '__repr__' to '__str__' then I get: > import pytest p = pytest.Pytest("abc" + chr(178) + "def") print(p) > Traceback (most recent call last): > File "", line 1, in > TypeError: __str__ returned non-string (type bytes) In Python 3.3 there is one kind of string, the one that under Python 2.x was called “unicode”. When you encode such a string with a specific encoding you obtain a plain “bytes array”. No surprise that the __str__() method complains, it's called like that for a reason :) > I'm trying to get my head around all this codecs/unicode stuff. I > haven't had to deal with it until now but I'm determined to not let it > get the best of me :-) Two good readings on the subject: - http://nedbatchelder.com/text/unipain.html - http://www.joelonsoftware.com/articles/Unicode.html ciao, lele. -- nickname: Lele Gaifax | Quando vivrò di quello che ho pensato ieri real: Emanuele Gaifas | comincerò ad aver paura di chi mi copia. l...@metapensiero.it | -- Fortunato Depero, 1929. -- http://mail.python.org/mailman/listinfo/python-list
Re: A gnarly little python loop
On Sunday, November 11, 2012 1:54:46 AM UTC-8, Peter Otten wrote: > Paul Rubin wrote: > > > > > Cameron Simpson writes: > > >> | I'd prefer the original code ten times over this inaccessible beast. > > >> Me too. > > > > > > Me, I like the itertools version better. There's one chunk of data > > > that goes through a succession of transforms each of which > > > is very straightforward. > > > > [Steve Howell] > > > def get_tweets(term, get_page): > > > page_nums = itertools.count(1) > > > pages = itertools.imap(api.getSearch, page_nums) > > > valid_pages = itertools.takewhile(bool, pages) > > > tweets = itertools.chain.from_iterable(valid_pages) > > > return tweets > > > > > > But did you spot the bug(s)? > My first version was sketching out the technique, and I don't have handy access to the API. Here is an improved version: def get_tweets(term): def get_page(page): return getSearch(term, page) page_nums = itertools.count(1) pages = itertools.imap(get_page, page_nums) valid_pages = itertools.takewhile(bool, pages) tweets = itertools.chain.from_iterable(valid_pages) return tweets for tweet in get_tweets("foo"): process(tweet) This is what I used to test it: def getSearch(term = "foo", page = 1): # simulate api for testing if page < 5: return [ 'page %d, tweet A for term %s' % (page, term), 'page %d, tweet B for term %s' % (page, term), ] else: return None def process(tweet): print tweet -- http://mail.python.org/mailman/listinfo/python-list
Re: A gnarly little python loop
On Nov 11, 1:09 am, Paul Rubin wrote: > Cameron Simpson writes: > > | I'd prefer the original code ten times over this inaccessible beast. > > Me too. > > Me, I like the itertools version better. There's one chunk of data > that goes through a succession of transforms each of which > is very straightforward. Thanks, Paul. Even though I supplied the "inaccessible" itertools version, I can understand why folks find it inaccessible. As I said to the OP, there was nothing wrong with the original imperative approach; I was simply providing an alternative. It took me a while to appreciate itertools, but the metaphor that resonates with me is a Unix pipeline. It's just a metaphor, so folks shouldn't be too literal, but the idea here is this: page_nums -> pages -> valid_pages -> tweets The transforms are this: page_nums -> pages: call API via imap pages -> valid_pages: take while true valid_pages -> tweets: use chain.from_iterable to flatten results Here's the code again for context: def get_tweets(term): def get_page(page): return getSearch(term, page) page_nums = itertools.count(1) pages = itertools.imap(get_page, page_nums) valid_pages = itertools.takewhile(bool, pages) tweets = itertools.chain.from_iterable(valid_pages) return tweets -- http://mail.python.org/mailman/listinfo/python-list
Re: Question about email.message_from_string() and Message objects
tinn...@isbd.co.uk wrote: > I'm a little confused about the relationship between the Python > email.parser convenience function email.message_from_string() and the > mailbox.Message objects. > > If I want an mailbox.mboxMessage given the message as a stream of text > is the right way to do it as follows (or at least a reasonable way to > do it):- > > msg = email.message_from_string(messageAsAString) > > mbxMsg = mailbox.mboxMessage(msg) > > Or can I go direct to mbox by doing:- > > mbxMsg = mailbox.mboxMessage(messageAsAString) > Answered myself by just trying it, the simple, straightforward mbxMsg = mailbox.mboxMessage(messageAsAString) works perfectly. -- Chris Green -- http://mail.python.org/mailman/listinfo/python-list
Re: Is there a simpler way to modify all arguments in a function before using the arguments?
On Nov 9, 4:48 pm, bruceg113...@gmail.com wrote: > Is there a simpler way to modify all arguments in a function before using the > arguments? > > For example, can the below code, in the modify arguments section be made into > a few statements? > > def someComputation (aa, bb, cc, dd, ee, ff, gg, hh): > # modify arguments > # -- > aa = aa.replace (“_” , “”) > bb= bb.replace (“_” , “”) > cc = cc.replace (“_” , “”) > dd = dd.replace (“_” , “”) > ee = ee.replace (“_” , “”) > ff = ff.replace (“_” , “”) > gg = gg.replace (“_” , “”) > hh = hh.replace (“_” , “”) > > # use the arguments > # - > # … I would couch this problem in a little more specific terms than trying to make this "simpler." The word "simple" is a dangerous term, because it's so broad and subjective. By my mind, the code is already simple, but that's just my own two cents. The real problem with the code that it's a maintenance trap, because a careless developer could add the ii parameter and forget to clean the output. So the problem statement here might be more like "How do I make sure future developers don't forget to fix the underscores in future args?". That's still a controversial question, but at least it's a little more specific. The other problem with the current code is that all the boilerplate distracts from the real logic of the function. That's a valid concern, although it's likely that most maintainers of the code would simply page down past the boilerplate without too much complaint. -- http://mail.python.org/mailman/listinfo/python-list
logging, can one get it to email messages over a certain level?
I'm sure this must be possible but at the moment I can't see how to do it. I want to send an E-Mail when the logging module logs a message above a certain level (probably for ERROR and CRITICAL messages only). I.e. I want some sort of hook that will be called when these messages are logged (I can do the sendmail bit OK, I've got code that does that). -- Chris Green -- http://mail.python.org/mailman/listinfo/python-list
Re: logging, can one get it to email messages over a certain level?
On Nov 11, 9:48 am, tinn...@isbd.co.uk wrote: > I'm sure this must be possible but at the moment I can't see how to do it. > > I want to send an E-Mail when the logging module logs a message above > a certain level (probably for ERROR and CRITICAL messages only). > > I.e. I want some sort of hook that will be called when these messages > are logged (I can do the sendmail bit OK, I've got code that does that). > > -- > Chris Green Scroll down to the Handlers section here: http://docs.python.org/2/howto/logging.html#logging-basic-tutorial I'm not sure this explains perfectly what you're gonna need to do, but I hope it gets you in the ballpark. -- http://mail.python.org/mailman/listinfo/python-list
Re: A gnarly little python loop
Steve Howell wrote: > On Nov 11, 1:09 am, Paul Rubin wrote: >> Cameron Simpson writes: >> > | I'd prefer the original code ten times over this inaccessible beast. >> > Me too. >> >> Me, I like the itertools version better. There's one chunk of data >> that goes through a succession of transforms each of which >> is very straightforward. > > Thanks, Paul. > > Even though I supplied the "inaccessible" itertools version, I can > understand why folks find it inaccessible. As I said to the OP, there > was nothing wrong with the original imperative approach; I was simply > providing an alternative. > > It took me a while to appreciate itertools, but the metaphor that > resonates with me is a Unix pipeline. It's just a metaphor, so folks > shouldn't be too literal, but the idea here is this: > > page_nums -> pages -> valid_pages -> tweets > > The transforms are this: > > page_nums -> pages: call API via imap > pages -> valid_pages: take while true > valid_pages -> tweets: use chain.from_iterable to flatten results > > Here's the code again for context: > > def get_tweets(term): > def get_page(page): > return getSearch(term, page) > page_nums = itertools.count(1) > pages = itertools.imap(get_page, page_nums) > valid_pages = itertools.takewhile(bool, pages) > tweets = itertools.chain.from_iterable(valid_pages) > return tweets > Actually you supplied the "accessible" itertools version. For reference, here's the inaccessible version: class api: """Twitter search API mock-up""" pages = [ ["a", "b", "c"], ["d", "e"], ] @staticmethod def GetSearch(term, page): assert term == "foo" assert page >= 1 if page > len(api.pages): return [] return api.pages[page-1] from collections import deque from functools import partial from itertools import chain, count, imap, takewhile def process(tweet): print tweet term = "foo" deque( imap( process, chain.from_iterable( takewhile(bool, imap(partial(api.GetSearch, term), count(1), maxlen=0) ;) -- http://mail.python.org/mailman/listinfo/python-list
Re: A gnarly little python loop
On Nov 11, 10:34 am, Peter Otten <__pete...@web.de> wrote: > Steve Howell wrote: > > On Nov 11, 1:09 am, Paul Rubin wrote: > >> Cameron Simpson writes: > >> > | I'd prefer the original code ten times over this inaccessible beast. > >> > Me too. > > >> Me, I like the itertools version better. There's one chunk of data > >> that goes through a succession of transforms each of which > >> is very straightforward. > > > Thanks, Paul. > > > Even though I supplied the "inaccessible" itertools version, I can > > understand why folks find it inaccessible. As I said to the OP, there > > was nothing wrong with the original imperative approach; I was simply > > providing an alternative. > > > It took me a while to appreciate itertools, but the metaphor that > > resonates with me is a Unix pipeline. It's just a metaphor, so folks > > shouldn't be too literal, but the idea here is this: > > > page_nums -> pages -> valid_pages -> tweets > > > The transforms are this: > > > page_nums -> pages: call API via imap > > pages -> valid_pages: take while true > > valid_pages -> tweets: use chain.from_iterable to flatten results > > > Here's the code again for context: > > > def get_tweets(term): > > def get_page(page): > > return getSearch(term, page) > > page_nums = itertools.count(1) > > pages = itertools.imap(get_page, page_nums) > > valid_pages = itertools.takewhile(bool, pages) > > tweets = itertools.chain.from_iterable(valid_pages) > > return tweets > > Actually you supplied the "accessible" itertools version. For reference, > here's the inaccessible version: > > class api: > """Twitter search API mock-up""" > pages = [ > ["a", "b", "c"], > ["d", "e"], > ] > @staticmethod > def GetSearch(term, page): > assert term == "foo" > assert page >= 1 > if page > len(api.pages): > return [] > return api.pages[page-1] > > from collections import deque > from functools import partial > from itertools import chain, count, imap, takewhile > > def process(tweet): > print tweet > > term = "foo" > > deque( > imap( > process, > chain.from_iterable( > takewhile(bool, imap(partial(api.GetSearch, term), count(1), > maxlen=0) > > ;) I know Peter's version is tongue in cheek, but I do think that it has a certain expressive power, and it highlights three mind-expanding Python modules. Here's a re-flattened take on Peter's version ("Flat is better than nested." -- PEP 20): term = "foo" search = partial(api.GetSearch, term) nums = count(1) paged_tweets = imap(search, nums) paged_tweets = takewhile(bool, paged_tweets) tweets = chain.from_iterable(paged_tweets) processed_tweets = imap(process, tweets) deque(processed_tweets, maxlen=0) The use of deque to exhaust an iterator is slightly overboard IMHO, but all the other lines of code can be fairly easily understood once you read the docs. partial: http://docs.python.org/2/library/functools.html count, imap, takewhile, chain.from_iterable: http://docs.python.org/2/library/itertools.html deque: http://docs.python.org/2/library/collections.html -- http://mail.python.org/mailman/listinfo/python-list
Re: A gnarly little python loop
In article , Peter Otten <__pete...@web.de> wrote: > deque( > imap( > process, > chain.from_iterable( > takewhile(bool, imap(partial(api.GetSearch, term), count(1), > maxlen=0) > > ;) If I wanted STL, I would still be writing C++ :-) -- http://mail.python.org/mailman/listinfo/python-list
Re: problem with module PyVisa
On 9 nov, 22:14, w...@mac.com wrote: > On Nov 9, 2012, at 3:43 PM, Jean Dubois wrote: > > > > > > > > > > > > > The error may be obvious but finding this file and how to install it > > is not unfortunately. > > It seems I have to install it from the National Instruments site but > > Debian Linux doesn't seem to be supported... > > and I doubt whether just copying this file will be sufficient to make > > PyVisa work. > > I wonder whether there might be another way to communicate via USB > > with a Keithley programmable power supply using Python. > > > best regards, > > Jean > > > -- > >http://mail.python.org/mailman/listinfo/python-list > > I've been using pyserial quite successfully to control a USB-to-serial > converter. > > That is, controlling a couple of RS232 serial devices via the USB port > through a KeySpan USB-to-Serial converter. > > Pyserial seems to make communication through the USB port quite transparent, > at least on my OS-X system. > > -Bill Well, in fact I do have some working scripts using pyserial to control an older (and more expensive) Keithley sourcemeter in combination with a USB-to-serial converter. But the trouble started when buying a cheaper and newer Keithley model which does not have rs232 but only USB. I noticed they have put an extra layer above USB called USBTMC which complicates things further. I followed the instructions at http://www.home.agilent.com/upload/cmc_upload/All/usbtmc.htm?&cc=BE&lc=dut#3.Copyright%20Notice|outline and compiled and loaded the usbtmc-driver but I still can't communicate with the Keithley, hence I started looking for an alternative using PyVisa...and now I'm stuck jean -- http://mail.python.org/mailman/listinfo/python-list
List comprehension for testing **params
Hi, I'm writing a small mail library for my own use, and at the time I'm testing parameters like this: class Mail(object): def __init__(self, smtp, login, **params) blah blah required = ['Subject', 'From', 'To', 'msg'] for i in required: if not i in params.keys(): print "Error, \'%s\' argument is missing" %i exit(1) ... md = {'Subject' : 'Test', 'From' :'Me', 'To' :['You', 'Them'], 'msg' :my.txt"} m = Mail('smtp.myprovider.com', ["mylogin", "mypasswd"], **md) I'd like to do something like that instead of the 'for' loop in __init__: assert[key for key in required if key in params.keys()] but it doesn't work. It doesn't find anythin wrong if remove, say msg, from **md. I thought it should because I believed that this list comprehension would check that every keyword in required would have a match in params.keys. Could you explain why it doesn't work and do you have any idea of how it could work ? Thanks in advance :) Cheers, Cantabile -- http://mail.python.org/mailman/listinfo/python-list
Re: Method default argument whose type is the class not yet defined
On Sun, 11 Nov 2012 14:21:19 +, Oscar Benjamin wrote: > On 11 November 2012 02:47, Chris Angelico wrote: >> On Sun, Nov 11, 2012 at 1:43 PM, Ian Kelly >> wrote: >>> On Sat, Nov 10, 2012 at 7:13 PM, Chris Angelico >>> wrote: I would not assume that. The origin is a point, just like any other. With a Line class, you could deem a zero-length line to be like a zero-element list, but Point(0,0) is more like the tuple (0,0) which is definitely True. Don't conflate the set of all tuples of arbitrary length with points, which have fixed length. Points are not *sequences* -- in Python, we treat tuples as sequences first and records second, because that is a useful thing to do. (But it is not the only useful thing to do: if we treated them as records first and sequences second, we might want to say that a tuple t was falsey if all the fields in t were falsey.) In the case of a Point class, a Point is definitely not a sequence. That we put the x-coordinate first and the y-coordinate second is a mere convention, like writing left to right. The mathematical properties of points do not depend on the x-coordinate coming first. Since points should not be treated as sequences, the requirement that non-empty sequences be treated as truthy is irrelevant. >>> It's more like the number 0 than the tuple (0,0). >>> >>> 0 is the origin on a 1-dimensional number line. (0,0) is the origin on >>> a 2-dimensional number plane. >>> >>> In fact, it might be pointed out that Point(0, 0) is a generalization >>> of 0+0j, which is equal to 0. >> >> Ah, good point. In any case, though, it'd be an utterly inconsequential >> bug. > > You were right the first time, Chris. A point that happens to coincide > with the arbitrarily chosen origin is no more truthy or falsey than any > other. A vector of length 0 on the other hand is a very different beast. Nonsense. The length and direction of a vector is relative to the origin. If the origin is arbitrary, as you claim, then so is the length of the vector. Just because we can perform vector transformations on the plane to move the origin to some point other that (0,0) doesn't make (0,0) an "arbitrarily chosen origin". It is no more arbitrary than 0 as the origin of the real number line. And yes, we can perform 1D vector transformations on the real number line too. Here's a version of range that sets the origin to 42, not 0: def myrange(start, end=None, step=1): if end is None: start = 42 return range(start, end, step) Nevertheless, there really is something special about the point 0 on the real number line, the point (0,0) on the complex number plane, the point (0,0,0) in the 3D space, (0,0,0,0) in 4D space, etc. It is not just an arbitrary convention that we set the origin to 0. In other words: to the extent that your arguments that zero-vectors are special are correct, the same applies to zero-points, since vectors are defined as a magnitude and direction *from the origin*. To put it yet another way: The complex number a+bj is equivalent to the 2D point (a, b) which is equivalent to the 2D vector [a, b]. If (0, 0) shouldn't be considered falsey, neither should [0, 0]. > The significance of zero in real algebra is not that it is the origin > but rather that it is the additive and multiplicative zero: > >a + 0 = a for any real number a >a * 0 = 0 for any real number a I'm not sure what you mean by "additive and multiplicative zero", you appear to be conflating two different properties here. 0 is the additive *identity*, but 1 is the multiplicative identity: a + 0 = a a * 1 = a for any real number a. If the RHS must be zero, then there is a unique multiplicative zero, but no unique additive zero: a * 0 = 0 for any real number a a + -a = 0 for any real number a > The same is true for a vector v0, of length 0: > >v + v0 = v for any vector v >a * v0 = v0 for any scalar a Well that's a bogus analogy. Since you're talking about the domain of vectors, the relevant identify for the second line should be: v * v0 = v0 for any vector v except that doesn't work, since vector algebra doesn't define a vector multiplication operator.[1] It does define multiplication between a vector and a scalar, which represents a scale transformation. > There is however no meaningful sense in which points (as opposed to > vectors) can be added to each other or multiplied by anything, so there > is no zero point. I think that the great mathematician Carl Gauss would have something to say about that. Points in the plane are equivalent to complex numbers, and you can certainly add and multiply complex numbers. Adding two points is equivalent to a translation; multiplication of a scalar with a point is equivalent to a scale transformation. Multiplying two points is equivalent to complex multiplication, which is a scale + a rotation. Oh look, that's exactly the same geometric interpretation as for vectors. H
Re: List comprehension for testing **params
On Sun, Nov 11, 2012 at 3:24 PM, Cantabile wrote: > I'd like to do something like that instead of the 'for' loop in __init__: > > assert[key for key in required if key in params.keys()] A list evaluates as true if it is not empty. As long as at least one of the required parameters is present, the list will not be empty and will evaluate as true, and the assertion will pass. Try this instead: assert all(key in params.keys() for key in required) By the way, using assertions for input checking is generally not considered good practice. As soon as Python is invoked with the -O option, your input testing is tossed out the window. Assertions are good to use for internal logic testing, to avoid unexpected state. For input checking, use an explicit if test and exception: if any(key not in params.keys() for key in required): raise ValueError("Missing required keyword argument") Additionally, if the arguments are required, then they probably have no business being wrapped up in **params in the first place. Why not just define your method like: def __init__(self, smtp, login, subject, from, to, msg): # ... And then Python will do all the work of requiring them to be present for you. -- http://mail.python.org/mailman/listinfo/python-list
Re: List comprehension for testing **params
> assert[key for key in required if key in params.keys()] ... > Could you explain why it doesn't work and do you have any idea of how it > could work ? Well, here, if any of the items are found, you get a list that is non-False'ish, so the assert passes. It sounds like you want all() (available as of 2.5) assert all(key in params for key in required) This is modulo any key normalization for "From" vs. "FROM" vs. "from", etc; but should be enough to pass your initial requirements. -tkc -- http://mail.python.org/mailman/listinfo/python-list
Re: List comprehension for testing **params
On Sun, 11 Nov 2012 23:24:14 +0100, Cantabile wrote: > Hi, > I'm writing a small mail library for my own use, and at the time I'm > testing parameters like this: > > class Mail(object): > def __init__(self, smtp, login, **params) > blah > blah > required = ['Subject', 'From', 'To', 'msg'] for i in required: > if not i in params.keys(): > print "Error, \'%s\' argument is missing" %i exit(1) > ... Eeek! Don't do that. Seriously dude, that is Evil. Why should a simple missing argument to a class *kill the entire application* How horrible would it be if you called "chr()" and instead of raising a TypeError, Python shut down? Don't do that. Raise a proper exception. Then you have the choice to either catch the exception and continue, or let it propagate as appropriate. But you shouldn't even be manually checking for required arguments. Just use real arguments: def __init__(self, smpt, login, Subject, From, To, msg, **params): blah See how easy it is? Problem solved. If you don't provide an argument, Python gives you an exception for free. Best of all, you can use inspection to see what arguments are required, and help(Mail) shows you what arguments are needed. You can still use **md as below, and Python will automatically do everything you're manually trying to do (and failing). Don't fight the language, even when you win, you lose. > md = {'Subject' : 'Test', 'From' :'Me', 'To' :['You', 'Them'], 'msg' > :my.txt"} > > m = Mail('smtp.myprovider.com', ["mylogin", "mypasswd"], **md) Conventionally, a tuple ("mylogin", "mypasswd") would express the intent better than a list. > I'd like to do something like that instead of the 'for' loop in > __init__: > > assert[key for key in required if key in params.keys()] > > but it doesn't work. It doesn't find anythin wrong if remove, say msg, > from **md. I thought it should because I believed that this list > comprehension would check that every keyword in required would have a > match in params.keys. No, you have three problems there. The first problem is that only the empty list is falsey: assert [] # this raises an exception assert ["Subject", "From"] # this doesn't, even though "To" and "msg" are missing. You could say: assert all([key in params for key in required]) but that leaves you with the next two problems: 2) Fixing the assert still leaves you with the wrong exception. You wouldn't raise a ZeroDivisionError, or a UnicodeDecodeError, or an IOError would you? No of course not. So why are you suggesting raising an AssertionError? That is completely inappropriate, the right exception to use is TypeError. Don't be lazy and treat assert as a quick and easy way to get exceptions for free. 3) Asserts are not guaranteed to run. Never, never, never use assert to test function arguments supplied by the caller, because you have no control over whether or not the asserts will even be called. The whole point of assertions is that the caller can disable them for speed. Asserts should be used for testing your code's internal logic, not user-provided arguments. Or for testing things which "can't possibly fail". But of course, since what can't go wrong does, you sometimes still want to test things. If you've ever written something like: if condition: process() else: # this cannot happen, but just in case! print "something unexpected went wrong!" that's a perfect candidate for an assertion: assert condition, "something unexpected went wrong!" process() -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: List comprehension for testing **params
On 11/11/2012 5:56 PM, Ian Kelly wrote: On Sun, Nov 11, 2012 at 3:24 PM, Cantabile wrote: I'd like to do something like that instead of the 'for' loop in __init__: assert[key for key in required if key in params.keys()] A list evaluates as true if it is not empty. As long as at least one of the required parameters is present, the list will not be empty and will evaluate as true, and the assertion will pass. Try this instead: assert all(key in params.keys() for key in required) By the way, using assertions for input checking is generally not considered good practice. As soon as Python is invoked with the -O option, your input testing is tossed out the window. Assertions are good to use for internal logic testing, to avoid unexpected state. For input checking, use an explicit if test and exception: if any(key not in params.keys() for key in required): raise ValueError("Missing required keyword argument") Additionally, if the arguments are required, then they probably have no business being wrapped up in **params in the first place. Why not just define your method like: def __init__(self, smtp, login, subject, from, to, msg): or if you want them to be identified by keyword only (since 7 positional args is a bit much) def __init__(self, smtp, login, *, subject, from, to, msg): (I forget when this feature was added) # ... And then Python will do all the work of requiring them to be present for you. -- Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
Re: List comprehension for testing **params
On Sun, 11 Nov 2012 18:37:05 -0500, Terry Reedy wrote: > or if you want them to be identified by keyword only (since 7 positional > args is a bit much) > > def __init__(self, smtp, login, *, subject, from, to, msg): > > (I forget when this feature was added) It's a Python 3 feature. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: List comprehension for testing **params
Thanks everyone for your answers. That's much clearer now. I see that I was somehow fighting python instead of using it. Lesson learned (for the time being at least) :) I'll probably get back with more questions... Cheers, Cantabile -- http://mail.python.org/mailman/listinfo/python-list
writing a csv file
Hello, I have the script below, which it extracts NOAA data from HTML and is planed writes it to a CSV file. Here is the script: import urllib2 from bs4 import BeautifulSoup from time import localtime, strftime import csv #This script is intended to retrive NOAA data and apend it to a csv file. # Wait 45 min #Need to work on this part... # Go into URL page = urllib2.urlopen("http://w1.weather.gov/obhistory/PAFA.html";) soup = BeautifulSoup(page) datemonth=strftime("%m", localtime()) dateday=strftime("%d", localtime()) with open("/home/eyalak/Documents/weather/weather.csv", "wb") as f: writer = csv.writer(f) table = soup.findAll("table")[3] #print table for tr in table.findAll("tr", valign="top"): a={x.string for x in tr.findAll('td')} print str(a) writer.writerows([a]) It did not work unless I changed the line a={x.string for x in tr.findAll('td')} to a=list({x.string for x in tr.findAll('td')}) But that disorganizes the data. How can I write the data to a csv file without altering the order prior to the list function. Thanks E -- http://mail.python.org/mailman/listinfo/python-list
Re: List comprehension for testing **params
On 11/11/12 17:18, Steven D'Aprano wrote: > but that leaves you with the next two problems: > > 2) Fixing the assert still leaves you with the wrong exception. You > wouldn't raise a ZeroDivisionError, or a UnicodeDecodeError, or an IOError > would you? No of course not. So why are you suggesting raising an > AssertionError? That is completely inappropriate, the right exception to > use is TypeError. Don't be lazy and treat assert as a quick and easy way > to get exceptions for free. I'd say that it depends on whether the dictionary/kwargs gets populated from user-supplied data (whether mail, a file, direct input, etc), or whether it's coder-supplied. I like to think of "assert" as a "hey, you bone-headed programmer, you did something that violated conditions for using this code properly!" and as such, entirely appropriate to use in the coder-supplied case. This rolls into... > 3) Asserts are not guaranteed to run. Never, never, never use assert to > test function arguments supplied by the caller, because you have no > control over whether or not the asserts will even be called. where, once the programmer is satisfied that the code runs, meeting all the appropriate tests/assertions, the assertions can then be turned off (if one really cares that much; can't say I've done it more than a couple times, mostly out of experimentation/testing to see if it made any grave difference in performance). I think you intend this in your > Or for testing things which "can't possibly fail". But of > course, since what can't go wrong does, you sometimes still want > to test things. -tkc -- http://mail.python.org/mailman/listinfo/python-list
Re: writing a csv file
On 12/11/2012 00:05, ejsa...@alaska.edu wrote: with open("/home/eyalak/Documents/weather/weather.csv", "wb") as f: writer = csv.writer(f) table = soup.findAll("table")[3] #print table for tr in table.findAll("tr", valign="top"): a={x.string for x in tr.findAll('td')} print str(a) writer.writerows([a]) It did not work unless I changed the line a={x.string for x in tr.findAll('td')} to a=list({x.string for x in tr.findAll('td')}) But that disorganizes the data. How can I write the data to a csv file without altering the order prior to the list function. Thanks E Change the line print str(a) to print type(a), a You'll see what the problem is and be able to fix it. -- Cheers. Mark Lawrence. -- http://mail.python.org/mailman/listinfo/python-list
Re: Method default argument whose type is the class not yet defined
On 11 November 2012 22:31, Steven D'Aprano wrote: > On Sun, 11 Nov 2012 14:21:19 +, Oscar Benjamin wrote: > >> On 11 November 2012 02:47, Chris Angelico wrote: >>> On Sun, Nov 11, 2012 at 1:43 PM, Ian Kelly >>> wrote: On Sat, Nov 10, 2012 at 7:13 PM, Chris Angelico wrote: > I would not assume that. The origin is a point, just like any other. > With a Line class, you could deem a zero-length line to be like a > zero-element list, but Point(0,0) is more like the tuple (0,0) which > is definitely True. It's more like the number 0 than the tuple (0,0). 0 is the origin on a 1-dimensional number line. (0,0) is the origin on a 2-dimensional number plane. In fact, it might be pointed out that Point(0, 0) is a generalization of 0+0j, which is equal to 0. >>> >>> Ah, good point. In any case, though, it'd be an utterly inconsequential >>> bug. >> >> You were right the first time, Chris. A point that happens to coincide >> with the arbitrarily chosen origin is no more truthy or falsey than any >> other. A vector of length 0 on the other hand is a very different beast. > > Nonsense. The length and direction of a vector is relative to the origin. > If the origin is arbitrary, as you claim, then so is the length of the > vector. Wrong on all counts. Neither the length not the direction os a vector are relative to any origin. When we choose to express a vector in Cartesian components our representation assumes an orientation for the axes of the coordinate system. Even in this sense, though, the origin itself does not affect the components of the vector. I have spent a fair few hours in the past few weeks persuading teenaged Engineering students to maintain a clear distinction between points, vectors and lines. One of the ways that I distinguish vectors from points is to say that a vector is like an arrow but its base has no particular position. A point on the other hand is quite simply a position. Given an origin (an arbitrarily chosen point) we can specify another point using a "position vector": a vector from the origin to the point in question. > Just because we can perform vector transformations on the plane to move > the origin to some point other that (0,0) doesn't make (0,0) an > "arbitrarily chosen origin". It is no more arbitrary than 0 as the origin > of the real number line. (0, 0) are the coordinates of the origin *relative to itself*. Had we chosen a different origin, the point that was previously called (0, 0) would now be called (a, b) for some other numbers a and b. > And yes, we can perform 1D vector transformations on the real number line > too. Here's a version of range that sets the origin to 42, not 0: > > def myrange(start, end=None, step=1): > if end is None: > start = 42 > return range(start, end, step) This is lost on me... > Nevertheless, there really is something special about the point 0 on the > real number line Agreed. > , the point (0,0) on the complex number plane, Also agreed. > the point > (0,0,0) in the 3D space, (0,0,0,0) in 4D space, etc. It is not just an > arbitrary convention that we set the origin to 0. Wrong. The point (0,0,0,...) in some ND space is an arbitrarily chosen position. By this I don't mean to say that the sequence of coordinates consisting of all zeros is arbitrary. The choice of the point *in the real/hypothetical space* that is designated by the sequence of zero coordinates is arbitrary. > In other words: to the extent that your arguments that zero-vectors are > special are correct, the same applies to zero-points, since vectors are > defined as a magnitude and direction *from the origin*. Plain wrong. Vectors are not defined *from any origin*. > To put it yet another way: > > The complex number a+bj is equivalent to the 2D point (a, b) which is > equivalent to the 2D vector [a, b]. If (0, 0) shouldn't be considered > falsey, neither should [0, 0]. a+bj is not equivalent to the 2D point (a, b). It is possible to define a mapping between complex numbers and a 2D space so that a+bj corresponds to the point (a, b) *under that map*. However there are an infinite number of such possible mappings between the two spaces including a+bj -> (a+1, b+1). >> The significance of zero in real algebra is not that it is the origin >> but rather that it is the additive and multiplicative zero: >> >>a + 0 = a for any real number a >>a * 0 = 0 for any real number a > > I'm not sure what you mean by "additive and multiplicative zero", you > appear to be conflating two different properties here. 0 is the additive > *identity*, but 1 is the multiplicative identity: I mean that it has the properties that zero has when used in addition and multiplication: http://en.wikipedia.org/wiki/0_%28number%29#Elementary_algebra > > a + 0 = a > a * 1 = a > for any real number a. No. I meant the two properties that I listed. > > If the RHS must be zero, then there is a unique multiplicative
Re: Method default argument whose type is the class not yet defined
On Nov 10, 11:33 am, Jennie wrote: > What is the best solution to solve the following problem in Python 3.3? > > import math > >>> class Point: > ... def __init__(self, x=0, y=0): > ... self.x = x > ... self.y = y > ... def __sub__(self, other): > ... return Point(self.x - other.x, self.y - other.y) > ... def distance(self, point=Point()): > ... """Return the distance from `point`.""" > ... return math.sqrt((self - point).x ** 2 + (self - point).y ** 2) Before you do anything else, introduce a Vector class into your app. The difference between two Points is not a Point; it's a Vector. Create a magnitude() method in your Vector class, then make your Point.distance return the results of Vector.magnitude(self - other). To define the distance of a point from the origin, don't make your distance() method have default arguments; instead, define another method called distance_from_origin(). -- http://mail.python.org/mailman/listinfo/python-list
Re: A gnarly little python loop
On 11Nov2012 11:16, Steve Howell wrote: | On Nov 11, 10:34 am, Peter Otten <__pete...@web.de> wrote: | > Steve Howell wrote: | > > On Nov 11, 1:09 am, Paul Rubin wrote: | > >> Cameron Simpson writes: | > >> > | I'd prefer the original code ten times over this inaccessible beast. | > >> > Me too. | > | > >> Me, I like the itertools version better. There's one chunk of data | > >> that goes through a succession of transforms each of which | > >> is very straightforward. | > | > > Thanks, Paul. | > | > > Even though I supplied the "inaccessible" itertools version, I can | > > understand why folks find it inaccessible. As I said to the OP, there | > > was nothing wrong with the original imperative approach; I was simply | > > providing an alternative. | > | > > It took me a while to appreciate itertools, but the metaphor that | > > resonates with me is a Unix pipeline. [...] | > Actually you supplied the "accessible" itertools version. For reference, | > here's the inaccessible version: [...] | I know Peter's version is tongue in cheek, but I do think that it has | a certain expressive power, and it highlights three mind-expanding | Python modules. | Here's a re-flattened take on Peter's version ("Flat is better than | nested." -- PEP 20): [...] Ok, who's going to quiz the OP on his/her uptake of these techniques... -- Cameron Simpson It's hard to make a man understand something when his livelihood depends on him not understanding it. - Upton Sinclair -- http://mail.python.org/mailman/listinfo/python-list
Re: Method default argument whose type is the class not yet defined
On Nov 11, 4:31 pm, Oscar Benjamin wrote: > On 11 November 2012 22:31, Steven D'Aprano > > Nonsense. The length and direction of a vector is relative to the origin. > > If the origin is arbitrary, as you claim, then so is the length of the > > vector. > > Wrong on all counts. Neither the length not the direction os a vector > are relative to any origin. When we choose to express a vector in > Cartesian components our representation assumes an orientation for the > axes of the coordinate system. Even in this sense, though, the origin > itself does not affect the components of the vector. > Thank you for pushing back on Steven's imprecise statement that the "direction of a vector is relative to the origin." You can't find an angle between two points. That's absurd. You need axes for context. > Vectors, points and complex numbers are not equivalent. There are > cases in which it is reasonable to think of them as equivalent for a > particular purpose. That does not diminish the fundamental differences > between them. > I looked to wikipedia for clarity, but the definition of a Euclidean vector is somewhat muddy: http://en.wikipedia.org/wiki/Euclidean_vector They say that the formal definition of a vector is a directed line segment. But then they define a "free vector" as an entity where only the magnitude and direction matter, not the initial point. As you say, it's not unreasonable to treat vectors, points, and complex numbers as equivalent in many circumstances. But, if you're gonna be pedantic, they really are different things. -- http://mail.python.org/mailman/listinfo/python-list
Re: Method default argument whose type is the class not yet defined
On 12/11/2012 00:31, Oscar Benjamin wrote: Plain wrong. Vectors are not defined *from any origin*. So when the Captain says "full speed ahead, steer 245 degrees", you haven't the faintest idea where you're going, because you have no origin? -- Cheers. Mark Lawrence. -- http://mail.python.org/mailman/listinfo/python-list
Re: Method default argument whose type is the class not yet defined
On 12 November 2012 01:10, Mark Lawrence wrote: > On 12/11/2012 00:31, Oscar Benjamin wrote: >> >> >> Plain wrong. Vectors are not defined *from any origin*. >> > > So when the Captain says "full speed ahead, steer 245 degrees", you haven't > the faintest idea where you're going, because you have no origin? As Steve has just explained, the origin has nothing to do with the orientation of the coordinate system. But then I'm assuming you meant that 245 degrees was a bearing relative to North. Was it supposed to be relative to my current angle? Truthfully I wouldn't know what to do without asking the captain a couple more questions. Oscar -- http://mail.python.org/mailman/listinfo/python-list
Re: Method default argument whose type is the class not yet defined
In article , Mark Lawrence wrote: > On 12/11/2012 00:31, Oscar Benjamin wrote: > > > > Plain wrong. Vectors are not defined *from any origin*. > > > > So when the Captain says "full speed ahead, steer 245 degrees", you > haven't the faintest idea where you're going, because you have no origin? Vectors have a length ("full speed ahead") and a direction ("245 degrees"). What they don't have is a fixed location in space. The captain didn't say, "Full speed ahead, steer 245 degrees, from 45.0N, 20.0W". In other words, you are correct. The order, "full speed ahead, steer 245 degrees", doesn't give you the faintest idea of where you're going. If you were the helmsman, after you executed that order, without any additional information (such as your current location), you would have no idea what piece of land you will hit, or when you will hit it, if you maintain your current course and speed. -- http://mail.python.org/mailman/listinfo/python-list
Re: Method default argument whose type is the class not yet defined
On 12/11/2012 01:18, Oscar Benjamin wrote: On 12 November 2012 01:10, Mark Lawrence wrote: On 12/11/2012 00:31, Oscar Benjamin wrote: Plain wrong. Vectors are not defined *from any origin*. So when the Captain says "full speed ahead, steer 245 degrees", you haven't the faintest idea where you're going, because you have no origin? As Steve has just explained, the origin has nothing to do with the orientation of the coordinate system. But then I'm assuming you meant that 245 degrees was a bearing relative to North. Was it supposed to be relative to my current angle? Truthfully I wouldn't know what to do without asking the captain a couple more questions. Oscar The only good acedemic is a dead acedemic? -- Cheers. Mark Lawrence. -- http://mail.python.org/mailman/listinfo/python-list
Re: Method default argument whose type is the class not yet defined
On 12/11/2012 01:15, Roy Smith wrote: In article , Mark Lawrence wrote: On 12/11/2012 00:31, Oscar Benjamin wrote: Plain wrong. Vectors are not defined *from any origin*. So when the Captain says "full speed ahead, steer 245 degrees", you haven't the faintest idea where you're going, because you have no origin? Vectors have a length ("full speed ahead") and a direction ("245 degrees"). What they don't have is a fixed location in space. The captain didn't say, "Full speed ahead, steer 245 degrees, from 45.0N, 20.0W". In other words, you are correct. The order, "full speed ahead, steer 245 degrees", doesn't give you the faintest idea of where you're going. If you were the helmsman, after you executed that order, without any additional information (such as your current location), you would have no idea what piece of land you will hit, or when you will hit it, if you maintain your current course and speed. Thank you for your explanation. -- Cheers. Mark Lawrence. -- http://mail.python.org/mailman/listinfo/python-list
Re: Method default argument whose type is the class not yet defined
In article , Oscar Benjamin wrote: > But then I'm assuming you meant that 245 degrees was a bearing > relative to North. Was it supposed to be relative to my current angle? > Truthfully I wouldn't know what to do without asking the captain a > couple more questions. Granted, this requires some domain-specific knowledge, but an order to "steer 245 degrees" means relative to north (and, technically, it's a heading, not a bearing, but that's another discussion). If the captain wanted you to change you heading relative to your current heading, he would say something like, "turn left 10 degrees" (that may not be strictly the correct wording). -- http://mail.python.org/mailman/listinfo/python-list
Re: A gnarly little python loop
On Nov 11, 4:44 pm, Cameron Simpson wrote: > On 11Nov2012 11:16, Steve Howell wrote: > | On Nov 11, 10:34 am, Peter Otten <__pete...@web.de> wrote: > | > Steve Howell wrote: > | > > On Nov 11, 1:09 am, Paul Rubin wrote: > | > >> Cameron Simpson writes: > | > >> > | I'd prefer the original code ten times over this inaccessible > beast. > | > >> > Me too. > | > > | > >> Me, I like the itertools version better. There's one chunk of data > | > >> that goes through a succession of transforms each of which > | > >> is very straightforward. > | > > | > > Thanks, Paul. > | > > | > > Even though I supplied the "inaccessible" itertools version, I can > | > > understand why folks find it inaccessible. As I said to the OP, there > | > > was nothing wrong with the original imperative approach; I was simply > | > > providing an alternative. > | > > | > > It took me a while to appreciate itertools, but the metaphor that > | > > resonates with me is a Unix pipeline. > [...] > | > Actually you supplied the "accessible" itertools version. For reference, > | > here's the inaccessible version: > [...] > | I know Peter's version is tongue in cheek, but I do think that it has > | a certain expressive power, and it highlights three mind-expanding > | Python modules. > | Here's a re-flattened take on Peter's version ("Flat is better than > | nested." -- PEP 20): > [...] > > Ok, who's going to quiz the OP on his/her uptake of these techniques... Cameron, with all due respect, I think you're missing the point. Roy posted this code: page = 1 while 1: r = api.GetSearch(term="foo", page=page) if not r: break for tweet in r: process(tweet) page += 1 In his own words, he described the loop as "gnarly" and the overall code as "fidgety." One way to eliminate the "while", the "if", and the "break" statements is to use higher level constructs that are shipped with all modern versions of Python, and which are well documented and well tested (and fast, I might add): search = partial(api.GetSearch, "foo") paged_tweets = imap(search, count(1)) paged_tweets = takewhile(bool, paged_tweets) tweets = chain.from_iterable(paged_tweets) for tweet in tweets: process(tweet) The moral of the story is that you can avoid brittle loops by relying on a well-tested library to work at a higher level of abstraction. For this particular use case, the imperative version is fine, but for more complex use cases, the loops are only gonna get more gnarly and fidgety. -- http://mail.python.org/mailman/listinfo/python-list
Re: Method default argument whose type is the class not yet defined
On 12 November 2012 01:29, Mark Lawrence wrote: > On 12/11/2012 01:18, Oscar Benjamin wrote: >> >> On 12 November 2012 01:10, Mark Lawrence wrote: >>> >>> On 12/11/2012 00:31, Oscar Benjamin wrote: Plain wrong. Vectors are not defined *from any origin*. >>> >>> So when the Captain says "full speed ahead, steer 245 degrees", you >>> haven't >>> the faintest idea where you're going, because you have no origin? >> >> >> As Steve has just explained, the origin has nothing to do with the >> orientation of the coordinate system. >> >> But then I'm assuming you meant that 245 degrees was a bearing >> relative to North. Was it supposed to be relative to my current angle? >> Truthfully I wouldn't know what to do without asking the captain a >> couple more questions. > > The only good acedemic is a dead acedemic? Is that what happens when people ask questions on your ship: "it's the plank for him with the questions-askin'!" I'm glad you're not my captain. Oscar -- http://mail.python.org/mailman/listinfo/python-list
Re: Method default argument whose type is the class not yet defined
On Mon, 12 Nov 2012 00:31:53 +, Oscar Benjamin wrote: [...] >>> You were right the first time, Chris. A point that happens to coincide >>> with the arbitrarily chosen origin is no more truthy or falsey than >>> any other. A vector of length 0 on the other hand is a very different >>> beast. >> >> Nonsense. The length and direction of a vector is relative to the >> origin. If the origin is arbitrary, as you claim, then so is the length >> of the vector. > > Wrong on all counts. Neither the length not the direction os a vector > are relative to any origin. When we choose to express a vector in > Cartesian components our representation assumes an orientation for the > axes of the coordinate system. Even in this sense, though, the origin > itself does not affect the components of the vector. Draw a set of axes and mark the vector [1, 1]. Here's a crappy ASCII art diagram, with X marking the head of the vector and a line drawn from the origin to the head. | | X | / | / |/ +-- Now draw a second set of axes with the origin set at the head of that vector. For reference, I leave the previous axis in place. As before, X represents the head of the vector. | | X- | | | | | | +---|-- Note that the "body" of the vector -- the line from the origin to the head -- is gone. That's because the vector [1, 1] is transformed to the vector [0, 0] under a translation of one unit in both the X and Y directions. The magnitude of the vector under one coordinate system is 1, under the second it is 0. In a nutshell, you can't talk about either *distance* (magnitude) or *direction* without an answer to "distance from where? direction relative to what?". > I have spent a fair few hours in the past few weeks persuading teenaged > Engineering students to maintain a clear distinction between points, > vectors and lines. One of the ways that I distinguish vectors from > points is to say that a vector is like an arrow but its base has no > particular position. A point on the other hand is quite simply a > position. Given an origin (an arbitrarily chosen point) we can specify > another point using a "position vector": a vector from the origin to the > point in question. Just because you have spent a lot of time and effort giving people advice doesn't make it *good* advice. [...] > Wrong. The point (0,0,0,...) in some ND space is an arbitrarily chosen > position. By this I don't mean to say that the sequence of coordinates > consisting of all zeros is arbitrary. The choice of the point *in the > real/hypothetical space* that is designated by the sequence of zero > coordinates is arbitrary. So what? All you are saying is that there is more than one coordinate system, and we can choose the one we like for any problem. Of course we can, and that's a good thing. >>> The significance of zero in real algebra is not that it is the origin >>> but rather that it is the additive and multiplicative zero: >>> >>>a + 0 = a for any real number a >>>a * 0 = 0 for any real number a >> >> I'm not sure what you mean by "additive and multiplicative zero", you >> appear to be conflating two different properties here. 0 is the >> additive *identity*, but 1 is the multiplicative identity: > > I mean that it has the properties that zero has when used in addition > and multiplication: > http://en.wikipedia.org/wiki/0_%28number%29#Elementary_algebra I see no reference to "additive and multiplicative zero" there. Did you make up that terminology? The *identity* element is a common mathematical term, but 1 is the multiplicative identity element. What you are describing is generally known as the "absorbing element" over multiplication: if X*a = X for any a, then X is an absorbing element under multiplication. http://en.wikipedia.org/wiki/Absorbing_element And by the way, the vector [0, 0] (generalised to however many dimensions you need) is not necessarily the only null (zero) vector. Some vector spaces have many null vectors with non-zero components. http://en.wikipedia.org/wiki/Zero_vector but I digress. The exact terminology doesn't really change anything, since everything you say about vector [0,0] applies equally to the point (0,0) in the Cartesian plane. [...] >>> There is however no meaningful sense in which points (as opposed to >>> vectors) can be added to each other or multiplied by anything, so >>> there is no zero point. >> >> I think that the great mathematician Carl Gauss would have something to >> say about that. > > Is the text below a quote? No. >> Points in the plane are equivalent to complex numbers, and you can >> certainly add and multiply complex numbers. Adding two points is >> equivalent to a translation; multiplication of a scalar with a point is >> equivalent to a scale transformation. Multiplying two points is >> equivalent to complex multiplication, which is a scale + a rotation. > > The last point is bizarre. Complex multiplication makes no sense w
Re: A gnarly little python loop
On Nov 11, 3:58 am, Roy Smith wrote: > I'm trying to pull down tweets with one of the many twitter APIs. The > particular one I'm using (python-twitter), has a call: > > data = api.GetSearch(term="foo", page=page) > > The way it works, you start with page=1. It returns a list of tweets. > If the list is empty, there are no more tweets. If the list is not > empty, you can try to get more tweets by asking for page=2, page=3, etc. > I've got: > > page = 1 > while 1: > r = api.GetSearch(term="foo", page=page) > if not r: > break > for tweet in r: > process(tweet) > page += 1 > > It works, but it seems excessively fidgety. Is there some cleaner way > to refactor this? This is a classic problem -- structure clash of parallel loops -- nd Steve Howell has given the classic solution using the fact that generators in python simulate/implement lazy lists. As David Beazley http://www.dabeaz.com/coroutines/ explains, coroutines are more general than generators and you can use those if you prefer. The classic problem used to be stated like this: There is an input in cards of 80 columns. It needs to be copied onto printer of 132 columns. The structure clash arises because after reading 80 chars a new card has to be read; after printing 132 chars a linefeed has to be given. To pythonize the problem, lets replace the 80,132 by 3,4, ie take the char-square abc def ghi and produce abcd efgh i The important difference (explained nicely by Beazley) is that in generators the for-loop pulls the generators, in coroutines, the 'generator' pushes the consuming coroutines. --- from __future__ import print_function s= ["abc", "def", "ghi"] # Coroutine-infrastructure from pep 342 def consumer(func): def wrapper(*args,**kw): gen = func(*args, **kw) gen.next() return gen return wrapper @consumer def endStage(): while True: for i in range(0,4): print((yield), sep='', end='') print("\n", sep='', end='') def genStage(s, target): for line in s: for i in range(0,3): target.send(line[i]) if __name__ == '__main__': genStage(s, endStage()) -- http://mail.python.org/mailman/listinfo/python-list
Re: List comprehension for testing **params
On Sun, 11 Nov 2012 18:21:32 -0600, Tim Chase wrote: > On 11/11/12 17:18, Steven D'Aprano wrote: >> but that leaves you with the next two problems: >> >> 2) Fixing the assert still leaves you with the wrong exception. You >> wouldn't raise a ZeroDivisionError, or a UnicodeDecodeError, or an >> IOError would you? No of course not. So why are you suggesting raising >> an AssertionError? That is completely inappropriate, the right >> exception to use is TypeError. Don't be lazy and treat assert as a >> quick and easy way to get exceptions for free. > > I'd say that it depends on whether the dictionary/kwargs gets populated > from user-supplied data (whether mail, a file, direct input, etc), or > whether it's coder-supplied. No, it doesn't matter if it is end-user supplied or coder-supplied. As usual, look at the standard library and Python builtins for best practices: py> len(42) # do we get an AssertionError? Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() > I like to think of "assert" as a "hey, you bone-headed programmer, you > did something that violated conditions for using this code properly!" You mean like passing a list to ord()? Or trying to add a number and a string? Raise the appropriate exception for the error: TypeError for type errors and missing function parameters, ValueErrors for objects of the right type but a bad argument, etc. Assertion errors are for asserting facts about internal program logic. "I assert that such-and-such is a fact", rather than "I require that such-and-such is a fact". For example, this might be a reasonable (although trivial) use of assert: def spam(n): if isinstance(n, int) and n > 0: result = ' '.join(["spam"]*n) assert result, "expected non-empty string but got empty" return result else: raise SpamError("No spam for you!!!") This gives a measure of protection against logic errors such as writing n >= 0. The presence of the assert is partly documentation and partly error checking, but the important thing is that it checks things which depend on the internal logic of the code itself, not on the input to the code. Given that you have already explicitly tested that n > 0, then the logical consequence is that "spam"*n will be non-empty. Hence an assertion "I assert that the string is not empty", rather than an overt test "Is the string empty?" Now, I accept that sometimes it is hard to draw a line between "internal program logic" and external input. E.g. if one function generates a value x, then calls another function with x as argument, the state of x is an internal detail to the first function and an external input to the other function. The rules I use are: * If the argument is a public parameter to a public function, then you must not use assert to validate it; * If the argument is a private parameter, or if the function is a private function, then you may use assert to validate it (but probably shouldn't); * You can use assert to check conditions of function internal variables (locals that you control); * Once you cross the boundary to another function, your objects should be treated as external again. E.g. I might have: def foo(a, b): # foo, a and b are public, so don't use assert if not (isinstance(a, int) and isinstance(b, int)): raise TypeError x = abs(a) + abs(b) # x is purely internal, so okay to assert assert x >= 0, "Hey McFly, you screwed up!" return bar(x) def bar(x): if x <= 0: raise ValueError("expected positive x") ... This now guards against something other than foo calling bar. -- Steven -- http://mail.python.org/mailman/listinfo/python-list