我想要
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)
答案 0 :(得分:60)
用户kaizer.se就原始问题而言已经开始了。我在简单性方面更进了一步,所以它现在只需要一个装饰器:
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
如上所述,这种创建单身的方式并不是一个好的设计模式;如果必须这样做,元类工厂是一个更好的方法。我对于一个阶级财产的前景感到很兴奋,所以,就是这样。
答案 1 :(得分:3)
静态方法在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
答案 2 :(得分:3)
单人在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
与简单的object
不同,所以并不总是这么简单。但就你的目的而言,这似乎已经足够了:
class Stats:
twitter_count = 0
Stats.twitter_count +=1
Stats.twitter_count +=1
assert Stats.twitter_count == 2
答案 3 :(得分:1)
跟进KyleAlanHale所写的内容:
他的榜样很有效,直到你尝试做:
Stats.singleton = 5
这不会给你一个错误,它会覆盖这个功能,所以当你输入下一个
single = Stats.singleton
print single
你会得到
5
我认为在没有@classproperties装饰的情况下,你最好使用Kyle的答案。
答案 4 :(得分:0)
我认为这是实现单例的最佳方法:
class Foo:
_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, *args, **kwargs);
vars(cls._static_self).clear(); # wipe old state
return cls._static_self;
@property
def a_property(self):
return 'a value' # or a real variable...
请注意,the object is (re)initialized automatically(带有适当的参数)由__new__()
返回
您还可以结合使用__new__
和__init_subclass__()
以干净的pythonic方式实现工厂模式。
答案 5 :(得分:0)
我想给出一个Python代码段来说明属性和静态方法的工作方式会有所帮助。
它们都是实现 __ get __ 或 __ set __
的描述符属性是数据描述符
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__)
静态方法是一个非数据描述符
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