0

我正在使用Python 3.5. 我想创建一个工厂,其中外部函数的局部变量可以被用户 kwargs 覆盖。

这样做时,我发现某些变量没有在内部范围内定义而没有明显的原因。

这是函数工厂的 MWE:

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

对工厂及其内部函数的简单调用:

test = TicksFormatterFactory(minor_fontsize=4)
fig, axe = plt.subplots()
test(axe, title='Hello world')

导致:

# (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}

我看到的更深:

键指向的变量'limits'未在内部范围内定义:

locals()[k] # (3')

键失败'limits'(实际上是第三个工厂参数,无论它被调用什么都不会传递给内部)。这就是为什么我从# (3') to更改为,# (3)并且我必须从外部范围存储密钥,# (2)以便跟踪密钥并使 MWE 工作。

这完全让我感到困惑!

我的问题是:为什么我的一些 locals 变量没有到达我工厂的内部范围?

4

1 回答 1

1

我尝试了你的 MWE,它给了我不同的结果(Python 3.5.2):

>>> test = TicksFormatterFactory(minor_fontsize=4)
{'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': {}}
>>> test(1, title='Hello')
{'axe': 1,
 'kwargs': {'title': 'Hello'},
 'varKeys': dict_keys(['title_kw', 'minor_fontsize', 'minor_rotation', 'minor_gridstyle', 'minor_format', 'minor_locator', 'major_fontsize', 'major_rotation', 'major_gridstyle', 'major_format', 'major_locator', 'limits', 'target', 'title'])}
{'limits': None,
 'major_fontsize': None,
 'major_format': None,
 'major_gridstyle': None,
 'major_locator': None,
 'major_rotation': None,
 'minor_fontsize': None,
 'minor_format': None,
 'minor_gridstyle': None,
 'minor_locator': None,
 'minor_rotation': None,
 'target': None,
 'title': 'Hello',
 'title_kw': None}

这是我所期望的。locals()内部调用inner不应返回外部函数的参数,因为inner除非您引用它们,否则它们不是本地的。

您需要以TicksFormatterFactory这种方式访问​​ 's locals:

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)
    localVars = locals() # (2)
    def inner(axe, **kwargs):

        pprint.pprint(locals())   # (5)

        # Allow User to overwrite settings using kwargs:
        settings = dict()
        for k in localVars:
            settings[k] = kwargs.get(k, localVars.get(k)) # (3)

        pprint.pprint(settings) # (4)

    return inner

产生:

>>> test = TicksFormatterFactory(minor_fontsize=4)
{'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': {}}
>>> test(1, title='Hello')
{'axe': 1,
 'kwargs': {'title': 'Hello'},
 'localVars': {'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': {}}}
{'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': 'Hello',
 'title_kw': {}}
于 2017-05-31T08:38:57.043 回答