อะไรคือความสัมพันธ์ระหว่างขอบเขตและเนมสเปซใน Python


12

ในแหล่งข้อมูลมากมายฉันพบว่า"ขอบเขต"และ"เนมสเปซ"ถูกใช้แทนกันได้ซึ่งดูเหมือนว่าจะสับสนเล็กน้อยเนื่องจากมันหมายถึงสิ่งที่แตกต่างกัน

  • ขอบเขตกำหนดขอบเขตของรหัสที่มีชื่อ
  • กฎ LEGB กำหนดวิธีค้นหาชื่อ
  • Namespace เป็นสถานที่ที่คุณค้นหาชื่อ

จากนั้นฉันก็อ่าน:

  • "ชื่อถูกผูกไว้กับ namespace ตามที่พวกเขาได้รับมอบหมาย ... " (ซึ่งฉันเชื่อว่าเป็นข้อตกลงกับขอบเขตในการกำหนดขอบเขตคำศัพท์)
  • "ฟังก์ชั่นเพิ่มเนมสเปซเลเยอร์พิเศษให้กับโปรแกรมของคุณ" [ อ้างอิง ] (พวกเขาไม่ได้เพิ่มขอบเขตในพื้นที่พิเศษหรือไม่)
  • "ชื่อทั้งหมดที่กำหนดภายในนิยามฟังก์ชั่นจะอยู่ในขอบเขตภายใน (เนมสเปซที่เกี่ยวข้องกับการเรียกใช้ฟังก์ชัน)"
  • "โกลบอลสโคป - กล่าวคือเนมสเปซซึ่งตัวแปรสร้างขึ้น (กำหนด) ที่ระดับบนสุดของไฟล์โมดูลอยู่"

* ราคาทั้งหมดมาจากการเรียนรู้ python 5th edition ch17

เนมสเปซใน Python เป็นการนำไปใช้กับขอบเขตหรือไม่ พวกเขาเหมือนกันหรือไม่ มีใครสอนฉันได้ไหม


1
คุณสามารถให้การอ้างอิงสำหรับคำพูดได้หรือไม่ฉันหาได้ แต่ไม่ใช่อันอื่น
jonrsharpe

1
เนมสเปซเป็นเพียงขอบเขตประเภทเดียว ดูstackoverflow.com/questions/291978/…
Robert Harvey

คำตอบ:


16

namespaceเป็นพจนานุกรมชื่อการทำแผนที่ (สตริง) ไปเป็นค่า เมื่อคุณทำการกำหนดเช่นa = 1คุณกำลังกลายพันธุ์เนมสเปซ เมื่อคุณทำการอ้างอิงเช่นprint(a)Python จะค้นหารายการเนมสเปซเพื่อลองและค้นหาด้วยชื่อเป็นคีย์

ขอบเขตกำหนดซึ่ง namespaces จะถูกมองในและในสิ่งที่สั่งซื้อ ขอบเขตของการอ้างอิงใด ๆ ที่จะเริ่มต้นใน namespace ท้องถิ่นและย้ายออกไปจนกว่าจะถึง namespace โลกของโมดูลก่อนที่จะย้ายไปยังbuiltins(namespace ที่อ้างอิง ธ ฟังก์ชั่นที่กำหนดไว้ล่วงหน้าและค่าคงที่เหมือนrangeและgetattr) ซึ่งเป็นจุดสิ้นสุดของเส้น .

ลองนึกภาพคุณมีฟังก์ชั่นชื่อinnerซ้อนกันภายในฟังก์ชั่นทั่วโลกชื่อouterและinnerมีการอ้างอิงถึงชื่อ Python ค้นหาในinnerเนมสเปซเป็นครั้งแรก ถ้าชื่อไม่มี Python จะค้นหาในouterเนมสเปซ ถ้าสิ่งนั้นล้มเหลว Python จะพยายามใช้globalเนมสเปซของโมดูลจากนั้นbuiltinเนมสเปซจะขว้างNameErrorถ้าไม่มีชื่อนั้นในที่สุด

เมื่อเราพูดว่าxอยู่ใน namespace ของฟังก์ชั่นเราหมายถึงมันมีการกำหนดไว้ภายในฟังก์ชั่น เมื่อเราพูดว่าxอยู่ในขอบเขตของฟังก์ชั่นเราหมายถึงxเป็นใน namespace ของฟังก์ชั่นหรือใน namespaces ด้านนอกใด ๆ ที่ namespace ของฟังก์ชั่นจะซ้อนอยู่ภายใน

เมื่อใดก็ตามที่คุณกำหนดฟังก์ชั่นคุณจะสร้างเนมสเปซใหม่และขอบเขตใหม่ เนมสเปซคือแฮชของชื่อแบบโลคัลใหม่ ขอบเขตคือสายโซ่โดยนัยของเนมสเปซที่เริ่มต้นที่เนมสเปซใหม่จากนั้นทำงานผ่านเนมสเปซด้านนอกใด ๆ (สโคปด้านนอก) ถึงเนมสเปซส่วนกลาง

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


3
"เงื่อนไขสามารถใช้แทนกันได้เกือบทั้งหมด แต่นั่นไม่ใช่เพราะพวกเขาหมายถึงสิ่งเดียวกัน แต่เป็นเพราะพวกเขาทับซ้อนกันมากในสิ่งที่พวกเขาบ่งบอก"
Nikos

2
คำตอบนี้ถูกต้องในจิตวิญญาณ แต่ผิดในรายละเอียด คลาสใน Python ไม่แนะนำเนมสเปซใหม่ซึ่งเป็นสาเหตุที่แอตทริบิวต์คลาสต้องผ่านการรับรองด้วยชื่อคลาสและสาเหตุที่แอตทริบิวต์ของคุณสมบัติต้องมีคุณสมบัติที่มีชื่ออินสแตนซ์ ระดับของเนมสเปซใน Python จากภายในสู่ภายนอกคือ Local, Enclosing, Global และ Built-in คลาสอาจถูกกำหนดในระดับใด ๆ เหล่านี้ แต่สมาชิกของคลาสต้องมีคุณสมบัติเสมอ
Rob Smallshire

คุณถูก. ชั้นเรียนไม่ทำงานตามที่ฉันพูด ฉันคิดว่าพวกเขาสร้างขอบเขตคำศัพท์เช่นฟังก์ชั่น แต่พวกเขาทำไม่ได้ โปรดอัปเดตคำตอบหากคุณมีเวลามิฉะนั้นฉันจะทำบางอย่าง ขอบคุณ
Carl Smith

1
+1 คำตอบที่ยอดเยี่ยมแค็ปซูลความละเอียดอ่อนดังกล่าวเพื่อประหยัด ฉันพบสิ่งนี้มีประโยชน์มากขอบคุณ!
ผู้สมัคร

1
"เนมสเปซคือแฮชของชื่อ, คู่ค่า, เหมือนพจนานุกรมไพ ธ อน" - ฉันค่อนข้างแน่ใจว่าเนมสเปซถูกจัดเก็บเป็นพจนานุกรมไพ ธ อน ตัวอย่างเช่นคุณสามารถแก้ไขเนมสเปซส่วนกลางได้โดยการเรียก globals () ซึ่งช่วยให้คุณแก้ไขพจนานุกรมโดยตรงกับการผูกออบเจ็กต์และชื่อ: ตัวอย่างเช่น globals () [name] = "object" คำตอบที่ดีอย่างอื่น
Evan Rosica

4

มีบทความดีเกี่ยวกับงูหลาม namespaces ที่นี่ หากต้องการอ้างอิงส่วนที่เกี่ยวข้องเพื่อตอบคำถามของคุณเกี่ยวกับการอ้างอิงระหว่างขอบเขตและเนมสเปซ:

ขอบเขตหมายถึงขอบเขตของโปรแกรมที่สามารถเข้าถึงเนมสเปซได้โดยไม่ต้องมีคำนำหน้า

ตัวอย่างเช่นลองนึกภาพโปรแกรมรีดง่าย:

import random  # 'random' is in module namespace

def roll(sides=6):  # 'roll' is in module namespace, 'sides' is in roll's
    return random.randint(1, sides)  # both 'random' and 'sides' are in scope here

# but sides can't be accessed out here 

roll มีเนมสเปซของตัวเองแต่ชื่อในเนมสเปซของโมดูลก็อยู่ในขอบเขตเช่นกัน


@CarlSmith โปรดทราบว่าเอกสาร Python รุ่นแรกบอกว่าเหมือนกัน: "ขอบเขตคือขอบเขตข้อความของโปรแกรม Python ที่สามารถเข้าถึงพื้นที่ชื่อได้โดยตรง" การเข้าถึงได้โดยตรง '' ที่นี่หมายถึงการอ้างอิงอย่างไม่มีเงื่อนไขกับชื่อพยายามค้นหาชื่อ ในช่องว่างของชื่อ "
jonrsharpe

@CarlSmith นอกเหนือจากการเพิ่มเติมของขอบเขตไม่ใช่ท้องถิ่น / ปิดล้อมนั้นมีการเปลี่ยนแปลงมากมาย ฉันคิดว่าเรากำลังพูดในสิ่งเดียวกัน - เนมสเปซมีชื่อและค่าและขอบเขตบอกคุณว่าเนมสเปซนั้นสามารถเข้าถึงได้
jonrsharpe

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