7

私は次のことを達成しようとしています:

class A:
    username = None
    username = get_username()
    def get_username(self):
        if username is None:
            try:
                uname = os.environ["USER"]
            except:
                printf("Couldn't find a user name")
            return uname
        return username

これを達成する方法がわからない。きっと「自分」が欠けていると思います。プレフィックスですが、Python と静的メンバーを扱うのはこれが初めてです。

ある意味では、いくつかのメンバーと関数を含むクラスでこれらのメンバーの値を計算したいのですが、再計算は必要ありません。また、これらを静的関数とデータ メンバーにしたいと考えています。

問題は、「username = get_username()」という行の関数がまだ定義されていないことです。関数の後にユーザー名を付けると、そうではありません

4

2 に答える 2

13

まず、直後に再割り当てNoneする場合は、に割り当てる必要はありません。username

次に、メソッドを静的メソッドにしたい場合、self引数を与えることはできません。実際の静的メソッドが必要な場合は、明示的に宣言する必要があります。

    @staticmethod
    def get_username():
        if username is None:
        ...

それ以外の場合は、それを呼び出すクラスのインスタンス ( that self) が必要ですが、まだありません。

Python 3 では、通常のメソッドは、クラスで呼び出されると静的メソッドのように機能し、インスタンスで呼び出されるとインスタンス メソッドのように機能します。a.get_username()したがって、インスタンスを呼び出したくないことが確実な場合はa、デコレータをスキップできます。ただし、パラメーターを削除する必要がありselfます。

あなたが実際にやろうとしているのは、クラス変数を使用して静的メソッドの結果をメモすることだと思います。それはできませんが、クラス変数を使用してクラスメソッドの結果をメモすることはできます。これは十分に近いかもしれません。それは次のようになります。

class A:
    username = None
    @classmethod
    def get_username(cls):
        if cls.username is None:
            try:
                uname = os.environ["USER"]
            except:
                print("Couldn't find a user name")
            else:
                cls.username = uname
        return cls.username

一方、ユーザー名がクラスのメンバーでなければならない正当な理由はありません。関数にメンバーを追加する、変更可能なデフォルト変数を渡す、またはクラスに感染する必要がget_usernameなく、クラスメソッドではなく静的メソッドとして残すことができるその他のさまざまな方法でメモ化できます。

しかし、実際には、最善の解決策は、PyPI や ActiveState のレシピ リストなどでメモ化ライブラリを見つけることです。したがって、次のように記述できます。

class A:
    @memoize
    @staticmethod
    def get_username():
        try:
            return os.environ["USER"]
        except:
            print("Couldn't find a user name")
            return None

繰り返しますが、@staticmethod誰も のインスタンスを作成してA呼び出しようとしないことが確実な場合は、 を削除できますget_username

于 2012-11-02T19:39:44.153 に答える
1

A.username を参照する機能を失いたくない場合は、わずかなメタクラスで class プロパティを使用できます。

class A(type):
    def __new__(cls, name, bases, attrs):
        # this allows B().username to also work
        attrs['username'] = property(lambda s: s.__class__.username)
        return type.__new__(cls, name, bases, attrs)
    @property
    def username(self):
        if not hasattr(self, '_username'):
            self._username = 'bar'
        return self._username

class B(object):
    __metaclass__ = A

print B.username
print B().username
于 2012-11-05T04:47:03.000 に答える