Почему я могу вызывать подпрограмму Fortran через f2py, не имея нужного количества входов?

Я пытаюсь изучить f2py, и у меня есть следующий код на Фортране

      subroutine fibonacci(a, n)
      implicit none
      integer :: i, n
      double precision :: a(n)
      do i = 1, n
          if (i .eq. 1) then
              a(i) = 0d0
          elseif (i .eq. 2) then
              a(i) = 1d0
          else 
              a(i) = a(i - 1) + a(i - 2)
          endif
      enddo
      end subroutine fibonacci

который компилируется с помощью f2py -c fibonacci.f -m fibonacci и позже вызывается в Python

import numpy
import fibonacci

a = numpy.zeros(13)
fibonacci.fibonacci(a)
print a

Вызванная в Python подпрограмма fibonacci не получила достаточного количества аргументов, но код загадочным образом сработал. Кстати, вызов подпрограммы fibonacci с помощью fibonacci.fibonacci(a, len(a)) тоже сработал!

Может кто-нибудь объяснить это? Спасибо!


person zyy    schedule 14.03.2019    source источник
comment
Используйте тег fortran для всех вопросов Fortran. В любом случае ваш код не Fortran 77, это как минимум Fortran 90.   -  person Vladimir F    schedule 14.03.2019
comment
@VladimirF Спасибо! Какая часть кода делает его Fortran 90? Я думал, что написал код с отступами на Фортране 77.   -  person zyy    schedule 14.03.2019
comment
implicit none, ::, enddo, end subroutine Сообщение должно быть, забудьте F77 в 21 веке.   -  person Vladimir F    schedule 14.03.2019
comment
@VladimirF Я пытаюсь перевести старый код Fortran 77 на Python, мне нужно его изучить.   -  person zyy    schedule 14.03.2019
comment
Ладно, учись, но не пиши программы на чистом F77. Почти весь Fortran 77 по-прежнему является легальным Fortran 90 и более поздними версиями, поэтому изучение более современных версий включает изучение большей части Fortran 77. Писать чистый F77 в 2019 году просто нонсенс, даже ваша короткая программа здесь полна Фортран 90.   -  person Vladimir F    schedule 14.03.2019
comment
@VladimirF Это имеет смысл, спасибо!   -  person zyy    schedule 14.03.2019


Ответы (1)


f2py знает, что a и n являются параметрами функции, и из объявления

double precision :: a(n)

он может сделать вывод, что n является длиной a. Массивы NumPy имеют длину, поэтому параметр n в оболочке Python не нужен, а f2py делает его необязательным.

Обратите внимание, что код, сгенерированный f2py, проверяет, не указано ли слишком большое значение n:

In [19]: a = np.zeros(10)

In [20]: fibonacci.fibonacci(a, 99)
---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
<ipython-input-20-e9497469fd10> in <module>()
----> 1 fibonacci.fibonacci(a, 99)

error: (len(a)>=n) failed for 1st keyword n: fibonacci:n=99

Можно указать меньшее значение:

In [21]: a = np.zeros(10)

In [22]: fibonacci.fibonacci(a, 6)

In [23]: a
Out[23]: array([0., 1., 1., 2., 3., 5., 0., 0., 0., 0.])

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

f2py -h fibonacci.pyf fibonacci.f

дисплеи

Reading fortran codes...
    Reading file 'fibonacci.f' (format:fix,strict)
Post-processing...
    Block: fibonacci
Post-processing (stage 2)...
Saving signatures to file "./fibonacci.pyf"

и генерирует файл fibonacci.pyf, который содержит

!    -*- f90 -*-
! Note: the context of this file is case sensitive.

subroutine fibonacci(a,n) ! in fibonacci.f
    double precision dimension(n) :: a
    integer, optional,check(len(a)>=n),depend(a) :: n=len(a)
end subroutine fibonacci

! This file was auto-generated with f2py (version:2).
! See http://cens.ioc.ee/projects/f2py2e/

Вы можете видеть из сгенерированного объявления

    integer, optional,check(len(a)>=n),depend(a) :: n=len(a)

что f2py сделал вывод, что n должен быть необязательным параметром, значение которого не должно превышать длину a и значением по умолчанию является len(a).

person Warren Weckesser    schedule 14.03.2019