call outer class without using the variable in main file - python

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.

Related

Override and extend method defined in parent class in Python

I want to redefine the method Old.do(self) in New.do(self, x) so that it takes one argument as below:
#!/usr/bin/env python3
class Old(object):
def __init__(self):
self.a = 0
self.do()
def do(self):
print(self.a)
class New(Old):
def __init__(self):
Old.__init__(self)
b = 1
self.do(b)
def do(self, b):
print(self.a + b)
if __name__ == '__main__':
new = New()
I can do it with the name mangling:
#!/usr/bin/env python3
class Old(object):
def __init__(self):
self.a = 0
self.__do()
def do(self):
print(self.a)
__do = do
class New(Old):
def __init__(self):
Old.__init__(self)
b = 1
self.do(b)
def do(self, b):
print(self.a + b)
if __name__ == '__main__':
new = New()
or I can do it with an explicit reference to the base class:
#!/usr/bin/env python3
class Old(object):
def __init__(self):
self.a = 0
Old.do(self)
def do(self):
print(self.a)
class New(Old):
def __init__(self):
Old.__init__(self)
b = 1
self.do(b)
def do(self, b):
print(self.a + b)
if __name__ == '__main__':
new = New()
Is there any other way to get the same result? Can super() do this?
Thanks
You can do what you trying with super, like this:
class Old(object):
def __init__(self):
self.a = 1
Old.do(self, self.a)
def do(self, a):
print(a)
class New(Old):
def __init__(self):
super(New, self).__init__()
self.b = 2
self.do(self.b)
def do(self, b):
print(self.a + b)
new = New()
the first call will return 1, and the second call 3

One constant value for multiple classes

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

How to initialize a class stored in a variable in python

I am wondering if it is possible to initialize a class stored in a variable. For example:
class cl():
def __init(self, a):
self.a = a
return
def print(self):
print(self.a)
return a
In[27]: c = cl
In[28]: c
Out[28]: __main__.cl
and now I want to initialize cl with value of a=3
class cl():
def __init__(self, a):
self.a = a
def print_a(self):
print(self.a)
c = cl
c(3)
c.print_a()
>>> 3
Yes it is totally possible. When you do c = c1 it creates c as an exact alias of c1.
You then do
obj_from_c1 = c1()
obj_from_c c()

Python construct child class from parent

I am quite new with python, is there a way to construct a child class using a parent instance?
Well I was thinking about:
class A:
def __init__(self,a,b):
self.a = a
self.b = b
class B(A):
def __init__(self,A):
self.super = A
self.c = -1
def __init__(self,a,b,c):
super(a,b)
self.c = c
myA = A(1,2)
myB = B(myA)
So for having B objects I could use A objects to construct them.
This will do what you ask, and create a new B, using the data from an existing A, and then complete the initialisation of the new B:
class A(object):
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return "A: a = %s, b = %s" % (self.a, self.b)
class B(A):
def __init__(self, *args):
if type(args[0]) is A:
self.__dict__ = args[0].__dict__.copy()
c = args[1]
else:
super(B, self).__init__(*args[:2])
c = args[2]
self.c = c
def __str__(self):
return "B: a = %s, b = %s, c = %s" % (self.a, self.b, self.c)
Usage:
myA = A(1, 2)
print myA
print B(3,4,5) # regular B
myB = B(myA, 10) # B created from an A
print myB
Output:
A: a = 1, b = 2
B: a = 3, b = 4, c = 5
B: a = 1, b = 2, c = 10
Note that the new instance doesn't get a new copy of the data, it gets a new set of references to that data. If a were a list and you did myA.a.append(value), then myB.a would also have value in it. If you want that not to be the case, change the assignment of __dict__ to:
self.__dict__ = deepcopy(args[0].__dict__)
Note: None of this won't work if you're using slots, because __dict__ won't exist
You can make use of the facts that:
class is an executable statement;
classes are first-class objects.
For example:
class A(object):
pass
def CreateB(superclass):
class subclass(superclass):
pass
return subclass
B = CreateB(A)
myA = A()
myB = B()
That said, it's not entirely clear to me what is the actual problem you are trying to solve.
In your example, methods in classes need a first argument to refer to themselves. Normally this is named self.
class A:
pass #class A code
class B(A):
def __init__(self, a):
self.super = a
myA = A()
myB = B(myA)
The code above will create a B instance with a reference to an A instance called super. If you want B to inherit from A then you would change the code slightly more.
class A:
pass #class A code
class B(A):
def __init__(self):
A.__init__(self)
myA = A()
myB = B()

How to implement this mechanism:

i want to implement a dynamic relation mechanism with python something like:
a:=10
b:=30
c:=a+b
print c
a+=20
print c
output:
40
60
c is always result of a+b.
so if a or b change, then c automatically updates value. i write a code in C# and do this by set and get mechanism. now want to translate it to python code for using in another program (FontLab Studio 5). I'm not so familiar with Python. does he have a get,set feature like C#? if not ho to implement one?
This is probably overkill, but it illustrates how you should create getters/setters in Python and achieve the functionality you want:
class Calc(object):
def __init__(self, a = 0, b = 0):
self._a = a
self._b = b
#property
def a(self):
return self._a
#a.setter
def a(self, value):
self._a = value
#property
def b(self):
return self._b
#b.setter
def b(self, value):
self._b = value
#property
def c(self):
return self._a + self._b
def __str__(self):
return str(self.c)
calc = Calc()
calc.a = 1
calc.b = 2
print calc.c
calc.a += 10
print calc.c
If you don't want to make a and b a property, the code can be simplified:
class Calc(object):
def __init__(self, a = 0, b = 0):
self.a = a
self.b = b
#property
def c(self):
return self.a + self.b
def __str__(self):
return str(self.c)
In your situation, c actually is a function which must be called.
You could use something like this:
a = 10
b = 30
c = lambda: a + b
print c()
a += 20
print c()
If you dislike that the method call is made explicit for c, you could use a general Calc object, which hides this implementation:
class Calc(object):
def __init__(self):
object.__setattr__(self, '_params', dict())
def __getattr__(self, name):
param = self._params[name]
if callable(param):
return param()
else:
return param
def __setattr__(self, name, value):
self._params[name] = value
def __delattr__(self, name):
del self._params[name]
And then you could do:
c = Calc()
c.a = 10
c.b = 30
c.c = lambda: c.a + c.b
print c.c
c.a += 20
print c.c
New-style Python classes support properties.
something like this:
class C:
def __init__(self):
self.x = 0
self.y = 0
def get(self):
return self.x + self.y
def __str__(self):
return self.__unicode__()
def __unicode__(self):
return str(self.get())
c = C()
c.x = 1
print c
c.y =2
print c
With new style classes and annotations you can probably make it better.

Categories

Resources