0

I'm trying to get a better understanding of python class system. This question is intended only to satisfy my curiosity.

Is it possible to use somehow a class instance as a parent class for another class. So far what I tried to do is

class A:
    pass

a = A()

class B(a):
    pass

and it gives following error: TypeError: object() takes no parameters

class Meta(type):
    pass

class A:
    pass

a = A()

class B(a, metaclass=Meta):
    pass

and it gives this error TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

I'm wondering, is it possible to somehow proxy all of the class instance methods to metaclass, so my instance would behave as a class

1
  • It's unclear why you'd want to ever do this, but if you really want it google "prototypes in python" Commented May 11, 2018 at 13:12

4 Answers 4

1

Is it possible to use somehow a class instance as a parent class for another class

Well, actually that's always the case since classes ARE instances (of their metaclass). But then the class of the instance you want to use as a parent class (yeah, re-read it thrice...) must behave as if it was a genuine metaclass - which can rapidily become impractical.

I'm wondering, is it possible to somehow proxy all of the class instance methods to metaclass, so my instance would behave as a class

There might be a way indeed (overriding __getattr__() or __getattribute__()), but devil is in the details and chances are that by the time you make this rube goldberg contraption "kind-of-work-with-severe-limitations-and-corner-cases", you will wonder if that was really worth the pain.

Note that OTHO both composition/delegation and dynamic (runtime) creation / modification of classes is absurdly easy in Python so I can hardly think of a problem that would be better solved by (ab)using an instance as a parent class.

Sign up to request clarification or add additional context in comments.

Comments

0

Every instance has a __class__ attribute that refers to the underlying class structure.

Knowing this, you can actually do the following:

class A(object):
   def foo(self):
      return 'hello'

a = A()

class B(a.__class__):
    pass

b = B()
print(b.foo()) # Prints 'hello'

Alternatively, you can also use type:

class B(type(a)):
    pass

b = B()
print(b.foo()) # Prints 'hello'

4 Comments

Yes, I know about __class__ attribute, but as I said in the question, I want to inherit a class from class instance, not from its class
@KirillCherepanov I'm not quite following. What exactly do you mean by inheriting from an instance? May you provide an example and desired output?
The first code snippet is something I want to achieve. Again, I don't see any practical usage for this, I just want to know if it's possible and how it can be done
@KirillCherepanov this only makes sense in the context of objects being able to accept new properties dynamically at runtime: otherwise they only have the properties defined by their class(es) and an instance is uninteresting as a template for new objects.
0

Your instance needs to be a type in order to be used in inheritance chains. For example:

class A(type):
    pass

a = A(str)  # you need to pass the type's `type` to the construcor

class B(a):
    pass

That being said, there's little, if no practical application for this that I can think of - or rather whatever you achieve this way will be easier and more Pythonic to achieve through normal inheritance and metaclasses.

Comments

0

EDIT:

OK, so it is possible to hack if you have control over the base class (either using metaclasses or __init_subclass__ (python 3.6 or later))

class A:
    x = 1
    def __init_subclass__(cls, inst, **kwargs):
        super().__init_subclass__(**kwargs)
        for k, v in vars(inst).items():
            if k not in dir(cls):  # i.e. don't override but remove if you want to
                setattr(cls, k, v)

a = A()
a.y = 2   

class B(A, inst=a):
    pass

B.x # --> 1
B.y # --> 2

You're sort of on the right tracks with your second example. Yes it is possible.

class Meta(type): pass
class A(metaclass=Meta): pass
class B(A): pass

issubclass(B, A) # --> True
isinstance(B, Meta) # --> True

Thats because A is an instance of Meta (thats what a metaclass means, a class whose instance is also a class). Hence B is a subclass of an instance of Meta.

So yes, you could set for example

class Meta(type):
    def __init__(cls, *args, **kwargs):
         cls.x = 1
         super().__init__(cls, *args, **kwargs)

class A(Meta):
    def __init__(self):
         self.y = 2

A.x  # 1 (acts as an instance of Meta)
a = A()
a.y  # 2 (acts as an instance of A)
a.x  # AttributeError (does not act as an instance of Meta)

3 Comments

This does not answer the question. OP clearly wants some form of prototypal inheritance a la JavaScript.
@JaredSmith You seem very sure of that. What makes you think so?
Because that's what "inherit from a class instance" means: take some given object x and use it as a template for stamping out more xs dynamically, and indeed the OPs response to Matias Cicero's answer confirms it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.