1

解決策: エラーは、関数が実際にはメソッドであるということでした。

関数の変数をシミュレートするためにデコレータを使用しようとしています。以下の最後の行でこのエラーが発生するのはなぜですか?global name 'onecmd' is not defined

def static_var(varname, initial_value):
  def decorate(func):
        setattr(func, varname, initial_value)
        return func
  return decorate

@static_var("last", None)
def onecmd(self, line):
    if line == "lastcmd":
        line = onecmd.last
    else:
        onecmd.last = line
4

1 に答える 1

4

onecmdあなたのコードはグローバルとしてアクセスできることを期待しているようですが、これはメソッドです。モジュール レベルで定義された関数は、(グローバルとして格納されるため) その名前で実際に到達できますが、クラス メソッドはクラス オブジェクトにのみ格納されます。

これを定義したクラスを介して、またはself属性を介して関数オブジェクトを見つける必要があります。その後、クラスに戻り、次に関数に戻ります。

@static_var("last", None)
def onecmd(self, line):
    onecmd = type(self).onecmd.im_func  # im_func is the wrapped function
    if line == "lastcmd":
        line = onecmd.last
    else:
        onecmd.last = line

すでにクラス メソッドがあるので、代わりに変数をクラスに格納する方がよいでしょう。

class Foo(object):
    last = None

    def onecmd(self, line):
        if line == "lastcmd":
            line = type(self).last
        else:
            type(onecmd).last = line

または、代わりにこれをクラスメソッドにすることもできます:

class Foo(object):
    last = None

    @classmethod
    def onecmd(cls, line):
        if line == "lastcmd":
            line = cls.last
        else:
            cls.last = line
于 2013-03-18T16:20:24.173 に答える