Bạn có thể có đối số mặc định trong Python không?

Việc gán giá trị mặc định cho đối số từ khóa là rất phổ biến khi xác định hàm Python. Vì nó có thể tránh được các lỗi tiềm ẩn, nên phương pháp này được khuyến khích thực hiện nếu chúng ta không thể chắc chắn liệu đối số từ khóa có luôn nhận được giá trị hay không

Gần đây tôi đã tìm thấy một lỗi khó chịu trong một số mã Python do sử dụng sai đối số mặc định. Nếu bạn đã biết mọi thứ về các đối số mặc định và chỉ muốn cười vào lỗi hài hước này, vui lòng chuyển đến cuối bài viết. Than ôi, đoạn mã do tôi viết, nhưng tôi khá chắc chắn rằng ngày hôm đó tôi đã bị thay thế bởi một bản sao độc ác của chính mình. Bạn biết đấy, đôi khi nó xảy ra. =]

Bài đăng này chỉ tóm tắt những điều cơ bản về các đối số tiêu chuẩn và mặc định trong các hàm Python và cảnh báo những cạm bẫy có thể xảy ra trong mã của bạn. Nếu bạn mới tiếp cận Python và bắt đầu viết các hàm, tôi thực sự khuyên bạn nên kiểm tra hướng dẫn sử dụng Python chính thức nói gì về chúng tại các liên kết sau. và

Đánh giá nhanh các chức năng

Python là một ngôn ngữ hướng đối tượng mạnh mẽ, đẩy mô hình lập trình này lên mức tối đa. Nhưng lập trình hướng đối tượng vẫn dựa trên khái niệm hàm, đó là thứ bạn có thể sử dụng để xử lý dữ liệu. Python có một khái niệm tổng quát hơn về callable object, đó là mọi đối tượng có thể gọi được, nghĩa là áp dụng trên một số dữ liệu

Các hàm trong Python là các đối tượng có thể gọi được và thoạt nhìn chúng hoạt động giống như các hàm trong các ngôn ngữ khác. Họ chỉ lấy một số dữ liệu, được gọi là đối số, xử lý chúng và trả về kết quả [là

def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
1 nếu không có câu lệnh
def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
2 nào được đưa ra]

Các đối số được khai báo [khi hàm được xác định] dưới dạng trình giữ chỗ cho các đối tượng thực sẽ được truyền khi hàm được gọi. Trong Python, bạn không khai báo loại đối số [chẳng hạn như bạn làm trong C hoặc Java] vì triết lý Python dựa trên tính đa hình

Hãy nhớ rằng các biến Python là các tham chiếu, đó là địa chỉ bộ nhớ của các biến thực tế. Điều này có nghĩa là các hàm Python luôn hoạt động giống như được "chuyển theo địa chỉ" [sử dụng danh pháp C/C++]. Khi bạn gọi một hàm, bạn không sao chép giá trị của các đối số vào phần giữ chỗ của hàm. Thay vào đó, bạn đang chỉ trình giữ chỗ cho chính biến đó. Điều này có một hệ quả rất quan trọng. bạn có thể thay đổi giá trị của biến từ bên trong hàm

Các tài liệu tham khảo đóng một vai trò rất lớn trong Python, là xương sống của cách tiếp cận đa hình đầy đủ của nó. Kiểm tra liên kết này để được giải thích rõ hơn về chủ đề rất quan trọng này

Để kiểm tra sự hiểu biết của bạn về hành vi cơ bản này của ngôn ngữ, hãy thử làm theo mã đơn giản này [trong đó biến ph là viết tắt của "placeholder"]

>>> def print_id[ph]:
..  print[hex[id[ph]]]
.. 
>>> a = 5
>>> print[hex[id[a]]]
0x84ab460
>>> print_id[a]
0x84ab460
>>> 
>>> def alter_value[ph]:
..  ph = ph + 1
..  return ph
.. 
>>> b = alter_value[a]
>>> b
6
>>> a
5
>>> hex[id[a]]
'0x84ab460'
>>> hex[id[b]]
'0x84ab470'
>>> 
>>> def alter_value[ph]:
..  ph.append[1]
..  return ph
.. 
>>> a = [1,2,3]
>>> b = alter_value[a]
>>> a
[1, 2, 3, 1]
>>> b
[1, 2, 3, 1]
>>> hex[id[a]]
'0xb701f72c'
>>> hex[id[b]]
'0xb701f72c'
>>>

Nếu bạn không ngạc nhiên với những gì đang xảy ra ở đây thì bạn đã nắm được một trong những điều quan trọng nhất trong Python và có thể yên tâm bỏ qua phần giải thích sau

Hàm

def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
3 chứng minh rằng các trình giữ chỗ bên trong các hàm là cùng một biến được truyền vào thời gian chạy [địa chỉ bộ nhớ của chúng khớp với nhau]

Hai phiên bản của

def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
4 có nghĩa là các hàm cố gắng thay đổi giá trị của đối số đã truyền. Như bạn có thể thấy phiên bản đầu tiên của
def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
4 không thành công trong việc thay đổi giá trị của biến
def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
6, trong khi phiên bản thứ hai thì không. Tại sao? . Mặt khác, danh sách không phải là bất biến, do đó, chức năng thực hiện những gì tên của nó cam kết. [ở đây bạn tìm thêm chi tiết về các loại bất biến]

Còn rất nhiều điều để nói về các hàm trong Python, nhưng đây là những viên gạch cơ bản về các đối số tiêu chuẩn

Giá trị đối số mặc định

Thỉnh thoảng, bạn cần xác định một hàm có thể chấp nhận một đối số và sẽ hoạt động khác đi cho dù có hay không có đối số. Nếu một ngôn ngữ không cung cấp hỗ trợ cho những trường hợp như vậy, bạn chỉ có hai lựa chọn. cách thứ nhất là xác định hai hàm khác nhau và quyết định hàm nào phù hợp nhất để gọi mỗi lần, cách thứ hai là buộc sự hiện diện của đối số, chọn giá trị "null" báo hiệu rằng không được sử dụng đối số . Cả hai giải pháp đều khả thi nhưng chưa tối ưu

Python, giống như các ngôn ngữ khác, cung cấp hỗ trợ cho các giá trị đối số mặc định, đó là các đối số hàm có thể được người gọi chỉ định hoặc để trống để tự động nhận giá trị được xác định trước

Một ví dụ rất đơn giản [và khá vô dụng] về giá trị mặc định như sau

def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]

Chức năng này có thể được chạy với một đối số [có thể là

def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
1]

def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
1

nhưng cũng có thể được gọi mà không có đối số, trong trường hợp đó, nó sẽ nhận giá trị mặc định được đặt trong nguyên mẫu của nó [

def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
1, trong trường hợp này]

def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
3

Bạn có thể tìm thấy nhiều ví dụ thú vị hơn trong thư viện chuẩn, chẳng hạn như trong hàm

def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
11 [kiểm tra phần ]

def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
5

Rõ ràng từ nguyên mẫu rằng một lệnh gọi như

def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
12 che giấu rất nhiều đối số bằng cách chuyển cho chúng các giá trị mặc định [
def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
13,
def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
14,
def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
15, v.v.] và làm cho hàm trở nên rất đơn giản để sử dụng trong trường hợp sử dụng tiêu chuẩn của nó

Như bạn thấy từ hàm dựng sẵn

def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
11, chúng ta có thể sử dụng cả đối số tiêu chuẩn và mặc định trong một hàm, nhưng thứ tự xuất hiện của chúng trong nguyên mẫu hàm là cố định. tất cả các đối số tiêu chuẩn trước, sau đó là các đối số mặc định

>>> def print_id[ph]:
..  print[hex[id[ph]]]
.. 
>>> a = 5
>>> print[hex[id[a]]]
0x84ab460
>>> print_id[a]
0x84ab460
>>> 
>>> def alter_value[ph]:
..  ph = ph + 1
..  return ph
.. 
>>> b = alter_value[a]
>>> b
6
>>> a
5
>>> hex[id[a]]
'0x84ab460'
>>> hex[id[b]]
'0x84ab470'
>>> 
>>> def alter_value[ph]:
..  ph.append[1]
..  return ph
.. 
>>> a = [1,2,3]
>>> b = alter_value[a]
>>> a
[1, 2, 3, 1]
>>> b
[1, 2, 3, 1]
>>> hex[id[a]]
'0xb701f72c'
>>> hex[id[b]]
'0xb701f72c'
>>>
1

Lý do rất dễ tìm ra. nếu chúng ta đặt một đối số có giá trị mặc định trước một giá trị tiêu chuẩn, ngôn ngữ sẽ không có cách nào để hiểu liệu đối số có giá trị mặc định đã được khởi tạo hay chưa. Ví dụ, xét định nghĩa hàm sau

>>> def print_id[ph]:
..  print[hex[id[ph]]]
.. 
>>> a = 5
>>> print[hex[id[a]]]
0x84ab460
>>> print_id[a]
0x84ab460
>>> 
>>> def alter_value[ph]:
..  ph = ph + 1
..  return ph
.. 
>>> b = alter_value[a]
>>> b
6
>>> a
5
>>> hex[id[a]]
'0x84ab460'
>>> hex[id[b]]
'0x84ab470'
>>> 
>>> def alter_value[ph]:
..  ph.append[1]
..  return ph
.. 
>>> a = [1,2,3]
>>> b = alter_value[a]
>>> a
[1, 2, 3, 1]
>>> b
[1, 2, 3, 1]
>>> hex[id[a]]
'0xb701f72c'
>>> hex[id[b]]
'0xb701f72c'
>>>
2

khi gọi hàm

def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
17 chúng ta sẽ chuyển đối số nào?

>>> def print_id[ph]:
..  print[hex[id[ph]]]
.. 
>>> a = 5
>>> print[hex[id[a]]]
0x84ab460
>>> print_id[a]
0x84ab460
>>> 
>>> def alter_value[ph]:
..  ph = ph + 1
..  return ph
.. 
>>> b = alter_value[a]
>>> b
6
>>> a
5
>>> hex[id[a]]
'0x84ab460'
>>> hex[id[b]]
'0x84ab470'
>>> 
>>> def alter_value[ph]:
..  ph.append[1]
..  return ph
.. 
>>> a = [1,2,3]
>>> b = alter_value[a]
>>> a
[1, 2, 3, 1]
>>> b
[1, 2, 3, 1]
>>> hex[id[a]]
'0xb701f72c'
>>> hex[id[b]]
'0xb701f72c'
>>>
8

Đánh giá đối số mặc định

Các đối số mặc định có thể được cung cấp dưới dạng các giá trị đơn giản hoặc là kết quả của một lệnh gọi hàm, nhưng kỹ thuật sau cần một cảnh báo rất lớn

Mặc dù các giá trị đơn giản được mã hóa cứng, do đó không cần đánh giá ngoại trừ được thực hiện tại thời điểm biên dịch, các lệnh gọi hàm dự kiến ​​sẽ được thực thi trong thời gian chạy [kiểm tra nhận xét này trên Reddit để được giải thích rõ hơn về vấn đề này]. Vì vậy, chúng tôi có thể viết

>>> def print_id[ph]:
..  print[hex[id[ph]]]
.. 
>>> a = 5
>>> print[hex[id[a]]]
0x84ab460
>>> print_id[a]
0x84ab460
>>> 
>>> def alter_value[ph]:
..  ph = ph + 1
..  return ph
.. 
>>> b = alter_value[a]
>>> b
6
>>> a
5
>>> hex[id[a]]
'0x84ab460'
>>> hex[id[b]]
'0x84ab470'
>>> 
>>> def alter_value[ph]:
..  ph.append[1]
..  return ph
.. 
>>> a = [1,2,3]
>>> b = alter_value[a]
>>> a
[1, 2, 3, 1]
>>> b
[1, 2, 3, 1]
>>> hex[id[a]]
'0xb701f72c'
>>> hex[id[b]]
'0xb701f72c'
>>>
9

mong đợi chức năng

def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
32 cung cấp chính xác thời gian hiện tại mỗi khi chúng tôi gọi nó. Thật không may, điều này không hoạt động. các đối số mặc định được ước tính tại thời điểm xác định [ví dụ: khi bạn nhập mô-đun lần đầu tiên] và kết quả của các lệnh gọi liên tiếp là

def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
1

Nếu bạn đặt giá trị mặc định cho một thể hiện của lớp, kết quả có thể còn xa lạ hơn, như bạn có thể đọc trong Hướng dẫn về Python của Người đi nhờ xe. Theo đề xuất của tài nguyên sau, giải pháp thông thường là thay thế giá trị mặc định bằng

def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
1 và kiểm tra giá trị của đối số bên trong hàm

def log[message=None]:
    if message:
        print["LOG: {0}".format[message]]
0

kết luận

Các đối số mặc định có thể đơn giản hóa đáng kể các API, miễn là bạn chú ý đến "điểm lỗi" duy nhất của chúng, thời gian đánh giá. Đáng ngạc nhiên, một trong những điều cơ bản nhất trong Python, đối số hàm và tham chiếu, là một trong những nguồn gây ra lỗi lớn nhất, đôi khi đối với các lập trình viên có kinh nghiệm. Tôi khuyên bạn nên dành thời gian nghiên cứu tài liệu tham khảo và tính đa hình

cập nhật

2015-06-10. brandjon đã thêm một số thông tin hữu ích tại đây, giải thích cách CPython xử lý các hàm và giá trị đơn giản. Tôi đã thêm liên kết vào phần nhận xét

Đối số mặc định trong Python là gì?

Đối số mặc định là giá trị dự phòng . Các tham số như vậy là tùy chọn trong khi gọi hàm. Nếu không có đối số nào được cung cấp, thì giá trị mặc định sẽ được sử dụng và nếu có đối số được cung cấp, nó sẽ ghi đè lên giá trị mặc định.

Các hàm tạo Python có thể có các đối số mặc định không?

Có thể có hàm tạo với các đối số mặc định . Điều đó có nghĩa là nếu hàm tạo được định nghĩa với n tham số, chúng ta có thể gọi nó với ít hơn n đối số được chỉ định trong lệnh gọi. Tên bất kỳ [ para1,para2,para3,para 4 =val4, … paran = valna>

3 loại đối số trong Python là gì?

Do đó, chúng tôi kết luận rằng Đối số hàm Python và ba loại đối số hàm của nó. Đây là- các đối số mặc định, từ khóa và tùy ý .

4 loại đối số trong Python là gì?

Trong Python, chúng ta có 4 loại đối số hàm sau. .
Đối số mặc định
Đối số từ khóa [đối số được đặt tên]
đối số vị trí
Đối số tùy ý [đối số có độ dài thay đổi *args và **kwargs ]

Chủ Đề