Является ли "импорт модуля" лучшим стилем кодирования, чем "из функции импорта модуля"?



пусть from module import function можно назвать стиль кодирования FMIF.



пусть import module называется стилем кодирования IM.



пусть from package import module называется стилем кодирования FPIM.



почему IM + FPIM считается лучшим стилем кодирования, чем FMIF? (См. этот пост для вдохновения для этого вопроса.)



вот некоторые критерии, которые заставляют меня предпочесть FMIF над IM:



  1. краткость кода: это позволяет мне использовать более короткие имена функций и таким образом помогите придерживаться соглашения 80 столбцов на строку.

  2. читаемость: chisquare(...) выглядит более читаемым, чем scipy.stats.stats.chisquare(...). Хотя это субъективный критерий, я думаю, что большинство людей согласятся.

  3. простота перенаправления: если я использую FMIF и по какой-то причине позже хочу перенаправить python для определения function С alt_module вместо module мне нужно изменить только одну строку: from alt_module import function. Если бы я использовал IM, мне нужно было бы изменить много строк кода.


Я поймите, что FPIM каким-то образом сводит к нулю первые две проблемы, но как насчет третьего?

меня интересуют все причины, почему IM + FPIM может быть лучше, чем FMIF,
но в частности, я был бы заинтересован в разработке следующих пунктов, упомянутых здесь:



плюсы для IM:



  1. легкость издеваться / впрыскивать в тестах. (Я не очень хорошо знаком с насмешками, хотя недавно узнал, что означает этот термин. Можете ли вы показать код, который демонстрирует, как им лучше FMIF здесь?)

  2. возможность гибкого изменения модуля путем переопределения некоторых записей. (Я, должно быть, что-то недопонимаю, потому что это, похоже, преимущество FMIF над IM. См. мою третью причину в пользу FMIF выше.)

  3. предсказуемое и контролируемое поведение при сериализации и восстановлении ваших данных. (Я действительно не понимаю, как выбор IM или FMIF влияет на эту проблему. Пожалуйста, уточните.)


  4. я понимаю, что FMIF "загрязняет мой пространство имен", но помимо того, что это отрицательно звучащая фраза, Я не понимаю, как это вредит коду каким-либо конкретным образом.


ПС. При написании этого вопроса я получил предупреждение о том, что вопрос кажется субъективным и, скорее всего, будет закрыт. Пожалуйста, не закрывай его. Я не ищу субъективного мнения, а скорее конкретных ситуаций кодирования, где IM+FPIM явно лучше, чем FMIF.

большое спасибо.

410   5  

5 ответов:

негативы, которые вы перечисляете для IM / FPIM, часто могут быть улучшены соответствующим использованием as предложения. from some.package import mymodulewithalongname as mymod можно бы сократить код и повысить его читаемость, и при переименовании mymodulewithalongname до somethingcompletelydifferent завтра as предложение может быть использовано в качестве одного оператора для редактирования.

рассмотрим вашу точку pro-FMIF 3 (назовите ее R для перенаправления) против вашей точки pro-FPIM 2 (назовите ее F для гибкости): R означает облегчение потери целостности границ модуля, в то время как F укрепляет его. Множество функций, классов и переменных в модуле часто предназначены для совместной работы: они не должны быть независимо переключены на разные значения. Например, рассмотрим модуль random и его функции seed и uniform: если бы вы переключили импорт только одного из них в другой модуль, то вы бы разорвали нормальное соединение между вызовами seed и результаты звонков в uniform. Когда модуль был спроектирован с согласия и целостности, R облегчение разрушения границ модуля на самом деле является отрицательным-это облегчает выполнение чего-то, что вам лучше не делаешь.

наоборот, F-это то, что позволяет скоординированных переключение связанных функций, классов и переменных (так, как правило, сущностей, которые принадлежат вместе, модульность). Например, чтобы сделать тестирование повторяемым (FPIM pro-point 1), Вы издеваетесь над обоими seed и random на random модуль, и если ваш код следует за FPIM, вы все настроены, координация гарантирована; но если у вас есть код, который импортировал функции напрямую, вам нужно выследить каждый такой модуль и повторять насмешку снова и снова. Чтобы сделать тесты идеально повторяемыми, как правило, также требуется "скоординированное издевательство" над функциями даты и времени-если вы используете from datetime import datetime в некоторых модулях, вам нужно найти и издеваться над ними все (а также все те, кто делает from time import time и так далее), чтобы убедиться, что все время, полученное, когда различные части системы спрашивают: "Так сколько сейчас времени?"совершенно последовательны (Если вы используете FPIM, вы просто издеваетесь над двумя соответствующими модулями).

мне нравится FPIM, потому что там действительно не так много добавленной стоимости с помощью умножение квалифицированное имя, а не однократное (в то время как разница между barenames и квалифицированными именами огромный - вы так гораздо больше контроля с определенным именем, будь то поодиночке или умножить, чем вы, возможно, когда-либо сможете с barename!).

Ну, не могу посвятить весь рабочий день, чтобы ответить на каждый из ваших пунктов - ваш вопрос, вероятно, должен быть полдюжины вопросов;-). Я надеюсь, что это по крайней мере решает "почему F лучше, чем R" и некоторые из насмешливых/тестовых вопросов-это сводится к сохранение и повышение хорошо продуманной модульности (через F) вместо того, чтобы подрывать его (через R).

классический текст об этом, как это часто бывает, от Фредрика Лунда, эффбота. Его совет:всегда используйте import - кроме случаев, когда вы не должны.

другими словами, будьте благоразумны. Лично я считаю, что все, что несколько модулей глубоко, как правило, импортируется через from x.y.z import a - основным примером являются модели Django. Но как и все остальное, это вопрос стиля, и вы должны иметь последовательный - особенно с модулями, такими как datetime, где и модуль и класс, который он содержит, называется то же самое. Вам нужно написать datetime.datetime.now() или просто datetime.now()? (В моем коде всегда первое.)

пункты 1 и 2 в вашем списке вопросов, кажется, та же проблема. Динамическая природа Python означает, что довольно просто заменить элемент в пространстве имен модуля независимо от того, какой из методов вы используете. Трудность возникает, если одна функция в модуле ссылается на другую, которую вы хотите высмеять. В этом случае импортируйте модуль, а не функции означает, что вы можете сделать module.function_to_replace = myreplacementfunc и все работает прозрачно - но это так же легко сделать через FPIM, как и через IM.

Я также не понимаю, как пункт 3 имеет какое-либо отношение к чему-либо. Я думаю, что Ваш пункт 4, однако основан на небольшое недоразумение. Ни один из методов, которые вы даете, не будет "загрязнять ваше пространство имен". Что тут это from module import *, где вы понятия не имеете, что вы импортируете, и поэтому функции могут появляться в вашем коде без каких-либо подсказка дана читателю откуда они взялись. Это ужасно, и его следует избегать любой ценой.

как Алекс Мартелли, я люблю использовать as при импорте функции.

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

from random import seed as r_seed
from random import random as r_random

r_seed короче, чем random.seed но несколько сохраняет границы модуля. Кто-то случайно глядя на ваш код может видеть r_seed() и r_random() и есть шанс понять, что они связаны.

конечно, вы всегда можете просто делать:

import random as r

и затем использовать r.random() и r.seed(), что может быть идеальным компромиссом для этого случая. Я использую трюк с префиксом только при импорте одной или двух функций из модуля. Когда я хочу использовать много функций из одного модуля, я импортирую модуль, возможно, с as чтобы сократить название.

отличные ответы здесь (я их всех поддержал), и вот мои мысли по этому поводу:

во-первых, обращаясь к каждой из ваших пуль:

(предположительно) плюсы FMIF:

  • краткость кода: более короткие имена функций помогают придерживаться 80 столбцов в строке.

возможно, но имена модулей обычно достаточно короткие, поэтому это не актуально. Конечно, есть datetime, но и os, re,sys и т. д. И Python имеет свободные разрывы строк внутри { [ (. А для вложенных модулей всегда есть as как в IM, так и в FPIM

  • читаемость: chisquare(...) выглядит более читаемым, чем составляющей.статистика.статистика.chisquare(...).

категорически не согласен. При чтении иностранного кода (или моего собственного кода через несколько месяцев) трудно понять, откуда берется каждая функция. Квалифицированные имена спасают меня от перехода туда и обратно из строки 2345 в заголовок объявления модуля. И это также дает вам контекст:"chisquare? Что это такое? О, это от scypy? Хорошо, некоторые математические вещи, то". И, еще раз, вы всегда можете сократить scipy.stats.stats as scypyst. scypyst.chisquare(...) достаточно короткий со всеми преимуществами квалифицированного имени.

import os.path as osp еще один хороший пример, учитывая, что очень часто цепочка 3 или более его функций вместе в одном вызове: join (expanduser (), basename (splitext())) так далее.

  • простота перенаправления: однострочное переопределение функции из altmodule вместо модуля.

как часто вы хотите переопределить одну функцию, а не весь модуль? Границы модуля и координация функций должны быть сохранены, и Алекс уже объяснил это очень подробно. Для большинства (всех?) реальные сценарии, если alt_module.x является жизнеспособной заменой для module.x, тогда наверное alt_module сам по себе является каплей Альтернатива для module, так как им и ФПИМ один-вкладыши FMIF как, если вы используете as.

  • я понимаю, что FPIM каким-то образом сводит на нет первые две проблемы...

на самом деле as это тот, который смягчает первые 2 проблемы (и 3-й), а не FPIM. Вы можете использовать IM для этого тоже:import some.long.package.path.x as x для того же результата, что и FPIM.


таким образом, ни один из вышеперечисленных не является настоящим плюсом FMIF. И причины Я предпочитаю IM / FPIM являются:

для простоты и согласованности, когда я импортирую что-то, либо IM, либо FPIM, я всегда импортирую модуль, а не объект из модуля. Помните, что FMIF можно (ab-)использовать для импорта функций, классов, переменных или даже других модулей! Подумайте о беспорядке from somemodule import sys, somevar, os, SomeClass, datetime, someFunc.

кроме того, если вы хотите больше, чем один объект из модуля, FMIF будет загрязнять ваше пространство имен больше, чем IM или FPIM, который будет использовать одно имя независимо от того, сколько объектов вы хотите использовать. И такие объекты будут иметь квалификации имя, которое является pro, а не con: как я уже сказал в выпуске 2, IMHO a it улучшает читабельности.

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

Я согласен с MestreLion больше всего здесь (и так upvote).

МОЯ перспектива: я часто просматриваю код, с которым я незнаком, и не знаю, какой модуль функция исходит от простого просмотра функции, довольно неприятно.

код пишется один раз и читается много раз, и поэтому читаемость и ремонтопригодность превосходит простоту ввода.

в аналогичном ключе, как правило, код не пишется в интересах кодер, но в интересах другой сущности.

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

импорт полного пути также может лучше помочь IDE указать вам на правильный источник функции или объекта, на который вы смотрите.

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

Comments

    Ничего не найдено.