Re: [Tutor] encoding question
On 2014-01-04 21:20, Danny Yoo wrote: Oh! That's unfortunate! That looks like a bug on the hostip.info side. Check with them about it. I can't get the source code to whatever is implementing the JSON response, so I can not say why the city is not being properly included there. [... XML rant about to start. I am not disinterested, so my apologies in advance.] ... In that case... I suppose trying the XML output is a possible approach. Well, I've tried the xml approach which seems promising but still I get an encoding related error. Is there a bug in the xml.etree module (not very likely, me thinks) or am I doing something wrong? There's no denying that the whole encoding issue is still not completely clear to me in spite of having devoted a lot of time to trying to grasp all that's involved. Here's what I've got: alex@x301:~/Python/Parse$ cat ip_xml.py #!/usr/bin/env python # -*- coding : utf -8 -*- # file: 'ip_xml.py' import urllib2 import xml.etree.ElementTree as ET url_format_str = \ u'http://api.hostip.info/?ip=%s&position=true' def ip_info(ip_address): response = urllib2.urlopen(url_format_str %\ (ip_address, )) encoding = response.headers.getparam('charset') print "'encoding' is '%s'." % (encoding, ) info = unicode(response.read().decode(encoding)) n = info.find('\n') print "location of first newline is %s." % (n, ) xml = info[n+1:] print "'xml' is '%s'." % (xml, ) tree = ET.fromstring(xml) root = tree.getroot() # Here's where it blows up!!! print "'root' is '%s', with the following children:" % (root, ) for child in root: print child.tag, child.attrib print "END of CHILDREN" return info if __name__ == "__main__": info = ip_info("201.234.178.62") alex@x301:~/Python/Parse$ ./ip_xml.py 'encoding' is 'iso-8859-1'. location of first newline is 44. 'xml' is 'xmlns:gml="http://www.opengis.net/gml"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xsi:noNamespaceSchemaLocation="http://www.hostip.info/api/hostip-1.0.1.xsd";> This is the Hostip Lookup Service hostip inapplicable 201.234.178.62 Bogotá COLOMBIA CO http://www.opengis.net/gml/srs/epsg.xml#4326";> -75.2833,10.4 '. Traceback (most recent call last): File "./ip_xml.py", line 33, in info = ip_info("201.234.178.62") File "./ip_xml.py", line 23, in ip_info tree = ET.fromstring(xml) File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1301, in XML parser.feed(text) File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1641, in feed self._parser.Parse(data, 0) UnicodeEncodeError: 'ascii' codec can't encode character u'\xe1' in position 456: ordinal not in range(128) ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] More or less final Chutes & Ladders
On 05/01/2014 07:09, Keith Winston wrote: Thanks all, interesting. I'll play more with tuples, I haven't knowingly used them at all... Keith Homework for you :) Write a line of code that creates a list of say 3 or 4 integers, then write a line that creates a tuple with the same integers. Use the dis module to compare the byte code that the two lines of code produce. The difference is interesting. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] More or less final Chutes & Ladders
Thanks all, interesting. I'll play more with tuples, I haven't knowingly used them at all... Keith ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] encoding question
On 2014-01-04 21:20, Danny Yoo wrote: Oh! That's unfortunate! That looks like a bug on the hostip.info side. Check with them about it. I can't get the source code to whatever is implementing the JSON response, so I can not say why the city is not being properly included there. [... XML rant about to start. I am not disinterested, so my apologies in advance.] ... In that case... I suppose trying the XML output is a possible approach. But I truly dislike XML for being implemented in ways that are usually not fun to navigate: either the APIs or the encoded data are usually convoluted enough to make it a chore rather than a pleasure. The beginning does look similar: ## import xml.etree.ElementTree as ET import urllib response = urllib.urlopen("http://api.hostip.info?ip=201.234.178.62&position=true";) tree = ET.parse(response) tree ## Up to this point, not so bad. But this is where it starts to look silly: ## tree.find('{http://www.opengis.net/gml}featureMember/Hostip/ip').text '201.234.178.62' tree.find('{http://www.opengis.net/gml}featureMember/Hostip/{http://www.opengis.net/gml}name').text u'Bogot\xe1' ## where we need to deal with XML namespaces, an extra complexity for a benefit that I have never bought into. More than that, usually the XML I run into in practice isn't even properly structured, as is the case with the lat-long value in the XML output here: ## tree.find('.//{http://www.opengis.net/gml}coordinates').text '-75.2833,10.4' ## which is truly silly. Why is the latitude and longitude not two separate, structured values? What is this XML buying us here, really then? I'm convinced that all the extraneous structure and complexity in XML causes the people who work with it to stop caring, the result being something that isn't for the benefit of either humans nor computer programs. Hence, that's why I prefer JSON: JSON export is usually a lot more sensible, for reasons that I can speculate on, but I probably should stop this rant. :P Not a rant at all. As it turns out, one of the other things that have interested me of late is docbook, an xml dialect (I think this is the correct way to express it.) I've found it very useful and so do not share your distaste for xml although one can't disagree with the points you've made with regard to xml as a solution to the problem under discussion. I've not played with the python xml interfaces before so this will be a good project for me. Thanks. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] encoding question
> then? I'm convinced that all the extraneous structure and complexity > in XML causes the people who work with it to stop caring, the result > being something that isn't for the benefit of either humans nor > computer programs. ... I'm sorry. Sometimes I get grumpy when I haven't had a Snickers. I should not have said the above here. It isn't factual, and worse, it insinuates an uncharitable intent to people who I do not know. There's enough insinuation and insults out there in the world already: I should not be contributing to those things. For that, I apologize. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python, speed, game programming
Hi Danny, no, I don't think there's any disk access, and the memory of the two machines is rather different: one is 4 Gb or so, the other 9 changing to 12 any day... but I think I haven't been rigorous enough to justify a great deal more attention here. I am convinced that I should just keep developing my next project, and my programming skills, and worry about speed issues as I hit them. I was overreaching, or anticipating or something... On Sat, Jan 4, 2014 at 10:30 PM, Danny Yoo wrote: > There's an assumption in the question here that all programs are CPU bound. > > I actually do not think so. From prior discussion about what the > program is doing, I got the impression that it was trying to hold > gigabytes of data in RAM. Isn't that still true? If so, then I would > be very surprised if the program were not thrashing virtual memory. > Under such conditions, give up on any assumptions about program speed > being related to CPU speed. It's hitting disk hard, and that's a Game > Over. Under heavy virtual memory swapping conditions, it doesn't > matter how fast your CPU is: the time that your program is taking is > due to the physical act of moving spindles and spinning disks of metal > around. > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- Keith ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] encoding question
Oh! That's unfortunate! That looks like a bug on the hostip.info side. Check with them about it. I can't get the source code to whatever is implementing the JSON response, so I can not say why the city is not being properly included there. [... XML rant about to start. I am not disinterested, so my apologies in advance.] ... In that case... I suppose trying the XML output is a possible approach. But I truly dislike XML for being implemented in ways that are usually not fun to navigate: either the APIs or the encoded data are usually convoluted enough to make it a chore rather than a pleasure. The beginning does look similar: ## >>> import xml.etree.ElementTree as ET >>> import urllib >>> response = >>> urllib.urlopen("http://api.hostip.info?ip=201.234.178.62&position=true";) >>> tree = ET.parse(response) >>> tree ## Up to this point, not so bad. But this is where it starts to look silly: ## >>> tree.find('{http://www.opengis.net/gml}featureMember/Hostip/ip').text '201.234.178.62' >>> tree.find('{http://www.opengis.net/gml}featureMember/Hostip/{http://www.opengis.net/gml}name').text u'Bogot\xe1' ## where we need to deal with XML namespaces, an extra complexity for a benefit that I have never bought into. More than that, usually the XML I run into in practice isn't even properly structured, as is the case with the lat-long value in the XML output here: ## >>> tree.find('.//{http://www.opengis.net/gml}coordinates').text '-75.2833,10.4' ## which is truly silly. Why is the latitude and longitude not two separate, structured values? What is this XML buying us here, really then? I'm convinced that all the extraneous structure and complexity in XML causes the people who work with it to stop caring, the result being something that isn't for the benefit of either humans nor computer programs. Hence, that's why I prefer JSON: JSON export is usually a lot more sensible, for reasons that I can speculate on, but I probably should stop this rant. :P ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] encoding question
On Sat, Jan 4, 2014 at 11:16 PM, Alex Kleider wrote: > {u'city': None, u'ip': u'201.234.178.62', u'lat': u'10.4', u'country_code': > u'CO', u'country_name': u'COLOMBIA', u'lng': u'-75.2833'} > > If I use my own IP the city comes in fine so there must still be some > problem with the encoding. Report a bug in their JSON API. It's returning b'"city":null'. I see the same problem for www.msj.go.cr in San José, Costa Rica. It's probably broken for all non-ASCII byte strings. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] encoding question
On 2014-01-04 18:44, Danny Yoo wrote: Hi Alex, According to: http://www.hostip.info/use.html there is a JSON-based interface. I'd recommend using that one! JSON is a format that's easy for machines to decode. The format you're parsing is primarily for humans, and who knows if that will change in the future to make it easier to read? Not only is JSON probably more reliable to parse, but the code itself should be fairly straightforward. For example: # ## In Python 2.7 ## import json import urllib response = urllib.urlopen('http://api.hostip.info/get_json.php') info = json.load(response) info {u'country_name': u'UNITED STATES', u'city': u'Mountain View, CA', u'country_code': u'US', u'ip': u'216.239.45.81'} # This strikes me as being the most elegant solution to date, and I thank you for it! The problem is that the city name doesn't come in: alex@x301:~/Python/Parse$ cat tutor.py #!/usr/bin/env python # -*- coding : utf -8 -*- # file: 'tutor.py' """ Put your docstring here. """ print "Running 'tutor.py'..." import json import urllib response = urllib.urlopen\ ('http://api.hostip.info/get_json.php?ip=201.234.178.62&position=true') info = json.load(response) print info alex@x301:~/Python/Parse$ ./tutor.py Running 'tutor.py'... {u'city': None, u'ip': u'201.234.178.62', u'lat': u'10.4', u'country_code': u'CO', u'country_name': u'COLOMBIA', u'lng': u'-75.2833'} If I use my own IP the city comes in fine so there must still be some problem with the encoding. should I be using encoding = response.headers.getparam('charset') in there somewhere? Any ideas? ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python, speed, game programming
There's an assumption in the question here that all programs are CPU bound. I actually do not think so. From prior discussion about what the program is doing, I got the impression that it was trying to hold gigabytes of data in RAM. Isn't that still true? If so, then I would be very surprised if the program were not thrashing virtual memory. Under such conditions, give up on any assumptions about program speed being related to CPU speed. It's hitting disk hard, and that's a Game Over. Under heavy virtual memory swapping conditions, it doesn't matter how fast your CPU is: the time that your program is taking is due to the physical act of moving spindles and spinning disks of metal around. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] code smells: Object-orientation Abusers: switch statements
Compare: ### class Dog(object): pass class Cat(object): pass class Cow(object): pass def sayHi(animal): if isinstance(animal, Dog): print("Woof") elif isinstance(animal, Cat): print("Meow") elif isinstance(animal, Cow): print("Moo") else: raise ValueError("animal doesn't know how to greet") sayHi(Dog()) sayHi(Cat()) sayHi(Cow()) ### where there are explicit type tests. The decision-making here, the flow of control, is explicit in the structure of the sayHi() function. Now compare that versus the following: ### class Dog(object): def getGreeting(self): return "Woof" class Cat(object): def getGreeting(self): return "Meow" class Cow(object): def getGreeting(self): return "Moo" def sayHi(animal): print(animal.getGreeting()) sayHi(Dog()) sayHi(Cat()) sayHi(Cow()) ### You should see similar behavior. But the control flow here is more implicit: it's not all apparent from the structure of sayHi(): sayHi() looks like straight-line code. The decision-making hides in the type of the animal. The flow of control jumps from sayHi() to the getGreeting() of the particular animal, and then finally back to sayHi() to do the printing of the greeting. One of the values of this latter approach is that it's easier to add more animals without having to rewrite sayHi(). For example, we can introduce a Crow: class Crow(object): def getGreeting(self): return "Kaaa" sayHi(Crow()) and sayHi() can deal with it just fine. In the first approach with the explicit type tests, we'd have to modify sayHi() to let it handle Crows. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] encoding question
On Sat, 04 Jan 2014 18:31:13 -0800, Alex Kleider wrote: exactly what the line # -*- coding : utf -8 -*- really indicates or more importantly, is it true, since I am using vim and I assume things are encoded as ascii? I don't know vim specifically, but I'm 99% sure it will let you specify the encoding,. Certainly emacs does, so I'd not expect vim to fall behind on such a fundamental point. Anyway it's also likely that it defaults to utf for new files. Anyway your job is to make sure that the encoding line matches what the editor is using. Emacs also looks in the first few lines for that same encoding line, so if you format it carefully, it'll just work. Easy to test anyway for yourself. Just paste some international characters into a literal string. -- DaveA ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python 3.3 split method confusion
One of the common cases for split() is to break a line into a list of words, for example. # >>> 'hello this is a test'.split() ['hello', 'this', 'is', 'a', 'test'] # The Standard Library can not do everything that we can conceive of as being useful, because that set is fairly large. If the Standard Library doesn't do it, we'll probably need to do it ourselves, or find someone who has done it already. ## >>> def mysplit(s, delim): ... start = 0 ... while True: ... index = s.find(delim, start) ... if index != -1: ... yield s[start:index] ... yield delim ... start = index + len(delim) ... else: ... yield s[start:] ... return ... >>> list(mysplit("this,is,a,test", ",")) ['this', ',', 'is', ',', 'a', ',', 'test'] ## ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] encoding question
You were asking earlier about the line: # -*- coding : utf -8 -*- See PEP 263: http://www.python.org/dev/peps/pep-0263/ http://docs.python.org/release/2.3/whatsnew/section-encodings.html It's a line that tells Python how to interpret the bytes of your source program. It allows us to write unicode literal strings embedded directly in the program source itself. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] encoding question
Hi Alex, According to: http://www.hostip.info/use.html there is a JSON-based interface. I'd recommend using that one! JSON is a format that's easy for machines to decode. The format you're parsing is primarily for humans, and who knows if that will change in the future to make it easier to read? Not only is JSON probably more reliable to parse, but the code itself should be fairly straightforward. For example: # ## In Python 2.7 ## >>> import json >>> import urllib >>> response = urllib.urlopen('http://api.hostip.info/get_json.php') >>> info = json.load(response) >>> info {u'country_name': u'UNITED STATES', u'city': u'Mountain View, CA', u'country_code': u'US', u'ip': u'216.239.45.81'} # Best of wishes! ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] encoding question
A heartfelt thank you to those of you that have given me much to ponder with your helpful responses. In the mean time I've rewritten my procedure using a different approach all together. I'd be interested in knowing if you think it's worth keeping or do you suggest I use your revisions to my original hack? I've been maintaining both a Python3 and a Python2.7 version. The latter has actually opened my eyes to more complexities. Specifically the need to use unicode strings rather than Python2.7's default ascii. Here it is: alex@x301:~/Python/Parse$ cat ip_info.py #!/usr/bin/env python # -*- coding : utf -8 -*- import re import urllib2 url_format_str = \ u'http://api.hostip.info/get_html.php?ip=%s&position=true' info_exp = r""" Country:[ ](?P.*) [\n] City:[ ](?P.*) [\n] [\n] Latitude:[ ](?P.*) [\n] Longitude:[ ](?P.*) [\n] IP:[ ](?P.*) """ info_pattern = re.compile(info_exp, re.VERBOSE).search def ip_info(ip_address): """ Returns a dictionary keyed by Country, City, Lat, Long and IP. Depends on http://api.hostip.info (which returns the following: 'Country: UNITED STATES (US)\nCity: Santa Rosa, CA\n\nLatitude: 38.4486\nLongitude: -122.701\nIP: 76.191.204.54\n'.) THIS COULD BREAK IF THE WEB SITE GOES AWAY!!! """ response = urllib2.urlopen(url_format_str %\ (ip_address, )) encoding = response.headers.getparam('charset') info = info_pattern(response.read().decode(encoding)) return {"Country" : unicode(info.group("country")), "City" : unicode(info.group("city")), "Lat" : unicode(info.group("lat")), "Lon" : unicode(info.group("lon")), "IP" : unicode(info.group("ip"))} if __name__ == "__main__": print """IP address is %(IP)s: Country: %(Country)s; City: %(City)s. Lat/Long: %(Lat)s/%(Lon)s""" % ip_info("201.234.178.62") Apart from soliciting your general comments, I'm also interested to know exactly what the line # -*- coding : utf -8 -*- really indicates or more importantly, is it true, since I am using vim and I assume things are encoded as ascii? I've discovered that with Ubuntu it's very easy to switch from English (US) to English (US, international with dead keys) with just two clicks so thanks for that tip as well. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] encoding question
On Sat, Jan 04, 2014 at 04:15:30PM -0800, Alex Kleider wrote: > >py> 'Bogotá'.encode('utf-8') > > I'm interested in knowing how you were able to enter the above line > (assuming you have a key board similar to mine.) I'm running Linux, and I use the KDE or Gnome character selector, depending on which computer I'm using. They give you a graphical window showing a screenful of characters at a time, depending on which application I'm using you can search for characters by name or property, then copy them into the clipboard to paste them into another application. I can also use the "compose" key. My keyboard doesn't have an actual key labelled compose, but my system is set to use the right-hand Windows key (between Alt and the menu key) as the compose key. (Why the left-hand Windows key isn't set to do the same thing is a mystery to me.) So if I type: 'a I get á. The problem with the compose key is that it's not terribly intuitive. Sure, a few of them are: 1 2 gives ½ but how do I get π (pi)? p doesn't work. -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python 3.3 split method confusion
Thank you for clarifying my inquiry. I was just unable to find the reason as to why the built-in excludes the delimiter from the outpu. On Sat, Jan 4, 2014 at 9:25 AM, Alan Gauld wrote: > On 04/01/14 14:10, Christian Alexander wrote: > > I am curious to know why the split() method does not output the >> arbitrary delimiter that is passed as an argument? For example: >> > > Because in most cases you don't want it and would have to strip > it off each element manually after the event. > > I suppose they could have had a preserve parameter with a > default value of False for the few cases where you want to > keep it. > > But in the majority of cases split is used where we read a line > of input from a data file where the data fields are separated > by some arbitrary character, usually comma, tab or pipe. The > important bit is the data not the separator. > > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.flickr.com/photos/alangauldphotos > > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- Regards, Christian Alexander ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] encoding question
Following my previous email... On Sat, Jan 04, 2014 at 11:26:35AM -0800, Alex Kleider wrote: > Any suggestions as to a better way to handle the problem of encoding in > the following context would be appreciated. The problem arose because > 'Bogota' is spelt with an acute accent on the 'a'. Eryksun has given the right answer for how to extract the encoding from the webpage's headers. That will help 9 times out of 10. But unfortunately sometimes webpages will lack an encoding header, or they will lie, or the text will be invalid for that encoding. What to do then? Let's start by factoring out the repeated code in your giant for-loop into something more manageable and maintainable: > sp = response.splitlines() > country = city = lat = lon = ip = '' > for item in sp: > if item.startswith(b"Country:"): > try: > country = item[9:].decode('utf-8') > except: > print("Exception raised.") > country = item[9:] > elif item.startswith(b"City:"): > try: > city = item[6:].decode('utf-8') > except: > print("Exception raised.") > city = item[6:] and so on, becomes: encoding = ... # as per Eryksun's email sp = response.splitlines() country = city = lat = lon = ip = '' for item in sp: key, value = item.split(':', 1) key = key.decode(encoding).strip() value = value.decode(encoding).strip() if key == 'Country': country = value elif key == 'City': city = value elif key == 'Latitude': lat = value elif key = "Longitude": lon = value elif key = 'IP': ip = value else: raise ValueError('unknown key "%s" found' % key) return {"Country" : country, "City" : city, "Lat" : lat, "Long" : lon, "IP" : ip } But we can do better than that! encoding = ... # as per Eryksun's email sp = response.splitlines() record = {"Country": None, "City": None, "Latitude": None, "Longitude": None, "IP": None} for item in sp: key, value = item.split(':', 1) key = key.decode(encoding).strip() value = value.decode(encoding).strip() if key in record: record[key] = value else: raise ValueError('unknown key "%s" found' % key) if None in list(record.values()): for key, value in record.items(): if value is None: break raise ValueError('missing key in record: %s' % key) return record This simplifies the code a lot, and adds some error-handling. It may be appropriate for your application to handle missing keys by using some default value, such as an empty string, or some other value that cannot be mistaken for an actual value, say "*missing*". But since I don't know your application's needs, I'm going to leave that up to you. Better to start strict and loosen up later, than start too loose and never realise that errors are occuring. I've also changed the keys "Lat" and "Lon" to "Latitude" and "Longitude". If that's a problem, it's easy to fix. Just before returning the record, change the key: record['Lat'] = record.pop('Latitude') and similar for Longitude. Now that the code is simpler to read and maintain, we can start dealing with the risk that the encoding will be missing or wrong. A missing encoding is easy to handle: just pick a default encoding, and hope it is the right one. UTF-8 is a good choice. (It's the only *correct* choice, everybody should be using UTF-8, but alas they often don't.) So modify Eryksun's code snippet to return 'UTF-8' if the header is missing, and you should be good. How to deal with incorrect encodings? That can happen when the website creator *thinks* they are using a certain encoding, but somehow invalid bytes for that encoding creep into the data. That gives us a few different strategies: (1) The third-party "chardet" module can analyse text and try to guess what encoding it *actually* is, rather than what encoding it claims to be. This is what Firefox and other web browsers do, because there are an awful lot of shitty websites out there. But it's not foolproof, so even if it guesses correctly, you still have to deal with invalid data. (2) By default, the decode method will raise an exception. You can catch the exception and try again with a different encoding: for codec in (encoding, 'utf-8', 'latin-1'): try: key = key.decode(codec) except UnicodeDecodeError: pass else: break Latin-1 should be last, because it has the nice property that it will *always* succeed. That doesn't mean it will give you the right characters, as intended by the person who wrote the website, just that it will always give
Re: [Tutor] encoding question
On Sat, Jan 4, 2014 at 7:15 PM, Alex Kleider wrote: >> >> py> 'Bogotá'.encode('utf-8') > > I'm interested in knowing how you were able to enter the above line > (assuming you have a key board similar to mine.) I use an international keyboard layout: https://en.wikipedia.org/wiki/QWERTY#US-International One could also copy and paste from a printed literal: >>> 'Bogot\xe1' 'Bogotá' Or more verbosely: >>> 'Bogot\N{latin small letter a with acute}' 'Bogotá' ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] encoding question
On 2014-01-04 15:52, Steven D'Aprano wrote: Oh great. An exception was raised. What sort of exception? What error message did it have? Why did it happen? Nobody knows, because you throw it away. Never, never, never do this. If you don't understand an exception, you have no business covering it up and hiding that it took place. Never use a bare try...except, always catch the *smallest* number of specific exception types that make sense. Better is to avoid catching exceptions at all: an exception (usually) means something has gone wrong. You should aim to fix the problem *before* it blows up, not after. I'm reminded of a quote: "I find it amusing when novice programmers believe their main job is preventing programs from crashing. ... More experienced programmers realize that correct code is great, code that crashes could use improvement, but incorrect code that doesn't crash is a horrible nightmare." -- Chris Smith Your code is incorrect, it does the wrong thing, but it doesn't crash, it just covers up the fact that an exception occured. The output I get on an Ubuntu 12.4LTS system is as follows: alex@x301:~/Python/Parse$ ./IP_info.py3 Exception raised. IP address is 201.234.178.62: Country: COLOMBIA (CO); City: b'Bogot\xe1'. Lat/Long: 10.4/-75.2833 I would have thought that utf-8 could handle the 'a-acute'. Of course it can: py> 'Bogotá'.encode('utf-8') I'm interested in knowing how you were able to enter the above line (assuming you have a key board similar to mine.) b'Bogot\xc3\xa1' py> b'Bogot\xc3\xa1'.decode('utf-8') 'Bogotá' But you don't have UTF-8. You have something else, and trying to decode it using UTF-8 fails. py> b'Bogot\xe1'.decode('utf-8') Traceback (most recent call last): File "", line 1, in UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe1 in position 5: unexpected end of data More to follow... I very much agree with your remarks. In a pathetic attempt at self defence I just want to mention that what I presented wasn't what I thought was a solution. Rather it was an attempt to figure out what the problem was as a preliminary step to fixing it. With help from you and others, I was successful in doing this. And for that help, I thank all list participants very much. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] encoding question
On Sat, Jan 04, 2014 at 11:26:35AM -0800, Alex Kleider wrote: > Any suggestions as to a better way to handle the problem of encoding in > the following context would be appreciated. Python gives you lots of useful information when errors occur, but unfortunately your code throws that information away and replaces it with a totally useless message: > try: > country = item[9:].decode('utf-8') > except: > print("Exception raised.") Oh great. An exception was raised. What sort of exception? What error message did it have? Why did it happen? Nobody knows, because you throw it away. Never, never, never do this. If you don't understand an exception, you have no business covering it up and hiding that it took place. Never use a bare try...except, always catch the *smallest* number of specific exception types that make sense. Better is to avoid catching exceptions at all: an exception (usually) means something has gone wrong. You should aim to fix the problem *before* it blows up, not after. I'm reminded of a quote: "I find it amusing when novice programmers believe their main job is preventing programs from crashing. ... More experienced programmers realize that correct code is great, code that crashes could use improvement, but incorrect code that doesn't crash is a horrible nightmare." -- Chris Smith Your code is incorrect, it does the wrong thing, but it doesn't crash, it just covers up the fact that an exception occured. > The output I get on an Ubuntu 12.4LTS system is as follows: > alex@x301:~/Python/Parse$ ./IP_info.py3 > Exception raised. > IP address is 201.234.178.62: > Country: COLOMBIA (CO); City: b'Bogot\xe1'. > Lat/Long: 10.4/-75.2833 > > > I would have thought that utf-8 could handle the 'a-acute'. Of course it can: py> 'Bogotá'.encode('utf-8') b'Bogot\xc3\xa1' py> b'Bogot\xc3\xa1'.decode('utf-8') 'Bogotá' But you don't have UTF-8. You have something else, and trying to decode it using UTF-8 fails. py> b'Bogot\xe1'.decode('utf-8') Traceback (most recent call last): File "", line 1, in UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe1 in position 5: unexpected end of data More to follow... -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] encoding question
On 2014-01-04 12:01, eryksun wrote: On Sat, Jan 4, 2014 at 2:26 PM, Alex Kleider wrote: . b'\xe1' is Latin-1. Look in the response headers: url = 'http://api.hostip.info/get_html.php?ip=201.234.178.62&position=true' >>> response = urllib.request.urlopen(url) >>> response.headers.get_charsets() ['iso-8859-1'] >>> encoding = response.headers.get_charsets()[0] >>> sp = response.read().decode(encoding).splitlines() >>> sp[1] 'City: Bogotá' Thank you very much. Now things are more clear. cheers, alex ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] code smells: Object-orientation Abusers: switch statements
I meant to add... On 04/01/14 20:47, Alan Gauld wrote: Its called polymorphism and is one of the most powerful advantages of OOP since case or switch statements are one of the most fault prone structures in procedural programming. ... Without OOP you would need to do something like for shape in shapes: if shape['type'] == CIRCLE: result = circle_area(shape['radius']) elif shape['type'] == SQUARE: result = square_area(shape['length']) elif But with OOP we simply call each shapes area method and the interpreter works out which method to call: for shape in shapes: result = shape.area() This reduction in code in switch statements (and similar savings in other scenarios) is one of the reasons that OOP solutions are often much shorter than non OOP programs for non-trivial cases. Beginners often don't see these benefits because their short programs only have one or two classes and the overhead of creating the classes dwarfs the savings that might accrue. But in a big project where lots of if/else type situations may arise the code savings can easily add up to 20-30%. HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] code smells: Object-orientation Abusers: switch statements
On 04/01/14 20:11, Alex Kleider wrote: Assuming I am correct that in Python, switch statements must be implemented as a series of if; elif; .. statements, how is it that this can be avoided by creating subclasses? Its called polymorphism and is one of the most powerful advantages of OOP since case or switch statements are one of the most fault prone structures in procedural programming. You can see an example in my OOP topic in my tutor under the heading 'Same thing, Differenmt thing' http://www.alan-g.me.uk/tutor/tutclass.htm It uses a Shape class and several subclasses - Square, Triangle, Circle. It calculates the areas of a list of these shapes. Without OOP you would need to do something like for shape in shapes: if shape['type'] == CIRCLE: result = circle_area(shape['radius']) elif shape['type'] == SQUARE: result = square_area(shape['length']) elif But with OOP we simply call each shapes area method and the interpreter works out which method to call: for shape in shapes: result = shape.area() This has several benefits. First we can add new shape types and not have to change any of the application level code. The new shapes will supply their own area() methods and all is well. Second if we use the case style and need to modify the set of tests, we probably will need to do this in all sorts of places in our code. It's easy to forget one statement in a rarely used backwater... Thirdly polymorphism means we never inadvertently miss out a case. OOP will handle all object types in all situations. Cases can only handle the cases they have been programmed for. Finally the case statement require an intimate knowledge of both the attributes used for the test (if they ever get renamed, ouch!) and also the calling signatures (including how many and what type of parameters they have and the names) of the area functions. The OOP area method can use the internal attributes so no arguments need be provided. (The alternative for the switch is that the functions rely on the incoming object being cast or type converted to the correct shape subtype, which is almost as unreliable as reading the correct attributes). Even worse is that for short functions like area it's often tempting to inline the calculation within the case block. But then the same calculation is needed somewhere else and we then get duplicate code to maintain as well! HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] code smells: Object-orientation Abusers: switch statements
Continuing to look into the subject of code smells, I ran across this: "The situation where switch statements or type codes are needed should be handled by creating subclasses." @ http://www.soberit.hut.fi/mmantyla/BadCodeSmellsTaxonomy.htm Assuming I am correct that in Python, switch statements must be implemented as a series of if; elif; .. statements, how is it that this can be avoided by creating subclasses? tks alex ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] encoding question
On Sat, Jan 4, 2014 at 2:26 PM, Alex Kleider wrote: > The output I get on an Ubuntu 12.4LTS system is as follows: > alex@x301:~/Python/Parse$ ./IP_info.py3 > Exception raised. > IP address is 201.234.178.62: > Country: COLOMBIA (CO); City: b'Bogot\xe1'. > Lat/Long: 10.4/-75.2833 > > > I would have thought that utf-8 could handle the 'a-acute'. b'\xe1' is Latin-1. Look in the response headers: url = 'http://api.hostip.info/get_html.php?ip=201.234.178.62&position=true' >>> response = urllib.request.urlopen(url) >>> response.headers.get_charsets() ['iso-8859-1'] >>> encoding = response.headers.get_charsets()[0] >>> sp = response.read().decode(encoding).splitlines() >>> sp[1] 'City: Bogotá' ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] encoding question
Any suggestions as to a better way to handle the problem of encoding in the following context would be appreciated. The problem arose because 'Bogota' is spelt with an acute accent on the 'a'. $ cat IP_info.py3 #!/usr/bin/env python3 # -*- coding : utf -8 -*- # file: 'IP_info.py3' a module. import urllib.request url_format_str = \ 'http://api.hostip.info/get_html.php?ip=%s&position=true' def ip_info(ip_address): """ Returns a dictionary keyed by Country, City, Lat, Long and IP. Depends on http://api.hostip.info (which returns the following: 'Country: UNITED STATES (US)\nCity: Santa Rosa, CA\n\nLatitude: 38.4486\nLongitude: -122.701\nIP: 76.191.204.54\n'.) THIS COULD BREAK IF THE WEB SITE GOES AWAY!!! """ response = urllib.request.urlopen(url_format_str %\ (ip_address, )).read() sp = response.splitlines() country = city = lat = lon = ip = '' for item in sp: if item.startswith(b"Country:"): try: country = item[9:].decode('utf-8') except: print("Exception raised.") country = item[9:] elif item.startswith(b"City:"): try: city = item[6:].decode('utf-8') except: print("Exception raised.") city = item[6:] elif item.startswith(b"Latitude:"): try: lat = item[10:].decode('utf-8') except: print("Exception raised.") lat = item[10] elif item.startswith(b"Longitude:"): try: lon = item[11:].decode('utf-8') except: print("Exception raised.") lon = item[11] elif item.startswith(b"IP:"): try: ip = item[4:].decode('utf-8') except: print("Exception raised.") ip = item[4:] return {"Country" : country, "City" : city, "Lat" : lat, "Long" : lon, "IP" : ip} if __name__ == "__main__": addr = "201.234.178.62" print ("""IP address is %(IP)s: Country: %(Country)s; City: %(City)s. Lat/Long: %(Lat)s/%(Long)s""" % ip_info(addr)) """ The output I get on an Ubuntu 12.4LTS system is as follows: alex@x301:~/Python/Parse$ ./IP_info.py3 Exception raised. IP address is 201.234.178.62: Country: COLOMBIA (CO); City: b'Bogot\xe1'. Lat/Long: 10.4/-75.2833 I would have thought that utf-8 could handle the 'a-acute'. Thanks, alex ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] simple arg problem
On 2014-01-04 10:56, Alan Gauld wrote: On 04/01/14 17:21, Alex Kleider wrote: In the reference you site, under "Oddball Solution" mention is made of "adaptor model." Is this the same as what is described here, http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93adapter, under the name of "Model-View-Adaptor?" I haven't read it but I'm guessing its more likely associated with the adapter (or wrapper) pattern: http://en.wikipedia.org/wiki/Adapter_pattern just guessing though, Yes, that fits; i.e. makes more sense. thanks. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] simple arg problem
On 04/01/14 17:21, Alex Kleider wrote: In the reference you site, under "Oddball Solution" mention is made of "adaptor model." Is this the same as what is described here, http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93adapter, under the name of "Model-View-Adaptor?" I haven't read it but I'm guessing its more likely associated with the adapter (or wrapper) pattern: http://en.wikipedia.org/wiki/Adapter_pattern just guessing though, -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] simple arg problem
On 2014-01-03 20:45, Steven D'Aprano wrote: On Fri, Jan 03, 2014 at 09:56:25PM -0500, Keith Winston wrote: ... >>> Eryksun has already solved your immediate problem, but I'd like to point out that the above has a couple of code smells. Are you familiar with the concept of a code smell? Code which smells wrong might not be wrong, but it's worth giving it a good hard long look just to be sure. Like Grandma used to say about your nappies, "If it stinks, change it", code smells usually suggest there's a problem with the code. http://www.codinghorror.com/blog/2006/05/code-smells.html In the reference you site, under "Oddball Solution" mention is made of "adaptor model." Is this the same as what is described here, http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93adapter, under the name of "Model-View-Adaptor?" I don't understand the connection, so perhaps I got the wrong reference. Light shed on the issue would be appreciated. cheers, Alex ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python 3.3 split method confusion
On 04/01/14 14:10, Christian Alexander wrote: I am curious to know why the split() method does not output the arbitrary delimiter that is passed as an argument? For example: Because in most cases you don't want it and would have to strip it off each element manually after the event. I suppose they could have had a preserve parameter with a default value of False for the few cases where you want to keep it. But in the majority of cases split is used where we read a line of input from a data file where the data fields are separated by some arbitrary character, usually comma, tab or pipe. The important bit is the data not the separator. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] python 3.3 split method confusion
Hello fellow tutors, I am curious to know why the split() method does not output the arbitrary delimiter that is passed as an argument? For example: string1 = "this,is,just,another,string" print(string1.split(",")) I understand the the above code simply states, "break at every ' , ' ". But why is the delimiter not printed as well? -- Regards, Christian Alexander ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python problems on android
On Sat, 04 Jan 2014 12:16:29 +, blech...@fireflyuk.net wrote: Thank you. I see, it was running python 3.x when that didn't work I uninstalled it and used SL4a to reinstall it installed Python 2.x So raw_input should work instead of input If you're stuck with 2.x then you could use raw_input (). But there are many other differences. If you're learning 3.x you should reinstall 3.x. Or doesn't slate work with a current python? -- DaveA ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python problems on android
On 04/01/14 11:24, blech...@fireflyuk.net wrote: At the command line (on my computer) I can type h = input(" enter character ") and when i type a response and enter it, then type h and return, i am given back the response i put in. I type j , get 'j' back Now on my phone i can do the same. And here is the odd bit If I type a number in, the response will be the number type 4, get '4' back but if i type in a letter I get an error, the same error as if i had typed in the response to the command line. NameError: name '" is not defined What you describe is the symptoms of using different versions of Python. In Python v3 (your computer?) input reads a string from the user. In Python v2 input reads a string and evaluates it as code. Thus a number evaluates to a number but a string is evaluated like a variable name. Presumably your Android is running your code under a v2 Python interpreter. You can try putting raw_input() instead of input() in your code to see if that fixes it. [input() in v3 is a renaming of input() and the original input() function was removed.] If that works for the simple test case you could try adding this at the top of your script: try: input = raw_input except NameError: pass But that only addresses one aspect of Python v2/3 incompatibility so there will probably be other fixes needed. The best thing is to align Python versions. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] More or less final Chutes & Ladders
On 01/04/2014 02:03 PM, Steven D'Aprano wrote: >I'm also a bit confused here: obviously tuples are immutable, but one can >use lists in them... I think that makes those lists' contents immutable? Nope. It makes the tuple immutable in the sense that it's *direct* contents cannot be changed, but mutable in the sense that the contents of the tuple can be mutated. py> t = (1, 2, []) py> t[2] = ["hello"] Traceback (most recent call last): File "", line 1, in TypeError: 'tuple' object does not support item assignment py> t[2].append("hello") py> t (1, 2, ['hello']) >And could one define a namedtuple that included lists that were different >lengths for different instantiations (like my game results, for example)? Naturally. The nametuple doesn't care what you put inside it. I used to explain this by making people note that there 2 ways of *changing* a given item (or field, or any var for the matter), if its value is complex & mutable: *replacing* vs *modifying*: l = [1,2,3] l = [1,0,3] # replace (by brand new value/object) l[1] = 0# modify (the value/object itself) When a symbol's value is simple or mutable, one can only replace it. (You can change _only_ the second digit of "123", or its n-th bit in binary representation, or the fractional part of "-123.45", less so its sign ;-). Denis ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] More or less final Chutes & Ladders
On 01/04/2014 02:03 PM, Steven D'Aprano wrote: >I understand that Python doesn't have composite objects, but neither does >it dislallow my list of lists of ints and lists... which is, I imagine, >very space efficient. I'm afraid I have no idea what you mean by Python not having "composite objects". What's a composite object? It was "individual" composite objects: Python requires writing a custom type (class), as if there were tons of them. Eg in Keith Winston's project he would have to define a class for the game tupe (ChutesAndLadder) even is there were only one of them (there are many because he collects stats, and the game is not really played, his app is more like instrumenting a game engine for automagic statistics collection; in a common case, there would be only one 'game' object). Denis ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] More or less final Chutes & Ladders
On Sat, Jan 04, 2014 at 07:19:43AM -0500, Keith Winston wrote: > I understand that Python doesn't have composite objects, but neither does > it dislallow my list of lists of ints and lists... which is, I imagine, > very space efficient. I'm afraid I have no idea what you mean by Python not having "composite objects". What's a composite object? > I think what you are in essence saying is that it's a > mistake for me to worry about space at the expense of clarity... What Denis and I are trying to say is that when you are using a high-level language like Python, you should aim to optimize programmer time and effort, not computer time and effort. There are applications where you have to optimize what the computer does, where every byte counts, where microseconds matter. Python is not the right programming language for those applications. Python is a language for when you have the luxury of tens of megabytes of memory, not kilobytes, when you don't care whether something takes a millisecond to calculate instead of a tenth of a millisecond. (Actually, there are versions of Python for embedded devices, such as Android, where memory does matter -- at least, where every kilobyte counts.) Everything is a tradeoff. In programming, one common set of tradeoffs is space (memory) versus time: use more memory to run faster, or save memory but run slower. Python generally trades off memory for speed. There is very little point in trying to save bytes, because behind the scenes Python is using and re-using memory like its going out of fashion, just to ensure that it can be as fast as possible. py> import sys py> sys.getsizeof(42) 14 Fourteen bytes just for a tiny little integer like that??? How wasteful! I remember when numbers like 42 would only require *two* bytes. Of course, back then the biggest number you could deal with was 65535, and a computer with 64K of memory was considered unbelievably luxurious. Meanwhile, Python let's me handle numbers with thousands of digits with ease: py> n = 2**1 py> len(str(n)) 3011 Another tradeoff is between programmer effort (which equals time, and cost) versus speed. Programs written in C are typically between 10 and 1 times faster than the same program written in Python, but they typically take between 20 and 200 times longer and more effort to write. You should ask, is my program *fast enough*? rather than ask if it is fast. Often, Python is fast enough. When it's not, there are ways to make it faster. So don't sweat the small stuff. If you ever have to write an operating system kernel or a graphics card driver, then you need care about optimizing every little thing. Until then, write the most natural code you can, and only if it actually is too slow should you worry about it. > I'm not meaning to argue, but to understand. Especially in lieu of an > upcoming project with, perhaps, larger and more complex structures. I am > increasingly curious about whether namedtuples are a good strategy for some > of this: they store their field names, as I understand it, and I can live > with an immutable type in all these cases: I wonder if they are as > efficient in named-field (key) lookup as dictionaries? Pretty close to it. Not quite, but within a factor of about 3. Let's do some micro-benchmarks! First, let's create some data objects with three fields, using three different techniques: a dict x, a regular class with named fields y, and a namedtuple z. py> x = {'a': 23, 'b': 42, 'c': 57} py> class Record: ... def __init__(self, a, b, c): ... self.a = a ... self.b = b ... self.c = c ... py> y = Record(23, 42, 57) py> from collections import namedtuple py> recordnt = namedtuple('recordnt', 'a b c') py> z = recordnt(23, 42, 57) Now let's set up some timing code, where we extract all three fields in reverse order: py> from timeit import Timer py> setup = "from __main__ import x, y, z" py> t1 = Timer("x['c'], x['b'], x['a']", setup) py> t2 = Timer("y.c, y.b, y.a", setup) py> t3 = Timer("z.c, z.b, z.a", setup) And now let's time them: py> min(t1.repeat()) 0.2941127344965935 py> min(t2.repeat()) 0.34186235070228577 py> min(t3.repeat()) 0.7729006875306368 That's not too shabby. Even the slowest of the three (test t3, the one using the namedtuples) takes only 0.26 microseconds per field lookup. Times shown are seconds for one million repeats of the test code, or nanoseconds per single run. There are three field lookups per test, so 0.77 nanoseconds/3 is about 0.26 nanoseconds. If you ever find a piece of code where the difference between 0.1 ns and 0.26 ns per field lookup is meaningful, I'd like to see it. > I'm also a bit confused here: obviously tuples are immutable, but one can > use lists in them... I think that makes those lists' contents immutable? Nope. It makes the tuple immutable in the sense that it's *direct* contents cannot be changed, but mutable in the sense that the co
Re: [Tutor] python problems on android
On 04/01/2014 10:47, blech...@fireflyuk.net wrote: Ok. Will try and explain the problem. I wrote a script in python and found I could use it on my android phone with SL4a. It was really useful. Haven't used it for a few months. A few days ago I decided to improve it and found it no longer works. the problem seems to be that when it reaches an input statement it will only accept a number. If I try to input a letter I get an error message the same as if I had just typed the letter into the command line. I am not sure what has happened, it used to work ok. Is there another way of getting input into my script without using.input? Or better still does anyone understand what is going wrong? Both my main and spare cystal balls are at the menders so I'm terribly sorry but you'll have to go to all the effort of posting a sample of code that fails and the full traceback asssuming that there is one. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] More or less final Chutes & Ladders
Thanks again Denis, I might just have to ruminate on this, but I am definitely having an allergic reaction. I understand that Python doesn't have composite objects, but neither does it dislallow my list of lists of ints and lists... which is, I imagine, very space efficient. I think what you are in essence saying is that it's a mistake for me to worry about space at the expense of clarity... ok, but if I really don't need to break out those single lists ever, to speak of... it seems like I've vastly enlarged my array for little gain. I'm not meaning to argue, but to understand. Especially in lieu of an upcoming project with, perhaps, larger and more complex structures. I am increasingly curious about whether namedtuples are a good strategy for some of this: they store their field names, as I understand it, and I can live with an immutable type in all these cases: I wonder if they are as efficient in named-field (key) lookup as dictionaries? I'm also a bit confused here: obviously tuples are immutable, but one can use lists in them... I think that makes those lists' contents immutable? And could one define a namedtuple that included lists that were different lengths for different instantiations (like my game results, for example)? I really should be playing with them instead of asking questions, at this point... Thanks as always! Keith ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python, speed, game programming
On Fri, Jan 03, 2014 at 08:38:47PM -0500, Keith Winston wrote: > The thing that put me on edge was noticing that my simple > Chutes & Ladders game doesn't go ANY faster on a machine that benchmarks > perhaps 1000 times faster than another... Damn! You've discovered our secret! Hidden deep insight the Python compiler is code that determines the speed of computer, and deliberately slows down the Python runtime so that it runs just as slowly on all PCs, no matter how fast they are or how much memory they have... *wink* But seriously... This is clearly bogus. There has to be an explanation, apart from "Python secretly tries to run just as slow on everything". Even slow, inefficient code will run faster on faster hardware. But how much faster? How accurate are your timing measurements? Some possible explanations: - the method you used to time the code is inaccurate or doesn't measure what you think it does; - the code you have written spends most of its time doing things that aren't sped up by a faster computer, e.g. waiting for human input, downloading data from the Internet, reading and writing to a network drive, etc.; - the benchmarks that say the second computer is 1000 times faster than the first are bogus (not necessarily lying, although possibly lying by ommission). I expect that the anwser to this mystery is a combination of the first and the last factors. It's harder to measure the execution speed of code than you might think, and most PC benchmarks are worse than you might think. Many benchmarks are artifical and designed as advertising, to show the product in the best possible light. If a machine has a CPU clock speed that is 1000 times faster than the last model, the benchmarks will all be for tiny little programlets that are reliant on CPU speed. Meanwhile, the fact that real-world applications see hardly any benefit because the computer can't push data into and out of the CPU any faster than before gets conveniently swept under the carpet. (Cynical? Who, me?) -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python problems on android
Thank you. I see, it was running python 3.x when that didn't work I uninstalled it and used SL4a to reinstall it installed Python 2.x (Thanks, sorry for being slow to catch on and for multiple threads) So raw_input should work instead of input ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python problems on android
On Sat, Jan 4, 2014 at 11:24 AM, wrote: > > I havent included the script as it seems to be the use ' input' on my phone > that now wont work. > Even if the error is with 'input', it is still an odd error and no one will be able to debug your program or have a clue what's going wrong if you don't provide us any code. It will save a lot of time also. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] More or less final Chutes & Ladders
On 01/04/2014 12:33 PM, Keith Winston wrote: Thanks Alan & Denis: Alan, the improvement you suggested had already been made, and adopted. Good catch. Denis: alas, there are chutes and ladders dicts, but I guess your chutes & ladders lists are local to the results class... Your suggestion is quite shocking to me, I wouldn't have thought of creating a class for results... I guess it allows clearer modularity of the final candl_array? I don't really get it... I think you are using it, essentially, for nothing other than a data structure, right? And some cleaner print options, though I have only looked at the raw game data for debugging... it's a great suggestion, obviously, because I am a little dumbfounded by it, and it's making me think. My initial reaction is concern about having too many classes, but I don't really have any sense of how important that is. I was playing with storing ChutesAndLadders instances in my game array, but of course they include all their methods, etc: all kinds of overhead (at least, that's my impression), which is why I created the results method, so I could just pass a... list? composite object? Collection? I can't really sort out what the latter two mean in Python, and must be looking in the wrong place... while I was researching I found out about namedtuple(), which seems like a promising structure for game data, but I haven't really looked into it. It might also be a collection... The entire game is to be played in bulk (that is, it's really a statistical foray, albeit a silly one), so the candl_array might get large (perhaps millions of "records" -- results lists). Is there some way the Results class helps that? A class for results makes your global game result stats a plain list of result object, each with a clear composition / structure, with nicely self-commenting field names. What best could you dream of. A result is "by nature" (if I may say) a composite with well definite fields; think at a C struct. Some may have different views, but I'd say it's worth making a class (custom object type) when: * it defines conceptually and practically _composite_ elements, just like C structs or Pascal records, * or, some type-specific methods are needed or useful. (in fact string output methods are nearly always useful, for signicant elements or element types of an app, if only for your own feedback as programmer, in debugging, testing, diagnosing...) An additional factor is, as in your case, that there are multiple such elements [*]. Usually, they are then stored in a collection (list, set, dict). Denis [*] Unfortunately, in python there are no individual composite objects: Python provides "class-based" OOP (as opposed to "prototype-based", or object-based if you like). In eg Lua or JS, you'd just write for instance: origin = {x=0, y=0, label="Origin"} full dot. (And then access fields like 'origin.y', like in python for class instances.) One can simulate that in python, or abuse dicts (however with annoying syntax), but in any case it is not a feature of the language. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python problems on android
Well, I probably can't help you, I haven't installed SL4 (yet), and am a Python beginner myself anyway. I imagine others might be more prepared to help you with a copy of the script. However: something about the way you are responding to this thread keeps breaking it, so you end up starting a new thread (you've started three). That's a little hard to keep track of, and there are those here who truly hate that kind of thing. This message, for example, started a new thread (at least for me, I assume others), but your last reply didn't, so if you know what you did (or didn't do) that time, do that from now on! My only thought on the problem is: what is the script doing with the input? Maybe for some reason a number works in that context, but a letter doesn't? Even just including a few lines of the code around the input statement might be better than nothing. keith ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] More or less final Chutes & Ladders
Thanks Alan & Denis: Alan, the improvement you suggested had already been made, and adopted. Good catch. Denis: alas, there are chutes and ladders dicts, but I guess your chutes & ladders lists are local to the results class... Your suggestion is quite shocking to me, I wouldn't have thought of creating a class for results... I guess it allows clearer modularity of the final candl_array? I don't really get it... I think you are using it, essentially, for nothing other than a data structure, right? And some cleaner print options, though I have only looked at the raw game data for debugging... it's a great suggestion, obviously, because I am a little dumbfounded by it, and it's making me think. My initial reaction is concern about having too many classes, but I don't really have any sense of how important that is. I was playing with storing ChutesAndLadders instances in my game array, but of course they include all their methods, etc: all kinds of overhead (at least, that's my impression), which is why I created the results method, so I could just pass a... list? composite object? Collection? I can't really sort out what the latter two mean in Python, and must be looking in the wrong place... while I was researching I found out about namedtuple(), which seems like a promising structure for game data, but I haven't really looked into it. It might also be a collection... The entire game is to be played in bulk (that is, it's really a statistical foray, albeit a silly one), so the candl_array might get large (perhaps millions of "records" -- results lists). Is there some way the Results class helps that? keith ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python, speed, game programming
On 01/04/2014 02:38 AM, Keith Winston wrote: The thing that put me on edge was noticing that my simple Chutes & Ladders game doesn't go ANY faster on a machine that benchmarks perhaps 1000 times faster than another... You could say this about most programs in most langs. Actually, some even regress in perf while harware progresses by orders of magnitude. This is due to the whole software platform (OS + layers of UI and graphics, plus underlying libs and frameworks, plus the ones your apps explicitely call) becoming more and more HW resource consuming, this independently of actual app logic processing. As Alan evoked, I remember how early PCs were fast, retrospectively, with comparatively ridiculous HW resources (clock freq & live mem mainly). Resource consumptions of what I call here software platforms have progressed at a rythm comparable to HW resources. However, in general, there remain resource gains for apps, in absolute (rather than proportional) value. (But you can see that prop gains are not that important when running multiple heavy apps at once.) Denis ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python, speed, game programming
On 01/04/2014 10:14 AM, Steven D'Aprano wrote: While I agree with Devin, it is possible to write absurdly slow code in *any* language. This is why is is better to write straightforward, simple code in preference to complicated, intricate code -- it is easier to understand simple code, which means it is easier to work out which bits are bottlenecks and do something about them. Then, only if it turns out the code is too slow, do you add complexity to speed it up. +++ I would add: it is preferable to write _clear_ code, in the widest sense of "easy to understand". Simplicity is not the only factor or clarity (good naming, using right constructs [1], direct mapping from conception to code structure & logic...); also, some simple schemes are very difficult to figure out (eg various functional programing idioms). From clear code, everything else is easier: modification, extension, improving efficeincy (time and/or space), doc, debugging, testing, trials... I would even say (surprisingly?) that clarity has precedence over correctness: it's easier to correct clear code, while correct but obscure code makes anything else harder. personal point of view: Issue number 1 in programming is understanding (what code actually means and actually does). That's why we spend about 97.531% of our time thinking ;-) Denis [1] Python's "one good way to do it". ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] python problems on android
I havent included the script as it seems to be the use ' input' on my phone that now wont work. At the command line (on my computer) I can type h = input(" enter character ") and when i type a response and enter it, then type h and return, i am given back the response i put in. I type j , get 'j' back Now on my phone i can do the same. And here is the odd bit If I type a number in, the response will be the number type 4, get '4' back but if i type in a letter I get an error, the same error as if i had typed in the response to the command line. NameError: name '" is not defined so if my response was G I get back NameError: name 'G" is not defined Is there any other (easy) way I can get around this by not using input for input? could I use android to pass input to my script? ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Copying [was Re: What's in a name?]
On 01/04/2014 07:24 AM, Keith Winston wrote: I had heard about deep/shallow copies, though in this particular example (all int dicts), I don't think there's a difference...? There's none, you're right. It's only whenever inner items (fields, etc...) themselves are complex elements and mutable. Else, mutations on original items would show on copies, and conversely. But when htere are simple items only, or immutable (tuples, strings...) the ambiguity does not exist. Denis ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Fwd: What's in a name?
On 01/04/2014 06:36 AM, Steven D'Aprano wrote: Now, it's true that when *debugging code*, being able to see the name of the variable and the contents of the variable is useful. But in ordinary code, why would you care to print the name of the variable and its contents. Who cares what the variable is named? Debuggers stick all sorts of nasty hooks into the running interpreter in order to do this (and much more), and we should all be thankful that (1) debuggers exist, (2) that they aren't running by default, and most importantly (3) that we don't have to write code like them. In addition to powerful debuggers, we also have fantastic poor-man's debugger called "print": for name, value in zip( 'alist blist clist'.split(), [alist, blist, clist]): print(name, "=", value) I dream of a 'note' debug write function (or better statement with keyword, like assert) working like: n = 0 i = 1 note n # ==> n = 1 note i n# ==> i = 0 | n = 1 note i (type) # ==> i = 0 (int) note i (where) # ==> i = 0 (mod.cls.f, 333) (The latter version gives full func name & line n° in module.) I have always disliked debuggers, and REPL's as well (both too rigid & heavy), so maybe my view is somewhat marginal. Yes, it's a little bit messy code. We have to repeat the name of the variable twice. But this isn't code that will hang around in the finished program. It only need exist for just long enough to debug the problem we're having (you are having a problem, I presume?), then, it's job done, it's gone. You are right, but people who like exploratory, flexible, trial-and-error programming (even at tmes, not systematically), constantly write such debug statemetns or pieces of code, anew. (That's why I tend to let them code for a while; and I use a "write" debug func which just wraps print, just to have another name and be able to find & erase them all at once quickly.) Denis ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python problems on android
Perhaps you could include the script? On Sat, Jan 4, 2014 at 5:47 AM, wrote: > > > Ok. Will try and explain the problem. > I wrote a script in python and found I could use it on my android phone > with SL4a. > It was really useful. > Haven't used it for a few months. > A few days ago I decided to improve it and found it no longer works. > the problem seems to be that when it reaches an input statement it will > only accept a number. > If I try to input a letter I get an error message the same as if I had > just typed the letter into the command line. > I am not sure what has happened, it used to work ok. > > Is there another way of getting input into my script without > using.input? > > Or better still does anyone understand what is going wrong? > > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > > -- Keith ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] What's in a name?
Thanks to both of you. In this particular case, the main use of eval() was only for 2 calls, which were essentially hard-coded (you could see the calls to summarize_game in my code). I was looking for a more general solution to what I was trying to do, but I don't need it for this project. Still, this has been an informative conversation. On Sat, Jan 4, 2014 at 12:56 AM, Steven D'Aprano wrote: > On Sat, Jan 04, 2014 at 12:32:19AM -0500, Keith Winston wrote: > > On Fri, Jan 3, 2014 at 11:59 PM, Steven D'Aprano >wrote: > > > > > thelist = vars()[name] > > > > > > I see: vars() certainly looks less dangerous than eval(), but I'm > guessing > > that's still smelly code? I hadn't known about vars() or I probably would > > have used it. > > Yes, it's still a bit smelly: but only a bit, since while "direct" code > is the idea, sometimes the only way to do things is with one (or two) > layers of indirection. > > Code should (as a general rule) not rely on, or be affected by, the name > of the variable. Functions which inspect the running environment (i.e. > peek deep inside the interpreter) or use eval or other techniques to > operate "behind the scenes" on *names* rather than values can often lead > to confusing code. As debugging tools, they're useful. Putting such > functionality inside normal everyday programs is a code smell. > > > -- > Steven > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- Keith ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] What's in a name?
On 01/04/2014 06:32 AM, Keith Winston wrote: On Fri, Jan 3, 2014 at 11:59 PM, Steven D'Aprano wrote: thelist = vars()[name] I see: vars() certainly looks less dangerous than eval(), but I'm guessing that's still smelly code? I hadn't known about vars() or I probably would have used it. It is not as much smelly as somewhat "meta". It talks about Python's own conception, here about scopes (or namespaces). [I will let so-called "non-locals" aside, for simplicity.] Imagine that Python provided 2 dicts, always there: * top_vars, for vars defined at top module level (included imports) * local_vars for function local vars (included inputs) Then, you could write: a = 1 def f (): top_vars.a = 2# redef / change symbol a local_vars.b = 1# def / create symbol b print(top_vars.a, local_vars.b) which is the same as actual Python code: a = 1 def f (): global a a = 2 b = 1 print(a, b) but shows more or less how things work behind the stage. local() and globals() return a dict equivalent to my imaginary local_vars and global_vars, resp. [But in the actual implementation, things are somewhat more low-level for efficiency; esp. IIRC locals are not truely named if you don't ask for them, as in most dynamic langs; but I may be wrong]. If Python scope were simply, truely, directly Python data (dicts), without the need to call a function that fabricates the dict on need, then the language would be "homoiconic" (on this aspect of its functioning), which just means that it works using its own data (types). Thus, the "meta" view. vars() is somewhat special, works for any namespace-like component. See: http://docs.python.org/3/library/functions.html for a few details. Denis ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python problems on android
Ok. Will try and explain the problem. I wrote a script in python and found I could use it on my android phone with SL4a. It was really useful. Haven't used it for a few months. A few days ago I decided to improve it and found it no longer works. the problem seems to be that when it reaches an input statement it will only accept a number. If I try to input a letter I get an error message the same as if I had just typed the letter into the command line. I am not sure what has happened, it used to work ok. Is there another way of getting input into my script without using.input? Or better still does anyone understand what is going wrong? ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] simple arg problem
On 01/04/2014 05:45 AM, Steven D'Aprano wrote: On Fri, Jan 03, 2014 at 09:56:25PM -0500, Keith Winston wrote: gmail is driving me crazy. Anyway, every time I run it with: if __name__ == "__main__": tarray = CandL_Array tarray.populate(100) I get an error Traceback (most recent call last): File "/home/keithwins/Dropbox/Python/CandL8.py", line 127, in tarray.populate(100) TypeError: populate() missing 1 required positional argument: 'gamecount1' Eryksun has already solved your immediate problem, but I'd like to point out that the above has a couple of code smells. Are you familiar with the concept of a code smell? Code which smells wrong might not be wrong, but it's worth giving it a good hard long look just to be sure. Like Grandma used to say about your nappies, "If it stinks, change it", code smells usually suggest there's a problem with the code. http://www.codinghorror.com/blog/2006/05/code-smells.html Like parmesan and blue cheeses, or durian fruit, there are a few exceptions, but normally code is like food: it only smells bad when it has gone off. You should never write smelly code without giving it a good, hard look. Anyway, back to your code... you have a class CandL_Array which apparently you call with no arguments. If it needed arguments, you wouldn't have made the error you did, which is to forget to include parentheses: # No tarray = CandL_Array # makes tarray an alias to the class # Yes tarray = CandL_Array() # makes tarray an instance of the class If CandL_Array() needed arguments, you wouldn't have forgotten the round brackets, and wouldn't have got the error you did. So there's a little whiff of a smell right there... why does the class not take any arguments? That suggests that every instance it creates is exactly the same as every other instance. That's not necessarily wrong, but it is a little bit whiffy. But then there's the next line: tarray.populate(100) Apparently, and I'm reading between the lines here, once you create the CandL_Array instance, you can't use it until you populate it. If I'm right, that's pretty smelly. That means you have errors like this: tarray = CandL_Array() # Initialise an instance. tarray.play_game() # or something, you don't show that part of the code which blows up in your face because you forgot to call populate first. That's ugly, stinking code. Imagine if you had to write code like this: x = float("12.345") x.prepare() # Make the float ready to use y = x + 1.0 # Now we can use it! Yuck. Most of the time, creating an instance should do everything needed to prepare it for use. I suspect that your game is no exception. If you need to call some method to make the instance ready to use, then the constructor __new__ or initialiser __init__ should do so. You don't even have to get rid of the populate method. You just need to change this: class CandL_Array: def __init__(self): ... def populate(self, size): ... to this: class CandL_Array: def __init__(self, size): ... self.populate(size) def populate(self, size): ... and change this: tarray = CandL_Array() tarray.populate(100) to this: tarray = CandL_Array(100) Waow! that was problem analysis. Denis ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] More or less final Chutes & Ladders
On 01/04/2014 05:47 AM, Keith Winston wrote: Here is what I think will be about the final version of C and L. I rearranged it quite a bit (into 2 classes), fixed a bug or two, and generally cleaned it up a bit. I haven't really polished it, but hopefully it will be less difficult to read... which is to say, if anyone wants to go through it AGAIN (at your leisure) I would appreciate comments on style, etc. A few notes: * You don't need, for lists, names likes 'self.chutes_list': 'self.chutes' does the job and is de facto standard in Python. Similarly, for a dict like one mapping names to phones, one can use 'names_phones' (read: "names' phones" or "names to phones"). * Try to find a satisfying personal convention (there is no standard in Python) for indexes (number of A thing) and counts (numbers of things), which constantly come up programming. (I use i_thing & n_things, or just i & n when in context there is no possible ambiguity.) * What is the point of method reset apart from __init__? (Even if you need to reset a game after it has started, you could call __init__ for that. Rarely needed, but happens, esp. in games when eg a trap or bad luck brings the player back to start.) * Make a class for results (see example below). Not only it is semantically correct (a result is a composite object, not a collection, but youy use a list), not only it makes code cleaner, but it allows more simply modifying and extending. Also, you could add there, directly in the concerned class, methods that deal with results (in addition to ones for result output, as in the example, which I also write first). * When posting code, place your signature (-- Keith) _after_. Else, it causes weird bugs in email readers (eg mine, Thunderbird); I cannot even copy-paste it, for some weird reason. Denis === class Result example == class Result: ''' result of an individual game Fields: * no: 'numéro' (?) of the game * n_moves : number of moves * chutes: list of chute positions * ladders : list of ladder positions Methods: * __repr__ : notation, as in code * __str__ : writing with field names ''' def __init__ (self, no, n_moves, chutes, ladders): ''' Store game stat data. ''' self.no = no self.n_moves= n_moves self.chutes = chutes self.ladders= ladders # output def __repr__ (self): ''' notation, as in code (for programme feedback) ''' return "Result(%r, %r, %r, %r)" % \ (self.no, self.n_moves, self.chutes, self.ladders) def __str__ (self): ''' writing with field names (eg for user info in UI) ''' return "{no:%s n-moves:%s chutes:%s ladders:%s}" % \ (self.no, self.n_moves, self.chutes, self.ladders) # fake example res = Result(3, 333, [1,2,3], [99,33,11]) print("\n%r\n\n%s\n" %(res, res)) """ writes out: Result(3, 333, [1, 2, 3], [99, 33, 11]) {no:3 n-moves:333 chutes:[1, 2, 3] ladders:[99, 33, 11]} """ ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] More or less final Chutes & Ladders
On 04/01/14 04:47, Keith Winston wrote: Here is what I think will be about the final version of C and L. Much better. Only one suggestion... def run_CandL(gamecount): tarray = CandL_Array() tarray.populate(gamecount) tarray.print_stuff() Remove the middle line by making the array take a gamecount argument and call populate from the init method. Why should the user have to populate the class when it can do it itself? Being picky I'm not keen on "stuff" as part of the name of the final method call. Surely there a slkightly descriptive term somewhere? print_stats, print_data, print_game_results etc? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python, speed, game programming
On Fri, Jan 03, 2014 at 02:11:21PM -0800, Devin Jeanpierre wrote: > On Fri, Jan 3, 2014 at 1:53 PM, Keith Winston wrote: > > I am gearing up for the next project (yeah, an eventual end to Chutes & > > Ladders!). It is a typing tutor, I am inclined to use it to learn Dvorak but > > I would expect it easily adapted to QWERTY or anything else. [...] > Modern computers are just so absurdly fast that the overhead Python > has compared to other languages just doesn't matter for the kind of > work you are doing. If you typed at a hundred characters per second > Python could still keep up, unless there's something about your > problem you aren't describing. While I agree with Devin, it is possible to write absurdly slow code in *any* language. This is why is is better to write straightforward, simple code in preference to complicated, intricate code -- it is easier to understand simple code, which means it is easier to work out which bits are bottlenecks and do something about them. Then, only if it turns out the code is too slow, do you add complexity to speed it up. -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor