I am using Python 3.5
. I would like to create a factory where local variables of the outer function can be overwritten by user kwargs.
When doing so, I found out that some variable are not defined in the inner scope without apparent reasons.
Here is a MWE of the function factory:
def TicksFormatterFactory( \
title=None, target='xaxis', limits=100 \
,major_locator=None, major_format=None, major_gridstyle=None, major_rotation=90, major_fontsize=7 \
,minor_locator=None, minor_format=None, minor_gridstyle=None, minor_rotation=None, minor_fontsize=None \
,title_kw=dict() \
):
pprint.pprint(locals()) # (1)
varKeys = locals().keys() # (2)
def inner(axe, **kwargs):
pprint.pprint(locals()) # (5)
# Allow User to overwrite settings using kwargs:
settings = dict()
for k in varKeys:
settings[k] = kwargs.get(k, locals().get(k)) # (3)
pprint.pprint(settings) # (4)
return inner
A simple call to the factory and its inner function:
test = TicksFormatterFactory(minor_fontsize=4)
fig, axe = plt.subplots()
test(axe, title='Hello world')
Leads to:
# (1)
{'limits': 100,
'major_fontsize': 7,
'major_format': None,
'major_gridstyle': None,
'major_locator': None,
'major_rotation': 90,
'minor_fontsize': 4,
'minor_format': None,
'minor_gridstyle': None,
'minor_locator': None,
'minor_rotation': None,
'target': 'xaxis',
'title': None,
'title_kw': {}}
# (5)
{'axe': <matplotlib.axes._subplots.AxesSubplot object at 0x0000027793B02BE0>,
'kwargs': {'title': 'Hello world'},
'major_fontsize': 7,
'major_format': None,
'major_gridstyle': None,
'major_locator': None,
'major_rotation': 90,
'minor_fontsize': 4,
'minor_format': None,
'minor_gridstyle': None,
'minor_locator': None,
'minor_rotation': None,
'target': 'xaxis',
'varKeys': dict_keys(['major_gridstyle', 'major_format', 'minor_format', 'target', 'minor_gridstyle', 'major_fontsize', 'minor_rotation', 'minor_locator', 'major_rotation', 'major_locator', 'title_kw', 'title', 'limits', 'minor_fontsize'])}
# (4)
{'limits': None,
'major_fontsize': 7,
'major_format': None,
'major_gridstyle': None,
'major_locator': None,
'major_rotation': 90,
'minor_fontsize': 4,
'minor_format': None,
'minor_gridstyle': None,
'minor_locator': None,
'minor_rotation': None,
'target': 'xaxis',
'title': 'Hello world',
'title_kw': None}
What I have seen deeper:
Variable pointed by 'limits'
key is not defined in inner scope:
locals()[k] # (3')
Fails for 'limits'
key (in fact the third factory parameter, whatever it is called is not passed to inner). This is why I have changed from # (3')
to # (3)
and I must store keys from outer scope with # (2)
in order to keep track of keys and make the MWE working.
This is totally puzzling me!
My question is: Why some of my locals variable does not reach the inner scope of my factory?
I tried your MWE and it gave me different results (Python 3.5.2):
Which is what I expected. Calling
locals()
insideinner
shouldn't return the outer function's parameters, simply because they're not local toinner
unless you reference them.You need to access
TicksFormatterFactory
's locals this way:Which yields: