Как использовать данные модуля Fortran 90

предположим, у вас есть модуль Fortran 90, содержащий много переменных, функций и подпрограмм. В USE заявление, которому вы следуете:

  1. явно объявлять переменные/функции/подпрограммы вы используете с , only : синтаксис, например:USE [module_name], only : variable1, variable2, ...?
  2. вставить одеяло USE [module_name]?

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

вот пример:

module constants
  implicit none
  real, parameter :: PI=3.14
  real, parameter :: E=2.71828183
  integer, parameter :: answer=42
  real, parameter :: earthRadiusMeters=6.38e6
end module constants

program test
! Option #1:  blanket "use constants"
!  use constants
! Option #2:  Specify EACH variable you wish to use.
  use constants, only : PI,E,answer,earthRadiusMeters
  implicit none

  write(6,*) "Hello world.  Here are some constants:"
  write(6,*) PI, &
       E, &
       answer, &
       earthRadiusInMeters
end program test

обновление Надеюсь, кто-то скажет что-то вроде "Фортран? Просто перекодируйте его в C#!" так что я могу против вас.


обновление

мне нравится ответ Тима Уиткомба, который сравнивает Fortran USE modulename С языка Python from modulename import *. Тема, которая была на переполнении стека раньше:

  • 'import module' или 'from module import'

    • в ответ Марк Родди упомянул:

      не используйте ' from module import *'. Для любой разумный большой набор кода, если вы " импортируете *", скорее всего, будете цементировать его в модуль, неспособный для удаления. Это потому, что это трудно определение используемых элементов в коде идут от "модуль", направляюсь на восток, чтобы добраться до сути. где вы думаете, что не используете импорт больше, но его чрезвычайно трудно сказать наверняка.

  • каковы хорошие эмпирические правила для импорта python?

    • ответ dbr содержит

      не делайте из X import * - это делает ваш код очень трудно понять, как вы не можете легко увидеть, где метод пришел из (из X import *; из y import *; my_func () - где находится my_func определенными?)

Итак, я склоняюсь к консенсусу явно указать все элементы, которые я использую в модуле через

USE modulename, only : var1, var2, ...

и Стефано Борини упоминает,

[если] у вас есть модуль настолько велик, что вы чувствуйте себя обязанным добавить только, это означает что ваш модуль слишком большой. Разделить его.

7 ответов


Это вопрос баланса.

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

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

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

Обновление: Fortran? просто перекодируйте его в python;)


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

после этого я стал конвертировать с помощью use...only по возможности. Я также начал собирать Python и просматривать его так же, как from modulename import *. Есть много замечательных вещей, которые дают вам модули, но я предпочитаю держать свое глобальное пространство имен под строгим контролем.


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

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

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

module basicdata
   implicit none
   ! First the data types...
   type input_data
      integer :: a, b
   end type input_data
   type init_data
      integer :: b, c
   end type init_data

   ! ... then declare the data
   type(input_data) :: input
   type(init_data) :: init
end module basicdata

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

subroutine doesstuff
   use basicdata, only : init
   ...
   q = init%b
end subroutine doesstuff

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


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


согласен с большинством ранее данных ответов,use ..., only: ... - это путь, использовать типы, когда это имеет смысл, применить python мышления как можно больше. Другое предложение-использовать соответствующие соглашения об именах в импортированном модуле вместе с private / public заявления.

например,netcdf библиотека использует nf90_<some name>, что ограничивает загрязнение пространства имен на стороне импортера.

use netcdf  ! imported names are prefixed with "nf90_"

nf90_open(...)
nf90_create(...)
nf90_get_var(...)
nf90_close(...)

аналогично ncio обертка для этой библиотеки использует nc_<some name> (nc_read, nc_write...).

главное, с такими конструкциями, где use: ..., only: ... становится менее актуальным, вам лучше контролировать пространство имен импортируемого модуля, установив соответствующий private / public атрибуты в заголовке, так что быстрый взгляд на него будет достаточным для читателей, чтобы оценить, с каким уровнем "загрязнения" они сталкиваются. Это в основном то же самое, что use ..., only: ..., но на стороне импортированного модуля-таким образом, записываться только один раз, а не при каждом импорте).

еще одна вещь: что касается объектной ориентации и python, разница, на мой взгляд, заключается в том, что fortran действительно не поощряет процедуры с привязкой к типу, отчасти потому, что это относительно новый стандарт (например, не совместим с рядом инструментов и менее рационально, это просто необычно) и потому, что он нарушает удобное поведение, такое как беспроцессная производная копия типа (type(mytype) :: t1, t2 и t2 = t1). Это означает, что вам часто приходится импортировать тип и все потенциальные процедуры с привязкой к типу, а не только класс. Это само по себе делает код fortran более подробным по сравнению с python, и практические решения, такие как соглашение об именовании префиксов, могут пригодиться.

IMO, суть в следующем: выберите свой стиль кодирования для людей, которые будут его читать (это включает в себя Ваше более позднее "я"), как учил python. Чем лучше, тем более многословным use ..., only: ... при каждом импорте, но в некоторых случаях простое соглашение об именах будет делать это (если вы достаточно дисциплинированы...).


Да, пожалуйста, используйте use module, only: .... Для большой базы кода с несколькими программистами, это делает код легче следовать всем (или просто использовать grep).

пожалуйста, не используйте include, вместо этого используйте меньший модуль. Include-это текстовая вставка исходного кода, которая не проверяется компилятором на том же уровне, что и модуль use, см.: FORTRAN: разница между INCLUDE и modules. Include вообще делает его более трудным как для людей, так и для компьютера использовать код а это значит, что его нельзя использовать. Бывший. из mpi-форума: "использование mpif.h файл include сильно не рекомендуется и может быть устаревшим в будущей версии MPI."(http://mpi-forum.org/docs/mpi-3.1/mpi31-report/node411.htm).


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

внутри файла, например, константы.для

real, parameter :: pi = 3.14
real, parameter :: g = 6.67384e-11
...


program main
    use module1, only : func1, subroutine1, func2 
    implicit none

    include 'constants.for'
    ...
end program main

отредактировано, чтобы удалить " real (4)", поскольку некоторые считают, что это плохая практика.