2

私はクラスのジェネレーター関数とプライベート関数を扱っていました。不思議なんだけど

  1. __someFuncで(私の1つのケースでは偶然でした)yieldを実行すると、この関数が__someGenerator内から呼​​び出されていないように見えるのはなぜですか。また、言語のこれらの側面を参照するときに使用したい用語は何ですか?
  2. Pythonインタープリターはそのようなインスタンスについて警告できますか?

以下は私のシナリオのスニペットの例です。

class someClass():
    def __init__(self):
        pass

    #Copy and paste mistake where yield ended up in a regular function
    def __someFunc(self):
        print "hello"
        #yield True #if yielding in this function it isn't called

    def __someGenerator (self):
        for i in range(0, 10):
            self.__someFunc()
            yield True
        yield False

    def someMethod(self):
        func = self.__someGenerator()
        while func.next():
            print "next"

sc = someClass()
sc.someMethod()

私はこれに夢中になり、関数が呼び出されなかった理由を理解しようと時間を費やしました。私はついに、自分がやりたくない機能を譲っていることに気づきました。

4

5 に答える 5

6

「ジェネレーター」は言語の機能ではなく、「生成する」関数の名前です。降伏はほとんど常に合法です。Python が、何らかの関数から生成することを「意図」していなかったことを知る方法は実際にはありません。

この PEP http://www.python.org/dev/peps/pep-0255/はジェネレーターについて説明しており、背景をよりよく理解するのに役立つかもしれません。

私はあなたの経験に同情しますが、コンパイラはあなたが「彼らに何をするつもりだったか」を理解することができず、あなたが実際に彼らに何をするように言ったかだけを理解することができません.

于 2009-07-06T13:43:41.453 に答える
2

Pythonは、後で反復するためにジェネレータオブジェクトを作成するか、関数を呼び出すかを認識していません。しかし、Pythonは、コードで何が起こっているかを確認するための唯一のツールではありません。カスタマイズされた構文の強調表示を可能にするエディターまたはIDEを使用している場合は、yieldキーワードに別の色、または明るい背景を指定するように指示できます。これにより、少なくともエラーをより迅速に見つけることができます。たとえば、vimでは次のようにします。

:syntax keyword Yield yield
:highlight yield ctermbg=yellow guibg=yellow ctermfg=blue guifg=blue

ちなみに、それらは恐ろしい色です。もっと良いものを選ぶことをお勧めします。エディターまたはIDEが連携しない場合の別のオプションは、pylintなどのコードチェッカーでカスタムルールを設定することです。pylintのソースtarballの例:

from pylint.interfaces import IRawChecker
from pylint.checkers import BaseChecker

class MyRawChecker(BaseChecker):
    """check for line continuations with '\' instead of using triple
    quoted string or parenthesis
    """

    __implements__ = IRawChecker

    name = 'custom_raw'
    msgs = {'W9901': ('use \\ for line continuation',
                     ('Used when a \\ is used for a line continuation instead'
                      ' of using triple quoted string or parenthesis.')),
           }
    options = ()

    def process_module(self, stream):
        """process a module

        the module's content is accessible via the stream object
        """
        for (lineno, line) in enumerate(stream):
            if line.rstrip().endswith('\\'):
                self.add_message('W9901', line=lineno)


def register(linter):
    """required method to auto register this checker"""
    linter.register_checker(MyRawChecker(linter))

pylintのマニュアルはここから入手できます:http ://www.logilab.org/card/pylint_manual そしてvimの構文ドキュメントはここから入手できます: http ://www.vim.org/htmldoc/syntax.html

于 2009-07-06T14:37:16.307 に答える
2

最初の質問に答えようと思います。

次のように呼び出された場合の通常の関数:

val = func()

終了するか、returnステートメントに到達するまで、内部ステートメントを実行します。次に、関数の戻り値が に代入されvalます。

コンパイラーが関数を実際にはジェネレーターであり、通常の関数ではないことを認識した場合 (関数内のステートメントを探すことによってそれをyield行います。少なくとも 1 つある場合、それはジェネレーターです)、上記と同じ方法で呼び出した場合のシナリオさまざまな結果があります。を呼び出すとfunc()関数内のコードは実行されず、特別な<generator>値が に割り当てられvalます。次に、最初に を呼び出すと、またはが検出されるまでval.next()の実際のステートメントが実行され、関数の実行が停止すると、生成された値が返され、ジェネレーターは への別の呼び出しを待ちます。funcyieldreturnval.next()

そのため、あなたの例では、 function__someFuncは「hello」を出力しませんでした - そのステートメントは実行されませんでしself.__someFunc().next()self.__someFunc().

残念ながら、あなたのようなプログラミング エラーに対する組み込みの警告メカニズムはないと確信しています。

于 2009-07-06T14:21:41.323 に答える
1

キーワードはジェネレーター関数と通常の関数の両方に適用できるため、return(@Christopher が言及しているように) チェックできるものはありません。ジェネレーターのreturnキーワードは、StopIteration 例外を発生させる必要があることを示します。

ジェネレーター内からの値を使用しようとするreturnと (これは単に「反復を停止する」ことを意味するため、意味がありませんreturn)、コンパイラーはコンパイル時に文句を言います。

>>> def foo():
...     yield 12
...     return 15
... 
  File "<stdin>", line 3
SyntaxError: 'return' with argument inside generator

個人的には、コピー アンド ペースト プログラミングに反対することをお勧めします。:-)

PEP から:

return は、ジェネレーター関数と非ジェネレーター関数の両方について、「完了しました。返すものは何もありません」を意味することに注意してください。

于 2009-07-06T14:02:40.227 に答える
0

これを行います。

ジェネレーターには、名前に「generate」または「gen」が含まれる名前があります。本体に yield ステートメントが含まれます。20 行をはるかに超えるコードのメソッドはないため、視覚的に確認するのは非常に簡単です。

他のメソッドには、名前に「gen」が含まれていません。

また、__どのような状況でも (二重下線) 名前を使用するわけではありません。32,000 行のコード。非__名。

「ジェネレーター対非ジェネレーター」メソッド機能は、完全に設計上の問題です。プログラマーが「意図」したこと。コンパイラは意図を簡単に検証できません。実際に入力した内容のみを検証できます。

于 2009-07-06T14:50:16.660 に答える