Related
How can I decorate the last function in a class inheritance?
If I decorate a superclass function, the subclass function overrides the decorator.
I'd like to find out if there is a neat way to automatically decorate the top function in the MRO.
def wrapper(f):
def _wrap(*args, **kwargs):
print("In wrapper")
return f(*args, **kwargs)
return _wrap
class A:
#wrapper
def f(self):
print("In class A")
class B(A):
def f(self):
print("In class B")
if __name__ == '__main__':
a = A()
b = B()
print("Calling A:")
a.f()
print("Calling B:")
b.f()
Here is the output. As expected, B.f() does not call the wrapper, though I'd like it to.
Calling A:
In wrapper
In class A
Calling B:
In class B
Here is what I have tried thus far. A metaclass that holds all the decorators and injects them during class instantiation.
from abc import ABCMeta
class WrapperMetaClass(ABCMeta):
def __init__(cls, *args, **kwargs):
wrappers_dict = getattr(cls, "_wrappers")
for attr_name in dir(cls):
if attr_name not in wrappers_dict:
continue
else:
wrapper = wrappers_dict[attr_name]
attr = getattr(cls, attr_name)
if not hasattr(attr, '__call__'):
raise Exception("What you're trying to wrap is not a function!")
attr = wrapper(attr)
setattr(cls, attr_name, attr)
super().__init__(*args, **kwargs)
This works:
class A(metaclass=WrapperMetaClass):
_wrappers = {
"f": wrapper
}
def f(self):
print("In class A")
class B(A):
def f(self):
print("In class B")
The output is what I wanted.
Calling A:
In wrapper
In class A
Calling B:
In wrapper
In class B
However, this runs into a different issue. If B does not override f, the metaclass wraps A.f() twice. This makes sense, as both A and B inherit WrapperMetaClass, so A.f() is wrapped first, and then B.f() is wrapped again.
class A(metaclass=WrapperMetaClass):
_wrappers = {
"f": wrapper
}
def f(self):
print("In class A")
class B(A):
pass
The output becomes:
Calling A:
In wrapper
In class A
Calling B:
In wrapper
In wrapper
In class A
I have no idea what else I could do.
Yes, I remember facing this once or twice - and you are on the right track.
But first things first: if the logic in your "wrapper" is something that
could be put in a method in the base class, then breaking-up the methods
in smaller-tasks, and have a "method slot" system is preferable to this,
as user 2357112 supports monica puts in the comments. If you find out you really need or prefer decorators, the full code is bellow
class A:
def do_things(self):
create_connection() # <- this is the code you'd are putting in the wrapper in the other approach
do_thing_1()
class B(A):
def do_things(self):
# here we have to do thing_1 and thing_2, but
# the connection is created in the superclass method...
# this could be the origin of your question
# Refactor to:
class A:
def do_things(self):
create_connection()
self.internal_do_things()
def internal_do_things(self):
do_thing_1()
class B(A):
def internal_do_things(self):
super().internal_do_things()
do_thing_2()
So, classical inheritance and OO solves this
If you need the decorators anway:
The thing to do is to have the decorator itself, the "wrapper", get
a way to "know" if it already was called in an outer method (i.e. a method
in a subclass which calls super()), and just act as a transparent
wrapper in this case.
It gets a bit further complicated when we want a robust solution:
a wrapper that can work for different methods in the same class,
and does not get confused if they are called concurrently
(in different threads, or a method calling another method,
not super(), which should trigger the wrapper).
And in the end, the mechanisms for that are complicated enough that
they should not get in the way of your actual wrapper - so,
ideally they should be built as a decorator themselves, which will
decorate your wrapper.
[hours later]
So, sorry if it does not look "neat" - it turns out implementing what is described above is a bit more complex than I thought initially - we need an intermediate decorator level (called meta_wrapper_applier in the code), so that the metaclass can re-wrap the methods each time they are redeclared.
I hope the comments in the code and variable names are enough to understand the idea:
from abc import ABCMeta
from functools import wraps
import threading
class WrapperMetaClass(ABCMeta):
def __init__(cls, name, bases, ns, **kw):
super().__init__(name, bases, ns, **kw)
# Get the wrapped methods for all the superclasses
super_wrappers = {}
for supercls in cls.__mro__[::-1]:
super_wrappers.update(supercls.__dict__.get("_wrappers", {}))
# unconditionally install a wrappers dict for each subclass:
sub_wrappers = cls._wrappers = {}
for attrname, attr in ns.items():
if attrname in super_wrappers:
# Applies the wrapper in the baseclass to the subclass method:
setattr(cls, attrname, super_wrappers[attrname]._run_once_wrapper(attr))
elif hasattr(attr, "_run_once_wrapper"):
# Store the wrapper information in the cls for use of the subclasses:
sub_wrappers[attrname] = attr
def run_once_method_decorator(original_wrapper):
re_entering_stacks = {}
# This is the callable used to place a wrapper on the original
# method and on each overriden method.
# All methods with the same name in the subclasses will share the same original wrapper and the
# "re_entering_stacks" data structure.
def meta_wrapper_applier(raw_method):
wrapped_method_in_subclass = None
#wraps(original_wrapper)
def meta_wrapper(*args, **kw):
nonlocal wrapped_method_in_subclass
# uses a plain list to keep track of re-entering the same-named method
# in each thread:
re_entering_stack = re_entering_stacks.setdefault(threading.current_thread(), [])
re_entering = bool(re_entering_stack)
try:
re_entering_stack.append(1)
if re_entering:
result = raw_method(*args, **kw)
else:
if wrapped_method_in_subclass is None:
# Applies the original decorator lazily, and caches the result:
wrapped_method_in_subclass = original_wrapper(raw_method)
result = wrapped_method_in_subclass(*args, **kw)
finally:
re_entering_stack.pop()
return result
# registry = original_wrapper.__dict__.setdefault("_run_once_registry", {})
meta_wrapper._run_once_wrapper = meta_wrapper_applier
return meta_wrapper
return meta_wrapper_applier
# From here on, example code only;
#run_once_method_decorator
def wrapper(f):
#wraps(f)
def _wrap(*args, **kwargs):
print("Entering wrapper")
result = f(*args, **kwargs)
print("Leaving wrapper\n")
return result
return _wrap
#run_once_method_decorator
def other_wrapper(f):
#wraps(f)
def _wrap(*args, **kwargs):
print("Entering other wrapper")
result = f(*args, **kwargs)
print("Leaving other wrapper\n")
return result
return _wrap
class A(metaclass=WrapperMetaClass):
#wrapper
def f(self):
print("In class A")
def g(self):
print("g in A")
class B(A):
def f(self):
print("In class B")
super().f()
#other_wrapper
def g(self):
print("g in B")
super().g()
class C(B):
def g(self):
print("g in C")
super().g()
if __name__ == '__main__':
a = A()
b = B()
print("Calling A:")
a.f()
a.g()
print("Calling B:")
b.f()
b.g()
print("Calling C:")
C().g()
Output:
Calling A:
Entering wrapper
In class A
Leaving wrapper
g in A
Calling B:
Entering wrapper
In class B
In class A
Leaving wrapper
Entering other wrapper
g in B
g in A
Leaving other wrapper
Calling C:
Entering other wrapper
g in C
g in B
g in A
Leaving other wrapper
i read about decorators and i am trying to decorate all the methods of a class WITHOUT static methods.
right now i just use the decorator i wrote for the specific functions that are not static, so i wonder if there is a way to both decorate a lot of methods but avoid static ones
what i get with my decorator:
TypeError: unbound method test() must be called with ClassTest instance as first argument (got nothing instead)
my decorator:
def decorator(func):
def wrapper(self, *args, **kwargs):
print "test"
return func(self, *args, **kwargs)
return wrapper
First of all, decorating a class is pretty simple:
def class_decorator(cls):
# modify cls
return cls
In order to add/remove/modify functionality to a method, you could call setattr with a decorated version of a method (or a variable):
setattr(some_class, some_attribute, decorator(some_callable))
As to differentiating between different types of methods, there are a couple of attributes you'll be able to use
to determine whether a method is an instance/class/static method.
A full working example:
def _is_instance_method(var):
if not hasattr(var, '__call__'): # It's not a callable
return False
if not hasattr(var, 'im_self'): # It's a callable, but it's not a bound method
return False
if getattr(var, 'im_self') is not None: # At this point, if it's a class method,
# it will be bound to the class, while
# the instance method is still unbound
# return False if it's bound (i.e. a class method)
return False
return True # All that remains is a callable, that's boundable, but not yet -- an instance method!
def func_decorator(func):
def func_wrapper(self, *args, **kwargs):
print "Inside %s!" % (func.__name__,)
return func(self, *args, **kwargs)
return func_wrapper
def class_decorator(cls):
for attr in cls.__dict__:
var = getattr(cls, attr)
if _is_instance_method(var): # Determine whether the attribute is an instance method
setattr(cls, attr, func_decorator(var)) # Replace the function with a decorated one
return cls # Return the class with its new decorated instance methods
#class_decorator
class B(object):
#staticmethod
def static_method():
return "static method"
#classmethod
def cls_method(cls):
return "cls method"
def instance_method(self):
return "instance method"
print B.static_method()
print B.cls_method()
b = B()
print b.instance_method()
I write a decorator for class method
def decor(method):
def wrapped(self, *args, **kwargs):
return method(self, *args, **kwargs)
# [*]
return wrapped
I would like use this like:
class A(metaclass=mymetaclass):
#decor
def meth(self):
pass
How I can in decorator add method/variable to class which has decorated method? I need it do near [*].
Inside wrapped I could write self.__class__, but what to do here?
I cannot imagine a way to meet such a requirement, because decor function only receives a function object that knows nothing about a containing class.
The only workaround that I can imagine is to use a parameterized decorator and pass it the class being decorated
def decor(cls):
def wrapper(method):
def wrapped(self, *args, **kwargs):
return self.method(*args, **kwargs)
print method # only a function object here
return wrapped
print cls # here we get the class and can manipulate it
return wrapper
class A
#decor(A)
def method(self):
pass
Alternatively, you could decorate the class itself:
def cdecor(cls):
print 'Decorating', cls # here we get the class and can manipulate it
return cls
#cdecor
class B:
def meth(self):
pass
gives:
Decorating __main__.B
It looks like you just wanted to decorate one of a classes functions, not specifically an #classmethod. Here's a simple way that I did it when I wanted to call a classes save function when the function returned a successful result:
def save_on_success(func):
""" A decorator that calls a class object's save method when successful """
def inner(self, *args, **kwargs):
result = func(self, *args, **kwargs)
if result:
self.save()
return result
return inner
Here is an example of how it was used:
class Test:
def save(self):
print('saving')
#save_on_success
def test(self, var, result=True):
print('testing, var={}'.format(var))
return result
Testing to make sure it works as expected:
>>> x = Test()
>>> print(x.test('test True (should save)', result=True))
testing, var=test True (should save)
saving
True
>>> print(x.test('test False (should not save)', result=False))
testing, var=test False (should not save)
False
It looks like it is not directly possible, according to this response :
Get Python function's owning class from decorator
What you could do instead is providing a decorator for your class, something like that :
class InsertMethod(object):
def __init__(self, methodToInsert):
self.methodToInsert = methodToInsert
def __call__(self, classObject):
def wrapper(*args, **kwargs):
setattr(classObject, self.methodToInsert.__name__, self.methodToInsert)
return classObject(*args, **kwargs)
return wrapper
def IWillBeInserted(self):
print "Success"
#InsertMethod(IWillBeInserted)
class Something(object):
def __init__(self):
pass
def action(self):
self.IWillBeInserted()
a = Something()
a.action()
Actually, you may decorate the class itself:
def class_decorator(class_):
class_.attribute = 'value'
class_.method = decorate(class_.method)
return class_
#class_decorator
class MyClass:
def method(self):
pass
I'm a little late to the party, but late is better than never eh? :)
We can do this by decorating our class method with a decorator which is itself a class object, say B, and then hook into the moment when Python calls B.__get__ so to fetch the method. In that __get__ call, which will be passed both the owner class and the newly generated instance of that class, you can elect to either insert your method/variable into the original owner class, or into the newly defined instance.
class B(object):
def __init__(self, f):
self.f = f
def __call__(self, *args, **kwargs):
return self.f(*args, **kwargs)
def __get__(self, instance, owner):
instance.inserted = True
# owner.inserted = True
def wrapper(*args, **kwargs):
return self(instance, *args, **kwargs)
return wrapper
class A:
#B
def method(self):
pass
if __name__ == "__main__":
a = A()
a.method()
b = A()
print(hasattr(a, 'inserted'))
print(hasattr(b, 'inserted'))
In this example, we're wrapping def method(self) with #B. As written, the inserted attribute inserted will only persist in the a object because it's being applied to the instance. If we were to create a second object b as shown, the inserted attribute is not included. IE, hasattr(a, 'inserted') prints True and hasattr(b, 'inserted') prints False. If however we apply inserted to the owner class (as shown in the commented out line) instead, the inserted attribute will persist into all future A() objects. IE hasattr(a, 'inserted') prints True and hasattr(b, 'inserted') prints True, because b was created after a.method() was called.
This question already has answers here:
Using property() on classmethods
(19 answers)
Closed 3 years ago.
In python I can add a method to a class with the #classmethod decorator. Is there a similar decorator to add a property to a class? I can better show what I'm talking about.
class Example(object):
the_I = 10
def __init__( self ):
self.an_i = 20
#property
def i( self ):
return self.an_i
def inc_i( self ):
self.an_i += 1
# is this even possible?
#classproperty
def I( cls ):
return cls.the_I
#classmethod
def inc_I( cls ):
cls.the_I += 1
e = Example()
assert e.i == 20
e.inc_i()
assert e.i == 21
assert Example.I == 10
Example.inc_I()
assert Example.I == 11
Is the syntax I've used above possible or would it require something more?
The reason I want class properties is so I can lazy load class attributes, which seems reasonable enough.
Here's how I would do this:
class ClassPropertyDescriptor(object):
def __init__(self, fget, fset=None):
self.fget = fget
self.fset = fset
def __get__(self, obj, klass=None):
if klass is None:
klass = type(obj)
return self.fget.__get__(obj, klass)()
def __set__(self, obj, value):
if not self.fset:
raise AttributeError("can't set attribute")
type_ = type(obj)
return self.fset.__get__(obj, type_)(value)
def setter(self, func):
if not isinstance(func, (classmethod, staticmethod)):
func = classmethod(func)
self.fset = func
return self
def classproperty(func):
if not isinstance(func, (classmethod, staticmethod)):
func = classmethod(func)
return ClassPropertyDescriptor(func)
class Bar(object):
_bar = 1
#classproperty
def bar(cls):
return cls._bar
#bar.setter
def bar(cls, value):
cls._bar = value
# test instance instantiation
foo = Bar()
assert foo.bar == 1
baz = Bar()
assert baz.bar == 1
# test static variable
baz.bar = 5
assert foo.bar == 5
# test setting variable on the class
Bar.bar = 50
assert baz.bar == 50
assert foo.bar == 50
The setter didn't work at the time we call Bar.bar, because we are calling
TypeOfBar.bar.__set__, which is not Bar.bar.__set__.
Adding a metaclass definition solves this:
class ClassPropertyMetaClass(type):
def __setattr__(self, key, value):
if key in self.__dict__:
obj = self.__dict__.get(key)
if obj and type(obj) is ClassPropertyDescriptor:
return obj.__set__(self, value)
return super(ClassPropertyMetaClass, self).__setattr__(key, value)
# and update class define:
# class Bar(object):
# __metaclass__ = ClassPropertyMetaClass
# _bar = 1
# and update ClassPropertyDescriptor.__set__
# def __set__(self, obj, value):
# if not self.fset:
# raise AttributeError("can't set attribute")
# if inspect.isclass(obj):
# type_ = obj
# obj = None
# else:
# type_ = type(obj)
# return self.fset.__get__(obj, type_)(value)
Now all will be fine.
If you define classproperty as follows, then your example works exactly as you requested.
class classproperty(object):
def __init__(self, f):
self.f = f
def __get__(self, obj, owner):
return self.f(owner)
The caveat is that you can't use this for writable properties. While e.I = 20 will raise an AttributeError, Example.I = 20 will overwrite the property object itself.
[answer written based on python 3.4; the metaclass syntax differs in 2 but I think the technique will still work]
You can do this with a metaclass...mostly. Dappawit's almost works, but I think it has a flaw:
class MetaFoo(type):
#property
def thingy(cls):
return cls._thingy
class Foo(object, metaclass=MetaFoo):
_thingy = 23
This gets you a classproperty on Foo, but there's a problem...
print("Foo.thingy is {}".format(Foo.thingy))
# Foo.thingy is 23
# Yay, the classmethod-property is working as intended!
foo = Foo()
if hasattr(foo, "thingy"):
print("Foo().thingy is {}".format(foo.thingy))
else:
print("Foo instance has no attribute 'thingy'")
# Foo instance has no attribute 'thingy'
# Wha....?
What the hell is going on here? Why can't I reach the class property from an instance?
I was beating my head on this for quite a while before finding what I believe is the answer. Python #properties are a subset of descriptors, and, from the descriptor documentation (emphasis mine):
The default behavior for attribute access is to get, set, or delete the
attribute from an object’s dictionary. For instance, a.x has a lookup chain
starting with a.__dict__['x'], then type(a).__dict__['x'], and continuing
through the base classes of type(a) excluding metaclasses.
So the method resolution order doesn't include our class properties (or anything else defined in the metaclass). It is possible to make a subclass of the built-in property decorator that behaves differently, but (citation needed) I've gotten the impression googling that the developers had a good reason (which I do not understand) for doing it that way.
That doesn't mean we're out of luck; we can access the properties on the class itself just fine...and we can get the class from type(self) within the instance, which we can use to make #property dispatchers:
class Foo(object, metaclass=MetaFoo):
_thingy = 23
#property
def thingy(self):
return type(self).thingy
Now Foo().thingy works as intended for both the class and the instances! It will also continue to do the right thing if a derived class replaces its underlying _thingy (which is the use case that got me on this hunt originally).
This isn't 100% satisfying to me -- having to do setup in both the metaclass and object class feels like it violates the DRY principle. But the latter is just a one-line dispatcher; I'm mostly okay with it existing, and you could probably compact it down to a lambda or something if you really wanted.
If you use Django, it has a built in #classproperty decorator.
from django.utils.decorators import classproperty
For Django 4, use:
from django.utils.functional import classproperty
I think you may be able to do this with the metaclass. Since the metaclass can be like a class for the class (if that makes sense). I know you can assign a __call__() method to the metaclass to override calling the class, MyClass(). I wonder if using the property decorator on the metaclass operates similarly.
Wow, it works:
class MetaClass(type):
def getfoo(self):
return self._foo
foo = property(getfoo)
#property
def bar(self):
return self._bar
class MyClass(object):
__metaclass__ = MetaClass
_foo = 'abc'
_bar = 'def'
print MyClass.foo
print MyClass.bar
Note: This is in Python 2.7. Python 3+ uses a different technique to declare a metaclass. Use: class MyClass(metaclass=MetaClass):, remove __metaclass__, and the rest is the same.
As far as I can tell, there is no way to write a setter for a class property without creating a new metaclass.
I have found that the following method works. Define a metaclass with all of the class properties and setters you want. IE, I wanted a class with a title property with a setter. Here's what I wrote:
class TitleMeta(type):
#property
def title(self):
return getattr(self, '_title', 'Default Title')
#title.setter
def title(self, title):
self._title = title
# Do whatever else you want when the title is set...
Now make the actual class you want as normal, except have it use the metaclass you created above.
# Python 2 style:
class ClassWithTitle(object):
__metaclass__ = TitleMeta
# The rest of your class definition...
# Python 3 style:
class ClassWithTitle(object, metaclass = TitleMeta):
# Your class definition...
It's a bit weird to define this metaclass as we did above if we'll only ever use it on the single class. In that case, if you're using the Python 2 style, you can actually define the metaclass inside the class body. That way it's not defined in the module scope.
def _create_type(meta, name, attrs):
type_name = f'{name}Type'
type_attrs = {}
for k, v in attrs.items():
if type(v) is _ClassPropertyDescriptor:
type_attrs[k] = v
return type(type_name, (meta,), type_attrs)
class ClassPropertyType(type):
def __new__(meta, name, bases, attrs):
Type = _create_type(meta, name, attrs)
cls = super().__new__(meta, name, bases, attrs)
cls.__class__ = Type
return cls
class _ClassPropertyDescriptor(object):
def __init__(self, fget, fset=None):
self.fget = fget
self.fset = fset
def __get__(self, obj, owner):
if self in obj.__dict__.values():
return self.fget(obj)
return self.fget(owner)
def __set__(self, obj, value):
if not self.fset:
raise AttributeError("can't set attribute")
return self.fset(obj, value)
def setter(self, func):
self.fset = func
return self
def classproperty(func):
return _ClassPropertyDescriptor(func)
class Bar(metaclass=ClassPropertyType):
__bar = 1
#classproperty
def bar(cls):
return cls.__bar
#bar.setter
def bar(cls, value):
cls.__bar = value
bar = Bar()
assert Bar.bar==1
Bar.bar=2
assert bar.bar==2
nbar = Bar()
assert nbar.bar==2
I happened to come up with a solution very similar to #Andrew, only DRY
class MetaFoo(type):
def __new__(mc1, name, bases, nmspc):
nmspc.update({'thingy': MetaFoo.thingy})
return super(MetaFoo, mc1).__new__(mc1, name, bases, nmspc)
#property
def thingy(cls):
if not inspect.isclass(cls):
cls = type(cls)
return cls._thingy
#thingy.setter
def thingy(cls, value):
if not inspect.isclass(cls):
cls = type(cls)
cls._thingy = value
class Foo(metaclass=MetaFoo):
_thingy = 23
class Bar(Foo)
_thingy = 12
This has the best of all answers:
The "metaproperty" is added to the class, so that it will still be a property of the instance
Don't need to redefine thingy in any of the classes
The property works as a "class property" in for both instance and class
You have the flexibility to customize how _thingy is inherited
In my case, I actually customized _thingy to be different for every child, without defining it in each class (and without a default value) by:
def __new__(mc1, name, bases, nmspc):
nmspc.update({'thingy': MetaFoo.services, '_thingy': None})
return super(MetaFoo, mc1).__new__(mc1, name, bases, nmspc)
If you only need lazy loading, then you could just have a class initialisation method.
EXAMPLE_SET = False
class Example(object):
#classmethod
def initclass(cls):
global EXAMPLE_SET
if EXAMPLE_SET: return
cls.the_I = 'ok'
EXAMPLE_SET = True
def __init__( self ):
Example.initclass()
self.an_i = 20
try:
print Example.the_I
except AttributeError:
print 'ok class not "loaded"'
foo = Example()
print foo.the_I
print Example.the_I
But the metaclass approach seems cleaner, and with more predictable behavior.
Perhaps what you're looking for is the Singleton design pattern. There's a nice SO QA about implementing shared state in Python.
This question already has answers here:
Creating a singleton in Python
(38 answers)
Closed 4 years ago.
There seem to be many ways to define singletons in Python. Is there a consensus opinion on Stack Overflow?
I don't really see the need, as a module with functions (and not a class) would serve well as a singleton. All its variables would be bound to the module, which could not be instantiated repeatedly anyway.
If you do wish to use a class, there is no way of creating private classes or private constructors in Python, so you can't protect against multiple instantiations, other than just via convention in use of your API. I would still just put methods in a module, and consider the module as the singleton.
Here's my own implementation of singletons. All you have to do is decorate the class; to get the singleton, you then have to use the Instance method. Here's an example:
#Singleton
class Foo:
def __init__(self):
print 'Foo created'
f = Foo() # Error, this isn't how you get the instance of a singleton
f = Foo.instance() # Good. Being explicit is in line with the Python Zen
g = Foo.instance() # Returns already created instance
print f is g # True
And here's the code:
class Singleton:
"""
A non-thread-safe helper class to ease implementing singletons.
This should be used as a decorator -- not a metaclass -- to the
class that should be a singleton.
The decorated class can define one `__init__` function that
takes only the `self` argument. Also, the decorated class cannot be
inherited from. Other than that, there are no restrictions that apply
to the decorated class.
To get the singleton instance, use the `instance` method. Trying
to use `__call__` will result in a `TypeError` being raised.
"""
def __init__(self, decorated):
self._decorated = decorated
def instance(self):
"""
Returns the singleton instance. Upon its first call, it creates a
new instance of the decorated class and calls its `__init__` method.
On all subsequent calls, the already created instance is returned.
"""
try:
return self._instance
except AttributeError:
self._instance = self._decorated()
return self._instance
def __call__(self):
raise TypeError('Singletons must be accessed through `instance()`.')
def __instancecheck__(self, inst):
return isinstance(inst, self._decorated)
You can override the __new__ method like this:
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(
cls, *args, **kwargs)
return cls._instance
if __name__ == '__main__':
s1 = Singleton()
s2 = Singleton()
if (id(s1) == id(s2)):
print "Same"
else:
print "Different"
A slightly different approach to implement the singleton in Python is the borg pattern by Alex Martelli (Google employee and Python genius).
class Borg:
__shared_state = {}
def __init__(self):
self.__dict__ = self.__shared_state
So instead of forcing all instances to have the same identity, they share state.
The module approach works well. If I absolutely need a singleton I prefer the Metaclass approach.
class Singleton(type):
def __init__(cls, name, bases, dict):
super(Singleton, cls).__init__(name, bases, dict)
cls.instance = None
def __call__(cls,*args,**kw):
if cls.instance is None:
cls.instance = super(Singleton, cls).__call__(*args, **kw)
return cls.instance
class MyClass(object):
__metaclass__ = Singleton
See this implementation from PEP318, implementing the singleton pattern with a decorator:
def singleton(cls):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls()
return instances[cls]
return getinstance
#singleton
class MyClass:
...
The Python documentation does cover this:
class Singleton(object):
def __new__(cls, *args, **kwds):
it = cls.__dict__.get("__it__")
if it is not None:
return it
cls.__it__ = it = object.__new__(cls)
it.init(*args, **kwds)
return it
def init(self, *args, **kwds):
pass
I would probably rewrite it to look more like this:
class Singleton(object):
"""Use to create a singleton"""
def __new__(cls, *args, **kwds):
"""
>>> s = Singleton()
>>> p = Singleton()
>>> id(s) == id(p)
True
"""
it_id = "__it__"
# getattr will dip into base classes, so __dict__ must be used
it = cls.__dict__.get(it_id, None)
if it is not None:
return it
it = object.__new__(cls)
setattr(cls, it_id, it)
it.init(*args, **kwds)
return it
def init(self, *args, **kwds):
pass
class A(Singleton):
pass
class B(Singleton):
pass
class C(A):
pass
assert A() is A()
assert B() is B()
assert C() is C()
assert A() is not B()
assert C() is not B()
assert C() is not A()
It should be relatively clean to extend this:
class Bus(Singleton):
def init(self, label=None, *args, **kwds):
self.label = label
self.channels = [Channel("system"), Channel("app")]
...
As the accepted answer says, the most idiomatic way is to just use a module.
With that in mind, here's a proof of concept:
def singleton(cls):
obj = cls()
# Always return the same object
cls.__new__ = staticmethod(lambda cls: obj)
# Disable __init__
try:
del cls.__init__
except AttributeError:
pass
return cls
See the Python data model for more details on __new__.
Example:
#singleton
class Duck(object):
pass
if Duck() is Duck():
print "It works!"
else:
print "It doesn't work!"
Notes:
You have to use new-style classes (derive from object) for this.
The singleton is initialized when it is defined, rather than the first time it's used.
This is just a toy example. I've never actually used this in production code, and don't plan to.
I'm very unsure about this, but my project uses 'convention singletons' (not enforced singletons), that is, if I have a class called DataController, I define this in the same module:
_data_controller = None
def GetDataController():
global _data_controller
if _data_controller is None:
_data_controller = DataController()
return _data_controller
It is not elegant, since it's a full six lines. But all my singletons use this pattern, and it's at least very explicit (which is pythonic).
The one time I wrote a singleton in Python I used a class where all the member functions had the classmethod decorator.
class Foo:
x = 1
#classmethod
def increment(cls, y=1):
cls.x += y
Creating a singleton decorator (aka an annotation) is an elegant way if you want to decorate (annotate) classes going forward. Then you just put #singleton before your class definition.
def singleton(cls):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls()
return instances[cls]
return getinstance
#singleton
class MyClass:
...
There are also some interesting articles on the Google Testing blog, discussing why singleton are/may be bad and are an anti-pattern:
Singletons are Pathological Liars
Where Have All the Singletons Gone?
Root Cause of Singletons
I think that forcing a class or an instance to be a singleton is overkill. Personally, I like to define a normal instantiable class, a semi-private reference, and a simple factory function.
class NothingSpecial:
pass
_the_one_and_only = None
def TheOneAndOnly():
global _the_one_and_only
if not _the_one_and_only:
_the_one_and_only = NothingSpecial()
return _the_one_and_only
Or if there is no issue with instantiating when the module is first imported:
class NothingSpecial:
pass
THE_ONE_AND_ONLY = NothingSpecial()
That way you can write tests against fresh instances without side effects, and there is no need for sprinkling the module with global statements, and if needed you can derive variants in the future.
The Singleton Pattern implemented with Python courtesy of ActiveState.
It looks like the trick is to put the class that's supposed to only have one instance inside of another class.
class Singleton(object[,...]):
staticVar1 = None
staticVar2 = None
def __init__(self):
if self.__class__.staticVar1==None :
# create class instance variable for instantiation of class
# assign class instance variable values to class static variables
else:
# assign class static variable values to class instance variables
class Singeltone(type):
instances = dict()
def __call__(cls, *args, **kwargs):
if cls.__name__ not in Singeltone.instances:
Singeltone.instances[cls.__name__] = type.__call__(cls, *args, **kwargs)
return Singeltone.instances[cls.__name__]
class Test(object):
__metaclass__ = Singeltone
inst0 = Test()
inst1 = Test()
print(id(inst1) == id(inst0))
OK, singleton could be good or evil, I know. This is my implementation, and I simply extend a classic approach to introduce a cache inside and produce many instances of a different type or, many instances of same type, but with different arguments.
I called it Singleton_group, because it groups similar instances together and prevent that an object of the same class, with same arguments, could be created:
# Peppelinux's cached singleton
class Singleton_group(object):
__instances_args_dict = {}
def __new__(cls, *args, **kwargs):
if not cls.__instances_args_dict.get((cls.__name__, args, str(kwargs))):
cls.__instances_args_dict[(cls.__name__, args, str(kwargs))] = super(Singleton_group, cls).__new__(cls, *args, **kwargs)
return cls.__instances_args_dict.get((cls.__name__, args, str(kwargs)))
# It's a dummy real world use example:
class test(Singleton_group):
def __init__(self, salute):
self.salute = salute
a = test('bye')
b = test('hi')
c = test('bye')
d = test('hi')
e = test('goodbye')
f = test('goodbye')
id(a)
3070148780L
id(b)
3070148908L
id(c)
3070148780L
b == d
True
b._Singleton_group__instances_args_dict
{('test', ('bye',), '{}'): <__main__.test object at 0xb6fec0ac>,
('test', ('goodbye',), '{}'): <__main__.test object at 0xb6fec32c>,
('test', ('hi',), '{}'): <__main__.test object at 0xb6fec12c>}
Every object carries the singleton cache... This could be evil, but it works great for some :)
My simple solution which is based on the default value of function parameters.
def getSystemContext(contextObjList=[]):
if len( contextObjList ) == 0:
contextObjList.append( Context() )
pass
return contextObjList[0]
class Context(object):
# Anything you want here
Being relatively new to Python I'm not sure what the most common idiom is, but the simplest thing I can think of is just using a module instead of a class. What would have been instance methods on your class become just functions in the module and any data just becomes variables in the module instead of members of the class. I suspect this is the pythonic approach to solving the type of problem that people use singletons for.
If you really want a singleton class, there's a reasonable implementation described on the first hit on Google for "Python singleton", specifically:
class Singleton:
__single = None
def __init__( self ):
if Singleton.__single:
raise Singleton.__single
Singleton.__single = self
That seems to do the trick.
Singleton's half brother
I completely agree with staale and I leave here a sample of creating a singleton half brother:
class void:pass
a = void();
a.__class__ = Singleton
a will report now as being of the same class as singleton even if it does not look like it. So singletons using complicated classes end up depending on we don't mess much with them.
Being so, we can have the same effect and use simpler things like a variable or a module. Still, if we want use classes for clarity and because in Python a class is an object, so we already have the object (not and instance, but it will do just like).
class Singleton:
def __new__(cls): raise AssertionError # Singletons can't have instances
There we have a nice assertion error if we try to create an instance, and we can store on derivations static members and make changes to them at runtime (I love Python). This object is as good as other about half brothers (you still can create them if you wish), however it will tend to run faster due to simplicity.
In cases where you don't want the metaclass-based solution above, and you don't like the simple function decorator-based approach (e.g. because in that case static methods on the singleton class won't work), this compromise works:
class singleton(object):
"""Singleton decorator."""
def __init__(self, cls):
self.__dict__['cls'] = cls
instances = {}
def __call__(self):
if self.cls not in self.instances:
self.instances[self.cls] = self.cls()
return self.instances[self.cls]
def __getattr__(self, attr):
return getattr(self.__dict__['cls'], attr)
def __setattr__(self, attr, value):
return setattr(self.__dict__['cls'], attr, value)