Thuộc tính chức năng trong python là gì?

Xuyên suốt các hướng dẫn trước trong loạt bài này, bạn đã thấy nhiều ví dụ minh họa việc sử dụng các hàm Python tích hợp sẵn. In this tutorial, you’ll learn how to define your own Python function. You’ll learn when to divide your program into separate user-defined functions and what tools you’ll need to do this

Here’s what you’ll learn in this tutorial

  • How functions work in Python and why they’re beneficial
  • How to define and call your own Python function
  • Mechanisms for passing arguments to your function
  • How to return data from your function back to the calling environment

Free PDF Download. Python 3 Cheat Sheet

Functions in Python

You may be familiar with the mathematical concept of a function. A function is a relationship or mapping between one or more inputs and a set of outputs. In mathematics, a function is typically represented like this

Thuộc tính chức năng trong python là gì?

Here,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
16 is a function that operates on the inputs
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 and
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
18. The output of the function is
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
19. However, programming functions are much more generalized and versatile than this mathematical definition. In fact, appropriate function definition and use is so critical to proper software development that virtually all modern programming languages support both built-in and user-defined functions

In programming, a function is a self-contained block of code that encapsulates a specific task or related group of tasks. In previous tutorials in this series, you’ve been introduced to some of the built-in functions provided by Python. Ví dụ:

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
20 nhận một đối số và trả về mã định danh số nguyên duy nhất của đối tượng đó

>>>

>>> s = 'foobar'
>>> id(s)
56313440

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
21 trả về độ dài của đối số được truyền cho nó

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
22 lấy một iterable làm đối số của nó và trả về
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
23 nếu bất kỳ mục nào trong iterable là đúng và
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
24 nếu không

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
1

Mỗi chức năng tích hợp này thực hiện một nhiệm vụ cụ thể. Mã hoàn thành nhiệm vụ được xác định ở đâu đó, nhưng bạn không cần biết mã đó hoạt động ở đâu hoặc thậm chí như thế nào. Tất cả những gì bạn cần biết là giao diện của chức năng

  1. Những đối số (nếu có) nó cần
  2. Giá trị nào (nếu có) nó trả về

Sau đó, bạn gọi hàm và chuyển các đối số thích hợp. Việc thực thi chương trình chuyển sang phần thân mã được chỉ định và thực hiện công việc hữu ích của nó. Khi chức năng kết thúc, quá trình thực thi sẽ quay trở lại mã của bạn nơi nó đã dừng lại. Hàm có thể hoặc không thể trả về dữ liệu để mã của bạn sử dụng, như các ví dụ trên

Khi bạn xác định hàm Python của riêng mình, nó sẽ hoạt động giống như vậy. Từ một nơi nào đó trong mã của bạn, bạn sẽ gọi hàm Python của mình và việc thực thi chương trình sẽ chuyển sang phần thân mã tạo nên hàm

Ghi chú. Trong trường hợp này, bạn sẽ biết mã ở đâu và chính xác nó hoạt động như thế nào vì bạn đã viết nó

Khi chức năng kết thúc, thực thi trở lại vị trí mà chức năng đã được gọi. Tùy thuộc vào cách bạn thiết kế giao diện của hàm, dữ liệu có thể được truyền vào khi hàm được gọi và các giá trị trả về có thể được truyền lại khi hàm kết thúc

Loại bỏ các quảng cáo

Tầm quan trọng của các hàm Python

Hầu như tất cả các ngôn ngữ lập trình được sử dụng ngày nay đều hỗ trợ một dạng hàm do người dùng định nghĩa, mặc dù chúng không phải lúc nào cũng được gọi là hàm. Trong các ngôn ngữ khác, bạn có thể thấy chúng được gọi là một trong những ngôn ngữ sau

  • chương trình con
  • thủ tục
  • phương pháp
  • chương trình con

Vì vậy, tại sao phải xác định chức năng? . Bây giờ chúng ta hãy đi qua một số

Tính trừu tượng và khả năng sử dụng lại

Giả sử bạn viết một số mã làm điều gì đó hữu ích. Khi bạn tiếp tục phát triển, bạn thấy rằng tác vụ do mã đó thực hiện là tác vụ bạn cần thường xuyên, ở nhiều vị trí khác nhau trong ứng dụng của bạn. Những gì bạn nên làm?

Sau này, có thể bạn sẽ quyết định rằng mã được đề cập cần phải được sửa đổi. You’ll either find something wrong with it that needs to be fixed, or you’ll want to enhance it in some way. If copies of the code are scattered all over your application, then you’ll need to make the necessary changes in every location

Note. At first blush, that may seem like a reasonable solution, but in the long term, it’s likely to be a maintenance nightmare. While your code editor may help by providing a search-and-replace function, this method is error-prone, and you could easily introduce bugs into your code that will be difficult to find

A better solution is to define a Python function that performs the task. Anywhere in your application that you need to accomplish the task, you simply call the function. Down the line, if you decide to change how it works, then you only need to change the code in one location, which is the place where the function is defined. The changes will automatically be picked up anywhere the function is called

The abstraction of functionality into a function definition is an example of the Don’t Repeat Yourself (DRY) Principle of software development. This is arguably the strongest motivation for using functions

Modularity

Functions allow complex processes to be broken up into smaller steps. Imagine, for example, that you have a program that reads in a file, processes the file contents, and then writes an output file. Your code could look like this

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
2

In this example, the main program is a bunch of code strung together in a long sequence, with whitespace and comments to help organize it. However, if the code were to get much lengthier and more complex, then you’d have an increasingly difficult time wrapping your head around it

Alternatively, you could structure the code more like the following

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
3

This example is modularized. Instead of all the code being strung together, it’s broken out into separate functions, each of which focuses on a specific task. Those tasks are read, process, and write. The main program now simply needs to call each of these in turn

Note. The

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
25 keyword introduces a new Python function definition. You’ll learn all about this very soon

In life, you do this sort of thing all the time, even if you don’t explicitly think of it that way. If you wanted to move some shelves full of stuff from one side of your garage to the other, then you hopefully wouldn’t just stand there and aimlessly think, “Oh, geez. I need to move all that stuff over there. How do I do that???” You’d divide the job into manageable steps

  1. Take all the stuff off the shelves
  2. Take the shelves apart
  3. Mang các bộ phận của kệ qua nhà để xe đến vị trí mới
  4. Lắp ráp lại các kệ
  5. Mang đồ qua nhà để xe
  6. Đặt lại những thứ trên kệ

Chia một nhiệm vụ lớn thành các nhiệm vụ nhỏ hơn, nhỏ hơn giúp làm cho nhiệm vụ lớn dễ suy nghĩ và quản lý hơn. Khi các chương trình trở nên phức tạp hơn, việc mô đun hóa chúng theo cách này ngày càng trở nên có lợi.

Loại bỏ các quảng cáo

Tách không gian tên

Không gian tên là một vùng của chương trình trong đó các mã định danh có ý nghĩa. Như bạn sẽ thấy bên dưới, khi một hàm Python được gọi, một không gian tên mới được tạo cho hàm đó, một không gian tên khác với tất cả các không gian tên khác đã tồn tại

Kết quả thực tế của điều này là các biến có thể được xác định và sử dụng trong một hàm Python ngay cả khi chúng có cùng tên với các biến được xác định trong các hàm khác hoặc trong chương trình chính. Trong những trường hợp này, sẽ không có sự nhầm lẫn hoặc can thiệp vì chúng được giữ trong các không gian tên riêng biệt

Điều này có nghĩa là khi bạn viết mã trong một hàm, bạn có thể sử dụng tên biến và mã định danh mà không phải lo lắng về việc liệu chúng đã được sử dụng ở đâu khác bên ngoài hàm chưa. Điều này giúp giảm thiểu đáng kể các lỗi trong mã

Ghi chú. Bạn sẽ tìm hiểu thêm về không gian tên ở phần sau của loạt bài này

Hy vọng rằng bạn đã đủ thuyết phục về ưu điểm của các chức năng và mong muốn tạo ra một số. Hãy xem làm thế nào

Gọi hàm và định nghĩa

Cú pháp thông thường để xác định hàm Python như sau

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
5

Các thành phần của định nghĩa được giải thích trong bảng dưới đây

ComponentMeaning

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
25Từ khóa thông báo cho Python rằng một hàm đang được xác định
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
27Một mã định danh Python hợp lệ đặt tên cho hàm
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
28Một danh sách các tham số tùy chọn, được phân tách bằng dấu phẩy có thể được truyền cho hàm
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
29Dấu câu biểu thị phần cuối của tiêu đề hàm Python (danh sách tên và tham số)
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
30A

Mục cuối cùng,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
30, được gọi là phần thân của hàm. Phần thân là một khối các câu lệnh sẽ được thực hiện khi hàm được gọi. The body of a Python function is defined by indentation in accordance with the off-side rule. Điều này giống như các khối mã được liên kết với cấu trúc điều khiển, chẳng hạn như câu lệnh
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
32 hoặc
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
33

Cú pháp gọi hàm Python như sau

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
4

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
34 là các giá trị được truyền vào hàm. Chúng tương ứng với
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
28 trong định nghĩa hàm Python. Bạn có thể định nghĩa một hàm không nhận bất kỳ đối số nào, nhưng dấu ngoặc đơn vẫn được yêu cầu. Cả định nghĩa hàm và lời gọi hàm phải luôn bao gồm dấu ngoặc đơn, ngay cả khi chúng trống

Như thường lệ, bạn sẽ bắt đầu với một ví dụ nhỏ và thêm độ phức tạp từ đó. Hãy ghi nhớ truyền thống toán học lâu đời, bạn sẽ gọi hàm Python đầu tiên của mình là

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36. Đây là tệp script,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
37, xác định và gọi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
0

Đây là cách mã này hoạt động

  1. Dòng 1 sử dụng từ khóa

    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    25 để chỉ ra rằng một chức năng đang được xác định. Việc thực thi câu lệnh
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    25 chỉ tạo ra định nghĩa của
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    36. Tất cả các dòng sau được thụt vào (dòng 2 đến dòng 3) trở thành một phần của phần thân của
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    36 và được lưu trữ dưới dạng định nghĩa của nó, nhưng chúng chưa được thực thi

  2. Dòng 4 là một chút khoảng trắng giữa định nghĩa hàm và dòng đầu tiên của chương trình chính. Mặc dù nó không cần thiết về mặt cú pháp, nhưng thật tuyệt khi có. Để tìm hiểu thêm về khoảng trắng xung quanh các định nghĩa hàm Python cấp cao nhất, hãy xem Viết mã Pythonic đẹp với PEP 8

  3. Dòng 5 là câu lệnh đầu tiên không được thụt lề vì nó không phải là một phần của định nghĩa về

    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    36. Nó bắt đầu chương trình chính. Khi chương trình chính thực thi, câu lệnh này được thực hiện đầu tiên

  4. Dòng 6 là cuộc gọi đến

    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    36. Lưu ý rằng dấu ngoặc đơn trống luôn được yêu cầu trong cả định nghĩa hàm và lời gọi hàm, ngay cả khi không có tham số hoặc đối số. Quá trình thực thi tiếp tục đến
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    36 và các câu lệnh trong phần thân của
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    36 được thực thi

  5. Dòng 7 là dòng tiếp theo thực thi sau khi phần thân của

    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    36 kết thúc. Việc thực thi trả về câu lệnh
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    48 này

Trình tự thực hiện (hoặc luồng điều khiển) cho

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
37 được hiển thị trong sơ đồ sau

Thuộc tính chức năng trong python là gì?

Khi

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
37 được chạy từ dấu nhắc lệnh của Windows, kết quả như sau

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
3

Đôi khi, bạn có thể muốn định nghĩa một hàm rỗng không làm gì cả. Đây được gọi là sơ khai, thường là trình giữ chỗ tạm thời cho hàm Python sẽ được triển khai đầy đủ sau này. Giống như một khối trong cấu trúc điều khiển không thể để trống, phần thân của hàm cũng vậy. Để định nghĩa một hàm sơ khai, hãy sử dụng câu lệnh

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
51

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
5

Như bạn có thể thấy ở trên, lệnh gọi hàm sơ khai hợp lệ về mặt cú pháp nhưng không thực hiện bất kỳ điều gì

Loại bỏ các quảng cáo

Truyền đối số

Cho đến giờ trong hướng dẫn này, các hàm bạn đã xác định chưa nhận bất kỳ đối số nào. Điều đó đôi khi có thể hữu ích và thỉnh thoảng bạn sẽ viết các hàm như vậy. Tuy nhiên, thường xuyên hơn, bạn sẽ muốn truyền dữ liệu vào một hàm để hành vi của nó có thể thay đổi từ lần gọi này sang lần gọi tiếp theo. Hãy xem làm thế nào để làm điều đó

Đối số vị trí

Cách đơn giản nhất để truyền đối số cho hàm Python là sử dụng đối số vị trí (còn gọi là đối số bắt buộc). Trong định nghĩa hàm, bạn chỉ định danh sách tham số được phân tách bằng dấu phẩy bên trong dấu ngoặc đơn

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
0

Khi hàm được gọi, bạn chỉ định một danh sách các đối số tương ứng

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
1

Các tham số (

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
52,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
53 và
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
54) hoạt động giống như các biến được xác định cục bộ cho hàm. Khi hàm được gọi, các đối số được truyền (
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
55,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
56 và
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
57) được liên kết với các tham số theo thứ tự, như thể bằng cách gán biến

Tham sốArgument

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
52←
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
55
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
53←
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
61
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
54←
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
57

Trong một số văn bản lập trình, các tham số được đưa ra trong định nghĩa hàm được gọi là tham số hình thức và các đối số trong lệnh gọi hàm được gọi là tham số thực

Thuộc tính chức năng trong python là gì?

Mặc dù các đối số vị trí là cách đơn giản nhất để truyền dữ liệu đến một hàm, nhưng chúng cũng kém linh hoạt nhất. Đối với người mới bắt đầu, thứ tự của các đối số trong lệnh gọi phải khớp với thứ tự của các tham số trong định nghĩa. Tất nhiên, không có gì ngăn bạn chỉ định các đối số vị trí không theo thứ tự

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
2

Hàm thậm chí có thể vẫn chạy, như trong ví dụ trên, nhưng rất khó có thể tạo ra kết quả chính xác. Lập trình viên có trách nhiệm xác định chức năng để ghi lại các đối số phù hợp và trách nhiệm của người dùng chức năng là nhận thức được thông tin đó và tuân theo thông tin đó

Với các đối số vị trí, các đối số trong lệnh gọi và các tham số trong định nghĩa phải thống nhất không chỉ về thứ tự mà còn về số lượng. Đó là lý do đối số vị trí cũng được gọi là đối số bắt buộc. You can’t leave any out when calling the function

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
3

Bạn cũng không thể chỉ định những cái bổ sung

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
4

Đối số vị trí dễ sử dụng về mặt khái niệm, nhưng chúng không dễ tha thứ. Bạn phải chỉ định cùng một số đối số trong lệnh gọi hàm như có các tham số trong định nghĩa và theo đúng thứ tự. Trong các phần tiếp theo, bạn sẽ thấy một số kỹ thuật chuyển đối số giúp nới lỏng các hạn chế này

Đối số từ khóa

Khi gọi một hàm, bạn có thể chỉ định các đối số ở dạng

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
64. Trong trường hợp đó, mỗi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
65 phải khớp với một tham số trong định nghĩa hàm Python. Ví dụ: hàm được xác định trước đó
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 có thể được gọi với các đối số từ khóa như sau

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
5

Tham chiếu một từ khóa không khớp với bất kỳ tham số nào đã khai báo sẽ tạo ra một ngoại lệ

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
6

Sử dụng các đối số từ khóa sẽ loại bỏ hạn chế về thứ tự đối số. Mỗi đối số từ khóa chỉ định rõ ràng một tham số cụ thể theo tên, vì vậy bạn có thể chỉ định chúng theo bất kỳ thứ tự nào và Python sẽ vẫn biết đối số nào đi với tham số nào

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
7

Tuy nhiên, giống như đối số vị trí, số lượng đối số và tham số vẫn phải khớp với nhau

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
8

Vì vậy, các đối số từ khóa cho phép linh hoạt trong thứ tự các đối số chức năng được chỉ định, nhưng số lượng đối số vẫn còn cứng nhắc

Bạn có thể gọi một hàm bằng cách sử dụng cả đối số vị trí và từ khóa

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
9

Khi cả hai đối số vị trí và từ khóa đều xuất hiện, tất cả các đối số vị trí phải xuất hiện trước

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
10

Khi bạn đã chỉ định một đối số từ khóa, không thể có bất kỳ đối số vị trí nào ở bên phải của nó

Để tìm hiểu thêm về các tham số vị trí và từ khóa, hãy xem khóa học Real Python Khám phá các tham số chức năng đặc biệt

Loại bỏ các quảng cáo

Thông số mặc định

Nếu một tham số được chỉ định trong định nghĩa hàm Python có dạng

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
67, thì
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
68 sẽ trở thành giá trị mặc định cho tham số đó. Các tham số được xác định theo cách này được gọi là tham số mặc định hoặc tùy chọn. Một ví dụ về định nghĩa hàm với các tham số mặc định được hiển thị bên dưới

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
11

Khi phiên bản này của

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 được gọi, bất kỳ đối số nào bị bỏ qua sẽ nhận giá trị mặc định của nó

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
12

Tóm tắt

  • Các đối số vị trí phải thống nhất về thứ tự và số với các tham số được khai báo trong định nghĩa hàm
  • Các đối số từ khóa phải phù hợp với các tham số đã khai báo về số lượng, nhưng chúng có thể được chỉ định theo thứ tự tùy ý
  • Tham số mặc định cho phép bỏ qua một số đối số khi gọi hàm

Giá trị tham số mặc định có thể thay đổi

Mọi thứ có thể trở nên kỳ lạ nếu bạn chỉ định một giá trị tham số mặc định là một đối tượng có thể thay đổi. Xem xét định nghĩa hàm Python này

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
13

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 lấy một tham số danh sách, nối chuỗi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
71 vào cuối danh sách và trả về kết quả

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
14

Giá trị mặc định cho tham số

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
72 là danh sách trống, vì vậy nếu
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 được gọi mà không có bất kỳ đối số nào, thì giá trị trả về là danh sách có một phần tử duy nhất là
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
71

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
15

Mọi thứ đều có ý nghĩa cho đến nay. Bây giờ, bạn mong đợi điều gì sẽ xảy ra nếu

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 được gọi mà không có bất kỳ tham số nào lần thứ hai và thứ ba?

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
16

Ối. Bạn có thể mong đợi mỗi cuộc gọi tiếp theo cũng trả về danh sách đơn lẻ

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
76, giống như cuộc gọi đầu tiên. Thay vào đó, giá trị trả lại tiếp tục tăng. Chuyện gì đã xảy ra thế?

Trong Python, các giá trị tham số mặc định chỉ được xác định một lần khi hàm được xác định (nghĩa là khi câu lệnh

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
25 được thực thi). Giá trị mặc định không được xác định lại mỗi khi hàm được gọi. Do đó, mỗi lần bạn gọi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 mà không có tham số, bạn đang thực hiện
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
79 trên cùng một danh sách

Bạn có thể chứng minh điều này với

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
20

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17

Mã định danh đối tượng được hiển thị xác nhận rằng, khi

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
72 được phép đặt mặc định, giá trị là cùng một đối tượng với mỗi cuộc gọi. Vì các danh sách có thể thay đổi, nên mỗi lệnh gọi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
79 tiếp theo sẽ khiến danh sách dài hơn. Đây là một cạm bẫy phổ biến và được ghi lại khá rõ ràng khi bạn đang sử dụng một đối tượng có thể thay đổi làm giá trị mặc định của tham số. Nó có khả năng dẫn đến hành vi mã khó hiểu và có lẽ tốt nhất nên tránh

Như một giải pháp thay thế, hãy cân nhắc sử dụng một giá trị đối số mặc định báo hiệu rằng không có đối số nào được chỉ định. Hầu hết mọi giá trị sẽ hoạt động, nhưng

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
83 là một lựa chọn phổ biến. Khi giá trị sentinel cho biết không có đối số nào được đưa ra, hãy tạo một danh sách trống mới bên trong hàm

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
18

Lưu ý cách điều này đảm bảo rằng giờ đây

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
72 thực sự mặc định là một danh sách trống bất cứ khi nào
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 được gọi mà không có đối số

Loại bỏ các quảng cáo

Pass-By-Value vs Pass-By-Reference trong Pascal

Trong thiết kế ngôn ngữ lập trình, có hai mô hình phổ biến để truyền đối số cho hàm

  1. Pass-by-giá trị. Một bản sao của đối số được chuyển đến hàm
  2. Chuyển qua tham chiếu. Một tham chiếu đến đối số được chuyển đến hàm

Các cơ chế khác tồn tại, nhưng về cơ bản chúng là các biến thể của hai cơ chế này. Trong phần này, bạn sẽ đi một đoạn ngắn từ Python và xem xét ngắn gọn về Pascal, một ngôn ngữ lập trình tạo ra sự khác biệt đặc biệt rõ ràng giữa hai ngôn ngữ này.

Ghi chú. Đừng lo lắng nếu bạn không quen thuộc với Pascal. Các khái niệm này tương tự như các khái niệm của Python và các ví dụ được hiển thị kèm theo lời giải thích đủ chi tiết để bạn có được ý tưởng chung. Khi bạn đã thấy cách truyền đối số hoạt động trong Pascal, chúng ta sẽ quay lại Python và bạn sẽ thấy nó so sánh như thế nào

Đây là những gì bạn cần biết về cú pháp Pascal

  • thủ tục. Một thủ tục trong Pascal tương tự như một hàm trong Python
  • Dấu hai chấm bằng. Toán tử này (
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    86) dùng để gán trong Pascal. Nó tương tự như dấu bằng (
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    87) trong Python
  • >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    88. Hàm này hiển thị dữ liệu ra bàn điều khiển, tương tự như hàm
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    48 của Python

Với một chút nền tảng đó, đây là ví dụ Pascal đầu tiên

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
19

Đây là những gì đang xảy ra

  • Dòng 12. Chương trình chính xác định một biến số nguyên
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    17
  • dòng 15. Ban đầu nó gán cho
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    17 giá trị
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    92
  • Dòng 17. Sau đó, nó gọi thủ tục
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    36, chuyển
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    17 làm đối số
  • dòng 5. Bên trong
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    36, câu lệnh
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    88 cho thấy tham số tương ứng
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    97 ban đầu là
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    92, giá trị được truyền vào
  • dòng 6.
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    97 sau đó được gán giá trị
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    100
  • dòng 7. Giá trị này được xác minh bởi câu lệnh
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    88 này được thực thi ngay trước khi thoát
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    36
  • Dòng 18. Trở lại môi trường gọi của chương trình chính, câu lệnh
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    88 này cho thấy rằng sau khi
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    36 trả về,
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    17 vẫn là
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    92, giống như trước khi gọi thủ tục

Chạy mã này tạo ra đầu ra sau

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
20

Trong ví dụ này,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 được truyền theo giá trị, vì vậy,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 chỉ nhận được một bản sao. Khi tham số tương ứng
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
97 được sửa đổi, thì
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 không bị ảnh hưởng

Ghi chú. Nếu bạn muốn thấy điều này hoạt động, thì bạn có thể tự chạy mã bằng trình biên dịch Pascal trực tuyến

Chỉ cần làm theo các bước sau

  1. Sao chép mã từ hộp mã ở trên
  2. Truy cập Trình biên dịch Pascal trực tuyến
  3. In the code box on the left, replace any existing contents with the code you copied in step 1
  4. Nhấp vào Thực hiện

Bạn sẽ thấy đầu ra tương tự như trên

Bây giờ, hãy so sánh điều này với ví dụ tiếp theo

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
21

Mã này giống với ví dụ đầu tiên, với một thay đổi. Đó là sự hiện diện của từ

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
111 ở phía trước của
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
97 trong định nghĩa của thủ tục
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 trên dòng 3. Điều đó chỉ ra rằng đối số của
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 được chuyển qua tham chiếu. Các thay đổi được thực hiện đối với tham số tương ứng
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
97 cũng sẽ sửa đổi đối số trong môi trường gọi

Đầu ra từ mã này giống như trước, ngoại trừ dòng cuối cùng

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
22

Một lần nữa,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
97 được gán giá trị
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
100 bên trong
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 như trước. Nhưng lần này, khi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 quay trở lại, thì
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 trong chương trình chính cũng đã được sửa đổi

Trong nhiều ngôn ngữ lập trình, về cơ bản đó là sự khác biệt giữa pass-by-value và pass-by-reference

  • Nếu một biến được truyền theo giá trị, thì hàm có một bản sao để hoạt động, nhưng nó không thể sửa đổi giá trị ban đầu trong môi trường gọi
  • Nếu một biến được truyền theo tham chiếu, thì bất kỳ thay đổi nào mà hàm thực hiện đối với tham số tương ứng sẽ ảnh hưởng đến giá trị trong môi trường gọi

Lý do tại sao xuất phát từ ý nghĩa của một tài liệu tham khảo trong các ngôn ngữ này. Các giá trị biến được lưu trữ trong bộ nhớ. Trong Pascal và các ngôn ngữ tương tự, tham chiếu về cơ bản là địa chỉ của vị trí bộ nhớ đó, như minh họa bên dưới

Thuộc tính chức năng trong python là gì?

Trong sơ đồ bên trái,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 có bộ nhớ được phân bổ trong không gian tên của chương trình chính. Khi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 được gọi,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 được truyền theo giá trị, vì vậy bộ nhớ cho tham số tương ứng
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
97 được phân bổ trong không gian tên của
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 và giá trị của
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 được sao chép vào đó. Khi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 sửa đổi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
97, bản sao cục bộ này được thay đổi. Giá trị của
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 trong môi trường gọi vẫn không bị ảnh hưởng

Trong sơ đồ bên phải,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 được chuyển qua tham chiếu. Tham số tương ứng
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
97 trỏ đến địa chỉ thực trong không gian tên của chương trình chính nơi lưu trữ giá trị của
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17. Khi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 sửa đổi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
97, nó sẽ sửa đổi giá trị ở vị trí đó, giống như khi chương trình chính đang sửa đổi chính
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17

Loại bỏ các quảng cáo

Pass-By-Value vs Pass-By-Reference trong Python

Các tham số trong Python có truyền theo giá trị hoặc theo tham chiếu không? . Đó là bởi vì một tham chiếu không có nghĩa hoàn toàn giống như trong Python như trong Pascal

Nhớ lại rằng trong Python, mọi phần dữ liệu đều là một đối tượng. Một tham chiếu trỏ đến một đối tượng, không phải là một vị trí bộ nhớ cụ thể. Điều đó có nghĩa là phép gán không được hiểu theo cùng một cách trong Python như trong Pascal. Xét cặp câu lệnh sau trong Pascal

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
23

Chúng được giải thích theo cách này

  • Biến
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    17 tham chiếu đến một vị trí bộ nhớ cụ thể
  • Câu lệnh đầu tiên đặt giá trị
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    92 vào vị trí đó
  • Câu lệnh tiếp theo ghi đè lên
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    92 và thay vào đó đặt
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    100 ở đó

Ngược lại, trong Python, các câu lệnh gán tương tự như sau

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
24

Các câu lệnh gán này có ý nghĩa như sau

  • Câu lệnh đầu tiên làm cho
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    17 trỏ đến một đối tượng có giá trị là
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    92
  • Câu lệnh tiếp theo gán lại
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    17 làm tham chiếu mới cho một đối tượng khác có giá trị là
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    100. Nói cách khác, phép gán thứ hai liên kết lại
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    17 với một đối tượng khác có giá trị
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    100

Trong Python, khi bạn truyền một đối số cho một hàm, một rebinding tương tự sẽ xảy ra. Hãy xem xét ví dụ này

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
25

Trong chương trình chính, câu lệnh

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
146 trên dòng 4 tạo một tham chiếu có tên là
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 gắn với một đối tượng có giá trị là
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
92. Sau đó,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 được gọi ở dòng 5, với đối số là
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17. Khi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 bắt đầu lần đầu tiên, một tham chiếu mới có tên là
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
97 được tạo, tham chiếu này ban đầu trỏ đến cùng một đối tượng
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
92 như
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17

Thuộc tính chức năng trong python là gì?

Tuy nhiên, khi câu lệnh

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
155 trên dòng 2 được thực thi,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 liên kết lại
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
97 với một đối tượng mới có giá trị là
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
100. Hai tài liệu tham khảo,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 và
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
97, không được tách rời khỏi nhau. Không có gì khác mà
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 làm sẽ ảnh hưởng đến
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 và khi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 kết thúc,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 sẽ vẫn trỏ đến đối tượng
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
92, giống như trước khi gọi hàm

Thuộc tính chức năng trong python là gì?

Bạn có thể xác nhận tất cả điều này bằng cách sử dụng

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
20. Đây là phiên bản tăng cường một chút của ví dụ trên hiển thị số nhận dạng số của các đối tượng liên quan

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
26

Khi

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 bắt đầu lần đầu tiên, cả
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
97 và
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 đều trỏ đến cùng một đối tượng, có
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
20 là
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
171. After
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 executes the statement
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
155 on line 3,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
97 points to a different object whose
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
20 is
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
176. Kết nối với đối tượng ban đầu trong môi trường gọi bị mất

Truyền đối số trong Python có phần kết hợp giữa truyền theo giá trị và truyền theo tham chiếu. Những gì được truyền cho hàm là một tham chiếu đến một đối tượng, nhưng tham chiếu được truyền theo giá trị

Ghi chú. Cơ chế truyền đối số của Python đã được gọi là chuyển từng lần gán. Điều này là do các tên tham số được liên kết với các đối tượng trên mục nhập hàm trong Python và phép gán cũng là quá trình liên kết tên với một đối tượng. Bạn cũng có thể thấy các thuật ngữ truyền theo đối tượng, tham chiếu theo đối tượng hoặc chia sẻ theo đối tượng

Điểm mấu chốt ở đây là một hàm Python không thể thay đổi giá trị của một đối số bằng cách gán lại tham số tương ứng cho một thứ khác. Ví dụ sau minh họa điều này

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
27

Ở đây, các đối tượng kiểu

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
177,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
178,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
179,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
180 và
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
181 được truyền cho
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 dưới dạng đối số.
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 cố gắng gán từng cái cho đối tượng chuỗi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
184, nhưng như bạn có thể thấy, khi quay lại môi trường gọi, tất cả chúng đều không thay đổi. Ngay sau khi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 thực thi nhiệm vụ
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
186, tham chiếu được phục hồi và kết nối với đối tượng ban đầu bị mất

Điều đó có nghĩa là một hàm Python không bao giờ có thể sửa đổi các đối số của nó? . Xem những gì xảy ra ở đây

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
28

Trong trường hợp này, đối số của

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 là một danh sách. Khi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 được gọi, một tham chiếu đến
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
72 được chuyển. Bạn đã thấy rằng
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 không thể chỉ định lại giá trị bán buôn của
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
72. Nếu
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 được gán cho một thứ khác, thì nó sẽ bị ràng buộc với một đối tượng khác và kết nối với
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
72 sẽ bị mất

Tuy nhiên,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 có thể sử dụng tham chiếu để thực hiện các sửa đổi bên trong
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
72. Ở đây,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 đã sửa đổi phần tử đầu tiên. Bạn có thể thấy rằng khi hàm trả về, trên thực tế,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
72 đã bị thay đổi trong môi trường gọi. Khái niệm tương tự áp dụng cho một cuốn từ điển

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
29

Ở đây,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 sử dụng
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 làm tham chiếu để thực hiện thay đổi bên trong
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
200. Sự thay đổi đó được phản ánh trong môi trường gọi sau khi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 trả về

Loại bỏ các quảng cáo

Tóm tắt thông qua đối số

Truyền đối số trong Python có thể được tóm tắt như sau. Truyền một đối tượng bất biến, chẳng hạn như

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
177,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
180,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
204 hoặc
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
205, cho một hàm Python hoạt động giống như truyền theo giá trị. Chức năng không thể sửa đổi đối tượng trong môi trường gọi

Truyền một đối tượng có thể thay đổi, chẳng hạn như một

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
181,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
178, hoặc
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
179 hoạt động phần nào—nhưng không chính xác—giống như truyền qua tham chiếu. Hàm không thể chỉ định lại toàn bộ đối tượng nhưng có thể thay đổi các mục tại chỗ trong đối tượng và những thay đổi này sẽ được phản ánh trong môi trường gọi

Phản ứng phụ

Vì vậy, trong Python, bạn có thể sửa đổi một đối số từ bên trong một hàm để thay đổi được phản ánh trong môi trường gọi. Nhưng bạn có nên làm điều này?

Tổng quát hơn, một hàm Python được cho là gây ra tác dụng phụ nếu nó sửa đổi môi trường gọi của nó theo bất kỳ cách nào. Thay đổi giá trị của đối số hàm chỉ là một trong những khả năng

Ghi chú. Có lẽ bạn đã quen thuộc với các tác dụng phụ trong lĩnh vực sức khỏe con người, trong đó thuật ngữ này thường đề cập đến hậu quả không mong muốn của thuốc. Thông thường, hậu quả là không mong muốn, chẳng hạn như nôn mửa hoặc an thần. Mặt khác, tác dụng phụ có thể được sử dụng có chủ ý. Ví dụ: một số loại thuốc gây kích thích thèm ăn, có thể được sử dụng để tạo lợi thế, ngay cả khi đó không phải là mục đích chính của thuốc

Khái niệm này tương tự trong lập trình. Nếu tác dụng phụ là một phần được ghi chép rõ ràng trong đặc tả chức năng và người dùng chức năng nhận thức rõ ràng về thời điểm và cách thức môi trường gọi có thể được sửa đổi, thì điều đó có thể ổn. Nhưng một lập trình viên có thể không phải lúc nào cũng ghi lại chính xác các tác dụng phụ hoặc thậm chí họ có thể không biết rằng các tác dụng phụ đang xảy ra

Khi chúng bị ẩn hoặc không mong đợi, các tác dụng phụ có thể dẫn đến các lỗi chương trình rất khó theo dõi. Nói chung, tốt nhất là tránh chúng

Tuyên bố >>> a = ['foo', 'bar', 'baz', 'qux'] >>> len(a) 4 209

Hàm Python để làm gì sau đó? . Làm thế nào một chức năng nên ảnh hưởng đến người gọi của nó?

Chà, một khả năng là sử dụng các giá trị trả về của hàm. A

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
209 statement in a Python function serves two purposes

  1. Nó ngay lập tức kết thúc chức năng và chuyển quyền kiểm soát thực thi trở lại người gọi
  2. Nó cung cấp một cơ chế mà chức năng có thể chuyển dữ liệu trở lại người gọi

Thoát khỏi một chức năng

Trong một hàm, câu lệnh

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
209 khiến hàm Python bị thoát ngay lập tức và chuyển việc thực thi trở lại trình gọi

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
30

Trong ví dụ này, câu lệnh

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
209 thực sự là thừa. Một hàm sẽ trở lại nơi gọi khi nó kết thúc—nghĩa là sau khi câu lệnh cuối cùng của thân hàm được thực thi. Vì vậy, hàm này sẽ hoạt động giống hệt nhau nếu không có câu lệnh
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
209

Tuy nhiên, câu lệnh

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
209 không cần phải ở cuối hàm. Chúng có thể xuất hiện ở bất kỳ đâu trong thân hàm và thậm chí nhiều lần. Hãy xem xét ví dụ này

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
31

Hai lệnh gọi đầu tiên đến

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 không tạo ra bất kỳ kết quả nào, bởi vì câu lệnh
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
209 được thực thi và hàm thoát sớm, trước khi đạt đến câu lệnh
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
48 trên dòng 6

Loại mô hình này có thể hữu ích để kiểm tra lỗi trong một chức năng. Bạn có thể kiểm tra một số điều kiện lỗi khi bắt đầu chức năng, với các câu lệnh

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
209 giải quyết nếu có sự cố

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
32

Nếu không gặp phải tình trạng lỗi nào, thì chức năng có thể tiến hành xử lý bình thường

Loại bỏ các quảng cáo

Trả lại dữ liệu cho người gọi

Ngoài việc thoát khỏi một chức năng, câu lệnh

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
209 còn được sử dụng để truyền dữ liệu trở lại người gọi. Nếu một câu lệnh
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
209 bên trong hàm Python được theo sau bởi một biểu thức, thì trong môi trường gọi, lệnh gọi hàm ước tính giá trị của biểu thức đó

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
33

Ở đây, giá trị của biểu thức

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 trên dòng 5 là
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
184, giá trị này sau đó được gán cho biến
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
223

Một hàm có thể trả về bất kỳ loại đối tượng nào. Trong Python, điều đó có nghĩa là bất cứ thứ gì. Trong môi trường gọi, lệnh gọi hàm có thể được sử dụng về mặt cú pháp theo bất kỳ cách nào phù hợp với loại đối tượng mà hàm trả về

Ví dụ, trong mã này,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 trả về một từ điển. Khi đó, trong môi trường gọi, biểu thức
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 đại diện cho một từ điển và
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
226 là một tham chiếu khóa hợp lệ trong từ điển đó

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
34

Trong ví dụ tiếp theo,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 trả về một chuỗi mà bạn có thể cắt như bất kỳ chuỗi nào khác

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
35

Ở đây,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 trả về một danh sách có thể được lập chỉ mục hoặc cắt lát

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36

Nếu nhiều biểu thức được phân tách bằng dấu phẩy được chỉ định trong câu lệnh

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
209, thì chúng sẽ được đóng gói và trả về dưới dạng một bộ

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
37

Khi không có giá trị trả về nào được đưa ra, một hàm Python trả về giá trị Python đặc biệt

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
83

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
38

Điều tương tự cũng xảy ra nếu thân hàm hoàn toàn không chứa câu lệnh

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
209 và hàm bị lỗi ở cuối

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
39

Nhớ lại rằng

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
83 là sai khi được đánh giá trong ngữ cảnh Boolean

Vì các hàm thoát qua một câu lệnh

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
209 trống hoặc rơi ra khỏi kết thúc trả về
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
83, nên có thể sử dụng lệnh gọi tới một hàm như vậy trong ngữ cảnh Boolean

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
50

Ở đây, các cuộc gọi đến cả

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 và
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
236 đều là giả, vì vậy
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
237 cũng vậy và mệnh đề
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
238 thực thi

Loại bỏ các quảng cáo

Xem lại tác dụng phụ

Giả sử bạn muốn viết một hàm nhận một đối số nguyên và nhân đôi nó. Nghĩa là, bạn muốn truyền một biến số nguyên cho hàm và khi hàm trả về, giá trị của biến trong môi trường gọi phải gấp đôi giá trị ban đầu. Trong Pascal, bạn có thể thực hiện việc này bằng cách sử dụng tham chiếu chuyển qua

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
51

Việc thực thi mã này tạo ra kết quả sau, xác minh rằng

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
239 thực sự sửa đổi
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 trong môi trường gọi

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
52

Trong Python, điều này sẽ không hoạt động. Như bạn đã biết, số nguyên trong Python là bất biến, do đó, hàm Python không thể thay đổi đối số số nguyên bằng tác dụng phụ

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
53

Tuy nhiên, bạn có thể sử dụng giá trị trả về để có được hiệu ứng tương tự. Simply write

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
239 so that it takes an integer argument, doubles it, and returns the doubled value. Sau đó, người gọi chịu trách nhiệm về nhiệm vụ sửa đổi giá trị ban đầu

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
54

Điều này được cho là thích hợp hơn để sửa đổi bởi tác dụng phụ. Rất rõ ràng rằng

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 đang được sửa đổi trong môi trường cuộc gọi vì người gọi đang tự làm như vậy. Dù sao, đó là lựa chọn duy nhất, bởi vì sửa đổi bằng tác dụng phụ không hoạt động trong trường hợp này

Tuy nhiên, ngay cả trong trường hợp có thể sửa đổi đối số bằng tác dụng phụ, việc sử dụng giá trị trả về vẫn có thể rõ ràng hơn. Giả sử bạn muốn nhân đôi mọi mục trong danh sách. Vì danh sách có thể thay đổi, nên bạn có thể xác định hàm Python để sửa đổi danh sách tại chỗ

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
55

Không giống như

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
239 trong ví dụ trước,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
244 thực sự hoạt động như dự kiến. Nếu tài liệu về hàm nêu rõ rằng nội dung của đối số danh sách đã bị thay đổi, thì đây có thể là một cách triển khai hợp lý

Tuy nhiên, bạn cũng có thể viết

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
244 để chuyển danh sách mong muốn trở lại bằng giá trị trả về và cho phép người gọi thực hiện phép gán, tương tự như cách viết lại
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
239 trong ví dụ trước

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
56

Một trong hai cách tiếp cận hoạt động tốt như nhau. Như thường lệ, đây là vấn đề về phong cách và sở thích cá nhân khác nhau. Các tác dụng phụ không nhất thiết phải hoàn toàn xấu xa và chúng có vị trí của chúng, nhưng vì hầu như mọi thứ đều có thể được trả về từ một hàm, nên điều tương tự cũng có thể được thực hiện thông qua các giá trị trả về.

Danh sách đối số có độ dài thay đổi

Trong một số trường hợp, khi bạn định nghĩa một hàm, bạn có thể không biết trước mình muốn nó nhận bao nhiêu đối số. Ví dụ, giả sử bạn muốn viết một hàm Python để tính giá trị trung bình của một vài giá trị. Bạn có thể bắt đầu với một cái gì đó như thế này

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
57

Tất cả đều ổn nếu bạn muốn tính trung bình ba giá trị

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
58

Tuy nhiên, như bạn đã thấy, khi sử dụng đối số vị trí, số lượng đối số được truyền vào phải bằng với số lượng tham số được khai báo. Rõ ràng sau đó, tất cả đều không ổn với việc triển khai

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
247 này cho bất kỳ số lượng giá trị nào ngoài ba

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
59

Bạn có thể thử xác định

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
247 với các tham số tùy chọn

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
40

Điều này cho phép một số lượng đối số khác nhau được chỉ định. Các cuộc gọi sau ít nhất là đúng về mặt cú pháp

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
41

Nhưng cách tiếp cận này vẫn gặp phải một số vấn đề. Đối với người mới bắt đầu, nó vẫn chỉ cho phép tối đa năm đối số, không phải là một số tùy ý. Tệ hơn nữa, không có cách nào để phân biệt giữa các đối số đã được chỉ định và những đối số được phép mặc định. Hàm không có cách nào để biết có bao nhiêu đối số thực sự được truyền vào, vì vậy nó không biết chia cho cái gì

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
42

Rõ ràng, điều này cũng sẽ không làm được

Bạn có thể viết

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
247 để lấy một đối số danh sách

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
43

Ít nhất điều này hoạt động. Nó cho phép một số lượng giá trị tùy ý và tạo ra một kết quả chính xác. Là một phần thưởng bổ sung, nó cũng hoạt động khi đối số là một bộ

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
44

Hạn chế là bước bổ sung phải nhóm các giá trị vào một danh sách hoặc bộ dữ liệu có thể không phải là điều mà người dùng hàm mong đợi và nó không được thanh lịch cho lắm. Bất cứ khi nào bạn tìm thấy mã Python trông không phù hợp, có thể có một tùy chọn tốt hơn

Trong trường hợp này, thực sự có. Python cung cấp một cách để chuyển một hàm một số lượng đối số khác nhau với việc đóng gói và giải nén bộ đối số bằng cách sử dụng toán tử dấu hoa thị (

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
250)

Loại bỏ các quảng cáo

Đối số Tuple đóng gói

Khi tên tham số trong định nghĩa hàm Python được đặt trước dấu hoa thị (

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
250), nó biểu thị việc đóng gói bộ đối số. Mọi đối số tương ứng trong lệnh gọi hàm được đóng gói thành một bộ mà hàm có thể tham chiếu tới bằng tên tham số đã cho. Đây là một ví dụ

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
45

Trong định nghĩa của

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36, đặc tả tham số
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
253 biểu thị việc đóng gói bộ. Trong mỗi lệnh gọi đến
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36, các đối số được đóng gói thành một bộ mà hàm có thể tham chiếu bằng tên
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
255. Bất kỳ tên nào cũng có thể được sử dụng, nhưng
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
255 thường được chọn đến mức thực tế nó là một tiêu chuẩn

Sử dụng đóng gói tuple, bạn có thể dọn sạch

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
247 như thế này

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
46

Tốt hơn nữa, bạn có thể dọn dẹp nó hơn nữa bằng cách thay thế vòng lặp

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
258 bằng hàm Python tích hợp sẵn
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
259, tính tổng các giá trị số trong bất kỳ lần lặp nào.

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
47

Bây giờ,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
247 được viết chính xác và hoạt động như dự kiến

Still, depending on how this code will be used, there may still be work to do. Như đã viết,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
247 sẽ tạo ra một ngoại lệ
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
262 nếu bất kỳ đối số nào không phải là số

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
48

Để mạnh mẽ nhất có thể, bạn nên thêm mã để kiểm tra xem các đối số có thuộc loại phù hợp không. Ở phần sau của loạt bài hướng dẫn này, bạn sẽ học cách nắm bắt các ngoại lệ như

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
262 và xử lý chúng một cách thích hợp. Bạn cũng có thể kiểm tra Ngoại lệ Python. Một lời giới thiệu

Giải nén Tuple đối số

Một hoạt động tương tự có sẵn ở phía bên kia của phương trình trong lệnh gọi hàm Python. Khi một đối số trong lệnh gọi hàm được đặt trước dấu hoa thị (

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
250), điều đó cho biết đối số đó là một bộ nên được giải nén và chuyển đến hàm dưới dạng các giá trị riêng biệt

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
49

Trong ví dụ này,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
265 trong lệnh gọi hàm chỉ ra rằng
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
266 là một bộ cần được giải nén. Các giá trị chưa giải nén
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
184,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
268 và
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
269 được gán cho các tham số
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
18 và
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
19 tương ứng

Mặc dù kiểu giải nén này được gọi là giải nén theo bộ, nhưng nó không chỉ hoạt động với các bộ. Toán tử dấu hoa thị (

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
250) có thể được áp dụng cho bất kỳ lần lặp nào trong lệnh gọi hàm Python. Ví dụ: một danh sách hoặc bộ cũng có thể được giải nén

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
00

Bạn thậm chí có thể sử dụng đóng gói và giải nén tuple cùng một lúc

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
01

Ở đây,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
274 chỉ ra rằng danh sách
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
275 nên được giải nén và các mục được chuyển đến
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 dưới dạng các giá trị riêng lẻ. Đặc tả tham số
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
253 làm cho các giá trị được đóng gói sao lưu vào bộ dữ liệu
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
255

Đóng gói từ điển đối số

Python có một toán tử tương tự, dấu hoa thị kép (

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
279), có thể được sử dụng với các tham số và đối số của hàm Python để chỉ định đóng gói và giải nén từ điển. Trước một tham số trong định nghĩa hàm Python bằng dấu hoa thị kép (
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
279) cho biết rằng các đối số tương ứng, dự kiến ​​là các cặp
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
281, nên được đưa vào từ điển

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
02

Trong trường hợp này, các đối số

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
282,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
283 và
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
284 được đóng gói trong một từ điển mà hàm có thể tham chiếu theo tên
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
285. Một lần nữa, bất kỳ tên nào cũng có thể được sử dụng, nhưng tên đặc biệt
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
285 (viết tắt của từ khóa args) gần như là tiêu chuẩn. Bạn không cần phải tuân theo nó, nhưng nếu bạn làm như vậy, thì bất kỳ ai quen thuộc với các quy ước mã hóa Python sẽ biết ngay ý của bạn

Giải nén từ điển đối số

Giải nén từ điển đối số tương tự như giải nén bộ dữ liệu đối số. Khi dấu hoa thị kép (

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
279) đứng trước một đối số trong lệnh gọi hàm Python, nó chỉ định rằng đối số đó là một từ điển cần được giải nén, với các mục kết quả được chuyển đến hàm dưới dạng đối số từ khóa

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
03

Các mục trong từ điển

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
288 được giải nén và chuyển đến
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 dưới dạng đối số từ khóa. Vì vậy,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
290 tương đương với
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
291

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
04

Trên thực tế, hãy kiểm tra điều này

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
05

Ở đây,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
292 tạo một từ điển từ các cặp khóa/giá trị được chỉ định. Sau đó, toán tử dấu hoa thị kép (
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
279) giải nén nó và chuyển các từ khóa tới
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36

Để tất cả chúng cùng nhau

Hãy coi

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
253 là danh sách đối số vị trí có độ dài thay đổi và
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
296 là danh sách đối số từ khóa có độ dài thay đổi

Ghi chú. Để có cái nhìn khác về

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
253 và
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
296, hãy xem Python args và kwargs. làm sáng tỏ

Tất cả ba—tham số vị trí tiêu chuẩn,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
253 và
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
296—có thể được sử dụng trong một định nghĩa hàm Python. If so, then they should be specified in that order

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
06

Điều này mang lại sự linh hoạt gần như bạn có thể cần trong một giao diện chức năng

Nhiều lần giải nén trong một lệnh gọi hàm Python

Python phiên bản 3. 5 đã giới thiệu hỗ trợ cho các khái quát hóa giải nén bổ sung, như được nêu trong PEP 448. One thing these enhancements allow is multiple unpackings in a single Python function call

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
07

You can specify multiple dictionary unpackings in a Python function call as well

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
08

Note. This enhancement is available only in Python version 3. 5 or later. If you try this in an earlier version, then you’ll get a

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
301 exception

By the way, the unpacking operators

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
250 and
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
279 don’t apply only to variables, as in the examples above. You can also use them with literals that are iterable

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
09

Here, the literal lists

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
304 and
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
305 are specified for tuple unpacking, and the literal dictionaries
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
306 and
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
307 are specified for dictionary unpacking

Keyword-Only Arguments

A Python function in version 3. x can be defined so that it takes keyword-only arguments. These are function arguments that must be specified by keyword. Let’s explore a situation where this might be beneficial

Suppose you want to write a Python function that takes a variable number of string arguments, concatenates them together separated by a dot (

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
308), and prints them to the console. Something like this will do to start

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
30

As it stands, the output prefix is hard-coded to the string

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
309. What if you want to modify the function to accept this as an argument as well, so the user can specify something else? This is one possibility

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
31

This works as advertised, but there are a couple of undesirable things about this solution

  1. The

    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    310 string is lumped together with the strings to be concatenated. Just from looking at the function call, it isn’t clear that the first argument is treated differently from the rest. To know that, you’d have to go back and look at the function definition

  2. >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    310 isn’t optional. It always has to be included, and there’s no way to assume a default value

You might think you could overcome the second issue by specifying a parameter with a default value, like this, perhaps

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
32

Unfortunately, this doesn’t work quite right.

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
310 is a positional parameter, so the interpreter assumes that the first argument specified in the function call is the intended output prefix. This means there isn’t any way to omit it and obtain the default value

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
33

What if you try to specify

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
310 as a keyword argument? Well, you can’t specify it first

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
34

As you’ve seen previously, when both types of arguments are given, all positional arguments must come before any keyword arguments

However, you can’t specify it last either

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
35

Again,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
310 is a positional parameter, so it’s assigned the first argument specified in the call (which is
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
315 in this case). Then, when it’s specified again as a keyword argument at the end, Python thinks it’s been assigned twice

Keyword-only parameters help solve this dilemma. In the function definition, specify

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
253 to indicate a variable number of positional arguments, and then specify
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
310 after that

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36

In that case,

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
310 becomes a keyword-only parameter. Its value will never be filled by a positional argument. It can only be specified by a named keyword argument

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
37

Note that this is only possible in Python 3. In versions 2. x of Python, specifying additional parameters after the

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
253 variable arguments parameter raises an error

Keyword-only arguments allow a Python function to take a variable number of arguments, followed by one or more additional options as keyword arguments. If you wanted to modify

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
320 so that the separator character can optionally be specified as well, then you could add an additional keyword-only argument

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
38

If a keyword-only parameter is given a default value in the function definition (as it is in the example above), and the keyword is omitted when the function is called, then the default value is supplied

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
39

If, on the other hand, the parameter isn’t given a default value, then it becomes required, and failure to specify it results in an error

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
50

What if you want to define a Python function that takes a keyword-only argument but doesn’t take a variable number of positional arguments? For example, the following function performs the specified operation on two numerical arguments

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
51

If you wanted to make

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
321 a keyword-only parameter, then you could add an extraneous dummy variable argument parameter and just ignore it

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
52

The problem with this solution is that

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
322 absorbs any extraneous positional arguments that might happen to be included

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
53

In this example, the extra argument shouldn’t be there (as the argument itself announces). Instead of quietly succeeding, it should really result in an error. The fact that it doesn’t is untidy at best. At worst, it may cause a result that appears misleading

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
54

To remedy this, version 3 allows a variable argument parameter in a Python function definition to be just a bare asterisk (

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
250), with the name omitted

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
55

The bare variable argument parameter

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
250 indicates that there aren’t any more positional parameters. This behavior generates appropriate error messages if extra ones are specified. It allows keyword-only parameters to follow

Positional-Only Arguments

As of Python 3. 8, function parameters can also be declared positional-only, meaning the corresponding arguments must be supplied positionally and can’t be specified by keyword

To designate some parameters as positional-only, you specify a bare slash (

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
325) in the parameter list of a function definition. Any parameters to the left of the slash (
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
325) must be specified positionally. For example, in the following function definition,
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
17 and
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
18 are positional-only parameters, but
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
19 may be specified by keyword

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
56

This means that the following calls are valid

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
57

The following call to

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36, however, is not valid

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
58

The positional-only and keyword-only designators may both be used in the same function definition

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
59

In this example

  • >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    17 and
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    18 are positional-only
  • >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    275 and
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    334 are keyword-only
  • >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    19 and
    >>> a = ['foo', 'bar', 'baz', 'qux']
    >>> len(a)
    4
    
    336 may be specified positionally or by keyword

For more information on positional-only parameters, see the Python 3. 8 release highlights

Docstrings

When the first statement in the body of a Python function is a string literal, it’s known as the function’s docstring. A docstring is used to supply documentation for a function. It can contain the function’s purpose, what arguments it takes, information about return values, or any other information you think would be useful

The following is an example of a function definition with a docstring

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
00

Về mặt kỹ thuật, các chuỗi tài liệu có thể sử dụng bất kỳ cơ chế trích dẫn nào của Python, nhưng quy ước được đề xuất là trích dẫn ba lần bằng cách sử dụng các ký tự trích dẫn kép (

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
337), như minh họa ở trên. Nếu chuỗi tài liệu nằm trên một dòng, thì dấu ngoặc kép đóng phải nằm trên cùng một dòng với dấu ngoặc kép mở

Các chuỗi tài liệu nhiều dòng được sử dụng cho tài liệu dài hơn. Một chuỗi tài liệu nhiều dòng phải bao gồm một dòng tóm tắt, theo sau là một dòng trống, tiếp theo là một mô tả chi tiết hơn. Các trích dẫn đóng phải nằm trên một dòng

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
01

Định dạng chuỗi tài liệu và quy ước ngữ nghĩa được trình bày chi tiết trong PEP 257

Khi một chuỗi tài liệu được xác định, trình thông dịch Python sẽ gán nó cho một thuộc tính đặc biệt của hàm có tên là

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
338. Thuộc tính này là một trong những bộ định danh chuyên biệt trong Python, đôi khi được gọi là thuộc tính ma thuật hoặc phương thức ma thuật vì chúng cung cấp chức năng ngôn ngữ đặc biệt

Ghi chú. These attributes are also referred to by the colorful nickname dunder attributes and dunder methods. Từ dunder kết hợp d từ double và under từ ký tự gạch dưới (

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
339). Bạn sẽ gặp nhiều thuộc tính và phương thức khác trong các hướng dẫn trong tương lai của loạt bài này

Bạn có thể truy cập chuỗi tài liệu của hàm bằng biểu thức

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
340. The docstrings for the above examples can be displayed as follows

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
02

Trong trình thông dịch Python tương tác, bạn có thể nhập

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
341 để hiển thị chuỗi tài liệu cho
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
27

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
03

It’s considered good coding practice to specify a docstring for each Python function you define. For more on docstrings, check out Documenting Python Code. A Complete Guide

Python Function Annotations

As of version 3. 0, Python provides an additional feature for documenting a function called a function annotation. Annotations provide a way to attach metadata to a function’s parameters and return value

To add an annotation to a Python function parameter, insert a colon (

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
29) followed by any expression after the parameter name in the function definition. To add an annotation to the return value, add the characters
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
344 and any expression between the closing parenthesis of the parameter list and the colon that terminates the function header. Here’s an example

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
04

The annotation for parameter

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
275 is the string
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
346, for
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
334 the string
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
348, and for the function return value the string
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
349

The Python interpreter creates a dictionary from the annotations and assigns them to another special dunder attribute of the function called

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
350. The annotations for the Python function
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 shown above can be displayed as follows

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
05

The keys for the parameters are the parameter names. The key for the return value is the string

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
352

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
06

Note that annotations aren’t restricted to string values. They can be any expression or object. For example, you might annotate with type objects

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
07

An annotation can even be a composite object like a list or a dictionary, so it’s possible to attach multiple items of metadata to the parameters and return value

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
08

In the example above, an annotation is attached to the parameter

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
353 and to the return value. Each annotation is a dictionary containing a string description and a type object

If you want to assign a default value to a parameter that has an annotation, then the default value goes after the annotation

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
09

What do annotations do? Frankly, they don’t do much of anything. They’re just kind of there. Let’s look at one of the examples from above again, but with a few minor modifications

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
10

What’s going on here? The annotations for

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 indicate that the first argument is
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
177, the second argument
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
180, and the return value
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
357. But the subsequent call to
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36 breaks all the rules. The arguments are
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
180 and
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
357, respectively, and the return value is a tuple. Yet the interpreter lets it all slide with no complaint at all

Annotations don’t impose any semantic restrictions on the code whatsoever. They’re simply bits of metadata attached to the Python function parameters and return value. Python dutifully stashes them in a dictionary, assigns the dictionary to the function’s

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
350 dunder attribute, and that’s it. Annotations are completely optional and don’t have any impact on Python function execution at all

To quote Amahl in Amahl and the Night Visitors, “What’s the use of having it then?”

For starters, annotations make good documentation. You can specify the same information in the docstring, of course, but placing it directly in the function definition adds clarity. The types of the arguments and the return value are obvious on sight for a function header like this

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
11

Granted, the interpreter doesn’t enforce adherence to the types specified, but at least they’re clear to someone reading the function definition

Deep Dive. Enforcing Type-Checking

If you were inclined to, you could add code to enforce the types specified in the function annotations. Here’s a function that checks the actual type of each argument against what’s specified in the annotation for the corresponding parameter. It displays

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
23 if they match ans
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
24 if they don’t

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
12

(The

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
364 module contains functions that obtain useful information about live objects—in this case, function
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
36. )

A function defined like the one above could, if desired, take some sort of corrective action when it detects that the passed arguments don’t conform to the types specified in the annotations

In fact, a scheme for using annotations to perform static type checking in Python is described in PEP 484. A free static type checker for Python called mypy is available, which is built on the PEP 484 specification

There’s another benefit to using annotations as well. The standardized format in which annotation information is stored in the

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
350 attribute lends itself to the parsing of function signatures by automated tools

When it comes down to it, annotations aren’t anything especially magical. You could even define your own without the special syntax that Python provides. Here’s a Python function definition with type object annotations attached to the parameters and return value

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
13

The following is essentially the same function, with the

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
350 dictionary constructed manually

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
14

The effect is identical in both cases, but the first is more visually appealing and readable at first glance

In fact, the

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
350 attribute isn’t significantly different from most other attributes of a function. For example, it can be modified dynamically. You could choose to use the return value attribute to count how many times a function is executed

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len(a)
4
15

Python function annotations are nothing more than dictionaries of metadata. It just happens that you can create them with convenient syntax that’s supported by the interpreter. They’re whatever you choose to make of them

Conclusion

As applications grow larger, it becomes increasingly important to modularize code by breaking it up into smaller functions of manageable size. You now hopefully have all the tools you need to do this

You’ve learned

  • How to create a user-defined function in Python
  • Several different ways you can pass arguments to a function
  • How you can return data from a function to its caller
  • How to add documentation to functions with docstrings and annotations

Next up in this series are two tutorials that cover searching and pattern matching. You will get an in-depth look at a Python module called re, which contains functionality for searching and matching using a versatile pattern syntax called a regular expression

« Python String Formatting Techniques

Defining Your Own Python Function

Regular Expressions. Regexes in Python (Part 1) »

Mark as Completed

Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding. Defining and Calling Python Functions

🐍 Python Tricks 💌

Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team

Thuộc tính chức năng trong python là gì?

Send Me Python Tricks »

About John Sturtz

Thuộc tính chức năng trong python là gì?
Thuộc tính chức năng trong python là gì?

John is an avid Pythonista and a member of the Real Python tutorial team

» More about John


Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. Các thành viên trong nhóm đã làm việc trong hướng dẫn này là

Thuộc tính chức năng trong python là gì?

Aldren

Thuộc tính chức năng trong python là gì?

Jaya

Thuộc tính chức năng trong python là gì?

Joanna

Master Real-World Python Skills With Unlimited Access to Real Python

Thuộc tính chức năng trong python là gì?

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas

Nâng cao kỹ năng Python của bạn »

Master Real-World Python Skills
With Unlimited Access to Real Python

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas

Nâng cao kỹ năng Python của bạn »

What Do You Think?

Đánh giá bài viết này

Tweet Chia sẻ Chia sẻ Email

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know

Commenting Tips. The most useful comments are those written with the goal of learning from or helping out other students. Get tips for asking good questions and get answers to common questions in our support portal

What is a function attribute?

Function attributes are extensions implemented to enhance the portability of programs developed with GNU C . Các thuộc tính có thể chỉ định cho các hàm cung cấp các cách rõ ràng để giúp trình biên dịch tối ưu hóa các lệnh gọi hàm và hướng dẫn trình biên dịch kiểm tra nhiều khía cạnh hơn của mã. Others provide additional functionality.

Can a Python function have an attribute?

Yes, Python functions are objects. And because they're objects, they have attributes . And because they're objects, we can assign new attributes to them, as well as retrieve the values of those attributes.

What is difference between function and attribute in Python?

A variable stored in an instance or class is called an attribute. A function stored in an instance or class is called a method .

What are the 4 types of functions in Python?

The following are the different types of Python Functions. .
Python Built-in Functions
Python Recursion Functions
Hàm Lambda trong Python
Python User-defined Functions