reference instance attribute in child class - python

I am trying to call an instance variable from a "parent" class (subclass) to it's "child" class (subsubclass)
class mainclass():
def __init__(self):
self.mainclassvar1 = "mainclass"
class subclass(mainclass):
def __init__(self):
self.subclassvar1 = "subclass"
def changeval(self):
self.subclassvar1 = "subclassedited"
class subsubclass(subclass):
def __init__(self):
self.subsubclassvar1 = subclass.subclassvar1 #<- naturally this fails
def handler():
main=mainclass()
sub = subclass()
sub.changeval()
subsub = subsubclass()
print(subsub.subsubclassvar1)# <- how do I achieve this? I would expect "subclassedited" but it doesn't
if __name__ == "__main__":
handler()
The above does not work obviously but I am trying to show what I am trying to achieve in my head.
if I change the class subsubclass(subclass) as follows it semi-works:
class subsubclass(subclass):
def __init__(self):
subclass.__init__(self)
self.subsubclassvar1 = self.subclassvar1
however the returned value is the original default value of subclass instead of the expected subclassedited.
I am not sure if I should even be trying to do this but I've got some code where the logic has now come to this point and I want to try see if I can get details from the middle class in to the final child class in their final modified states instead of the defaults and without refactoring a lot of code.

Each __init__ method should be invoking the parent's __init__ method, so that the instance is properly initialized for all the classes in the hierarchy.
class mainclass:
def __init__(self):
super().__init__()
self.mainclassvar1 = "mainclass"
class subclass(mainclass):
def __init__(self):
super().__init__()
self.subclassvar1 = "subclass"
def changeval(self):
self.subclassvar1 = "subclassedited"
class subsubclass(subclass):
def __init__(self):
super().__init__()
# Not sure why you would really need this, but...
self.subsubclassvar1 = self.subclassvar1
There's no reason, though that subsub.subclassvar1 should be related to sub.subclassvar1, though. Calling sub.changeval() has nothing to do with subsub.

Related

How to force a python class to have a CLASS property? (not a INSTANCE property!!!)

I have googled around for some time, but what I got is all about INSTANCE property rather than CLASS property.
For example, this is the most-voted answer for question from stackoverflow
class C(ABC):
#property
#abstractmethod
def my_abstract_property(self):
return 'someValue'
class D(C)
def my_abstract_property(self):
return 'aValue'
class E(c)
# I expect the subclass should have this assignment,
# but how to enforce this?
my_abstract_property = 'aValue'
However, that is the INSTANCE PROPERTY case, not my CLASS PROPERTY case. In other words, calling
D.my_abstract_property will return something like <unbound method D.my_abstract_property>. Returning 'aValue' is what I expected, like class E.
Based on your example and comment to my previous reply, I've structured the following which works with ABC. :
from abc import ABC
class C(ABC):
_myprop = None
def __init__(self):
assert self._myprop, "class._myprop should be set"
#property
def myprop(self):
return self._myprop
class D(C):
_myprop = None
def __init__(self):
super().__init__()
class E(C):
_myprop = 'e'
def __init__(self):
super().__init__()
e = E()
print(e.myprop)
d = D()
print(d.myprop)
You are correct that there is no Python pre-scan that will detect another developer has not assigned a value to a class variable before initializing. The initializer will take care of notifying pretty quickly in usage.
You can use #classmethod decorator.
I come up with a tricky workaround.
class C(object):
myProp = None
def __init__(self):
assert self.myProp, 'you should set class property "name"'
class D(C):
def __init__(self):
C.__init__(self)
class E(C):
myProp = 'e'
def __init__(self):
C.__init__(self)
print(D.myProp)
print(E.myProp)
But it still has some problems:
D.myProp will not raise any exception to warn the developer about the constraint (assigning myProp as its class property), until the developer initialize an instance of his class.
abc module cannot work with this solution, which means loss of lots of useful features of that module

how can i print a using class Employee here and having trouble inheriting

class Person:
def _init_(self):
self.A=1
class Employee(Person):
def _init_(self):
print(A)
object1=Person()
object2=Employee()
There are actually multiple problems with that code, besides the misspelled constructor...
Your _init_ method should be __init__, otherwise it's not a constructor but just a method that happens to be called _init_, and thus never called.
You have to call the constructor of the super-class, or A will not be set, e.g. using super().__init__() or Person.__init__(self)
You have to use self.A to read the field A of the instance; otherwise it will look for a local variable called A
This should work:
class Person:
def __init__(self): # misspelled
self.A = 1
class Employee(Person):
def __init__(self): # misspelled
super().__init__() # call super constructor
print(self.A) # use self.A

dictionary as a class argument in python

I am just starting Python for solving one project and I am struggling a lot with the syntax and usage as I have coded in type checking language only (Java, C++).
Here I am defining one class and inside that class, I want to store one dictionary of objects but I am not able to access that dictionary in other function of that class. below example give me the same error:
Code:
class abc:
def __init__(self):
a =10
class test:
def __init__(self):
self.ddict['xyz'] = abc()
def access(self):
self.ddict['def'] = abc()
I am getting the error:
self.ddict['xyz'] = abc()
AttributeError: test instance has no attribute 'ddict'
You need to initialize your dict before using it. You code should look like this:
class abc:
def __init__(self):
self.a = 10
class test:
def __init__(self):
self.ddict = {'xyz': abc()}
Thanks, #jonrsharpe. It worked!
class abc:
def __init__(self):
a =10
class test:
def __init__(self):
self.ddict = {} /* need to init first*/
self.ddict['xyz'] = abc()
def access(self):
self.ddict['def'] = abc()

Can I call a subclass from a parent class to create the object

For example:
class parent(self):
def __init__(self, i):
self.i = i
def something(self, value):
a = child(value)
return a
class child(parent):
def something_that_is_not_init(self):
return self.i
The child class inherits init from the parent class. So my question is, in my parent class, can I create an instance of the child object, use and return it?
I would execute it as following:
a = parent(2)
b = a.something(3)
b.something_that_is_not_init()
3
Edited question a bit, updated code section since the question wasn't clear.
Yes, it's valid, but I don't recommend it. It's generally considered bad OOP programming. Also, you can create it as a static method so you never actually have to instantiate the parent class.
class parent():
def __init__(self, i):
self.i = i
#staticmethod
def foo(i):
c = child(i)
return c
class child(parent):
def bar(self):
print("Lucker number {}.".format(self.i)) # just to show the parent __init__ function is called
c = parent.foo(7)
c.bar() #=> Lucky number 7.
I just tried your example (including some missing self) and with python3 at least it works:
class Parent():
def __init__(self):
pass
def something(self):
a = child()
return a
class Child(parent):
def something_that_is_not_init(self):
print('yes, you got me')
and calling the something method works:
print(parent().something().__class__.__name__)
# Child
parent().something().something_that_is_not_init()
# yes, you got me
But maybe that's not very good design. Consider a factory or using __new__. But since you explicitly stated you wanted something like this: It works, even though I feel slightly spoiled writing it :-)

Using Python how can I have multiple class instances with their own objects as members?

I am trying to have two objects of the same class have their own object as a member...when I call a function of their individual classes, that function is being called from both top-objects...
like this...
class Operation(threading._Timer):
def __init__(self):
threading._Timer.__init__(self)
def cancel(self):
self.finished.set()
class Manager():
def __init__(self):
self.ops = Operation()
def stop(self):
self.ops.cancel()
class A(object):
def __init__(self):
self.ClassManager = Manager()
instance1 = A()
instance2 = A()
instance1.ClassManager.stop()
#
When I call instance1.ClassManager.stop(), it also stops the instance2's Manager.Operation....
I've looked around and only found that if your class has __init__(self): with its members defined with the self tag, they should be individualized for that particular instance of the class...
Thanks

Categories

Resources