Распространение аргументов функции в теле - PullRequest
0 голосов
/ 19 июня 2020

Возможно, глупый вопрос, но задается из любопытства

In, python Я могу распространить *args и **kwargs в сигнатуре функции

def my_func(foo, bar):
   print(f"foo={foo}, bar={bar}")

my_func(1, 2)          # 1 2
my_func(1, bar=2)      # 1 2
my_func(foo=1, bar=2)  # 1 2

Можно ли выложить его в теле функции примерно так?

def my_func(*args, **kwargs):
   foo, bar = *args, **kwargs       <=== Something like this

   print(f"foo={foo}, bar={bar}")

my_func(1, 2)          # 1 2
my_func(1, bar=2)      # 1 2
my_func(foo=1, bar=2)  # 1 2

Ответы [ 3 ]

1 голос
/ 19 июня 2020

args - это кортеж, а не foo.

kwargs - это dict, а не значение bar.

def my_func(*args, **kwargs):
   foo = args[0]  # Assumes there is at least one positional argument
   bar = kwargs['bar']  # Assumes there is a keyword argument named bar

   print(f"foo={foo}, bar={bar}")

my_func(1, bar=2)                   # 1 2

Если вы для go используете подпись, вы должны четко указать сопоставление позиционных аргументов с именами. Например,

def my_func(*args, **kwargs):
    if len(args) == 0 and `foo` not in kwargs:
        raise TypeError("Missing argument for 'foo'")
    else:
        try:
            foo = args[0]
        except IndexError:
            foo = kwargs['foo']

    if len(args) == 1 and `bar` not in kwargs:
        raise TypeError("Missing argument for 'bar'")
    else:
        try:
            bar = args[1]
        except IndexError:
            bar = kwargs['bar']

    ....

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

def my_func(*args, **kwargs):
    if len(args) == 0 and `foo` not in kwargs:
        raise TypeError("Missing argument for 'foo'")
    else:
        try:
            foo = kwargs['foo'
        except IndexError:
            foo = args[0]

    if len(args) == 1 and `bar` not in kwargs:
        raise TypeError("Missing argument for 'bar'")
    else:
        try:
            bar = kwargs['bar']
        except IndexError:
            bar = args[1]

    ....

или продолжали рассматривать попытку использования обоих как ошибку:

def my_func(*args, **kwargs):
    if len(args) == 0 and `foo` not in kwargs:
        raise TypeError("Missing argument for 'foo'")
    elif len(args) > 0 and `foo` in kwargs:
        raise TypeError("Multiple attempts to assign foo")
    else:
        try:
            foo = args[0]
        except IndexError:
            foo = kwargs['foo']

    if len(args) == 1 and `bar` not in kwargs:
        raise TypeError("Missing argument for 'bar'")
     elif len(args) > 1 and `bar` in kwargs:
        raise TypeError("Multiple attempts to assign bar")      
    else:
        try:
            bar = args[1]
        except IndexError:
            bar = kwargs['bar']

    ....
0 голосов
/ 19 июня 2020

Основная проблема заключается в том, что при объявлении функции с помощью (*args, **kwargs) нет внутреннего упорядочивания до foo и bar, если мы позже не наложим его в теле функции. Но мы могли бы сделать что-то вроде этого:

def my_func(*args, **kwargs):

    # we didn't say in the declaration what the arguments
    # were meant to be, but now we want to impose an
    # interpretation on the args,

    params = ["foo", "bar"]
    argsd = dict(zip(params, args))

    # and fold in the kwargs
    argsd.update(kwargs)

    # unpack into variables, choosing names based on the 
    # params that we are using (this rather assumes that 
    # the params list has been hard-coded because we wouldn't
    # want to try naming the local variables dynamically)

    foo, bar = [argsd[k] for k in params]
    print(f"foo={foo}, bar={bar}, args={args}, kwargs={kwargs}")


my_func(1, 2)  
my_func(1, bar=2)  
my_func(foo=1, bar=2)  
my_func(bar=2, foo=1)  

Вывод:

foo=1, bar=2, args=(1, 2), kwargs={}
foo=1, bar=2, args=(1,), kwargs={'bar': 2}
foo=1, bar=2, args=(), kwargs={'foo': 1, 'bar': 2}
foo=1, bar=2, args=(), kwargs={'bar': 2, 'foo': 1}
0 голосов
/ 19 июня 2020

* args - это просто кортеж, а ** kwargs - просто dict. Вы можете использовать их как любые другие.

for arg in args:

for name, arg in kwargs.items():

Вот руководство по этому поводу:

https://www.digitalocean.com/community/tutorials/how-to-use-args-and-kwargs-in-python-3#: ~: text = Понимание% 20 ** kwargs, а не% 20enced% 20by% 20the% 20language.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...