Benefit of initializing dictionary in function call - python

I was looking at this code on the Google Map API website:
import simplejson, urllib
GEOCODE_BASE_URL = 'http://maps.googleapis.com/maps/api/geocode/json'
def geocode(address,sensor, **geo_args):
geo_args.update({
'address': address,
'sensor': sensor
})
url = GEOCODE_BASE_URL + '?' + urllib.urlencode(geo_args)
result = simplejson.load(urllib.urlopen(url))
print simplejson.dumps([s['formatted_address'] for s in result['results']], indent=2)
if __name__ == '__main__':
geocode(address="San+Francisco",sensor="false")
I noticed that in the geocode function, when we actually apply the function we don't use the geo_args dictionary when we call the function, but we instead use it to initialize a dictionary we update in the next lines. What is the benefit of using this, as opposed to initializing the dictionary within the function itself? It makes the code a bit less clear so I assume there is a reason for doing it.

geo_args is used. The literal dictionary
{
'address': address,
'sensor': sensor
}
updates geo_args, not the other way around.
The reason it's like this looks to me that address and sensor are required arguments. This structure allows the function to enforce that requireness, and also allow them to be passed positionally. The .update() is just there to consolidate all the arguments into one so they can be given to urllib.urlencode.

Not clear? This is the normal behaviour of **kwargs (the keyword argument dictionary).
So when you see something with **, a bunch of named parameters or keyword arguments will be passed.
Seeing the other answers. I probably misunderstood your question. I agree with the other answers: address and sensor are required.

Related

I am a beginner in python where is the error

#python
sql="UPDATE bebliothequee SET title=:titl,author=:autho,ISBN=:ISB WHERE oid='{}'.format(oid.get())",title='{}'.format(title_editor.get()),author='{}'.format(author_editor.get()),ISBN='{}'.format(ISBN_editor.get()),oid='{}'.format(record_id.get())
Your first mistake is that you didn't read Stackoverflow documentation how to create good question. So you didn't add all details in question - and we can't read in your mind - and we can't help it.
Next mistake: you put code in comment but you should put it in question so it would be more readalbe but what is more important: all people could see it and help you.
Code shows that you try to create sql =... with all arguments for execute() and later use it in execute() but it doesn't work this way. You can't assing positional and named values to variable and later put it in function. You should use it directly in execute() or you should create list/tuple with positional variables and dictionary with named variables.
BTW: you don't need '{}'.format() to convert it to strings. You could use str() but I think execute() should convert it automatically.
query = "UPDATE bebliothequee SET title=:title, author=:author, ISBN=:ISBN WHERE oid=:oid"
execute(query, title=title_editor.get(), author=author_editor.get(), ISBN=ISBN_editor.get(), oid=record_id.get())
Other problem is that you use :titl but you should use full name :title like in argument title=....
You have also oid='{}'.format(oid.get() inside query which is totally useless.
BTW: Eventually you can create dictionary
args = {
'title': title_editor.get(),
'author', author_editor.get(),
'ISBN': ISBN_editor.get(),
'oid': record_id.get(),
}
and then you can use ** to unpack it as named arguments
execute(query, **args)

Mapping a returned string to a specific function

I have router that is deciding which function to call based upon user input (uses ConfigParser) and then tries to decide which function to call.
def SomethingElse():
print 'hello'
def UploadDirectory():
print 'hi'
def router(config):
if config.has_option('job', 'Some_Task'):
taskName = config.get('job', 'Some_Task')
# taskName is now 'UploadDirectory'
###execute the UploadDirectory function
###execute something else if something else, etc
So what is the way to write this in python? If I prebuilt a map of functions to strings, can i execute them that way?
How would you write this?
Yep, building a map of strings to function names is perfectly valid:
task_map = {
'upload': UploadDirectory,
'something': SomethingElse,
}
And execute as:
task_map[task_name]()
Aside: try to follow PEP-8, the python style guide; it helps make your code more readable to all other Python programmers. Specifically in this case, prefer underscore_separated function names instead of LeadingCaps.
Another hacky way to do it is to use globals(), if you're not running just by importing the router function:
globals()[taskName]()

How can I read a task's 'params' value during unit testing in App Engine

I am using Taskqueue stub in google app engine. It is very nice, but there is one thing that is driving me nuts.
During my test, a method I'm testing creates a task, and I want to check if that task has been created correctly. So, one of the things I have to check is that the proper 'params' have been passed. To do that, I do the following to get the task:
tasks = self.taskqueue_stub.GetTasks(queue_name)
self.assertEqual(1, len(tasks))
task = tasks[0]
But this task does not have a 'params' key, which is a shame, because that info is very valuable to assert that everything is fine.
Instead, the task has a 'body' key, which contains a base64 encoded version of the request body, something like this (once base64decoded):
muted=False&class_=Decoder&failures=3&last_orders=Key%28%27ProspectiveSale%27%2C+%27cl1%27%29&last_orderl=Key%28%27ProspectiveSale%27%2C+%27cl2%27%29&hit_per=5.0
I have tried to parse that to get the 'params' dict, but I'm finding it a bit tedious to parse all different items to their corresponding types, etc. Somehow, I feel that is just wrong, there has to be a simpler way to do this.
So, to consider this question as answered, I would need one of the following:
A way to read the 'params' dict.
A way to reconstruct the 'params' dict from the 'body' value mentioned above.
Another solution that I cannot imagine now but that would let me read that frikin 'params' dict ;-)
Cheers!
The urlparse module has a function for converting a parameter string to a dict: parse_qs.
For example:
import urlparse
params = 'muted=False&class_=Decoder&failures=3&last_orders=Key%28%27ProspectiveSale%27%2C+%27cl1%27%29&last_orderl=Key%28%27ProspectiveSale%27%2C+%27cl2%27%29&hit_per=5.0'
print urlparse.parse_qs(params)
prints the following:
{'muted': ['False'], 'class_': ['Decoder'], 'hit_per': ['5.0'], 'last_orders': ["Key(
'ProspectiveSale', 'cl1')"], 'last_orderl': ["Key('ProspectiveSale', 'cl2')"], 'failu
res': ['3']}

tornado maps GET and POST arguments to lists. How can I disable this "feature"?

The HTTPRequest class in the tornado* web framework helpfully maps GET and POST arguments to lists. I understand why -- in case a given argument name is used multiple times. But for some RequestHandlers, this is a pain. For instance, if I want to pass a json object and parse it as-is on the server.
What's the most straightforward way to disable the map-to-list behavior so that I can send unaltered json to a tornado/cyclone server?
*Cyclone, actually, in case there's an implementation difference here.
Instead of accessing self.request.arguments directly you should use the accessor functions:
self.get_argument("ID", default=None, strip=False)
This returns a single item.
If you want to turn the arguments into a JSON object you can quite easily do so:
json.dumps({ k: self.get_argument(k) for k in self.request.arguments })
I'm going to go with "you're out of luck." You could re-write the class in question (looks like that would not be fun), but aside from that I don't see many options.
I would just use a dict comprehension.
{k:''.join(v) for k,v in self.request.arguments.iteritems()}

Soap get arguments with wrong order in twisted

Now i use twisted.soap to build my soap server, I'd like to build a function with plural arguments like this:
def soap_searchFlight(self,name=None,startpoint=None,destination=None):
d=Deferred()
d.addCallback(functions.searchFlight)
d.addErrback(functions.failure)
print "name"+name
print "startpoint"+startpoint
print "destination"+destination
requestdic={"name":name,"startpoint":startpoint,"destination":destination}
print requestdic
d.callback(requestdic)
return d.result
and I wrote a script to test :
import SOAPpy
import twisted
p = SOAPpy.SOAPProxy('http://localhost:7080/')
p.config.dumpSOAPOut=1
p.config.dumpSOAPIn=1
print p.searchFlight(name='3548',startpoint="北京飞机场",destination="上海飞机场")
It gives me back like this:
name上海飞机场
startpoint北京飞机场
destination3548
it looks like the args order are totally wrong so what happens and how can i ensure the right order ?
Without seeing functions.searchFlight, it's a little hard to tell, but it appears that you're passing a dict to in in a callback, then assuming that the items in the dict are in a particular order (they're not).
Change the signature of functions.searchFlight to take a tuple, and call it with a tuple in the order you want. (or pass in an ordered dict...or don't assume the dict's items are in the order that you created it in).

Categories

Resources