Perubahan pada pernyataan impor python3

177

Saya tidak mengerti yang berikut dari pep-0404

Dalam Python 3, impor relatif implisit dalam paket tidak lagi tersedia - hanya impor absolut dan impor relatif eksplisit yang didukung. Selain itu, impor bintang (misalnya dari x impor *) hanya diizinkan dalam kode tingkat modul.

Apa itu impor relatif? Di tempat lain mana impor bintang diizinkan dalam python2? Tolong jelaskan dengan contoh.

balki
sumber

Jawaban:

277

Impor relatif terjadi setiap kali Anda mengimpor paket relatif terhadap skrip / paket saat ini.

Pertimbangkan contoh pohon berikut:

mypkg
├── base.py
└── derived.py

Sekarang, Anda derived.pymembutuhkan sesuatu dari base.py. Dengan Python 2, Anda bisa melakukannya seperti ini derived.py:

from base import BaseThing

Python 3 tidak lagi mendukung itu karena tidak eksplisit apakah Anda menginginkan 'relatif' atau 'absolut' base. Dengan kata lain, jika ada paket Python yang baseterinstal di sistem, Anda akan salah.

Alih-alih itu mengharuskan Anda untuk menggunakan impor eksplisit yang secara eksplisit menentukan lokasi modul berdasarkan path-sama. Anda derived.pyakan terlihat seperti:

from .base import BaseThing

Yang terkemuka .mengatakan 'impor basedari direktori modul'; dengan kata lain, .basepeta ke ./base.py.

Demikian pula, ada ..awalan yang naik hirarki direktori seperti ../(dengan ..modpemetaan ke ../mod.py), dan ...yang naik dua tingkat (../../mod.py ) dan seterusnya.

Namun harap dicatat bahwa jalur relatif yang tercantum di atas relatif terhadap direktori tempat modul saat ini ( derived.py) berada, bukan direktori kerja saat ini.


@BrenBarn telah menjelaskan impor bintang. Untuk kelengkapan, saya harus mengatakan hal yang sama;).

Misalnya, Anda perlu menggunakan beberapa mathfungsi tetapi Anda menggunakannya hanya dalam satu fungsi. Dalam Python 2 Anda diizinkan menjadi semi-malas:

def sin_degrees(x):
    from math import *
    return sin(degrees(x))

Perhatikan bahwa itu sudah memicu peringatan dengan Python 2:

a.py:1: SyntaxWarning: import * only allowed at module level
  def sin_degrees(x):

Dalam kode Python 2 modern Anda harus dan dalam Python 3 Anda harus melakukan salah satu:

def sin_degrees(x):
    from math import sin, degrees
    return sin(degrees(x))

atau:

from math import *

def sin_degrees(x):
    return sin(degrees(x))
Michał Górny
sumber
14

Untuk impor relatif lihat dokumentasi . Impor relatif adalah ketika Anda mengimpor dari modul relatif ke lokasi modul itu, bukan dari mutlak sys.path.

Adapun import *, Python 2 membolehkan impor bintang dalam fungsi, misalnya:

>>> def f():
...     from math import *
...     print sqrt

Peringatan dikeluarkan untuk ini dalam Python 2 (setidaknya versi terbaru). Dalam Python 3 itu tidak lagi diizinkan dan Anda hanya dapat melakukan impor bintang di tingkat atas modul (tidak di dalam fungsi atau kelas).

BrenBarn
sumber
6
Mengapa keputusan itu dibuat?
Dor
1
Dugaan saya adalah bahwa ide di baliknya adalah 'Eksplisit lebih baik daripada implisit.' dari PEP20 - The Zen of Python. Modul Dot before membuat tautan yang relatif / tidak relevan secara eksplisit sehingga menyelesaikan kemungkinan tabrakan nama. Meskipun 'Keterbacaan penting.' sedikit menderita.
Pafnucy
2
Tidak, pada kenyataannya itu adalah keputusan "berlawanan", "kepraktisan mengalahkan kemurnian". Itu diperlukan untuk mengoptimalkan akses variabel lokal di dalam fungsi, karena tanpa "impor *", kompiler selalu tahu hanya dengan menganalisis kode, variabel apa yang lokal dan dapat dilihat secara langsung. Bahkan, fungsi-fungsi bahkan tidak menggunakan dict untuk penyimpanan lokal, tetapi sebuah array yang dioptimalkan di mana variabel mendapatkan indeks unik.
Veky
11

Untuk mendukung Python 2 dan Python 3, gunakan impor relatif eksplisit seperti di bawah ini. Mereka relatif terhadap modul saat ini. Mereka telah didukung mulai dari 2,5 .

from .sister import foo
from . import brother
from ..aunt import bar
from .. import uncle
Akseli Palén
sumber
14
import .brother memberi saya kesalahan sintaks yang tidak valid dalam Python 3.5. Ini normal? Saya memiliki init .py di direktori yang ada di
Frikster
1
import .brothersintaks tidak valid untuk kedua python 2 dan 3
Rodrigo E. Principe
@ RodrigoE.Principe dan sepertinya begitu import ..uncle. Tetap. Oh, apa yang telah kupikirkan ... mungkin terganggu oleh para ksatria yang mengatakan Ni!
Akseli Palén
4

Menambahkan kasus lain pada jawaban Michał Górny:

Perhatikan bahwa impor relatif didasarkan pada nama modul saat ini. Karena nama modul utama selalu " __main__", modul yang dimaksudkan untuk digunakan sebagai modul utama aplikasi Python harus selalu menggunakan impor absolut.

Panfeng Li
sumber