模块中函数的条件定义

gro*_*k13 18 python design-patterns cross-platform

我的问题是找到定义一个函数的"好方法",该函数的实现根据给定的标准而不同.这个函数将从几个脚本中调用,因此我必须将它放在一个模块中.

举例来说,我的标准涉及运行脚本的平台,但要明确测试可以承担任何事情.我的函数允许持久定义/检索环境变量,所以我根据以下方案创建了一个名为persistenv.py的模块(解决方案1):

# CROSS-PLATFORM PART
def my_function1() :
    # ... body1 ...

# WINDOWS-ONLY PART
if sys.platform.lower().startswith('win') :
    def my_function2() :
        # ...body2 for Windows...

# LINUX-ONLY PART
elif sys.platform.lower().startswith('linux') :
    def my_function2() :
        # ...body2 for Linux...

else :
    raise ImportError('Your platform is not supported')
Run Code Online (Sandbox Code Playgroud)

以上介绍了单个模块中相同功能的两种可能定义.无论如何,对我来说,每次调用函数时测试平台(解决方案2)听起来都比我更清晰:

# CROSS-PLATFORM PART
def my_function1() :
    # ... body1 ...


def my_function2() :

    # WINDOWS-ONLY PART
    if sys.platform.lower().startswith('win') :
        # ...body2 for Windows...

    # LINUX-ONLY PART
    elif sys.platform.lower().startswith('linux') :
        # ...body2 for Linux...
Run Code Online (Sandbox Code Playgroud)

我找到了另一种方法,其中每个特定于平台的部分都被提取到自己的模块中,然后在persistenv.py中有条件地导入(解决方案3):

# CROSS-PLATFORM PART
def my_function1() :
    # ... body1 ...

# WINDOWS-ONLY PART
if sys.platform.lower().startswith('win') :
    from persistenv_win import my_function2

# LINUX-ONLY PART
elif sys.platform.lower().startswith('linux') :
    from persistenv_linux import my_function2

else :
    raise ImportError('Your platform is not supported')
Run Code Online (Sandbox Code Playgroud)

到目前为止,我得出了以下结论(并得到了以下问题):

  • 解决方案2应该很难使用,特别是如果你有几个特定于平台的函数my_function2,my_function3,my_function4 ...(因为你必须在每个函数中重复测试)

  • 解决方案1看起来非常简单(没有额外的文件,单个测试),但我想知道如果需要调用"来自persistenv import my_function2",Python如何(内部)行为

  • 解决方案3似乎更像Pythonic(用于内置实现,例如os.path),但是当persistenv.py,persistenv_win.py和persistenv_linux.py是同一个包(在其他模块中)的一部分时,它不会有问题我会在主脚本中执行"import my_package"全局导入

glg*_*lgl 11

如果您查看Python标准库,您会看到所有这三个都被使用:

  • subprocess使用解决方案1和2; 测试发生的地方有几个.

  • os使用解决方案3(import ... as path)的变体.

所以使用看起来最合适也最简单的那个.

[解决方案1]

如果需要调用" from persistenv import my_function2" ,Python如何(内部)行为?

它的行为完全符合要求.导出导入模块时定义的功能.

从技术上讲,模块就像导入一样import module,然后在其命名空间中查找给定的名称并放入当前名称.

[解决方案3]

当persistenv.py,persistenv_win.py和persistenv_linux.py是同一个包(在其他模块中)的一部分时,我会通过在主脚本中执行"import my_package"来全局导入,这不是问题吗?

为什么会有问题?您导入my_package主脚本,然后主脚本(或程序包的一个模块)从平台相关模块执行所述导入.这完全有效.