4

私は Python を初めて使用しますが、この言語が大好きです。しかし、Eclipse で PyDev を使用しているときに、最近 1 つの厄介な問題に遭遇しました。

一部のメソッドが一部のクラスのインスタンスを返しました。しかし、インスタンスのメソッドのインテリセンスを取得できません。

例えば:

import openpyxl
from openpyxl.reader.excel import load_workbook
from openpyxl.worksheet import Worksheet


xlsFile='hello.xlsx'
wbook = load_workbook(xlsFile)

wsheet1=wbook.get_sheet_by_name('mysheet')
wsheet1.cell('A9').hyperlink=r'\\sharefolder'

wsheet2=Worksheet()
wsheet2.cell('A1').hyperlink=r'\\sharefolder'

このコードでは、メソッドのプロンプトを で取得できますが、 では取得できcell()ませwsheet2wsheet1。どちらもWorksheet輸入済みのタイプですが。python または PyDev が返されたオブジェクトの型を正しく検出できないようです。

これは言語の制限ですか?それとも私が間違ったことをしましたか?とりあえず、ソース コードを掘り下げて、戻り値の実際の型を確認する必要があります。次に、その型で定義されているメソッドを確認します。とても面倒です。

この問題を再現するための小さなテストを作成しました。奇妙なことに、インテリセンスは機能しているようです。

ここに画像の説明を入力

4

3 に答える 3

2

これは、Python が動的に型付けされるという事実の結果です。

C# などの静的に型指定された言語では、メソッドに型シグネチャの注釈が付けられます。(余談ですが、型チェッカーによって型を推測できるシステムもあります。) 型を書き留めているので、コードを実行しなくても、コンパイラは関数の戻り値の型と引数の型を認識します。これにより、ツールでプログラムの型をチェックできるだけでなく、プログラム内のメソッドとその型に関するメタデータを構築することもできます。Intellisense は、プログラムのテキストから収集されたこのメタデータを照会することによって機能します。


Python には、言語に組み込まれている静的型システムはありません。これにより、ツールがコードを実行せずにヒントを提供することがはるかに難しくなります。たとえば、この関数の戻り値の型は何ですか?

def spam(eggs):
    if eggs:
        return "ham"
    return 42

spam文字列を返すこともあります。整数を返すこともあります。Intellisense は、呼び出しの戻り値にどのメソッドを表示する必要がありますspamか?

このクラスで利用可能な属性は何ですか?

class Spam:
    def __getattr__(self, name):
        if len(name) > 5:
            return "foo"
        return super().__getattr__(name)

Spam動的に属性を生成する場合があります: Intellisense は のインスタンスに対して何を表示する必要がありますSpamか?

これらの場合、正解はありません。いくつかの推測を自発的に行うことはできますが (たとえば、の戻り値に対して と のメソッドのstr両方を含むリストを表示することができます)、常に正しい提案をすることはできません。intspam


そのため、Python の Intellisense ツールは最善の推測に限定されます。あなたが与えた例では、あなたのIDEは の戻り値の型について十分に知っていないため、 についてのget_sheet_by_name情報を提供できませんwsheet1。ただし、wsheet2インスタンス化してWorksheet. f12 番目の例では、Intellisense は、ソース コードを調べることによって、戻り値の型について (正しい) 推測を行っているだけです。

ちなみに、IPython のような対話型シェルでのオートコンプリートは、より信頼性が高くなります。これは、入力したコードを IPython が実際に実行するためです。分析は実行時に行われるため、オブジェクトの実行時の型が何であるかがわかります。

于 2016-01-23T12:04:22.333 に答える
1

技術的には、Python ではメソッドは何でも返すことができ、操作の結果は操作が完了したときにのみ定義されます。

この単純な関数を考えてみましょう:

def f(a):
    if a == 1:
        return 1 # returns int
    elif a == 2:
        return "2" # returns string
    else:
        return object() # returns an `object` instance

関数は Python に対してかなり有効であり、その結果は厳密に定義されていますが、関数の実行の最後にのみです。それはそう:

>>> type(f(1))
<type 'int'>
>>> type(f(2))
<type 'str'>
>>> type(f(3))
<type 'object'>

確かに、この柔軟性は常に必要なものではなく、ほとんどのメソッドはアプリオリに予測可能なものを返します。インテリジェントな IDE はコード (および引数や戻り値の型を指定する可能性がある docstrings などのヒント) を分析できますが、これは常に一定レベルの信頼度がある推測になります。また、言語レベルで型ヒントを導入するPEP0484もありますが、これはオプションであり、比較的新しく、すべてのレガシー コードでは確実に使用されていません。

PyDev が特定のケースで機能しない場合、それは残念ですが、Python のような動的言語を選択する場合は、それを受け入れる必要があります。おそらく、別のよりインテリジェントな IDE を試すか、IDE の横に対話型の Python プロンプトが開いているコンソールを用意して、その場でコードをテストする価値があります。bpythonのような洗練された python シェルを使用することをお勧めします

于 2016-01-23T11:58:02.223 に答える