web-dev-qa-db-ja.com

@propertyを指定した@staticmethod

が欲しいです

Stats.singleton.Twitter_count += 1

私はできると思った

class Stats:
    singleton_object = None

    @property
    @staticmethod
    def singleton():
        if Stats.singleton_object:
            return Stats.singleton_object
        Stats.singleton_object = Stats()
        return Stats.singleton()

しかし、それは例外を投げます:

>>> Stats.singleton.a = "b"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'property' object has only read-only attributes (assign to .a)
43
Paul Tarjan

シングルトンはPythonでは無意味です。

class A:
  class_var = object()

# two objects
a, b = A(), A()

# same var everywhere
assert a.class_var is b.class_var is A.class_var

Pythonのintsは単純なobjectsとは異なるため、必ずしも単純ではありません。しかし、あなたの目的のためには、これで十分なようです:

class Stats:
    Twitter_count = 0

Stats.Twitter_count +=1
Stats.Twitter_count +=1
assert Stats.Twitter_count == 2
3
Jochen Ritzel

ユーザーkaizer.seは、元の質問に関する限り、何かに興味を持っていました。シンプルさの点でさらに一歩踏み込んだので、デコレーターは1つだけで済みます。

class classproperty(property):
    def __get__(self, cls, owner):
        return classmethod(self.fget).__get__(None, owner)()

使用法:

class Stats:
    _current_instance = None

    @classproperty
    def singleton(cls):
        if cls._current_instance is None:
            cls._current_instance = Stats()
        return cls._current_instance

前述のように、シングルトンを作成するこの方法は、良いデザインパターンではありません。これを行う必要がある場合は、メタクラスファクトリを使用する方がはるかに優れています。でもクラスの物件の展望に興奮していたので、そうです。

70
kylealanhale

静的メソッドはPythonでは意味がありません。これは、クラスメソッドでは実行できないことを何も実行せず、将来的に拡張しやすいクラスメソッドであるためです(複数のクラスメソッドが互いに使用している場合など)。

必要なのは、単にクラスメソッドのプロパティです。

ここに私のコードのクラスメソッドプロパティがあります。これは読み取り専用で、必要なのはそれだけでした(残りは読者への練習です):

class ClassProperty (property):
    """Subclass property to make classmethod properties possible"""
    def __get__(self, cls, owner):
        return self.fget.__get__(None, owner)()

# how I would use it
class Stats:
    singleton_object = None
    @ClassProperty
    @classmethod
    def singleton(cls):
        if cls.singleton_object is None:
            cls.singleton_object = cls()
        return cls.singleton_object
3
u0b34a0f6ae

KyleAlanHaleが書いたことをフォローアップします。

あなたが試してみるまで、彼の例はうまくいきます:

Stats.singleton = 5

これはあなたにエラーを与えません、それは関数を上書きしますので、あなたが次にタイプするとき

single = Stats.singleton
print single

あなたが得るでしょう

5

@classpropertiesの装飾なしでカイルの回答を使用するのが最善です。

1
Charles Plager

Pythonコードスニペットをどのように表示するかを示すコードスニペットpropertyおよびstaticmethodを指定すると役立つと思います。

どちらも__ get __または__ set __を実装する記述子です

propertyはデータ記述子です

class Property(object):
    "Emulate PyProperty_Type() in Objects/descrobject.c"

    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
        self.fget = fget
        self.fset = fset
        self.fdel = fdel
        if doc is None and fget is not None:
            doc = fget.__doc__
        self.__doc__ = doc

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        if self.fget is None:
            raise AttributeError("unreadable attribute")
        return self.fget(obj)

    def __set__(self, obj, value):
        if self.fset is None:
            raise AttributeError("can't set attribute")
        self.fset(obj, value)

    def __delete__(self, obj):
        if self.fdel is None:
            raise AttributeError("can't delete attribute")
        self.fdel(obj)

    def getter(self, fget):
        return type(self)(fget, self.fset, self.fdel, self.__doc__)

    def setter(self, fset):
        return type(self)(self.fget, fset, self.fdel, self.__doc__)

    def deleter(self, fdel):
        return type(self)(self.fget, self.fset, fdel, self.__doc__)

そしてstaticmethodは非データ記述子です

class StaticMethod(object):
    "Emulate PyStaticMethod_Type() in Objects/funcobject.c"

    def __init__(self, f):
        self.f = f

    def __get__(self, obj, objtype=None):
        return self.f
0
Jacky1205

これがシングルトンを実装する最良の方法だと思います:

_class Singleton:
    __static_self = None

    # __new__ takes object creation out of user's hands
    def __new__(cls, *args, **kwargs):
        if not cls.__static_self:
            cls.__static_self = super().__new__(cls)
        else:
            vars(cls.__static_self).clear()  # wipe old state
        return cls.__static_self

    @classmethod
    def get(cls):
        """ get the singleton instance """
        return cls.__static_self

class Foo(Singleton):
    def __init__(self, a):
        self._a = a

    @property
    def a(self):
        return self._a

f = Foo(1)
f1 = Foo.get()
f2 = Foo(2)
print(f is f1 and f1 is f2) # True
print(f.a) # 2
_

__new__()によって返された後、 オブジェクトは自動的に(再)初期化されます (適切なパラメーターを使用)であることに注意してください。また、たとえば、構成ファイルをロードするときに、これを行う必要があることがわかっているため、再初期化可能にしました(その後、変数をデフォルトにリセットする必要があります)。

追伸___new___を__init_subclass__()と組み合わせて使用​​することで、クリーンなPythonの方法でファクトリパターンを実装することもできます。

0
profPlum