3

開いているファイルを受け入れるメソッドを作成しようとしています

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

ファイルタイプが定義されていないのはなぜですか? ファイルは常に定義されるべきではありませんか? ファイルの両方のパスを有効な引数の型として適切に処理するには、実装をどのように修正する必要がありますか?

4

3 に答える 3

3

チェックを入力しないでください!Pythonic ではありません。ダックタイピングの核心は、アヒルのように鳴くなら、それはアヒルだという考えです。必要な動作は、ファイルのような場合は機能し、文字列のような場合は機能します。これは単なるイデオロギーではありません。これは Python の標準であるため、人々はファイルのようなオブジェクトを提供してそれを機能させることができると期待しています。特定のファイル タイプのみに制限すると、コードが壊れやすく、柔軟性がなくなります。

最も単純なオプションは、より一般的な結果を単純に選択し、それを使用する場合と同じように動作を試み、例外が発生した場合は他の方法に失敗することです。

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

「フロー制御に例外を使用する」ことが悪いと見なされる他の言語に慣れている場合、これは悪いように思えるかもしれませんが、Python ではそうではありません。Python では、それらは通常そのように使用される言語のコア部分です (すべての for ループ例外で終了します!)。

または、ほとんどの場合、ファイル オブジェクトを取得する可能性が高いと思われる場合は、その逆を行います。

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

ファイルを開くための最良の方法であるステートメントwith使用に注意してください。これは読みやすく、例外が発生した場合でも常にファイルを閉じます。

型チェックが本当に必要な場合(例: 操作が失敗しても非常にコストがかかり、短絡する方法がない)、文字列側をチェックする必要があります。ファイルのようなものとは対照的に。ファイルのようなものをチェックする必要がある場合は、実際に型チェックを行うのではなく、抽象基本クラスを実装し必要な機能を探す必要があります

元のコードが失敗した理由は、3.x でfile返されるオブジェクトの基本クラスではないためです。open()

open() 関数によって返されるファイル オブジェクトのタイプは、モードによって異なります。open() を使用してファイルをテキスト モード ('w'、'r'、'wt'、'rt' など) で開くと、io.TextIOBase のサブクラス (具体的には io.TextIOWrapper) が返されます。バッファリングを使用してバイナリ モードでファイルを開くために使用すると、返されるクラスは io.BufferedIOBase のサブクラスになります。正確なクラスはさまざまです。バイナリ読み取りモードでは、io.BufferedReader を返します。書き込みバイナリ モードと追加バイナリ モードでは io.BufferedWriter を返し、読み取り/書き込みモードでは io.BufferedRandom を返します。バッファリングが無効になっている場合、io.RawIOBase のサブクラスである io.FileIO である raw ストリームが返されます。ソース

だからあなたが欲しいio.FileIO

于 2012-05-21T21:44:09.743 に答える
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
于 2012-05-21T21:12:39.493 に答える
1

filePython 3 には typeがありません。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.
于 2012-05-22T07:11:55.540 に答える