Adakah yang bisa menjelaskan __all__ dengan Python?

983

Saya telah menggunakan Python semakin banyak, dan saya terus melihat __all__set variabel dalam __init__.pyfile yang berbeda . Adakah yang bisa menjelaskan hal ini?

varikin
sumber

Jawaban:

566

Ini adalah daftar objek publik dari modul itu, sebagaimana ditafsirkan oleh import *. Itu menimpa default menyembunyikan segala sesuatu yang dimulai dengan garis bawah.

Jimmy
sumber
146
Objek yang dimulai dengan garis bawah, atau tidak disebutkan __all__jika __all__ada, tidak sepenuhnya tersembunyi; mereka dapat dilihat dan diakses dengan normal jika Anda tahu namanya. Hanya dalam kasus "impor *", yang tidak dianjurkan, perbedaannya memiliki bobot.
Brandon Rhodes
28
@BrandonRhodes: itu juga tidak sepenuhnya benar: Disarankan hanya mengimpor modul yang Anda tahu dirancang untuk import *(seperti misalnya tk). Petunjuk yang bagus jika hal ini terjadi adalah keberadaan __all__atau nama yang dimulai dengan garis bawah pada kode modul.
domba terbang
12
Antarmuka publik dan internal - python.org/dev/peps/pep-0008/#id50 , Untuk lebih mendukung introspeksi, modul harus secara eksplisit mendeklarasikan nama-nama dalam API publik mereka menggunakan atribut __all__. Pengaturan __all__ ke daftar kosong menunjukkan bahwa modul tidak memiliki API publik.
debug
Saya tidak yakin apakah tkdirilis hari ini (atau pada 2012, bahkan), praktik yang disarankan adalah menggunakan from tk import *. Saya pikir praktik ini diterima karena inersia, bukan desain yang disengaja.
chepner
Seperti yang ditunjukkan BrandonRhodes, ini sebenarnya tidak benar
duhaime
947

Tertaut ke, tetapi tidak secara eksplisit disebutkan di sini, adalah persis kapan __all__digunakan. Ini adalah daftar string yang mendefinisikan simbol apa dalam modul yang akan diekspor saat from <module> import *digunakan pada modul.

Misalnya, kode berikut foo.pysecara eksplisit mengekspor simbol bardan baz:

__all__ = ['bar', 'baz']

waz = 5
bar = 10
def baz(): return 'baz'

Simbol-simbol ini kemudian dapat diimpor seperti:

from foo import *

print(bar)
print(baz)

# The following will trigger an exception, as "waz" is not exported by the module
print(waz)

Jika di __all__atas dikomentari, kode ini kemudian akan dieksekusi sampai selesai, karena perilaku default import *adalah mengimpor semua simbol yang tidak dimulai dengan garis bawah, dari namespace yang diberikan.

Referensi: https://docs.python.org/tutorial/modules.html#importing-from-a-package

CATATAN: hanya __all__ mempengaruhi from <module> import *perilaku. Anggota yang tidak disebutkan dalam __all__masih dapat diakses dari luar modul dan dapat diimpor dengan from <module> import <member>.

Alec Thomas
sumber
1
bukankah seharusnya kita mencetak baz print(baz())?
John Cole
@JohnCole baz adalah objek fungsi dan baz () akan menjalankan objek fungsi
Bhanu Tez
@BhanuTez tepatnya. Jadi print(baz)mencetak sesuatu seperti cetakan <function baz at 0x7f32bc363c10>sementaraprint(baz())baz
John Cole
223

Jelaskan __all__ dengan Python?

Saya terus melihat __all__set variabel dalam __init__.pyfile yang berbeda .

Apa fungsinya?

Apa yang __all__harus dilakukan

Ini mendeklarasikan nama "publik" semantik dari sebuah modul. Jika ada nama di __all__, pengguna diharapkan untuk menggunakannya, dan mereka dapat memiliki harapan bahwa itu tidak akan berubah.

Itu juga akan memiliki dampak terprogram:

import *

__all__dalam sebuah modul, misalnya module.py:

__all__ = ['foo', 'Bar']

berarti bahwa ketika Anda import *dari modul, hanya nama-nama dalam __all__yang diimpor:

from module import *               # imports foo and Bar

Alat dokumentasi

Alat dokumentasi dan pelengkapan otomatis kode dapat (pada kenyataannya, harus) juga memeriksa __all__untuk menentukan nama yang akan ditampilkan sebagai tersedia dari modul.

__init__.py membuat direktori paket Python

Dari dokumen :

The __init__.pyfile yang diperlukan untuk membuat Python memperlakukan direktori sebagai mengandung paket; ini dilakukan untuk mencegah direktori dengan nama umum, seperti string, dari menyembunyikan modul valid yang terjadi kemudian pada jalur pencarian modul.

Dalam kasus yang paling sederhana, __init__.pybisa berupa file kosong, tetapi juga dapat mengeksekusi kode inisialisasi untuk paket atau mengatur __all__variabel.

Jadi __init__.pydapat mendeklarasikan __all__untuk paket .

Mengelola API:

Paket biasanya terdiri dari modul yang dapat mengimpor satu sama lain, tetapi yang harus diikat bersama dengan __init__.pyfile. File itu yang membuat direktori paket Python yang sebenarnya. Misalnya, Anda memiliki file berikut dalam satu paket:

package
├── __init__.py
├── module_1.py
└── module_2.py

Mari kita buat file-file ini dengan Python sehingga Anda dapat mengikuti - Anda dapat menempelkan yang berikut ke dalam shell Python 3:

from pathlib import Path

package = Path('package')
package.mkdir()

(package / '__init__.py').write_text("""
from .module_1 import *
from .module_2 import *
""")

package_module_1 = package / 'module_1.py'
package_module_1.write_text("""
__all__ = ['foo']
imp_detail1 = imp_detail2 = imp_detail3 = None
def foo(): pass
""")

package_module_2 = package / 'module_2.py'
package_module_2.write_text("""
__all__ = ['Bar']
imp_detail1 = imp_detail2 = imp_detail3 = None
class Bar: pass
""")

Dan sekarang Anda telah menyajikan api lengkap yang dapat digunakan orang lain saat mereka mengimpor paket Anda, seperti:

import package
package.foo()
package.Bar()

Dan paket tidak akan memiliki semua detail implementasi lain yang Anda gunakan saat membuat modul Anda mengacaukan packagenamespace.

__all__ di __init__.py

Setelah lebih banyak pekerjaan, mungkin Anda telah memutuskan bahwa modul terlalu besar (seperti ribuan baris?) Dan perlu dipisah. Jadi, Anda melakukan hal berikut:

package
├── __init__.py
├── module_1
│   ├── foo_implementation.py
│   └── __init__.py
└── module_2
    ├── Bar_implementation.py
    └── __init__.py

Pertama-tama buat direktori subpackage dengan nama yang sama dengan modul:

subpackage_1 = package / 'module_1'
subpackage_1.mkdir()
subpackage_2 = package / 'module_2'
subpackage_2.mkdir()

Pindahkan implementasinya:

package_module_1.rename(subpackage_1 / 'foo_implementation.py')
package_module_2.rename(subpackage_2 / 'Bar_implementation.py')

buat __init__.pys untuk sub paket yang menyatakan __all__untuk masing-masing:

(subpackage_1 / '__init__.py').write_text("""
from .foo_implementation import *
__all__ = ['foo']
""")
(subpackage_2 / '__init__.py').write_text("""
from .Bar_implementation import *
__all__ = ['Bar']
""")

Dan sekarang Anda masih memiliki api yang disediakan di tingkat paket:

>>> import package
>>> package.foo()
>>> package.Bar()
<package.module_2.Bar_implementation.Bar object at 0x7f0c2349d210>

Dan Anda dapat dengan mudah menambahkan hal-hal ke API Anda yang dapat Anda kelola di tingkat sub-paket bukan tingkat modul sub-paket. Jika Anda ingin menambahkan nama baru ke API, Anda cukup memperbarui __init__.py, misalnya di module_2:

from .Bar_implementation import *
from .Baz_implementation import *
__all__ = ['Bar', 'Baz']

Dan jika Anda belum siap untuk mempublikasikan Bazdi API tingkat atas, di level teratas __init__.pyAnda, Anda dapat memiliki:

from .module_1 import *       # also constrained by __all__'s
from .module_2 import *       # in the __init__.py's
__all__ = ['foo', 'Bar']     # further constraining the names advertised

dan jika pengguna Anda mengetahui ketersediaan Baz, mereka dapat menggunakannya:

import package
package.Baz()

tetapi jika mereka tidak mengetahuinya, alat lain (seperti pydoc ) tidak akan memberi tahu mereka.

Anda nanti dapat mengubahnya saat Bazsiap untuk prime time:

from .module_1 import *
from .module_2 import *
__all__ = ['foo', 'Bar', 'Baz']

Awalan _versus __all__:

Secara default, Python akan mengekspor semua nama yang tidak dimulai dengan _. Anda tentu bisa mengandalkan mekanisme ini. Beberapa paket di pustaka standar Python, pada kenyataannya, memang mengandalkan ini, tetapi untuk melakukannya, mereka alias impor mereka, misalnya, di ctypes/__init__.py:

import os as _os, sys as _sys

Menggunakan _konvensi dapat menjadi lebih elegan karena menghilangkan redundansi penamaan nama lagi. Tetapi itu menambah redundansi untuk impor (jika Anda memiliki banyak impor) dan mudah untuk melupakan hal ini secara konsisten - dan hal terakhir yang Anda inginkan adalah harus tanpa batas mendukung sesuatu yang Anda maksudkan hanya menjadi detail implementasi, hanya saja karena Anda lupa untuk awalan _ketika memberi nama fungsi.

Saya pribadi menulis __all__awal dalam siklus hidup pengembangan saya untuk modul sehingga orang lain yang mungkin menggunakan kode saya tahu apa yang harus mereka gunakan dan tidak gunakan.

Sebagian besar paket di perpustakaan standar juga digunakan __all__.

Saat menghindar __all__masuk akal

Masuk akal untuk tetap berpegang pada _konvensi awalan sebagai pengganti __all__ketika:

  • Anda masih dalam mode pengembangan awal dan tidak memiliki pengguna, dan terus-menerus mengubah API Anda.
  • Mungkin Anda memang memiliki pengguna, tetapi Anda memiliki unittests yang menutupi API, dan Anda masih aktif menambahkan ke API dan tweaker dalam pengembangan.

sebuah exportdekorator

Kelemahan dari penggunaan __all__adalah bahwa Anda harus menulis nama fungsi dan kelas yang diekspor dua kali - dan informasi disimpan terpisah dari definisi. Kita bisa menggunakan dekorator untuk menyelesaikan masalah ini.

Saya mendapat ide untuk dekorator ekspor dari pembicaraan David Beazley tentang pengemasan. Implementasi ini tampaknya bekerja dengan baik di importir tradisional CPython. Jika Anda memiliki kait atau sistem impor khusus, saya tidak menjaminnya, tetapi jika Anda mengadopsinya, itu cukup sepele untuk mundur - Anda hanya perlu menambahkan nama secara manual ke dalam__all__

Jadi di, misalnya, perpustakaan utilitas, Anda akan mendefinisikan dekorator:

import sys

def export(fn):
    mod = sys.modules[fn.__module__]
    if hasattr(mod, '__all__'):
        mod.__all__.append(fn.__name__)
    else:
        mod.__all__ = [fn.__name__]
    return fn

dan kemudian, di mana Anda akan mendefinisikan __all__, Anda melakukan ini:

$ cat > main.py
from lib import export
__all__ = [] # optional - we create a list if __all__ is not there.

@export
def foo(): pass

@export
def bar():
    'bar'

def main():
    print('main')

if __name__ == '__main__':
    main()

Dan ini berfungsi baik apakah dijalankan sebagai utama atau diimpor oleh fungsi lain.

$ cat > run.py
import main
main.main()

$ python run.py
main

Dan penyediaan API dengan import *akan bekerja juga:

$ cat > run.py
from main import *
foo()
bar()
main() # expected to error here, not exported

$ python run.py
Traceback (most recent call last):
  File "run.py", line 4, in <module>
    main() # expected to error here, not exported
NameError: name 'main' is not defined
Aaron Hall
sumber
1
Referensi silang: Saya menyebutkan dekorator Anda dalam jawaban CW ini untuk pertanyaan tentang bagaimana menulis @exportdekorator.
MvG
13
Ini adalah satu-satunya jawaban yang paling membantu yang pernah saya lihat dalam hal membantu pengembang python yang relatif baru memahami proses mengimpor modul / paket dengan __init__.pydan penggunaan__all__
Brett Reinhard
Ini sangat membantu saya. Masalah saya, tho, adalah bahwa submodul yang ingin saya impor adalah semua file yang dihasilkan dengan banyak celah di simbol mereka yang ingin saya hapus, tanpa harus secara manual memastikan bahwa __all__itu benar.
Mike C
@ MikeC kemudian mungkin Anda harus menghasilkan Anda __all__juga - tapi kemudian saya akan mengatakan Anda memiliki API tidak stabil ... Ini akan menjadi sesuatu untuk memiliki beberapa tes penerimaan yang komprehensif.
Aaron Hall
@ AaronHall "mereka tidak akan memiliki semua nama lain ... mengacaukan namespace paket" Tapi mereka akan memiliki nama module_1dan module_2; apakah boleh memasukkan eksplisit del module_1dalam __init__.py? Apakah saya salah menganggap ini berharga?
Mike C
176

Saya hanya menambahkan ini tepatnya:

Semua jawaban lain merujuk pada modul . Pertanyaan asli secara eksplisit disebutkan __all__dalam __init__.pyfile, jadi ini tentang paket python .

Umumnya, __all__hanya berlaku ketika from xxx import *varian importpernyataan digunakan. Ini berlaku untuk paket dan juga untuk modul.

Perilaku untuk modul dijelaskan dalam jawaban lain. Perilaku yang tepat untuk paket dijelaskan di sini secara rinci.

Singkatnya, __all__pada tingkat paket melakukan hal yang kira-kira sama dengan untuk modul, kecuali itu berkaitan dengan modul dalam paket (berbeda dengan menentukan nama-nama dalam modul ). Jadi __all__tentukan semua modul yang akan dimuat dan diimpor ke namespace saat ini saat kami gunakan from package import *.

Perbedaan besar adalah, bahwa ketika Anda menghilangkan deklarasi __all__dalam sebuah paket __init__.py, pernyataan from package import *itu tidak akan mengimpor apa pun (dengan pengecualian yang dijelaskan dalam dokumentasi, lihat tautan di atas).

Di sisi lain, jika Anda menghilangkan __all__dalam sebuah modul, "impor berbintang" akan mengimpor semua nama (tidak dimulai dengan garis bawah) yang ditentukan dalam modul.

MartinStettner
sumber
29
from package import *masih akan mengimpor semua yang didefinisikan __init__.py, bahkan jika tidak ada all. Perbedaan penting adalah bahwa tanpa __all__itu tidak akan secara otomatis mengimpor modul yang ditentukan dalam direktori paket.
Nikratio
Ketika semua berisi [foo, bar] dan dalam file test.py jika kita menggunakan: dari paket import *, lalu, apakah foo dan bar dapat diimpor di namespace lokal test.py atau di foo dan bar memiliki namespace sendiri?
variabel
87

Itu juga mengubah apa yang akan ditampilkan pydoc:

module1.py

a = "A"
b = "B"
c = "C"

module2.py

__all__ = ['a', 'b']

a = "A"
b = "B"
c = "C"

$ pydoc module1

Bantuan pada module module1:

NAMA
    modul 1

MENGAJUKAN
    module1.py

DATA 
    a = 'A'
     b = 'B'
     c = 'C'

$ pydoc module2

Bantuan pada module module2:

NAMA
    module2

MENGAJUKAN
    module2.py

DATA 
    __all__ = ['a', 'b']
     a = 'A'
     b = 'B'

Saya menyatakan __all__dalam semua modul saya, serta menggarisbawahi detail internal, ini sangat membantu ketika menggunakan hal-hal yang belum pernah Anda gunakan sebelumnya dalam sesi penerjemah langsung.

L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
sumber
54

__all__menyesuaikan *difrom <module> import *

__all__menyesuaikan *difrom <package> import *


Sebuah modul adalah .pyfile yang dimaksudkan untuk diimpor.

Sebuah paket adalah direktori dengan __init__.pyfile yang. Paket biasanya berisi modul.


MODUL

""" cheese.py - an example module """

__all__ = ['swiss', 'cheddar']

swiss = 4.99
cheddar = 3.99
gouda = 10.99

__all__memungkinkan manusia mengetahui fitur "publik" dari sebuah modul . [ @AaronHall ] Juga, pydoc mengenali mereka. [ @Longpoke ]

dari impor modul *

Lihat bagaimana swissdan cheddardibawa ke ruang nama lokal, tetapi tidak gouda:

>>> from cheese import *
>>> swiss, cheddar
(4.99, 3.99)
>>> gouda
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'gouda' is not defined

Tanpa __all__, simbol apa pun (yang tidak dimulai dengan garis bawah) akan tersedia.


Impor tanpa *tidak terpengaruh oleh__all__


modul impor

>>> import cheese
>>> cheese.swiss, cheese.cheddar, cheese.gouda
(4.99, 3.99, 10.99)

dari nama impor modul

>>> from cheese import swiss, cheddar, gouda
>>> swiss, cheddar, gouda
(4.99, 3.99, 10.99)

impor modul sebagai localname

>>> import cheese as ch
>>> ch.swiss, ch.cheddar, ch.gouda
(4.99, 3.99, 10.99)

PAKET

Dalam __init__.pyfile paket __all__ adalah daftar string dengan nama-nama modul publik atau objek lainnya. Fitur-fitur tersebut tersedia untuk impor wildcard. Seperti halnya modul, __all__sesuaikan *kapan wildcard mengimpor dari paket. [ @MartinStettner ]

Berikut ini kutipan dari Konektor Python MySQL __init__.py :

__all__ = [
    'MySQLConnection', 'Connect', 'custom_error_exception',

    # Some useful constants
    'FieldType', 'FieldFlag', 'ClientFlag', 'CharacterSet', 'RefreshOption',
    'HAVE_CEXT',

    # Error handling
    'Error', 'Warning',

    ...etc...

    ]

Kasing standar, tanda bintang tanpa __all__paket , rumit, karena perilaku yang jelas akan mahal: menggunakan sistem file untuk mencari semua modul dalam paket. Sebaliknya, dalam membaca dokumen saya, hanya objek yang didefinisikan __init__.pydiimpor:

Jika __all__tidak didefinisikan, pernyataan from sound.effects import *itu tidak mengimpor semua submodul dari paket sound.effectske namespace saat ini; hanya memastikan bahwa paket sound.effectstelah diimpor (mungkin menjalankan kode inisialisasi apa pun __init__.py) dan kemudian mengimpor nama apa pun yang didefinisikan dalam paket. Ini termasuk nama apa pun yang didefinisikan (dan submodul yang dimuat secara eksplisit) oleh __init__.py. Ini juga termasuk semua submodul dari paket yang secara eksplisit dimuat oleh pernyataan impor sebelumnya.


Impor wildcard ... harus dihindari karena mereka [membingungkan] pembaca dan banyak alat otomatis.

[ PEP 8 , @ToolmakerSteve]

Bob Stein
sumber
2
Saya sangat suka jawaban ini, tetapi saya kehilangan informasi tentang apa perilaku default from <package> import *tanpa __all__di __init__.pyyang tidak mengimpor modul .
radzak
Terima kasih @Jatimir, saya mengklarifikasi sebaik mungkin tanpa menjalankan percobaan. Saya hampir ingin mengatakan kasus ini (tanda bintang tanpa semua paket) berperilaku sama seperti jika __init__.pymodul . Tapi saya tidak yakin itu akurat, atau khususnya jika objek garis bawah-awalan dikecualikan. Juga, saya lebih jelas memisahkan bagian tentang MODUL dan PAKET. Pikiran Anda?
Bob Stein
49

Dari Wiki Referensi Python (An Tidak Resmi) :

Nama publik yang ditentukan oleh modul ditentukan dengan memeriksa namespace modul untuk variabel bernama __all__; jika didefinisikan, harus berupa urutan string yang merupakan nama yang didefinisikan atau diimpor oleh modul itu. Semua nama yang diberikan __all__dianggap publik dan harus ada. Jika __all__tidak didefinisikan, himpunan nama publik mencakup semua nama yang ditemukan di namespace modul yang tidak dimulai dengan karakter garis bawah ("_"). __all__harus mengandung seluruh API publik. Hal ini dimaksudkan untuk menghindari ekspor barang yang bukan bagian dari API (seperti modul perpustakaan yang diimpor dan digunakan dalam modul).

Lasse V. Karlsen
sumber
Tautan yang tercantum sudah mati. tetapi menemukan teks kata demi kata di vdocuments.net/… & di sini: dokumen.tips/documents/reference-567bab8d6118a.html
JayRizzo
8

__all__digunakan untuk mendokumentasikan API publik dari modul Python. Meskipun bersifat opsional, __all__harus digunakan.

Berikut adalah kutipan yang relevan dari referensi bahasa Python :

Nama publik yang ditentukan oleh modul ditentukan dengan memeriksa namespace modul untuk variabel bernama __all__; jika didefinisikan, harus berupa urutan string yang merupakan nama yang didefinisikan atau diimpor oleh modul itu. Semua nama yang diberikan __all__dianggap publik dan harus ada. Jika __all__tidak didefinisikan, himpunan nama publik mencakup semua nama yang ditemukan di namespace modul yang tidak dimulai dengan karakter garis bawah ('_'). __all__harus mengandung seluruh API publik. Hal ini dimaksudkan untuk menghindari ekspor barang yang bukan bagian dari API (seperti modul perpustakaan yang diimpor dan digunakan dalam modul).

PEP 8 menggunakan kata-kata yang serupa, meskipun juga menjelaskan bahwa nama yang diimpor bukan bagian dari API publik ketika __all__tidak ada:

Untuk mendukung introspeksi dengan lebih baik, modul harus secara eksplisit mendeklarasikan nama-nama di API publik mereka menggunakan __all__atribut. Pengaturan __all__ke daftar kosong menunjukkan bahwa modul tidak memiliki API publik.

[...]

Nama yang diimpor harus selalu dianggap sebagai detail implementasi. Modul-modul lain tidak boleh mengandalkan akses tidak langsung ke nama-nama yang diimpor tersebut kecuali mereka merupakan bagian yang terdokumentasi secara eksplisit dari API modul yang mengandung, seperti os.pathatau __init__modul paket yang memperlihatkan fungsionalitas dari submodul.

Selanjutnya, seperti yang ditunjukkan dalam jawaban lain, __all__digunakan untuk mengaktifkan wildcard mengimpor untuk paket :

Pernyataan impor menggunakan konvensi berikut: jika __init__.pykode paket mendefinisikan daftar bernama __all__, itu diambil menjadi daftar nama modul yang harus diimpor ketika from package import *ditemui.

Mihai Capotă
sumber
8

Jawaban singkat

__all__memengaruhi from <module> import *pernyataan.

Jawaban panjang

Pertimbangkan contoh ini:

foo
├── bar.py
└── __init__.py

Dalam foo/__init__.py:

  • (Tersirat) Jika kami tidak mendefinisikan __all__, maka from foo import *hanya akan mengimpor nama yang didefinisikan dalam foo/__init__.py.

  • (Eksplisit) Jika kita mendefinisikan __all__ = [], maka tidak from foo import *akan mengimpor apa pun.

  • (Eksplisit) Jika kita mendefinisikan __all__ = [ <name1>, ... ], maka from foo import *hanya akan mengimpor nama-nama itu.

Perhatikan bahwa dalam kasus tersirat, python tidak akan mengimpor nama yang dimulai dengan _. Namun, Anda dapat memaksa mengimpor nama tersebut menggunakan __all__.

Anda dapat melihat dokumen Python di sini .

Cyker
sumber
5

__all__mempengaruhi cara from foo import *kerjanya.

Kode yang ada di dalam tubuh modul (tetapi tidak di tubuh fungsi atau kelas) dapat menggunakan tanda bintang ( *) dalam frompernyataan:

from foo import *

The *permintaan bahwa semua atribut modul foo(kecuali yang awal dengan garis bawah) terikat sebagai variabel global dalam modul mengimpor. Ketika foomemiliki atribut __all__, nilai atribut adalah daftar nama-nama yang terikat oleh jenis frompernyataan ini.

Jika foosebuah paket dan __init__.pymendefinisikan daftar bernama __all__, itu diambil menjadi daftar nama submodule yang harus diimpor ketika from foo import *ditemui. Jika __all__tidak didefinisikan, pernyataan from foo import *mengimpor nama apa pun yang didefinisikan dalam paket. Ini termasuk nama apa pun yang didefinisikan (dan submodul yang dimuat secara eksplisit) oleh __init__.py.

Catatan yang __all__tidak harus menjadi daftar. Sesuai dokumentasi pada importpernyataan , jika ditentukan, __all__harus berupa urutan string yang merupakan nama yang didefinisikan atau diimpor oleh modul. Jadi, Anda sebaiknya menggunakan tuple untuk menghemat beberapa siklus memori dan CPU. Hanya saja, jangan lupa koma jika modul mendefinisikan satu nama publik:

__all__ = ('some_name',)

Lihat juga Mengapa “impor *” buruk?

Eugene Yarmash
sumber
1

Ini didefinisikan dalam PEP8 di sini :

Nama Variabel Global

(Mari kita berharap bahwa variabel-variabel ini dimaksudkan untuk digunakan di dalam satu modul saja.) Konvensi hampir sama dengan yang untuk fungsi.

Modul yang dirancang untuk digunakan melalui from M import *harus menggunakan __all__mekanisme untuk mencegah ekspor global, atau menggunakan konvensi yang lebih lama untuk mengawali globalisasi tersebut dengan garis bawah (yang mungkin ingin Anda lakukan untuk menunjukkan bahwa global ini adalah "modul non-publik").

PEP8 menyediakan konvensi pengkodean untuk kode Python yang terdiri dari pustaka standar dalam distribusi Python utama. Semakin banyak Anda mengikuti ini, semakin dekat Anda dengan maksud aslinya.

prosti
sumber