Программный модуль это: Мегаэнциклопедия Кирилла и Мефодия

Содержание

Основные характеристики программного модуля. — Студопедия

РАЗРАБОТКА СТРУКТУРЫ ПРОГРАММЫ И МОДУЛЬНОЕ ПРОГРАММИРОВАНИЕ

Цель модульного программирования.

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

 

Модуль характеризуют:

1. один вход и один выход — на входе программный модуль получает определенный набор исходных данных, выполняет содержательную обработку и возвращает один набор результатных данных, т.е. реализуется стандартный принцип IPO (Input — Process — Output) — вход-процесс-выход;

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

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

4. слабые информационные связи с другими программными модулями — обмен информацией между модулями должен быть по возможности минимизирован;

5. обозримый по размеру и сложности программный элемент.

 

Таким образом, модули содержат определение доступных для обработки данных, операции обработки данных, схемы взаимосвязи с другими модулями.

Каждый модуль состоит из спецификации и тела. Спецификации определяют правила использования модуля, а тело — способ реализации процесса обработки.

 

Приступая к разработке каждой программы ПС, следует иметь ввиду, что она, как правило, является большой системой, поэтому мы должны принять меры для ее упрощения. Для этого такую программу разрабатывают по частям, которые называются программными модулями. А сам такой метод разработки программ называют модульным программированием.

 

Программный модуль — это любой фрагмент описания процесса, оформляемый как самостоятельный программный продукт, пригодный для использования в описаниях процесса. Это означает, что каждый программный модуль программируется, компилируется и отлаживается отдельно от других модулей программы, и тем самым, физически разделен с другими модулями программы. Более того, каждый разработанный программный модуль может включаться в состав разных программ, если выполнены условия его использования, декларированные в документации по этому модулю. Таким образом, программный модуль может рассматриваться и как средство борьбы со сложностью программ, и как средство борьбы с дублированием в программировании (т.е. как средство накопления и многократного использования программистских знаний).

 

Модульное программирование является воплощением в процессе разработки программ обоих общих методов борьбы со сложностью и обеспечение независимости компонент системы, и использование иерархических структур. Для воплощения первого метода формулируются определенные требования, которым должен удовлетворять программный модуль, т.е. выявляются основные характеристики «хорошего» программного модуля. Для воплощения второго метода используют древовидные модульные структуры программ (включая деревья со сросшимися ветвями).

 

Основные характеристики программного модуля.

Не всякий программный модуль способствует упрощению программы. Выделить хороший с этой точки зрения модуль является серьезной творческой задачей. Для оценки приемлемости выделенного модуля используются некоторые критерии. Так, Хольт предложил следующие два общих таких критерия:

· хороший модуль снаружи проще, чем внутри;

· хороший модуль проще использовать, чем построить.

 

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

 

Размер модуля измеряется числом содержащихся в нем операторов (строк). Модуль не должен быть слишком маленьким или слишком большим. Маленькие модули приводят к громоздкой модульной структуре программы и могут не окупать накладных расходов, связанных с их оформлением. Большие модули неудобны для изучения и изменений, они могут существенно увеличить суммарное время повторных трансляций программы при отладке программы. Обычно рекомендуются программные модули размером от нескольких десятков до нескольких сотен операторов.

Прочность модуля — это мера его внутренних связей. Чем выше прочность модуля, тем больше связей он может спрятать от внешней по отношению к нему части программы и, следовательно, тем больший вклад в упрощение программы он может внести. Для оценки степени прочности модуля Майерс предлагает упорядоченный по степени прочности набор из семи классов модулей. Самой слабой степенью прочности обладает модуль, прочный по совпадению. Это такой модуль, между элементами которого нет осмысленных связей. Такой модуль может быть выделен, например, при обнаружении в разных местах программы повторения одной и той же последовательности операторов, которая и оформляется в отдельный модуль. Необходимость изменения этой последовательности в одном из контекстов может привести к изменению этого модуля, что может сделать его использование в других контекстах ошибочным. Такой класс программных модулей не рекомендуется для использования. Вообще говоря, предложенная Майерсом упорядоченность по степени прочности классов модулей не бесспорна. Однако, это не очень существенно, так как только два высших по прочности класса модулей рекомендуются для использования. Эти классы мы и рассмотрим подробнее.

Функционально прочный модуль — это модуль, выполняющий (реализующий) одну какую-либо определенную функцию. При реализации этой функции такой модуль может использовать и другие модули. Такой класс программных модулей рекомендуется для использования.

Информационно прочный модуль — это модуль, выполняющий (реализующий) несколько операций (функций) над одной и той же структурой данных (информационным объектом), которая считается неизвестной вне этого модуля. Для каждой из этих операций в таком модуле имеется свой вход со своей формой обращения к нему. Такой класс следует рассматривать как класс программных модулей с высшей степенью прочности. Информационно-прочный модуль может реализовывать, например, абстрактный тип данных.

В модульных языках программирования как минимум имеются средства для задания функционально прочных модулей (например, модуль типа FUNCTION в языке ФОРТРАН). Средства же для задания информационно прочных модулей в ранних языках программирования отсутствовали — они появились только в более поздних языках. Так в языке программирования Ада средством задания информационно прочного модуля является пакет.

Сцепление модуля — это мера его зависимости по данным от других модулей. Характеризуется способом передачи данных. Чем слабее сцепление модуля с другими модулями, тем сильнее его независимость от других модулей. Для оценки степени сцепления Майерс предлагает упорядоченный набор из шести видов сцепления модулей. Худшим видом сцепления модулей является сцепление по содержимому. Таким является сцепление двух модулей, когда один из них имеет прямые ссылки на содержимое другого модуля (например, на константу, содержащуюся в другом модуле). Такое сцепление модулей недопустимо. Не рекомендуется использовать также сцепление по общей области — это такое сцепление модулей, когда несколько модулей используют одну и ту же область памяти. Такой вид сцепления модулей реализуется, например, при программировании на языке ФОРТРАН с использованием блоков COMMON. Единственным видом сцепления модулей, который рекомендуется для использования современной технологией программирования, является параметрическое сцепление (сцепление по данным по Майерсу) — это случай, когда данные передаются модулю либо при обращении к нему как значения его параметров, либо как результат его обращения к другому модулю для вычисления некоторой функции. Такой вид сцепления модулей реализуется на языках программирования при использовании обращений к процедурам (функциям).

 

Рутинность модуля — это его независимость от предыстории обращений к нему. Модуль будем называть рутинным, если результат (эффект) обращения к нему зависит только от значений его параметров (и не зависит от предыстории обращений к нему). Модуль будем называть зависящим от предыстории, если результат (эффект) обращения к нему зависит от внутреннего состояния этого модуля, храняшего следы предыдущих обращений к нему. Майерс не рекомендует использовать зависящие от предыстории (непредсказуемые) модули, так как они провоцируют появление в программах хитрых (неуловимых) ошибок. Однако такая рекомендация является неконструктивной, так как во многих случаях именно зависящий от предыстории модуль является лучшей реализаций информационно прочного модуля. Поэтому более приемлема следующая (более осторожная) рекомендация:

 

· всегда следует использовать рутинный модуль, если это не приводит к плохим (не рекомендуемым) сцеплениям модулей;

· зависящие от предыстории модули следует использовать только в случае, когда это необходимо для обеспечения параметрического сцепления;

· в спецификации зависящего от предыстории модуля должна быть четко сформулирована эта зависимость таким образом, чтобы было возможно прогнозировать поведение (эффект выполнения) данного модуля при разных последующих обращениях к нему.

В связи с последней рекомендацией может быть полезным определение внешнего представления (ориентированного на информирование человека) состояний зависящего от предыстории модуля. В этом случае эффект выполнения каждой функции (операции), реализуемой этим модулем, следует описывать в терминах этого внешнего представления, что существенно упростит прогнозирование поведения данного модуля.\

 

 

1.3.3. Модульная структура программных продуктов

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

Однотипные функции реализуются одними и теми же модулями. Функция верхнего уровня обеспечивается главным модулем; он управляет выполнением нижестоящих функций, которым соответствуют подчиненные модули.

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

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

2. принятие основных решений в алгоритме выносится на максимально «высокий» по иерархии уровень;

3. для использования одной и той же функции в разных местах алгоритма создается один модуль, который вызывается на выполнение по мере необходимости. В результате дальнейшей детализации алгоритма создается функциональномодульная схема (ФМС) алгоритма приложения, которая является основой для программирования.

Состав и вид программных модулей, их назначение и характер использования в программе в значительной степени определяются инструментальными средствами. Например, применительно к средствам СУБД отдельными модулями могут быть:

1. экранные формы ввода и/или редактирования информации базы данных;

2. отчеты генератора отчетов;

3. макросы;

4. стандартные процедуры обработки информации;

5. меню, обеспечивающее выбор функции обработки и др.

Основной программный модуль — Большая Энциклопедия Нефти и Газа, статья, страница 2

Основной программный модуль

Cтраница 2

Вторым компонентом, который необходим для разработки приложения, является программный код, описывающий реакцию имеющихся на экране объектов и элементов управления на различные события, которые могут происходить в ходе выполнения программы. Реакция на событие описывается в виде соответствующей подпрограммы, входящей в основной программный модуль. Подобно заготовкам для экранных объектов, текстовое окно, содержащее исходный код программы, также имеет заготовки для подпрограмм. В частности, по правилам языка Object Pascal каждая подпрограмма должна иметь заголовок, начинающийся со служебного слова procedure, в начале основной части подпрограммы должно содержаться служебное слово begin, a завершаться она должна служебным словом end, после которого ставится точка с запятой.
 [16]

Следующей вспомогательной функцией является согласование параметров перечней исходных данных и параметров перечней результатов вычислений модулей программной модели по форме представления и единицам измерения с их общесистемным представлением. Формы представления и единицы измерения, используемые в системе в целом, могут отличаться от потребностей отдельных программных модулей. Поэтому перед началом выполнения функций основных программных модулей необходимо осуществить соответствующее согласование.
 [17]

Рассмотрим основные элементы, из которых формируется программная модель. Их состав определяется целью построения программной модели. Основными элементами программной модели являются следующие: основные программные модули, вспомогательные программные модули, основные информационные модули и вспомогательные информационные модули. Общим для всех этих элементов является принадлежность к одной и той же категории — категории модулей. Это означает, что при хранении модуля в различных видах памяти технических средств автоматизации он размещается там как поименованное множество, для обращения к которому достаточно указания его имени. Основные достоинства модульного представления были указаны в гл. Эти достоинства в полной мере сохраняются и для программной модели.
 [18]

На современном этапе развития радиотехники чрезвычайно возросла роль ЭВМ, эффективно выполняющих сложные и трудоемкие вычислительные операции. Здесь в качестве примеров приводятся две реальные подпрограммы на алгоритмическом языке ФОРТРАН, иллюстрирующие применение ЭВМ для расчета характеристик радиотехнических цепей с распределенными параметрами. Все приводимые подпрограммы оформлены как программные единицы типа SUBROUTINE; связь между ними и основным программным модулем осуществляется посредством формальных параметров, что обеспечивает максимальную универсальность использования.
 [19]

В 1976 — 1977 гг. в Институте проблем механики АН СССР был реализован вариант такого комплекса программ на языке Алгол применительно к ЭВМ БЭСМ-4М. Ниже описан последующий вариант комплекса программ на языке Фортран применительно к ЭВМ серии ЕС. К настоящему времени этот вариант КПП в целом и его отдельные части прошли отладку и систематически используются для конкретных расчетов. Данная статья содержит краткое описание функционального наполнения этого комплекса программ: исходную математическую модель, методику численного решения и обработки результатов и сводные характеристики основных программных модулей, составляющих комплекс, а также сложившийся опыт использования комплекса и некоторые конкретные примеры.
 [20]

Типовые модули могут разрабатываться как стандартные. Одновременно улучшаются условия для повышения надежности ( правильности) программной модели. Проверка качества ( работоспособности) каждого модуля может осуществляться автономно, независимо от других модулей. Включение ранее разработанных стандартных модулей, прошедших длительную проверку в других программных моделях, не только повышает надежность, но и сокращает сроки создания программной модели. Основные программные модули реализуют функции, определенные информационной и математической моделями. Между модулями математической модели и основными программными модулями может не быть взаимно-однозначного соответствия. Один модуль математической модели может отображаться несколькими основными программными модулями, и наоборот, один основной программный модуль может поглотить несколько модулей математической модели. Это объясняется тем, что математическая модель, учитывающая возможности технических средств автоматизации управления, тем не менее в значительной степени является машинонезависимым объектом. Она вместе с информационной моделью может отображаться на различные технические средства автоматизации управления.
 [21]

Видимы ли переменные, модуля В основному программному модулю. Напомним, что ничто из модуля невидимо за пределами модуля, если только оно не экспортируется, а переменные В не экспортировались модулем А. Именно поэтому мы говорили об игнорировании модуля В в списке экспорта модуля А. Обратите внимание, что переменные В экспортируются из А путем экспортирования имени модуля В. Это единственный имеющийся метод сделать переменные В доступными для основного программного модуля. Этот последний пример показывает, что, прежде чем объект из модуля нижнего уровня из группы вложенных модулей может стать видимым за пределами этой группы, его необходимо экспортировать через все уровни вложенных модулей.
 [22]

Ни один из модулей этого примера не может видеть никаких переменных, за исключением своих собственных, поскольку не применялись никакие импорты. Исключение составляет модуль А. Модуль А может видеть экспортированные объекты модуля В, поскольку А составляет окружение В. По этой же причине основной программный модуль может видеть все, что экспортируется из модулей А и С.
 [23]

Типовые модули могут разрабатываться как стандартные. Одновременно улучшаются условия для повышения надежности ( правильности) программной модели. Проверка качества ( работоспособности) каждого модуля может осуществляться автономно, независимо от других модулей. Включение ранее разработанных стандартных модулей, прошедших длительную проверку в других программных моделях, не только повышает надежность, но и сокращает сроки создания программной модели. Основные программные модули реализуют функции, определенные информационной и математической моделями. Между модулями математической модели и основными программными модулями может не быть взаимно-однозначного соответствия. Один модуль математической модели может отображаться несколькими основными программными модулями, и наоборот, один основной программный модуль может поглотить несколько модулей математической модели. Это объясняется тем, что математическая модель, учитывающая возможности технических средств автоматизации управления, тем не менее в значительной степени является машинонезависимым объектом. Она вместе с информационной моделью может отображаться на различные технические средства автоматизации управления.
 [24]

Аварийные ситуации могут приводить к длительному выходу из строя всех или только части технических средств автоматизации. Выработку реакции на подобные ситуации ( для устранения их последствий) осуществляют технические средства автоматизации и общесистемное математическое обеспечение. Эти меры носят универсальный характер и распространяются на все программные модели, обслуживаемые этими средствами. Однако не всегда с помощью таких универсальных мер удается полностью устранить последствия аварийных ситуаций. В этих случаях целесообразно привлечь и использовать особенности конкретных программных моделей для выработки реакции на подобные ситуации и устранения их последствий. Эти функции могут исполняться автономными вспомогательными программными модулями. Частично они могут быть реализованы внутри основных программных модулей. Включение таких функций в основные программные модули должно осуществляться системой, которая обеспечивает автоматическое формирование программного модуля.
 [25]

Типовые модули могут разрабатываться как стандартные. Одновременно улучшаются условия для повышения надежности ( правильности) программной модели. Проверка качества ( работоспособности) каждого модуля может осуществляться автономно, независимо от других модулей. Включение ранее разработанных стандартных модулей, прошедших длительную проверку в других программных моделях, не только повышает надежность, но и сокращает сроки создания программной модели. Основные программные модули реализуют функции, определенные информационной и математической моделями. Между модулями математической модели и основными программными модулями может не быть взаимно-однозначного соответствия. Один модуль математической модели может отображаться несколькими основными программными модулями, и наоборот, один основной программный модуль может поглотить несколько модулей математической модели. Это объясняется тем, что математическая модель, учитывающая возможности технических средств автоматизации управления, тем не менее в значительной степени является машинонезависимым объектом. Она вместе с информационной моделью может отображаться на различные технические средства автоматизации управления.
 [26]

Типовые модули могут разрабатываться как стандартные. Одновременно улучшаются условия для повышения надежности ( правильности) программной модели. Проверка качества ( работоспособности) каждого модуля может осуществляться автономно, независимо от других модулей. Включение ранее разработанных стандартных модулей, прошедших длительную проверку в других программных моделях, не только повышает надежность, но и сокращает сроки создания программной модели. Основные программные модули реализуют функции, определенные информационной и математической моделями. Между модулями математической модели и основными программными модулями может не быть взаимно-однозначного соответствия. Один модуль математической модели может отображаться несколькими основными программными модулями, и наоборот, один основной программный модуль может поглотить несколько модулей математической модели. Это объясняется тем, что математическая модель, учитывающая возможности технических средств автоматизации управления, тем не менее в значительной степени является машинонезависимым объектом. Она вместе с информационной моделью может отображаться на различные технические средства автоматизации управления.
 [27]

Аварийные ситуации могут приводить к длительному выходу из строя всех или только части технических средств автоматизации. Выработку реакции на подобные ситуации ( для устранения их последствий) осуществляют технические средства автоматизации и общесистемное математическое обеспечение. Эти меры носят универсальный характер и распространяются на все программные модели, обслуживаемые этими средствами. Однако не всегда с помощью таких универсальных мер удается полностью устранить последствия аварийных ситуаций. В этих случаях целесообразно привлечь и использовать особенности конкретных программных моделей для выработки реакции на подобные ситуации и устранения их последствий. Эти функции могут исполняться автономными вспомогательными программными модулями. Частично они могут быть реализованы внутри основных программных модулей. Включение таких функций в основные программные модули должно осуществляться системой, которая обеспечивает автоматическое формирование программного модуля.
 [28]

Это относится в первую очередь к определению объема и состава каждого программного модуля. Математическая модель оставляет определенную свободу при размещении ее функций в основных программных модулях. Объем и состав вспомогательных программных модулей полностью определяется на этапе построения программной модели. Эта свобода должна использоваться для минимизации затрат времени на вспомогательные работы. Например, если модули программной модели хранятся во внешней памяти и для исполнения вызываются в оперативную, то затраты времени на обмен между внешней памятью и оперативной относятся к непроизводительным. Для их сокращения необходимо минимизировать число обращений за пределы каждого программного модуля. Это достигается как соответствующим размещением выполняемых функций по модулям, так и увеличением объема каждого модуля до максимально допустимых размеров. Аналогично необходимо размещать параметры в информационных модулях, стремясь к минимизации числа вызовов этих модулей из внешней памяти в оперативную. Математическая модель разрабатывается с применением алгоритмических языков. Таким образом, при разработке программной модели используются модули математической модели, описанные на алгоритмических языках. Если между модулями математической модели и основными программными модулями удается установить взаимно-однозначное соответствие, то программы этих модулей получаются автоматически путем трансляции, осуществляемой вычислительными машинами. Если такого соответствия нет, то построение программ также может быть автоматизировано с помощью специальных систем комплексирования. В этом случае неавтоматизированным остается процесс составления параметрического описания задания на комплексиро-вание.
 [29]

Гораздо больших усилий требует разработка правил оформления и связи модулей, типовых управляющих конструкций. Разнообразие вариантов здесь достаточно велико, а эффективность применения каждого из них меняется в зависимости от конкретной ситуации. Целевая установка на поиск оптимального варианта программы не позволяет ограничивать средства языка, рекомендованные к применению. Но и в этом случае может быть найдено компромиссное решение, облегчающее разработку. Основано оно на том, что различные части программы оказывают существенно разное влияние на время ее работы. Если программа хорошо структурирована, то такая работа не вызовет трудностей. При таком подходе на первом этапе разработки могут быть применены макрокоманды, реализующие оформление модулей, типовые управляющие конструкции, описание данных. По своим функциям, а часто и форме, такие макрокоманды напоминают соответствующие конструкции языков высокого уровня. Ассемблер, дополненный набором упомянутых макрокоманд, обычно называют структурным. При переработке программного текста макрокоманды могут быть заменены более эффективными для конкретной ситуации последовательностями команд. При разработке или выборе набора макрокоманд важно только помнить, что цель состоит в упрощении процесса разработки и поэтому разнообразие макрокоманд должно быть невелико. Кроме написания текста основной программы, для ее реализации на ЭВМ необходимо написать текст управляющего задания. Задания необходимо подготавливать и для выполнения вспомогательных программ, обеспечивающих процесс разработки. С точки зрения технологии программирования управляющее задание представляет собой модуль самого верхнего уровня, выполняющий специфический набор функций. Как и все остальные модули, он должен быть тщательно спроектирован. Проект его может быть выполнен на языке текстового описания. Но если при проектировании основных программных модулей мы могли отвлечься от особенностей средств их будущей реализации, то в данном случае проект должен быть ориентирован на возможности и особенности языка управления заданиями.
 [30]

Страницы:  

   1

   2




Разработка программных модулей программного обеспечения

В ответ на усложнение и многочисленность задач, которые сегодня предъявляются к программному обеспечению, усложняется и сама система ПО, но при этом порождается и другая необходимость – упростить процесс создания, развития и модернизации программного обеспечения. Такой подход не только упрощает разработчикам решение своих задач, но и позволяет упростить и удешевить эксплуатацию ПО для пользователей.

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

1. Как составляющая часть процесса разработки ПО. В данном случае разработка модулей, в зависимости от проекта, может вестись последовательно и (или) параллельно, но всегда завершается их объединением в единую систему.

2. В процессе доработки, усовершенствования или модернизации ранее созданного ПО. Модульная конструкция программного обеспечения позволяет вносить изменения в отдельные модули, удалять некоторые из них или дополнять систему новыми модулями. При этом разработка программных модулей программного обеспечения и их внедрение, как и изменение или удаление, не заставляет переделывать всю систему ПО в целом.

В программном комплексе созданные модули могут представлять собой:

  • законченные компоненты;

  • функциональные группы;

  • пакеты программ;

  • единый программный комплекс – законченный программный продукт конкретного целевого назначения.

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

Компания АРТВЕЛЛ использует модульное программирование для различных целей – все зависит от задач и требований заказчика.

Возврат к списку

Программный модуль в 1С — PROGRAM1S.COM

Программный модуль

Программный модуль — это процедуры и функции, написанные на встроенном языке 1С, сгруппированные в единое целое. Платформа 1С вызывает программные модули по мере необходимости.

Экспортная процедура или функция — это такая процедура или функция, которую можно вызывать из других программных модулей. Для этого нужно добавить ключевое слово Экспорт.

Процедура ЭкспортнаяПроц() Экспорт

КонецПроцедуры



Процедура ЭкспортнаяПроц() Экспорт

КонецПроцедуры

Структура модуля

Модуль в 1С состоит из раздела описания переменных, раздела описания процедур и функций и раздела основной программы:

//переменные
Перем Пер1;
Перем Пер2;

//процедуры и функции
Процедура ПростоПроцедура()
КонецПроцедуры

Функция ПростоФункция()
Возврат Истина;
КонецФункции

//основной раздел программы
Пер1 = «программа»;
Пер2 = «1С»;



//переменные

Перем Пер1;

Перем Пер2;

//процедуры и функции

Процедура ПростоПроцедура()

КонецПроцедуры

Функция ПростоФункция()

Возврат Истина;

КонецФункции

//основной раздел программы

Пер1 = «программа»;

Пер2 = «1С»;

Контекст программного модуля

Это связь с другими составляющими конфигурации. Контекст может быть:

  • Глобальный — это методы и свойства глобального контекста, которые доступны в любой части конфигурации, например метод Сообщить, который можно вызвать в любом модуле.
  • Локальный — это объекты, методы и свойства конкретного модуля. Они не доступны в других модулях.

Виды программных модулей


Подписывайтесь на группу ВКонтакте , где я публикую ссылки на новые статьи с данного сайта, а также интересные материалы с других ресурсов по программированию в 1С

Понравилась статья? Поделиться с друзьями:

Терминологии: разница между программным интерфейсом, программное обеспечение, программный комплекс, программный модуль

Я вижу, что эти термины довольно часто используются различными авторами, но, похоже, я не могу остановиться на окончательных определениях.

Из моего POV программный интерфейс-это «type», определяющий способ, которым программный компонент может использоваться другими компонентами softare.

Но что именно представляет собой программный компонент, я не совсем уверен (и, похоже, никто другой тоже). То же самое касается программного блока и программного модуля, хотя я подозреваю, что программный блок-это меньшая, ГМ, единица, чем компонент, и программный модуль имеет какое-то отношение к упаковке.

Я надеюсь, что это не будет сочтено (и отвергнуто) как легкомысленное, поскольку у меня есть серьезные намерения в этом вопросе.

interface

module

components

Поделиться

Источник


JamieH    

29 июля 2009 в 22:52

2 ответа




0

Типично:

  • единица измерения-это файл исходного кода
  • модуль ( пакет UML и Java) — это каталог исходных файлов, вероятно, с собственным скриптом сборки
  • компонент -это вещь во время выполнения или, по крайней мере, во время установки, созданная процессом сборки

Большинство работ по этому вопросу пытаются быть достаточно абстрактными, чтобы вы не могли сказать, какая среда выполнения компонента используется, о каком языке идет речь, поддерживает ли OS ‘files’ и ‘directories’, или действительно собираетесь ли вы написать компьютерную программу или просто нарисовать диаграмму возможного способа взглянуть на часть программного обеспечения, которая, как можно утверждать, не является достаточно неправильной, чтобы ее стоило перерисовывать.

Поделиться


soru    

30 июля 2009 в 00:44



0

Интерфейс просто определяет прототипы. Компонент определяет поведение во время выполнения(т. е. Каким должно быть поведение, независимо от платформы).

Поделиться


Siva Krishna Aleti    

06 марта 2014 в 04:34


Похожие вопросы:

убедитесь, что я работаю со своим программным обеспечением, а не с самозванцем. Windows, Java, аппаратное обеспечение

Можете ли вы придумать механизм, гарантирующий, что мое программное обеспечение (приложение GUI) — это то программное обеспечение, которое я сейчас запускаю, а не самозванец (как черный ящик)? Это…

Как защитить свой программный код?

Возможные Дубликаты : Как вы защищаете свое программное обеспечение от незаконного распространения? Наилучшая практика предотвращения копирования программного обеспечения Гипотетическая ситуация :…

в чем разница между программным стеком и OS ? почему Android — это не OS, а программный стек?

Android-это программный стек, но не OS. как заявил developer.android.com Что такое Android? Android-это программный стек для мобильных устройств, который включает в себя операционную систему,…

Программный способ узнать, подключен ли PC к указанной сети

ОС: Windows, язык: C++ Я реализую этот вариант использования: Когда пользователь запускает мое программное обеспечение, программное обеспечение должно знать, подключен ли его/ее PC в данный момент к…

какое программное обеспечение может просматривать любой разработанный программный код?

Я хотел бы знать программное обеспечение, которое может просматривать код программного обеспечения Microsoft word и любой другой программный код. Чтобы я мог учиться на этом программном коде и на…

Является ли EJB промежуточным программным обеспечением? Или промежуточное программное обеспечение используется в EJB?

Я путаюсь между этими двумя нюансами: Является ли EJB сам по себе промежуточным программным обеспечением, или есть ли какое-либо промежуточное программное обеспечение, используемое в deployment из…

В чем разница между kernel и программным объектом?

Я просмотрел несколько ресурсов: книгу OpenCL Хроноса, учебник GATech, учебник NYU, и я мог бы пройти через большее. Но я все еще не совсем понимаю. В чем разница между kernel и программным…

В чем разница между программным обеспечением и прошивкой?

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

Angular Http модуль считается промежуточным программным обеспечением?

Я пытаюсь полностью понять, что такое промежуточное программное обеспечение, и пришел к некоторому затруднению. Я читаю документы expressJs и его определение функции промежуточного программного…

Программное обеспечение ОС внутри контейнеров Docker?

На Linux я знаю, что все контейнеры docker совместно используют хост-операционную систему Kernel. Насколько я знаю, в OS есть программный уровень выше Kernel, поэтому я думаю, что контейнеры,…

1




1


К оглавлению

   

82. Модульное программирование

Модульность — организация
программы в виде относительно независимых частей -

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

отладку и

тестирование.

Модулем обычно называют совокупность связанных процедур и тех
данных, которыми они управляют

Программный модуль – программа или функционально
завершенный фрагмент программы, предназначенный для: хранения, трансляции,
объединения с другими программными модулями и загрузки в оперативную память.

Различают: стандартные модули, входящие в язык
программирования и пользовательские модули, предназначенные для упрощения
работы программистов.

Модульное программирование – метод разработки
программ, предполагающий разбиение программы на независимые модули.

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

Модули содержат определение доступных для обработки данных,
операции обработки данных, схемы взаимосвязи с другими модулями.

Каждый модуль состоит из спецификации и тела.
Спецификации определяют правила использования модуля, а тело — способ реализации
процесса обработки.

Модульная структура программных продуктов

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

Однотипные функции реализуются одними и теми же модулями.
Функция верхнего уровня обеспечивается главным модулем; он управляет
выполнением нижестоящих функций, которым соответствуют подчиненные
модули.

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

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

2. принятие основных решений в
алгоритме выносится на максимально «высокий» по иерархии уровень;

3. для использования одной и
той же функции в разных местах  алгоритма  создается
один модуль, который вызывается на выполнение по мере необходимости. В
результате дальнейшей детализации алгоритма 
создается функционально-модульная  схема 
(ФМС)  алгоритма  приложения, которая является
основой для программирования.

Состав и вид программных модулей, их назначение и характер
использования в программе в значительной степени определяются инструментальными
средствами. Например, применительно к средствам СУБД отдельными модулями могут
быть:

1. экранные формы ввода и/или
редактирования информации базы данных;

2. отчеты генератора отчетов;

3. макросы;

4. стандартные процедуры
обработки информации;

5. меню, обеспечивающее выбор
функции обработки и др.

В качестве модульной структуры программы принято использовать
древовидную структуру, включая дерево со сросшимися ветвями. В узлах такого
дерева размещаются программные модули, а направленные дуги (стрелки) показывают
статическую подчиненность модулей, т.е. каждая дуга показывает, что в тексте
модуля, из которого она исходит, имеется ссылка на модуль, в который она входит.
Другими словами, каждый модуль может обращаться к подчиненным ему модулям, т.е.
выражается через эти модули. При этом модульная структура программы, в конечном
счете, должна включать и совокупность спецификаций модулей, образующих эту
программу. Спецификация программного модуля содержит,
во-первых, синтаксическую спецификацию его входов, позволяющую построить на
используемом языке программирования правильное обращение к нему (к любому его
входу), и, во-вторых, функциональную спецификацию модуля (описание семантики
функций, выполняемых этим модулем по каждому из его входов).

Основные характеристики программного модуля

Размер модуля измеряется числом содержащихся в
нем операторов (строк). Модуль не должен быть слишком маленьким или слишком
большим. Маленькие модули приводят к громоздкой модульной структуре программы и
могут не окупать накладных расходов, связанных с их оформлением. Большие модули
неудобны для изучения и изменений, они могут существенно увеличить суммарное
время повторных трансляций программы при отладке программы. Обычно рекомендуются
программные модули размером от нескольких десятков до нескольких сотен
операторов.

Прочность модуля — это мера его внутренних
связей. Чем выше прочность модуля, тем больше связей он может спрятать от
внешней по отношению к нему части программы и, следовательно, тем больший вклад
в упрощение программы он может внести. Самой слабой степенью прочности обладает
модуль, прочный по совпадению. Это такой модуль, между элементами
которого нет осмысленных связей. Такой модуль может быть выделен, например, при
обнаружении в разных местах программы повторения одной и той же
последовательности операторов, которая и оформляется в отдельный модуль.
Необходимость изменения этой последовательности в одном из контекстов может
привести к изменению этого модуля, что может сделать его использование в других
контекстах ошибочным. Такой класс программных модулей не рекомендуется для
использования.

Функционально прочный модуль — это модуль, выполняющий
(реализующий) одну какую-либо определенную функцию. При реализации этой функции
такой модуль может использовать и другие модули. Такой класс программных модулей
рекомендуется для использования.

Информационно прочный модуль — это модуль, выполняющий
(реализующий) несколько операций (функций) над одной и той же структурой данных
(информационным объектом), которая считается неизвестной вне этого модуля. Для
каждой из этих операций в таком модуле имеется свой вход со своей формой
обращения к нему. Такой класс следует рассматривать как класс программных
модулей с высшей степенью прочности. Информационно-прочный модуль может
реализовывать, например, абстрактный тип данных.

Сцепление модуля — это мера его зависимости по
данным от других модулей. Характеризуется способом передачи данных. Чем слабее
сцепление модуля с другими модулями, тем сильнее его независимость от других
модулей.

Рутинность модуля — это его независимость от
предыстории обращений к нему. Модуль будем называть рутинным, если
результат (эффект) обращения к нему зависит только от значений его параметров (и
не зависит от предыстории обращений к нему). Модуль будем называть зависящим
от предыстории
, если результат (эффект) обращения к нему зависит от
внутреннего состояния этого модуля, храняшего следы предыдущих обращений к нему.

Порядок разработки программного модуля

При разработке программного модуля целесообразно
придерживаться следующего порядка:

1) изучение и проверка спецификации модуля, выбор языка
программирования;

2) выбор алгоритма и структуры данных;

3) программирование модуля;

4) шлифовка текста модуля;

5) проверка модуля;

6) компиляция модуля.

Первый шаг разработки программного модуля в
значительной степени представляет собой смежный контроль структуры программы
снизу: изучая спецификацию модуля, разработчик должен убедиться, что она ему
понятна и достаточна для разработки этого модуля. В завершении этого шага
выбирается язык программирования.

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

На третьем шаге осуществляется построение текста
модуля на выбранном языке программирования. Обилие всевозможных деталей, которые
должны быть учтены при реализации функций, указанных в спецификации модуля,
легко могут привести к созданию весьма запутанного текста, содержащего массу
ошибок и неточностей. Искать ошибки в таком модуле и вносить в него требуемые
изменения может оказаться весьма трудоемкой задачей.

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

Шаг проверки модуля представляет собой ручную
проверку внутренней логики модуля до начала его отладки (использующей выполнение
его на ЭВМ), реализует общий принцип, сформулированный для технологии
программирования.

И, наконец, последний шаг разработки модуля
означает переход к процессу отладки модуля.

Контроль структуры программы.

Для контроля структуры программы можно использовать три
метода:

•   статический
контроль,

•   смежный контроль,

•   сквозной
контроль.

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

Смежный контроль сверху — это контроль со
стороны разработчиков архитектуры и внешнего описания ПС. Смежный контроль
снизу
— это контроль спецификации модулей со стороны разработчиков этих
модулей.

Сквозной контроль — это мысленное прокручивание
(проверка) структуры программы при выполнении заранее разработанных тестов.
Является видом динамического контроля так же, как и ручная имитация
функциональной спецификации или архитектуры ПС.

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

 

К оглавлению



Что такое программный модуль?

Программные модули в конфигурации системы 1С:Предприятие не являют­ся самостоятельными программами в
общепринятом понимании этого слова, поскольку они являются только частью всей конфигурации задачи. Программ­ный модуль
— это своего рода «контейнер» для размещения текстов процедур и функций, вызываемых
системой во время исполнения задачи в определенные моменты работы. Поэтому
программный модуль не имеет формальных границ своего описания типа: «Начало
модуля» — «Конец модуля».

Место размещения конкретного программного модуля (тот самый
«контей­нер») предоставляется конфигуратором в тех точках конфигурации задачи,
ко­торые требуют описания специфических алгоритмов функционирования. Эти
алгоритмы следует оформлять в виде процедур или функций, которые будут вызваны
самой системой в заранее предусмотренных ситуациях (например, при нажатии
кнопки в диалоговом окне).

Каждый отдельный программный модуль воспринимается системой
как единое целое, поэтому все процедуры и функции программного модуля вы­полняются
в едином контексте.

Контекст выполнения программного модуля

Каждый программный модуль связан с остальной частью
конфигурации за­дачи. Эта связь называется контекстом выполнения модуля.
Следует различать два вида контекста:

·        
глобальный контекст задачи;

·        
локальный контекст выполнения конкретного
модуля.

Глобальный контекст образуется:

·        
значениями системных атрибутов, системными
процедурами и функ­циями;

·        
значениями заданных в конфигураторе констант, перечислений, регист­ров, видов
расчета, групп видов расчета
;

·        
переменными, процедурами и функциями глобального
программного модуля, объявленными с ключевым словом Экспорт.

Глобальный контекст виден
всем программным модулям и определяет об­щую языковую среду конфигурации.

Локальный контекст модуля образуется тем конкретным местом
конфигу­рации задачи, для которого использован программный модуль. Локальный
кон­текст виден только конкретному программному модулю и определяет для мо­дуля
набор непосредственно доступных модулю значений агрегатных типов данных, их
атрибутов и методов (см. «Виды программных модулей»).
Однако, контекст модуля можно передать как объект в
виде параметра при вызове про­цедур и функций (см. «Передача локального
контекста программного модуля в качестве параметра»). Кроме того, контекст
модуля определяет тот набор мето­дов, которые доступны только в данном
контексте. Локальный контекст предназначен для того,
чтобы дать воз­можность управлять частными аспектами поведения задачи,
присущими дан­ному модулю.

 

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

Комментарий начинается парой символов «//» и
заканчивается концом строки.

Пример:

А=В;
// Это – комментарий

//
Это тоже комментарий

Операторы имеют вид стандартного
обращения к процедуре, за исключени­ем оператора присваивания (А=В;) и
управляющих конструкций (таких как Для, Пока, Если).
Между собой операторы обязательно следует разделять сим­волом «;». Конец строки не является признаком конца опе­ратора,
т. е. операторы могут свободно переходить через строки и продолжаться на другой
строке. Можно располагать произвольное число операторов на од­ной строке,
разделяя их символом «;».

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

В общем случае формат оператора языка следующий:

~метка:Оператор[(параметры)] [ДобКлючевоеСлово];

В качестве меток
используются специальные идентификаторы, начинаю­щиеся с символа ‘~’ (тильда) и
состоящие из последовательности букв, цифр и символов ‘_’. Чтобы пометить
оператор, надо поместить перед ним метку и сле­дующий за ней символ «:».

Пример:

~метка:А=В;

 

Преимущества модульного программного обеспечения и программирования — Gwentech Embedded

Модульное программирование

— это процесс, который включает в себя разделение компьютерной программы на отдельные подпрограммы. Модуль — это отдельный компонент, который может использоваться с рядом функций и приложений в сочетании с другими компонентами в системе. Идентичные функции организованы вместе с одним и тем же программным кодом, а отдельные функции создаются как отдельные блоки кода, что делает их доступными для повторного использования с другими приложениями.

Использование модульного программного обеспечения и программирования дает много преимуществ по сравнению с другими методами.

Развитие можно разделить

Модульное программирование

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

Читаемые программы

Modular Programming помогает разрабатывать программы, которые намного легче читать, поскольку они могут быть включены как определяемые пользователем функции.За программой, несущей несколько функций, легче следить, тогда как за программой, не имеющей функции, следовать гораздо труднее.

Ошибки программирования легко обнаружить

Модульное программирование

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

Позволяет повторно использовать коды

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

Повышает управляемость

Разделение программы на более мелкие подпрограммы упрощает управление. Отдельные модули легче тестировать, внедрять или проектировать. Эти отдельные модули затем можно использовать для разработки всей программы.

Сотрудничество

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

Проект документации Linux

Информация о LDP

FAQ

Манифест / лицензия

История

Волонтеры / сотрудники

Должностные инструкции

Списки рассылки

IRC

Обратная связь

Автор / внести свой вклад

Руководство для авторов LDP

Внесите свой вклад / помогите

Ресурсы

Как отправить

Репозиторий GIT

Загрузок

Контакты

Спонсор сайта LDP
Мастерская

LDP Wiki : LDP Wiki — это отправная точка для любой незавершенной работы
Члены |
Авторы |
Посетители
Документы


HOWTO
:
тематическая справка
последние обновления |
основной индекс |
просматривать по категориям


Руководства
:
более длинные и подробные книги
последние обновления / основной указатель


Часто задаваемые вопросы
:
Часто задаваемые вопросы
последние обновления / основной индекс


страницы руководства
:
справка по отдельным командам (20060810)

Бюллетень Linux
:
Интернет-журнал
Поиск / Ресурсы

Ссылки

Поиск OMF

Объявления / Разное

Обновления документа
Ссылка на HOWTO, которые были недавно обновлены.

Что такое тестирование модулей? — Определение и различия

Программное обеспечение состоит из ряда программных модулей, которые объединены вместе, чтобы сформировать программное приложение. Сам модуль — это программа, написанная на определенном языке, которая состоит из подпрограмм, подпрограмм, классов, процедур и функций. Определение тестирования модуля: тестирование этих единиц составного модуля может быть выполнено посредством тестирования модуля.

Модульное тестирование можно в основном разделить на «белый ящик». Иногда тестирование модулей также называют тестированием программ или компонентов. Основная цель проведения тестирования модуля — убедиться, что модуль полностью протестирован и работает, чтобы участвовать в тестировании приложения. Тестирование модуля снижает количество дефектов или ошибок, которые могут быть обнаружены во время тестирования приложения на более позднем этапе тестирования. Он также вводит параллелизм в подход к тестированию, поскольку дает возможность тестировать несколько модулей приложения одновременно.

Что такое тестирование модулей?

Тестирование модулей

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

Также прочтите => Разница между модульным тестом и интеграционным тестом

Почему всегда рекомендуется тестирование модулей?

Module Testing всегда рекомендуется по следующим причинам.

  1. Всегда легче протестировать небольшой фрагмент программы или подпрограммы, чем большую программу или полное приложение. Небольшую единицу кода можно протестировать с помощью требуемых модульных тестов и убедиться, что конкретная функция, процедура, подпрограмма и т. Д. Работает нормально и все настроены для интеграции с другими программами или модулями, присутствующими в программном приложении.
  2. Поддерживает параллельное тестирование. Несколько модулей, принадлежащих одному приложению, можно тестировать параллельно, независимо друг от друга.Когда эти независимо протестированные модули интегрированы в программное обеспечение, конечный продукт определенно будет качественным.
  3. Благодаря модульному тестированию тестировщики могут легко справиться со сложностью программного приложения, поскольку тестирование проводится на уровне отдельных модулей или небольшой части программы.

Примеры советов по тестированию модулей

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

  • Очень важно разработать тестовый пример до того, как можно будет начать тестирование модуля. Кроме того, тестировщик должен принять во внимание следующие две вещи, прежде чем разрабатывать тестовый пример для тестирования модуля.
  • Спецификация модуля.
  • Исходный код тестируемого модуля.
  • Важно проанализировать логику кода тестируемого модуля. Тестировщик может использовать один или несколько методов белого ящика и может легко улучшить эти тестовые примеры путем применения методов черного ящика к спецификации модулей.
  • После завершения разработки тестовых примеров следующим шагом является связывание модуля для тестирования. Тестировщик может использовать либо инкрементный, либо не инкрементный метод для подхода к тестированию.
  • При инкрементальном подходе каждый программный модуль сначала тестируется, а затем постепенно увеличивается, чтобы протестировать как совокупность посредством пошагового подхода. Кроме того, подход инкрементального тестирования для тестирования модулей можно разделить на два подхода. Это подход к тестированию снизу-вверх и подход к тестированию сверху вниз.
  • При неинкрементном подходе все программные модули сначала тестируются независимо, а затем интегрируются и тестируются как целая программа.
  • Мы должны подготовить тестовые данные, которые должны быть переданы в модуль через драйвер, чтобы выполнить тест для этого модуля, отслеживая выполнение теста и фиксируя результаты теста.

Лучшие практики для тестирования модулей / компонентов

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

  • Обзор тестовых примеров: Мы должны получать наши тестовые примеры на рассмотрение с необходимой командой или коллегами, чтобы убедиться, что у нас есть 100% тестовое покрытие.
  • Автоматическое выполнение теста : Мы должны определить сценарии тестирования или функции, которые можно автоматизировать с помощью инструмента тестирования. Это сэкономит нам время при многократном выполнении таких тестовых примеров.
  • Избегайте путаницы: Не должно быть путаницы, связанной с вводом данных и ожидаемым выводом, который нужно протестировать для любого модуля.
  • Изучите переменные: Переменные, которые предполагается изменять или постоянно поддерживать постоянными, следует тщательно контролировать и исследовать во время записи результатов испытаний.
  • Повторно используйте тестовые примеры и избегайте дублирования тестовых примеров.

Разница между модульным тестированием и модульным тестированием

Ниже приводится сравнение модульного тестирования и модульного тестирования.

No. Модульное тестирование Модульное тестирование
1. Модульные тесты — это набор тестов, которые написаны разработчиком во время процесса разработки программного обеспечения. Модульные тесты — это набор тестов, которые написаны тестировщиком после того, как разработчик завершил кодирование для конкретного модуля.
2. Модульное тестирование включает тестирование отдельных модулей. Модульное тестирование включает комбинацию модульного теста.

Проблемы при тестировании модулей

Ниже перечислены проблемы, с которыми часто сталкивается тестировщик при выполнении тестирования модулей.

  • Если подход к тестированию модулей — это не инкрементный подход, то тестирование может потребовать дополнительной работы, так как каждый модуль должен быть протестирован сначала независимо, а затем все вместе как одно приложение.
  • Возможно недопонимание тестовых двойников при выполнении тестирования модуля.
  • Может потребоваться отладка тестов очень часто, что может потребовать много усилий и времени на тестирование.
  • Тестировщики должны понимать код, и поэтому тестирование модулей не может выполняться просто тестировщиками, не имеющими навыков языка программирования.

Заключение

В этом классе мы изучаем определение тестирования модуля, примеры, различия. Тестирование модуля — это тестирование подпрограмм, подпрограмм, классов, процедур и функций, связанных с конкретным модулем, которое может быть выполнено с помощью подходов к инкрементному и неинкрементному тестированию модулей.Основное преимущество проведения тестирования модуля перед тестированием приложения заключается в том, что вероятность выявления дефектов или ошибок в меньшей части программы становится выше, чем в случае выявления дефектов для большой программы, и, кроме того, это сводит к минимуму усилия по тестированию, необходимые для выполнения тестирования приложения, т.е. все программное обеспечение за раз.


⇓ Подписаться на нас


Если вы не являетесь постоянным читателем этого сайта, то настоятельно рекомендуем вам Подпишитесь на нашу бесплатную рассылку новостей по электронной почте! ! Зарегистрируйтесь, просто указав свой адрес электронной почты ниже:

Удачного тестирования !!!

Модуль

— Характеристики модулей

Модуль

Модуль — это часть программы.Программы
состоит из одного или нескольких независимо разработанных модулей. Один модуль может
содержат одно или несколько утверждений, тесно связанных друг с другом. Модули работают
идеально на индивидуальном уровне и может быть интегрирован с другими модулями. А
программное обеспечение можно разделить на модули, чтобы упростить программирование и
также отладка. Программу можно разделить на небольшие функциональные модули, которые
работать вместе, чтобы получить результат. Процесс разделения компьютерной программы
на отдельные подпрограммы называется модульным программированием.Модульное программирование
позволяет программистам разделить работу и отладить части программы
независимо. Примерами модулей являются процедуры, подпрограммы и
функции.

Характеристики модулей

Ниже приведены желательные характеристики
модуля.

1. Модули содержат инструкции, логику обработки и данные.

2.Модули можно компилировать отдельно и хранить в библиотеке.

3. В программу можно включать модули.

4. Сегменты модуля можно использовать, вызывая имя и некоторые
параметры.

5. Сегменты модуля могут использоваться другими
модули.

Преимущества использования модульного программирования включают

·
Нужно писать меньше кода.

·
Можно разработать единую процедуру для повторного использования, что устраняет необходимость
повторно набирать код много раз.

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

·
Модульное программирование позволяет многим программистам совместно работать над
то же приложение.

·
Код хранится в нескольких файлах.

·
Код короткий, простой и понятный.

·
Ошибки легко идентифицировать, так как они локализованы на
подпрограмма или функция.

·
Один и тот же код можно использовать во многих приложениях.

·
Объем переменных можно легко контролировать. Меньше кода, чтобы быть
написано.

Контроль доступа

Контроль доступа — это метод безопасности, который
регулирует, кто или что может просматривать или использовать ресурсы в вычислительной среде.Это
это фундаментальная концепция безопасности, которая сводит к минимуму риск для объекта. В
Другими словами, контроль доступа — это выборочное ограничение доступа к данным. В
В объектно-ориентированных языках программирования реализовано через доступ
модификаторы. Классические объектно-ориентированные языки, такие как C ++ и Java, управляют
доступ к членам класса по публичным, частным и защищенным ключевым словам. Частный
членам класса отказано в доступе извне класса. Они могут быть
обрабатывается только изнутри класса.

Открытые члены (обычно методы, объявленные в
class) доступны извне класса. Объект того же класса
требуется для вызова общедоступного метода. Это расположение частного экземпляра
переменные и общедоступные методы обеспечивают принцип инкапсуляции данных
.

Доступны защищенные члены класса
изнутри класса, а также доступны для его подклассов.Нет другого
процессу разрешен доступ к нему. Это позволяет использовать определенные ресурсы
родительский класс, который будет унаследован дочерним классом.

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

Все члены класса Python открыты
по умолчанию, тогда как по умолчанию в C ++ и java они являются частными.Любой участник может быть
доступ извне среды класса в Python, что невозможно в
C ++ и java.

Руководство для разработчиков модулей — EnergyPlus 8.9

Программные модули

[ССЫЛКА]

Модуль — это программная конструкция Fortran 90/95, которую можно использовать по-разному. В EnergyPlus его основное назначение — сегментировать довольно большую программу на более мелкие и более управляемые части.Каждый модуль представляет собой отдельный пакет исходного кода, хранящийся в отдельном файле. Вся коллекция модулей после компиляции и компоновки образует исполняемый код EnergyPlus.

Каждый модуль содержит исходный код для тесно связанных структур данных и процедур. Например, модуль WeatherManager содержит все процедуры обработки погоды в EnergyPlus. Модуль содержится в файле WeatherManager.f90. Другой пример — PlantPumps. Этот модуль содержит весь код для моделирования насосов в EnergyPlus.Он содержится в файле PlantPumps.f90.

Конечно, разделение программы на модули можно осуществить разными способами. Мы попытались создать модули, которые были бы как можно более автономными. Философия, которая использовалась при создании EnergyPlus, содержится в справочном документе по стандарту программирования. Логически модули в EnergyPlus образуют перевернутую древовидную структуру. Вверху находится EnergyPlus. Чуть ниже находятся ProcessInput и ManageSimulation. Внизу расположены такие модули, как HVACDamperComponent, которые моделируют фактические компоненты HVAC.

Data Only Modules [ССЫЛКА]

EnergyPlus также использует модули, которые в основном содержат данные и структуры данных, которые могут использоваться несколькими модулями. Эти модули образуют один из основных способов структурирования и обмена данными в EnergyPlus. Примером может служить модуль DataEnvironment. Многие части программы требуют доступа к условиям на открытом воздухе. Все эти данные инкапсулируются в DataEnvironment. Модули, которым нужны эти данные, получают доступ через USE-оператор Fortran.Без такого доступа модули не могут использовать или изменять эти данные.

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

FAQ по программированию — документация Python 3.9.7

Есть ли отладчик на уровне исходного кода с точками останова, пошаговым режимом и т. Д.?

Да.

Несколько отладчиков для Python описаны ниже, а встроенная функция
breakpoint () позволяет перейти к любой из них.

Модуль pdb — это простой, но адекватный отладчик консольного режима для Python. это
часть стандартной библиотеки Python и документирована в Библиотеке
Справочное руководство
. Вы также можете написать свой собственный отладчик, используя код
для pdb в качестве примера.

Интерактивная среда разработки IDLE, входящая в стандартную
Дистрибутив Python (обычно доступный как Tools / scripts / idle) включает
графический отладчик.

PythonWin — это среда разработки Python, которая включает отладчик графического интерфейса пользователя на основе pdb.В
Отладчик PythonWin раскрашивает точки останова и имеет довольно много интересных функций, таких как
отладка программ, отличных от PythonWin. PythonWin доступен как часть
проект pywin32 и
как часть
Распространение ActivePython.

Eric — это IDE, построенная на PyQt
и компонент редактирования Scintilla.

trepan3k — отладчик, подобный gdb.

Visual Studio Code — это IDE с отладкой
инструменты, которые интегрируются с ПО для контроля версий.

Существует ряд коммерческих Python IDE, которые включают графические отладчики.В их числе:

Как я могу создать автономный двоичный файл из скрипта Python?

Вам не нужна возможность компилировать Python в код C, если все, что вам нужно, это
автономная программа, которую пользователи могут загружать и запускать без установки
сначала дистрибутив Python. Есть ряд инструментов, которые определяют
набор модулей, необходимых для программы, и связать эти модули вместе с
Бинарный файл Python для создания одного исполняемого файла.

Один — использовать инструмент замораживания, который включен в дерево исходных текстов Python как
Инструменты / заморозка .Он преобразует байтовый код Python в массивы C; компилятор C вы можете
встроить все свои модули в новую программу, которая затем будет связана с
стандартные модули Python.

Он работает путем рекурсивного сканирования исходного кода на предмет операторов импорта (в обоих
forms) и ищем модули в стандартном пути Python, а также в
исходный каталог (для встроенных модулей). Затем он превращает байт-код для модулей
написаны на Python в коде C (инициализаторы массивов, которые можно превратить в код
объекты с помощью модуля маршала) и создает настраиваемый файл конфигурации, который
содержит только те встроенные модули, которые фактически используются в программе.Это
затем компилирует сгенерированный код C и связывает его с остальной частью Python
интерпретатор для формирования автономного двоичного файла, который действует точно так же, как ваш скрипт.

Следующие пакеты могут помочь в создании консоли и графического интерфейса.
исполняемые файлы:

Почему я получаю ошибку UnboundLocalError, когда переменная имеет значение?

Это может быть сюрпризом, если UnboundLocalError ранее работал
код, когда он изменен путем добавления оператора присваивания где-нибудь в
тело функции.

Этот код:

 >>> х = 10
>>> def bar ():
... печать (x)
>>> бар ()
10
 

работает, но этот код:

 >>> х = 10
>>> def foo ():
... печать (x)
... х + = 1
 

приводит к UnboundLocalError:

 >>> foo ()
Отслеживание (последний вызов последний):
  ...
UnboundLocalError: локальная переменная 'x', на которую ссылается перед присваиванием
 

Это связано с тем, что когда вы выполняете присвоение переменной в области видимости, это
переменная становится локальной для этой области и затеняет любую переменную с аналогичным именем
во внешнем объеме.Поскольку последний оператор в foo присваивает новое значение
x , компилятор распознает его как локальную переменную. Следовательно, когда
ранее print (x) пытается распечатать неинициализированную локальную переменную и
возникает ошибка.

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

 >>> х = 10
>>> def foobar ():
... глобальный x
... печать (x)
... х + = 1
>>> foobar ()
10
 

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

Вы можете сделать то же самое во вложенной области, используя нелокальный
ключевое слово:

 >>> def foo ():
... x = 10
... def bar ():
... нелокальный x
... печать (x)
... х + = 1
...    бар()
... печать (x)
>>> foo ()
10
11
 

Каковы правила для локальных и глобальных переменных в Python?

В Python переменные, которые упоминаются только внутри функции, неявно
Глобальный. Если переменной присваивается значение в любом месте тела функции,
предполагается, что он является локальным, если явно не объявлен как глобальный.

Поначалу это может показаться немного удивительным, но небольшое размышление объясняет это.На
одной рукой, требующей глобальных для присвоенных переменных, обеспечивает полосу
от непреднамеренных побочных эффектов. С другой стороны, если требуется global
для всех глобальных ссылок вы всегда будете использовать global . У тебя было бы
объявить глобальными каждую ссылку на встроенную функцию или компонент
импортированный модуль. Этот беспорядок сводит на нет полезность global .
объявление для выявления побочных эффектов.

Почему лямбда-выражения, определенные в цикле с разными значениями, возвращают один и тот же результат?

Предположим, вы используете цикл for для определения нескольких различных лямбда-выражений (или даже простых
функции), e.г .:

 >>> квадраты = []
>>> для x в диапазоне (5):
... squares.append (лямбда: x ** 2)
 

Это дает вам список, содержащий 5 лямбд, которые вычисляют x ** 2 . Ты
может ожидать, что при вызове они вернут, соответственно, 0 , 1 ,
4 , 9 и 16 . Однако, когда вы действительно попробуете, вы увидите, что
все они возвращают 16 :

 >>> квадраты [2] ()
16
>>> квадраты [4] ()
16
 

Это происходит потому, что x не является локальным для лямбда-выражений, но определено в
внешняя область видимости, и к ней обращаются, когда вызывается лямбда, а не когда она
определено.В конце цикла значение x равно 4 , поэтому все
теперь функции возвращают 4 ** 2 , т.е. 16 . Вы также можете проверить это,
измените значение x и посмотрите, как изменятся результаты лямбда-выражений:

 >>> х = 8
>>> квадраты [2] ()
64
 

Чтобы этого избежать, вам необходимо сохранить значения в переменных, локальных для
лямбды, чтобы они не полагались на значение глобального x :

 >>> квадраты = []
>>> для x в диапазоне (5):
... squares.append (лямбда n = x: n ** 2)
 

Здесь n = x создает новую переменную n , локальную для лямбды, и вычисляет
когда лямбда определена так, что она имеет то же значение, что и x в
эта точка в петле. Это означает, что значение n будет 0
в первой лямбде, 1 во второй, 2 в третьей и т. д.
Поэтому каждая лямбда теперь будет возвращать правильный результат:

 >>> квадраты [2] ()
4
>>> квадраты [4] ()
16
 

Обратите внимание, что это поведение не свойственно лямбдам, но применяется к обычным
функции тоже.

Как поделиться глобальными переменными между модулями?

Канонический способ обмена информацией между модулями в рамках одной программы —
для создания специального модуля (часто называемого config или cfg). Просто импортируйте конфиг
модуль во всех модулях вашего приложения; модуль затем становится доступным как
глобальное имя. Поскольку существует только один экземпляр каждого модуля, любые изменения
внесенные в объект модуля отражаются повсюду. Например:

config.py:

 x = 0 # Значение по умолчанию для параметра конфигурации 'x'
 

мод.py:

 конфигурация импорта
config.x = 1
 

main.py:

 конфигурация импорта
импорт мода
печать (config.x)
 

Обратите внимание, что использование модуля также является основой для реализации дизайна Singleton.
узор по той же причине.

Каковы «лучшие практики» использования импорта в модуле?

Как правило, не используйте из импорта имени модуля * . Это загромождает
пространство имен импортера, и линтерам намного сложнее обнаружить undefined
имена.

Импортировать модули в начало файла. Так станет понятно, какие еще модули
ваш код требует и позволяет избежать вопросов о том, входит ли имя модуля в область видимости.
Использование одного импорта на строку упрощает добавление и удаление импорта модуля, но
при использовании нескольких операций импорта на строку используется меньше места на экране.

Рекомендуется импортировать модули в следующем порядке:

  1. стандартных библиотечных модуля — например, sys , os , getopt , re

  2. сторонних библиотечных модулей (все, что установлено в пакетах сайтов Python
    справочник) — эл.грамм. mx.DateTime, ZODB, PIL.Image и т. д.

  3. модуля местной разработки

Иногда необходимо переместить импорт в функцию или класс, чтобы избежать
проблемы с циклическим импортом. Гордон Макмиллан говорит:

Циклический импорт подходит, если оба модуля используют форму «import ».
импорта. Они терпят неудачу, когда 2-й модуль хочет вырвать имя из
first («из имени импорта модуля»), а импорт — на верхнем уровне. Это
потому что имена в 1-м еще недоступны, потому что первый модуль
занят импортом 2-го.

В этом случае, если второй модуль используется только в одной функции, то импорт
можно легко перенести в эту функцию. К моменту вызова импорта
первый модуль завершит инициализацию, а второй модуль сможет выполнить свою
Импортировать.

Также может потребоваться переместить импорт с верхнего уровня кода, если некоторые из
модули зависят от платформы. В этом случае, возможно, даже не удастся
импортировать все модули в верхней части файла. В этом случае импорт
правильные модули в соответствующем программном коде — хороший вариант.

Перемещайте импорт только в локальную область, например внутри определения функции, если
необходимо решить такую ​​проблему, как избежать циклического импорта или
пытается сократить время инициализации модуля. Эта техника
особенно полезно, если многие из импорта не нужны в зависимости от того, как
программа выполняется. Вы также можете переместить импорт в функцию, если
модули используются только в этой функции. Обратите внимание, что при загрузке модуля
первый раз может быть дорогим из-за однократной инициализации
модуль, но загрузка модуля несколько раз практически бесплатна и стоит всего лишь
пару поисков по словарю.Даже если имя модуля вышло за рамки,
модуль, вероятно, доступен в sys.modules .

Почему значения по умолчанию разделяются между объектами?

Этот тип ошибок обычно укусывает начинающих программистов. Рассмотрим эту функцию:

 def foo (mydict = {}): # Опасность: общая ссылка на один dict для всех вызовов
    ... вычислить что-нибудь ...
    mydict [ключ] = значение
    вернуть mydict
 

При первом вызове этой функции mydict содержит единственный элемент.В
во второй раз mydict содержит два элемента, потому что, когда начинается foo ()
при выполнении mydict начинается с уже содержащегося в нем элемента.

Часто ожидается, что вызов функции создает новые объекты по умолчанию.
ценности. Это не то, что происходит. Значения по умолчанию создаются ровно один раз, когда
функция определена. Если этот объект был изменен, как словарь в этом
Например, последующие вызовы функции будут ссылаться на этот измененный объект.

По определению неизменяемые объекты, такие как числа, строки, кортежи и Нет ,
защищены от изменений.Изменения в изменяемых объектах, таких как словари, списки,
и экземпляры классов могут привести к путанице.

Из-за этой функции рекомендуется не использовать изменяемые
объекты как значения по умолчанию. Вместо этого используйте Нет в качестве значения по умолчанию и
внутри функции проверьте, является ли параметр Нет и создайте новый
список / словарь / что угодно, если это так. Например, не пишите:

а:

 def foo (mydict = None):
    если mydict - Нет:
        mydict = {} # создать новый dict для локального пространства имен
 

Эта функция может быть полезной.Когда у вас есть функция, требующая много времени,
вычислить, распространенным методом является кэширование параметров и результирующего значения
каждого вызова функции, и вернуть кешированное значение, если то же значение
попросил еще раз. Это называется «запоминанием» и может быть реализовано следующим образом:

 # Вызывающие могут предоставить только два параметра и опционально передать _cache по ключевому слову
def дорого (arg1, arg2, *, _cache = {}):
    если (arg1, arg2) в _cache:
        return _cache [(arg1, arg2)]

    # Рассчитать значение
    результат =... дорогое вычисление ...
    _cache [(arg1, arg2)] = result # Сохранить результат в кеше
    вернуть результат
 

Вместо значения по умолчанию можно использовать глобальную переменную, содержащую словарь.
ценить; это дело вкуса.

Как передать необязательные параметры или параметры ключевого слова из одной функции в другую?

Соберите аргументы, используя спецификаторы * и ** в функциях
список параметров; это дает вам позиционные аргументы в виде кортежа и
аргументы ключевого слова как словарь.Затем вы можете передать эти аргументы, когда
вызов другой функции с использованием * и ** :

 def f (x, * args, ** kwargs):
    ...
    kwargs ['ширина'] = '14 .3c '
    ...
    g (x, * аргументы, ** kwargs)
 

В чем разница между аргументами и параметрами?

Параметры определяются именами, которые появляются в
определение функции, а аргументы — это значения
фактически передается функции при ее вызове. Параметры определяют, какие типы
аргументы, которые функция может принимать.Например, учитывая определение функции:

 def func (foo, bar = None, ** kwargs):
    проходить
 

foo , bar и kwargs являются параметрами func . Однако при звонке
func , например:

 func (42, bar = 314, extra = somevar)
 

значения 42 , 314 и somevar являются аргументами.

Почему при изменении списка «y» изменился и список «x»?

Если вы написали такой код:

 >>> x = []
>>> у = х
>>> у.добавить (10)
>>> у
[10]
>>> х
[10]
 

вам может быть интересно, почему добавление элемента к y также изменило x .

Есть два фактора, которые приводят к этому результату:

  1. Переменные — это просто имена, относящиеся к объектам. Выполнение y = x не дает
    создать копию списка — он создает новую переменную y , которая ссылается на
    тот же объект x относится. Это означает, что есть только один объект
    (список), и к нему относятся как x , так и y .

  2. Списки изменяемы, что означает, что вы можете изменять их содержимое.

После вызова append () содержимое изменяемого объекта имеет
изменено с [] на [10] . Поскольку обе переменные относятся к одному и тому же
объект, используя любое имя, получает доступ к измененному значению [10] .

Если вместо этого мы присвоим неизменяемому объекту значение x :

 >>> x = 5 # целые числа неизменяемы
>>> у = х
>>> x = x + 1 # 5 не может быть изменен, здесь мы создаем новый объект
>>> х
6
>>> у
5
 

мы видим, что в этом случае x и y больше не равны.Это
потому что целые числа неизменяемы, и когда мы делаем x = x + 1 , мы не
изменение int 5 путем увеличения его значения; вместо этого мы создаем
новый объект (int 6 ) и присвоение ему значения x (то есть изменение
объект x относится). После этого назначения у нас есть два объекта (int
6 и 5 ) и две переменные, которые к ним относятся ( x теперь относится к
6 , но y все еще относится к 5 ).

Некоторые операции (например, y.append (10) и y.sort () ) изменяют
объект, тогда как внешне похожие операции (например, y = y + [10]
и sorted (y) ) создают новый объект. В целом в Python (и во всех случаях
в стандартной библиотеке) метод, изменяющий объект, вернет Нет
чтобы избежать путаницы между двумя типами операций. Итак, если вы
по ошибке напишите y.sort () , думая, что это даст вам отсортированную копию y ,
вместо этого вы получите Нет , что, вероятно, приведет к тому, что ваша программа
генерировать легко диагностируемую ошибку.

Однако есть один класс операций, в котором одна и та же операция иногда
имеет разное поведение с разными типами: расширенное задание
операторы. Например, + = изменяет списки, но не кортежи или целые числа ( a_list
+ = [1, 2, 3]
эквивалентно a_list.extend ([1, 2, 3]) и изменяет
a_list , тогда как some_tuple + = (1, 2, 3) и some_int + = 1 создают
новые объекты).

Другими словами:

  • Если у нас есть изменяемый объект ( список , dict , set ,
    и т.п.), мы можем использовать некоторые специальные операции, чтобы изменить его и все переменные
    которые относятся к нему, увидят изменение.

  • Если у нас есть неизменяемый объект ( str , int , tuple ,
    и т. д.), все относящиеся к нему переменные всегда будут иметь одно и то же значение,
    но операции, которые преобразуют это значение в новое значение, всегда возвращают новое
    объект.

Если вы хотите знать, относятся ли две переменные к одному и тому же объекту или нет, вы можете
используйте оператор is или встроенную функцию id () .

Как мне написать функцию с выходными параметрами (вызов по ссылке)?

Помните, что аргументы в Python передаются путем присваивания. С момента присвоения
просто создает ссылки на объекты, нет псевдонима между именем аргумента в
вызывающий и вызываемый, и, следовательно, никакого вызова по ссылке как такового. Вы можете добиться
желаемый эффект несколькими способами.

  1. Путем возврата кортежа результатов:

     >>> def func1 (a, b):
    ... a = 'new-value' # a и b - локальные имена
    ... b = b + 1 # назначается новым объектам
    ... return a, b # вернуть новые значения
    ...
    >>> x, y = 'старое значение', 99
    >>> func1 (x, y)
    ('новое значение', 100)
     

    Это почти всегда самое ясное решение.

  2. С использованием глобальных переменных. Это не является потокобезопасным и не рекомендуется.

  3. Путем передачи изменяемого (изменяемого на месте) объекта:

     >>> def func2 (a):
    ... a [0] = 'new-value' # 'a' ссылается на изменяемый список
    ... a [1] = a [1] + 1 # изменяет общий объект
    ...
    >>> args = ['старое значение', 99]
    >>> func2 (аргументы)
    >>> аргументы
    ['новое значение', 100]
     
  4. Путем передачи изменяемого словаря:

     >>> def func3 (аргументы):
    ... args ['a'] = 'new-value' # args - изменяемый словарь
    ... args ['b'] = args ['b'] + 1 # изменить его на месте
    ...
    >>> args = {'a': 'старое значение', 'b': 99}
    >>> func3 (аргументы)
    >>> аргументы
    {'a': 'новое значение', 'b': 100}
     
  5. Или объедините значения в экземпляр класса:

     >>> Пространство имен класса:
    ... def __init __ (self, /, ** args):
    ... для ключа значение в args.items ():
    ... setattr (сам, ключ, значение)
    ...
    >>> def func4 (аргументы):
    ... args.a = 'new-value' # args - изменяемое пространство имен
    ... args.b = args.b + 1 # изменить объект на месте
    ...
    >>> args = Пространство имен (a = 'старое значение', b = 99)
    >>> func4 (аргументы)
    >>> vars (аргументы)
    {'a': 'новое значение', 'b': 100}
     

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

Лучше всего вернуть кортеж, содержащий несколько результатов.

Как сделать в Python функцию высшего порядка?

У вас есть два варианта: вы можете использовать вложенные области или вы можете использовать вызываемые объекты.
Например, предположим, что вы хотите определить linear (a, b) , который возвращает
функция f (x) , которая вычисляет значение a * x + b . Использование вложенных областей:

 def linear (a, b):
    def результат (x):
        вернуть a * x + b
    вернуть результат
 

Или используя вызываемый объект:

 класс линейный:

    def __init __ (self, a, b):
        себя.a, self.b = a, b

    def __call __ (self, x):
        вернуть self.a * x + self.b
 

В обоих случаях

дает вызываемый объект, где налогов (10e6) == 0,3 * 10e6 + 2 .

Подход вызываемых объектов имеет тот недостаток, что он немного медленнее и
приводит к немного более длинному коду. Однако обратите внимание, что набор вызываемых
может передать свою подпись по наследству:

 класс экспоненциальный (линейный):
    # __init__ унаследовано
    def __call __ (self, x):
        вернуть себя.а * (х ** сам.б)
 

Объект может инкапсулировать состояние для нескольких методов:

 счетчик классов:

    значение = 0

    def set (self, x):
        self.value = x

    def up (self):
        self.value = self.value + 1

    def down (self):
        self.value = self.value - 1

счетчик = счетчик ()
inc, dec, reset = count.up, count.down, count.set
 

Здесь inc () , dec () и reset () действуют как функции, которые разделяют
та же счетная переменная.

Как мой код может узнать имя объекта?

Вообще говоря, не может, потому что у объектов на самом деле нет имен.
По сути, присвоение всегда связывает имя со значением; то же самое верно и в отношении
def инструкции и class , но в этом случае значение будет
вызываемый. Рассмотрим следующий код:

 >>> класс A:
...     проходить
...
>>> B = A
>>> a = B ()
>>> б = а
>>> print (b)
<__ main __. Объект по адресу 0x16D07CC>
>>> print (а)
<__ main__.Объект по адресу 0x16D07CC>
 

Возможно, у класса есть имя: хотя он привязан к двум именам и вызывается
через имя B созданный экземпляр по-прежнему сообщается как экземпляр
class A. Однако невозможно сказать, является ли имя экземпляра a или
b, поскольку оба имени привязаны к одному и тому же значению.

Вообще говоря, не обязательно, чтобы ваш код «знал имена»
определенных ценностей. Если вы намеренно не пишете интроспективный
программ, это обычно указывает на то, что изменение подхода может быть
выгодный.

В comp.lang.python Фредрик Лунд однажды дал отличную аналогию в ответ на
этот вопрос:

Так же, как вы получили имя той кошки, которую нашли у себя на крыльце: кошка
(объект) сам по себе не может сказать вам свое имя, и ему все равно, поэтому
единственный способ узнать, как это называется, — спросить всех своих соседей
(пространства имен), если это их кот (объект)…

… .и не удивляйтесь, если вы обнаружите, что он известен под разными именами, или
вообще без имени!

Что случилось с приоритетом оператора запятой?

Запятая не является оператором в Python.Рассмотрим этот сеанс:

 >>> «а» в «б», «а»
(Ложь, 'а')
 

Поскольку запятая является не оператором, а разделителем между выражениями,
выше оценивается, как если бы вы ввели:

не:

То же самое верно и для различных операторов присваивания ( = , + = и т. Д.). Они
на самом деле не операторы, а синтаксические ограничители в операторах присваивания.

Существует ли эквивалент тернарного оператора C «?:»?

Да, есть.Синтаксис следующий:

 [on_true] if [выражение] else [on_false]

х, у = 50, 25
small = x, если x 

До того, как этот синтаксис был введен в Python 2.5, распространенной идиомой было использование
логические операторы:

 [выражение] и [on_true] или [on_false]
 

Однако эта идиома небезопасна, поскольку может дать неверные результаты, если on_true
имеет ложное логическое значение. Поэтому всегда лучше использовать
форма ... if ... else ... .

Можно ли писать запутанные однострочные строки в Python?

Да. Обычно это делается путем вложения лямбда в
лямбда . См. Следующие три примера, принадлежащие Ульфу Бартельту:

 из functools import reduce

# Простые числа <1000
print (list (filter (None, map (lambda y: y * reduce (lambda x, y: x * y! = 0,
map (лямбда x, y = y: y% x, диапазон (2, int (pow (y, 0.5) +1))), 1), диапазон (2,1000)))))

# Первые 10 чисел Фибоначчи
print (list (map (lambda x, f = lambda x, f: (f (x-1, f) + f (x-2, f)) if x> 1 else 1:
f (x, f), диапазон (10))))

# Набор Мандельброта
print ((lambda Ru, Ro, Iu, Io, IM, Sx, Sy: reduce (lambda x, y: x + y, map (lambda y,
Iu = Iu, Io = Io, Ru = Ru, Ro = Ro, Sy = Sy, L = лямбда yc, Iu = Iu, Io = Io, Ru = Ru, Ro = Ro, i = IM,
Sx = Sx, Sy = Sy: reduce (lambda x, y: x + y, map (lambda x, xc = Ru, yc = yc, Ru = Ru, Ro = Ro,
i = i, Sx = Sx, F = лямбда xc, yc, x, y, k, f = lambda xc, yc, x, y, k, f: (k <= 0) или (x * x + y * у
> = 4.0) или 1 + f (xc, yc, x * xy * y + xc, 2.0 * x * y + yc, k-1, f): f (xc, yc, x, y, k, f): chr (
64 + F (Ru + x * (Ro-Ru) / Sx, yc, 0,0, i)), диапазон (Sx))): L (Iu + y * (Io-Iu) / Sy), диапазон ( Sy
)))) (- 2,1, 0,7, -1,2, 1,2, 30, 80, 24))
# \ ___ ___ / \ ___ ___ / | | | __ строк на экране
# V V | | ______ столбцов на экране
# | | | __________ максимум «итераций»
# | | _________________ диапазон по оси y
# | ____________________________ диапазон по оси x
 

Не пробуйте это дома, детки!

Что означает косая черта (/) в списке параметров функции?

Косая черта в списке аргументов функции означает, что параметры до
это только позиционное.Только позиционные параметры - это параметры без
внешне используемое имя. При вызове функции, которая принимает только позиционные
параметры, аргументы сопоставляются с параметрами исключительно на основе их положения.
Например, divmod () - это функция, которая принимает только позиционные
параметры. Его документация выглядит так:

 >>> справка (divmod)
Справка по встроенной функции divmod во встроенных модулях:

divmod (х, у, /)
    Вернуть кортеж (x // y, x% y). Инвариант: div * y + mod == x.

Косая черта в конце списка параметров означает, что оба параметра
только позиционный. Таким образом, вызов divmod () с аргументами ключевого слова приведет к
к ошибке:

 >>> divmod (x = 3, y = 4)
Отслеживание (последний вызов последний):
  Файл "", строка 1, в 
TypeError: divmod () не принимает аргументов ключевого слова
 

Как указать шестнадцатеричные и восьмеричные целые числа?

Чтобы указать восьмеричную цифру, поставьте перед восьмеричным значением ноль, а затем нижний
или заглавная буква «о».Например, чтобы установить для переменной «а» восьмеричное значение «10»
(8 в десятичной системе), введите:

В шестнадцатеричной системе счисления так же просто. Просто поставьте перед шестнадцатеричным числом ноль,
а затем букву «x» в нижнем или верхнем регистре. Шестнадцатеричные цифры можно указывать в нижнем регистре.
или в верхнем регистре. Например, в интерпретаторе Python:

 >>> a = 0xa5
>>> а
165
>>> b = 0XB2
>>> б
178
 

Почему -22 // 10 возвращает -3?

Это в первую очередь вызвано желанием, чтобы i% j имели тот же знак, что и j .Если вы этого хотите, а также хотите:

 я == (я // j) * j + (я% j)
 

, то целочисленное деление должно вернуть пол. C также требует, чтобы это удостоверение
удерживайте, а затем компиляторы, которые усекают i // j , должны заставить i% j иметь
тот же знак, что и i .

Существует несколько реальных вариантов использования для i% j , когда значение j отрицательное. Когда j
положительный, их много, и практически во всех из них он более полезен для
i% j должно быть > = 0 .Если часы показывают 10 сейчас, что они говорят 200 часов
назад? -190% 12 == 2 полезно; -190% 12 == -10 - это ошибка, ожидающая
кусать.

Как преобразовать строку в число?

Для целых чисел используйте встроенный конструктор типа int () , например int ('144')
== 144
. Точно так же float () преобразуется в числа с плавающей запятой,
например с плавающей запятой ('144') == 144.0 .

По умолчанию они интерпретируют число как десятичное, так что int ('0144') ==
144
верно, а int ('0x144') вызывает ValueError . int (строка,
base)
принимает базу для преобразования в качестве второго необязательного аргумента, поэтому int (
'0x144', 16) == 324
. Если база указана как 0, число интерпретируется
используя правила Python: ведущий «0o» указывает на восьмеричное, а «0x» - на шестнадцатеричный
количество.

Не используйте встроенную функцию eval () , если все, что вам нужно, это преобразовать
строки в числа. eval () будет значительно медленнее и представляет
угроза безопасности: кто-то может передать вам выражение Python, которое может иметь
нежелательные побочные эффекты.Например, кто-то мог пройти
__import __ ('os'). System ("rm -rf $ HOME") , который сотрет ваш дом
каталог.

eval () также имеет эффект интерпретации чисел как выражений Python,
так что, например, eval ('09 ') дает синтаксическую ошибку, потому что Python не позволяет
ведущий «0» в десятичном числе (кроме «0»).

Как изменить строку на месте?

Вы не можете, потому что строки неизменяемы. В большинстве ситуаций вам следует
просто создайте новую строку из различных частей, которые вы хотите собрать
это из.Однако, если вам нужен объект с возможностью изменения на месте
данные Unicode, попробуйте использовать объект io.StringIO или массив
модуль:

 >>> import io
>>> s = "Привет, мир"
>>> sio = io.StringIO (s)
>>> sio.getvalue ()
'Привет, мир'
>>> sio.seek (7)
7
>>> sio.write («туда!»)
6
>>> sio.getvalue ()
'Привет!'

>>> импортный массив
>>> a = array.array ('u', s)
>>> print (а)
array ('u', 'Привет, мир')
>>> а [0] = 'у'
>>> print (а)
array ('u', 'yello, world')
>>> а.туникод ()
'yello, world'
 

Как использовать строки для вызова функций / методов?

Существуют разные техники.

  • Лучше всего использовать словарь, который отображает строки в функции. Главная
    Преимущество этого метода в том, что строки не должны совпадать с именами
    функций. Это также основной метод, используемый для имитации дела.
    построить:

     def a ():
        проходить
    
    def b ():
        проходить
    
    dispatch = {'go': a, 'stop': b} # Обратите внимание на отсутствие скобок для функций
    
    dispatch [get_input ()] () # Обратите внимание на конечные скобки для вызова функции
     
  • Используйте встроенную функцию getattr () :

     import foo
    getattr (фу, 'бар') ()
     

    Обратите внимание, что getattr () работает с любым объектом, включая классы, класс
    экземпляры, модули и так далее.

    Используется в нескольких местах стандартной библиотеки, например:

     класс Foo:
        def do_foo (сам):
            ...
    
        def do_bar (сам):
            ...
    
    f = getattr (foo_instance, 'do_' + имя операции)
    f ()
     
  • Используйте locals () для разрешения имени функции:

     def myFunc ():
        print ("привет")
    
    fname = "myFunc"
    
    f = locals () [fname]
    f ()
     

Есть ли аналог Perl chomp () для удаления завершающих символов новой строки из строк?

Можно использовать S.rstrip ("\ r \ n") , чтобы удалить все вхождения любой строки
терминатор с конца строки S без удаления других завершающих
пробел. Если строка S представляет более одной строки, с несколькими
пустые строки в конце, терминаторы для всех пустых строк будут
удалено:

 >>> lines = ("строка 1 \ r \ n"
... "\ r \ n"
... "\ r \ n")
>>> lines.rstrip ("\ n \ r")
'строка 1 '
 

Так как это обычно требуется только при чтении текста по одной строке за раз, используйте
С.rstrip () этот способ работает хорошо.

Есть ли эквивалент scanf () или sscanf ()?

Не как таковой.

Для простого синтаксического анализа ввода самый простой подход - обычно разбить строку на
слова, разделенные пробелами, с использованием метода строковых объектов split ()
а затем преобразовать десятичные строки в числовые значения с помощью int () или
поплавок () . split () поддерживает дополнительный полезный параметр «sep».
если в строке используется что-то другое, кроме пробела, в качестве разделителя.

Для более сложного синтаксического анализа ввода более эффективны регулярные выражения.
чем C sscanf () и лучше подходит для этой задачи.

Как преобразовать кортежи в списки?

Конструктор типа tuple (seq) преобразует любую последовательность (фактически, любую
iterable) в кортеж с теми же элементами в том же порядке.

Например, кортеж ([1, 2, 3]) дает (1, 2, 3) и кортеж ('abc')
дает ('a', 'b', 'c') .Если аргумент является кортежем, он не делает копию
но возвращает тот же объект, поэтому дешево вызвать tuple () , когда вы
не уверены, что объект уже является кортежем.

Конструктор типа list (seq) преобразует любую последовательность или итерацию в список
с теми же предметами в том же порядке. Например, list ((1, 2, 3)) возвращает
[1, 2, 3] и list ('abc') дает ['a', 'b', 'c'] . Если аргумент
является списком, он делает копию точно так же, как seq [:] .

Что такое отрицательный индекс?

последовательности Python индексируются положительными и отрицательными числами. Для
положительные числа 0 - это первый индекс, 1 - второй индекс и так далее. Для
отрицательные индексы -1 - последний индекс, -2 - предпоследний (предпоследний)
index и так далее. Считайте seq [-n] тем же, что и seq [len (seq) -n] .

Использование отрицательных индексов может быть очень удобным. Например, S [: - 1] - это все
строка, за исключением ее последнего символа, который полезен для удаления
завершающий символ новой строки из строки.

Как удалить дубликаты из списка?

См. В Поваренной книге Python подробное обсуждение многих способов сделать это:

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

, если мой список:
    mylist.sort ()
    last = mylist [-1]
    для i в диапазоне (len (mylist) -2, -1, -1):
        if last == mylist [i]:
            del mylist [я]
        еще:
            last = mylist [i]
 

Если все элементы списка могут использоваться в качестве ключей набора (т.е. они все
hashable) это часто быстрее

 mylist = список (набор (мой список))
 

Преобразует список в набор, тем самым удаляя дубликаты, а затем обратно
в список.

Как удалить несколько элементов из списка

Как и при удалении дубликатов, явная итерация в обратном порядке с
условие удаления - одна из возможностей. Однако так проще и быстрее
использовать замену среза с неявной или явной итерацией вперед.
Вот три варианта.:

 mylist [:] = фильтр (keep_function, mylist)
mylist [:] = (x вместо x в моем списке, если keep_condition)
mylist [:] = [x вместо x в моем списке, если keep_condition]
 

Понимание списка может быть самым быстрым.

Как создать массив в Python?

Используйте список:

 ["это", 1, "есть", "an", "массив"]
 

Списки эквивалентны массивам C или Pascal по своей временной сложности; Главная
разница в том, что список Python может содержать объекты самых разных типов.

Модуль array также предоставляет методы для создания массивов фиксированных типов.
с компактными представлениями, но они индексируются медленнее, чем списки. Также
обратите внимание, что числовые расширения и другие определяют структуры, подобные массиву, с
также различные характеристики.

Чтобы получить связанные списки в стиле Lisp, вы можете эмулировать cons-ячейки с помощью кортежей:

 lisp_list = ("нравится", ("это", ("пример", Нет)))
 

Если требуется изменчивость, вы можете использовать списки вместо кортежей.Здесь
аналог машины lisp - lisp_list [0] а аналог cdr -
lisp_list [1] . Делайте это только в том случае, если уверены, что вам это действительно нужно, потому что это
обычно намного медленнее, чем при использовании списков Python.

Как создать многомерный список?

Вы, наверное, пробовали сделать многомерный массив вот так:

Выглядит правильно, если распечатать:

 >>> А
[[Нет, Нет], [Нет, Нет], [Нет, Нет]]
 

Но когда вы присваиваете значение, оно появляется в нескольких местах:

 >>> A [0] [0] = 5
>>> А
[[5, Нет], [5, Нет], [5, Нет]]
 

Причина в том, что репликация списка с * не создает копии, а только
создает ссылки на существующие объекты. * 3 создает список
содержащий 3 ссылки на один и тот же список длиной два. Изменения в одной строке будут
показывать во всех строках, что почти наверняка не то, что вам нужно.

Предлагаемый подход состоит в том, чтобы сначала создать список желаемой длины, а затем
заполните каждый элемент вновь созданным списком:

 A = [Нет] * 3
для i в диапазоне (3):
    A [i] = [Нет] * 2
 

Это генерирует список, содержащий 3 разных списка длиной два. Вы также можете
используйте понимание списка:

 ш, в = 2, 3
A = [[Нет] * w для i в диапазоне (h)]
 

Или вы можете использовать расширение, которое предоставляет тип данных матрица; NumPy - самый известный.

Почему a_tuple [i] + = [‘item’] вызывает исключение, когда добавление работает?

Это связано с тем, что расширенное присваивание
операторы присваивания операторов, и разница между изменяемыми и
неизменяемые объекты в Python.

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

Если вы написали:

 >>> a_tuple = (1, 2)
>>> a_tuple [0] + = 1
Отслеживание (последний вызов последний):
   ...
TypeError: объект 'tuple' не поддерживает назначение элементов
 

Причина исключения должна быть понятна сразу: 1 добавлено в
объект a_tuple [0] указывает на ( 1 ), создавая объект результата, 2 ,
но когда мы пытаемся присвоить результат вычисления 2 элементу
0 кортежа, мы получаем ошибку, потому что не можем изменить элемент
кортеж указывает на.

Под обложками то, что делает этот оператор расширенного присваивания,
примерно это:

 >>> результат = a_tuple [0] + 1
>>> a_tuple [0] = результат
Отслеживание (последний вызов последний):
  ...
TypeError: объект 'tuple' не поддерживает назначение элементов
 

Это часть операции присваивания, которая вызывает ошибку, поскольку
кортеж неизменен.

Когда вы пишете что-то вроде:

 >>> a_tuple = (['foo'], 'bar')
>>> a_tuple [0] + = ['элемент']
Отслеживание (последний вызов последний):
  ...
TypeError: объект 'tuple' не поддерживает назначение элементов
 

Исключение несколько удивительнее, и еще более удивительным является тот факт, что
что даже несмотря на то, что произошла ошибка, приложение работало:

 >>> a_tuple [0]
['фу', 'элемент']
 

Чтобы понять, почему это происходит, вам нужно знать, что (а) если объект реализует
__iadd__ магический метод, он вызывается при расширенном назначении + =
выполняется, и его возвращаемое значение используется в операторе присваивания;
и (b) для списков __iadd__ эквивалентно вызову , продлите в списке.
и возврат списка.Вот почему мы говорим, что для списков + = является
«Стенография» для list.extend :

 >>> a_list = []
>>> a_list + = [1]
>>> a_list
[1]
 

Это эквивалент:

 >>> результат = a_list .__ iadd __ ([1])
>>> a_list = результат
 

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

Таким образом, в нашем примере с кортежем то, что происходит, эквивалентно:

 >>> result = a_tuple [0] .__ iadd __ (['элемент'])
>>> a_tuple [0] = результат
Отслеживание (последний вызов последний):
  ...
TypeError: объект 'tuple' не поддерживает назначение элементов
 

__iadd__ завершается успешно, и, таким образом, список расширяется, но даже если
Результат указывает на тот же объект, на который уже указывает a_tuple [0] ,
это последнее присвоение по-прежнему приводит к ошибке, потому что кортежи неизменяемы.

Как отсортировать один список по значениям из другого списка?

Объедините их в итератор кортежей, отсортируйте полученный список, а затем выберите
из нужного вам элемента.

 >>> list1 = ["что", "я", "сортировка", "по"]
>>> list2 = ["что-то", "еще", "в", "сортировать"]
>>> пары = zip (список1, список2)
>>> пары = отсортированные (пары)
>>> пары
[("Я", "еще"), ("по", "сортировать"), ("сортировка", "по"), ("что", "что-то")]
>>> result = [x [1] для x в парах]
>>> результат
['else', 'sort', 'to', 'что-то']
 

Что такое класс?

Класс - это особый тип объекта, созданный при выполнении оператора класса.Объекты класса используются в качестве шаблонов для создания экземпляров объектов, которые воплощают
как данные (атрибуты), так и код (методы), относящиеся к типу данных.

Класс может быть основан на одном или нескольких других классах, называемых его базовым классом (ами). Это
затем наследует атрибуты и методы своих базовых классов. Это позволяет
объектная модель, которая будет последовательно уточняться путем наследования. У вас может быть
общий класс Mailbox , который предоставляет базовые методы доступа для почтового ящика,
и подклассы, такие как MboxMailbox , MaildirMailbox , OutlookMailbox
которые обрабатывают различные специфические форматы почтовых ящиков.

Что такое метод?

Метод - это функция некоторого объекта x , который вы обычно вызываете как
x.name (аргументы ...) . Методы определяются как функции внутри класса
определение:

 класс C:
    def meth (self, arg):
        вернуть arg * 2 + self.attribute
 

Как проверить, является ли объект экземпляром данного класса или его подклассом?

Используйте встроенную функцию isinstance (obj, cls) . Вы можете проверить, есть ли у объекта
является экземпляром любого из нескольких классов, предоставляя кортеж вместо
одноклассник, эл.грамм. isinstance (obj, (class1, class2, ...)) , а также может
проверьте, является ли объект одним из встроенных типов Python, например
isinstance (obj, str) или isinstance (obj, (int, float, complex)) .

Обратите внимание, что isinstance () также проверяет виртуальное наследование от
абстрактный базовый класс. Таким образом, тест вернет True для
зарегистрированный класс, даже если он не унаследовал прямо или косвенно. К
тест на «истинное наследование», просканируйте MRO класса:

 из коллекций.abc import Mapping

класс P:
     проходить

класс C (P):
    проходить

Mapping.register (P)
 
 >>> c = C ()
>>> isinstance (c, C) # прямой
Правда
>>> isinstance (c, P) # косвенный
Правда
>>> isinstance (c, Mapping) # виртуальный
Правда

# Актуальная цепочка наследования
>>> введите (c) .__ mro__
(<класс 'C'>, <класс 'P'>, <класс 'объект'>)

# Тест на "истинное наследование"
>>> Отображение в типе (c) .__ mro__
Ложь
 

Обратите внимание, что большинство программ не используют isinstance () в пользовательских классах.
очень часто.Если вы сами разрабатываете классы, более подходящий
объектно-ориентированный стиль заключается в определении методов в классах, которые инкапсулируют
конкретное поведение, вместо проверки класса объекта и выполнения
разные вещи в зависимости от того, к какому классу это относится. Например, если у вас есть функция
что-то делает:

 поиск def (obj):
    если isinstance (obj, Mailbox):
        ... # код для поиска в почтовом ящике
    elif isinstance (объект, документ):
        ... # код для поиска в документе
    Элиф...
 

Лучшим подходом является определение метода search () для всех классов и просто
позвони:

Почтовый ящик класса

:
    def search (self):
        ... # код для поиска в почтовом ящике

класс Document:
    def поиск (сам):
        ... # код для поиска в документе

obj.search ()
 

Что такое делегирование?

Делегирование - это объектно-ориентированный метод (также называемый шаблоном проектирования).
Допустим, у вас есть объект x , и вы хотите изменить поведение только одного
его методов.Вы можете создать новый класс, который предоставляет новую реализацию
метода, который вы хотите изменить, и делегирует все остальные методы
соответствующий метод x .

Программисты

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

 класс UpperOut:

    def __init __ (self, outfile):
        self._outfile = outfile

    def write (self, s):
        себя._outfile.write (s.upper ())

    def __getattr __ (я, имя):
        вернуть getattr (self._outfile, имя)
 

Здесь класс UpperOut переопределяет метод write () для преобразования
строку аргумента в верхний регистр перед вызовом базового
self._outfile.write () метод. Все остальные методы делегированы
базовый объект self._outfile . Делегирование осуществляется через
__getattr__ метод; обратитесь к справочнику по языку
для получения дополнительной информации об управлении доступом к атрибутам.

Обратите внимание, что в более общих случаях делегирование может стать сложнее. Когда атрибуты
должен быть установлен, а также извлечен, класс должен определять __setattr __ ()
метод тоже, и он должен делать это осторожно. Базовая реализация
__setattr __ () примерно эквивалентен следующему:

 класс X:
    ...
    def __setattr __ (я, имя, значение):
        self .__ dict __ [имя] = значение
    ...
 

Большинство реализаций __setattr __ () должны модифицировать self.__dict__ хранить
локальное состояние для себя, не вызывая бесконечной рекурсии.

Как вызвать метод, определенный в базовом классе, из производного класса, который его переопределяет?

Используйте встроенную функцию super () :

 класс, производный (базовый):
    def meth (self):
        super (производное, собственное) .meth ()
 

Для версии до 3.0 вы можете использовать классические классы: Для класса
определение, такое как class Derived (Base): ... вы можете вызвать метод meth ()
определяется в Base (или одном из базовых классов Base ) как Base.мет (я,
аргументы ...)
. Здесь Base.meth - это несвязанный метод, поэтому вам нужно
предоставить аргумент self .

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

Вы можете назначить базовый класс псевдониму и унаследовать его от псевдонима. Тогда все
необходимо изменить значение, присвоенное псевдониму. Между прочим, этот трюк
также удобен, если вы хотите принимать решения динамически (например, в зависимости от наличия
ресурсов), какой базовый класс использовать.Пример:

 класс Base:
    ...

BaseAlias ​​= База

класс Derived (BaseAlias):
    ...
 

Как создать данные статического класса и методы статического класса?

Поддерживаются как статические данные, так и статические методы (в смысле C ++ или Java).
в Python.

Для статических данных просто определите атрибут класса. Чтобы присвоить новое значение
атрибут, вы должны явно использовать имя класса в назначении:

 класс C:
    count = 0 # количество раз C.__init__ называется

    def __init __ (сам):
        C.count = C.count + 1

    def getcount (self):
        вернуть C.count # или вернуть self.count
 

c.count также относится к C.count для любого c , так что isinstance (c,
C)
сохраняется, если не отменено самим c или каким-либо классом базового класса
путь поиска от c .__ class__ до C .

Осторожно: в методе языка C присваивание типа self.count = 42 создает
новый и не связанный с ним экземпляр с именем «count» в собственном dict self. Переплет
имя статических данных класса всегда должно указывать класс, будь то внутри метода или
нет:

Возможны статические методы:

 класс C:
    @staticmethod
    def static (arg1, arg2, arg3):
        # Нет параметра "self"!
        ...
 

Однако гораздо более простой способ получить эффект статического метода - это
через простую функцию уровня модуля:

 def getcount ():
    вернуть C.считать
 

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

Как я могу перегрузить конструкторы (или методы) в Python?

Этот ответ действительно применим ко всем методам, но обычно возникает вопрос
сначала в контексте конструкторов.

В C ++ вы должны написать

 класс C {
    C () {cout << "Нет аргументов \ n"; }
    C (int i) {cout << "Аргумент:" << i << "\ n"; }
}
 

В Python вам нужно написать единственный конструктор, который улавливает все случаи, используя
аргументы по умолчанию.Например:

 класс C:
    def __init __ (self, i = None):
        если я Нет:
            print ("Без аргументов")
        еще:
            print ("Аргумент равен", i)
 

Это не полностью эквивалентно, но на практике достаточно близко.

Вы также можете попробовать список аргументов переменной длины, например

 def __init __ (self, * args):
    ...
 

Тот же подход работает для всех определений методов.

Я пытаюсь использовать __spam и получаю сообщение об ошибке _SomeClassName__spam.

Имена переменных с двойным подчеркиванием в начале «искажены» для упрощения
но эффективный способ определения частных переменных класса. Любой идентификатор формы
__spam (минимум два символа подчеркивания в начале и не более одного символа подчеркивания в конце)
текстуально заменяется на _classname__spam , где имя класса - это
имя текущего класса без начальных подчеркиваний.

Это не гарантирует конфиденциальность: посторонний пользователь по-прежнему может преднамеренно получить доступ
атрибут «_classname__spam», а частные значения видны в
__dict__ .Многие программисты Python никогда не утруждают себя использованием закрытых переменных.
имена вообще.

Мой класс определяет __del__, но он не вызывается, когда я удаляю объект.

Для этого есть несколько возможных причин.

Оператор del не обязательно вызывает __del __ () - это просто
уменьшает счетчик ссылок объекта, и если он достигает нуля
Вызывается __del __ () .

Если ваши структуры данных содержат циклические ссылки (например, дерево, в котором каждый дочерний элемент имеет
родительская ссылка, и у каждого родителя есть список дочерних элементов) количество ссылок
никогда не вернется к нулю.Время от времени Python запускает алгоритм для обнаружения
таких циклов, но сборщик мусора может запускаться через некоторое время после последнего
ссылка на вашу структуру данных исчезает, поэтому ваш метод __del __ () может быть
позвонили в неудобное и случайное время. Это неудобно, если вы пытаетесь
воспроизвести проблему. Хуже того, порядок, в котором объект __del __ ()
методы выполняются произвольно. Вы можете запустить gc.collect () , чтобы
коллекции, но - это патологических случая, когда предметы никогда не будут
собраны.

Несмотря на сборщик циклов, все же неплохо определить явный
close () для объектов, которые будут вызываться всякий раз, когда вы закончите с ними. В
Затем метод close () может удалить атрибуты, относящиеся к подобъектам. Не
вызовите __del __ () напрямую - __del __ () должен вызвать close () и
close () должен убедиться, что его можно вызывать более одного раза для одного и того же
объект.

Другой способ избежать циклических ссылок - использовать модуль weakref ,
что позволяет указывать на объекты без увеличения их счетчика ссылок.Например, древовидные структуры данных должны использовать слабые ссылки для своих родительских
и ссылки на братьев и сестер (если они им нужны!).

Наконец, если ваш метод __del __ () вызывает исключение, предупреждающее сообщение
печатается на sys.stderr .

Почему результат

id () кажется не уникальным?

Встроенная функция id () возвращает целое число, которое гарантированно будет уникальным в течение
время жизни объекта. Поскольку в CPython это память объекта
адреса, часто бывает, что после удаления объекта из памяти
следующий только что созданный объект размещается в той же позиции в памяти.Этот
иллюстрируется этим примером:

 >>> id (1000)
132
>>> id (2000)
132
 

Два идентификатора принадлежат разным целочисленным объектам, созданным ранее, и
удаляется сразу после выполнения вызова id () . Чтобы убедиться, что
объекты, идентификатор которых вы хотите изучить, все еще живы, создайте еще одну ссылку
до объекта:

 >>> а = 1000; b = 2000
>>> id (а)
132
>>> id (b)
138

Когда я могу положиться на тесты идентичности с оператором

is ?

- это оператор , проверяющий идентичность объекта.Тест a is b is
эквивалент id (a) == id (b) .

Самым важным свойством проверки идентичности является то, что объект всегда
идентично самому себе, a - это , всегда возвращает True . Идентификационные тесты
обычно быстрее, чем тесты на равенство. И в отличие от тестов на равенство, тесты идентичности
гарантированно возвращают логическое значение Истина или Ложь .

Однако тесты идентичности могут только заменять тесты на равенство, когда
идентичность объекта гарантируется.Как правило, есть три обстоятельства, когда
идентичность гарантирована:

1) Назначения создают новые имена, но не изменяют идентичность объекта. После
присвоение новый = старый , гарантируется, что новый - старый .

2) Помещение объекта в контейнер, в котором хранятся ссылки на объекты, не
изменить идентичность объекта. После присвоения списка s [0] = x , это
Гарантировано, что s [0] равно x .

3) Если объект синглтон, это означает, что только один экземпляр этого объекта
может существовать.После присвоений a = Нет и b = Нет , это
Гарантировано, что a - это b , потому что None - одноэлементный.

В большинстве других обстоятельств тесты идентичности нецелесообразны, а тесты на равенство
являются предпочтительными. В частности, не следует использовать тесты личности для проверки
такие константы, как int и str , которые не гарантируются
одиночные:

 >>> а = 1000
>>> b = 500
>>> c = b + 500
>>> а есть с
Ложь

>>> a = 'Python'
>>> b = 'Py'
>>> c = b + 'тон'
>>> а есть с
Ложь
 

Аналогичным образом, новые экземпляры изменяемых контейнеров никогда не идентичны:

 >>> a = []
>>> b = []
>>> а это б
Ложь
 

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

1) В соответствии с рекомендациями PEP 8 , проверка личности является предпочтительным способом проверки
для Нет .Это читается как простой английский в коде и позволяет избежать путаницы с
другие объекты, которые могут иметь логические значения, которые оцениваются как ложные.

2) Обнаружение необязательных аргументов может быть затруднительным, если Нет является допустимым входом
ценить. В таких ситуациях вы можете создать одноэлементный дозорный объект.
гарантированно отличаться от других объектов. Например, вот как
реализовать метод, который ведет себя как dict.pop () :

 _sentinel = объект ()

def pop (self, key, default = _sentinel):
    если ввести self:
        значение = сам [ключ]
        дель сам [ключ]
        возвращаемое значение
    если по умолчанию _sentinel:
        поднять KeyError (ключ)
    вернуть по умолчанию
 

3) В реализациях контейнеров иногда требуется дополнять тесты на равенство с помощью
тесты личности.Это предохраняет код от путаницы с такими объектами, как
float ('NaN') , которые не равны сами себе.

Например, вот реализация
collections.abc.Sequence .__ содержит __ () :

 def __contains __ (self, value):
    для v в себе:
        если v - значение или v == значение:
            вернуть True
    вернуть ложь
 

Как подкласс может контролировать, какие данные хранятся в неизменяемом экземпляре?

При создании подкласса неизменяемого типа переопределите метод __new __ ()
вместо метода __init __ () .Последний запускает только после и
создан экземпляр, но уже слишком поздно для изменения данных в неизменяемом
пример.

Все эти неизменяемые классы имеют другую сигнатуру, чем их
родительский класс:

 с даты импорта даты и времени

class FirstOfMonthDate (дата):
    «Всегда выбирайте первый день месяца»
    def __new __ (cls, год, месяц, день):
        return super () .__ new __ (cls, год, месяц, 1)

класс NamedInt (число):
    «Разрешить текстовые имена для некоторых номеров»
    xlat = {'ноль': 0, 'один': 1, 'десять': 10}
    def __new __ (cls, значение):
        значение = cls.xlat.get (значение, значение)
        return super () .__ new __ (cls, значение)

класс TitleStr (str):
    "Преобразовать str в имя, подходящее для пути URL"
    def __new __ (cls, s):
        s = s.lower (). replace ('', '-')
        s = '' .join ([c вместо c в s, если c.isalnum () или c == '-'])
        вернуть super () .__ new __ (cls, s)
 

Классы можно использовать так:

 >>> FirstOfMonthDate (2012, 2, 14)
FirstOfMonthDate (2012, 2, 1)
>>> NamedInt ('десять')
10
>>> NamedInt (20)
20
>>> TitleStr ('Блог: почему Python Rocks')
'блог-почему-питон-камни'
 

Как создать файл.pyc файл?

Когда модуль импортируется впервые (или когда исходный файл
изменен с момента создания текущего скомпилированного файла) файл .pyc , содержащий
скомпилированный код должен быть создан в подкаталоге __pycache__ каталога
каталог, содержащий файл .py . Файл .pyc будет иметь
имя файла, которое начинается с того же имени, что и файл .py , и заканчивается на
.pyc , со средним компонентом, который зависит от конкретного python
двоичный файл, который его создал.(Подробнее см. PEP 3147 .)

Одна из причин, по которой файл .pyc не может быть создан, - это проблема с разрешениями
с каталогом, содержащим исходный файл, что означает, что __pycache__
подкаталог не может быть создан. Это может произойти, например, если вы разрабатываете как
один пользователь, но запускается от имени другого, например, если вы тестируете с помощью веб-сервера.

Если не установлена ​​переменная среды PYTHONDONTWRITEBYTECODE ,
создание файла .pyc происходит автоматически, если вы импортируете модуль и Python
имеет возможность (разрешения, свободное место и т. д.) для создания __pycache__
подкаталог и запишите скомпилированный модуль в этот подкаталог.

Запуск Python в скрипте верхнего уровня не считается импортом и не
.pyc будет создан. Например, если у вас есть модуль верхнего уровня
foo.py , который импортирует другой модуль xyz.py , когда вы запускаете foo (by
набрав python foo.py в качестве команды оболочки), будет создан .pyc для
xyz , потому что xyz импортирован, но файл .pyc не будет создан для
foo начиная с foo.py не импортируется.

Если вам нужно создать файл .pyc для foo , то есть создать
.pyc для модуля, который не импортирован - вы можете, используя
py_compile и компилируют все модулей.

Модуль py_compile может вручную скомпилировать любой модуль. Один из способов - использовать
функция compile () в этом модуле интерактивно:

 >>> импорт py_compile
>>> py_compile.компилировать ('foo.py')
 

Это приведет к записи .pyc в подкаталог __pycache__ в том же
location как foo.py (или вы можете переопределить это с помощью необязательного параметра
, файл ).

Вы также можете автоматически компилировать все файлы в каталоге или каталогах, используя
модуль compileall . Вы можете сделать это из командной строки, запустив
compileall.py и указание пути к каталогу, содержащему файлы Python
для компиляции:

Как узнать текущее имя модуля?

Модуль может узнать свое собственное имя модуля, посмотрев на предопределенный глобальный
переменная __name__ .Если это значение '__main__' , программа
работает как скрипт. Многие модули, которые обычно используются, также импортируя их
предоставить интерфейс командной строки или самопроверку и выполнять только этот код
после проверки __name__ :

 def main ():
    print ('Выполняется тест ...')
    ...

если __name__ == '__main__':
    главный()
 

Как я могу иметь модули, которые взаимно импортируют друг друга?

Предположим, у вас есть следующие модули:

foo.py:

 из бара импорта bar_var
foo_var = 1
 

бар.py:

 из foo import foo_var
bar_var = 2
 

Проблема в том, что интерпретатор выполнит следующие шаги:

  • основной импорт foo

  • Создаются пустые глобальные объекты для foo

  • foo компилируется и начинает выполнение

  • foo импорт бар

  • Создаются пустые глобальные объекты для бара

  • bar компилируется и начинает выполняться

  • bar импортирует foo (что невозможно, поскольку уже существует модуль с именем foo)

  • бар.foo_var = foo.foo_var

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

То же самое происходит, когда вы используете import foo , а затем пытаетесь получить доступ
foo.foo_var в глобальном коде.

Есть (как минимум) три возможных решения этой проблемы.

Гвидо ван Россум рекомендует избегать любого использования из import... ,
и размещение всего кода внутри функций. Инициализации глобальных переменных и
переменные класса должны использовать только константы или встроенные функции. Это означает
все из импортированного модуля обозначается как <модуль>. <имя> .

Джим Роскинд предлагает выполнить шаги в следующем порядке в каждом модуле:

  • экспорта (глобальные объекты, функции и классы, которым не требуется импортированная база
    классов)

  • импорт выписки

  • активный код (включая глобальные переменные, которые инициализируются из импортированных значений).

ван Россуму не очень нравится такой подход, потому что импорт появляется в
странное место, но оно работает.

Маттиас Урликс рекомендует реструктурировать код так, чтобы рекурсивный импорт
в первую очередь не нужно.

Эти решения не исключают друг друга.

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

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

 импорт importlib
импортировать имя мода
importlib.reload (имя мода)
 

Предупреждение: этот метод не на 100% надежен. В частности, модули
содержащие утверждения типа

 из имени мода import some_objects
 

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

 >>> импорт importlib
>>> import cls
>>> c = cls.C () # Создать экземпляр C
>>> importlib.reload (cls)
<модуль cls из cls.py>
>>> isinstance (c, cls.C) # isinstance is false?!?
Ложь
 

Суть проблемы станет ясной, если вы распечатаете «идентичность»
объекты класса:

 >>> шестнадцатеричный (id (c.__класс__))
'0x7352a0'
>>> шестнадцатеричный (идентификатор (cls.C))
'0x4198d0'
 

Модули среды

Что такое модули среды?

Обычно пользователи инициализируют свою среду при входе в систему через
установка информации о среде для каждого приложения, на которое они будут ссылаться
во время сеанса. Пакет Environment Modules - это инструмент, упрощающий
инициализации оболочки и позволяет пользователям легко изменять свою среду во время
сеанс с файлами модулей.

Каждый файл модуля содержит информацию, необходимую для настройки оболочки для
приложение.После инициализации пакета Modules среда
может быть изменен для каждого модуля с помощью команды модуля, которая
интерпретирует файлы модулей. Обычно файлы модуля указывают команду модуля
для изменения или установки переменных среды оболочки, таких как PATH, MANPATH и т. д.
файлы модулей могут совместно использоваться многими пользователями в системе, и пользователи могут иметь
свою собственную коллекцию для дополнения или замены общих файлов модулей.

Модули могут быть загружены , и выгружены, динамически
и атомарно, в
чистый мод.Поддерживаются все популярные оболочки, в том числе
баш , кш , зш , ш ,
csh , tcsh , fish , а также некоторые языки сценариев
например perl , ruby ​​, tcl , python ,
cmake и R .

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

Быстрые примеры

Вот пример загрузки модуля на машину Linux под bash.

  $ загрузка модуля gcc / 9.4
$ which gcc
/usr/local/gcc/9.4/linux-x86_64/bin/gcc  

Теперь перейдем на другую версию модуля

  $ модуль коммутатора gcc gcc / 10
$ which gcc
/usr/local/gcc/10.3/linux-x86_64/bin/gcc  

А сейчас выгрузим модуль совсем

  $ модуль выгрузки gcc
$ which gcc
gcc не найден  

Теперь мы войдем в систему на другом компьютере, используя другую оболочку (tcsh).

 % загрузка модуля gcc / 10,3
% which gcc
/usr/local/gcc/10.3/linux-aarch64/bin/gcc  

Обратите внимание, что командная строка точно такая же, но путь имеет
автоматически настроен на правильную архитектуру.

Начало работы с модулями

Загрузите последнюю версию модулей. Узнайте, как установить его в Unix или как установить в Windows. В качестве альтернативы вы можете автоматически получать и устанавливать модули с помощью предпочитаемого вами диспетчера пакетов, поскольку модули среды широко доступны.Обзор новых функций, представленных в каждой версии, доступен в Руководстве по новым функциям. Примечания к выпуску содержат полный список изменений, добавленных в каждую версию. Документ Changes дает подробный обзор измененного поведения и новых функций между основными версиями.

Справочная страница руководства для команд module (1) и ml (1) и для сценария modulefile (4) содержит подробную информацию обо всех поддерживаемых параметрах. Книга рецептов описывает, как использовать различные функции модулей и как расширить команду модуля для достижения конкретных потребностей.Если у вас есть вопросы, комментарии или предложения по развитию для сообщества модулей, пожалуйста, прочтите руководство «ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ».

Публикации

  • Ксавье Деларюэль,
    Модули: обеспечивает динамическое изменение среды пользователя,
    FOSDEM'19 , Брюссель, 2-3 февраля 2019 г.
  • Ксавье Деларюэль,
    Модули: автоматическая и последовательная обработка зависимостей файлов модулей,
    4-е собрание пользователей EasyBuild , Лувен-ла-Нев, 30 января - 1 февраля 2019 г.
  • Ксавье Деларюэль,
    Модули v4: продвижение управления пользовательской средой,
    FOSDEM'18 , Брюссель, 3-4 февраля 2018 г.
  • Ксавье Деларюэль,
    Модули v4: Да, проект Environment Modules не умер,
    3-е собрание пользователей EasyBuild , Амстердам, 30 января - 1 февраля 2018 г.
  • Брок Пален и Джефф Скуайрес разговаривают с Р. К. Оуэном,
    RCE 60: Модули,
    Подкаст Исследования, вычисления и инженерия (RCE) ,
    20 сентября 2011 г.
  • Эрих Уитни, Марк Спраг,
    Перетащите свою дизайнерскую среду в 90-е с модулями!
    Группа пользователей Synopsys , Бостон, Массачусетс, 2001.
  • Джон Л. Фурлани, Питер У. Осел,
    Абстрагируйтесь с помощью модулей,
    Труды Десятой конференции по администрированию крупных систем установки (LISA X) , стр. 193-204,
    Чикаго, Иллинойс, 29 сентября - 4 октября 1996 г.
  • Ричард Эллинг, Мэтью Лонг,
    user-setup: система для настраиваемой конфигурации пользовательских сред или помощи пользователям в помощи самим себе,
    Труды Шестой конференции системного администрирования (LISA VI) , стр.215-223, г.
    Лонг-Бич, Калифорния, 19-23 октября 1992 г.
  • Джон Л. Фурлани,
    Модули: обеспечение гибкой пользовательской среды,
    Труды пятой конференции по администрированию крупных систем установки (LISA V) , стр. 141-152,
    Сан-Диего, Калифорния, 30 сентября - 3 октября 1991 г.

Сопутствующие инструменты

EasyBuild - это программная сборка и
фреймворк для установки, который позволяет управлять (научным) программным обеспечением на
Системы высокопроизводительных вычислений (HPC) эффективным способом.

Spack - пакетный менеджер для суперкомпьютеров,
Linux и macOS. Это упрощает установку научного программного обеспечения. Spack не
привязан к определенному языку; вы можете создать программный стек на Python или R,
ссылка на библиотеки, написанные на C, C ++ или Fortran, и простая замена компиляторов
или нацелены на конкретные микроархитектуры.

Env2 - это сценарий Perl
для преобразования переменных среды между языками сценариев. Например,
преобразовать сценарий установки csh в bash или наоборот.Поддерживает bash,
csh , ksh , модуль, cmd , perl , plist ,
sh , tclsh , tcsh , vim , yaml
и zsh . Этот пакет написан и поддерживается Дэвидом К. Блэком.

Коллекции программного обеспечения - это
Проект Red Hat, позволяющий создавать и одновременно устанавливать несколько
Версии RPM одних и тех же компонентов в вашей системе, не влияя на
системные версии пакетов RPM, установленных из вашего дистрибутива.Один раз
установленная коллекция программного обеспечения включается с помощью команды scl
который полагается на модули для настройки пользовательской среды.

Эталонные установки

.

Добавить комментарий

Ваш адрес email не будет опубликован.