你如何使用Fortran 90模块数据

Pet*_*ete 36 fortran module conventions fortran90

假设您有一个包含大量变量,函数和子例程的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
Run Code Online (Sandbox Code Playgroud)

更新 希望有人说"Fortran之类的东西?只需用C#重新编写它!" 所以我可以投票给你了.


更新

我喜欢Tim Whitcomb的答案,它将Fortran USE modulename与Python的比较from modulename import *.之前在Stack Overflow上的一个主题:

  • '导入模块'或'从模块导入'

    • Mark Roddy 在回答中提到:

      不要使用'from module import*'.对于任何合理的大型代码集,如果您'导入*',您可能会将其粘合到模块中,无法删除.这是因为很难确定代码中使用的项目来自"模块",使其向东到达您认为不再使用导入的点,但很难确定.

  • python导入有哪些好的经验法则?

    • dbr的答案包含

      不要从x import* - 它使你的代码很难理解,因为你不能轻易地看到方法的来源(来自x import*;来自y import*; my_func() - 其中my_func定义了什么?)

所以,我倾向于明确说明我在模块中使用的所有项目的共识

USE modulename, only : var1, var2, ...
Run Code Online (Sandbox Code Playgroud)

正如Stefano Borini所提到的,

[if]你有一个如此大的模块,你觉得有必要添加,这意味着你的模块太大了.拆分它.

Tim*_*omb 25

我曾经只是做use modulename- 然后,随着我的应用程序的增长,我发现找到函数的源代码越来越困难(没有转向grep) - 在办公室周围浮动的一些其他代码仍然使用一个子例程-file,它有一组自己的问题,但它使得使用文本编辑器在代码中移动并快速找到所需内容变得更加容易.

在经历了这个之后,我已经成为一个转换为使用use... only尽可能.我也开始学习Python,并以同样的方式查看它from modulename import *.模块给你带来了很多很棒的东西,但我更喜欢严格控制我的全局命名空间.


Ste*_*ini 16

这是一个平衡问题.

如果您只使用模块中的一些内容,那么只有添加ONI才有意义,以清楚地指定您正在使用的内容.

如果你使用模块中的很多东西,那么指定ONLY后会有很多东西,所以它没有多大意义.你基本上是挑选你使用的东西,但事实是你依赖于整个模块.

然而,最终的最佳理念是这样的:如果你担心名称空间污染,并且你有一个如此大的模块,你觉得有必要加入,那就意味着你的模块太大了.拆分它.

更新:Fortran?只是在python中重新编码;)

  • 这是一个有用的启发式"我的模块应该有多大?". (5认同)

小智 6

这里没有完全回答这个问题,只是抛出我在某些情况下发现有用的另一个解决方案,如果由于某种原因你不想拆分你的模块并开始获得命名空间冲突.您可以使用派生类型在一个模块中存储多个名称空间.

如果存在一些变量的逻辑分组,您可以为每个组创建自己的派生类型,在模块中存储此类型的实例,然后您只能导入您需要的组.

小例子:我们有很多数据,其中一些是用户输入,一些是杂项初始化的结果.

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
Run Code Online (Sandbox Code Playgroud)

现在,如果子程序仅使用来自的数据init,则只导入:

subroutine doesstuff
   use basicdata, only : init
   ...
   q = init%b
end subroutine doesstuff
Run Code Online (Sandbox Code Playgroud)

这绝对不是一个普遍适用的解决方案,你从派生类型语法中得到一些额外的冗长,然后如果你的模块不是basicdata上面的那种,它当然几乎没有帮助,而是更多allthestuffivebeenmeaningtosortout种类.无论如何,我已经运气好了,以这种方式获得更容易融入大脑的代码.