Changes to attribute in a class be activated in another class - python

class Main:
def __init__(self):
self.number = 10
class Sub1(Main):
def __init__(self):
super().__init__()
def addnum(self):
self.number += 1
print(self.number)
class Sub2(Main):
def __init__(self):
super().__init__()
def func(self):
print(self.number)
sub2 = Sub2()
sub1 = Sub1()
sub1.addnum()
sub2.func()
In class Main, attribute number=10 is created
In class Sub1, function addnum increases number by 1
In class Sub2, function func prints the number, it prints 10, how do I make it print 11?
So how can changes to an attribute in a class be activated in another class?

So you want number to be shared across Main, Sub1, and Sub2, so that if an instance of Sub1 modifies number instances of Main and Sub2 can access that new number. You really don't want to do this, if you need to share variables across classes you're better off using a container that all those classes can access. For example:
class Container:
number = 10
class Main:
def __init__(self):
self.container = Container()
def set_number(self, new_num):
self.container.number = new_num
class New:
def __init__(self, main):
self.container = main.container
def addone(self):
self.container.number += 1
main = Main()
new = New(main)
new.addone()
print(main.container.number) # 11
main.set_number(1000)
print(new.container.number) # 1000
This is just a much cleaner and easier approach.

Related

How to get parent constructor attributes in child constructor?

How do I get attributes from parent class constructor in child class constructor?
class A:
def __init__(number):
self.number = number
class B(A):
def __init__():
self.number = A.number?
test = B(A)
print(test.number)
I don't know how to do it so as not to pass arguments to the child class.
I think you have something wrong there. The correct code for parent / derived class would be
class A:
def __init__(self, number):
self.number = number
class B(A):
def __init__(self, number):
super().__init__(0) # Initialize parent class.
self.number = number
# Instantiate a B object
test = B(7)
# Print the property
print(test.number)
That will always produce '7' in the screen. Now both A and B __init__ methods refer to the same 'number' property of the object, so, it does not make much sense both classes setting the same property upon initialization. If you change B's __init__ method for:
class B(A):
def __init__(self, number):
self.number = number
super().__init__(0) # Initialize parent class.
Then print(test.number) would always print '0' instead of anything you passed on creation because you are overwriting the property.
The typical code would rather be:
class A:
def __init__(self, number):
self.number = number
class B(A):
def __init__(self, number):
super().__init__(number)
This way the derived class initializes the parent in a meaningful way.

Python - Calling a variable exists in 3 classes

I have a project with 3 classes, I will represent them as in the code below, in the first it will run class 1, and it must change the value of class 2, and when calling the variable in class 3 you should read the value we put in class 1...
but the code I made did not change That value
class class1(QMainWindow):
def __init__(self):
self.models = class2()
self.models.variable = 200
class class2(QWidget):
variable = 0
def __init__(self):
super().__init__()
class class3:
def __init__(self):
super().__init__()
self.models = class2()
print(self.models.variable) # Here I want to show 200 but the value that appears is 0
There must be 3 classes as in the order, also class 1 must not be called in class 3
It sounds like you want to make class2 as a namespace to hold variable. So just do that:
class class1(QMainWindow):
def __init__(self):
self.models = class2()
class2.variable = 200
class class2(QWidget):
variable = 0
def __init__(self):
super().__init__()
class class3:
def __init__(self):
super().__init__()
self.models = class2()
print(class2.variable)

How do I save a variable in a class without the variable being lost through class inheritance

I want it so that when the active() function Is called in the StopSign class, it calls the stop() function in the Car class. However, in my actual code(code is kinda long and distractingly sloppy so I used this one so you can get the idea) when I call upon the active function StopSign object has no attribute 'movement_code'. How can I get around this?
class Car:
def __init__(self):
self.color = blue
more code
def go(self):
self.movement_code = movement_function
def stop:
self.movement_code.kill()
class StopSign(car):
def __init__(self):
some code
def active(self):
self.stop()
The problem you're having is that StopSign wasn't initializing its parent class and so didn't inherit the stop method. Besides that though I agree with Arya. It doesn't make sense to have the StopSign class inherit from the Car class.
class Car:
def __init__(self):
self.color = 'blue'
# more code
def go(self):
pass
# self.movement_code = movement_function
def stop(self):
pass
# self.movement_code.kill()
class StopSign(Car):
def __init__(self):
super().__init__()
pass
# some code
def active(self):
self.stop()
sign = StopSign()
sign.active()
Here is a simple example of how you could avoid to have StopSign subclass Car:
class Car:
def __init__(self):
self.color = 'blue'
def go(self):
pass
def stop(self):
pass
class StopSign:
def __init__(self):
self.cars_in_vicinity = []
def active(self):
for car in self.cars_in_vicinity:
car.stop()
car = Car()
sign = StopSign()
sign.cars_in_vicinity.append(car)
sign.active()
There are many other ways to approach this though.

How to use super() to update a value in a specific instance of the parent?

I want to use the super function to write a string into a list of a specific instance of a parent object. Here's my code so far:
#!/usr/bin/env python
# test.py
class Master(object):
def __init__(self):
pass
class Sub1(Master):
list = []
def __init__(self):
pass
class Sub2(Sub1):
def __init__(self, name):
super(Sub2, self).list.append(name)
m = Master()
m.foo = Sub1()
m.foo.bar = Sub2('something')
m.bla = Sub1()
m.bla.blub = Sub2('else')
print(m.foo.list)
In this case the output is of course
['something', 'else']
However I want it to be just 'something'.
How can I achieve this?
I tried:
class Sub1(Master):
def __init__(self):
self.list = []
Which yields:
AttributeError: 'super' object has no attribute 'list'
Is there an easy solution?
As you have noted, if you define lst as a class attribute in Sub1, it is shared among all instances, which is not what you want. So you have to define lst as an instance attribute in Sub1 but then it has to be managed by an instance of Sub1 and not an instance of Sub2. Here is a modified code that offers what you expect:
class Master(object):
def __init__(self):
super().__init__()
class Sub1(Master):
def __init__(self):
super().__init__()
self.lst = []
def add(self, item):
self.lst.append(item.name)
class Sub2(Sub1):
def __init__(self, name):
super().__init__()
self.name = name
m = Master()
m.foo = Sub1()
m.foo.add(Sub2('something'))
m.bla = Sub1()
m.bla.add(Sub2('else'))
print(m.foo.lst)
print(m.bla.lst)
Here is the ouput:
['something'] <-- m.foo.lst
['else'] <-- m.bla.lst
Rem1: When using super() the whole class hierarchy has to be collaborative (i.e. use super() in the constructor).
Rem2: In Python3, super() is equivalent to super(classname, self)
Rem3: Don't use list as a variable name (it is a builtin type)
Rem4: My code stores only the name attribute in the list to mimic the example your gave, but I guess that in real life you would rather store instances of Sub2 in that list. To do so, simply remove the .name in the addfunction.
EDIT : Thinking a bit more about my answer, I came to another solution that may be closer to your initial attempt. Let me know which one works best for your actual problem...
class Master(object):
def __init__(self):
super().__init__()
class Sub1(Master):
def __init__(self):
super().__init__()
self.lst = []
class Sub2(Sub1):
def __init__(self, parent, name):
super().__init__()
parent.lst.append(name)
m = Master()
m.foo = Sub1()
m.foo.bar = Sub2(m.foo, 'something')
m.bla = Sub1()
m.bla.blub = Sub2(m.bla, 'else')
print(m.foo.lst)
print(m.bla.lst)
Your actual problem seems to be in the way you initialize list.
You need to assign it in __init__(), not within the class body, to avoid it being shared between all instances of the class (see Static class variables in Python).
class Sub1(Master):
def __init__(self):
self.list = []

Acessing a property from a parent object

In python, I'm creating an object inside a class:
class A:
def __init__(self):
self.one = 1
self.two = B()
Now I define class B, and I want to access self.one from inside B()
class B()
def __init__(self):
self.three = "hello"
# here I want to change self.one from class A to self.one + 1
# how to do it without doing self.two = B(self.one) on class A
# definition?
something = A()
is there a way to reference the parent object property, or do we have to pass the value when creating the object ?
A is not a parent object, parent object is the object from which you inherit. B has no knowledge about A, you have to modify your classes structure, for example by passing reference to parent in B's constructor (which you say you do not want to do, althouth it is not entirely clear what do you mean by "without doing self.two = B(self.one)", as this would pass copy of self.one, not a reference, but this is the way to do it)
class A:
def __init__(self):
self.one = 1
self.two = B(self)
class B()
def __init__(self, parent):
self.three = "hello"
self.parent = parent
print self.parent.one # or do whatever you want with it
If you really have to do this, you can use introspection, but this is ugly, hacky, bad way of achieving the result
import inspect
class A():
def __init__(self):
self.one = 1
self.two = B()
class B():
def __init__(self):
self.three = "hello"
self.parent = inspect.currentframe().f_back.f_locals['self']
print self.parent.one

Categories