Saya sudah mencoba menemukan panduan komprehensif tentang apakah yang terbaik untuk digunakan import module
atau from module import
? Saya baru saja mulai dengan Python dan saya mencoba memulai dengan praktik terbaik dalam pikiran.
Pada dasarnya, saya berharap jika ada yang bisa berbagi pengalaman mereka, preferensi apa yang dimiliki pengembang lain dan apa cara terbaik untuk menghindari gotcha di jalan?
python
python-import
Filip Dupanović
sumber
sumber
from … import …
sintaksis dalam Python & 'modul impor' vs. 'dari fungsi impor modul''from module import X,Y,Z
vs'from module import *
. Yang terakhir mencemari namespace Anda dan dapat memberikan hasil yang tidak terduga tergantung pada apa yang terjadi di modul. Lebih buruk lagi masih melakukanfrom module import *
dengan beberapa modul.Jawaban:
Perbedaan antara
import module
danfrom module import foo
terutama subyektif. Pilih yang paling Anda sukai dan konsisten dalam menggunakannya. Berikut adalah beberapa poin untuk membantu Anda memutuskan.import module
import
laporan Anda . Tidak perlu menambahkan impor tambahan untuk mulai menggunakan item lain dari modulmodule.foo
kode Anda bisa membosankan dan berlebihan (kebosanan dapat diminimalkan dengan menggunakanimport module as mo
lalu mengetikmo.foo
)from module import foo
foo
import
pernyataan Andafoo
. Misalnya, kurang jelas apa yangceil()
dibandingkan denganmath.ceil()
Metode mana pun dapat diterima, tetapi jangan gunakan
from module import *
.Untuk sejumlah besar kode yang masuk akal, jika Anda
import *
kemungkinan akan memasukkannya ke dalam modul, tidak dapat dihapus. Ini karena sulit untuk menentukan item apa yang digunakan dalam kode berasal dari 'modul', membuatnya mudah untuk sampai ke titik di mana Anda pikir Anda tidak menggunakanimport
lagi tetapi sangat sulit untuk memastikan.sumber
from module import *
dapat sangat berguna, jika menggunakannya sebagai:if(windows):\n\t from module_win import * \n else: \n\t from module_lin import *
. Maka modul induk Anda berpotensi berisi nama fungsi independen OS, jika nama fungsi di module_lin & module_win memiliki nama yang sama. Ini seperti mewarisi kedua kelas secara bersyarat.Ada detail lain di sini, tidak disebutkan, terkait dengan menulis ke modul. Memang ini mungkin tidak terlalu umum, tetapi saya membutuhkannya dari waktu ke waktu.
Karena cara referensi dan pengikatan nama berfungsi dalam Python, jika Anda ingin memperbarui beberapa simbol dalam sebuah modul, katakan foo.bar, dari luar modul itu, dan minta kode impor lainnya "lihat" perubahan itu, Anda harus mengimpor foo a cara tertentu. Sebagai contoh:
modul foo:
modul a:
modul b:
Namun, jika Anda mengimpor nama simbol alih-alih nama modul, ini tidak akan berfungsi.
Sebagai contoh, jika saya melakukan ini dalam modul a:
Tidak ada kode di luar bilah yang akan melihat "jeruk" karena pengaturan bilah saya hanya memengaruhi nama "bilah" di dalam modul a, itu tidak "menjangkau" objek modul foo dan memperbarui "bilah" -nya.
sumber
Meskipun banyak orang sudah menjelaskan tentang
import
vsimport from
, saya ingin mencoba menjelaskan lebih banyak tentang apa yang terjadi di bawah tenda, dan di mana semua tempat itu berubah berada.import foo
:Mengimpor
foo
, dan membuat referensi ke modul itu di namespace saat ini. Kemudian Anda perlu mendefinisikan jalur modul yang telah selesai untuk mengakses atribut atau metode tertentu dari dalam modul.Misalnya
foo.bar
tetapi tidakbar
from foo import bar
:Impor
foo
, dan buat referensi ke semua anggota yang terdaftar (bar
). Tidak mengatur variabelfoo
.Misalnya
bar
tetapi tidakbaz
ataufoo.baz
from foo import *
:Mengimpor
foo
, dan membuat referensi ke semua objek publik yang ditentukan oleh modul itu di namespace saat ini (semua yang terdaftar__all__
jika__all__
ada, jika tidak semua yang tidak dimulai dengan_
). Tidak mengatur variabelfoo
.Misal
bar
danbaz
tapi tidak_qux
ataufoo._qux
.Sekarang mari kita lihat kapan kita melakukannya
import X.Y
:Periksa
sys.modules
dengan namaos
danos.path
:Periksa
globals()
danlocals()
dict namespace denganos
danos.path
:Dari contoh di atas kami menemukan bahwa hanya
os
dimasukkan dalam namespace lokal dan global. Jadi, kita harus dapat menggunakan:Tapi tidak
path
.Setelah Anda menghapus
os
namespace dari lokal (), Anda tidak akan dapat mengaksesos
jugaos.path
meskipun mereka ada di sys.modules:Sekarang mari kita bicara tentang
import from
:from
:Periksa
sys.modules
denganos
danos.path
:Kami menemukan bahwa dalam
sys.modules
kami menemukan sama seperti yang kami lakukan sebelumnya dengan menggunakanimport name
OK, mari kita periksa seperti apa dict
locals()
danglobals()
namespace dicts:Anda dapat mengakses dengan menggunakan nama
path
bukan denganos.path
:Mari kita hapus 'path' dari
locals()
:Satu contoh terakhir menggunakan alias:
Dan tidak ada jalur yang ditentukan:
sumber
as SYMBOL
perubahan cara kerja jawaban ini?Kedua cara didukung karena suatu alasan: ada saat-saat ketika satu lebih tepat daripada yang lain.
import module
: bagus ketika Anda menggunakan banyak bit dari modul. Kekurangannya adalah bahwa Anda harus memenuhi syarat setiap referensi dengan nama modul.from module import ...
: bagus karena barang yang diimpor dapat digunakan langsung tanpa awalan nama modul. Kekurangannya adalah Anda harus membuat daftar setiap hal yang Anda gunakan, dan tidak jelas dalam kode dari mana sesuatu berasal.Yang digunakan tergantung pada yang membuat kode jelas dan mudah dibaca, dan memiliki lebih dari sedikit hubungannya dengan preferensi pribadi. Saya condong ke arah
import module
umumnya karena dalam kode itu sangat jelas dari mana objek atau fungsi berasal. Saya menggunakanfrom module import ...
ketika saya menggunakan beberapa objek / fungsi banyak dalam kode.sumber
from M import X
dan masih mendapatkan manfaat dari menggunakan kualifikasi? Sepertinya Anda bisa mendapatkan yang terbaik dari kedua dunia jika Anda masih bisa melakukannyaM.X
setelah impor itu.class m: from something.too.long import x, y, z
. Tidak akan benar-benar merekomendasikan itu.Saya pribadi selalu menggunakan
dan kemudian akses semuanya sebagai
dll. Alasannya adalah bahwa pada saat yang sama Anda memiliki doa pendek, dan Anda dengan jelas mendefinisikan namespace modul setiap rutin, sesuatu yang sangat berguna jika Anda harus mencari penggunaan modul yang diberikan di sumber Anda.
Tidak perlu dikatakan, jangan gunakan impor *, karena itu mencemari namespace Anda dan tidak memberi tahu Anda dari mana fungsi yang diberikan berasal (dari modul mana)
Tentu saja, Anda dapat menjalankan masalah jika Anda memiliki nama modul yang sama untuk dua modul berbeda dalam dua paket berbeda, misalnya
dalam hal ini, tentu saja Anda mengalami masalah, tetapi kemudian ada petunjuk kuat bahwa tata letak paket Anda cacat, dan Anda harus memikirkannya kembali.
sumber
Lebih baik bila Anda akan menggunakan banyak fungsi dari modul.
Yang terbaik adalah ketika Anda ingin menghindari polusi namespace global dengan semua fungsi dan tipe dari modul saat Anda hanya perlu
function
.sumber
Saya baru saja menemukan satu lagi perbedaan halus antara kedua metode ini.
Jika modul
foo
menggunakan impor berikut:Kemudian modul
bar
dapat digunakan tanpa sengajacount
seolah-olah itu didefinisikanfoo
, bukan diitertools
:Jika
foo
menggunakan:kesalahan masih mungkin terjadi, tetapi kecil kemungkinannya untuk dilakukan.
bar
perlu:Ini menyebabkan beberapa masalah bagi saya. Saya memiliki modul yang secara tidak sengaja mengimpor pengecualian dari modul yang tidak mendefinisikannya, hanya mengimpornya dari modul lain (menggunakan
from module import SomeException
). Ketika impor tidak lagi diperlukan dan dihapus, modul yang melanggar rusak.sumber
Inilah perbedaan lain yang tidak disebutkan. Ini disalin kata demi kata dari http://docs.python.org/2/tutorial/modules.html
Perhatikan bahwa saat menggunakan
item dapat berupa submodule (atau subpackage) dari paket, atau nama lain yang didefinisikan dalam paket, seperti fungsi, kelas atau variabel. Pernyataan impor terlebih dahulu menguji apakah item tersebut didefinisikan dalam paket; jika tidak, ini dianggap sebagai modul dan mencoba memuatnya. Jika gagal menemukannya, pengecualian ImportError dimunculkan.
Sebaliknya, ketika menggunakan sintaks suka
setiap item kecuali yang terakhir harus berupa paket; item terakhir bisa berupa modul atau paket tetapi tidak bisa berupa kelas atau fungsi atau variabel yang didefinisikan dalam item sebelumnya.
sumber
Karena saya juga seorang pemula, saya akan mencoba menjelaskan ini dengan cara sederhana: Dengan Python, kami memiliki tiga jenis
import
pernyataan yaitu:1. Impor generik:
jenis impor ini adalah favorit pribadi saya, satu-satunya kelemahan dari teknik impor ini adalah bahwa jika Anda perlu menggunakan fungsi modul apa pun, Anda harus menggunakan sintaks berikut:
tentu saja, ini meningkatkan upaya pengetikan tetapi sebagai pemula, ini akan membantu Anda untuk melacak modul dan fungsi yang terkait dengannya, (editor teks yang baik akan mengurangi upaya pengetikan secara signifikan dan direkomendasikan).
Upaya pengetikan selanjutnya dapat dikurangi dengan menggunakan pernyataan impor ini:
sekarang, alih-alih menggunakan,
math.sqrt()
Anda dapat menggunakanm.sqrt()
.2. Fungsi impor:
jenis impor ini paling cocok jika kode Anda hanya perlu mengakses satu atau beberapa fungsi dari modul, tetapi untuk menggunakan item baru dari modul Anda harus memperbarui pernyataan impor.
3. Impor universal:
Meskipun ini mengurangi upaya pengetikan secara signifikan tetapi tidak direkomendasikan karena akan mengisi kode Anda dengan berbagai fungsi dari modul dan namanya dapat bertentangan dengan nama fungsi yang ditentukan pengguna. contoh:
Jika Anda memiliki fungsi sqrt Anda sendiri bernama dan Anda mengimpor matematika, fungsi Anda aman: ada sqrt Anda dan ada math.sqrt. Namun, jika Anda melakukannya dari impor matematika *, Anda memiliki masalah: yaitu, dua fungsi berbeda dengan nama yang persis sama. Sumber: Codecademy
sumber
Dengan
import
, token harus berupa modul (file yang berisi perintah Python) atau paket (folder dalam file yangsys.path
berisi__init__.py
.)Ketika ada sub paket:
persyaratan untuk folder (paket) atau file (modul) sama, tetapi folder atau file harus di dalam
package2
yang harus di dalampackage1
, dan keduanyapackage1
danpackage2
harus berisi__init__.py
file. https://docs.python.org/2/tutorial/modules.htmlDengan
from
gaya impor:paket atau modul memasuki namespace file yang berisi
import
pernyataan sebagaimodule
(ataupackage
) alih-alihpackage1.package2.module
. Anda selalu dapat mengikat ke nama yang lebih nyaman:Hanya
from
gaya impor yang memungkinkan Anda menyebutkan nama fungsi atau variabel tertentu:diizinkan, tetapi
tidak diizinkan.
sumber
Untuk menambah apa yang dikatakan orang tentang
from x import *
: selain membuatnya lebih sulit untuk mengetahui dari mana nama berasal, ini melempar pemeriksa kode seperti Pylint. Mereka akan melaporkan nama-nama itu sebagai variabel yang tidak ditentukan.sumber
Jawaban saya sendiri untuk ini sebagian besar tergantung pada pertama, berapa banyak modul yang berbeda yang akan saya gunakan. Jika saya hanya akan menggunakan satu atau dua, saya akan sering menggunakan
from
...import
karena itu membuat penekanan tombol lebih sedikit di sisa file, tetapi jika saya akan menggunakan banyak modul yang berbeda, saya lebih suka hanyaimport
karena itu berarti bahwa setiap referensi modul mendokumentasikan diri. Saya bisa melihat dari mana setiap simbol berasal tanpa harus berburu.Biasanya saya lebih suka gaya dokumentasi impor diri dan hanya mengubah dari .. impor ketika berapa kali saya harus mengetik nama modul tumbuh di atas 10 hingga 20, bahkan jika hanya ada satu modul yang diimpor.
sumber
Salah satu perbedaan signifikan yang saya temukan yang secara mengejutkan tidak ada yang berbicara adalah menggunakan impor biasa Anda dapat mengakses
private variable
danprivate functions
dari modul impor, yang tidak mungkin dengan pernyataan dari-impor .Kode dalam gambar:
setting.py
plain_importer.py
from_importer.py
sumber
Modul Impor - Anda tidak perlu upaya tambahan untuk mengambil hal lain dari modul. Ini memiliki kelemahan seperti mengetik berlebihan
Modul Impor Dari - Kurang mengetik & Lebih banyak kontrol terhadap item modul mana yang dapat diakses. Untuk menggunakan item baru dari modul, Anda harus memperbarui pernyataan impor Anda.
sumber
Ada beberapa modul builtin yang sebagian besar berisi fungsi telanjang ( base64 , matematika , os , shutil , sys , time , ...) dan jelas merupakan praktik yang baik untuk memiliki fungsi telanjang ini terikat ke beberapa namespace dan dengan demikian meningkatkan keterbacaan Anda kode. Pertimbangkan betapa sulitnya memahami makna fungsi-fungsi ini tanpa ruang namanya:
daripada ketika mereka terikat pada beberapa modul:
Kadang-kadang Anda bahkan perlu namespace untuk menghindari konflik antara modul yang berbeda ( json.load vs pickle.load )
Di sisi lain ada beberapa modul yang sebagian besar berisi kelas ( configparser , datetime , tempfile , zipfile , ...) dan banyak dari mereka membuat nama kelas mereka cukup jelas:
jadi bisa ada perdebatan apakah menggunakan kelas-kelas ini dengan namespace modul tambahan dalam kode Anda menambahkan beberapa informasi baru atau hanya memperpanjang kode.
sumber
Saya ingin menambahkan ini, ada beberapa hal yang perlu dipertimbangkan selama panggilan impor:
Saya memiliki struktur berikut:
main.py:
dis.dis menunjukkan perbedaan:
Pada akhirnya mereka terlihat sama (STORE_NAME adalah hasil dalam setiap contoh), tetapi ini patut dicatat jika Anda perlu mempertimbangkan empat impor melingkar berikut:
Contoh 1
Ini bekerja
contoh2
Tidak ada dadu
contoh3
Masalah serupa ... tetapi jelas dari x impor y tidak sama dengan impor impor xy sebagai y
contoh4
Yang ini juga berfungsi
sumber
Ini adalah struktur direktori saya dari direktori saya saat ini:
The
import
Pernyataan mengingat semua nama menengah .Nama-nama ini harus memenuhi syarat:
The
from ... import ...
pernyataan ingat hanya nama diimpor .Nama ini tidak boleh memenuhi syarat:
sumber
Seperti yang dikatakan Jan Wrobel , satu aspek dari impor yang berbeda adalah cara pengungkapan impor.
Modul mymath
Penggunaan mymath :
Jika saya mengimpor
gcd
hanya untuk penggunaan internal, bukan untuk mengungkapkannya kepada penggunamymath
, ini bisa merepotkan. Saya sering melakukannya, dan dalam banyak kasus saya ingin "menjaga modul saya tetap bersih".Terlepas dari usulan Jan Wrobel untuk mengaburkan ini sedikit lebih banyak dengan menggunakan
import math
sebagai gantinya, saya sudah mulai menyembunyikan impor dari pengungkapan dengan menggunakan garis bawah utama:Dalam proyek yang lebih besar, "praktik terbaik" ini memungkinkan saya untuk mengontrol dengan tepat apa yang diungkapkan pada impor berikutnya dan apa yang tidak. Ini menjaga modul saya bersih dan membayar kembali pada ukuran proyek tertentu.
sumber