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
Related
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.
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.
Lets take the next code
class main:
def __init__(self):
self.a = 3
self.b = 4
self.methods = sub
class sub:
def printval():
print(a,b)
How can I use main class in this way?
main.methods.printval()
This is quite a bizzare thing to do, but here goes
class Main(object):
__slots__ = ('a', 'b', 'methods')
def __init__(self):
self.a = 3
self.b = 4
self.methods = Sub(self)
class Sub:
__slots__ = ('other')
def __init__(self, other):
self.other = other;
def printval(self):
print(self.other.a, self.other.b)
main = Main()
main.methods.printval()
Also there is no inheritance going on between Main and Sub. You are simply taking advantage of function calls.
EDIT:
Another way of accomplishing the same thing, but this time using inheritance:
class Main(object):
__slots__ = ('a', 'b')
def __init__(self):
self.a = 3
self.b = 4
class Sub(Main):
def printval(self):
print(self.a, self.b)
main = Sub()
main.printval()
I need something like this
class Parent(object):
class Base(object):
def __init__(self, a, b):
self.a = a
self.b = b
class Derived(Base):
def __init__(self, a, b, c):
super(Derived,self).__init__(a, b)
self.c = c
def doit():
pass
parent = Parent()
derived = parent.Derived(x,y,z)
derived.doit()
When I try to run this, i get this following error: NameError: name 'Derived' is not defined
I tried with 'Base' in the place of 'Derived' in super() - didn't help
Class inheritance does not change the parent class. In this case your Parent class only contains the original Base class and not the derived class.
You can simply use monkey-patching to solve this problem,
class Parent(object):
pass
class Base(object):
def __init__(self, a, b):
self.a = a
self.b = b
class Derived(Base):
def __init__(self, a, b, c):
super(Derived,self).__init__(a, b)
self.c = c
def doit(self):
pass
Parent.Derived = Derived
parent = Parent()
x, y , z = 1, 1, 1
derived = parent.Derived(x,y,z)
derived.doit()
Prefixing 'Derived' with 'Parent.', made it. As I already have commented on the question. This is just for experimenting with the 'Derived' class. But I am still wondering how the, 'class Derived(Base):' is fine (without 'Parent.' prefix for 'Base' class)
class Parent(object):
class Base(object):
def __init__(self, a, b):
self.a = a
self.b = b
class Derived(Base):
def __init__(self, a, b, c):
super(Parent.Derived,self).__init__(a, b)
self.c = c
def doit():
pass
parent = Parent()
derived = parent.Derived(x,y,z)
derived.doit()
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()