Casting to other class in Python - python

I have a code (simplified):
class A(object):
attrib1 = "a"
attrib2 = "b"
class B(A):
flag = True
in some place in my code, I have an instance of A, but I need to create an instance of class B, which will have all the data from instance of A... I feel myself stupid, but I don't want to do something like:
class B(A):
def __init__(self,a1,a2,a3,a4,..):
self.a1 = a1
self.a2 = a2
and call like:
obj_b = B( obj_a.a1, obj_a.a2,...)

class B(A):
def __init__(self, obj):
self.__dict__.update(obj.__dict__)

Another option is to change the __class__ variable on your instance of A.
a = A()
a.__class__ = B

Related

Setting self as an instance from another class doesn't work [Python]

Let's assume I have a class A and a class B.
class A:
def __init__(self):
self.variable1 = 1
self.variable2 = 'sometext'
class B:
def __init__(self, inst):
self = inst
print(self.__dict__.keys(), inst.__dict__.keys())
The print function returns
b = B(inst)
dict_keys(['variable1', 'variable2']) dict_keys(['variable1', 'variable2'])
However when I try
b.variable1
It returns the following error
AttributeError: 'B' object has no attribute 'variable1'
In my more complex code I need almost all variable from class A in class B.
I tried using class inheritance however I couldn't make it work with class methods and constructors.
Is there a reason why the above method doesn't work?
Thx
You're trying to overwrite self, but that only works while you're in the init. Instead, try assigning the inst to a variable of the class B:
class B:
def __init__(self, inst):
self.inst = inst
print(self.__dict__.keys(), inst.__dict__.keys())
Now you can access the variables of class A via:
inst = A()
b = B(inst)
b.inst.variable1
Not sure what you're trying to achieve here exactly, but you could also initiate the class A object inside the init of class B instead of passing the object to class B.
To use variable from class A in B you have to access to class A from B. Then execute class B
class A:
variable1 = 1
variable2 = 'sometext'
class B:
def __init__(self, inst=None):
self.f1 = A().variable1
self.f2 = A().variable2
def get_var(self):
print (self.f1)
B().get_var()

Create class instance within a class

I have a nested class in python for instance:
class A():
def __init__(self, attr1):
self.attr1 = attr1
class B():
def __init__(self, attr2):
self.attr2 = attr2
What I want to achieve is that instance b for class B, will be like a data structure of instance a for class A
However, it seems that b is not associate with a.
How can I achieve that?
Update:
What I want to do is something like the picture shown below, which is a java program object initialization:
It seems that user contains userID and Password and it is associated with the serviceOrder object.
There is rarely any reason to nest classes in Python. I think what you mean is to have an instance of B as an attribute of an instance of A, which is easy to do:
class A():
def __init__(self, attr1, attr2):
self.attr1 = attr1
self.b = B(attr2)
class B():
def __init__(self, attr2):
self.attr2 = attr2
In all likelihood your preferred solution has already been provided in Daniel Roseman's answer.
However, if for some reason you or someone else really does need to nest class B inside of A, you can do that this way:
class A():
def __init__(self, attr1, attr2):
self.attr1 = attr1
self.b = A.B(attr2) # NOTE: refer to class B via ``A.B``
class B():
def __init__(self, attr2):
self.attr2 = attr2
The reason you have to do it this way is B is a class attribute of A. It is no different than any other class-level attribute, and therefore accessing the attribute must be done via the owning class, e.g.:
MyClass.my_attr
# OR:
getattr(MyClass, 'my_attr')
# OR:
MyClass.__dict__['my_attr']
# etc. etc.
Note this is true even when you're inside of the owning class:
class MyClass():
class_attr = 1
def get_class_attr(self):
# return class_attr would raise a NameError
return MyClass.class_attr # no error
MyClass().get_class_attr() # 1

How can I call methods between two classes?

I have a class A. During the __init__ method of an instance of A;
I create these following two instances of classes B and C:
b = B()
c = C()
Once all's set, I need to call, within a method of B, a method from C.
Example:
Triggered:
b.call_c()
Does:
def call_c(self):
parent.c.a_method_of_c()
What do I need to do to achieve this structure?
You need to pass either of self or c to B() so that it can know about the other object.
Here is how this looks if you pass the A object to both B and C as a parent/container object:
class A(object):
def __init__(self):
self.b = B(self)
self.c = C(self)
class B(object):
def __init__(self, parent):
self.parent = parent
def call_c(self):
self.parent.c.a_method_of_c()
class C(object):
def __init__(self, parent):
self.parent = parent
# whatever...
Or, you can just pass the C instance to B's initializer like this:
class A(object):
def __init__(self):
self.c = C()
self.b = B(self.c)
class B(object):
def __init__(self, c):
self.cobj = c
def call_c(self):
self.cobj.a_method_of_c()
class C(object):
# whatever...
I like the second approach better, since it cuts out the dependencies of B and C on A, and the necessity of A to implement b and c attributes.
If B and C have to call methods on each other, you can still use A to make these associations, but keep B and C ignorant of A:
class A(object):
def __init__(self):
self.b = B()
self.c = C()
self.b.cobj = self.c
self.c.bobj = self.b
class B(object):
def __init__(self, c):
self.cobj = None
def call_c(self):
if self.cobj is not None:
self.cobj.a_method_of_c()
else:
raise Exception("B instance not fully initialized")
class C(object):
# similar to B
In general, your goal is to try to avoid or at least minimize these dependencies - have a parent know about a child, but a child be ignorant of the parent. Or a container knows its contained objects, but the contained objects do not know their container. Once you add circular references (back references to a parent or container object), things can get ugly in all kinds of surprising ways. A relationship can get corrupted when one of the links gets cleared but not the reflecting link. Or garbage-collection in circular relations can get tricky (handled in Python itself, but may not be handled if these objects and relations are persisted or replicated in a framework).
I need to call, within a method of B, a method from C.
Basically, if the method is not a class method or a static method, then calling a method always means that you have access to the (c) object of the C class.
Have a look at the example:
#!python3
class B:
def __init__(self, value):
self.value = value
def __str__(self):
return 'class B object with the value ' + str(self.value)
class C:
def __init__(self, value):
self.value = value
def __str__(self):
return 'class C object with the value ' + str(self.value)
class A:
def __init__(self, value):
self.value = value
self.b = B(value * 2)
self.c = C(value * 3)
def __str__(self):
lst = ['class A object with the value ' + str(self.value),
' containing the ' + self.b.__str__(),
' containing also the ' + str(self.c),
]
return '\n'.join(lst)
a = A(1)
print(a)
print(a.b)
print(a.c)
The self.b.__str__() is the example of calling the method of the object of the B class from the method of the object of the A class. The str(self.c) is the same, only called indirectly via the str() function.
The following is displayed:
class A object with the value 1
containing the class B object with the value 2
containing also the class C object with the value 3
class B object with the value 2
class C object with the value 3

Different instances of A in B (Python)

In a situation like this b1 and b2 both have the same instanse of A.
class A:
def __init__(self):
self.var=1
class B:
a=A()
def __init__(self):
pass
b1=B()
b2=B()
b1.a.var=2 #changing "var" in b1 would also change it in b2
print(b2.a.var) # prints 2
What should i do to have 2 different instances of A in B?
With B defined as it is, its attribute a belongs to the class itself, not each individual instance. You would need to do something like this:
class B:
def __init__(self):
self.a = A()
to get separate instances of A for every B.
You were using what amounts to a static variable. Try this:
class A:
def __init__(self):
self.var = 1
class B:
def __init__(self):
self.a = A()
You need to initialize it on a per-instance basis instead of at the class level like you have now:
class B:
def __init__(self):
self.a = A()
You're initialising A() as a static class variable when it is first parsed.
To have one instance of A() per instance of B() it should be in the __init__ of B()
class A:
def __init__(self):
self.var=1
class B:
def __init__(self):
self.a = A()
b1=B()
b2=B()
b1.a.var=2 # changing "var" in b1 would not change it in b2
print(b2.a.var) # now prints 1

Accessing outer class methods from an inner class

I want a python class that has a nested class where the inner class can access the members of the outer class. I understand that normal nesting doesn't even require that the outer class has an instance. I have some code that seems to generate the results I desire and I want feedback on style and unforeseen complications
Code:
class A():
def __init__(self,x):
self.x = x
self.B = self.classBdef()
def classBdef(self):
parent = self
class B():
def out(self):
print parent.x
return B
Output:
>>> a = A(5)
>>> b = a.B()
>>> b.out()
5
>>> a.x = 7
>>> b.out()
7
So, A has an inner class B, which can only be created from an instance of A. Then B has access to all the members of A through the parent variable.
This doesn't look very good to me. classBdef is a class factory method. Usually (and seldomly) you would use these to create custom classes e.g. a class with a custom super class:
def class_factory(superclass):
class CustomClass(superclass):
def custom_method(self):
pass
return CustomClass
But your construct doesn't make use of a customization. In fact it puts stuff of A into B and couples them tightly. If B needs to know about some A variable then make a method call with parameters or instantiate a B object with a reference to the A object.
Unless there is a specific reason or problem you need to solve, it would be much easier and clearer to just make a normal factory method giving a B object in A instead of stuff like b = a.B().
class B(object):
def __init__(self, a):
self.a = a
def out(self):
print self.a.x
class A(object):
def __init__(self,x):
self.x = x
def create_b(self):
return B(self)
a = A()
b = a.create_b()
b.out()
I don't think what you're trying to do is a very good idea. "Inner" classes in python have absolutely no special relationship with their "outer" class, if you bother to define one inside of another. It is exactly the same to say:
class A(object):
class B(object):
pass
as it is to say:
class B(object): pass
class A(object): pass
A.B = B
del B
That said, it is possible to accomplish something like what you're describing, by making your "inner" class into a descriptor, by defining __get__() on its metaclass. I recommend against doing this -- it's too complicated and yields little benefit.
class ParentBindingType(type):
def __get__(cls, inst, instcls):
return type(cls.__name__, (cls,), {'parent': inst})
def __repr__(cls):
return "<class '%s.%s' parent=%r>" % (cls.__module__,
cls.__name__, getattr(cls, 'parent', None))
class B(object):
__metaclass__ = ParentBindingType
def out(self):
print self.parent.x
class A(object):
_B = B
def __init__(self,x):
self.x = x
self.B = self._B
a = A(5)
print a.B
b = a.B()
b.out()
a.x = 7
b.out()
printing:
<class '__main__.B' parent=<__main__.A object at 0x85c90>>
5
7

Categories

Resources