I'm learning Python, and found a fun little video on YouTube called "Learn Python through public data hacking". In essence it uses the CTA unofficial API to do some parsing of XML data. In taking things further than inline code, I'm chunking behaviors into modules and classes to further understand how Python works.
The XML from the API looks something like this:
<buses rt="22">
<time>1:40 AM</time>
<bus>
<id>4194</id>
<rt>22</rt>
<d>East Bound</d>
<dd>Northbound</dd>
<dn>E</dn>
<lat>41.88327006970422</lat>
<lon>-87.62828115689553</lon>
<pid>5421</pid>
<pd>Northbound</pd>
<run>P238</run>
<fs>Howard</fs>
<op>49875</op>
<dip>5314</dip>
<bid>7323287</bid>
<wid1>0P</wid1>
<wid2>238</wid2>
</bus>
<!-- bus... n -->
</buses>
I'm using the python-requests module for the HTTP side, and once the XML is downloaded, I parse each <bus>
node into a Bus
class, assign each of the child nodes into a dictionary, and make that visible with a get(prop)
statement, so I can just call bus.get('lat')
to retrieve the latitude, etc. However, in order to do the correct calculations on it (i.e. arithmetic) each node's value needs to be returned as the correct type. By default, they're all read as strings.
Considering that Python doesn't have a "switch" statement like most other languages, someone at SO said to use a dictionary. Is this the/a correct way of doing something like this? Or is there some nifty builtin that I don't know of?
def dyncast(value):
_type = type(value)
types = {
"FloatType": (r'^[\d]{2}\.[\d]+$', lambda f : float(f)),
"IntType" : (r'^[\d]+$', lambda i : int(i)),
"StrType" : (r'^[a-zA-z]+$', lambda s : str(s))
}
for typeval in types:
pattern = types[typeval][0]
fn = types[typeval][1]
match = re.match(pattern, value)
# if it matches a regex and has a group(), return the
# lambda calculation (typecast)
if match and match.group():
return fn(value)
# return straight up if no matches
return value
# Called via:
for elm in node:
self._data[elm.tag] = dyncast(elm.text)
# where node is the bus node, and elm are the child nodes
It seems to work well, as I get returns such as:
# print bus.get('fs'), type(bus.get('fs'))
Harrison <type 'str'>
# print bus.get('lat'), type(bus.get('lat'))
41.9027030677 <type 'float'>