เหตุใดอาร์กิวเมนต์ที่ไม่ใช่ค่าเริ่มต้นจึงไม่เป็นไปตามอาร์กิวเมนต์เริ่มต้น


144

เหตุใดโค้ดส่วนนี้จึงส่ง SyntaxError

  >>> def fun1(a="who is you", b="True", x, y):
...     print a,b,x,y
... 
  File "<stdin>", line 1
SyntaxError: non-default argument follows default argument

ขณะที่โค้ดต่อไปนี้ทำงานโดยไม่มีข้อผิดพลาดที่มองเห็นได้:

>>> def fun1(x, y, a="who is you", b="True"):
...     print a,b,x,y
... 

ใน python นั่นคือโครงสร้างเป็นอย่างไรเมื่อคุณกำหนดฟังก์ชันdef myfunction(position_arguments, *arguments, **keywords):".... `
abhishekgarg

คำตอบ:


179

ต้องวางพารามิเตอร์ที่จำเป็นทั้งหมดก่อนอาร์กิวเมนต์เริ่มต้นใด ๆ เพียงเพราะเป็นข้อบังคับในขณะที่อาร์กิวเมนต์เริ่มต้นไม่ใช่ ในทางไวยากรณ์มันจะเป็นไปไม่ได้ที่ล่ามจะตัดสินใจว่าค่าใดที่ตรงกับอาร์กิวเมนต์ใดหากอนุญาตให้ใช้โหมดผสม A SyntaxErrorจะเพิ่มขึ้นหากไม่ได้ระบุอาร์กิวเมนต์ตามลำดับที่ถูกต้อง:

ให้เราดูอาร์กิวเมนต์คำหลักโดยใช้ฟังก์ชันของคุณ

def fun1(a="who is you", b="True", x, y):
...     print a,b,x,y

สมมติว่าได้รับอนุญาตให้ประกาศฟังก์ชันตามข้างต้นจากนั้นด้วยการประกาศข้างต้นเราสามารถทำการเรียกอาร์กิวเมนต์ตำแหน่งหรือคำหลักต่อไปนี้:

func1("ok a", "ok b", 1)  # Is 1 assigned to x or ?
func1(1)                  # Is 1 assigned to a or ?
func1(1, 2)               # ?

คุณจะแนะนำการกำหนดตัวแปรในการเรียกใช้ฟังก์ชันอย่างไรอาร์กิวเมนต์เริ่มต้นจะถูกใช้ร่วมกับอาร์กิวเมนต์คำหลักอย่างไร

>>> def fun1(x, y, a="who is you", b="True"):
...     print a,b,x,y
... 

Reference O'Reilly - Core-Python
โดยที่ฟังก์ชันนี้ใช้ประโยชน์จากอาร์กิวเมนต์เริ่มต้นที่ถูกต้องตามหลักไวยากรณ์สำหรับการเรียกฟังก์ชันข้างต้น อาร์กิวเมนต์คำหลักที่เรียกพิสูจน์ว่ามีประโยชน์สำหรับความสามารถในการจัดหาอาร์กิวเมนต์ตำแหน่งที่ไม่อยู่ในลำดับ แต่เมื่อรวมกับอาร์กิวเมนต์เริ่มต้นแล้วก็ยังสามารถใช้เพื่อ "ข้ามผ่าน" อาร์กิวเมนต์ที่ขาดหายไปได้เช่นกัน


4
<q> ในเชิงสัณฐานวิทยาเป็นไปไม่ได้ที่ล่ามจะตัดสินใจว่าค่าใดตรงกับอาร์กิวเมนต์ใดหากอนุญาตโหมดผสม </q> Ruby อนุญาตให้อาร์กิวเมนต์ที่ไม่ใช่ค่าเริ่มต้นตามค่าเริ่มต้น <Q> วิธีที่คุณจะแนะนำการมอบหมายของตัวแปรในการเรียกใช้ฟังก์ชัน </ q> func1(x=1, y=2)เพียงแค่การใช้งาน
อ่อนแอลง

สวัสดี @weakish ขอบคุณสำหรับความคิดเห็น Python มีวิธีที่ดีในการบรรลุเป้าหมายนี้โปรดไปค้นหา * args และ ** kwargs
Rahul Gautam

สวัสดี @ Rahul Gautam ฉันสับสน ฉันคิดว่า**kwargsไม่สามารถสร้างdef fun1(a="who is you", b="True", x, y)หรือทำงานที่คล้ายกันได้ หากคุณใช้def f(**kwargs)คุณต้องจัดการกับค่าเริ่มต้นในร่างกายหรือไม่?
อ่อนแอ

@ weakish def fun1(a="who is you", b="True", x, y)สิ่งเดียวกันสามารถทำได้ด้วยสไตล์ที่แตกต่างกัน ถ้า def fun1 (** kwrgs) `แล้วเรียกfun1({'a': 'who is you', 'b': True})ไม่จำเป็นต้องผ่าน x และ y
Rahul Gautam

2
เหตุใดคุณจึงเขียน "Syntactically มันเป็นไปไม่ได้ที่ล่ามจะตัดสินใจว่าค่าใดตรงกับอาร์กิวเมนต์ใดหากอนุญาตโหมดผสม" ฉันคิดว่าอัลกอริทึมที่PEP 3102สามารถทำงานได้เหมือนกันแม้ว่าdef foo(x=None, y)จะได้รับอนุญาตก็ตาม ดังนั้นฉันยังคงสงสัยว่าเหตุใด Python จึงไม่อนุญาต มีเหตุผลพื้นฐานที่แท้จริงหรือเป็นเพียง "เราไม่อนุญาตเพราะเราไม่อนุญาต"
Jeroen Demeyer

15
SyntaxError: non-default argument follows default argument

หากคุณกำลังจะปล่อยให้เรื่องนี้ขัดแย้งเริ่มต้นจะไม่ได้ผลเพราะคุณจะไม่สามารถที่จะใช้เป็นค่าเริ่มต้นตั้งแต่การขัดแย้งที่ไม่ใช่ค่าเริ่มต้นมาหลังจาก

อย่างไรก็ตามใน Python 3 คุณสามารถทำสิ่งต่อไปนี้:

def fun1(a="who is you", b="True", *, x, y):
    pass

ซึ่งสร้างxและyคีย์เวิร์ดเท่านั้นเพื่อให้คุณสามารถทำได้:

fun1(x=2, y=2)

สิ่งนี้ได้ผลเพราะไม่มีความคลุมเครืออีกต่อไป โปรดทราบว่าคุณยังไม่สามารถทำได้fun1(2, 2)(ซึ่งจะตั้งค่าอาร์กิวเมนต์เริ่มต้น)


ข้อโต้แย้งคำหลักเพียงมีคุณสมบัติเรียบร้อยของงูหลาม 3. เกินไปไม่ดีแพทช์ที่จะย้ายกลับให้พวกเขางูหลาม 2.6 และ 2.7 เป็นเพียงที่เหลือจะหมดอายุ
Nick Chammas

10

ขอฉันเคลียร์สองประเด็นที่นี่:

  • ประการแรกอาร์กิวเมนต์ที่ไม่ใช่ค่าเริ่มต้นไม่ควรเป็นไปตามอาร์กิวเมนต์เริ่มต้นหมายความว่าคุณไม่สามารถกำหนด (a = b, c) ในฟังก์ชันได้ลำดับการกำหนดพารามิเตอร์ในฟังก์ชันคือ:
    • พารามิเตอร์ตำแหน่งหรือพารามิเตอร์ที่ไม่ใช่ค่าเริ่มต้นเช่น (a, b, c)
    • พารามิเตอร์คำหลักหรือพารามิเตอร์เริ่มต้นเช่น (a = "b", r = "j")
    • พารามิเตอร์คำหลักเท่านั้นเช่น (* args)
    • พารามิเตอร์ var-keyword เช่น (** kwargs)

def example(a, b, c=None, r="w" , d=[], *ae, **ab):

(a, b) คือพารามิเตอร์ตำแหน่ง

(c = none) เป็นพารามิเตอร์ทางเลือก

(r = "w") คือพารามิเตอร์คำหลัก

(d = []) คือพารามิเตอร์รายการ

(* ae) เป็นคำหลักเท่านั้น

(** ab) คือพารามิเตอร์ var-keyword

  • ตอนนี้สิ่งรองคือถ้าฉันลองทำสิ่งนี้: def example(a, b, c=a,d=b):

ไม่ได้กำหนดอาร์กิวเมนต์เมื่อบันทึกค่าเริ่มต้น Python จะคำนวณและบันทึกค่าเริ่มต้นเมื่อคุณกำหนดฟังก์ชัน

ไม่ได้กำหนด c และ d ไม่มีอยู่เมื่อสิ่งนี้เกิดขึ้น (มีอยู่เฉพาะเมื่อเรียกใช้ฟังก์ชัน)

"a, a = b" ไม่อนุญาตในพารามิเตอร์


0

อาร์กิวเมนต์ที่จำเป็น (อาร์กิวเมนต์ที่ไม่มีค่าดีฟอลต์) ต้องอยู่ที่จุดเริ่มต้นเพื่ออนุญาตให้โค้ดไคลเอ็นต์จัดหาสองเท่านั้น หากอาร์กิวเมนต์ที่เป็นทางเลือกอยู่ในช่วงเริ่มต้นจะทำให้เกิดความสับสน:

fun1("who is who", 3, "jack")

สิ่งนี้จะทำอะไรในตัวอย่างแรกของคุณ? สุดท้าย x คือ "ใครเป็นใคร", y คือ 3 และ a = "แจ็ค"

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.