Hướng dẫn python call function with variable arguments - hàm gọi python với các đối số biến

Cách đơn giản nhất để bọc một hàm

    func(*args, **kwargs)

... là viết thủ công một trình bao bọc sẽ gọi func () bên trong chính nó:

    def wrapper(*args, **kwargs):
        # do something before
        try:
            return func(*a, **kwargs)
        finally:
            # do something after

Trong hàm Python là một đối tượng, vì vậy bạn có thể chuyển tên của nó như một đối số của một hàm khác và trả về nó. Bạn cũng có thể viết trình tạo trình bao bọc cho bất kỳ chức năng nào anyfunc ():

    def wrapperGenerator(anyFunc, *args, **kwargs):
        def wrapper(*args, **kwargs):
            try:
                # do something before
                return anyFunc(*args, **kwargs)
            finally:
                #do something after
        return wrapper

Cũng xin lưu ý rằng trong Python khi bạn không biết hoặc không muốn đặt tên cho tất cả các đối số của một hàm, bạn có thể tham khảo một bộ lý đối số, được ký hiệu bằng tên của nó, trước dấu hoa thị trong dấu ngoặc đơn sau Tên chức năng:

    *args

Ví dụ: bạn có thể xác định một hàm sẽ lấy bất kỳ số lượng đối số nào:

    def testFunc(*args):
        print args    # prints the tuple of arguments

Python cung cấp cho thao túng hơn nữa trên các đối số chức năng. Bạn có thể cho phép một chức năng lấy các đối số từ khóa. Trong cơ thể chức năng, các đối số từ khóa được giữ trong một từ điển. Trong dấu ngoặc đơn sau tên hàm này từ điển này được ký hiệu là hai dấu hoa thị theo sau là tên của từ điển:

    **kwargs

Một ví dụ tương tự in từ điển từ khóa đối số:

    def testFunc(**kwargs):
        print kwargs    # prints the dictionary of keyword arguments

Một câu chuyện ngắn về *args và ** kwargs

Hình ảnh được thực hiện bởi tác giả

Trong bài viết này, chúng tôi sẽ tìm hiểu về *args và ** kwargs, hai biểu tượng Python đặc biệt mà bạn có thể gặp phải trong một số chữ ký chức năng trước đây.

Họ làm gì? Họ giải quyết vấn đề gì? Và làm thế nào bạn sẽ sử dụng chúng để cải thiện tính linh hoạt của mã của bạn?

Chúng tôi sẽ trả lời những câu hỏi này. 📚

Số lượng đối số khác nhau trong các hàm Python

Tiêu đề là một loại spoiler: *Args và ** kwargs cho phép bạn chuyển một số lượng đối số thay đổi cho các chức năng của bạn. Nhưng chúng tôi sẽ nhận được điều đó.*args and **kwargs allow you to pass a variable number of arguments to your functions. But we’ll get to that.

Hiện tại, hãy để Lôi nhìn vào một số chức năng phổ biến có tính linh hoạt này và hãy để Lôi nghĩ về cách bạn cũng có thể hưởng lợi từ nó.

Nếu bạn quen thuộc với ngôn ngữ lập trình Python, có lẽ bạn sẽ biết hai chức năng sau:

1-Hàm

    def wrapperGenerator(anyFunc, *args, **kwargs):
        def wrapper(*args, **kwargs):
            try:
                # do something before
                return anyFunc(*args, **kwargs)
            finally:
                #do something after
        return wrapper
6 tích hợp nổi tiếng nổi tiếng:The notoriously famous built-in
    def wrapperGenerator(anyFunc, *args, **kwargs):
        def wrapper(*args, **kwargs):
            try:
                # do something before
                return anyFunc(*args, **kwargs)
            finally:
                #do something after
        return wrapper
6 function:

Như tên chỉ ra rõ ràng, hàm này in dữ liệu vào đầu ra tiêu chuẩn. Nhưng bạn có biết rằng nó cũng có thể lấy bất kỳ số lượng đối số (để in) không?

print("hello")
# hello
print("hello", "there")
# hello there
print("I", "have", 5, "dollars")
# I have 5 dollars
print("a", 2, [1, 2, 3])
# a 2 [1, 2, 3]
...

2 - Hàm

    def wrapperGenerator(anyFunc, *args, **kwargs):
        def wrapper(*args, **kwargs):
            try:
                # do something before
                return anyFunc(*args, **kwargs)
            finally:
                #do something after
        return wrapper
7 từ mô -đun
    def wrapperGenerator(anyFunc, *args, **kwargs):
        def wrapper(*args, **kwargs):
            try:
                # do something before
                return anyFunc(*args, **kwargs)
            finally:
                #do something after
        return wrapper
8:
The
    def wrapperGenerator(anyFunc, *args, **kwargs):
        def wrapper(*args, **kwargs):
            try:
                # do something before
                return anyFunc(*args, **kwargs)
            finally:
                #do something after
        return wrapper
7 function from the
    def wrapperGenerator(anyFunc, *args, **kwargs):
        def wrapper(*args, **kwargs):
            try:
                # do something before
                return anyFunc(*args, **kwargs)
            finally:
                #do something after
        return wrapper
8 module:

Hàm này tham gia một số lượng đường dẫn tùy ý trên hệ thống tập tin. Tương tự như vậy, nó chấp nhận một số lượng đường dẫn là đối số.

import ospath2 = os.path.join("/")
path2 = os.path.join("/", "Users")
path3 = os.path.join("/", "Users", "Library")
# ...

Sử dụng một hàm chấp nhận một số lượng đối số có thể rất hữu ích: điều này cung cấp rất nhiều tính linh hoạt và giảm sự lộn xộn trong chữ ký hàm. Ngoài ra, nó không đưa ra bất kỳ giả định nào về số lượng các đối số cần thiết, có thể phù hợp trong nhiều kịch bản.

Có nhiều tình huống mà bạn cần sử dụng một chức năng có số lượng đối số khác nhau.

Hãy để lấy một ví dụ: Hãy tưởng tượng rằng bạn muốn xây dựng một hàm tính toán một tập hợp số (trung bình, tổng, nhân, v.v.) trên một số số. Xem xét phép nhân cho đơn giản (cùng áp dụng cho các tập hợp khác).
Consider the multiplication for simplicity (the same applies to the other aggregations).

Nếu bạn muốn xác định một hàm nhân lên hai số, bạn có thể chỉ cần làm như thế này:

def multiply_numbers(n1, n2):
product = n1 + n2
return product

Điều này hoạt động tốt nhưng làm thế nào về việc nhân ba số thay thế? hoặc bốn? hoặc một nghìn?

Một giải pháp tự nhiên mà bạn có thể nghĩ đến là đặt tất cả các số vào một danh sách và chuyển nó cho chức năng:

    def wrapper(*args, **kwargs):
        # do something before
        try:
            return func(*a, **kwargs)
        finally:
            # do something after
0

Mặc dù giải pháp này hoạt động, nhưng nó có thể hơi bất tiện và không linh hoạt hơn lắm nếu bạn không biết trước tất cả các yếu tố đi vào danh sách của bạn. Bên cạnh đó, nó buộc bạn phải tạo một đối tượng danh sách có vẻ không cần thiết.

Vượt qua các đối số không phải là Keyword với *args

*Args: Bạn có thể đã thấy đối số kỳ lạ này được sử dụng trong các chức năng trước đây nhưng bạn chưa bao giờ hiểu tất cả những gì về nó. you may have seen this strange argument used in functions before but you never understood what it was all about.

Chà, sử dụng *args trong một hàm là cách Python để nói rằng điều này sẽ:

  1. Chấp nhận một số lượng đối số tùy ý
  2. Đóng gói các đối số nhận được trong một tuple có tên Args. Lưu ý rằng Args chỉ là một cái tên và bạn có thể sử dụng bất cứ thứ gì bạn muốn thay thế. (Chúng tôi sẽ thấy một ví dụ ở bên dưới)tuple named args. Note that args is just a name and you can use anything you want instead. (we’ll see an example down below)

Hãy để ném một số mã để làm cho mọi thứ rõ ràng.

Hãy để xác định một hàm gói đối số trong một biến ARGS và in cái này vào bảng điều khiển. Không có gì lạ mắt.

    def wrapper(*args, **kwargs):
        # do something before
        try:
            return func(*a, **kwargs)
        finally:
            # do something after
1

Nếu chúng ta vượt qua một số lượng đối số tùy ý:

    def wrapper(*args, **kwargs):
        # do something before
        try:
            return func(*a, **kwargs)
        finally:
            # do something after
2

Chúng tôi sẽ thấy rõ rằng tất cả chúng thực sự được đóng gói trong một tuple.

Ngay cả khi chúng tôi không vượt qua bất kỳ cuộc tranh luận nào,

    def wrapper(*args, **kwargs):
        # do something before
        try:
            return func(*a, **kwargs)
        finally:
            # do something after
3

Chúng tôi vẫn nhận được một tuple (trống).

Điều này có thể làm cho một số người co rúm lại một chút, nhưng bạn thậm chí có thể đóng gói nhiều đối số của các loại khác nhau.

    def wrapper(*args, **kwargs):
        # do something before
        try:
            return func(*a, **kwargs)
        finally:
            # do something after
4

Toán tử * làm gì? Đây là một toán tử giải nén. Nó xuất hiện trước khi có thể lặp lại (ví dụ: một danh sách hoặc một tuple) và những gì nó thực sự làm là truyền bá yếu tố của nó như là đối số của hàm. Nó về cơ bản là một ký hiệu trong đó:
This is an unpacking operator. It comes before an iterable (e.g. a list or a tuple) and what it really does is spreading out its element as the arguments of the function. It’s basically a notation where:

    def wrapper(*args, **kwargs):
        # do something before
        try:
            return func(*a, **kwargs)
        finally:
            # do something after
5

tương đương với:

    def wrapper(*args, **kwargs):
        # do something before
        try:
            return func(*a, **kwargs)
        finally:
            # do something after
6

Bây giờ, quay trở lại ví dụ trước đây của chúng tôi về phép nhân, chúng tôi có thể viết lại chức năng bằng cách sử dụng đóng gói.

    def wrapper(*args, **kwargs):
        # do something before
        try:
            return func(*a, **kwargs)
        finally:
            # do something after
7

Hàm này giờ đây có thể nhận được một số lượng đối số tùy ý và ngay cả khi bạn có danh sách các số, bạn vẫn có thể sử dụng nó: đây là nơi giải nén là hữu ích.

    def wrapper(*args, **kwargs):
        # do something before
        try:
            return func(*a, **kwargs)
        finally:
            # do something after
8

Vượt qua các đối số từ khóa với ** kwargs

Trước hết, các đối số từ khóa là gì?

Khi bạn xác định một chức năng như sau:

    def wrapper(*args, **kwargs):
        # do something before
        try:
            return func(*a, **kwargs)
        finally:
            # do something after
9

Bạn có thể gọi nó theo hai cách khác nhau, bằng cách

1 - Các đối số vị trí vượt qua

    def wrapperGenerator(anyFunc, *args, **kwargs):
        def wrapper(*args, **kwargs):
            try:
                # do something before
                return anyFunc(*args, **kwargs)
            finally:
                #do something after
        return wrapper
0

2 - hoặc các đối số từ khóa (hoặc đặt tên)

    def wrapperGenerator(anyFunc, *args, **kwargs):
        def wrapper(*args, **kwargs):
            try:
                # do something before
                return anyFunc(*args, **kwargs)
            finally:
                #do something after
        return wrapper
1

Như bạn mong đợi, Python cũng có cách riêng để vượt qua các đối số từ khóa có độ dài thay đổi (hoặc đối số được đặt tên): Điều này đạt được bằng cách sử dụng ký hiệu ** kwargs.**kwargs symbol.

Khi sử dụng ** kwargs, tất cả các từ khóa bạn chuyển đến hàm được đóng gói bên trong một từ điển. Và, như bạn mong đợi, biến từ điển này được gọi là kwargs.

Hãy cùng nhìn vào một ví dụ nhỏ sử dụng ** kwargs. Một ví dụ đơn giản có trong các đối số từ khóa và in các cặp giá trị khóa của chúng.**kwargs. A simple example that takes in keyword arguments and prints their key-value pairs.

    def wrapperGenerator(anyFunc, *args, **kwargs):
        def wrapper(*args, **kwargs):
            try:
                # do something before
                return anyFunc(*args, **kwargs)
            finally:
                #do something after
        return wrapper
2

Làm việc với *args và ** kwargs

Bây giờ bạn đã hiểu những điều cơ bản của hai ký hiệu này, có một số quy tắc cụ thể áp dụng cho chúng:

  • Bạn có thể sử dụng *Args với các đối số vị trí. Trong bối cảnh này, *args phải đến vào cuối
    def wrapperGenerator(anyFunc, *args, **kwargs):
        def wrapper(*args, **kwargs):
            try:
                # do something before
                return anyFunc(*args, **kwargs)
            finally:
                #do something after
        return wrapper
3
  • Nếu chúng ta thêm một đối số vị trí với giá trị mặc định vào ví dụ trước, đối số này phải ở cuối
    def wrapperGenerator(anyFunc, *args, **kwargs):
        def wrapper(*args, **kwargs):
            try:
                # do something before
                return anyFunc(*args, **kwargs)
            finally:
                #do something after
        return wrapper
4
  • Bạn có thể kết hợp *args với ** kwargs và thậm chí thêm các đối số vị trí với giá trị mặc định. Trong trường hợp đó, thứ tự là: *args, đối số vị trí với các giá trị mặc định, ** kwargs*args with **kwargs and even add positional arguments with a default value. In that case, the order is: *args, positional arguments with default values, **kwargs
    def wrapperGenerator(anyFunc, *args, **kwargs):
        def wrapper(*args, **kwargs):
            try:
                # do something before
                return anyFunc(*args, **kwargs)
            finally:
                #do something after
        return wrapper
5

Sự kết luận

Hãy để bọc nó lên.

  • *args và ** kwargs cho phép bạn có các đối số có độ dài thay đổi and **kwargs allow you to have variable-length arguments
  • *args cho phép bạn vượt qua một số lượng các đối số không phải là Keyeword được đóng gói thành một tuple allow you to pass a variable number of non-keyword arguments that are packed into a tuple
  • ** kwargs cho phép bạn vượt qua một số lượng các đối số từ khóa được đóng gói vào từ điển allow you to pass a variable number of keyword arguments that are packed into a dictionary
  • *args và ** kwargs làm cho mã của bạn linh hoạt hơnand **kwargs make your code more flexible
  • *args và ** kwargs có thể được kết hợp với nhau cùng với các đối số vị trí

Tài nguyên

Nếu bạn quan tâm đến việc đi sâu vào chủ đề của *args và ** kwargs thậm chí nhiều hơn, bạn có thể xem xét các tài nguyên sau:

  • https://stackoverflow.com/questions/33542959/why-use-packed-args-kwargs-instead-of-passing-list-dict
  • https://www.pythontutorial.net/python-basics/python-args/
  • https://treyhunner.com/2018/04/keyword-arguments-in-python/#What_are_keyword_arguments?
  • https://towardsdatascience.com/10-examples-to-master-args-and-kwargs-in-python-6f1e8cc30749

Cảm ơn bạn đã đọc 🙏

Một lần nữa, nếu bạn đã làm cho nó đến nay, tôi muốn cảm ơn bạn về thời gian của bạn và hy vọng rằng bạn đã học được điều gì đó hữu ích để làm cho mã của bạn sạch hơn và linh hoạt hơn.

Đó là tất cả cho tôi ngày hôm nay. Cho đến lần sau! 👋

Làm thế nào để bạn chuyển các đối số biến cho một hàm trong Python?

Python có *arg cho phép chúng tôi vượt qua số lượng thay đổi của các đối số từ khóa cho chức năng. Trong hàm, chúng ta nên sử dụng dấu hoa thị * trước tên tham số để truyền các đối số độ dài biến.use an asterisk * before the parameter name to pass variable length arguments.

Một biến có thể gọi một hàm python có thể không?

Trong Python, chúng ta có thể gán một hàm cho một biến. Và sử dụng biến đó, chúng tôi có thể gọi hàm nhiều như thời gian chúng tôi muốn.we can assign a function to a variable. And using that variable we can call the function as many as times we want.

Làm cách nào để gọi một hàm có tham số trong Python?

Cách xác định và gọi một chức năng cơ bản trong Python..
Nhập tên chức năng ..
Tên chức năng phải được theo sau bởi dấu ngoặc đơn.Nếu có bất kỳ đối số cần thiết, chúng phải được thông qua trong dấu ngoặc đơn.Nếu chức năng không có bất kỳ đối số nào, bạn vẫn cần dấu ngoặc đơn ..

Làm thế nào chúng ta có thể chuyển các đối số trong gọi chức năng?

Để truyền một giá trị bằng cách tham chiếu, các gợi ý đối số được chuyển đến các hàm giống như bất kỳ giá trị nào khác.Vì vậy, theo đó, bạn cần khai báo các tham số hàm là loại con trỏ như trong hoán đổi hàm sau (), trao đổi các giá trị của hai biến số nguyên được trỏ đến, bằng các đối số của chúng.argument pointers are passed to the functions just like any other value. So accordingly you need to declare the function parameters as pointer types as in the following function swap(), which exchanges the values of the two integer variables pointed to, by their arguments.