Wie nutzen Sie Fortran 90-Moduldaten?
-
11-09-2019 - |
Frage
Nehmen wir an, Sie haben ein Fortran 90-Modul mit viele von Variablen, Funktionen und Unterprogrammen.In deinem USE
Aussage, welcher Konvention folgen Sie:
- Deklarieren Sie explizit, welche Variablen/Funktionen/Unterprogramme Sie mit dem verwenden
, only :
Syntax, wie zUSE [module_name], only : variable1, variable2, ...
? - Legen Sie eine Decke ein
USE [module_name]
?
Einerseits die only
-Klausel macht den Code etwas ausführlicher.Es zwingt Sie jedoch dazu, sich im Code zu wiederholen und wenn Ihr Modul Folgendes enthält viele von Variablen/Funktionen/Unterprogrammen beginnen die Dinge unruhig auszusehen.
Hier ist ein Beispiel:
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
AktualisierenHoffentlich sagt jemand so etwas wie „Fortran?Codieren Sie es einfach in C# neu!“ damit ich dich ablehnen kann.
Aktualisieren
Ich mag Tim Whitcombs Antwort, das Fortrans vergleicht USE modulename
mit Pythons from modulename import *
.Ein Thema, das schon einmal auf Stack Overflow war:
„Modul importieren“ oder „aus Modulimport“
- In einer Antwort, Mark Roddy erwähnte:
Verwenden Sie nicht „from module import *“.Wenn Sie für einen angemessenen großen Code -Satz *'importieren *' importieren, zementieren Sie ihn wahrscheinlich in das Modul und können nicht entfernt werden.
- In einer Antwort, Mark Roddy erwähnte:
Was sind gute Faustregeln für Python-Importe?
- dbrs Antwort enthält
Tun Sie nicht von X -Import * - er macht Ihren Code sehr schwer zu verstehen, da Sie nicht leicht erkennen können, woher eine Methode stammt (von X Import *;von y Import *;my_func () - wo ist my_func definiert?)
- dbrs Antwort enthält
Daher neige ich zu einem Konsens, alle Elemente, die ich in einem Modul verwende, explizit anzugeben über
USE modulename, only : var1, var2, ...
Und wie Stefano Borini erwähnt,
Wenn] Sie ein so großes Modul haben, dass Sie sich nur gezwungen fühlen, nur hinzuzufügen, bedeutet dies, dass Ihr Modul zu groß ist.Teile es auf.
Lösung
Es ist eine Frage der Balance.
Wenn Sie nur ein paar Sachen aus dem Modul zu benutzen, ist es sinnvoll, wenn Sie hinzufügen, klar angeben, was Sie verwenden.
Wenn Sie eine Menge Sachen aus dem Modul verwenden, und geben wird nur durch eine Menge Sachen folgen, so macht es weniger Sinn. Sie sind im Grunde Rosinenpickerei, was Sie verwenden, aber die wahre Tatsache ist, dass Sie an diesem Modul als Ganzes abhängig sind.
Doch am Ende die beste Philosophie ist dieser: wenn Sie über Namespace Verschmutzung betroffen sind, und Sie haben ein Modul so groß, dass man sich gezwungen fühlen, nur noch hinzuzufügen, bedeutet das, dass Ihr Modul zu groß ist. Teilen Sie es.
Update: Fortran? recode es nur in Python;)
Andere Tipps
Früher habe ich nur use modulename
tun - dann, wie meine Anwendung wuchs, fand ich es immer schwieriger, die Quelle zu Funktionen finden (ohne grep zu Drehen) - einige der anderen Code um das Büro floating verwendet immer noch eine ein -subroutine-per-Datei, die ihre eigenen Probleme hat, aber es macht es viel einfacher, einen Text-Editor zu verwenden, um den Code zu bewegen und schnell aufzuspüren, was Sie brauchen.
Dies Nach der Erfahrung, ich habe ein Konvertit worden mit use
... only
wann immer möglich. Ich habe auch begonnen, Python Kommissionierung, und es auf die gleiche Weise wie from modulename import *
anzuzeigen. Es gibt eine Menge von großen Dinge, die Module, die Sie geben, aber ich ziehe meine globalen Namensraum streng kontrolliert zu halten.
Ich beantworte die Frage hier nicht genau, sondern füge nur eine andere Lösung hinzu, die ich unter bestimmten Umständen als nützlich erachtet habe, wenn Sie aus irgendeinem Grund Ihr Modul nicht aufteilen möchten und es zu Namespace-Konflikten kommt.Sie können abgeleitete Typen verwenden, um mehrere Namespaces in einem Modul zu speichern.
Wenn es eine logische Gruppierung der Variablen gibt, können Sie für jede Gruppe einen eigenen abgeleiteten Typ erstellen, eine Instanz dieses Typs im Modul speichern und dann genau die Gruppe importieren, die Sie gerade benötigen.
Kleines Beispiel:Wir haben viele Daten, von denen einige Benutzereingaben sind und andere das Ergebnis verschiedener Initialisierungen sind.
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
Wenn nun ein Unterprogramm nur Daten von verwendet init
, importieren Sie genau das:
subroutine doesstuff
use basicdata, only : init
...
q = init%b
end subroutine doesstuff
Dies ist definitiv keine universell anwendbare Lösung. Sie erhalten eine zusätzliche Ausführlichkeit durch die Syntax des abgeleiteten Typs und dann wird es natürlich kaum helfen, wenn Ihr Modul nicht dies ist basicdata
oben sortieren, aber eher a allthestuffivebeenmeaningtosortout
Vielfalt.Wie auch immer, ich hatte etwas Glück dabei, Code zu bekommen, der auf diese Weise leichter ins Gehirn passt.
Der Hauptvorteil der Nutzung, nur für mich ist, dass es mit Sachen meines globalen Namensraum verschmutzen vermeidet brauche ich nicht.
Einverstanden mit den meisten Antworten vorher gegeben, use ..., only: ...
ist die Art und Weise, Typen Gebrauch zu gehen, wenn es sinnvoll ist, gelten python denken so viel wie möglich . Ein weiterer Vorschlag ist angemessen Namenskonventionen in importierten Modul zu verwenden, zusammen mit private
/ public
Aussagen.
Zum Beispiel der netcdf
Bibliothek verwendet nf90_<some name>
, die die Namespace Verschmutzung auf der Importseite begrenzt.
use netcdf ! imported names are prefixed with "nf90_"
nf90_open(...)
nf90_create(...)
nf90_get_var(...)
nf90_close(...)
ähnlich, der ncio Wrapper zu dieser Bibliothek verwendet nc_<some name>
(nc_read
, nc_write
...) .
Wichtig ist, dass mit solchen Konstruktionen, bei denen use: ..., only: ...
weniger relevant gemacht wird, sollten Sie besser den Namensraum des importierten Moduls durch die Festlegung geeigneten private
steuern würden / public
Attribut im Header, so dass ein kurzer Blick auf es für die Leser ausreichend sein wird, die Ebene der „Verschmutzung“ beurteilen sie konfrontiert sind. Dies ist im Grunde die gleiche wie use ..., only: ...
, aber auf der Modulseite importiert -. Also nur einmal geschrieben werden, nicht bei jedem Import)
Ein weitere Sache: so weit wie Objektorientierung und Python betroffen sind, ein Unterschied in meiner Ansicht ist, dass Fortran nicht wirklich typgebundene Prozeduren, teilweise fördern, weil es ein relativ neuer Standard (zB nicht kompatibel mit a Anzahl von Werkzeugen und weniger rational, ist es nur ungewöhnlich ist) und weil es praktisch Verhalten wie Verfahren frei abgeleiteten Typ Kopie (type(mytype) :: t1, t2
und t2 = t1
) bricht. Das heißt, Sie müssen oft die Art importieren und alle Möchtegern-typgebundene Prozeduren, statt nur die Klasse. Dies allein macht Fortran Code ausführlicher im Vergleich zu Python und praktische Lösungen wie ein Präfix-Namenskonvention in handlichen kommen können.
IMO, die untere Zeile ist: wählen Sie Ihren Coding-Style für Leute, die es lesen werden (dies schließt Sie später selbst), wie von Python gelehrt. Das Beste ist die ausführlichere use ..., only: ...
bei jedem Import, aber in einigen Fällen eine einfache Namenskonvention wird es tun (wenn Sie diszipliniert genug sind ...).
Ja, bitte benutzen use module, only: ...
. Für große Code-Basen mit mehreren Programmierern, macht es den Code leichter von jedermann zu folgen (oder einfach nur benutzen grep
).
Bitte verwenden Sie nicht enthalten, ein kleineres Modul für diese stattdessen verwenden. Einschliessen ist ein Text einfügen des Quellcodes, die nicht durch den Compiler auf dem gleichen Niveau wie die Verwendung Modul aktiviert ist, finden Sie unter: Fortran: Unterschied zwischen BEINHALTEN und Modulen . Include
macht es auch schwieriger für Menschen und Computer, den Code zu verwenden, das heißt, es sollte nicht verwendet werden. Ex. von mpi-Forum: „Die Verwendung der mpif.h Include-Datei wird dringend abgeraten und kann in einer zukünftigen Version von MPI veraltet.“ ( http://mpi-forum.org/docs/mpi -3.1 / mpi31-report / node411.htm ).
Ich weiß, ich bin ein wenig spät zur Party, aber wenn man erst nach einer Reihe von Konstanten und nicht unbedingt berechneten Werte sind, können Sie wie C zu tun, und erstellen Sie eine Include-Datei:
innerhalb einer Datei, z.B. constants.for
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
Edited "real (4)" zu entfernen, wie einige denken, es schlechte Praxis ist.