using a variable from a method of another class in python - python

I have code that goes like this:
class A(object):
def __init__(self, master):
"""Some work here"""
def do_this(self):
self.B = B.do_that()
print self.B[1]
class B(object):
def __init__(self, master):
"""Some work here"""
def do_that(self):
p = (1, 2)
I can't make the method in class A to use that self.B as a tuple. Help.

For starters, do_that() doesn't return anything. So calling it will pretty much do nothing.
self.B = B.do_that() also won't work. You have to first create an instance of the class B:
mything = B(your_parameters)
mything.do_that()
And if you want that to return something (i.e, the tuple), you should change your do_that() to:
def do_that(self):
return (1, 2)
One final note, this can all be achieved through Inheritance:
class A(B): # Inherits Class B
def __init__(self,master):
"""Some work here"""
def do_this(self):
print self.do_that()[1] # This is assuming the do_that() function returns that tuple
Using the inheritance method:
>>> class B:
... def __init__(self, master):
... """Some work here"""
... def do_that(self):
... return (1,2)
...
>>> class A(B):
... def __init__(self, master):
... """Some work here"""
... def do_this(self):
... print self.do_that()[1]
...
>>> mything = A('placeholder')
>>> mything.do_this()
2

First you have to instantiate B as a property of A in the method A.do_this().
The following code should work.
def do_this(self):
b = B()
self.B = b.do_that()
print self.B[1]

Related

Using a variable from one class to another one in python

I want to use a variable from class A for some computation in class B. I,m not sure that I use the self.out from the class A in class B appropriately?
Class A:
class A(nn.Module):
def __init__(self):
super(A, self).__init__()
self.out = func()
Class B:
class B(nn.Module):
def __init__(self):
super(A, self).__init__()
self.result = function_1() + A.self.out
Maybe this is what you need. I made a small example of what I understood.
These "prints" were placed to improve the understanding that Class "C" can fetch any function or variable from the other parent classes.
class A():
def __init__(self):
variable = None
def test(self, number):
return f'another class {number}'
class B():
def __init__(self):
self.data = None
self.out = self.print_data(5)
def print_data(self, number):
return number
def print_elem(self):
return self.data
class C(A, B):
def __init__(self):
super().__init__()
c = C()
print(c.print_data(8))
print(c.out)
c.data = 100
print(c.print_elem())
print(c.test(3))

In python, how to force a function argument to be of a specific Class

In the following example
class A():
def __init__(self):
self.foo = 'foo'
class B():
def __init__(self, a):
self.a = a
a = A()
B(a) # right
B('a') # wrong
I want to do something like B.__init__(self, a:A) so that the argument in class B is an object of A.
You can always raise a ValueError:
class B():
def __init__(self, a: A):
if not isinstance(a, A):
raise ValueError("a must an object of class A")
self.a = a

Python encapsulate data for a class

I have two python classes, A and B that inherits from A.
At runtime, I only have one instance of class A, but many instances of class B.
class A:
def __init__(self, a):
self.a = a
def _init2 (self, AA)
self.a = AA.a
class B(A):
def __init__(self, AA, b):
super()._init2(AA)
self.b = b
AA = A(0)
BB = B(AA, 1)
Is this the good way of writing it ? It seems ugly ...
It would probably be better to remove init2 and only use __init__. Having both is confusing and unnatural.
class A:
def __init__(self, obj):
# I believe that this is what you tried to achieve
if isinstance(obj, type(self)):
self.a = obj.a
else:
self.a = obj
class B(A):
def __init__(self, A, b):
super().__init__(A)
self.b = b
On a side note, there are too many things called A here. The A in def __init__(self, A, b): is most probably not referring to the A that you expect.

Accidentally calling an ovverriden method from base class's __init__

This program seems to do everything by the book, yet this issue cropped up: while a base class was being init'ed a member method was called that is overriden in the derived class and assumes that the derived class has been constructed.
Is there some best practice to protect against this?
#!/usr/bin/env python3
class A:
def __init__(self):
self.ax = 1
print(self)
def __repr__(self):
return "{} ax: {}".format(self.__class__.__name__, self.ax)
class B(A):
def __init__(self):
super().__init__()
self.bx = 10
def __repr__(self):
return super().__repr__() + " bx: {}".format(self.bx)
if __name__ == "__main__":
B()
And here's the error:
AttributeError: 'B' object has no attribute 'bx'
Generally, unless you really know what you are doing, you want to call the superclass initialization after everything your class needs to do is done. Same with this example, repr is trying to print self.bx before you initialize it. If you do
class B(A):
def __init__(self):
self.bx = 10
super().__init__()
def __repr__(self):
return super().__repr__() + " bx: {}".format(self.bx)
it works as expected
Edited:
Instead of doing computation on __init__, one idea may be to do that in a factory function/classmethod.
Example instead of doing:
class A:
def __init__(self, a, b):
self.a = a
self.b = b
self.initialize()
def initialize(self):
# do some things
Do:
class A:
def __init__(self, a, b):
self.a = a
self.b = b
#classmethod
def from_a_b(cls, a, b):
instance = cls(a, b)
instance.initialize()
return instance

Elegant multiple inheritance in Python

I'm currently using this pattern to create a class C that inherits from A and B. I couldn't call super().__init__ from C since I would have to do the same in A and B, and the unexpected parameter would cause problems at the top level. I feel like this isn't very elegant. What is the proper way to do multiple inheritance in Python? I guess it is unusual to query the mro to find out if the superclass expects a parameter?
class A:
def __init__(self, something):
self.a = X(something)
def method_a(self):
self.a.go()
def method_ab(self):
self.a.go2()
class B:
def __init__(self, something):
self.b = X(something)
def method_b(self):
self.b.go()
def method_ab(self):
self.b.go2()
class C(A, B):
def __init__(self, something):
self.a_ = A(something)
self.b_ = B(something)
#property
def a(self):
return self.a_.a
#property
def b(self):
return self.b_.b
def method_ab(self):
for x in [self.a, self.b]:
x.method_ab()
The best solution I found was to use a base class to absorb the extra parameters:
class Base:
def __init__(self, something):
pass
def method_ab(self):
pass
class A(Base):
def __init__(self, something):
super().__init__(something)
self.a = X(something)
def method_a(self):
self.a.go()
def method_ab(self):
super().method_ab()
self.a.go()
class B(Base):
def __init__(self, something):
super().__init__(something)
self.b = X(something)
def method_b(self):
self.b.go()
def method_ab(self):
super().method_ab()
self.b.go()
class C(A, B):
pass

Categories

Resources