How to create a singleton class based on its input? - python

I have a class defined as
class Conditional_Singleton(object):
def __init__(self, condition=None):
self.initialization = some_func_of(condition)
Since the "initialization" step really takes a lot of time to run and the output could be huge, I would really like that the class not be recreated over and over again given the same input, but do so once the input changes. Any ideas?

class Conditional_Singleton(object):
saved_insances = {}
def __new__(cls, condition = None):
if not condition in cls.saved_instances:
cls.saved_instances[condition] = super(
Conditional_Singleton, cls).__new__(cls)
return cls.saved_instances[condition]
def __init__(self, condition = None):
if not hasattr(self, 'initialization'):
self.initialization = some_func_of(condition)
This will save the dict of created instances in the class itself and automatically reuse them if the same condition is passed.
Edit: Just saw your comment. You need to find a good way to hash condition for this to work, so unless it derives from a class that implements __hash__, you need to implement it yourself.
Edit 2: Using __new__ instead of __init__ for the singleton.

You could potentially do something like this:
myInstances = {}
myInstances['condition'] = Conditional_Singleton('condition')
In other parts of your code you'd do something like this:
if 'condition' in myInstances:
# something down here that works with that instance
Whether or not that fits with your requirement is going to depend on whether or not you can simplify conditions to be something hashable for use as a dictionary key.

Related

Dynamically bind an instance method to class (not to class instance) in Python

Description & What I've tried:
I have seen many posts in stackoverflow about binding methods to class instances (I'm aware there are bunch of duplicates already).
However I havent found a discussion referring to binding a method to the class itself. I can think of workarounds but I'm curious if there is a simple way to achieve following:
import types
def quacks(some_class):
def quack(self, number_of_quacks):
self.number_of_quacks = number_of_quacks
setattr(some_class, "quack", types.MethodType(quack, some_class))
return some_class
#quacks
class Duck:
pass
but above would not work:
d1 = Duck()
d2 = Duck()
d1.quack(1)
d2.quack(2)
print(d2.number_of_quacks)
# 2
print(d1.number_of_quacks)
# 2
because quack is actually modifying the class itself rather than the instance.
There are two workarounds I can think of. Either something like below:
class Duck:
def __init__(self):
setattr(self, "quack", types.MethodType(quack, self))
or something like
class Quacks:
def quack(self, number_of_quacks):
self.number_of_quacks = number_of_quacks
class Duck(Quacks):
pass
Question:
So my question is, is there a simple way to achieve the simple #quacks class decorator I described above?
Why I'm asking:
I intend to create a set of functions to modularly add common methods I use to classes. If I dont quit this project, the list is likely to grow over time and I would prefer to have it look nice on code definition. And as a matter of taste, I think option 1 below looks nicer than option 2:
# option 1
#quacks
#walks
#has_wings
#is_white
#stuff
class Duck:
pass
# option 2
class Duck(
Quacks,
Walks,
HasWings,
IsWhite,
Stuff):
pass
If you don't mind changing your desired syntax completely to get the functionality you want, you can dynamically construct classes with type (see second signature).
The first argument is the name of the class, the second is a tuple of superclasses, and the third is a dictionary of attributes to add.
Duck = type("Duck", (), {
"quack", quack_function,
"walk", walk_function,
...
})
So, instead of decorators that inject the appropriate functionality after creation, you are simply adding the functionality directly at the time of creation. The nice thing about this method is that you can programatically build the attribute dictionary, whereas with decorators you cannot.
Found another workaround, I guess below would do it for me.
def quacks(some_class):
def quack(self, number_of_quacks):
self.number_of_quacks = number_of_quacks
old__init__ = some_class.__init__
def new__init__(self, *args, **kwargs):
setattr(self, "quack", types.MethodType(quack, self))
old__init__(self, *args, **kwargs)
setattr(some_class, "__init__", new__init__)
return some_class
Feel free to add any other alternatives, or if you see any drawbacks with this approach.
Edit: a less hacky way inspired from #SethMMorton's answer:
def quack(self, number_of_quacks):
self.number_of_quacks = number_of_quacks
def add_mixin(some_class, some_fn):
new_class = type(some_class.__name__, (some_class,), {
some_fn.__name__: some_fn
})
return new_class
def quacks(some_class):
return add_mixin(some_class, quack)
#quacks
class Duck:
pass
d1 = Duck()
d2 = Duck()
d1.quack(1)
d2.quack(2)
print(d1.number_of_quacks)
print(d2.number_of_quacks)

Don't break if class instance is passed as initialization argument

I'm trying to add flexibility to a python class, so that it notices when one of the init arguments is already an instance of that class. Skip "Initial situation" if you don't mind, how I got here.
Initial situation
I have this class:
class Pet:
def __init__(self, animal):
self._animal = animal
#property
def present(self):
return "This pet is a " + self._animal
...
and there are many functions which accept an instance of this class as an argument (def f(pet, ...)). Everything worked as expected.
I then wanted to add some flexibility to the usage of these functions: if the caller passes a Pet instance, everything keeps on working as before. In all other cases, a Pet instance is created. One way to achieve that, is like this:
def f(pet_or_animal, ...):
if isinstance(pet_or_animal, Pet): #Pet instance was passed
pet = pet_or_animal
else: #animal string was passed
pet = Pet(pet_or_animal)
...
This also works as expected, but these lines are repeated in every function. Not DRY, not good.
Goal
So, I'd like to extract the if/else from each of the functions, and integrate it into the Pet class itself. I tried changing its __init__ method to
class PetA: #I've changed the name to facilitate discussion here.
def __init__(self, pet_or_animal):
if isinstance(pet_or_animal, PetA):
self = pet_or_animal
else:
self._animal = pet_or_animal
...
and start each function with
def f(pet_or_animal, ...):
pet = PetA(pet_or_animal)
...
However, that is not working. If a Pet instance is passed, everything is good, but if a string is called, a Pet instance is not correctly created.
Current (ugly) solution
What is working, is to add a class method to the class, like so:
class PetB: #I've changed the name to facilitate discussion here.
#classmethod
def init(cls, pet_or_animal):
if isinstance(pet_or_animal, PetB):
return pet_or_animal
else:
return cls(pet_or_animal)
def __init__(self, animal):
self._animal = animal
...
and also change the functions to
def f(pet_or_animal, ...):
pet = PetB.init(pet_or_animal) #ugly
...
Questions
Does anyone know, how to change class PetA so, that it has the intended behavior? To be sure, here is the quick test:
pb1 = PetB.init('dog')
pb2 = PetB.init(pb1) #correctly initialized; points to same instance as pb1 (as desired)
pa1 = PetA('cat')
pa2 = PetA(pa1) #incorrectly initialized; pa1 != pa2
More generally, is this the right way to go about adding this flexibility? Another option I considered was writing a separate function to just do the checking, but this too is rather ugly and yet another thing to keep track of. I'd rather keep everything neat and wrapped in the class itself.
And one final remark: I realize that some people might find the added class method (petB) a more elegant solution. The reason I prefer to add to the __init__ method (petA) is that, in my real-world use, I already allow for many different types of initialization arguments. So, there is already a list of if/elif/elif/... statements that check, just which of the possibilities is used by the creator. I'd like to extend that by one more case, namely, if an initialized instance is passed.
Many thanks
I believe your current "ugly" solution is actually the correct approach.
This pushes the flexibility up as far as possible, since it is messy. Even though python allows for arbitrary types and values to float around, your users and yourself will thank you for keeping that constrained to the outermost levels.
I would think of it as (don't need to implement it this way)
class Pet:
#classmethod
def from_animal(cls, ...):
...
#classmethod
def from_pet(cls, ...):
...
#classmethod
def auto(cls, ...):
if is_pet(...):
return cls.from_pet(...)
def __init__(cls, internal_rep):
...
etc.
It is a code smell if you don't know whether your function is taking an object or an initializer. See if you can do processing as up-front as possible with user input and standardize everything beyond there.
You could use a function instead to get the same behaviour you want:
def make_pet_if_required(pet_or_animal):
if isinstance(pet_or_animal, PetA):
return pet_or_animal
else:
return Pet(pet_or_animal)
And then:
def f(pet_or_animal, ...):
pet = make_pet_if_required(pet_or_animal)
...
For more "beauty" you can try turning that function call into a decorator.

Switch case like mapping of a dictionary (values = methods)

As I'm fairly new python, I can't decide which of the following two solutions makes more sense, or maybe no sense at all.
Let's say my abstracted object class look like:
class SimpleData(object):
def __init__(self, data):
self.__data = data
def __getData(self):
return self.__data
def __setData(self, data):
self.__data = data
data = property(__getData, __setData)
#classmethod
def create_new(cls, data):
return cls(data)
Objects of this class, that I need frequently (having a 'predifined object payload'), I'd like to simply create by 'assigning' a preset_name to them. Using the preset_name I can create new copies of those specific objects, having that predefined payload, repeatedly.
I could use a dictionary:
class PresetDict(object):
#classmethod
def get_preset(cls, preset_name):
return {
'preset_111': SimpleData.create_new('111'),
'preset_222': SimpleData.create_new('222'),
'preset_333': SimpleData.create_new('333')
}.get(preset_name, None)
or map methods, using getattr:
class PresetMethod(object):
#classmethod
def get_preset(cls, preset_name):
return getattr(cls, preset_name, lambda: None)()
#classmethod
def preset_111(cls):
return SimpleData.create_new('111')
#classmethod
def preset_222(cls):
return SimpleData.create_new('222')
#classmethod
def preset_333(cls):
return SimpleData.create_new('333')
Both solutions do basically the same:
print(PresetDict.get_preset("preset_111").data)
print(PresetDict.get_preset("preset_333").data)
print(PresetDict.get_preset("not present"))
print(PresetMethod.get_preset("preset_111").data)
print(PresetMethod.get_preset("preset_333").data)
print(PresetMethod.get_preset("not present"))
I strongly prefer the dictionary solution, as it is easier to 'read', extend and will be easier to maintain in the future, especially with a big list of presets.
Here's the BUT:
Performace is of importance. Here, I have absolutely no insight, which of those two solutions will perform better, especially if the preset list grows. Especially the dictionary in PresetDict.get_preset looks 'dodgy' to me. Will it create only the SimpleData instance specified via 'preset_name' when called, or will it create all possible instances specified in the dictionary when PresetDict.get_preset is called, then return the instance specified via 'preset_name' and then discard all other instances.
Hope you can enlighten me on this matter. Maybe you know of possible improvements or even a better solution of what I'd like to achieve?
Thx in advance!
you're right, PresetDict.get_preset will create all three objects and then return one. You could just add a class variable to SimpleData that holds the dictionary so it is only created once, and the get_preset can return instances from that
class SimpleData(object):
_presets = {
'preset_111': SimpleData('111'),
'preset_222': SimpleData('222'),
'preset_333': SimpleData('333')
}
#classmethod
def get_preset(cls, preset_name):
return cls._presets.get(preset_name, None)
Note that this isn't really any more efficient, it will just make it easier to create commonly used classes.
Also see functools.lru_cache

How to change the behavior of append for a class attribute

I am using a python package (simpy), which provides several classes that I need. One of the classes is called Event, with the following constructor:
def __init__(self, env):
self.env = env
"""The :class:`~simpy.core.Environment` the event lives in."""
self.callbacks = []
"""List of functions that are called when the event is processed."""
self._value = PENDING
At many different places in the code, objects are added to the callbacks of an event, using the Event.callbacks.append method.
What I need is a new class (which i call Zombie), which is actually an Event class, except for three modifications. Firstly, it should contain an additional attribute Zombie.reset_callbacks and a method Zombie.reset() to reset Zombie.callbacks to a previous state (this is why I need the Zombie.reset_callbacks attribute. All of this, I can do by subclassing Event.
However, for this to work, I would need that everytime Zombie.callbacks.append(x) is called, xis not only appended to Zombie.callbacks, but also Zombie.reset_callbacks. I have been looking into decorators to see if I could do this, but I do not see the light at the end of the tunnel. I currently feel this is not possible, or I might be looking in wrong directions.
Is such thing possible (changing the append behavior for a class attribute) in Python? And if so, how?
Thanx for your effort in advance!
B.
Whoops. Misread this. If you're really dedicated to maintaining this interface, you can define a helper class.
class SplitLists(object):
def __init__(*append_methods):
self._append_methods = append_methods
def append(self, value):
for method in self._append_methods:
method(value)
a = []
b = []
split_list = SplitLists(a.append, b.append)
split_list.append(1)
a # [1]
b # [1]
class Zombie(Event):
def __init__(self, *args, **kwargs):
super(Zombie, self).__init__(*args, **kwargs)
self._real_callbacks = []
self._reset_callbacks = []
self.callbacks = SplitLists(self._real_callbacks.append,
self._reset_callbacks.append)

do's and don'ts of __init__ method

I was just wondering if it's considered wildly inappropriate, just messy, or unconventional at all to use the init method to set variables by calling, one after another, the rest of the functions within a class. I have done things like, self.age = ch_age(), where ch_age is a function within the same class, and set more variables the same way, like self.name=ch_name() etc. Also, what about prompting for user input within init specifically to get the arguments with which to call ch_age? The latter feels a little wrong I must say. Any advice, suggestions, admonishments welcome!
I always favor being lazy: if you NEED to initialize everything in the constructor, you should--in a lot of cases, I put a general "reset" method in my class. Then you can call that method in init, and can re-initialize the class instance easily.
But if you don't need those variables initially, I feel it's better to wait to initialize things until you actually need them.
For your specific case
class Blah1(object):
def __init__(self):
self.name=self.ch_name()
def ch_name(self):
return 'Ozzy'
you might as well use the property decorator. The following will have the same effect:
class Blah2(object):
def __init__(self):
pass
#property
def name():
return 'Ozzy'
In both of the implementations above, the following code should not issue any exceptions:
>>> b1 = Blah1()
>>> b2 = Blah2()
>>> assert b1.name == 'Ozzy'
>>> assert b2.name == 'Ozzy'
If you wanted to provide a reset method, it might look something like this:
class Blah3(object):
def __init__(self, name):
self.reset(name)
def reset(self, name):
self.name = name

Categories

Resources