8

この回答では、テスト ケースを動的に作成する方法について説明しています。

答えのコード:

class Tests(unittest.TestCase):
    def check(self, i, j):
        self.assertNotEquals(0, i-j)

for i in xrange(1, 4):
    for j in xrange(2, 6):
        def ch(i, j):
            return lambda self: self.check(i, j)
        setattr(Tests, "test_%r_%r" % (i, j), ch(i, j))

テストしましたが、動作しますが、方法がわかりません。

lambda self:主に、ここで行われている魔法を理解するのに苦労しています。

  1. ここで使用されるラムダは、正反対のことを実行するために使用されます(つまり、まだ知られていない追加functools.partial()のパラメーターを 1 つ持つラッパー関数を作成するため)。
  2. self意味のあるキーワードですか、それともlambda spam同様に機能しますか?
  3. そのラムダが評価されるポイントは何ですか?
  4. es.check()の範囲外で完全に問題ないのはなぜですか?class
  5. ラムダなしでこれを行うにはどうすればよいですか? - 私が正しく理解していれば、あなたはなくてもできるはずですlambda(言うまでもなく、それ目障りであり、なしでやりたいというグイドとアレックスに同意することは言うまでもありません:)
4

3 に答える 3

5

まず第一に、関数からラムダが返され、 の変更された値が後で使用されるのiを防ぎます。j

以下と比較してください。

for i in xrange(1, 4):
    for j in xrange(2, 6):
        setattr(Tests, "test_%r_%r" % (i, j), lambda self: self.check(i, j))

すべてのラムダが同じ名前空間を共有し、ループの終了後の値iを使用するため、これは期待どおりには機能しません。別の関数呼び出しを使用する場合は、関数が呼び出された時点での値をjキャプチャするたびに新しいクロージャーを導入します。ij

iと の現在の値をjラムダのデフォルト引数として保存することで、同じことを実現できます。itertools.product適切な測定のために、ネストされたループを回避するためにも使用しましょう。

from itertools import product
from operator import methodcaller

for i, j in product(range(1, 4), range(2, 6)):
  setattr(Tests, "test_%r_%r" % (i, j),
          lambda self, i=i, j=j: self.check(i, j))

ここで使用されるラムダは、 functools.partial() の正反対を実行するために使用されます (つまり、まだ知られていない追加のパラメーターを 1 つ持つラッパー関数を作成するため)。

あまり。check(i, j)引数として与えられたメソッドを呼び出すだけです。Testsこれは、クラスにメソッドを動的に追加するためにここで使用されます。

self は意味のあるキーワードですか、それともラムダ スパムも同様に機能しますか?

spam同様に機能します。selfラムダはメソッドを表すため、慣例によりここを選択します。

そのラムダが評価されるポイントは何ですか?

test_[i]_[j]()のインスタンスで呼び出されるとすぐにTests.

.check() がクラスの範囲外で完全に問題ないのはなぜですか?

ラムダの内部にあるため、引数Testsとしてのインスタンスを使用して後でのみ呼び出されます。self

于 2012-04-27T13:35:13.413 に答える
5

a_function = lambda x: do_something_with(x)

と同等です

def a_function(x):
    return do_something_with(x)

特定の例では、作成された関数はインスタンス メソッドです。したがって、たとえば、次のように書くことができます。

class Tests:
...
   test_1_2 = lambda self: self.check(1, 2)

これは次と同等です:

class Tests:
...
   def test_1_2(self):
       return self.check(1, 2)

現在、識別子は動的に生成されるため、setattr.


  1. ここで使用されるラムダは、正反対のことを実行するために使用されますfunctools.partial()(つまり、まだ知られていない追加のパラメーターを 1 つ持つラッパー関数を作成するため)。

いいえ、そうではありません。実はpartialここでも使えます。

test_1_2 = lambda self: self.check(1, 2)

なるだろう

test_1_2 = partial(Tests.check, i=1, j=2)
  1. self は意味のあるキーワードですか、それともラムダ スパムも同様に機能しますか?

インスタンス メソッドの最初の引数は、常にインスタンスである必要があります。規則では、そのパラメーターに名前を付けますselfが、他の名前を使用できます。コードを読みにくく理解しにくくするので、お勧めしません。

  1. そのラムダが評価されるポイントは何ですか?

lambda匿名関数を作成します。これは、呼び出し時に他の関数と同様に評価されます。

  1. .check() がクラスの範囲外で完全に問題ないのはなぜですか?

そうではありません。です。 はクラスself.check()selfインスタンスです。Tests

于 2012-04-27T13:50:41.857 に答える
3

ラムダは関数を返します。selfはその引数であり、iとjはその中に囲まれています

したがって、ch(i、j)はiとjの関数であり、selfの関数を返します

ここでは、Pythonには何もないので、selfには魔法のような意味はありません。一部の組み込み関数を除いて、すべての変数と関数は明示的です。しかし、これらのメソッドがクラスにアタッチされるとすぐに、selfが最初の引数になります。

これの意味は

  • ループの後Testsクラスはcheck_i_jと呼ばれる複数のメソッドを取得します

  • それぞれに値iとjが含まれています

  • それぞれに最初のパラメータが呼び出されselfます。これは、クラス内で定義されているため、インスタンスメソッドであるため、慣例により、最初のパラメータはselfと呼ばれる必要があります。

于 2012-04-27T13:27:39.090 に答える