が欲しいです
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)
シングルトンは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のint
sは単純なobject
sとは異なるため、必ずしも単純ではありません。しかし、あなたの目的のためには、これで十分なようです:
class Stats:
Twitter_count = 0
Stats.Twitter_count +=1
Stats.Twitter_count +=1
assert Stats.Twitter_count == 2
ユーザー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
前述のように、シングルトンを作成するこの方法は、良いデザインパターンではありません。これを行う必要がある場合は、メタクラスファクトリを使用する方がはるかに優れています。でもクラスの物件の展望に興奮していたので、そうです。
静的メソッドは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
KyleAlanHaleが書いたことをフォローアップします。
あなたが試してみるまで、彼の例はうまくいきます:
Stats.singleton = 5
これはあなたにエラーを与えません、それは関数を上書きしますので、あなたが次にタイプするとき
single = Stats.singleton
print single
あなたが得るでしょう
5
@classpropertiesの装飾なしでカイルの回答を使用するのが最善です。
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
これがシングルトンを実装する最良の方法だと思います:
_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の方法でファクトリパターンを実装することもできます。