Python

Special syntax (*args, **kwargs) in Python 3

1- In function calls

Dùng để unpack iterables và dictionaries thành các phần tử riêng biệt (arguments), chúng ta sử dụng operator *X (dùng cho iterable) và **X (dùng cho dictionary).

Example 1:

def demo(a,b,c,d):
    print(a,b,c,d)
d = {'c':3, 'd':4}
demo(*[1,2,3,4])
demo(1,*[2,3,4])
demo(1,2,**d)

Output:
1, 2, 3, 4
1, 2, 3, 4
1, 2, 3, 4

Như kết quả nhận được, các list và dictionary được tách thành các phần tử riêng biệt để trở thành tham số của function demo().

Chú ý: các key trong dictionary cần tương ứng với các tham số của function.


2- Extended sequence assignment

Example 2:

a, *b, c = range(10)
print(a,b,c)
*d, e = "ntppro"
print(d,e)

Output:
0 [1, 2, 3, 4, 5, 6, 7, 8] 9
[‘n’, ‘t’, ‘p’, ‘p’, ‘r’] ‘o’
Với kết quả trên ta thấy rằng biến a được gán với phần tử đầu tiên, biến c được gán với phần tử cuối cùng, còn lại được gán cho b ở dạng list. Tương tự với các biến de.

Chú ý: trong một phép gán chỉ cho phép tối đa một *argument.


3- *args in function headers

Collect extra positional arguments as a new tuple. Được dùng để tạo non-keyword variable-argument function.

Example 3:

def demoA(a,*b):
    print(a,b)
def demoB(*args):
    print(args)
def demoC(a,*b,c):
    print(a,b,c)

demoA(1,2,3,4,5)
demoB(1,2,3,4,5)
demoC(1,2,3,4,c=5)

Output:
1 (2, 3, 4, 5)
(1, 2, 3, 4, 5)
1 (2, 3, 4) 5

Đối với function demoA, tham số đầu tiên sẽ được gán vào biến a, tất cả tham số còn lại sẽ được gom vào tuple b.

Đối với function demoB, tất cả tham số đều được gom vào tuple args, vì không cần quan tâm đến số lượng tham số được truyền vào nên demoB là variable-argument function.

Đối với function demoC, tham số c chính là ‘Keyword-only arguments’ (only in Python 3) vì c nằm ngay sau *b, tham số c cần được truyền vào function demoC bởi keyword c (trong ví dụ là c=5) và là tham số bắt buộc nếu không có default. Như vậy, tham số đầu tiên sẽ được gán vào biến a, 3 tham số tiếp theo được gom vào tuple b và c = 5.

Example 4: optional keyword-only argument

>>> def demoD(a, *b, c=None)
...    print(a,b,c)
>>> demoD(1,2,3,4,c=5)
1 (2, 3, 4) 5
>>> demoD(1,2,3)
1 (2, 3) None

Chú ý một xíu chúng ta sẽ thấy rằng mục đích của * syntax trong function call và function header là tương phản nhau. Trong function call, * syntax dùng để unpack các iterables hoặc dictionaries thành các tham số riêng biệt dùng trong function. Ngược lại, trong function header, * syntax dùng để gom tất cả các unmatched arguments vào một tuple.


4- **kwargs in function headers

Collect extra keyword arguments as a new dictionary. Được dùng để tạo keyword variable-argument function.

Example 5:

def print_kwargs(**kwargs):
    print(kwargs)
print_kwargs(A=65, B=66, C=67)

Output:
{‘C’:67, ‘B’:66, ‘A’:65}

Với kết quả nhận được, ta thấy rằng các keyword-argument truyền vào function print_kwargs() đã được gom vào một dictionary và chúng ta có thể thao tác trên dictionay này tương tự như các dictionary bình thường khác.

Example 6:

def print_kwargs(**kwargs):
    for key,value in kwargs.items():
        print("The value of {} is {}".format(key, value))

print_kwargs(A=65, B=66, C=67)

Output:
The value of C is 67
The value of B is 66
The value of A is 65


Ordering Arguments

When ordering arguments within a function or function call, arguments need to occur in a particular order:

  1. Positional arguments.
  2. *args
  3. Keyword-only arguments.
  4. **kwargs

It is important to keep the order of arguments in mind when creating functions so that you do not receive a syntax error in your Python code.

Example 7:

def multiArgument(positional, *args, keywordonly=None, **kwargs):
    print(positional, args, keywordonly, kwargs, sep='\n')

multiArgument(100, 10, 20, 30, keywordonly="Hello guys", a=97,b=98,c=99)

Output:
100
(10, 20, 30)
Hello guys
{‘b’:98, ‘c’:99, ‘a’:97}


5- In data structure

Từ Python 3.4 chúng ta có thể sử dụng cú pháp *X và **X để unpack iterables và dictionaries thành các phần tử riêng biệt từ bên trong các cấu trúc dữ liệu như List, Tuple, Set và Dictionary.

Example 8:

>>> dictA = {'A':65, 'B':66}
>>> dictB = {'C':67, 'D':68}
>>> dictC = {**dictA, **dictB}
>>> print(dictC)
{'A':65, 'B':66, 'C':67, 'D':68}
>>> listA = [1,2,3,4]
>>> listB = [5,6,7,8]
>>> listC = [listA, *listB]
>>> print(listC)
[[1, 2, 3, 4], 5, 6, 7, 8]

Qua bài viết này chúng ta đã tìm hiểu về cách sử dụng *args**kwargs để tạo variable-argument function, cũng như cách sử dụng trong function calls. Cảm ơn các bạn đã theo dõi bài viết của mình.

Thân ái và quyết thắng.

Reference:
[1] How To Use *args and **kwargs in Python 3.
[2] The Assignment Statement.
[3] The Expression Statement.
[4] The def Statement.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s