Передача осей как **kwarg в Python

Я создаю оболочку для создания графиков в Matplotlib и хочу иметь возможность необязательно указывать оси, по которым строить график.

Например, у меня есть:

def plotContourf(thing, *argv, **kwargs):
    return plt.tricontourf(thing[0], thing[1], thing[2], *argv, **kwargs)

def plotScatter(thing, *argv, **kwargs )
    return plt.scatter(thing[0], thing[1], *argv, **kwargs)

fig, ((ax0,ax1),(ax2,ax3)) = plt.subplots(2,2)

plotContourf(some_thing, axes=ax0)
plotScatter(some_thing, axes=ax2)

Который работает, но все отображается на самых последних осях (ax3), а не в осях, указанных через kwargument осей. (Здесь нет ошибок, он просто появляется на неправильных осях)

Для любопытных, причина, по которой я хочу сделать это, заключается в том, чтобы пользователь мог либо установить оси, либо для ленивых людей они могут просто вызвать plotContourf() без указанных осей и все равно получить что-то, что они могут plt.show( )

С другой стороны, я пытался

def plotContourf(thing, axes=None, *argv, **kwargs):
    if axes is None:
        fig, axes = plt.subplots()

    return axes.tricontourf(thing[0], thing[1], thing[2], *argv, **kwargs)

Но потом я получаю:

TypeError: plotContourf() получил несколько значений для аргумента ключевого слова «оси»

Я понимаю, что эта ошибка связана с тем, что «оси» уже являются аргументом ключевого слова. Я знаю, что могу использовать другое ключевое слово, но тогда какая польза от осей kwarg?

Спасибо!

EDIT: Полная трассировка (для второго варианта, описанного выше):

Traceback (most recent call last):
  File "mods.py", line 51, in <module>
    adcirc.plotContourf(hsofs_mesh, -1*hsofs_mesh['depth'], axes=ax0)
TypeError: plotContourf() got multiple values for keyword argument 'axes'

И собственно обертка:

def plotContourf(grid, axes=None, *argv, **kwargs): 
    if axes is None:
        fig, axes = plt.subplot()
    return axes.tricontourf(grid['lon'], grid['lat'], grid['Elements']-1, *argv, **kwargs)

person Reniel Calzada    schedule 15.08.2017    source источник
comment
Ошибка не связана с тем, что axes является аргументом ключевого слова. Вы фактически звоните plotContourf(axes=something, exes=somethingelse).   -  person Jim Wright    schedule 15.08.2017
comment
Можете ли вы показать логику, где вы получаете ошибку?   -  person Jim Wright    schedule 15.08.2017
comment
Извините, я только что заметил несколько опечаток в своем вопросе, а именно, что в ответе у меня было ** argv вместо * argv. Я только что отредактировал, чтобы исправить это. Однако проблема все еще стоит. Можете ли вы помочь мне лучше понять, что вы имеете в виду под своим первым комментарием? Кроме того, единственное сообщение об ошибке, которое я получаю, это TypeError: plotContourf() получил несколько значений для аргумента ключевого слова «оси», и это только при использовании моего второго варианта. Я хотел бы найти причину, по которой использование axes=ax_instance не работает...   -  person Reniel Calzada    schedule 15.08.2017
comment
Поместите фактическую трассировку стека в вопрос.   -  person Jim Wright    schedule 15.08.2017
comment
Не решение, но вы должны использовать if axes is None: или if not axes:   -  person Cory Madden    schedule 15.08.2017
comment
Никакой трассировки стека, кроме: TypeError: plotContourf() получил несколько значений для аргумента ключевого слова «оси» при использовании второго варианта, в то время как первый фактически рисует, но все на последних осях (ax3) ... @CoryMadden, да, извините, это еще одна опечатка здесь, я отредактировал.   -  person Reniel Calzada    schedule 15.08.2017
comment
@RenielCalzada Ваша ошибка должна сопровождаться трассировкой, как в этом сообщении: stackoverflow.com/questions/45697169/   -  person Cory Madden    schedule 15.08.2017
comment
@CoryMadden, я добавил полную трассировку + фактическую функцию точно так, как она написана в моем модуле. Спасибо!   -  person Reniel Calzada    schedule 15.08.2017


Ответы (2)


Проблема в том, что вы вызываете функцию с -1*hsofs_mesh['depth'] вместо axes, а затем снова добавляете аргумент ключевого слова axes в конце.

In [10]: def fun(a, x=1, *args, **kwargs):
    ...:     print(x)
    ...:     

In [11]: fun(1, 3, x=4)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-11-31b5e42fb4be> in <module>()
----> 1 fun(1, 3, x=4)

TypeError: fun() got multiple values for keyword argument 'x'

Посмотрите, в этом примере 3 читается как x, а затем я передаю x=4. Причина ошибки, с которой вы столкнулись.

Решением было бы добавить еще один аргумент в вашу функцию следующим образом:

def plotContourf(thing, other_thing=None, axes=None, *argv, **kwargs):
person Cory Madden    schedule 15.08.2017
comment
Это многое проясняет, спасибо!! - person Reniel Calzada; 15.08.2017

Вы вполне можете оставить axes в качестве аргумента ключевого слова, что избавит вас от необходимости думать о порядке других аргументов.

import matplotlib.pyplot as plt
import numpy as np

def plotContourf(thing, *argv, **kwargs):
    axes = kwargs.pop("axes", None)
    if not axes:
        fig, axes = plt.subplots()

    return axes.tricontourf(thing[0], thing[1], thing[2], *argv, **kwargs)

a = [np.random.rand(10) for i in range(3)]
plotContourf(a) 

#or

fig, ax = plt.subplots()
plotContourf(a, axes=ax)

plt.show()
person ImportanceOfBeingErnest    schedule 16.08.2017
comment
На самом деле это тоже очень важный момент. В этом случае я выбрал другой ответ как принятый ответ, потому что в моем конкретном случае есть некоторая логика в порядке, в котором мы передаем эти аргументы. Думаю, Кори Мэдден понял, чего я пытался добиться, когда предложил использовать other_thing=None. Однако у меня есть много других функций, в которых нет определенного логического порядка во входных аргументах, поэтому этот метод пригодится для таких случаев. Большое спасибо, я тоже кое-что узнал из вашего предложения. - person Reniel Calzada; 16.08.2017
comment
Конечно, в другом ответе есть еще несколько объяснений. Я добавил это, сосредоточившись на том, о чем просил заголовок, т. Е. Передавая оси как kwarg. Но вы совершенно вольны выбирать, какой ответ принять. Вы по-прежнему можете голосовать за каждый ответ, который вы считаете полезным (голоса будут сохранены и подсчитаны, как только ваша репутация повысится). - person ImportanceOfBeingErnest; 16.08.2017