'İçe aktarma modülü' veya 'modül içe aktarmadan' kullanılsın mı?


411

Kullanmanın en iyi olup olmadığı konusunda kapsamlı bir rehber bulmaya çalıştım import moduleveya from module import? Python ile yeni başladım ve en iyi uygulamaları göz önünde bulundurarak başlamaya çalışıyorum.

Temelde, herkes deneyimlerini paylaşmak eğer ne tercihler diğer geliştiriciler ve herhangi kaçınmanın en iyi yolu nedir umuyordum FRİKİKLERİNDEN yolda?


5
Sadece size cevap vermek istedim, seçilen cevabın yanlış olduğunu. Farkın öznel olduğunu belirtirken, bir fark vardır. Bu muhtemelen hataları saptamanın zor olmasına yol açabilir. Michael Ray Lovetts'in cevabına bakınız.
Mayou36


2
Belirli adlandırılmış tanımlayıcıları 'from module import X,Y,Zvs içe aktarma arasında bir fark var'from module import * . İkincisi, ad alanınızı kirletir ve modülde neler olduğuna bağlı olarak öngörülemeyen sonuçlar verebilir. Daha da kötüsü from module import *birden fazla modülle yapıyor .
smci

Yanıtlar:


474

Arasındaki fark import moduleve from module import foobüyük ölçüde sübjektif de. En sevdiğinizi seçin ve kullanımınızda tutarlı olun. İşte karar vermenize yardımcı olacak bazı noktalar.

import module

  • Artıları:
    • importİfadeleriniz daha az korunur . Modülden başka bir öğe kullanmaya başlamak için ek ithalat eklemenize gerek yoktur
  • Eksileri:
    • module.fooKodunuzu yazmak yorucu ve gereksiz olabilir (tedium import module as modaha sonra yazarak en aza indirilebilir mo.foo)

from module import foo

  • Artıları:
    • Kullanmak için daha az yazma foo
    • Bir modülün hangi öğelerine erişilebileceği konusunda daha fazla kontrol
  • Eksileri:
    • Modülden yeni bir öğe kullanabilmek için öncelikle güncellemek zorunda importdeyimi
    • Hakkında bağlam kaybedersiniz foo. Örneğin, neye ceil()kıyasla daha az netmath.ceil()

Her iki yöntem de kabul edilebilir, ama yok kullanımı from module import *.

Herhangi bir makul büyük kod kümesi için, büyük import *olasılıkla modülün içine sağlamlaştırılacaksanız, kaldırılamaz. Bunun nedeni, kodda kullanılan öğelerin 'modül' den geldiğini belirlemek zor olduğundan, artık kullanmadığınızı düşündüğünüz noktaya ulaşmayı kolaylaştırır, importancak emin olmak son derece zordur.


66
+1, "modül içe aktarma *" kullanımından vazgeçirmek için, sadece ad alanını tıkar.
Christian Witts

22
ad alanını karıştırmak "içe aktarma *" nın en sorunlu kısmı değil , okunabilirliğin azalmasıdır: Herhangi bir ad çakışması (birim) testinde kendini gösterecektir. Ancak içe aktarılan modülden kullandığınız tüm isimler çıplak olacak, nary bir ipucu geliyordu. Kesinlikle "ithal *" nefret ediyorum.
Jürgen A. Erhard

21
Python'un Zen'i açıklığın örtükten daha iyi olduğunu söylemiyor mu?
Antony Koch

8
from module import *olarak kullanılıyorsa, özellikle faydalı olabilir: if(windows):\n\t from module_win import * \n else: \n\t from module_lin import *. Daha sonra, module_lin ve module_win içindeki işlev adları aynı adlara sahipse, ana modülünüz işletim sisteminden bağımsız işlev adları içerebilir. Her iki sınıfı da koşullu olarak miras almak gibidir.
anishsane

19
@anishsane. Bunu yapmanın başka bir yolu var. module_win dosyasını bir şey olarak içe aktarın. O zaman her zaman bir şey
Vinay

163

Burada, bir modüle yazmakla ilgili, bahsedilmeyen başka bir ayrıntı daha var. Bu çok yaygın olmayabilir, ama zaman zaman ihtiyacım vardı.

Python'da referansların ve ad bağlamanın çalışma şekli nedeniyle, bir modüldeki bazı sembolleri güncellemek istiyorsanız, foo.bar deyin, o modülün dışından ve bu değişiklikten "bkz." Diğer içe aktarma koduna sahipseniz, foo a doğru yol. Örneğin:

modül foo:

bar = "apples"

modül a:

import foo
foo.bar = "oranges"   # update bar inside foo module object

modül b:

import foo           
print foo.bar        # if executed after a's "foo.bar" assignment, will print "oranges"

Ancak, modül adları yerine sembol adlarını içe aktarırsanız, bu çalışmaz.

Örneğin, bunu modül a'da yaparsam:

from foo import bar
bar = "oranges"

Bir kodun dışında hiçbir kod çubuğu "portakal" olarak görecektir, çünkü çubuk ayarım sadece modülün içindeki "bar" adını etkiledi, foo modül nesnesine "ulaşamadı" ve "çubuğunu" güncelledi.


Bu son örnekle, hala 'foo' içindeki 'bar'ı güncellemek için' foo.bar = "orange" 'diyebilir misiniz?
velocirabbit

4
Hayır, son örnekte 'foo' adı bilinmiyor
Ghislain Leveque

31
BU yanıt, soruya "doğru" yanıtı verir: iki ithalat varyantı arasındaki fark nedir
Mayou36 23:17

3
Bu cevabın kesinlikle doğru olduğunu kanıtlayan bir pasaj yazdı, ama bunun ardındaki mantık nedir?
huangbeidu

Söylediğiniz şey yerel değişkenlere sahip olmak için ithal sembol isimleri ama küresel değişkenlere sahip olmak için ithal modül isimleri ???
WinEunuuchs2Unix

79

Birçok kişi importvs hakkında zaten açıklamış olsa da import from, kaputun altında neler olduğu ve değiştiği tüm yerlerin nerede olduğu hakkında biraz daha açıklamak istiyorum.


import foo:

fooGeçerli ad alanındaki bu modüle içe aktarılır ve bir başvuru oluşturur. Ardından, modülün içinden belirli bir özniteliğe veya yönteme erişmek için tamamlanmış modül yolunu tanımlamanız gerekir.

Örneğin foo.barama değilbar

from foo import bar:

fooListelenen tüm üyeleri ( bar) içe aktarır ve referanslar oluşturur . Değişkeni ayarlamaz foo.

Örneğin barama değil bazveyafoo.baz

from foo import *:

İthalat foove geçerli ad alanında bu modül tarafından tanımlanan tüm kamu nesnelere başvuru oluşturur (listelenen her şey __all__eğer __all__mevcutsa, ile başlamaz aksi takdirde her şey _). Değişkeni ayarlamaz foo.

Örneğin bar, bazama değil _quxya da foo._qux.


Şimdi ne zaman yaptığımızı görelim import X.Y:

>>> import sys
>>> import os.path

Kontrol sys.modulesadıyla osve os.path:

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

Kontrol globals()ve locals()ad alanı dikte osve ile os.path:

 >>> globals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> locals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> globals()['os.path']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os.path'
>>>

Yukarıdaki örnekte, yalnızca osyerel ve global ad alanına eklendiğini tespit ettik . Bu yüzden şunları kullanabilmeliyiz:

 >>> os
 <module 'os' from
  '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
 >>> os.path
 <module 'posixpath' from
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
 >>>

Ama değil path.

>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>

Silmek kez oshalktan () ad, erişmeye mümkün olmayacaktır ossıra sıra os.pathonlar sys.modules de bulunmasına rağmen:

>>> del locals()['os']
>>> os
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

Şimdi konuşalım import from:

from:

>>> import sys
>>> from os import path

Kontrol sys.modulesile osve os.path:

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

Biz sys.modulesdaha önce kullanarak yaptığımız gibi bulduğumuz bulunduimport name

Tamam, nasıl göründüğünü kontrol edelim locals()ve globals()ad alanı dikte ediyor:

>>> globals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> locals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['os']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os'
>>>

Aşağıdakileri pathdeğil, adı kullanarak erişebilirsiniz os.path:

>>> path
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

'Yolu' şuradan silelim locals():

>>> del locals()['path']
>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>

Takma ad kullanan son bir örnek:

>>> from os import path as HELL_BOY
>>> locals()['HELL_BOY']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['HELL_BOY']
<module 'posixpath' from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>

Ve tanımlanmış bir yol yok:

>>> globals()['path']
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
KeyError: 'path'
>>>

8
Bu ayrıntılı olsa da, bu oldukça karmaşık bir soru için listede gerçekten en iyi cevaptır. Bu özel konu için stilden daha önemli olan "başlık altında" inceliklerini açıklamaya yardımcı olacak gerçek kod sağlar. Keşke birden fazla kez oy verebilseydim!
Mike Williamson

Kullanmak as SYMBOLbu cevabın nasıl çalıştığını değiştiriyor mu ?
Maximilian Burszley

40

Her iki yol da bir nedenden dolayı desteklenir: birinin diğerinden daha uygun olduğu zamanlar vardır.

  • import module: modülden çok sayıda bit kullanırken güzel. dezavantajı, her bir referansı modül adıyla nitelemenizdir.

  • from module import ...: içe aktarılan öğelerin modül adı öneki olmadan doğrudan kullanılabilir olması güzel. Dezavantajı, kullandığınız her şeyi listelemeniz ve bir şeyin nereden geldiğinin kodda net olmamasıdır.

Hangi kodun hangisinin açık ve okunabilir olduğuna bağlıdır ve kişisel tercih ile ilgisi yoktur. import moduleGenelde doğru eğildi çünkü kodda bir nesnenin veya fonksiyonun nereden geldiğini çok açık. Kullandığım from module import ...bazı nesne kullanıyorum zaman / a işlev çok kodunda.


1
Niteleyicileri bir şekilde kullanmanın from M import Xve yine de faydalanmanın bir yolu var mı ? Bu M.Xithalattan sonra hala yapabilirseniz, her iki dünyanın en iyisini elde edebilirsiniz .
Eklem bacaklılar

@artgropod: Tür. Yapabilirsin class m: from something.too.long import x, y, z. Gerçekten olsa tavsiye etmem.
Yalan Ryan

35

Şahsen her zaman kullanırım

from package.subpackage.subsubpackage import module

ve sonra her şeye

module.function
module.modulevar

Bunun nedeni, aynı zamanda kısa bir çağrışmanızın olması ve her rutinin modül ad alanını açıkça tanımlamanızdır; bu, kaynağınızda belirli bir modülün kullanımını aramak zorunda kalırsanız çok yararlıdır.

Söylemeye gerek yok, import * 'ı kullanmayın, çünkü ad alanınızı kirletir ve belirli bir işlevin nereden geldiğini (hangi modülden) söylemez

Elbette, iki farklı pakette iki farklı modül için aynı modül adına sahipseniz,

from package1.subpackage import module
from package2.subpackage import module

bu durumda, elbette sıkıntılarla karşılaşıyorsunuz, ancak daha sonra paket düzeninizin kusurlu olduğuna dair güçlü bir ipucu var ve yeniden düşünmeniz gerekiyor.


10
Son durumda, her zaman şunları kullanabilirsiniz: import pkgN.sub.module modN olarak her modül için size ayrı adlar verir. Ayrıca, uzun bir adı kısaltmak veya tek bir ad değişikliğiyle aynı API'nın (örn. DB API modülleri) uygulamaları arasında geçiş yapmak için 'modulename'i mod1 olarak içe aktar' desenini de kullanabilirsiniz.
Jeff Shannon

15
import module

Modülden birçok işlevi kullanacağınız zaman en iyisidir.

from module import function

Sadece ihtiyacınız olduğunda bir modülün tüm fonksiyonları ve türleri ile global isim alanını kirletmekten kaçınmak istediğinizde en iyisidir function.


7
Eğer 'ithal modülü' yaparsanız, global isim alanındaki tek şey elbette 'modül' mü? Ad alanını yalnızca 'from .. import *' yaparsanız kirletirsiniz.
John Fouhy

10

Bu iki yöntem arasında daha ince bir fark daha buldum.

Modül fooaşağıdaki içe aktarmayı kullanıyorsa:

from itertools import count

Daha sonra modül baryanlışlıkla countdeğil, tanımlandığı gibi fookullanılabilir itertools:

import foo
foo.count()

Kullanıyorsa foo:

import itertools

hata hala mümkündür, ancak yapılması daha az olasıdır. barihtiyacı olmak:

import foo
foo.itertools.count()

Bu benim için bazı sıkıntılara neden oldu. Yanlışlıkla tanımlanmamış bir modülden, sadece diğer modülden (kullanarak from module import SomeException) bir istisna ithal bir modül vardı . İçe aktarma artık gerekli olmadığında ve kaldırıldığında, rahatsız edici modül kırıldı.


10

Burada belirtilmeyen başka bir fark var. Bu, http://docs.python.org/2/tutorial/modules.html adresinden aynen kopyalanmıştır.

Kullanırken

from package import item

öğe, paketin bir alt modülü (veya alt paketi) veya paket içinde tanımlanan işlev, sınıf veya değişken gibi başka bir ad olabilir. İmport ifadesi önce öğenin pakette tanımlı olup olmadığını test eder; değilse, bir modül olduğunu varsayar ve yüklemeye çalışır. Bulamazsa, bir ImportError istisnası oluşur.

Bunun aksine, söz dizimi gibi

import item.subitem.subsubitem

son hariç her öğe bir paket olmalıdır; son öğe bir modül veya paket olabilir, ancak önceki öğede tanımlanan bir sınıf veya işlev ya da değişken olamaz.


Fark ettim başka bir şey, öğe de paket içinde bir alt modül ise o zaman "paket ithalat öğesinden" çalışır ama "ithalat paketi" package.item.subitem = ... biz boş bir init .py ile çalışmıyor , biz sürece paketin init dosyasında "içe aktarma öğesi" var .
Amitoz Dandiana

6

Ben de bir acemi olduğumdan, bunu basit bir şekilde açıklamaya çalışacağım: Python'da üç tür ifademiz var import:

1. Genel ithalat:

import math

Bu içe aktarma türü benim kişisel favorim, bu içe aktarma tekniğinin tek dezavantajı, herhangi bir modülün işlevini kullanmanız gerekiyorsa, aşağıdaki sözdizimini kullanmanız gerektiğidir:

math.sqrt(4)

Tabii ki, yazma çabasını arttırır, ancak bir başlangıç ​​olarak, modül ve onunla ilişkili işlevi izlemenize yardımcı olacaktır, (iyi bir metin editörü yazma çabasını önemli ölçüde azaltacaktır ve önerilir).

Yazma çabası, bu içe aktarma ifadesi kullanılarak daha da azaltılabilir:

import math as m

şimdi kullanmak yerine math.sqrt()kullanabilirsiniz m.sqrt().

2. Fonksiyon ithalatı:

from math import sqrt

bu tür içe aktarma, kodunuzun modülden yalnızca tek veya birkaç işleve erişmesi gerekiyorsa, ancak modüldeki herhangi bir yeni öğeyi kullanmak için içe aktarma ifadesini güncellemeniz gerektiğinde en uygunudur.

3. Evrensel ithalat:

from math import * 

Yazma çabasını önemli ölçüde azaltmasına rağmen, kodunuzu modülden çeşitli işlevlerle dolduracağı ve adlarının kullanıcı tanımlı işlevlerin adıyla çakışabileceği için önerilmez. misal:

Kendi adlandırılmış sqrt'ınızın bir işlevine sahipseniz ve matematik içe aktarırsanız, işleviniz güvenlidir: sqrt'ınız var ve math.sqrt var. Bununla birlikte, matematik içe aktarma * 'dan yaparsanız, bir sorununuz vardır: yani, aynı ada sahip iki farklı işlev. Kaynak: Codecademy


5
import package
import module

İle importbelirteç bir modül (bir dosya Python komutlarını içeren) ya da bir paket olmalı, (bir klasör sys.pathbir dosya içeren __init__.py.)

Alt paketler olduğunda:

import package1.package2.package
import package1.package2.module

klasörün (paket) veya dosya (modül) için gereksinimler aynıdır, ancak klasör veya dosya içinde olmalıdır package2ki içinde olmalıdır package1ve her iki package1ve package2içermelidir __init__.pydosyaları. https://docs.python.org/2/tutorial/modules.html

İle fromithalat tarzında:

from package1.package2 import package
from package1.package2 import module

paket veya modül, importifadeyi içeren dosyanın ad alanını yerine module(veya package) olarak girer package1.package2.module. Her zaman daha uygun bir isme bağlanabilirsiniz:

a = big_package_name.subpackage.even_longer_subpackage_name.function

Yalnızca fromiçe aktarma stili belirli bir işlevi veya değişkeni adlandırmanıza izin verir:

from package3.module import some_function

izin verilir, ancak

import package3.module.some_function 

Müsade edilmez.


4

İnsanların söylediklerine eklemek için from x import *: isimlerin nereden geldiğini söylemeyi zorlaştırmanın yanı sıra, bu Pylint gibi kod denetleyicilerini atar. Bu adları tanımsız değişkenler olarak rapor edeceklerdir.


3

Buna kendi cevabım çoğunlukla önce, kaç farklı modül kullanacağım. Yalnızca bir veya iki kullanacaksam, sık sık kullanacağım from... importçünkü dosyanın geri kalanında daha az tuş vuruşu yapar, ancak birçok farklı modülü kullanacaksam, sadece importçünkü bu, her modül referansının kendi kendini belgelediği anlamına gelir. Avlanmak zorunda kalmadan her sembolün nereden geldiğini görebiliyorum.

Usuaully Ben düz belgelendirme kendi kendine belgeleme tarzı tercih ve sadece ithalat .. ithalat sadece bir modül olsa bile, modül adını yazmak zorunda sayısı 10 ila 20 üzerinde büyüdüğü zaman ithalat için değiştirin.


1

Öğrendiğim önemli farkın biri şaşırtıcı kimse bahsetti olduğunu düz kullanarak o ithalat erişebileceğiniz private variableve private functionsbirlikte mümkün değildir ithal modülünden gelen gelen-ithalat beyanı.

resim açıklamasını buraya girin

Resimdeki kod:

setting.py

public_variable = 42
_private_variable = 141
def public_function():
    print("I'm a public function! yay!")
def _private_function():
    print("Ain't nobody accessing me from another module...usually")

plain_importer.py

import settings
print (settings._private_variable)
print (settings.public_variable)
settings.public_function()
settings._private_function()

# Prints:
# 141
# 42
# I'm a public function! yay!
# Ain't nobody accessing me from another module...usually

from_importer.py

from settings import *
#print (_private_variable) #doesn't work
print (public_variable)
public_function()
#_private_function()   #doesn't work

0

Modülü İçe Aktar - Modülden başka bir şey almak için ek çabaya ihtiyacınız yoktur. Fazladan yazma gibi dezavantajları vardır

Modül İçe Aktarma Kaynağı - Bir modülün hangi öğelerine erişilebileceği konusunda daha az yazım ve daha fazla kontrol. Modülden yeni bir öğe kullanmak için içe aktarma ifadenizi güncellemeniz gerekir.


0

Çoğunlukla çıplak fonksiyonlar içeren bazı yerleşik modüller vardır ( base64 , matematik , os , shutil , sys , zaman , ...) ve bu çıplak fonksiyonların bazı ad alanlarına bağlı olması ve böylece okunabilirliğinizi arttırmanız kesinlikle iyi bir uygulamadır . kodu. Bu işlevlerin ad alanları olmadan anlamını anlamanın ne kadar zor olduğunu düşünün:

copysign(foo, bar)
monotonic()
copystat(foo, bar)

bazı modüllere bağlı olduklarından daha:

math.copysign(foo, bar)
time.monotonic()
shutil.copystat(foo, bar)

Bazen farklı modüller arasındaki çakışmaları önlemek için ad alanına bile ihtiyacınız olabilir ( json.load vs. pickle.load )


Öte yandan, çoğunlukla sınıflar içeren bazı modüller vardır ( configparser , datetime , tempfile , zipfile , ...) ve birçoğu sınıf adlarını yeterince açıklayıcı yapar:

configparser.RawConfigParser()
datetime.DateTime()
email.message.EmailMessage()
tempfile.NamedTemporaryFile()
zipfile.ZipFile()

bu nedenle, bu sınıfları kodunuzdaki ek modül ad alanı ile kullanmanın bazı yeni bilgiler ekleyip eklemeyeceği veya sadece kodu uzatabileceği konusunda bir tartışma olabilir.


0

Buna eklemek istiyorum, ithalat çağrıları sırasında dikkate alınması gereken bazı şeyler var:

Aşağıdaki yapıya sahibim:

mod/
    __init__.py
    main.py
    a.py
    b.py
    c.py
    d.py

main.py:

import mod.a
import mod.b as b
from mod import c
import d

dis.dis farkı gösterir:

  1           0 LOAD_CONST               0 (-1)
              3 LOAD_CONST               1 (None)
              6 IMPORT_NAME              0 (mod.a)
              9 STORE_NAME               1 (mod)

  2          12 LOAD_CONST               0 (-1)
             15 LOAD_CONST               1 (None)
             18 IMPORT_NAME              2 (b)
             21 STORE_NAME               2 (b)

  3          24 LOAD_CONST               0 (-1)
             27 LOAD_CONST               2 (('c',))
             30 IMPORT_NAME              1 (mod)
             33 IMPORT_FROM              3 (c)
             36 STORE_NAME               3 (c)
             39 POP_TOP

  4          40 LOAD_CONST               0 (-1)
             43 LOAD_CONST               1 (None)
             46 IMPORT_NAME              4 (mod.d)
             49 LOAD_ATTR                5 (d)
             52 STORE_NAME               5 (d)
             55 LOAD_CONST               1 (None)

Sonunda aynı görünüyorlar (her örnekte STORE_NAME sonucudur), ancak aşağıdaki dört dairesel ithalatı göz önünde bulundurmanız gerekip gerekmediğini belirtmek gerekir:

örnek 1

foo/
   __init__.py
   a.py
   b.py
a.py:
import foo.b 
b.py:
import foo.a
>>> import foo.a
>>>

Bu çalışıyor

example2

bar/
   __init__.py
   a.py
   b.py
a.py:
import bar.b as b
b.py:
import bar.a as a
>>> import bar.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "bar\a.py", line 1, in <module>
    import bar.b as b
  File "bar\b.py", line 1, in <module>
    import bar.a as a
AttributeError: 'module' object has no attribute 'a'

Nafile

example3

baz/
   __init__.py
   a.py
   b.py
a.py:
from baz import b
b.py:
from baz import a
>>> import baz.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "baz\a.py", line 1, in <module>
    from baz import b
  File "baz\b.py", line 1, in <module>
    from baz import a
ImportError: cannot import name a

Benzer bir sorun ... ama açıkça x import y'den, import import xy ile y ile aynı değil

example4

qux/
   __init__.py
   a.py
   b.py
a.py:
import b 
b.py:
import a
>>> import qux.a
>>>

Bu da işe yarıyor


0

Bu benim geçerli dizinin dizin yapısı:

.  
└─a  
   └─b  
     └─c
  1. importİfadesi hatırlar tüm ara isimler .
    Bu isimler olmak zorunda nitelikli:

    In[1]: import a.b.c
    
    In[2]: a
    Out[2]: <module 'a' (namespace)>
    
    In[3]: a.b
    Out[3]: <module 'a.b' (namespace)>
    
    In[4]: a.b.c
    Out[4]: <module 'a.b.c' (namespace)>
  2. from ... import ...İfadesi hatırlar sadece ithal ismi .
    Bu ad olmamalıdır nitelikli olması:

    In[1]: from a.b import c
    
    In[2]: a
    NameError: name 'a' is not defined
    
    In[2]: a.b
    NameError: name 'a' is not defined
    
    In[3]: a.b.c
    NameError: name 'a' is not defined
    
    In[4]: c
    Out[4]: <module 'a.b.c' (namespace)>

  • Not: Tabii ki, Python konsolumu 1. ve 2. adımlar arasında yeniden başlattım.

0

As Jan Wrobel söz farklı ithalat bir yönü ithalatı açıklanan, bir şekilde yer almaktadır.

Modül mymath

from math import gcd
...

Kullanımına mymath :

import mymath
mymath.gcd(30, 42)  # will work though maybe not expected

Ben ithal ederse gcddahili kullanım için yalnızca, kullanıcılarına bunu ifşa etmemeyimymath , bu rahatsız edici olabilir. Buna oldukça sık sahibim ve çoğu durumda "modüllerimi temiz tutmak" istiyorum.

Jan Wrobel'in bunu kullanarak biraz daha gizleme önerisinin yanı sıra, import mathithalatı önde gelen bir alt çizgi kullanarak açıklamadan gizlemeye başladım:

# for instance...
from math import gcd as _gcd
# or...
import math as _math

Daha büyük projelerde bu "en iyi uygulama", sonraki ithalatlara neyin açıklanacağını ve neyin olmadığını tam olarak kontrol etmeme izin verir. Bu, modüllerimi temiz tutar ve belirli bir projede geri ödeme yapar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.