0

So there is object.__new__(cls) and super().__new__(cls) functions could be used to create instance, but could I use type(name, bases, dict)(*args, **kwargs) to create instance?

class Singleton(object):

  instance = None

  def __init__(self, *args, **kwargs):
    pass

  def __new__(cls, *args, **kwargs):
    if isinstance(cls.instance, type(None)):
      mcls = cls.__class__
      cls.instance = type(mcls.__name__, mcls.__bases__, dict(cls.__dict__))(*args, *kwargs)

    return cls.instance

s = Singleton()
print(s)
Francesco Montesano
  • 8,485
  • 2
  • 40
  • 64
Heidll
  • 3
  • 4
  • 2
    Why are you doing this? – juanpa.arrivillaga Nov 09 '17 at 07:45
  • experimenting :) – Heidll Nov 09 '17 at 07:51
  • well, the error is pretty explicit, you are passing a `mappingproxy` instead of a `dict`, to argument 3, so do `dict(mcls.__dict__)`. Note, there's another error that I'm trying to figure out there... – juanpa.arrivillaga Nov 09 '17 at 07:56
  • Thanks, i had change to dict(mcls.__dict__) in result: TypeError: type __qualname__ must be a str, not getset_descriptor – Heidll Nov 09 '17 at 08:00
  • Yeah, so, what's going on there is that `type` has a descriptor for `__qualname__`. It expects a `str` apparently. – juanpa.arrivillaga Nov 09 '17 at 08:02
  • You should simplify this: you are trying to create a *metaclass* using `type`. This complicates things, and I'll admit, has my head scratching a bit. – juanpa.arrivillaga Nov 09 '17 at 08:04
  • also i had found that dict(cls.__dict__) is cause no errors. https://stackoverflow.com/questions/32720492/why-is-a-class-dict-a-mappingproxy but there come some maximum recursion error )) – Heidll Nov 09 '17 at 08:07
  • So, I would suggest re-writing your question and removing the unecessary context of being in a `__new__` implementation. What you are asking is why doesn't `type(type.__name__, type.__bases__, dict(type.__dict__))` work – juanpa.arrivillaga Nov 09 '17 at 08:07
  • So, when I define a metaclass explicitly, e.g. `class Meta(type): pass`, then `Meta.__dict__` returns `mappingproxy({'__doc__': None, '__module__': '__main__'})` – juanpa.arrivillaga Nov 09 '17 at 08:11
  • But again, **why** are you trying to create a metaclass that mimics `type` in all but ... identity? And yes, that may cause no errors, but neither would `{}`. – juanpa.arrivillaga Nov 09 '17 at 08:12
  • hmm with type(arg1,arg2,arg3) i can create any class right? so if i can create class i can create instance of it. I only wanted to be sure that there is no other ways to create instance of class then object.__new__(cls), super().__new__(cls). – Heidll Nov 09 '17 at 08:23
  • What? Can you elaborate in the question itself? – juanpa.arrivillaga Nov 09 '17 at 08:26
  • Sorry, added more description to question. – Heidll Nov 09 '17 at 08:36
  • You *can* do this, but then, `isinstance(s, Singleton)` would be *`False`*. Why do you want to do this??? Why are you trying to use the attributes from `type`, ie. `mcls`???? – juanpa.arrivillaga Nov 09 '17 at 08:38
  • I had see something like this in django source code for models, so trying to understand it on less complicated example – Heidll Nov 09 '17 at 08:42
  • But **why** are you using `mclas`? You realize `mclas is type`, right? – juanpa.arrivillaga Nov 09 '17 at 08:43
  • Without cls.__class__.__bases__ i can't use type to add superclasses to instance. Also in result of type(a1,a2,a3) i think that i have callable class, if i call it i will have instance or am i wrong? Also can you post answer i will mark it and close question. – Heidll Nov 09 '17 at 08:45
  • What do you mean? why are you using `cls.__class__.__bases__`, why not `(object,)`? – juanpa.arrivillaga Nov 09 '17 at 08:48
  • Youw ill have an instance, but note, this means your singleton instance, s, will have the property that `isinstance(s, Singleton) is False` – juanpa.arrivillaga Nov 09 '17 at 08:49
  • Becouse it's singleton and i want that instance has all class attributes, fields. methods ... etc including inheritence – Heidll Nov 09 '17 at 08:55
  • Then you want to use `cls` , not the metaclass. Again that is *`type`*... – juanpa.arrivillaga Nov 09 '17 at 08:55
  • Yes i know that isinstance will return false – Heidll Nov 09 '17 at 08:57
  • hmm are you sure about using cls and not cls.__class__ ? try this: '__bases__' in dir(cls) and '__bases__' in dir(cls.__class__) – Heidll Nov 09 '17 at 08:59
  • yes, so what? What is your point?? That's the `__bases__` descriptor. Do you understand what `cls.__class__` is?? – juanpa.arrivillaga Nov 09 '17 at 09:03
  • Can you post example how to create instance using type, please? – Heidll Nov 09 '17 at 09:05
  • 1
    `type('MyClass',(),{})()` – juanpa.arrivillaga Nov 09 '17 at 09:06
  • Note, btw, that `Singleton.__bases__` gives `(object,)`, so you **can** use `cls` and not `cls.__clas__`, which **doesn't make sense to begin with**. Why are you using the *metaclass* attributes to create an instance of the class? The *class* creates instances of the class, the metaclass creates the *class* – juanpa.arrivillaga Nov 09 '17 at 09:08
  • I had posted complete example – Heidll Nov 09 '17 at 09:14

1 Answers1

0

So i couldn't find the way to keep __new__ method in cls.__dict__ it leads to recoursion so i removed it before class creation.

class FooMixin(object):
  def print_somth(self):
    print('smth....')


class Singleton(FooMixin):

  instance = None

  def __new__(cls, *args, **kwargs):
    if cls.instance is None:
      temp = dict(cls.__dict__)
      del temp['__new__']
      temp['test'] = 100
      cls.instance = type('Singleton', cls.__bases__, temp)(*args, **kwargs)
    return cls.instance

s = Singleton()
print(s.test, s.print_somth())
Heidll
  • 3
  • 4