20

私は次のコードを持っています:

class Foo(object):
    def __init__(self):
        baz=self.bar(10)

    @staticmethod
    def bar(n):
        if n==0:
            return 'bar'
        else:
            return bar(n-1)

bar() は再帰関数として、それ自体への参照が必要です。ただし、 bar() はクラス内にあり、呼び出しreturn bar(n-1)は機能せず、 を呼び出しNameError: global name 'bar' is not definedます。どうすればこのような状況に対処できますか? or へのアクセスを許可して、bar() をクラスまたはインスタンス メソッドに変更する必要がありますselfcls?

4

5 に答える 5

48

barクラス名を前に付けることで参照できます。

class Foo(object):
    def __init__(self):
        baz=self.bar(10)

    @staticmethod
    def bar(n):
        if n==0:
            return 'bar'
        else:
            return Foo.bar(n-1)

静的メソッドは、クラスの名前空間に含まれる通常の関数に他なりません。

barまたは、代わりに通常の関数として定義します。

def bar(n):
    if n==0:
        return 'bar'
    else:
        return bar(n-1)

class Foo(object):
    def __init__(self):
        baz=bar(10)

これにより、問題全体が完全に回避されます。

于 2012-11-01T18:44:22.833 に答える
12

クラスメソッドを使用したり、名前でクラスを呼び出したりする代わりに(他の人が示すように)、クロージャを使用して関数への参照を保持することもできます。

class Foo(object):
    def bar():
        def bar(n):
            if n == 0:
               return "bar"
            return bar(n-1)
        return bar
    bar = staticmethod(bar())

(マイナーな)利点は、名前が変更されたときにこれが壊れにくいことです。たとえば、Foo.bar inside への参照がある場合、これはで定義されているクラスのグローバル名であり続けることにbar依存します。通常はこれが当てはまりますが、そうでない場合は、再帰呼び出しが中断されます。Foobar

このclassmethodアプローチは、クラスへの参照をメソッドに提供しますが、それ以外の場合はクラスはメソッドに必要ではないため、エレガントではないようです。クロージャーを使用すると、呼び出しごとに属性ルックアップが実行されないため、わずかに高速になります。

于 2012-11-01T20:02:27.000 に答える
9

そのことについて何?

class Foo(object):
    def __init__(self):
        baz = self.bar(10)

    @classmethod
    def bar(cls, n):
        if n == 0:
            return 'bar'
        else:
            return cls.bar(n-1)
于 2012-11-01T18:47:07.833 に答える