7

Calling Python Methods - Subtleties with and without Parens

 3 years ago
source link: https://fuzzyblog.io/blog/python/2019/10/28/calling-python-methods-subtleties-with-and-without-parens.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Calling Python Methods - Subtleties with and without Parens

Oct 28, 2019

sifry_london_bar.jpg

Photo courtesy of my boss and friend, Dave Sifry who is in London right now attending MozFest; lucky guy!

In the continuing saga of "Once upon a time I did ruby exclusively, now I do python and ruby side by side and I keep being stupid", I have discovered something subtle and interesting about how python works internally.

Let's start with a function definition in python:

expert_name = "Anti Semitic Speech Expert"
expert_version = 0.01

def make_opinion_template():
    template = {}
    template["name"] = "slurs"
    template["raw"] = None    
    template["score"] = None
    template["opinion"] = None
    template["expert_name"] = expert_name
    template["expert_version"] = expert_version
    return template

The first two lines are globals and all the next line does is construct a hash (ok dict if I have to talk python). I then embedded this method in my service and ran it using Firefly so I could call into it across the network and I got this curious error:

  File "/Users/sjohnson/Sync/fuzzygroup/adl/antihate/antihate_experts/venv/lib/python3.7/site-packages/firefly/app.py", line 170, in __call__
    result = self.function(**kwargs)
  File "/Users/sjohnson/Sync/fuzzygroup/adl/antihate/antihate_experts/expert_antisemitic_speech_service.py", line 107, in opinion
    new_opinion["raw"] = json_results
TypeError: 'function' object does not support item assignment

but new_opinion isn't a function – it is a dict – so what the heck is going on???

Note: If you're an experienced Python wrangler, you already got it – I know, I know – I'm slow as hell at times particularly when it comes to syntax changes.

In ruby you can call methods with or without parens and the issue here is I had this syntax:

opinion_template = make_opinion_template

instead of:

opinion_template = make_opinion_template()

I simply forgot to add the parens when I called make_opinion_template. Sigh. The way I ultimately found this was to use a pdb.set_trace() call and evaluate opinion_template in the debugger.

> /Users/sjohnson/Sync/fuzzygroup/adl/antihate/antihate_experts/expert_antisemitic_speech_service.py(109)opinion()
-> new_opinion["raw"] = json_results
(Pdb) new_opinion
<function make_opinion_template at 0x13e328ef0>
(Pdb) quit()

and then, after the fix:

> /Users/sjohnson/Sync/fuzzygroup/adl/antihate/antihate_experts/expert_antisemitic_speech_service.py(109)opinion()
-> new_opinion["raw"] = json_results
(Pdb) new_opinion
{'name': 'slurs', 'raw': None, 'score': None, 'opinion': None, 'expert_name': 'Anti Semitic Speech Expert', 'expert_version': 0.01}

Personally I would have thought this would have been syntactically invalid but when a compile check didn't find an error:

python -m py_compile expert_antisemitic_speech_service.py

I am forced to admit that this must be lexically correct for some reason that I'm too unskilled at python to understand.

So, a short note to myself: Don't forget the parens when you call methods.


Posted In: #python


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK