Импорт модулей в Python - лучшая практика - PullRequest
56 голосов
/ 29 марта 2012

Я новичок в Python, так как хочу расширить навыки, которые я выучил, используя R. В RI, как правило, загружается куча библиотек, что иногда приводит к конфликтам имен функций.

Что является лучшей практикой в ​​Python.Я видел некоторые конкретные вариации, в которых я не вижу разницы между

import pandas, from pandas import * и from pandas import DataFrame

Каковы различия между первыми двумя и нужно ли мне простоимпортировать то, что мне нужно.Кроме того, каковы могут быть наихудшие последствия для того, кто создает небольшие программы для обработки данных и вычисления простой статистики.

ОБНОВЛЕНИЕ

Я нашел это превосходное руководство .Это все объясняет.

Ответы [ 6 ]

43 голосов
/ 29 марта 2012

import pandas импортирует модуль pandas в пространство имен pandas, поэтому вам нужно будет вызывать объекты в pandas, используя pandas.foo.

from pandas import * импортирует все объекты из модуля панд в ваше текущее пространство имен, поэтому вы должны вызывать объекты внутри панд, используя только foo. Имейте в виду, что это может иметь непредвиденные последствия, если между вашим текущим пространством имен и пространством имен pandas будут какие-либо конфликты имен.

from pandas import DataFrame - это то же самое, что и выше, но только DataFrame (вместо всего) импортируется в ваше текущее пространство имен.

По моему мнению, первый, как правило, является наилучшей практикой, поскольку он позволяет разделить различные модули в вашем коде.

28 голосов
/ 22 марта 2015

Недостаток каждой формы

При чтении чужого кода (и эти люди используют очень разные стили импорта), я заметил следующие проблемы с каждым из стилей:

import modulewithaverylongname будет загромождать код далее длинным именем модуля (например, concurrent.futures или django.contrib.auth.backends) и уменьшать читабельность в этих местах.

from module import * дает мненет никакой возможности синтаксически увидеть, что, например, classA и classB происходят из одного модуля и имеют много общего друг с другом.Это делает чтение кода сложным .(То, что имена из такого импорта могут скрывать имена из более раннего импорта, является наименьшей частью этой проблемы.)

from module import classA, classB, functionC, constantD, functionE перегружает мою кратковременную память слишком большим количеством имен, которые ямысленно нужно присвоить module, чтобы связно понять код.

import modulewithaverylongname as mwvln иногда недостаточно мнемоничен для me .

Подходящий компромисс

Основываясь на вышеприведенных наблюдениях, я разработал следующий стиль в своем собственном коде:

import module является предпочтительным стилем, если имя модулякороче как например большинство пакетов в стандартной библиотеке.Это также предпочтительный стиль, если мне нужно использовать имена из модуля только в двух или трех местах в моем собственном модуле;тогда ясность важнее краткости ( «Читаемость имеет значение» ).

import longername as ln - предпочтительный стиль почти во всех других случаях.Например, я мог бы import django.contrib.auth.backends as dj_abe.По приведенному выше определению критерия 1 аббревиатура будет использоваться часто, и поэтому ее достаточно легко запомнить.

Только эти два стиля являются полностью питоническими согласно «Явное лучше, чем неявное." rule.

from module import xx все еще иногда встречается в моем коде.Я использую его в случаях, когда даже формат as выглядит преувеличенным, самый известный пример - from datetime import datetime.

23 голосов
/ 29 марта 2012

В общем, лучше сделать явный импорт.Как в:

import pandas
frame = pandas.DataFrame()

Или:

from pandas import DataFrame
frame = DataFrame()

Другой вариант в Python, когда у вас есть конфликтующие имена, это импорт x как y:

from pandas import DataFrame as PDataFrame
from bears import DataFrame as BDataFrame
frame1 = PDataFrame()
frame2 = BDataFrame()
14 голосов
/ 16 июня 2016

Вот некоторые рекомендации из Руководства по стилю PEP8.

  1. Импорт обычно должен быть в отдельных строках , например:

    Yes: import os
         import sys
    
    No:  import sys, os
    

    но это нормально

    from subprocess import Popen, PIPE
    
  2. Импорт всегда помещается вверху файла, сразу после любых комментариев и строк документации, а также перед модулемглобальные переменные и константы.

    • Импорт должен быть сгруппирован в следующем порядке:
      1. импорт стандартных библиотек
      2. импорт сторонних производителей
      3. локальный импорт приложений / библиотек
    • Между каждой группой импорта следует ставить пустую строку.
  3. Рекомендуется абсолютный импорт
    Они более читабельны и облегчают отладку, предоставляя лучшие сообщения об ошибках в случае сбоя в системе импорта.

    import mypkg.sibling
    from mypkg import sibling
    from mypkg.sibling import example
    

    или явный относительный импорт

    from . import sibling
    from .sibling import example
    
  4. Неявный относительный импорт никогда не должениспользовать и удаляется в Python 3.

    No:  from ..grand_parent_package import uncle_package
    
  5. Следует избегать импорта подстановочных знаков (from <module> import *) , поскольку из-за этого неясно, какиеимена присутствуют в пространстве имен, сбивая с толку как читателей, так и многие автоматизированные инструменты.


Некоторые рекомендации по lazy imports из советы по производительности Python.

Издержки оператора импорта

операторы импорта могут выполняться практически где угодно.Часто полезно размещать их внутри функций, чтобы ограничить их видимость и / или уменьшить начальное время запуска.Хотя интерпретатор Python оптимизирован для того, чтобы не импортировать один и тот же модуль несколько раз, многократное выполнение оператора импорта может серьезно повлиять на производительность в некоторых обстоятельствах.

нижеприведенный сценарий объясняется на странице,

>>> def doit1():
... import string
... string.lower('Python')
...
>>> import string
>>> def doit2():
... string.lower('Python')
...
>>> import timeit
>>> t = timeit.Timer(setup='from __main__ import doit1', stmt='doit1()')
>>> t.timeit()
11.479144930839539
>>> t = timeit.Timer(setup='from __main__ import doit2', stmt='doit2()')
>>> t.timeit()
4.6661689281463623
9 голосов
/ 03 апреля 2013
from A import B

по существу равняется следующим трем утверждениям

import A
B = A.B
del A

Вот и все.

2 голосов
/ 29 марта 2012

Они все подходят в разных контекстах (вот почему они все доступны). Там нет глубокого руководящего принципа, кроме общих заявлений материнства о ясности, ремонтопригодности и простоте. Некоторые примеры из моего собственного кода:

  1. import sys, os, re, itertools позволяет избежать коллизий имен и предоставляет очень лаконичный способ импорта нескольких стандартных модулей.
  2. from math import * позволяет мне писать sin(x) вместо math.sin(x) в математическом коде. Это становится немного рискованно, когда я также импортирую numpy, что удваивает некоторые из них, но это не слишком беспокоит меня, так как они, как правило, одинаковые функции. Кроме того, я склонен следовать нудистой документации - import numpy as np - которая полностью обходит проблему.
  3. Я предпочитаю from PIL import Image, ImageDraw только потому, что именно так документация PIL представляет свои примеры.
...