Self-Assessment Quiz: Fortran-Python Interoperability

Twenty questions to confirm you can wrap, call, and benchmark Fortran from Python before moving on. Aim for 16 or more. Answers and a topic map are at the end — try the whole quiz first.


Question 1

In the command f2py -c -m mykernel foo.f90, the string mykernel is: - A. the name of the Fortran source file - B. the name of the Fortran module inside the source - C. the name of the extension module you will import in Python - D. a compiler optimization level

Question 2

An extension module is: - A. a plain-text .py file of pure Python - B. a compiled shared library (.so/.pyd) that Python can import like any module - C. a Fortran module program unit - D. a Jupyter notebook

Question 3

A Fortran dummy argument declared intent(out) is presented by f2py to Python as: - A. a required input argument - B. a return value - C. an argument modified in place - D. a hidden argument

Question 4

Which NumPy dtype matches Fortran real(real64) (the book's dp)? - A. np.float32 - B. np.int64 - C. np.float64 - D. np.longdouble

Question 5

By default, a freshly created 2-D NumPy array is: - A. F-contiguous (column-major) - B. C-contiguous (row-major) - C. neither — always a copy - D. stored on the GPU

Question 6

You pass a default (C-contiguous) 2-D array to an f2py routine with an intent(in) argument. f2py: - A. refuses and raises an error - B. transposes your indices silently - C. makes an F-contiguous copy before the call — correct answer, but a per-call cost - D. corrupts the data

Question 7

The one-keyword cure for the silent copy in Question 6 is to create the array with: - A. dtype=object - B. order='F' - C. copy=False - D. ndmin=2

Question 8

True or false: "f2py transposes your array, so a[i, j] in Python becomes u(j, i) in Fortran." Justify.

Question 9

A 1-D NumPy array is: - A. only C-contiguous - B. only F-contiguous - C. both C- and F-contiguous - D. never contiguous

Question 10

You pass a C-contiguous array to an f2py routine whose argument is intent(inout). The most likely result: - A. it works, in place, silently - B. f2py raises a ValueError about the array not being Fortran-contiguous - C. it transposes the array - D. it converts the array to a Python list

Question 11

ctypes and cffi can call Fortran only if the Fortran procedure has: - A. implicit none - B. intent on every argument - C. the bind(c) attribute - D. an allocatable result

Question 12

Without bind(c), gfortran typically exports a module-less subroutine foo under the symbol name: - A. foo - B. FOO - C. foo_ (lowercased, trailing underscore) - D. a random hash

Question 13

In the two-language workflow, which work belongs on the Fortran side? - A. reading command-line arguments - B. the hot numerical kernel (the loop that dominates runtime) - C. drawing the matplotlib figure - D. parsing a config file

Question 14

The whole-program speed of a numerical code is set mainly by: - A. the language of its longest source file - B. the language of its hot loop - C. the number of comments - D. the operating system

Question 15

Why does this book present the pure-Python-vs-Fortran speedup as "10–100×, measure it yourself" rather than a single number? - A. because the speedup is always exactly 50× - B. because no code in the book is executed, and the real figure depends on hardware, compiler, flags, and size - C. because f2py has no timing tools - D. because Fortran is slower

Question 16

The pure-Python element loop is slow (relative to compiled Fortran) mainly because of: - A. the arithmetic itself being different - B. per-iteration interpreter overhead (bytecode dispatch, type checks, boxing) around each operation - C. Python using less memory - D. NumPy being uninstalled

Question 17

When a hot loop can be written as a few whole-array NumPy slice operations, you should usually: - A. still rewrite it in Fortran - B. use the NumPy version — it is already compiled C underneath - C. use a pure-Python loop - D. give up

Question 18

The heat time loop cannot be collapsed into a single NumPy array expression because: - A. NumPy has no arrays - B. each step depends on the field the previous step produced (a loop-carried dependency) - C. matplotlib forbids it - D. the field is too small

Question 19

What does the !f2py intent(hide), depend(x) :: n = shape(x,0) directive accomplish? - A. it deletes the argument x - B. it hides n from the Python signature and computes it from x's shape - C. it makes n a return value - D. it transposes x

Question 20

A subroutine foo inside Fortran module bar, wrapped as extension module lib, is called from Python as: - A. lib.foo(...) - B. bar.foo(...) - C. lib.bar.foo(...) - D. foo.lib.bar(...)


Answer Key

Q Ans Why
1 C -m NAME names the importable extension module; the filename and Fortran module name are independent.
2 B A compiled shared library Python imports like a .py — NumPy and SciPy are examples.
3 B intent(out) becomes a Python return value.
4 C real64float64 (8-byte IEEE double).
5 B NumPy defaults to C-contiguous (row-major).
6 C For intent(in), f2py copies to F-order if needed — right answer, per-call cost.
7 B order='F' makes it F-contiguous from birth, so no copy.
8 False f2py preserves indexing: a[i,j]u(i+1,j+1); it reconciles layout by copying, not transposing.
9 C A 1-D array is both C- and F-contiguous, so 1-D never hits the layout issue.
10 B intent(inout) cannot be faked with a copy, so f2py rejects a non-F-contiguous array.
11 C bind(c) gives the C name and calling convention the C-ABI FFIs need.
12 C gfortran lowercases and appends an underscore: foo_.
13 B The hot kernel is Fortran's job; the rest is Python's.
14 B The hot loop's language dominates; the bulk runs rarely.
15 B No code is executed here, and the real figure is hardware/compiler/size dependent — only the order of magnitude is robust.
16 B Interpreter overhead per element, not the arithmetic, is the gap.
17 B Vectorized NumPy is compiled C already — use it; reach for Fortran when you can't vectorize.
18 B A loop-carried dependency across steps blocks a single array expression.
19 B It hides n and infers it from x's shape.
20 C Module procedures live under lib.<fortran_module>: lib.bar.foo.

Topics to review by question

  • Q1–4, 19–20 → §15.2 (f2py, the build command, intent→signature, module namespacing).
  • Q5–10 → §15.3 (dtype, C- vs F-contiguous, order='F', the copy, intent(inout)).
  • Q11–12 → §15.4 (ctypes/cffi and bind(c)).
  • Q13–14, 17–18 → §15.1 (the two-language workflow; when NumPy suffices, when Fortran wins).
  • Q15–16 → §15.5 (honest benchmarking; where the gap comes from).

Scored below 16? Reread the flagged sections. If you missed Q6–Q10, build example-02 and pass it both a default and an order='F' array — seeing the difference fixes the idea faster than rereading.