Використовувати "модуль імпорту" або "з імпорту модуля"?


411

Я намагався знайти повне керівництво по чи це краще використовувати import moduleабо from module import? Я тільки почав з Python і намагаюся почати з найкращих практик.

В основному, я сподівався, що хтось зможе поділитися своїм досвідом, якими перевагами володіють інші розробники та який найкращий спосіб уникнути будь-яких проблем із дорогою?


5
Я просто хотів повідомити вам, що обрана відповідь неправильна. У ньому зазначається, що різниця є суб'єктивною, тоді як є різниця. Це може призвести до важко виявити помилки. Дивіться відповідь Майкла Рея Ловетца.
Mayou36


2
Існує певна різниця між імпортом конкретних ідентифікованих ідентифікаторів 'from module import X,Y,Zпроти'from module import * . Останнє забруднює ваше простір імен і може дати непередбачувані результати залежно від того, що відбувається в модулі. Гірше все-таки робиться from module import *з декількома модулями.
smci

Відповіді:


474

Різниця між import moduleі from module import fooпереважно суб'єктивна. Виберіть той, який вам найбільше подобається, і будьте послідовні у використанні. Ось кілька моментів, які допоможуть вам вирішити.

import module

  • Плюси:
    • Менше обслуговування ваших importзаяв. Не потрібно додавати жодного додаткового імпорту, щоб почати використовувати інший елемент з модуля
  • Мінуси:
    • Введення module.fooкоду може бути виснажливим і зайвим (тидій можна мінімізувати, використовуючи import module as moпотім набравши текст mo.foo)

from module import foo

  • Плюси:
    • Менш набравши для використання foo
    • Більший контроль над тим, до яких елементів модуля можна отримати доступ
  • Мінуси:
    • Щоб використовувати новий елемент з модуля, вам потрібно оновити свою importзаяву
    • Ви втрачаєте контекст про foo. Наприклад, менш зрозуміло, що з цим ceil()робитьсяmath.ceil()

Будь-який метод прийнятний, але не використовуйте from module import *.

Будь-який розумний великий набір коду, якщо ви import *, ймовірно, цементуєте його в модуль, неможливо видалити. Це тому, що важко визначити, які елементи, що використовуються в коді, походять від "модуля", що дозволяє легко дістатись до того пункту, коли ви думаєте, що більше не використовуєте, importале в цьому бути надзвичайно важко.


66
+1 для відмови від використання "від імпорту модуля *", це просто захаращує простір імен.
Крістіан Віттс

22
захаращення простору імен не є найбільш проблематичною частиною "імпорту *", це зменшення читабельності: будь-які конфлікти імен проявлять себе в (одиничному) тестуванні. Але всі назви, які ви використовуєте в імпортному модулі, будуть голими, з нарієм натяком, звідки вони походять. Я абсолютно ненавиджу "імпорт *".
Юрген А. Ерхард

21
Чи не говорить Дзен Пітона, що явний кращий, ніж неявний?
Антоній Кох

8
from module import *може бути особливо корисно, якщо використовувати його в якості: if(windows):\n\t from module_win import * \n else: \n\t from module_lin import *. Тоді ваш батьківський модуль потенційно може містити незалежні імена функцій ОС, якщо імена функцій у module_lin & module_win мають однакові імена. Це як умовно успадковувати будь-який клас.
anishsane

19
@anishsane. Є ще один спосіб зробити це. імпортувати module_win як щось. Тоді завжди використовуйте something.method_name ()
Vinay

163

Тут є ще одна деталь, не згадана, що стосується запису до модуля. Зрозуміло, це може бути не дуже поширеним, але мені це потрібно час від часу.

Через те, як посилання та посилання на імена працюють у Python, якщо ви хочете оновити якийсь символ у модулі, скажімо, foo.bar, з-за цього модуля та інший код імпорту "бачити", що змінюється, вам потрібно імпортувати foo a певним чином. Наприклад:

модуль foo:

bar = "apples"

модуль a:

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

модуль b:

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

Однак якщо ви імпортуєте імена символів замість імен модулів, це не працюватиме.

Наприклад, якщо я це роблю в модулі a:

from foo import bar
bar = "oranges"

Жоден код поза заповітом не буде бачити бар як "апельсини", оскільки моє налаштування бар просто вплинуло на назву "bar" всередині модуля a, воно не "потрапило" в об'єкт модуля foo та оновило його "bar".


З цього останнього прикладу, ви все ще можете зателефонувати 'foo.bar = "помаранчевий"', щоб оновити "бар" всередині "foo"?
velocirabbit

4
Ні, в останньому прикладі назва "foo" невідома
Ghislain Leveque

31
Ця відповідь дає "справжню" відповідь на питання: чим відрізняється два варіанти імпорту
Mayou36

3
Написав якийсь фрагмент, щоб довести цю відповідь абсолютно правильно, але яка обґрунтування цього лежить?
huangbeidu

Я думаю, що ви говорите, це назви символів імпорту, щоб вони мали локальні змінні, але імена імпортних модулів мали глобальні змінні ???
WinEunuuchs2Unix

79

Незважаючи на те, що багато людей вже пояснювали про importvs import from, я хочу спробувати трохи більше пояснити, що відбувається під кришкою та де знаходяться всі місця, де вона змінюється.


import foo:

Імпортує fooта створює посилання на цей модуль у поточному просторі імен. Потім потрібно визначити завершений шлях модуля, щоб отримати доступ до певного атрибута чи методу зсередини модуля.

Наприклад, foo.barале ніbar

from foo import bar:

Імпортує fooта створює посилання на всіх перерахованих членів ( bar). Не встановлює змінну foo.

Наприклад , barале не bazабоfoo.baz

from foo import *:

Імпортує fooта створює посилання на всі загальнодоступні об'єкти, визначені цим модулем, у поточному просторі імен (все, що перераховано у, __all__якщо __all__існує, інакше все, що не починається з _). Не встановлює змінну foo.

Наприклад , barі , bazале не _quxабо foo._qux.


Тепер давайте подивимось, коли ми зробимо import X.Y:

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

Перевірте sys.modulesім’я osта 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'>

Перевірте globals()і locals()продиктуйте дикти за допомогою osта 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'
>>>

З наведеного вище прикладу ми з’ясували, що лише osвін вставляється в локальний та глобальний простір імен. Отже, ми повинні мати можливість використовувати:

 >>> 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'>
 >>>

Але ні path.

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

Після видалення osз простору імен locals () ви не зможете отримати доступ до них os, а також os.pathвони існують у sys.modules:

>>> 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
>>>

Тепер поговоримо про import from:

from:

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

Перевірте sys.modulesз osі 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'>

Ми виявили, що sys.modulesми знайшли те саме, що і раніше, використовуючиimport name

Гаразд, давайте перевіримо, як це виглядає в дикті locals()та globals()просторі імен:

>>> 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'
>>>

Ви можете отримати доступ, використовуючи ім'я, а pathне 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
>>>

Видалимо "шлях" з locals():

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

Один заключний приклад використання псевдоніма:

>>> 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'>
>>>

І жоден шлях не визначений:

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

8
Хоча це багатослівно, це справді найкраща відповідь у списку на досить складне питання. Він надає фактичний код, який допомагає пояснити тонкощі "під капотом", які важливіші за стиль, для цього конкретного питання. Я б хотів, щоб я міг підкреслити це не раз!
Майк Вільямсон,

Чи використовує as SYMBOLзміна, як ця відповідь взагалі працює?
Максиміліан Бурслі

40

Обидва способи підтримуються з причини: бувають випадки, коли один є більш доцільним, ніж інший.

  • import module: приємно, коли ви використовуєте багато бітів з модуля. недолік полягає в тому, що вам потрібно буде кваліфікувати кожну посилання з назвою модуля.

  • from module import ...: приємно, що імпортовані елементи можна використовувати безпосередньо без префіксу назви модуля. Недолік полягає в тому, що ви повинні перелічити кожну з речей, які ви використовуєте, і що в коді не зрозуміло, звідки щось взялося.

Що використовувати, залежить від того, який робить код чітким і читабельним і має більше ніж мало спільного з особистими уподобаннями. Я схиляюся до import moduleзагального, тому що в коді дуже ясно, звідки взявся об’єкт чи функція. Я використовую, from module import ...коли в коді багато використовую якийсь об'єкт / функцію .


1
Чи є спосіб використати from M import Xта все ж отримати вигоду від того, щоб якось використовувати класифікатори? Здається, ви могли б отримати найкраще з обох світів, якби все-таки змогли зробити це M.Xпісля імпорту.
членистоногий

@artgropod: Щось. Можна зробити class m: from something.too.long import x, y, z. Не дуже рекомендував би це.
Лі Лі Раян

35

Я особисто завжди користуюся

from package.subpackage.subsubpackage import module

а потім отримати доступ до всього як

module.function
module.modulevar

Причина полягає в тому, що в той же час у вас є коротке виклик, і ви чітко визначаєте простір імен модулів кожної програми, що дуже корисно, якщо вам доведеться шукати використання даного модуля у своєму джерелі.

Потрібно сказати, що не використовуйте імпорт *, оскільки він забруднює ваше простір імен, і він не говорить вам, звідки походить дана функція (з якого модуля)

Звичайно, ви можете зіткнутися з проблемою, якщо у вас є однакова назва модуля для двох різних модулів у двох різних пакетах, наприклад

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

У цьому випадку ви, звичайно, стикаєтеся з неприємностями, але тоді є сильний натяк на те, що макет вашого пакета є помилковим, і вам доведеться переосмислити його.


10
В останньому випадку ви завжди можете використовувати: import pkgN.sub.module як modN, даючи вам виразні імена для кожного модуля. Ви також можете використовувати шаблон "імпортувати ім'я модуля як mod1" для скорочення довгого імені або для переключення між реалізаціями одного і того ж API (наприклад, модулів DB API) з однією зміною імені.
Джефф Шеннон

15
import module

Найкраще, коли ви будете використовувати багато функцій з модуля.

from module import function

Найкраще, коли ви хочете уникати забруднення глобального простору імен усіма функціями та типами з модуля, коли вам це потрібно function.


7
Безумовно, єдине, що у глобальному просторі імен, якщо ви робите "імпортний модуль", це "модуль"? Ви забруднюєте простору імен лише у випадку, якщо ви робите "з .. import *".
Джон Фухі

10

Я щойно відкрив ще одну тонку різницю між цими двома методами.

Якщо модуль fooвикористовує такий імпорт:

from itertools import count

Тоді модуль barможе помилково використовувати так, countяк би він був визначений у foo, а не в itertools:

import foo
foo.count()

Якщо fooвикористовується:

import itertools

помилка все ще можлива, але менша ймовірність буде допущена. barпотрібно:

import foo
foo.itertools.count()

Це викликало у мене певні неприємності. У мене був модуль, який помилково імпортував виняток з модуля, який не визначав його, а лише імпортував його з іншого модуля (використовуючи from module import SomeException). Коли імпорт більше не був потрібний та видалений, модуль-порушення порушено.


10

Ось ще одна відмінність не згадується. Це скопійовано дослівно з http://docs.python.org/2/tutorial/modules.html

Зверніть увагу, що при використанні

from package import item

елемент може бути або підмодулем (або субпакетом) пакету, або якоюсь іншою назвою, визначеною в пакеті, як функція, клас або змінна. Імпорт імпорту спочатку перевіряє, чи визначений товар у пакеті; якщо ні, то передбачається, що це модуль і намагається його завантажити. Якщо його не вдалося знайти, виникає виняток ImportError.

Навпаки, при використанні синтаксису типу

import item.subitem.subsubitem

кожен предмет, крім останнього, повинен бути пакетом; останній елемент може бути модулем або пакетом, але не може бути класом або функцією або змінною, визначеною в попередньому елементі.


Ще одна річ, яку я помітив, це те, що якщо елемент також є підмодулем всередині пакету, тоді "з елемента імпорту пакета" працює, але "імпорт пакета" package.item.subitem = ... не працює з порожнім init .py пакетом, якщо ми не мати "імпорт елемента" у файлі init пакета.
Амітоз Дандіана

6

Оскільки я також початківець, я намагаюся пояснити це простим способом: У Python у нас є три типи importтверджень, які є:

1. Загальний імпорт:

import math

цей тип імпорту - мій особистий фаворит, єдиний недолік цього методу імпорту - це те, що якщо вам потрібна функція будь-якого модуля, ви повинні використовувати такий синтаксис:

math.sqrt(4)

Звичайно, це збільшує зусилля набору тексту, але, як початківець, це допоможе вам відслідковувати пов'язані з ним модулі та функції (хороший редактор тексту значно зменшить зусилля набору тексту і рекомендується).

Намагання введення тексту можна додатково зменшити, використовуючи цю заяву про імпорт:

import math as m

тепер замість використання math.sqrt()ви можете використовувати m.sqrt().

2. Функція імпорту:

from math import sqrt

цей тип імпорту найкраще підходить, якщо ваш код потребує лише доступу до однієї або кількох функцій з модуля, але для використання будь-якого нового елемента з модуля вам потрібно оновити оператор імпорту.

3. Універсальний імпорт:

from math import * 

Хоча це значно зменшує зусилля набору тексту, але не рекомендується, оскільки він заповнить ваш код різними функціями модуля, а їх ім'я може суперечити імені визначених користувачем функцій. приклад:

Якщо у вас є функція власного імені sqrt і ви імпортуєте математику, ваша функція безпечна: є ваш sqrt і є math.sqrt. Якщо ви робите з імпорту математики *, то у вас є проблема: а саме дві різні функції з точно такою ж назвою. Джерело: Codecademy


5
import package
import module

З import, маркер повинен бути модулем (файл, що містить команди Python) або пакет (папка, що sys.pathмістить файл __init__.py.)

Коли є підпакети:

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

вимоги до папки (пакета) або файлу (модуля) однакові, але папка або файл повинні бути всередині, package2які повинні бути всередині package1, і обидва, package1і package2повинні містити __init__.pyфайли. https://docs.python.org/2/tutorial/modules.html

Зі fromстилем імпорту:

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

пакет або модуль входить у область імен файлу, що містить importоператор як module(або package) замість package1.package2.module. Ви завжди можете прив’язати до більш зручного імені:

a = big_package_name.subpackage.even_longer_subpackage_name.function

Тільки fromстиль імпорту дозволяє називати певну функцію чи змінну:

from package3.module import some_function

дозволено, але

import package3.module.some_function 

не дозволяється.


4

Щоб додати те, про що люди говорили from x import *: окрім того, що ускладнюється розповідати, звідки взялися імена, це відкидає перевіряючі коди, як Pylint. Вони повідомлять про ці імена як невизначені змінні.


3

Моя власна відповідь на це здебільшого залежить від того, скільки різних модулів я буду використовувати. Якщо я збираюся використовувати лише один або два, я часто буду використовувати from... importоскільки це робить меншу кількість натискань клавіш в решті файлу, але якщо я збираюся використовувати багато різних модулів, я віддаю перевагу просто importоскільки це означає, що кожна посилання на модуль - це самодокументування. Я бачу, звідки береться кожен символ, без того, щоб полювати.

Зазвичай я віддаю перевагу стилю самодокументування звичайного імпорту та змінююсь лише на .. імпортувати, коли кількість разів мені потрібно набрати ім'я модуля зростає від 10 до 20, навіть якщо імпортується лише один модуль.


1

Однією з суттєвих відмінностей, про які я з'ясував, про які дивно ніхто не говорив, є те, що за допомогою простого імпорту ви можете отримати доступ private variableі private functionsдо імпортного модуля, що неможливо з оператором from-import .

введіть тут опис зображення

Код у зображенні:

setu.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

Імпортний модуль - Вам не потрібні додаткові зусилля для отримання іншої речі з модуля. Він має такі недоліки, як надлишковий набір тексту

Імпорт модуля з - Менше введення та більше контролю над тим, до яких елементів модуля можна отримати доступ. Щоб використовувати новий елемент з модуля, вам потрібно оновити заяву про імпорт.


0

Є кілька вбудованих модулів, які містять в основному голові функції ( base64 , math , os , shutil , sys , time , ...), і це, безумовно, хороша практика, щоб ці головні функції були пов'язані з деяким простором імен і таким чином покращили читабельність вашого код. Поміркуйте, як складніше зрозуміти значення цих функцій без їх простору імен:

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

ніж коли вони прив'язані до якогось модуля:

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

Іноді навіть потрібен простір імен, щоб уникнути конфліктів між різними модулями ( json.load vs. pickle.load )


З іншого боку , є деякі модулі , які містять в основному класи ( ConfigParser , дату і час , тимчасові файли , ZipFile , ...) , і багато хто з них роблять їх імена класів за себе досить:

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

тож може бути дискусія, чи додавання цих класів з додатковою простором імен модулів у ваш код додає нову інформацію або просто подовжує код.


0

Я хотів би додати до цього, є щось, що слід врахувати під час імпортних дзвінків:

У мене така структура:

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 показує різницю:

  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)

Зрештою вони виглядають однаково (результат STORE_NAME є результатом у кожному прикладі), але це варто зазначити, якщо вам потрібно врахувати наступні чотири кругові імпорти:

приклад1

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

Це працює

приклад2

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'

Без кісток

приклад3

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

Аналогічне питання ... але явно з x import y не те саме, що імпорт імпорту xy, як y

приклад4

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

Цей також працює


0

Це структура мого поточного каталогу:

.  
└─a  
   └─b  
     └─c
  1. importОператор запам'ятовує всі проміжні імена .
    Ці імена мають бути кваліфіковані:

    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 ...Заява пам'ятає тільки імпортне ім'я .
    Це ім'я не повинно кваліфікуватися:

    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)>

  • Примітка. Звичайно, я перезапустив консоль Python між кроками 1 і 2.

0

Як зазначає Ян Вробель , одним із аспектів різного імпорту є спосіб розкриття імпорту.

Модульна міма

from math import gcd
...

Використання мімат :

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

Якщо я імпортував gcdлише для внутрішнього використання, а не розголошувати його користувачам mymath, це може бути незручно. У мене це є досить часто, і в більшості випадків я хочу "підтримувати модулі в чистоті".

Окрім пропозиції Яна Вробеля трохи більше приховати це, використовуючи import mathнатомість, я почав приховувати імпорт від розкриття, використовуючи провідне підкреслення:

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

У великих проектах ця "найкраща практика" дозволяє мені точно контролювати те, що розкрито для подальшого імпорту, а що ні. Це забезпечує збереження моїх модулів чистими і окупає певний розмір проекту.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.