Apa hubungan antara ruang lingkup dan ruang nama di Python?


12

Dalam banyak sumber saya menemukan "ruang lingkup" dan "ruang nama" digunakan secara bergantian, yang tampaknya sedikit membingungkan karena mereka bermakna berbeda.

  • Lingkup mendefinisikan wilayah kode tempat nama tersedia.
  • Aturan LEGB menentukan cara nama dilihat.
  • Namespace adalah tempat Anda mencari nama.

Lalu saya membaca:

  • "Nama-nama diikat ke namespace sesuai dengan tempat mereka ditugaskan ..." (yang saya percaya adalah kesepakatan dengan ruang lingkup dalam pelingkupan leksikal).
  • "fungsi menambahkan lapisan namespace tambahan ke program Anda" [ ref. ] (bukankah mereka menambahkan lingkup lokal tambahan?)
  • "Semua nama yang ditetapkan dalam definisi fungsi dimasukkan ke dalam ruang lingkup lokal (namespace yang terkait dengan panggilan fungsi)."
  • "Ruang lingkup global - yaitu, namespace tempat variabel dibuat (ditugaskan) di tingkat atas file modul."

* semua kutipan berasal dari belajar python 5th edition ch17

Apakah ruang nama dalam Python cara lingkup diterapkan? Apakah mereka sama? Adakah yang bisa menyadarkan saya?


1
Bisakah Anda memberikan referensi untuk kutipan - saya bisa menemukan satu, tetapi tidak yang lain.
jonrsharpe

1
Ruang nama hanyalah satu jenis ruang lingkup. Lihat stackoverflow.com/questions/291978/…
Robert Harvey

Jawaban:


16

Sebuah namespace adalah kamus, pemetaan nama (sebagai string) dengan nilai-nilai. Ketika Anda melakukan tugas, seperti a = 1, Anda sedang memutasi ruang nama. Ketika Anda membuat referensi, seperti print(a), Python melihat melalui daftar ruang nama untuk mencoba dan menemukan satu dengan nama sebagai kunci.

Sebuah lingkup mendefinisikan yang ruang nama akan melihat ke dalam dan dalam rangka apa. Lingkup setiap referensi selalu dimulai di namespace lokal, dan bergerak ke luar hingga mencapai namespace global modul, sebelum pindah ke builtins(namespace yang mereferensikan fungsi dan konstanta Python yang telah ditentukan, seperti rangedan getattr), yang merupakan akhir dari baris .

Bayangkan Anda memiliki fungsi bernama inner, bersarang di dalam fungsi global bernama outer, dan innerberisi referensi ke nama. Python pertama kali terlihat di innernamespace. Jika namanya tidak ada, Python kemudian mencari di outernamespace. Jika itu gagal, Python mencoba globalnamespace modul , lalu builtinnamespace, akhirnya melempar NameErrorjika namanya tidak ditemukan.

Ketika kita mengatakan xdalam namespace fungsi, kita berarti itu didefinisikan di sana, secara lokal di dalam fungsi. Ketika kita mengatakan xberada dalam ruang lingkup fungsi, berarti kita xberada di namespace fungsi atau di salah satu ruang nama luar yang fungsi namespace berada di dalam.

Setiap kali Anda mendefinisikan suatu fungsi, Anda membuat namespace baru dan cakupan baru. Namespace adalah hash nama lokal yang baru. Cakupannya adalah rantai ruang nama tersirat yang dimulai pada namespace baru, kemudian bekerja melalui ruang nama luar (lingkup luar), hingga namespace global (lingkup global), dan terus ke builtin.

Istilah ini dapat digunakan hampir secara bergantian, tetapi itu bukan karena mereka memiliki arti yang sama; itu karena mereka tumpang tindih banyak dalam apa yang mereka maksudkan.


3
"Istilah itu dapat digunakan hampir secara bergantian, tetapi itu bukan karena mereka berarti hal yang sama; itu karena mereka tumpang tindih banyak dalam apa yang mereka maksudkan."
Nikos

2
Jawaban ini benar dalam roh, tetapi salah dalam detail. Kelas di Python tidak memperkenalkan namespace baru, itulah sebabnya atribut kelas harus memenuhi syarat dengan nama kelas dan mengapa atribut instance harus memenuhi syarat dengan nama instance. Tingkat namespace dalam Python dari dalam ke luar adalah Lokal, Enclosing, Global dan Built-in. Kelas dapat didefinisikan pada level mana saja, tetapi anggota kelas harus selalu memenuhi syarat.
Rob Smallshire

Kamu benar. Kelas tidak berfungsi seperti yang saya katakan. Saya berpikir mereka membuat ruang lingkup leksikal seperti fungsi, tetapi tidak. Harap perbarui jawabannya jika Anda punya waktu, kalau tidak saya akan melakukannya nanti. Terima kasih.
Carl Smith

1
+1 Jawaban brilian, merangkum kehalusan demikian secara ekonomis. Saya menemukan ini sangat membantu, terima kasih!
seeker

1
"Sebuah namespace adalah hash dari nama, pasangan nilai, banyak seperti kamus Python" - Aku cukup yakin ruang nama yang disimpan sebagai kamus python. Misalnya, Anda dapat mengedit namespace global dengan memanggil globals (), yang memungkinkan Anda memodifikasi kamus secara langsung untuk mengikat objek dan nama: misalnya globals () [name] = "object". Jawaban yang bagus sebaliknya.
Evan Rosica

4

Ada artikel bagus tentang ruang nama Python di sini . Mengutip bagian yang relevan untuk menjawab pertanyaan Anda tentang referensi antara cakupan dan ruang nama:

Lingkup mengacu pada wilayah suatu program dari mana namespace dapat diakses tanpa awalan.

Misalnya, bayangkan program die-rolling sederhana:

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 memiliki namespace sendiri , tetapi nama-nama dalam namespace modul juga dalam ruang lingkup .


@CarlSmith mencatat bahwa dokumentasi Python awal mengatakan hal yang sama: "Lingkup adalah wilayah tekstual dari program Python di mana ruang nama dapat diakses secara langsung." Dapat diakses langsung '' di sini berarti bahwa referensi yang tidak memenuhi syarat untuk nama berusaha untuk menemukan nama dalam ruang nama. "
jonrsharpe

@CarlSmith selain dari penambahan lingkup non-lokal / terlampir, apakah sudah banyak berubah? Saya pikir kami mengatakan hal yang sama - namespace berisi nama dan nilai, dan ruang lingkup memberi tahu Anda ruang nama mana yang dapat diakses.
jonrsharpe

Saya menghapus komentar lama saya.
Carl Smith
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.