How to always use the same instance of a class in Python? - python

I am using the following solution to maintain a list of classes instances: https://stackoverflow.com/a/12102163
Now I want to use that list to make sure that there is always only one instance of the class. Renewed initializations of the class should return the one existing instance.
The code I have is:
class MyClass:
instances = []
def __init__(self):
if not MyClass.instances:
self.data=1234
else:
self = MyClass.instances[0]
So:
>> a=MyClass()
>> a.data
1234
And b=MyClass() should return the same instance as a. This is not working. What is wrong with my code?
EDIT: OK, so it turns out I am looking for the singleton pattern, but couldn't recreate it myself. Can anyone please explain why my code does not work?

Going on your code line and your style. You can make following modifications:-
class MyClass:
instance = None
def __init__(self):
self.data=1234
MyClass.instance = self
def get_myclass():
if MyClass.instance:
return MyClass.instance
return MyClass()
get_myclass would be a wrapper function for creating class objects. Trying the code.
>>> import instance
>>> a=instance.get_myclass()
>>> b=instance.get_myclass()
>>> a is b
True

Here's an example of the Singleton metaclass recipe. This example is from Ch. 9 of The Python Cookbook.
class Singleton(type):
def __init__(self, *args, **kwargs):
self.__instance = None
super().__init__(*args, **kwargs)
def __call__(self, *args, **kwargs):
if self.__instance is None:
self.__instance = super().__call__(*args, **kwargs)
return self.__instance
else:
return self.__instance
# Example
class Spam(metaclass=Singleton):
def __init__(self):
print('Creating Spam')
if __name__ == '__main__':
a = Spam()
b = Spam()
assert a is b

There's actually a quite simple solution to use the same instance of a class in Python. Here's a demo example:
#### module1.py ####
class MyClass1:
...
# Create an instance of the class in the same module!
my_class_1 = MyClass1()
#############################################################################
#############################################################################
#### module2.py ####
# Here import the instance (not the class!) from module1
from module1 import my_class_1
class MyClass2:
# Do stuff to my_class_1
...
#############################################################################
#############################################################################
#### module3.py ####
# Here also import the instance (not the class!) from module1
from module1 import my_class_1
class MyClass3:
# Also do stuff to my_class_1
...
In the example above, no matter which module (whether module2.py or module3.py) changes data of the my_class_1 instance, the changed data is reflected in both modules synchronously.

Related

Enumerate instance methods in Python

I would like to enumerate some instance methods inside a class. The operate function needs to use foo1, foo2,.. as Foo.FOO1, Foo.FOO2,.. .
class Machine:
def __init__(self):
self.operate()
def foo1(self):
pass
def foo2(self):
pass
..
class Foo(Enum):
FOO1 = Machine.foo1 # Machine is not defined
FOO2 = Machine.foo2 # Machine is not defined
..
def operate(self):
# use self.Foo.FOO1, self.Foo.FOO2,..
I do not know how to define the enum class.
The solution proposed by #giannisl9 is bugged, although it apparently works at first sight, a closer inspection reveals the Enum is broken:
from enum import Enum
class Machine:
def __init__(self):
class Foo(Enum):
FOO1 = self.foo1
self.foo = Foo
self.operate()
def foo1(self):
pass
def operate(self):
# breaks Enum contract, breaks syntax, breaks functionality...
self.foo.FOO1() # Enum member is NOT available! Method of class Machine bound in its place.
print(type(self.foo)) # {type}<class'enum.EnumMeta'> - Enum 'Foo'
print(type(self.foo.FOO1)) # {type} <class 'method'> - should be Enum member
print(type(self.foo.FOO1.name)) # {AttributeError}'function'object has no attribute 'name'
print(type(self.foo.FOO1.value)) # {AttributeError}'function'object has no attribute 'value'
Building on the answer by #Epic Programmer -since the original question only stated as requirement defining an Enum to run instance methods- given the application, organizing procedures in the __init__ or other methods, could suffice:
from inspect import ismethod
from inspect import isbuiltin
class Machine(object):
def operate(self):
for method in self.__dir__():
if ismethod(getattr(self, method)) \
and not isbuiltin(getattr(self, method)) \
and '__' not in method \
and 'operate' != method: # delete this to see a recursion
self.__getattribute__(method)() # after much filtering runs the method
def __init__(self):
self.operate()
def foo1(self):
print("drinks at bar1")
However, as I understand the question, it makes perfect sense the Enum should be internal to the class, since ontologically it pertains to encode/abbreviate a set of states proper to all instances of the class. That makes lots of sense!
It doesn't make much sense declaring it inside the __init__ as a self instance constant. Instead, it should be used as a symbolic class constant allowing to encode everything that in common may pertain to the instances.
from enum import Enum
class Machine:
class Foo(Enum):
# you could comma separate any combination for a given state
FOO1 = "foo1"
FOO2 = "foo2"
def __init__(self, arg_foo):
self.foo = arg_foo
self.operate()
self.all_operations()
def foo1(self):
print('drinks at bar1')
def foo2(self):
print('drinks at bar2')
def all_operations(self):
for one_member in Machine.Foo:
self.__getattribute__(one_member.value)()
def operate(self):
self.__getattribute__(str(self.foo.value))()
go_bar1 = Machine(Machine.Foo.FOO1)
go_bar2 = Machine(Machine.Foo.FOO2)
go_bar1.all_operations() # bar crawl
Or perhaps this is, approximately, what you're looking for:
from enum import Enum
class Machine:
def __init__(self, receive: Enum):
for one in receive.value:
if one is not None:
one(self) # Zen of Python
def foo1(self):
print('drinks at bar1')
def foo2(self):
print('drinks at bar2')
class Runner(Enum):
FOO1 = getattr(Machine, 'foo1'), getattr(Machine, 'foo2')
FOO2 = getattr(Machine, 'foo2'), None
first = Machine(Runner.FOO1)
second = Machine(Runner.FOO2)
I hope this helps.
Provided all methods in the Foo class that do not start with _ are methods you want to use, just iterate over the contents of the Foo class and get the attributes of the methods that match:
class Machine:
def operate(self):
for attribute in dir(self.Foo):
if attribute[0] != "_":
getattr(self.Foo, attribute)()
Following How to use class name in class scope?
and what made the most sense for my case, defining the enum inside the init method seems the way to go.
class Machine:
def __init__(self):
class Foo(Enum):
FOO1 = self.foo1
FOO2 = self.foo2
..
self.Foo = Foo
self.operate()
def foo1(self):
pass
def foo2(self):
pass
..
def operate(self):
#self.Foo.FOO1(), self.Foo.FOO2(),.. availabe
#self.Foo holds the enumeration

Make Python module classes able to be called from a separate class

I currently have a module, my_module, which contains classes.py:
from . import config
class Class1:
#staticmethod
def method_one(x)
return x + config.constant
#staticmethod
def method_two(y)
return x - config.constant
My problem is that I want to be able to have multiple instances of the module with different values for config.constant. Ideally, I'd have a new class called MyClass where the constant would be an instance variable, so that this would work:
instance1 = MyClass(5)
instance1.Class1.method_one(5) # 10
instance2 = MyClass(0)
instance2.Class1.method_one(5) # 5
Is there a way to do this without modifying the classes which are in my_module?
Make it a staticmethod.
class MyClass(object):
#staticmethod
def my_method(num):
return num + num
Then you can use it from another file by doing(assuming the file is my_module.py:
import my_module
my_module.MyClass.my_method(2)
>>>4
my_module.py
def __init__(self, constant):
self.constant = constant
def my_method(self, num):
return self.constant + num
some_other_file.py
import my_module
MyClass = type('MyClass', (), my_module.__dict__)
my_instance = MyClass(3)
my_instance.my_method(4)
>>> 7

python equivalent of functools 'partial' for a class / constructor

I want to create a class that behaves like collections.defaultdict, without having the usage code specify the factory. EG:
instead of
class Config(collections.defaultdict):
pass
this:
Config = functools.partial(collections.defaultdict, list)
This almost works, but
isinstance(Config(), Config)
fails. I am betting this clue means there are more devious problems deeper in also. So is there a way to actually achieve this?
I also tried:
class Config(Object):
__init__ = functools.partial(collections.defaultdict, list)
I don't think there's a standard method to do it, but if you need it often, you can just put together your own small function:
import functools
import collections
def partialclass(cls, *args, **kwds):
class NewCls(cls):
__init__ = functools.partialmethod(cls.__init__, *args, **kwds)
return NewCls
if __name__ == '__main__':
Config = partialclass(collections.defaultdict, list)
assert isinstance(Config(), Config)
I had a similar problem but also required instances of my partially applied class to be pickle-able. I thought I would share what I ended up with.
I adapted fjarri's answer by peeking at Python's own collections.namedtuple. The below function creates a named subclass that can be pickled.
from functools import partialmethod
import sys
def partialclass(name, cls, *args, **kwds):
new_cls = type(name, (cls,), {
'__init__': partialmethod(cls.__init__, *args, **kwds)
})
# The following is copied nearly ad verbatim from `namedtuple's` source.
"""
# For pickling to work, the __module__ variable needs to be set to the frame
# where the named tuple is created. Bypass this step in enviroments where
# sys._getframe is not defined (Jython for example) or sys._getframe is not
# defined for arguments greater than 0 (IronPython).
"""
try:
new_cls.__module__ = sys._getframe(1).f_globals.get('__name__', '__main__')
except (AttributeError, ValueError):
pass
return new_cls
At least in Python 3.8.5 it just works with functools.partial:
import functools
class Test:
def __init__(self, foo):
self.foo = foo
PartialClass = functools.partial(Test, 1)
instance = PartialClass()
instance.foo
If you actually need working explicit type checks via isinstance, you can simply create a not too trivial subclass:
class Config(collections.defaultdict):
def __init__(self): # no arguments here
# call the defaultdict init with the list factory
super(Config, self).__init__(list)
You'll have no-argument construction with the list factory and
isinstance(Config(), Config)
will work as well.
Could use *args and **kwargs:
class Foo:
def __init__(self, a, b):
self.a = a
self.b = b
def printy(self):
print("a:", self.a, ", b:", self.b)
class Bar(Foo):
def __init__(self, *args, **kwargs):
return super().__init__(*args, b=123, **kwargs)
if __name__=="__main__":
bar = Bar(1)
bar.printy() # Prints: "a: 1 , b: 123"

Dynamically add class methods during class definition

I have a bunch of methods somewhere, already defined. I want a class to just be a collection of those methods.
def _a(self):
pass
def _b(self):
pass
#decorated()
class MyClass(object):
a = _a
b = _b
The decorator is written by someone else, and it does some analysis on the class immediately.
What I want is to stick those methods on the class, but they need to be on there before the decorator does its magic.
methods = { 'a': _a, 'b': _b }
#decorated(...)
class MyClass(object):
for name, impl in methods
# What goes here?
How can I do this. I assume it's some form of setattr(), but how do I get the target when it's the class I'm currently building?
Update
Current experiment is:
def merged(method_dict):
def _impl(cls):
for name, impl in method_dict.iteritems():
setattr(cls, name, impl)
return cls
return _impl
#decorated(...)
#merged(methods)
class MyClass(object):
c = _c
pass
The decorated decorator is reporting that it sees c, but not a or b
The problem is that as soon as your class is defined, it is immediately getting decorated, as you use the # syntax. Some alternatives are to go the way jonrsharpe and Ashwini Chaudhary suggested.
Also, another way you can do the thing, is wrapping the decorator into your custom one, where you will do your stuff and then only, manually decorate with the provided one, like this:
def your_decorator(func):
# your stuff
return decorated(func)
#your_decorator
class MyClass():
# ...
I'd go with what jonrsharpe suggested in the comments section: Instead of decorating the class using the # syntax, which decorates the class immediately after it's created, you should decorate it manually afterwards:
class MyClass:
pass
def _method_to_add_later(self):
pass
MyClass.method_to_add_later = _method_to_add_later
MyClass = decorated(...)(MyClass)
For example, may be right
def decorator(fn):
def _fn(*args, **kwargs):
print "Decorator"
fn(*args, **kwargs)
return _fn
#decorator
class MyClass(object):
def __init__(self):
print "Init"
def _a():
print "a"
def _b():
print "b"
if __name__ == '__main__':
methods = { 'a': _a, 'b': _b }
my = decorator(MyClass())
for name in methods:
setattr(my, name, methods[name])
my.a()
my.b()
Out:
Decorator
Init
a
b

What is a singleton/borg pattern? Why don't they work for me/where is my concept wrong?

Similar questions has been asked many times, but I have problems understanding it. I was thinking that the Singleton or Borg pattern can be used to create only one instance of an object, or to share its state. I have a (working) test example which does not work as I expect. Either the code is incorrect, or I misunderstand the concept of singleton/borg patterns.
I used a singleton and a borg pattern to create the following code in the file borg.py:
class Singleton(object):
_instance = None
def __new__(class_, *args, **kwargs):
if not isinstance(class_._instance, class_):
class_._instance = object.__new__(class_, *args, **kwargs)
return class_._instance
class MySingleton(Singleton):
def __init__(self):
self._list = []
def add(self,x):
self._list.append(x)
def get(self):
return self._list
class MyBorg(object):
__shared_state = {}
def __init__(self):
self.__dict__ = self.__shared_state
# and whatever else you want in your class -- that's all!
self._list = []
def add(self,x):
self._list.append(x)
def get(self):
return self._list
then a file module.py
from borg import MyBorg
myborg = MyBorg()
myborg.add(42)
print "just added something"
and finally the main code:
from borg import MyBorg
import module
myborg = MyBorg()
myborg.add(4711)
print myborg.get()
One should replace MyBorg by MySingleton in the latter two classes to use the Singleton instead of the borg.
Now, when I run the main code I clearly can see that modules.py is called first, adding a value to the list. After that, the Singleton/Borg pattern is also instantiated in the main code, and (another) value is added. I expected to have two values in the list (42 and 4711), instead I only have the latter value in the list.
It might be the case that the instance in module.py went out of scope and so whatever were done in module.py has been deleted. But what I need is some was of having an object to contain the same content, no matter where I use it.
How can I achieve this? How can I make sure, that when I create an instance of the object MyBorg (or whatever), it contains the value '42' in the list, as added in module.py? What pattern/mechanism should I use to achieve this?
The reason for the behavior you're seeing is that in both cases __init__ gets called every time you do instance = WhateverClass().
Note that you are passing the same instance around. However, that instance is getting it's _list attribute cleared in __init__.
class Singleton(object):
_instance = None
def __new__(class_, *args, **kwargs):
if not isinstance(class_._instance, class_):
class_._instance = object.__new__(class_, *args, **kwargs)
return class_._instance
class Foo(Singleton):
def __init__(self):
self.data = []
pass
a = Foo()
a.data.append('Never see this')
b = Foo()
print a is b #True
print a.data # []

Categories

Resources