如何创建一个接受每个参数作为一种类型或另一种类型的函数?

时间:2015-04-12 22:59:15

标签: python python-3.x

我想创建一个接受3个参数的函数,每个参数都可以传递给open函数,我的函数将传递给open然后使用它,或者它可以是一个文件对象,然后我的函数可以使用它而无需打开它。

所以,就像这样

def work_with_files(file1, file2, file3):
    files_to_close = []
    file_objects = []
    try:
        for file in (file1, file2, file3):
            if not is_file_object(file):
                opened_file = open(file.argument_for_open)
                file_objects.append(opened_file)
                files_to_close.append(opened_file)
            else:
                file_objects.append(file.file_object)
        work_with_files(file_objects)
    finally:
        for file in files_to_close:
            file.close()

在C ++中我会使用boost::variant,在haskell中我可能会使用Either。什么是最pythonic的方式来做到这一点?我应该将什么作为参数传递,is_file_object应该如何工作?

3 个答案:

答案 0 :(得分:1)

您可以使用contextlib.ExitStack(因此fileobjs会在with内自动关闭)并概括您的函数(如果它是一个字符串) - 然后将其传递给open,否则假设它已经是一个文件类似于.close() ...

的对象
from contextlib import ExitStack

def work_with_files(*args):
    with ExitStack() as stack:
        fileobjs = [
            stack.enter_context(open(obj) if isinstance(obj, str) else obj)
            for obj in args
        ]
        # do something with fileobjs list

做某事可能是这样的:

from itertools import chain

for line in chain.from_iterable(fileobjs):
    print(line)

答案 1 :(得分:0)

您可以使用isinstance功能:

isinstance(file_name,file)
  

isinstance(object, classinfo)

     

如果object参数是classinfo参数的实例,或者是(直接,间接或虚拟)子类的实例,则返回true。如果classinfo是类型对象(新样式类)并且object是该类型的对象或其(直接,间接或虚拟)子类,则也返回true。

另外:

  

文件对象使用C的stdio包实现,可以使用内置的open()函数创建。

您可以使用try-except语句来处理file objects

try:
  open('file-name')
except IOError:
  #do stuff

答案 2 :(得分:0)

如果您不想检查参数类型,可以使用try-except结构完全按照您的意愿执行:

def work_with_files(file1, file2, file3):

    # ensure that each file* variable is a file-like object
    try: file1 = open(file1)  # if it opens, then file1 was a filepath
    except: pass  # else, file1 was already a file-like object

    try: file2 = open(file2)
    except: pass

    try: file3 = open(file3)
    except: pass

    do_stuff_with_files(file1, file2, file3)
    for f in (file1, file2, file3): f.close()  # close the files