Considering I have the following classes:
class A:
def __init__(self, origin, value):
self.origin = origin
self.origin.b1 = value
class B:
def __init__(self):
self.b1 = 0
self.b2 = A(self, 1)
print(self.b1)
b = B()
I wish to know if there is any way of avoiding passing the self when instancing class A, thus getting the origin (class B) of the instance from within the class A (replacing of course the "???"):
class A:
def __init__(self, value):
self.origin = ???
self.origin.b1 = value
class B:
def __init__(self):
self.b1 = 0
self.b2 = A(1)
print(self.b1)
b = B()
Related
Say I have the following classes:
DO_NOT_OVERRIDE = type() # this dictates if an attribute won't be overridden.
class Parent():
def __init__(self, a: int = 0, b: int = 0):
self.a = a
self.b = b
class Child():
def __init__(self, parent: Parent, a: int = DO_NOT_OVERRIDE, b: int = DO_NOT_OVERRIDE):
self.parent = parent
self._a = a
self._b = b
#property
def a(self):
if self._a is DO_NOT_OVERRIDE:
return self.parent.a
return self._a
#a.setter
def a(self, value: int):
self._a = value
#property
def b(self):
if self._b is DO_NOT_OVERRIDE:
return self.parent.b
return self._b
#b.setter
def b(self, value: int):
self._b = value
Now, let's create some objects.
parent_obj = Parent(a = 1, b = 2)
child_obj_1 = Child(parent = parent_obj)
child_obj_1.a would return 1 and child_obj_1.b would return 2, which are both values from parent.a and parent.b respectively
But consider another Child:
child_obj_2 = Child(parent_obj, a = 20)
child_obj_2.a would return 20 which is a value set in child_obj_2, though child_obj_2.bwould still return2sinceb` is not "overridden" by the child object.
What is this design pattern?
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))
I had meet the problem that, when calling method in class A, I need to set the value or call some functions in other classes, but I need all of them in the same python file, which is really long and ugly
. Are there some appropriate ways to write it clean?
Ideally, I hope this classes can be in seperate python file.
class A:
def __init__(self):
super(A, self).__init__()
self.value = 10
def set(self, new_value):
self.value = new_value
# set B value = new_value * 2
c.b.set(new_value * 2)
# set C value = new_value / 2
c.value = new_value / 2
class B:
def __init__(self):
super(B, self).__init__()
self.value = 10
def set(self, new_value):
self.value = new_value
class C:
def __init__(self):
super(C, self).__init__()
self.value = 1
self.a = A()
self.b = B()
if __name__ == '__main__':
c = C()
# class a function is called then class B and class C do somethings ...
c.a.set(100)
print(c.value)
print(c.a.value)
print(c.b.value)
There are many solutions to your design constraints, but here is one where dependencies are eliminated:
# imagine each of these classes are in their own projects (/A,/B,/C), in their own files (A.py, B.py, C.py)
class A:
def __init__(self, c):
self.value = 10
self.c = c
def set(self, new_value):
self.value = new_value
# set B value = new_value * 2
self.c.b.set(new_value * 2)
# set C value = new_value / 2
self.c.value = new_value / 2
# class B as before
class C:
def __init__(self, A, B):
self.value = 1
self.a = A()
self.b = B()
# Now main.py
from A.A import A
from B.B import B
from C.C import C
if __name__ == '__main__':
c = C(A, B) # Pass in the classes A and B which C will instantiate
# class a function is called then class B and class C do somethings ...
c.a.set(100)
print(c.value)
print(c.a.value)
print(c.b.value)
btw: A class which does not derive from another does not need to call super init.
Let's say that I have six different classes and three of them should use the same constant value. What can we do? We either:
Define as global variable
A = 1
class B:
def __init__(self):
self.a = A
class C:
def __init__(self):
self.a = A
class D:
def __init__(self):
self.a = A
Define as class level for 1 class and give it to another class:
class B:
A = 1
def __init__(self):
self.b = 2
class C:
def __init__(self, a):
self.a = a
self.b = 3
b = B()
c = B(a=b.A)
The second way I just made up and as for me it's dirty and not convenient. Is there any way to avoid using a global variable?
Use class inheritance:
class Holder:
a = 4
class A(Holder):
pass
print A().a
You could use inheritance, using B as the base class
class B:
A = 1
def __init__(self):
self.b = 2
class C(B):
def __init__(self):
B.__init__(self)
self.a = B.A
self.b = 3
b = B()
c = C()
print c.a
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