Thứ tự đối số mặc định của Python

Như đã trình bày trong ví dụ trước, mỗi đối số của hàm có một tên, nhưng khi hàm được gọi, các đối số không nhất thiết phải được liên kết với các tên đó. Khi các đối số được chuyển đến một hàm không có tên, Python giả định rằng bạn đã nhập các đối số theo đúng thứ tự mà chúng đã được xác định. Để minh họa, hãy xem xét một hàm đếm số lần một chữ cái cụ thể xuất hiện trong một chuỗi

def count_letter[string,letter]:
    count = 0
    for i in string:
        if i == letter:
            count = count + 1

    return count
Nếu chúng ta vô tình chuyển ký tự đầu tiên, tiếp theo là chuỗi, hàm sẽ chỉ trả về số 0, trừ khi ký tự và chuỗi giống hệt nhau. Để giảm bớt sự cần thiết phải biết thứ tự của các đối số trong một hàm, Python cho phép các đối số được đặt tên. Khi gọi một hàm, bạn có thể đặt tên và dấu bằng trước một số hoặc tất cả các đối số để cho hàm biết chính xác bạn đang chuyển đối số nào cho hàm. Vì vậy, nếu chúng ta gọi hàm
     num = count_letter[letter='a',string='dead parrot']
7 as
     num = count_letter[letter='a',string='dead parrot']
, chúng ta sẽ nhận được câu trả lời đúng [2] mặc dù các đối số theo thứ tự khác với thứ tự chúng được xác định

Để cung cấp tính linh hoạt cao hơn nữa, khi bạn định nghĩa một hàm, Python cho phép bạn chỉ định một giá trị mặc định cho bất kỳ hoặc tất cả các đối số của hàm đó; . Để cung cấp một giá trị mặc định khi xác định một hàm, bạn sử dụng một cú pháp tương tự như cách bạn sử dụng các đối số được đặt tên khi gọi một hàm, cụ thể là theo tên đối số với một dấu bằng và giá trị mặc định mong muốn. Sử dụng hàm count_letter làm ví dụ, giả sử theo mặc định, chúng ta muốn đếm số khoảng trống trong một chuỗi. Chúng tôi sẽ xác định lại chức năng như sau

def count_letter[string,letter=' ']:
    count = 0
    for i in string:
        if i == letter:
        count = count + 1

    return count
Thông số kỹ thuật của letter=' ' cho Python biết rằng khi hàm count_letter được gọi và không có giá trị nào được đưa ra cho đối số letter, hãy sử dụng khoảng trống làm giá trị cho letter. Hãy nhớ rằng nếu một giá trị được cung cấp cho chữ cái, dưới dạng đối số được đặt tên hoặc bằng cách gọi hàm có hai đối số, giá trị mặc định này sẽ bị ghi đè. Do đó, tất cả các lệnh gọi hàm sau đây sẽ đếm số lượng khoảng trống trong chuỗi đã chỉ định.
mystring = 'this parrot is dead'
count_letter[mystring,' ']
count_letter[mystring]
count_letter[letter=' ',string=mystring]

Khi bạn kết hợp các đối số có tên và không có tên trong một lệnh gọi hàm, các đối số chưa được đặt tên phải xuất hiện trước các đối số có tên trong danh sách đối số. Vì vậy, khi viết một hàm, bạn nên đặt các đối số cần thiết cho hàm trong danh sách đối số trước những đối số mà bạn cho là tùy chọn.

Giả sử chúng ta muốn mở rộng chương trình Count_letter bằng cách cung cấp cho nó một đối số bổ sung đại diện cho một ký tự mà chữ cái mà chúng ta đang tìm kiếm sẽ được thay đổi. Vì chuỗi là bất biến nên chúng ta không thể thay đổi chuỗi trực tiếp; . Chúng ta sẽ gọi hàm change_letter và làm cho hành vi mặc định của nó thay đổi khoảng trống thành chuỗi trống, i. e. xóa khoảng trống khỏi chuỗi

def findvolume[chiều dài=1, chiều rộng=1, chiều sâu=1]

print["Chiều dài = " + str[chiều dài]]

in["Chiều rộng = " + str[chiều rộng]]

in["Độ sâu = " + str[độ sâu]]

trả về chiều dài * chiều rộng * chiều sâu;

findvolume[chiều dài=5, chiều sâu=2, chiều rộng=4]

findvolume[2, depth=3, width=4]

Các tham số chức năng có thể có các giá trị mặc định được tính toán trong quá trình định nghĩa chức năng và được lưu lại. Đề xuất này giới thiệu một dạng mặc định đối số mới, được xác định bởi một biểu thức sẽ được đánh giá tại thời điểm gọi hàm

Động lực

Các đối số chức năng tùy chọn, nếu bị bỏ qua, thường có một số loại giá trị logic mặc định. Khi giá trị này phụ thuộc vào các đối số khác hoặc cần được đánh giá lại sau mỗi lần gọi hàm, thì hiện tại không có cách rõ ràng nào để nêu rõ điều này trong tiêu đề hàm

Thành ngữ hợp pháp hiện nay cho điều này bao gồm

# Very common: Use None and replace it in the function
def bisect_right[a, x, lo=0, hi=None, *, key=None]:
    if hi is None:
        hi = len[a]

# Also well known: Use a unique custom sentinel object
_USE_GLOBAL_DEFAULT = object[]
def connect[timeout=_USE_GLOBAL_DEFAULT]:
    if timeout is _USE_GLOBAL_DEFAULT:
        timeout = default_timeout

# Unusual: Accept star-args and then validate
def add_item[item, *optional_target]:
    if not optional_target:
        target = []
    else:
        target = optional_target[0]

Trong mỗi biểu mẫu,

     num = count_letter[letter='a',string='dead parrot']
8 không hiển thị giá trị mặc định thực. Mỗi người cũng có những vấn đề khác;

Sự chỉ rõ

Các đối số mặc định của hàm có thể được xác định bằng cách sử dụng ký hiệu

def count_letter[string,letter=' ']:
    count = 0
    for i in string:
        if i == letter:
        count = count + 1

    return count
0 mới

def bisect_right[a, x, lo=0, hi=>len[a], *, key=None]:
def connect[timeout=>default_timeout]:
def add_item[item, target=>[]]:
def format_time[fmt, time_t=>time.time[]]:

Biểu thức được lưu ở dạng mã nguồn cho mục đích kiểm tra và mã byte để đánh giá nó được thêm vào phần thân của hàm

Đáng chú ý, biểu thức được đánh giá trong phạm vi thời gian chạy của hàm, KHÔNG phải phạm vi mà hàm được xác định [như các giá trị mặc định giới hạn sớm]. Điều này cho phép biểu thức tham chiếu đến các đối số khác

Nhiều đối số bị ràng buộc muộn được đánh giá từ trái sang phải và có thể tham chiếu đến các giá trị đã xác định trước đó. Thứ tự được xác định bởi hàm, bất kể thứ tự mà các đối số từ khóa có thể được chuyển

def prevref[word=”foo”, a=>len[word], b=>a//2]. # Selfref def hợp lệ[spam=>spam]. # UnboundLocalError def spaminate[xúc xích=>trứng + 1, egg=>xúc xích - 1]. # Khó hiểu, đừng làm điều này def frob[n=>len[items], items=[]]. # Xem bên dưới

Thứ tự đánh giá là từ trái sang phải; . Nếu không, tất cả các đối số sẽ được chỉ định hoàn toàn từ trái sang phải

Từ chối lựa chọn chính tả

Mặc dù tài liệu này chỉ định một cú pháp duy nhất

def count_letter[string,letter=' ']:
    count = 0
    for i in string:
        if i == letter:
        count = count + 1

    return count
1, cách viết thay thế cũng hợp lý tương tự. Các cách viết sau đây đã được xem xét

def bisect[a, hi=>len[a]]:
def bisect[a, hi:=len[a]]:
def bisect[a, hi?=len[a]]:
def bisect[a, @hi=len[a]]:

Vì các đối số mặc định hoạt động phần lớn giống nhau cho dù chúng bị ràng buộc sớm hay muộn, nên cú pháp được chọn

def count_letter[string,letter=' ']:
    count = 0
    for i in string:
        if i == letter:
        count = count + 1

    return count
2 cố ý giống với cú pháp ràng buộc sớm hiện có

Một lý do để từ chối cú pháp

def count_letter[string,letter=' ']:
    count = 0
    for i in string:
        if i == letter:
        count = count + 1

    return count
3 là hành vi của nó với các chú thích. Chú thích đi trước mặc định, do đó, trong tất cả các tùy chọn cú pháp, nó phải rõ ràng [cả đối với con người và trình phân tích cú pháp] cho dù đây là chú thích, mặc định hay cả hai. Cú pháp thay thế
def bisect_right[a, x, lo=0, hi=>len[a], *, key=None]:
def connect[timeout=>default_timeout]:
def add_item[item, target=>[]]:
def format_time[fmt, time_t=>time.time[]]:
0 có nguy cơ bị hiểu sai thành
def bisect_right[a, x, lo=0, hi=>len[a], *, key=None]:
def connect[timeout=>default_timeout]:
def add_item[item, target=>[]]:
def format_time[fmt, time_t=>time.time[]]:
1 với chú thích bị bỏ qua do nhầm lẫn và do đó có thể che lấp các lỗi. Cú pháp đã chọn
def bisect_right[a, x, lo=0, hi=>len[a], *, key=None]:
def connect[timeout=>default_timeout]:
def add_item[item, target=>[]]:
def format_time[fmt, time_t=>time.time[]]:
2 không có vấn đề này

Làm thế nào để dạy điều này

Các đối số mặc định ràng buộc sớm phải luôn được dạy trước, vì chúng là cách đơn giản và hiệu quả hơn để đánh giá các đối số. Dựa trên chúng, các đối số bị ràng buộc muộn thường tương đương với mã ở đầu hàm

     num = count_letter[letter='a',string='dead parrot']
0

Một nguyên tắc đơn giản là. “mục tiêu=biểu thức” được đánh giá khi hàm được xác định và “mục tiêu=>biểu thức” được đánh giá khi hàm được gọi. Dù bằng cách nào, nếu đối số được cung cấp tại thời điểm gọi, giá trị mặc định sẽ bị bỏ qua. Mặc dù điều này không giải thích hoàn toàn tất cả sự tinh tế, nhưng nó đủ để bao hàm sự khác biệt quan trọng ở đây [và thực tế là chúng tương tự nhau]

Tương tác với các đề xuất khác

PEP 661 cố gắng giải quyết một trong những vấn đề tương tự như vấn đề này. Nó tìm cách cải thiện tài liệu về các giá trị trọng điểm trong các đối số mặc định, trong đó đề xuất này tìm cách loại bỏ nhu cầu về trọng điểm trong nhiều trường hợp phổ biến. PEP 661 có thể cải thiện tài liệu trong các chức năng phức tạp tùy ý [nó trích dẫn

def bisect_right[a, x, lo=0, hi=>len[a], *, key=None]:
def connect[timeout=>default_timeout]:
def add_item[item, target=>[]]:
def format_time[fmt, time_t=>time.time[]]:
3 làm động lực chính của nó, có hai đối số phải được chỉ định cả hai hoặc không]; . Ngoài ra, các đối tượng canh gác chuyên dụng có thể được sử dụng làm khóa tra cứu từ điển, trong đó PEP 671 không áp dụng

Đôi khi, một hệ thống chung để đánh giá hoãn lại đã được đề xuất [đừng nhầm lẫn với PEP 563 và PEP 649 dành riêng cho các chú thích]. Mặc dù nhìn bề ngoài có vẻ như các giá trị mặc định của đối số bị ràng buộc muộn có bản chất tương tự nhau, nhưng trên thực tế chúng là những ý tưởng không liên quan và trực giao, và cả hai đều có thể có giá trị đối với ngôn ngữ. Việc chấp nhận hoặc từ chối đề xuất này sẽ không ảnh hưởng đến khả năng tồn tại của đề xuất đánh giá bị trì hoãn và ngược lại. [Một điểm khác biệt chính giữa đánh giá trì hoãn tổng quát và giá trị mặc định của đối số là giá trị mặc định của đối số sẽ luôn luôn và chỉ được đánh giá khi hàm bắt đầu thực thi, trong khi các biểu thức trì hoãn sẽ chỉ được nhận ra khi tham chiếu. ]

Chi tiết triển khai

Phần sau đây liên quan đến việc triển khai tham chiếu và không nhất thiết là một phần của thông số kỹ thuật

Giá trị mặc định của đối số [vị trí hoặc từ khóa] có cả giá trị của chúng, như đã được giữ lại và một phần thông tin bổ sung. Đối với các đối số vị trí, các phần bổ sung được lưu trữ trong một bộ trong

def bisect_right[a, x, lo=0, hi=>len[a], *, key=None]:
def connect[timeout=>default_timeout]:
def add_item[item, target=>[]]:
def format_time[fmt, time_t=>time.time[]]:
4 và đối với chỉ từ khóa, một lệnh trong
def bisect_right[a, x, lo=0, hi=>len[a], *, key=None]:
def connect[timeout=>default_timeout]:
def add_item[item, target=>[]]:
def format_time[fmt, time_t=>time.time[]]:
5. Nếu thuộc tính này là
     num = count_letter[letter='a',string='dead parrot']
9, nó tương đương với việc có
     num = count_letter[letter='a',string='dead parrot']
9 cho mọi đối số mặc định

Đối với mỗi tham số có mặc định ràng buộc muộn, giá trị đặc biệt

def bisect_right[a, x, lo=0, hi=>len[a], *, key=None]:
def connect[timeout=>default_timeout]:
def add_item[item, target=>[]]:
def format_time[fmt, time_t=>time.time[]]:
8 được lưu dưới dạng trình giữ chỗ giá trị và thông tin bổ sung tương ứng cần được truy vấn. Nếu nó là
     num = count_letter[letter='a',string='dead parrot']
9, thì giá trị mặc định thực sự là giá trị
def bisect_right[a, x, lo=0, hi=>len[a], *, key=None]:
def connect[timeout=>default_timeout]:
def add_item[item, target=>[]]:
def format_time[fmt, time_t=>time.time[]]:
8;

Khi một tham số có giá trị mặc định bị ràng buộc muộn bị bỏ qua, hàm sẽ bắt đầu với tham số không bị ràng buộc. Hàm bắt đầu bằng cách kiểm tra từng tham số với mặc định bị ràng buộc muộn bằng cách sử dụng mã opcode mới QUERY_FAST/QUERY_DEREF và nếu không bị ràng buộc, sẽ đánh giá biểu thức ban đầu. Mã lệnh này [chỉ khả dụng cho các biến cục bộ nhanh và biến đóng] đẩy True vào ngăn xếp nếu cục bộ đã cho có giá trị và Sai nếu không - nghĩa là nó đẩy Sai nếu LOAD_FAST hoặc LOAD_DEREF sẽ tăng UnboundLocalError và True nếu nó thành công

Các tham chiếu biến không theo thứ tự được cho phép miễn là tham chiếu đó có giá trị từ một đối số hoặc giá trị mặc định giới hạn sớm

chi phí

Khi không sử dụng giá trị mặc định của đối số giới hạn cuối, các chi phí sau sẽ là tất cả những chi phí phát sinh

  • Các đối tượng hàm yêu cầu thêm hai con trỏ, sẽ là NULL
  • Biên dịch mã và chức năng xây dựng có kiểm tra cờ bổ sung
  • Sử dụng
    def bisect_right[a, x, lo=0, hi=>len[a], *, key=None]:
    def connect[timeout=>default_timeout]:
    def add_item[item, target=>[]]:
    def format_time[fmt, time_t=>time.time[]]:
    
    8 làm giá trị mặc định sẽ yêu cầu xác minh thời gian chạy để xem có tồn tại giá trị mặc định giới hạn muộn hay không

Các chi phí này dự kiến ​​sẽ ở mức tối thiểu [trên Linux 64-bit, điều này làm tăng tất cả các đối tượng chức năng từ 152 byte lên 168], hầu như không có chi phí thời gian chạy khi không sử dụng các giá trị mặc định giới hạn trễ

không tương thích ngược

Khi các giá trị mặc định giới hạn trễ không được sử dụng, hành vi phải giống hệt nhau. Cần cẩn thận nếu tìm thấy Dấu ba chấm, vì dấu ba chấm có thể không đại diện cho chính nó, nhưng ngoài ra, các công cụ sẽ thấy mã hiện tại không thay đổi

Người giới thiệu

https. //github. com/rosuav/cpython/tree/pep-671

bản quyền

Tài liệu này được đặt trong phạm vi công cộng hoặc theo CC0-1. 0-Giấy phép phổ thông, tùy theo điều kiện nào dễ dãi hơn

Thứ tự của đối số mặc định là gì?

Thứ tự của đối số mặc định sẽ là ngẫu nhiên .

Thứ tự của các đối số có quan trọng trong Python không?

Thứ tự lập luận quan trọng . Các đối số cần được truyền theo đúng thứ tự như thứ tự của các tham số đã được khai báo trong định nghĩa của hàm.

Thứ tự của các đối số có quan trọng không?

Vâng, điều đó quan trọng . Các đối số phải được đưa ra theo thứ tự mà hàm mong đợi chúng. C truyền đối số theo giá trị. Nó không có cách nào để liên kết một giá trị với một đối số khác với vị trí.

Thứ tự của các đối số khi gọi một hàm là gì?

3. Đối số vị trí. Trong khi gọi hàm, các giá trị được truyền qua đối số phải là theo thứ tự tham số trong định nghĩa hàm . Điều này được gọi là đối số vị trí.

Chủ Đề