Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
kwargs question
#4
In this expression "func" is the name of the function, a is a positional argument, args is a tuple of positional arguments, c is a keyword argument and kwargs is a dictionary of keyword arguments.
def func(a, *args, c=None, **kwargs):
    print("a", a)
    print("args", args)
    print("c", c)
    print("kwargs", kwargs)

func("Hello", "world", c="!", French="salut tout le monde")
Output:
a Hello args ('world',) c ! kwargs {'French': 'salut tout le monde'}
**kwargs is usually used to pass unused keyword arguments to the superclass __init__.
class A():
    def __init__(self, x=None, **kwargs):
        print("x =", x, "kwargs", kwargs)

class B(A):
    def __init__(self, y=None, **kwargs):
        super().__init__(**kwargs)
        print("y =", y, "kwargs", kwargs)

item = B(x=3.14, y=42)
Output:
x = 3.14 kwargs {} y = 42 kwargs {'x': 3.14}
B.__init__() pops "y" out of the keyword dictionary and passes it along to A.__init__(). The popping happens automatically because "y" is a keyward argument in A.__init__(). Here's an example that explicitly pops "z" out of kwargs before passing along to B.__init__().
class A():
    def __init__(self, x=None, **kwargs):
        print("x =", x, "kwargs", kwargs)

class B(A):
    def __init__(self, y=None, **kwargs):
        z = kwargs.pop("z")
        super().__init__(**kwargs)
        print("y =", y, "z=", z, "kwargs", kwargs)

item = B(x=3.14, y=42, z=1.618)
Output:
x = 3.14 kwargs {} y = 42 z= 1.618 kwargs {'x': 3.14}
The explicit remove of key/value pairs from kwargs is unusual, but it works just fine. Anything you can do with a dictionary you can do with kwargs. In this example A.__init__() does some processing on a keyword argument and passes it along.
class A():
    def __init__(self, x=None, **kwargs):
        print("x =", x, "kwargs", kwargs)

class B(A):
    def __init__(self, y=None, **kwargs):
        z = kwargs["z"]=round(kwargs["z"])
        super().__init__(**kwargs)
        print("y =", y, "kwargs", kwargs)

item = B(x=3.14, y=42, z=1.618)
Output:
x = 3.14 kwargs {'z': 2} y = 42 kwargs {'x': 3.14, 'z': 2}
This would normally be done by declaring a keyword argument in A.__init__()
class A():
    def __init__(self, x=None, **kwargs):
        print("x =", x, "kwargs", kwargs)

class B(A):
    def __init__(self, y=None, z=0, **kwargs):
        super().__init__(z=round(z), **kwargs)
        print("y =", y, "kwargs", kwargs)

item = B(x=3.14, y=42, z=1.618)
kwargs is really a dictionary. For proof, here is a function that creates a dictionary using kwargs.
def dictionary(**kwargs):
    return kwargs

constants = dictionary(pi=3.1416, Golden_ratio=1.618, Ultimate_answer=42)
print(constants)
print("pi =", constants["pi"])
Output:
{'pi': 3.1416, 'Golden_ratio': 1.618, 'Ultimate_answer': 42} pi = 3.1416
As to your question about how you could pass a bunch of options as arguments, you shouldn't. Functions should have few arguments. If your function has 5 or more arguments you should step back and review. "Is this the best way for me to do this?" "Are all these arguments confusing?" "Should all these arguments be attributes of my object, and should I set them independently of each other?

As to how you can pass a few values using keyword arguments, that is simple: keyward=value. If you want to configure a canvas object to have a blue background:
canvas = tk.Canvas(parent, bg="blue", width=200, height=150)
The argument/option names are described in the documentation of the Canvas class.

https://tkinter-docs.readthedocs.io/en/l...anvas.html
In this context "*" is the unpacking operator. *list unpacks the values from a list.
args = (1, 2, 3, 4)
print("args", args)
print("*args", *args)
a, b, c, d = args
print("a, b, c, d", a, b, c, d)
Output:
args (1, 2, 3, 4) *args 1 2 3 4 a, b, c, d 1 2 3 4
args is a tuple. That is why print surrounds the values by parenthesis when printing(args). *args unpacks the values returning the numbers 1, 2, 3, 4. When you print *args, parenthesis do not appear in the output. You can also unpacking during assignment. "a, b, c, d = args" unpacks the values of args into the variables a, b, c, d.

**kwargs unpacks a dictionary.
def myprint(one, two, three):
    print("**kwargs", one, two, three)

kwargs = {"one":1, "two":2, "three":3}
print("kwargs", kwargs)
print("*kwargs", *kwargs)
myprint(**kwargs)
Output:
kwargs {'one': 1, 'two': 2, 'three': 3} *kwargs one two three **kwargs 1 2 3
I could not "print(**kwargs)" because unpacking kwargs produces:
print(one=1, two=2, three=3)
The print function does not have keyword arguments one, two and three, so it raises an InvalidKeyword argument. To get around the problem I created a print function with the appropriate arguments.
Reply


Messages In This Thread
kwargs question - by Jeff_t - Feb-15-2022, 07:25 PM
RE: kwargs question - by menator01 - Feb-15-2022, 07:45 PM
RE: kwargs question - by Jeff_t - Feb-15-2022, 08:38 PM
RE: kwargs question - by deanhystad - Feb-15-2022, 08:48 PM
RE: kwargs question - by Jeff_t - Feb-15-2022, 09:04 PM
RE: kwargs question - by deanhystad - Feb-15-2022, 09:10 PM
RE: kwargs question - by stevendaprano - Feb-16-2022, 10:59 AM
RE: kwargs question - by snippsat - Feb-16-2022, 03:31 PM
RE: kwargs question - by Jeff_t - Feb-16-2022, 04:33 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  How do I instantiate a class with **kwargs? palladium 6 7,732 Feb-16-2023, 06:10 PM
Last Post: deanhystad
  Misunderstanding kwargs? Donovan 2 2,315 Aug-04-2020, 08:09 PM
Last Post: Donovan
  **kwargs question DPaul 10 4,516 Apr-01-2020, 07:52 AM
Last Post: buran
  Unpacking dictionary from .xlsx as Kwargs etjkai 5 2,947 Dec-27-2019, 05:31 PM
Last Post: etjkai
  opts vs kwargs Skaperen 4 2,543 Nov-30-2019, 04:57 AM
Last Post: Skaperen
  create dictionary from **kwargs that include tuple bluefrog 2 4,935 Oct-26-2016, 10:24 PM
Last Post: Larz60+
  How do you use *args and **kwargs? Gengar 3 20,004 Sep-20-2016, 04:22 PM
Last Post: Ofnuts

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020