There is a program on Python 3:

class A: ...... class B(A): ....... aA = A() 

How can one correctly and beautifully convert aA (an instance of class A) into an instance of class B?

  • 3
    Alternatively, you can add a class B method to init to pass an object of class A as a parameter and accurately specify exactly how to borrow the attributes. - Akari Gale
  • Could you give an example of such attribute borrowing? To do this, all the attributes you need to list? Those. copy code? - DmitryVil

3 answers 3

There is no general solution, you need to look and select the appropriate option for every A and B.

The main methods are:

one). Just replace the object class.

 a = A() a.__class__ = B 

after such a procedure, the object will retain all its own attributes, and the parent’s attributes and methods will be addressed to B, not A. And when explicitly checking the class, it will be considered an instance of class B.

2). Create an instance of class B and throw all the attributes of the original object into it. Then use the new object. If you wish, you can give him the name of the old.

 a = A() b = B() b.__dict__ = a.__dict__.copy() del a a = b del b 

Both of these options are not suitable for each case (for example, if the classes are different and non-trivial initializers). And in difficult cases, there is a high probability of something missing from attention and getting a poorly caught bug.

3). As it was rightly said in the comments, there is a slightly more complicated, but also more reliable way - to write logic in the initializer that could accept an object of another similar class as an alternative to the usual argument list, and create an instance of it in its image.

  • Alexander, thank you very much for your reply. Could you, describe the third option in more detail? Can you give an example? How in this case can you copy all the fields without listing them one by one? - DmitryVil

No Imagine A=object , and the implementation of B in no way limited. In general, having object() not enough to create a B() .

Specific classes B can, of course, define constructors that A accepts. For example, collections.Counter can be created from a dictionary ( dict ):

 >>> from collections import Counter >>> d = dict(a=1, b=0) >>> +Counter(d) Counter({'a': 1}) 
  • Can a person want to ask something about duck typing? and about whether it is possible to add methods to the object on the fly. although - I agree - to be interested in what exactly the person wanted to ask - to be more expensive - Vasyl Kolomiets
  • 2
    @VasylKolomiets: you don’t need to mislead people and put other answers to them just because I’ve pointed out to you: “the link to the solution is not the answer. State the essence of the decision directly in the answer or just as a comment, post the links” - again: Agree to this policy; contact Meta. Out of revenge, cons do not need to be put - this is misleading future readers. - jfs
  • one
    out of revenge? what is "necessary" and what is "not necessary" allow each person to decide independently. If you think this is revenge, that’s your right. I think the answer "no way" is not quite correct. Even if I am mistaken - it is also the right of every person. The law of large numbers will show you right or wrong. Well I'm not one "reader". At the same time I will see what is right. __________________________________________ Are you really worried about one minus with your 32k? Or do you believe that apart from the two of us, no one will read this post? Try to answer yourself about the reason for your desire to teach and it will become easier for everyone. - Vasyl Kolomiets

In order to make an object of another class from an object of one class, you will have to add methods and change the type of the class. How to replace the type - they told you.
In one of three ways, you can add methods to an instance of a class :

 class A: def back_print(a: str) -> None: print(a[::-1]) class B(A): def foo(self,a,b): print(a+b) b = B() print(type(b)) # строим функцию, которая будет добавлена как метод "а-ля" класс B() def foo(self,a,b): print(a, '+', b) 

1st way to add a method to an object dynamically

 aA = A() aA.foo = foo.__get__(aA) aA.foo(2,3) print(type(aA)) # подменяем тип: aA.__class__ = type(b) if type(aA)==type(b): print(' type(aA)==type(b) ') 

2nd way to add a method to an object dynamically

 def bind(instance, method): def binding_scope_fn(*args, **kwargs): return method(instance, *args, **kwargs) return binding_scope_fn bA = A() bA.foo = bind(bA, foo) aA.foo(2,3) print(type(bA)) 

3rd way to add a method to an object dynamically

 import types cA = A() cA.foo = types.MethodType(foo, cA) cA.foo(2,3) print(type(cA)) 

substitute type:

 cA.__class__ = type(b) cA.foo(2,3) b.foo(2,3) if type(cA)==type(b): print(' type(cA)==type(b) ') 

How to add properties to a class can be read here in curved Russian:

I think that encapsulated properties are just “special methods” that can be added in the same way. Let the "fathers" correct me if I am wrong.

Variable properties are added easily:

 cA.pro = 7 print(f'cA.pro: {cA.pro}') 

you will get:

 cA.pro: 7 

In conclusion, how to add dynamically methods to the class. So now you have everything for "partisan patching" on the fly! Good luck.

  • 2
    Basil, just saw your answer. I have not figured it out yet, but I already want to tell you - thank you very much. - DmitryVil
  • Basil, just tried your 3rd option. As a result, I received an instance of the parent class, not a descendant class. The task was: how to make an instance of the inherited class from an instance of the parent class. It was meant that the inherited class has all the fields of the parent class plus additional fields. What should I do here? - DmitryVil
  • @DmitryVil - and the type substitution line was made: _____ similar to this: cA .__ class__ = type (b)? the type still needs to be changed "manually" ... all three methods only add methods. - Vasyl Kolomiets