Re: [Tutor] encoding question

2014-01-04 Thread Alex Kleider

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

2014-01-04 Thread Mark Lawrence

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

2014-01-04 Thread Keith Winston
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

2014-01-04 Thread Alex Kleider

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

2014-01-04 Thread Danny Yoo
> 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

2014-01-04 Thread Keith Winston
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

2014-01-04 Thread Danny Yoo
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

2014-01-04 Thread eryksun
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

2014-01-04 Thread Alex Kleider

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

2014-01-04 Thread Danny Yoo
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

2014-01-04 Thread Danny Yoo
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

2014-01-04 Thread Dave Angel
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

2014-01-04 Thread Danny Yoo
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

2014-01-04 Thread Danny Yoo
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

2014-01-04 Thread Danny Yoo
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

2014-01-04 Thread Alex Kleider
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

2014-01-04 Thread Steven D'Aprano
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

2014-01-04 Thread Christian Alexander
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

2014-01-04 Thread Steven D'Aprano
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

2014-01-04 Thread eryksun
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

2014-01-04 Thread Alex Kleider

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

2014-01-04 Thread Steven D'Aprano
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

2014-01-04 Thread Alex Kleider

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

2014-01-04 Thread Alan Gauld

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

2014-01-04 Thread Alan Gauld

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

2014-01-04 Thread Alex Kleider

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

2014-01-04 Thread eryksun
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

2014-01-04 Thread Alex Kleider
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

2014-01-04 Thread Alex Kleider

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

2014-01-04 Thread Alan Gauld

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

2014-01-04 Thread Alex Kleider

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

2014-01-04 Thread Alan Gauld

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

2014-01-04 Thread Christian Alexander
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

2014-01-04 Thread Dave Angel

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

2014-01-04 Thread Alan Gauld

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

2014-01-04 Thread spir

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

2014-01-04 Thread spir

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

2014-01-04 Thread Steven D'Aprano
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

2014-01-04 Thread Mark Lawrence

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

2014-01-04 Thread Keith Winston
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

2014-01-04 Thread Steven D'Aprano
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

2014-01-04 Thread blechnum


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

2014-01-04 Thread Matthew Ngaha
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

2014-01-04 Thread spir

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

2014-01-04 Thread Keith Winston
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

2014-01-04 Thread Keith Winston
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

2014-01-04 Thread spir

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

2014-01-04 Thread spir

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

2014-01-04 Thread blechnum


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?]

2014-01-04 Thread spir

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?

2014-01-04 Thread spir

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

2014-01-04 Thread Keith Winston
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?

2014-01-04 Thread Keith Winston
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?

2014-01-04 Thread spir

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

2014-01-04 Thread blechnum




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

2014-01-04 Thread spir

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

2014-01-04 Thread spir

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

2014-01-04 Thread Alan Gauld

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

2014-01-04 Thread Steven D'Aprano
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