I think Borg is an antipattern. It is a terrible, unpythonic concept that is just going to hurt every codebase it touches by breaking basic assumptions about the way objects work, to implement something that could also be implemented in a million other ways. You have not managed to make any argument in the other direction that I think hold merit.
When I mean is that you need to get some Core Developers on your side, and I am not one of them.
Well, then this is the wrong place for you. This category, Ideas, is about discussing ideas and determining if they would fit into python. āDiscussingā means different people having different opinions and making arguments to convince others.
When you revisit Borg (IMO, Borg is even worse conceptually than Singletons, but apparently I am a bit more alone with that), you will need to provide arguments then.
But your goal, if you want to get this implemented, must be to change that.
Dontā tell me about patterns, tell me how itās useful. If you want a bunch of things that only take one space in memory⦠isnāt that just one object? Python gives you that for free. Just use the same object.
It can with a simple counter. Thatās how a GC with a refcount works.
For Singleton, I suspect a module is already enough, as Chris said.
Iām waiting as the others some real use case for Borgs. Maybe there are some that I canāt think about. But until now it seems a solution in search of a problem.
Iām tempted anyway to give a +1 only for the name
I am fairly aware of the meaning of a discussion, thank you very much
What I had meant is that I seem to be very much alone in here. And with such
overwhelming response from the community, I donāt think itās very useful for me
right now to try and save an idea with clearly visible holes in them.
It is hubris for me to think I know more than core developers with decades; and
discussing is very much not trying to defend an idea just for the sake of it.
I have tried to hold what I proposed up to scrutiny ā and there are clearly flaws in it.
I believe there are better things to do than to try and push an idea that is deeply unpopular.
Obviously. But that is done through proper study and thought. I have learnt the lessons
and before I say anything else I will come indeed better prepared.
Not so much as a full drop. But I absolutely acknowledge the defeat.
Iām glad though, I came out knowing more. And I hope to come back with
a proper proposal.
I think this is a very valid point. And one I donāt want to just answer away with a BS example.
Tbh, I was not hoping for the community to feel this strongly against it. But since Iām
not the owner of any absolute truth, it does mean that odds are, I am in the wrong.
I will read more deeply and test. And come back with a better plan and better grounding.
Thank you for the input so far, really.
And working in a different route, if you see ways forward to reshape the idea, Iām all ears
FWIW I have a kind of āSingletonā that supports equivalence classes based the constructor args. It looks something like this:
class SingletonMeta(type):
"""
Metaclass that makes classes into singletons keyed on their ``__init__`` args
When an instance of the class is created, if an instance already existed with the same
arguments, the existing instance is returned. For example::
>>> class A(metaclass=SingletonMeta):
... def __init__(self, x):
... self.x = x
...
>>> A(1) is A(1)
True
>>> A(1) is A(2)
False
.. warning::
Because instances are keyed on their constructor args, those arguments must always be
hashable. This is not enforced, however, by the type system.
By default the storage for a singleton is global and persists for the lifetime of the
application. However, if you mark the class with the ``thread_local = True`` class attribute,
its storage is thread/context-local.
"""
thread_local: ClassVar[bool] = False
def __init__(self, name: str, bases: tuple[type, ...], members: dict[str, object]) -> None:
super().__init__(name, bases, members)
if self.thread_local:
self._instances: InstancesContainer = ThreadlocalInstancesContainer()
else:
self._instances = GlobalInstancesContainer()
def __call__(self, *args: object, **kwargs: object) -> object:
sig = signature(self.__init__) # type: ignore[misc]
bound = sig.bind_partial(None, *args, **kwargs)
bound.apply_defaults()
key = (self, bound.args[1:], tuple(bound.kwargs.items()))
if key in self._instances.instances:
return self._instances.instances[key]
inst = super().__call__(*args, **kwargs)
self._instances.instances[key] = inst
return inst
Of course, whether or not this is a āgood ideaā is maybe an aesthetic preference. And of course all args and values of kwargs must be hashable (IIRC mypy didnāt enforce this though so I just left it as object for now).
I fully agree that the outlook of getting this into the stdlib is basically zero. If that is opās goal with furthering the discussion it would save time and energy to drop it.
If you mainly want to continue the discussion and understand why so many are sceptical to the need of the patterns that may still be possible.
While very many threads here in Ideas seem to have that as their only goal and tend to take take energy explaining that Iām not convinced all of them arenāt also an attempt to, or at least open to transition to, instead getting feedback and understanding of why it may not be reasonable.
In the effort of averting the former kind (which definitely can be a problem) itās very easy to appear very hostile towards the former if you donāt have that background in mind.
This is not a direct critique of the responses I quoted (I have very high respect for both) but rather just an observation of this and other threads.
If you give up your goal of getting the idea into the language/stdlib, then you should move your thread out of the Ideas category if you still want to continue the discussion. The category is already poorly moderated - further muddling the waters by allowing non-ideas is just going to make the problem worse.
But this is just getting dragged off-topic into the age old discussion āwhat is this category forā. The above is part of my opinion on that.
As it is ā yes. I think that any further attempt at anything like it must require a rethinking of how this is done. Maybe switching from metaclass shenanigans to a decorator-based approach.
I would very much appreciate input on this regard. I do agree with several of the counterarguments presented ā and I think the usecase of the singleton is smaller than I first considered (and Iāll reconsider their usage going forward).
I still think there may be some uses in situations where class instantiation is a consequence of some file that is codegened at runtime (where I first thought of it), and itās easier to have some Borg(āfooā) that is interchangable with MyObj(ābarā) at runtime for nested data structures where there is a lot of repetition.
If I think that is worth the addition to stdlib? Iām more cautious now.
Honestly, Iād like your opinion on the whole thing.
Iām taking this thread as an early peer-review. Serious and meaningful criticisms have been placed at the idea. Itās pointless to just re-iterate in a shallow way.
Not sure if I agree with you there. I think it is useful to keep the record of the rejected ideas. I did search before posting, and if I found a clear thread like this, I wouldnāt waste time proposing something that had been clearly rejected before ā but Iām not the one moderating.
Again, Iām not a moderator, so this is above what I can decide, but I do feel like rejected ideas should not be moved out. The negative space is important to understand what is and isnāt a good way forward when opening a thread
And my goal here was never just pushing an idea for the sake of it. I think that that sort of position is not how things should move if quality is the objective.
It all depends on how much more discussion you want to have about it AFTER itās no longer a viable idea. Continuing the discussion isnāt about an idea any more after that, itās about discussion of the concept, which belongs in the general category.
Well, what I had meant is that maybe rejected ideas should have a place where they live specifically. This way, the next person with a similar idea can visit the conversation before posting.
With regard to it not being a viable idea, yes. As it is, it has been rejected and thatās what it is.
I would like your thoughts on it though. Do you see any positive argument for a more standard way to make a singleton (not necessarily a metaclass)?
I donāt think changing the mechanics or API of a singleton would alter the view that, to the extent singletons are useful, Python already provides an effective and widely accepted way to implement them.