2015-04-12 90 views
0

我想創建一個接受3個參數的函數,每個參數都可以傳遞給open函數,我的函數會傳遞到open然後使用它,或者它可以是一個文件對象,然後我的函數可以在不需要打開它的情況下使用它。如何創建一個接受每個1參數爲一種類型或另一種類型的函數?

因此,它是這樣的

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。什麼是最Python的方式來做到這一點?我應該通過什麼作爲參數,以及is_file_object應該如何工作?

回答

0

可以使用isinstance功能:

isinstance(file_name,file) 

isinstance(object, classinfo)

返回真,如果該對象參數是CLASSINFO參數的實例,或其(直接,間接或虛擬的)的子類的。如果classinfo是一個類型對象(new-style class),並且object是該類型的對象或其(直接,間接或虛擬)子類的對象,則也會返回true。

而且爲:

File對象使用C的STDIO包中實現,並且可以與內置的open()函數創建。

您可以使用try-except語句來處理file objects

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

如果有什麼它實際上不是一個文件,而是一個文件 - 像StringIO一樣的對象? – CrabMan

+0

@CrabMan我沒有任何想法mayve StringIO模塊可以幫助你https://docs.python.org/2/library/stringio.html#module-StringIO – Kasramvd

+0

我實際上並不關心StringIO。我只是想將任何類似文件的對象傳遞給函數。 – CrabMan

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 
+0

就目前而言,這將無限遞歸。你想在finally塊中關閉,並且通常只在你打開它們的地方關閉它們。 –

+0

@Lattyware:哎呀!接得好。我打算說'do_stuff_with_files'。現在修復。謝謝你的頭! – inspectorG4dget

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) 
相關問題