Python “两个都暴露”;“输入,输出”;及;“就地”;带有f2py的子程序版本

Python “两个都暴露”;“输入,输出”;及;“就地”;带有f2py的子程序版本,python,f2py,Python,F2py,我正在使用f2py将一些Fortran77例程集成到python模块中,但无法找到解决以下问题的好方法。我的Fortran例程在计算过程中销毁所有输入数组。我想向用户提供使用这些例程的内存高效“就地”行为的选项,以及在不破坏Python端数据的情况下执行例程的选项 我可以想出两种方法: 如果用户不希望销毁输入,请在调用我的Fortran例程之前备份Python中的所有输入数组。使用签名中的“intent(inplace)”声明编译Fortran例程。退出时,我可以使用备份副本恢复输入 针对两个不

我正在使用f2py将一些Fortran77例程集成到python模块中,但无法找到解决以下问题的好方法。我的Fortran例程在计算过程中销毁所有输入数组。我想向用户提供使用这些例程的内存高效“就地”行为的选项,以及在不破坏Python端数据的情况下执行例程的选项

我可以想出两种方法:

  • 如果用户不希望销毁输入,请在调用我的Fortran例程之前备份Python中的所有输入数组。使用签名中的“intent(inplace)”声明编译Fortran例程。退出时,我可以使用备份副本恢复输入
  • 针对两个不同的签名文件编译相同的Fortran例程,一个带有“intent(inplace)”,另一个带有“intent(in,out)”(或仅“intent(in)”,具体取决于情况)。然后在python中,我可以将这两种风格的例程导入到我的模块中
  • 我不太喜欢这两种方法,因为它们看起来都不是蟒蛇。有没有更好的方法来解决这个问题?是否有更简单的方法来实现方法2,例如,我是否可以将具有两个不同签名的同一例程编译成单个共享对象模块

    下面是一个例子(基于此)

    Fortran例程fib.f:

    C FILE: FIB.F
          SUBROUTINE FIB(A,N)
    C
    C     CALCULATE FIRST N FIBONACCI NUMBERS
    C
          INTEGER N
          REAL*8 A(N)
          DO I=1,N
             IF (I.EQ.1) THEN
                A(I) = 0.0D0
             ELSEIF (I.EQ.2) THEN
                A(I) = 1.0D0
             ELSE 
                A(I) = A(I-1) + A(I-2)
             ENDIF
          ENDDO
          END
    C END FILE FIB.F
    
    我使用
    f2py fib.f-m fib.pyf
    生成签名文件,然后添加一些意图声明:

    !    -*- f90 -*-
    ! Note: the context of this file is case sensitive.
    
    python module fib ! in
        interface  ! in :fib
            subroutine fib(a,n) ! in :fib:fib.f
                real*8 dimension(n), intent(inout) :: a
                integer, optional,check(len(a)>=n),depend(a) :: n=len(a)
            end subroutine fib
        end interface
    end python module fib
    
    ! This file was auto-generated with f2py (version:2).
    ! See http://cens.ioc.ee/projects/f2py2e/
    
    我使用
    f2py-c fib.pyf fib.f
    编译,然后我可以在适当的位置运行例程:

    >>> import numpy as np
    >>> from fib import fib
    >>> A = np.zeros(10, dtype=float)
    >>> fib(A)
    >>> print(A)
    [  0.   1.   1.   2.   3.   5.   8.  13.  21.  34.]
    

    为了将这个示例更改为in/out模式,我只需将“fib.pyf”中的意图声明更改为
    intent(in,out)

    ,最后在签名文件中使用
    fortranname
    声明来生成同一子例程的in-place和in-out风格。这是签名文件:

        !    -*- f90 -*-
        ! Note: the context of this file is case sensitive.
    
        python module fib ! in
                interface  ! in :fib
                    subroutine fib_inplace(a,n) ! in :fib:fib.f
                        fortranname fib
                        real*8 dimension(n), intent(inout) :: a
                        integer, optional,check(len(a)>=n),depend(a) :: n=len(a)
                    end subroutine fib
                    subroutine fib(a,n) ! in :fib:fib.f
                        fortranname fib
                        real*8 dimension(n), intent(copy, in,out) :: a
                        integer, optional,check(len(a)>=n),depend(a) :: n=len(a)
                    end subroutine fib
                end interface
        end python module fib
    
    注意:为了防止第二个例程修改Python输入,我还必须将
    copy
    添加到intent指令中