【问题标题】:how to accept file or path as arguments to method in python如何接受文件或路径作为python中方法的参数
【发布时间】:2012-05-21 21:10:13
【问题描述】:

我正在尝试编写一个可以接受打开的文件的方法

myFile = open("myFile.txt")
obj.writeTo(myFile)
myFile.close()

或带路径的字符串

obj.writeTo("myFile.txt")

方法实现如下:

def writeTo(self, hessianFile):
    if isinstance(hessianFile,file):
        print("File type")
    elif isinstance(hessianFile,str):
        print("String type")
    else:
        pass

但这会引发错误

NameError: global name 'file' is not defined

为什么没有定义文件类型?不应该一直定义文件吗?应该如何更正实现以正确处理文件作为有效参数类型的路径

【问题讨论】:

    标签: python file python-3.x typechecking


    【解决方案1】:

    不要输入检查!这不是 Pythonic。鸭子类型的核心是如果它像鸭子一样嘎嘎叫,那就是鸭子。您想要的行为是,如果它是 file-like,它可以工作,如果它是 string-like,它可以工作。这不仅仅是意识形态 - 因为这是 Python 中的标准,人们希望能够给你一个类似文件的对象并让它工作。如果您将其限制为仅特定的文件类型,您的代码将变得脆弱且不灵活。

    最简单的选择是简单地选择更常见的结果,尝试按照你的方式工作,如果遇到异常,则无法使用其他方法:

    def writeTo(self, hessianFile):
        try:
            with open(hessianFile, "w") as f:
                do_stuff(f)
        except TypeError:
            do_stuff(hessianFile)
    

    如果您习惯于“使用异常进行流控制”被认为不好的其他语言,这可能看起来很糟糕,但在 Python 中并非如此,它们是经常以这种方式使用的语言的核心部分(每个 for 循环都以异常结束!)。

    或者,如果您认为您在大多数情况下更有可能获得文件对象,请反过来做:

    def writeTo(self, hessianFile):
        try:
            do_stuff(f)
        except AttributeError:
            with open(hessianFile, "w") as f:
                do_stuff(f)
    

    注意我使用了the with statement,这是处理打开文件的最佳方式 - 它更具可读性,而且总是会为您关闭文件,即使出现异常也是如此。

    如果您真的发现您必须进行类型检查(例如:即使失败,操作也非常昂贵,无法短路),您应该检查字符串侧,因为它如果某些东西是类似字符串的而不是类似文件的,则更容易解决。如果您必须检查类似文件的内容,则应实现abstract base class 并查找所需的功能,而不是实际进行类型检查。

    您的原始代码失败的原因是 file 不是 open() 在 3.x 中返回的对象的基类。

    open() 函数返回的文件对象类型取决于 模式。当 open() 用于以文本模式打开文件时('w', 'r', 'wt'、'rt' 等),它返回 io.TextIOBase 的子类 (特别是 io.TextIOWrapper)。用于打开二进制文件时 带缓冲的模式,返回的类是 io.BufferedIOBase。确切的类有所不同:在读取二进制模式下,它 返回一个 io.BufferedReader;在写入二进制和附加二进制模式下, 它返回一个 io.BufferedWriter,在读/写模式下,它返回一个 io.BufferedRandom。当缓冲被禁用时,原始流,a 返回 io.RawIOBase 的子类 io.FileIO。 Source

    所以你想要io.FileIO

    【讨论】:

      【解决方案2】:

      不要使用名称“文件”(python 中的内置对象)作为类文件对象的名称。

      f = open("myFile.txt")
      obj.writeTo(f)
      f.close()
      

      例子:

      >>> filetype = lambda x: isinstance(x, file)
      >>> file = open('t','w')
      >>> filetype(file)
      
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "<stdin>", line 1, in <lambda>
      TypeError: isinstance() arg 2 must be a class, type, or tuple of classes and types
      
      >>> f = open('t','w')
      >>> del file
      >>> filetype(f)
      True
      

      【讨论】:

      • 我做了你建议的改变,但它没有解决我的问题。我注意到您的错误表明 arg2 是错误的类型,而我的错误表明第二个参数未定义。 这是python3
      【解决方案3】:

      在 Python 3 中没有 file 类型。它在 Python 2 中内置,但在 Python 3 中消失了。比较以下内容:

      Python 2.7.1 [...]
      >>> f = open('zz.bak', 'w')
      >>> type(f)
      <type 'file'>
      >>> print f.__doc__
      file(name[, mode[, buffering]]) -> file object
      
      Open a file.  The mode can be 'r', 'w' or 'a' for reading (default),
      writing or appending.  The file will be created if it doesn't exist
      when opened for writing or appending; it will be truncated when
      opened for writing.  Add a 'b' to the mode for binary files.
      Add a '+' to the mode to allow simultaneous reading and writing.
      If the buffering argument is given, 0 means unbuffered, 1 means line
      buffered, and larger numbers specify the buffer size.  The preferred way
      to open a file is with the builtin open() function.
      Add a 'U' to mode to open the file for input with universal newline
      support.  Any line ending in the input file will be seen as a '\n'
      in Python.  Also, a file so opened gains the attribute 'newlines';
      the value for this attribute is one of None (no newline read yet),
      '\r', '\n', '\r\n' or a tuple containing all the newline types seen.
      
      'U' cannot be combined with 'w' or '+' mode.
      

      在 Python 3 中...

      Python 3.2.1 [...]
      >>> f = open('xx', 'w')
      >>> type(f)
      <class '_io.TextIOWrapper'>
      >>> print(f.__doc__)
      Character and line based layer over a BufferedIOBase object, buffer.
      
      encoding gives the name of the encoding that the stream will be
      decoded or encoded with. It defaults to locale.getpreferredencoding.
      
      errors determines the strictness of encoding and decoding (see the
      codecs.register) and defaults to "strict".
      
      newline can be None, '', '\n', '\r', or '\r\n'.  It controls the
      handling of line endings. If it is None, universal newlines is
      enabled.  With this enabled, on input, the lines endings '\n', '\r',
      or '\r\n' are translated to '\n' before being returned to the
      caller. Conversely, on output, '\n' is translated to the system
      default line seperator, os.linesep. If newline is any other of its
      legal values, that newline becomes the newline when the file is read
      and it is returned untranslated. On output, '\n' is converted to the
      newline.
      
      If line_buffering is True, a call to flush is implied when a call to
      write contains a newline character.
      

      【讨论】:

        猜你喜欢
        • 2023-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-06
        • 1970-01-01
        • 2013-02-19
        • 1970-01-01
        • 2022-12-07
        相关资源
        最近更新 更多