3

最初に言っておきますが、これは難解な目的で使用するためのものであり、製品コードではありません。私はPythonコードの1行で何かをして遊んでいるので、ステートメントではなく式が必要です。(編集:コードを(ほとんど)同等のPythonコード、BitBucket - onelinepythonの単一行に機械的にコンパイルすることに取り組んでいます。非常に進行中の作業であることに注意してください。したがって、最初に言及することは控えています)

私は基本的に2つのことをしたい:

  • 次のような選択した例外インスタンスを発生させる関数を呼び出します。

    raise_exception(WhateverException())

  • 囲まれた環境で関数を実行すると、発生した例外インスタンスが発生した場合はそれを取得でき、そうでない場合は呼び出された関数の戻り値を取得できます。例えば:

    has_exception, return_or_exception = check_exception(f, param1, param2, ...)

理想的には、これをデフォルトのライブラリまたは組み込み関数で実行したいと考えています (その意図された使用法をどれだけ野放しにする必要があるとしても)。私が提供した例とまったく同じシグネチャを持つ関数は必要ありません。十分に近いものにマングルできるものだけです。ただし、1 つの制限があります。eval() または同等の関数を使用しないことです

編集:これを行うために独自の関数を定義できることは知っていますが、それでも単一の式であるという制限に従う必要があります。raiseそのため、関数定義のtry内部で使用するソリューションはアウトです。関数定義、raise ステートメント、try ブロックは残念ながらステートメントであり、式ではありません。

私が試した解決策については。答えはまだありません。これを解決する方法のアイデアに最も近いのは、unittestのアサート機能を誤用することですが、それは行き止まりだと思います。

EDIT 2:明確にするために、コードのどこかでraise-statements または-blocksを使用するモジュールなどを使用しても問題ありません。try私の目標は、いくつかのコードを取得し、それを同等の 1 行のコード (使用している可能性のあるヘルパー関数を含む) に変換することです。しかし、これを Python のデフォルトのインストールで動作させたいので、デフォルトのライブラリのみを使用したいと考えています。

4

4 に答える 4

2

例外を発生させるには:

>>> import warnings
>>> WV = type("WV", (Warning, ValueError), {})
>>> warnings.simplefilter("error", WV)
>>> warnings.warn("wv", WV)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
__main__.WV: wv

例外をキャッチするには:

>>> import unittest
>>> res = type("TR", (unittest.TestResult, ), dict(addError=lambda self, test, err: setattr(self, '_last_err', err)))()
>>> unittest.FunctionTestCase(lambda: [][0])(res)
>>> res._last_err
(<type 'exceptions.IndexError'>, IndexError('list index out of range',), <traceback object at 0x2b4358e69950>)

warningsメソッドは から派生した例外に対してのみ機能することに注意してください。ただしWarning、常に乗算継承できる必要があります。例を次に示します。

>>> WS = type("WS", (Warning, StopIteration), {})
>>> warnings.simplefilter("error", WS)
>>> list(type("R", (object,), dict(__init__=lambda self, stop: (setattr(self, 'stop', stop), setattr(self, 'i', 0), None)[-1], __iter__=lambda self: self, next=lambda self: (self.i, setattr(self, 'i', self.i + 1))[0] if self.i < self.stop else warnings.warn("Stop", WS)))(5))
[0, 1, 2, 3, 4]
于 2012-06-19T10:08:24.797 に答える
1

これを行うために独自の関数を定義できます。

def raise_exception(ex):
    raise ex

def check_exception(f, *args, **kwargs):
    try:
        return False, f(*args, **kwargs)
    except Exception as e:
        return True, e
于 2012-06-18T19:41:39.047 に答える
1

この回答は、式で例外をキャッチすることは一般に不可能であることを示唆しています。を使用せずに任意の例外を発生させることは不可能であることも確信していraiseます。1/0( orのような式でいくつかの特定の例外を生成できますがdict['keyThatWillNeverExist']、任意の例外情報を持つ任意の例外は生成できません。)

言語リファレンスには次のように書かれています。

Python インタープリターは、実行時エラー (ゼロ除算など) を検出すると例外を発生させます。Python プログラムは、raise ステートメントを使用して明示的に例外を発生させることもできます。例外ハンドラは、try ... except ステートメントで指定されます。

これは、言語仕様のいくつかの暗いコーナーが他の方法で例外を発生させることを許可する可能性を排除するものではありませんが、ステートメントは非常に簡単です: で例外を発生させraise、 でそれらをキャッチしますtry/except

unittest には、try/except を使用する Python で記述された関数が含まれているため、unittest やその他の Python ライブラリを使用することは、実際の解決策ではないことに注意してください。したがって、unittest を使用しても問題ない場合は、独自の関数を作成しても問題ないはずです。

あなたが望むことをする機能を提供するC拡張機能を「だまして」書くことで、あなたの目標を達成できるかもしれないと思います。しかし、それは本当にそれを同等の Python コードに変換しているわけではありません。

于 2012-06-18T20:05:28.177 に答える
-1

raiseを使用せずに例外を発生させ、を使用せずに例外をキャッチする方法を尋ねていますexcept。これらのステートメントを使用することに抵抗があるのは、1行のコードで複数のステートメントを使用することはできず、Pythonモジュールをワンライナーにコンパイルするという考えがあるためです。

簡単な答え:まあ、できません。

そして、あなたができたとしても、なぜあなたはそうしますか?それは完全に無意味な努力です。コードは1行であるため、高速ではなく、大幅に小さくもなりません。Pythonの考え方にも反します。そして、それを難読化したい場合は、バイトコードにコンパイルするなど、はるかに優れた方法があります。

長い答え:

Pythonの例外とは関係なく、独自の例外システムを実装することもできますが、それは驚くほど遅く、Pythonの例外をキャッチできないため、この場合は役に立ちません。

-raiseステートメントの場合、Cの関数としてraiseステートメントを再実装できますが、これは不正行為だと思われます。また、などの他のステートメントでどのように可能になるかわかりませんexcept

一部のステートメントを別のモジュールの関数に移動することもできますが、これはもちろん、実際には意味のある方法でワンライナーモジュールではなくなり、すべてのステートメントがこのように簡単にラップされるわけではなく、exceptここで最も関連性の高いケースです。ブロック全体をラップする必要がありますtry/exceptが、結果の関数もパラメーターとして式のみを受け取るため、ブロックを関数に抽出する必要があり、基本的にPythonのほとんどを再実装する必要があります。ばかげているステートメントのない言語として。そして、ヘルパー関数が別のモジュールに含まれることになりますが、これは望ましくありません。

raiseしたがって、使用せずに例外を発生させ、使用せずに例外をキャッチする方法についての質問に対する答えexceptは、 「あなたはしない」です。

于 2012-06-19T09:22:54.147 に答える