การเปลี่ยนแปลงคำสั่ง import python3


177

ฉันไม่เข้าใจสิ่งต่อไปนี้จากpep-0404

ใน Python 3 การอิมพอร์ตสัมพัทธ์โดยนัยภายในแพ็คเกจไม่สามารถทำได้อีกต่อไป - รองรับการนำเข้าสัมบูรณ์และการนำเข้าสัมพัทธ์อย่างชัดเจนเท่านั้น นอกจากนี้การนำเข้ารูปดาว (เช่นจากการนำเข้า x *) ได้รับอนุญาตในรหัสระดับโมดูลเท่านั้น

การนำเข้าแบบสัมพันธ์คืออะไร อนุญาตการนำเข้าดาวในสถานที่อื่นได้อีกใน python2 กรุณาอธิบายด้วยตัวอย่าง

คำตอบ:


277

การนำเข้าญาติเกิดขึ้นทุกครั้งที่คุณกำลังนำเข้าแพ็คเกจที่สัมพันธ์กับสคริปต์ / แพ็คเกจปัจจุบัน

พิจารณาต้นไม้ดังต่อไปนี้:

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

ตอนนี้คุณต้องมีอะไรบางอย่างจากderived.py base.pyใน Python 2 คุณสามารถทำสิ่งนี้ (ในderived.py):

from base import BaseThing

งูหลาม 3 ไม่สนับสนุนแล้วว่าตั้งแต่มันไม่ชัดเจนว่าคุณต้องการให้ญาติ 'หรือ base'แน่นอน' กล่าวอีกนัยหนึ่งถ้ามีแพคเกจ Python ชื่อbaseติดตั้งในระบบคุณจะได้รับสิ่งที่ผิด

แต่ต้องการให้คุณใช้การนำเข้าที่ชัดเจนซึ่งระบุตำแหน่งของโมดูลอย่างชัดเจนบนเส้นทางที่เหมือนกัน คุณderived.pyจะมีลักษณะเช่น:

from .base import BaseThing

ผู้นำ.กล่าวว่า 'นำเข้าbaseจากไดเรกทอรีโมดูล'; ในคำอื่น ๆ ที่แมปไป.base./base.py

ในทำนองเดียวกันมี..คำนำหน้าซึ่งขึ้นไปตามลำดับชั้นไดเรกทอรีเช่น../(ด้วย..modการจับคู่กับ../mod.py) และจากนั้น...ไปสองระดับขึ้นไป ( ../../mod.py) และอื่น ๆ

อย่างไรก็ตามโปรดทราบว่าเส้นทางสัมพัทธ์ที่ระบุไว้ด้านบนนั้นสัมพันธ์กับไดเรกทอรีที่โมดูลปัจจุบัน ( derived.py) อยู่ในไม่ใช่ไดเรกทอรีทำงานปัจจุบัน


@BrenBarnได้อธิบายกรณีนำเข้าระดับดาวแล้ว เพื่อความสมบูรณ์ฉันจะต้องพูดเหมือนกัน;)

ตัวอย่างเช่นคุณต้องใช้mathฟังก์ชั่นบางอย่าง แต่คุณจะใช้งานได้ในฟังก์ชั่นเดียวเท่านั้น ใน Python 2 คุณได้รับอนุญาตให้กึ่งขี้เกียจ:

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

โปรดทราบว่ามันได้ทริกเกอร์คำเตือนใน Python 2 แล้ว:

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

ในโค้ด Python 2 ที่ทันสมัยคุณควรและใน Python 3 คุณต้องทำอย่างใดอย่างหนึ่ง:

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

หรือ:

from math import *

def sin_degrees(x):
    return sin(degrees(x))

14

สำหรับการนำเข้าญาติดูเอกสาร sys.pathนำเข้าญาติคือเมื่อคุณนำเข้าจากโมดูลที่สัมพันธ์กับตำแหน่งของโมดูลที่แทนอย่างจาก

สำหรับimport *Python 2 อนุญาตให้ดาวนำเข้าภายในฟังก์ชั่นเช่น:

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

มีการออกคำเตือนสำหรับสิ่งนี้ใน Python 2 (อย่างน้อยรุ่นล่าสุด) ใน Python 3 ไม่ได้รับอนุญาตอีกต่อไปและคุณสามารถนำเข้าดาวได้ที่ระดับสูงสุดของโมดูล (ไม่ใช่ภายในฟังก์ชั่นหรือคลาส)


6
เหตุใดการตัดสินใจนั้นจึงเกิดขึ้น
Dor

1
ฉันเดาว่าความคิดที่อยู่เบื้องหลังมันคือ 'ชัดเจนกว่าดีกว่า' จาก PEP20 - The Zen of Python จุดก่อนที่โมดูลจะทำการเชื่อมโยงแบบสัมพันธ์ / ไม่เกี่ยวข้องอย่างชัดเจนดังนั้นการแก้ไขการชนชื่อที่เป็นไปได้ แม้ว่า 'ความสามารถในการอ่านจะนับได้' ทนทุกข์ทรมานเล็กน้อย
Pafnucy

2
ไม่ในความเป็นจริงมันเป็นการตัดสินใจที่ "ตรงกันข้าม", "การปฏิบัติจริงเต้นบริสุทธิ์" นั่นเป็นสิ่งที่จำเป็นเพื่อปรับการเข้าถึงตัวแปรภายในให้เหมาะสมที่สุดภายในฟังก์ชั่นเนื่องจากไม่มี "import *" คอมไพเลอร์จะรู้เพียงแค่การวิเคราะห์โค้ดตัวแปรใดบ้างที่เป็นโลคัลและสามารถค้นหาได้โดยตรง ในความเป็นจริงฟังก์ชั่นไม่ได้ใช้ dict สำหรับที่จัดเก็บในตัวเครื่อง แต่เป็นอาร์เรย์ที่ปรับให้เหมาะสมที่สุดซึ่งตัวแปรจะได้รับดัชนีเฉพาะ
Veky

11

เพื่อรองรับทั้ง Python 2 และ Python 3 ให้ใช้การนำเข้าที่สัมพันธ์อย่างชัดเจนดังต่อไปนี้ พวกมันสัมพันธ์กับโมดูลปัจจุบัน พวกเขาได้รับการสนับสนุนที่เริ่มต้นจาก 2.5

from .sister import foo
from . import brother
from ..aunt import bar
from .. import uncle

14
import .brother ทำให้ฉันมีข้อผิดพลาดทางไวยากรณ์ที่ไม่ถูกต้องใน Python 3.5 นี่เป็นปกติ? ฉันได้เริ่มต้น. py ในไดเรกทอรีที่อยู่ใน
Frikster

1
import .brotherเป็นไวยากรณ์ที่ไม่ถูกต้องสำหรับ python 2 และ 3
Rodrigo E. Principe

@ RodrigoE.Principe และอื่น ๆ import ..uncleน่าจะเป็น แก้ไขแล้ว. โอ้ข้าคิดอะไรอยู่ ... อาจจะมีอัศวินที่พูด Ni!
Akseli Palén

4

เพิ่มอีกกรณีหนึ่งในคำตอบของMichałGórny:

โปรดทราบว่าการนำเข้าที่สัมพันธ์กันจะขึ้นอยู่กับชื่อของโมดูลปัจจุบัน เนื่องจากชื่อของโมดูลหลักเสมอ " __main__" โมดูลที่มีไว้เพื่อใช้เป็นโมดูลหลักของแอปพลิเคชัน Python จะต้องใช้การนำเข้าแบบสัมบูรณ์เสมอ

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