Using super within nested class - python

I am puzzled with the following error in python 2.7.12
Suppose we have a class definition within a class, something similar to this:
class C(object):
def __init__(self):
print "class C"
class D(object):
def __init__(self):
print "class D"
class A(D):
class B(C):
def __init__(self):
# Strangely here B is "not defined", why?
super(B, self).__init__()
print "class B"
def __init__(self):
super(D, self).__init__()
print "class A"
def do_something(self):
b_class = self.B()
print "b_class within A : {}".format(b_class)
a_class = A()
a_class.do_something()
but if we we extract the definition of class B outside the scope of class A,
everything works well.
Do we need to use "super" differently when called within a nested class? I fail to understand why its usage would be different within or outside the nested class. Any pointers?

The problem is not the subclass or superclass, but the nesting. B itself is not defined, only A.B is.
Note that in Python there is almost never a good reason to nest classes, though.

You need to address B by its full name, A.B:
class C(object):
def __init__(self):
print "class C"
class D(object):
def __init__(self):
print "class D"
class A(D):
class B(C):
def __init__(self):
super(A.B, self).__init__()
print "class B"
def __init__(self):
super(D, self).__init__()
print "class A"
def do_something(self):
b_class = self.B()
print "b_class within A : {}".format(b_class)
>>> a_class = A()
>>> a_class.do_something()
class A
class C
class B
b_class within A : <__main__.B object at 0x7f0cac98cbd0>

Related

Share attributes/ variables between classes python

class Base(object):
def __init__(self):
print("Base created")
a = "baseclass"
class ChildA(Base):
def __init__(self):
Base.__init__(self)
b = "child a"
class ChildB(Base):
def __init__(self):
super(ChildB, self).__init__()
c = "child b"
print(a)
print(b)
ChildA()
ChildB()
NameError: name 'a' is not defined
Your issue here is that you're trying to access local variables instead of instance attributes.
Here's how you should do it:
class Base():
def __init__(self):
print("Base created")
# Note that you should use `self.a` instead of `a`
self.a = "baseclass"
class ChildA(Base):
def __init__(self):
Base.__init__(self)
# Use `self.b` instead of `b`
self.b = "child a"
# Did you forget to inherit from `ChildA`?
class ChildB(ChildA):
def __init__(self):
# The `super()` call can be simplified
super().__init__()
# Use `self.c` instead of `c'
self.c = "child b"
# Access the instance variables using `self.`
print(self.c)
print(self.b)
print(self.a)
ChildA()
ChildB()
From the console output:
Base created
Base created
child b
child a
baseclass

Python: Access base class "Class variable" in derive class

I am trying to access a class variable from the base class in the derived class and I am getting a no AttributeError
class Parent(object):
variable = 'foo'
class Child(Parent):
def do_something(self):
local = self.variable
I tried using it as Parent.variable but that did not work either. I am getting the same error
AttributeError: 'Child' object has no attribute 'Child variable'
How do i resolve this
I'm not sure what you're doing wrong. The code below assumes you have an initialization method, however.
class Parent(object):
variable = 'foo'
class Child(Parent):
def __init__(self):
pass
def do_something(self):
local = self.variable
print(local)
c = Child()
c.do_something()
Output:
foo
The code shown below should work on both Python 2 & 3:
class Parent(object):
variable = 'foo'
class Child(Parent):
def do_something(self):
local = self.variable
c = Child()
print(c.variable) # output "foo"

How to access variables from inherited class of parent in python?

I have the following code , where I want to achieve the following:
Please Understand I am a newbie in OOP
1) Initialize "class B" from main function
2) Inherit "class A" from "class B" and depending upon some conditions of variables of "class A" call "class D" from within "class B"
3) After call of "class D" use variables from "class A" to modify them and print it out.
4) After that go back to "class B" to run code for more conditions.
```
class A(object):
def __init__(self):
super(A,self).__init__()
self.A_var = 0
print('Running A.__init__')
class B(A):
def __init__(self):
super(B,self).__init__()
#B.__init__(self)
def fun2():
self.A_var += 5
#foo = D()
self.fun1
print('Running B.__init__')
print self.A_var
#A.__init__(self)
class D(B,A):
def __init__(self):
#super(A,grandfather).__init__()
#A.__init__(grandfather)
super(D,self).__init__()
#D.__init__(self)
def fun1():
print('Running D.__init__')
self.A_var += 400
print self.A_var
if __name__ == '__main__':
b = B()
b.fun2
```
I want to print out the value of "self.A_var" from inside "class D"
if you want to print out the value of "self.A_var" from inside "class D"
than execute : d.fun1()
checkout this modified code:
class A(object):
def __init__(self):
super(A, self).__init__()
self.A_var = 0
print('Running A.__init__')
class B(A):
def __init__(self):
super(B, self).__init__()
def fun2(self):
self.A_var += 5
print ('Running B.__init__'), self.A_var
class D(B):
def __init__(self):
super(D, self).__init__()
def fun1(self):
self.A_var += 400
print ('Running D.__init__'), self.A_var
if __name__ == '__main__':
d = D()
d.fun2()
d.fun1()
with this code output is
Running A.__init__
Running B.__init__ 5
Running D.__init__ 405
You haven't understood what inheritance is. An instance of D is an instance of A and B, because it inherits from them. The only thing you need to do is make sure you call super() in each __init__ method; for some reason you've replaced the one in D with the totally wrong D.__init__, which will endlessly recurse. Put back super(D,self).__init__().
The only other change is to remove the pointless instantiation of D within B.fun2; just call self.fun1() there.

A Python Puzzler

I was wandering if you have any suggestions on how I should perform the following task in python:
Suppose I have the following classes:
class A(object):
self._classes = []
def magic(self):
c.foo() for c in self._classes
class B(object):
def foo():'''some cool stuff here'''
class C(B):
def foo():'''very cool stuff'''
class D(B):
def foo():'''very cool stuff'''
What I want to do is when class A is instantiated all classes of type B - (C and D) will be insantiated in self._classes, meaning _classes is [C(),D()].
The general motivation for this, is that I want the user to easily add classes without the need to know about class that uses them. Any help will be appricated.
Voila (thanks to this answer for all_subclasses()):
# recursively get all subclasses of a given class
def all_subclasses(cls):
return cls.__subclasses__() + [g for s in cls.__subclasses__()
for g in all_subclasses(s)]
class B(object):
def foo(self): print '''some cool stuff here in B'''
class C(B):
def foo(self): print '''very cool stuff in C'''
class D(B):
def foo(self): print '''very cool stuff in D'''
class E(D):
def foo(self): print '''very cool stuff in E'''
class A(object):
def __init__(self):
self._classes = [cls() for cls in all_subclasses(B)]
def magic(self):
for c in self._classes: c.foo()
# usage:
A().magic()
Output:
very cool stuff in C
very cool stuff in D
very cool stuff in E
If you know the module in question for example modulex, you can use dir(modulex) to list all the names in the module and then for each name x you can use modulex.__dict__.get(x) to get the actual object.
Then just check if it is of type of B.
In python you can store objects like other methods in list , so first note that you need to define other class then store them in a list , also you need to using self as your foo functions argument! if you haven't subclasses you can use this :
class B(object):
def foo(self):
print 'B'
class C(B):
def foo(self):
print 'C'
class D(B):
def foo(self):
print 'D'
class A(object):
def __init__(self):
self._classes = [B(),C(),D()]
def magic(self):
for c in self._classes:
c.foo()
A().magic()
resoult:
B
C
D

Python - Accessing parent members

I'm facing a standstill here while trying to figure out how to have member classes access data from their parent when they are part of an external module.
Basically, this works (the B class can access is parent's methods like so: A.say_hi(A) ):
class A:
def __init__(self):
print("Initializing parent object...")
self.child = self.B()
class B:
def __init__(self):
print("Initializing child...")
A.say_hi(A)
def say_hi(self):
print("A class says hi")
However, this can get pretty messy if classes start getting extra large, so I have been placing my additional classes in files and importing them inline. The problem with that is I can no longer get the member class to access its parent's members and functions if I try to use 'import B.py' when class B is defined within.
Is there any way to get the original behavior without leaving the member class inside the same file as the parent?
Actually in your example you couldn't access instance of A in your class B. And the code A.say_hi(A) does work however is wrong. This has been said in comments to your question.
Here is how you do that if you want to be able to access parent instance:
Module b:
class B(object):
def __init__(self, parent):
self.parent = parent
def say_hi(self):
print 'Child says hi to his parent %s' % (
self.parent.__class__.__name__
)
self.parent.say_hi()
Module a:
from b import B
class A(object):
def __init__(self):
self.b = B(self)
def say_hi(self):
print 'Parent says hi!'
If you pass the object (a) to the class (b), you can call it directly.
class a():
def __init__(self):
print"Made A"
def test(self):
print ">>A Test"
class b():
def __init__(self,parent):
print"Made B"
self.parent = parent
def test(self):
print ">>B Test"
self.parent.test()
a = a()
a.test()
b = b(a)
b.test()

Categories