correct class inheritance - python

I've written some code that allows the term 'job' to be used universally to perform a unique task. The specific jobs can be chosen through setting an initial variable "job_type". From that initial variable a particulay subclass is chosen to perform the appropriate job. Maybe the code will make more sense :)
if __name__=='__main__':
# these variables would normally be called in from a config file
job_type = 'job1'
uni_var = 10
job_select = superClass(job_type, uni_var)
job_select.job()
class superClass(object):
def __init__(self, job_type, uni_var):
self.job_type = job_type
self.uni_var = uni_var
if self.job_type == 'job1':
self.jobChoice = option1()
else:
self.jobChoice = option2()
# This is the definition called by the main function it then
# redirects the request to the appropriate job sub class
def job(self):
self.jobChoice.job()
class option1(superClass):
def __init__(self):
pass
def job(self):
print 'job option 1'
print uni_var
class option2(superClass):
def __init__(self):
pass
def job(self):
print 'job option 2'
print uni_var
The thought behind this code was to allow a single/constant 'main' function, to action a variety of unique tasks based purely on the variable 'job_type'. Which it seems to be doing fine.
My question (as a very inexperienced coder) is, have I gone about this the right way or is there a better way to do things?
Also, have I set up the variable 'uni_var' correctly in the superClass to be correctly shared across all/any superClass subclasses?
Thanks.

I suspect that what you really want is to use the Factory Method Pattern here.
You could change your code to something like this:
if __name__=='__main__':
# these variables would normally be called in from a config file
job_type = 'job1'
uni_var = 10
job_select = superClass.optionFactory(job_type, uni_var)
job_select.job()
class superClass(object):
def __init__(self, job_type, uni_var):
self.job_type = job_type
self.uni_var = uni_var
# This is the definition called by the main function it then
# redirects the request to the appropriate job sub class
def job(self):
raise NotImplementedError()
#staticmethod
def optionFactory(job_type, uni_var):
"Return an instance of superClass based on job_type and uni_var."
if job_type == "job1":
return option1(job_type, uni_var)
else:
return option2(job_type, uni_var)
class option1(superClass):
def __init__(self, job_type, uni_var):
super(option1, self).__init__(job_type, uni_var)
def job(self):
print 'job option 1'
print uni_var
class option2(superClass):
def __init__(self, job_type, uni_var):
super(option2, self).__init__(job_type, uni_var)
def job(self):
print 'job option 2'
print uni_var
However, notice that this implementation will require that superClass be changed every time a new subclass is created. Another alternative would be to make the optionFactory method a standalone function (rather than a method of superClass). Like this:
if __name__=='__main__':
# these variables would normally be called in from a config file
job_type = 'job1'
uni_var = 10
job_select = optionFactory(job_type, uni_var)
job_select.job()
class superClass(object):
def __init__(self, job_type, uni_var):
self.job_type = job_type
self.uni_var = uni_var
# This is the definition called by the main function it then
# redirects the request to the appropriate job sub class
def job(self):
raise NotImplementedError()
class option1(superClass):
def __init__(self, job_type, uni_var):
super(option1, self).__init__(job_type, uni_var)
def job(self):
print 'job option 1'
print uni_var
class option2(superClass):
def __init__(self, job_type, uni_var):
super(option2, self).__init__(job_type, uni_var)
def job(self):
print 'job option 2'
print uni_var
def optionFactory(job_type, uni_var):
"Return an instance of superClass based on job_type and uni_var."
if job_type == "job1":
return option1(job_type, uni_var)
else:
return option2(job_type, uni_var)

Don't use a class as a factory, it's silly. You just need a consistent interface across implementations.
class JobA(object):
def do_job(self, arg):
print 'job a', arg
class JobB(object):
def do_job(self, arg):
print 'job b', arg
job_types = {
'job1': JobA, 'job2': JobB
}
job_type = 'job1'
uni_var = 10
job = job_types[job_type]()
job.do_job(uni_var)
Hell, if the jobs don't keep state, they shouldn't be classes, either, but functions instead.
def job_a(arg):
...
def job_b(arg):
...
job = job_types[job_type]
job(uni_var)

You are actually not using inheritance at all in your original code, and your code contains a severe bug, but masks it from appearing.
You create an instance of superClass, which stores job_type and uni_var, and then instantiates either option1 or option2 and stores a reference to that. The "subclasses" are initialised with no data (so they have no job_type or uni_var attributes, and you have to override __init__ to do-nothing methods to avoid error).
When you call job_select.job(...), superClass explicitly delegates to its job_choice attribute. So there's no useful inheritance going on; you've overridden everything about superClass in your subclasses, and instead having job_select be an instance of different sub-classes depending on the job_type and using method resolution to call the right code, job_select is always a superClass which contains an option1 or option2 and explicitly delegates to it.
The serious bug I mentioned: neither option1 nor option2 actually contains any information about the job, so their job methods can't do anything interesting. You call print uni_var, which doesn't work (it would normally be print self.uni_var to get the uni_var of this job), but seems to work because you have a global called uni_var. As soon as you start doing anything more complicated this scheme will fall over badly.
#srgerg's answer is a good example of what you could do to actually use inheritance and factory functions to solve your problem. #CatPlusPlus's answer is a good example of how you can use more appropriate tools for the very simple code in this example (may not be what you need if your real requirements are more complex what you've got written at the moment).

Related

Creating methods on the fly for a class instance

The following program is unable to create a function of a class
class MyClass(object):
def __init__(self, name=""):
self.name = name
def read_name(self):
return self.name
# First argument should be a ref to class
def callback(fcn, arg):
fcn.name=arg
# Create a instance of class
a = MyClass("Blue")
# Lets add new member functions
setattr(a, 'callback1', callback)
setattr(a, 'callback2', callback)
print a.read_name()
print a.callback1("purple") #! FAILS
print a.callback2("cyan") #! FAILS
What is the right way of creating a class member function automatically?
I want to create 'N' callback functions, they all will modify some common/uncommon class data (A shared dict)
EDIT 1
I wish to collect information from 'N' separate/parallel threads by passing callback functions. I do not know beforehand how many callback functions I need thus I want to create them on fly.
EDIT 2
I have a dictionary(d) where I am storing the information of different processes. The dictionary(d) is accessed within the callback. But because the same callback function is called at different threads, the dictionary data gets garbled. As a quickfix, I thought of creating separate callbacks.
If you know what you're doing, you'd want to try
import types
setattr(a, 'callback1', types.MethodType(callback, a, MyClass))
In short: when grafting a method, assign it to the class, not to the instance.
Here's an elucidating example.
class A(object):
"""As trivial as a class can get."""
def foo(self):
return self.bar(1) + self.baz()
# Rework everything!
def new_bar(self, x):
return 'I got %r' % x
def new_baz(self):
return ' and I\'m okay!'
A.bar = new_bar
A.baz = new_baz
print A().foo()
Now grafting method to an instance.
a = A()
# An instance attribute is a bound method;
# when we replace it with a function, we lose access to self.
a.bar = lambda x: x * 100
A.baz = lambda self: 42
assert a.foo() == 142
# We can do better, though.
from types import MethodType
a2 = A()
a2.foo = MethodType(lambda self: 'I know myself, my class is %s' % self.__class__.__name__, a2)
print a2.foo()
Note how you don't need setattr to set an attribute, even an unknown attribute. You may remember that you don't use setattr in __init__ either.
You can't add a class method to an instance; you have to add it to the class:
setattr(MyClass, 'callback1', callback)
But it's still a terrible idea. Why would you want this functionality?
Edit: keep your callbacks in a container instead:
class MyClass(object):
def __init__(self, name=""):
self.name = name
self.callbacks = []
def callback(self, idx, arg):
self.callbacks[idx](self, arg)
# First argument should be a ref to class
def callback(fcn, arg):
fcn.name=arg
# Create a instance of class
a = MyClass("Blue")
# Lets add new member functions
a.callbacks.append(callback)
a.callbacks.append(callback)
print a.name
a.callback(0, "purple")
print a.name
a.callback(1, "cyan")
print a.name

Accessing Class variables from another class

How do you access an instance in an object and pass it to another 'main' object? I'm working with a parser for a file that parses different tags, INDI(individual), BIRT(event), FAMS(spouse), FAMC(children)
Basically there are three classes: Person, Event, Family
class Person():
def __init__(self, ref):
self._id = ref
self._birth : None
def addBirth(self, event):
self._birth: event
class Event():
def __init__(self, ref):
self._id = ref
self._event = None
def addEvent(self, event):
self._event = event
#**event = ['12 Jul 1997', 'Seattle, WA'] (this is generated from a function outside a class)
I want to transfer self._event from the Event class into addBirth method to add it into my person class. I have little knowledge on how classes and class inhertiances work. Please help!
If I understand your question, you want to pass an (for example) Event object to an instance of Person?
Honestly, I don't understand the intent of your code, but you probably just need to pass self from one class instance to the other class instance.
self references the current instance.
class Person:
def __init__(self):
self._events = []
def add_event(self, event)
self._events.append(event)
class Event:
def add_to_person(self, person):
person.add_event(self)
The most proper way to handle situations like this is to use getter and setter methods; data encapsulation is important in OO programming. I don't always see this done in Python where I think it should, as compared to other languages. It simply means to add methods to your classes who sole purpose are to return args to a caller, or modify args from a caller. For example
Say you have class A and B, and class B (caller) wants to use a variable x from class A. Then class A should provide a getter interface to handle such situations. Setting you work the same:
class class_A():
def __init__(self, init_args):
x = 0
def someMethod():
doStuff()
def getX():
return x
def setX(val):
x = val
class class_B():
def init(self):
init_args = stuff
A = class_A(init_args)
x = class_A.getX()
def someOtherMethod():
doStuff()
So if class B wanted the x property of an instance object A of class class_A, B just needs to call the getter method.
As far as passing instances of objects themselves, say if you wanted A to pass an already-created instance object of itself to a method in class B, then indeed, you simply would pass self.

How To Call A Class Function From A Variable

I need a class router (for lack of a better word). The router needs to instantiate a class & call a function of that class instance based on variables passed to it.
How do I properly define the class function?
How do I properly call the class function?
Example code:
class ClassWorker1:
def function_1(self):
print('1a')
def function_2(self):
print('2a')
def function_3(self):
print('3a')
class ClassWorker2:
def function_1(self):
print('1b')
def function_2(self):
print('2b')
def function_3(self):
print('3b')
class ClassRouter(object):
def __init__(self, class_name, class_function):
self.class_instance = class_name()
self.class_function = class_function
self.main()
def main(self):
# how should I call the class function here?
self.class_instance.class_function()
return
a = 1
b = 1
if a == 1:
class_name = ClassWorker1
else:
class_name = ClassWorker1
if b == 1:
# Strings won't work as class function definition
# I won't know the class at this point. I will only know
# the shared function name at this point.
# how could this class function be defined directly?
class_function = 'function_1'
elif b == 2:
class_function = 'function_2'
else:
class_function = 'function_3'
ClassRouter(class_name, class_function)
I need a class router (for lack of a better word).
Are you sure you need a class for this ?
The router needs to instantiate a class & call a function of that class instance
When it belongs to a class or instance, a function is usually named a "method". Not really important but it makes things clearer. Also, an "instance" is obviously always, by definition, an instance of a class ;)
How do I properly define the class function?
How do I properly call the class function?
Does the router really have to be a class ? But anyway...
There are a couple distinct issues here (I of course assume you need something that's generic enough).
The first one is that your class (the one that will be instanciated by the "router") constructor may need some args - position or named or both. If it's the router's duty to instanciate the class (but should it be ?), you'll have to pass those args (both position and named) to the router. And since your router has to be generic (else it's useless) you cannot explicitely name these args in your router's constructor.
Hopefully, Python has a way to "unpack" tuples (for position args) and dicts (for named args) when calling a function, using respectively the * and ** operators at call time, ie:
def somefunc(arg1, arg2, arg3="foo", arg4=None):
print arg1, arg2, arg3, arg4
args = ("one", "two", "three")
kwargs = {"arg4": "four"}
somefunc(*args, **kwargs)
This let you pass arguments to a function in a generic way.
So if you want your router to be in charge of instanciating the "target" class, you'll have to support this:
class Router(object):
def __init__(self, cls, clsargs=None, clskwargs=None):
if clsargs is None:
clsargs = ()
if clskwargs is None:
clskwargs = {}
self._obj = cls(*clsargs, **clskwargs)
class Worker(object):
def __init__(self, name):
self.name = name
print self.name
r = Router(Worker, clsargs=("foo",))
# or
r = Router(Worker, clskwargs={"name":"foo"})
Now note that at this point you really don't gain anything (except for more code) from having the router instanciating the Worker - since you need to have the Worker class and it's constructor's args to instanciate the router, you could as well just instanciate the Worker yourself and pass the Worker instance to the router:
Since you must have a reference to the class passed to the router (else you can't pass it ), you could as well
class Router(object):
def __init__(self, obj):
self._obj = obj
class Worker(object):
def __init__(self, name):
self.name = name
print self.name
r = Router(Worker("foo"))
# or
r = Router(Worker(name="foo"))
The cases where it would make sense to have the router instanciate the worker are:
1/ if the Worker's constructor arguments are not known when the router is instanciated and are to be passed later (which requires a distinct router method to pass those args)
2/ if the Worker's instanciation is very costly and you're not even sure you'll really need it, in which case you want to wait until the router's "main" method is called to instanciate the worker.
The second issue is "how do I get the worker's method by name". This one has already been answered by Lukas: you use getattr(obj, attrname).
The third issue is "if my worker method needs arguments, how do I pass them". This is the same problem as with the worker's constructor arguments, so the solution is obviously the same. Depending on the concrete use case, you'll have to pass those args either when instanciating the router or when calling it's "main" method.
wrt/ this "main" method, remember that you can define your own callable types by implementing the __call__ method, ie
class NotAFunc(object):
def __init__(self, wot):
self.wot = wot
def __call__(self, count):
print self.wot * count
notafunc = NotAFunc("wot ? ")
notafunc(42)
So it might make sense to use this as your router's "main" method
Now do you really need a router class at all ? Python functions are object on their own (so a function can take a function and/or return a function), and moreover act as closures (a closure is a function that "captures" part of the environment where it's been defined):
def route(instance, methodname, methargs=None, methkwargs=None):
method = getattr(instance, methodname)
if methargs is None:
methargs = ()
if methkwargs is None:
methkwargs = {}
def func():
return method(*methargs, **methkwargs)
return func
class Worker(object):
def __init__(self, name):
self.name = name
def work(self, count):
return [self.name for i in range(count)]
r = route(Worker("foo"), "work", (42,))
print r()
Note that while I kept your "router" term, most of what I described above are known patterns. You may want to search for "proxy", "proxy method", and (for the last exemple) "partial evaluation".
You are looking for dynamic attribute lookup.
class C:
def c1(self, x):
return 2*x
instance = C()
method_name = 'c1'
method = getattr(instance, method_name)
print(method(1)) # call method and print result
You'll need to override the __new__ method of your (new-style!) class.
class ClassRouter(object):
def __new__(self, class_name, *args):
if arg=="Class1":
new_instance = ClassWorker1(*args)
new_instance.method()
return new_instance
elif arg=="Class2":
return ClassWorker2(*args)

python classes getters and setters static method and class method

class Spam(object):
#a_string = 'candy'
def __init__(self, sold=0, cost=0):
self.sold = sold
self.cost = cost
#staticmethod
def total_cost():
return True
#classmethod
def items_sold(cls, how_many):
#property
def silly_walk(self):
return print (self.a_string)
#silly_walk.setter
def silly_walk(self, new_string):
self.a_string = new_string.upper()
def do_cost(self):
if self.total_cost():
print('Total cost is:', self.cost)
.
from spam import Spam
def main ():
cost = 25
sold = 100
a_string = 'sweets'
sp = Spam(100, 25)
sp.do_cost()
sw = Spam.silly_walk(a_string)
sw.silly_walk()
if __name__ == '__main__':
main()
so im new to python and i don't understand how to use the setters and getters in this. so what i want to do is:
use #property to create a setter and getter for a property named silly_walk. Have the setter upper case the silly_walk string.
Show example code that would access the static method.
Show example code that would use the silly_walk setter and getter.
im getting very confused with what "self" does in the class and im not sure if what im doing is correct
update:
problem was the #classmethod not having a return and indentation error, so everything is fixed thanks everybody
self is convention. Since you're inside a class, you don't have functions there you have methods. Methods expect a reference to the object calling them as the first argument, which by convention is named self. You can call it anything you like.
class Foo(object):
def __init__(itsa_me_maaaario, name):
itsa_me_maaario.name = "Mario"
That works just as well.
As for the rest of your code -- what's your QUESTION there? Looks like your setter is a bit weird, but other than that it should work mostly okay. This is better:
class Spam(object): # inherit from object in py2 for new-style classes
def __init__(self, a_string, sold=0, cost=0) # put the positional arg first
...
#staticmethod
def total_cost():
# you have to do something meaningful here. A static method can't access
# any of the objects attributes, it's really only included for grouping
# related functions to their classes.
#classmethod
def items_sold(cls, how_many):
# the first argument to a classmethod is the class, not the object, so
# by convention name it cls. Again this should be something relevant to
# the class not to the object.
#property
def silly_walk(self):
return self.a_string
# don't call itself.
#silly_walk.setter
def silly_walk(self, new_string):
self.a_string = new_string
# it really just hides the attribute.
For instance I have a class I built to abstract a computer system I'm in charge of. It might be something like:
class System(object):
type_ = "Base system"
def __init__(self, sitenum, devicenum, IP):
self._sitenum = sitenum
self._devicenum = devicenum
self._IP = IP
# the leading underscores are a flag to future coders that these are
# "private" variables. Nothing stopping someone from using it anyway,
# because System()._IP is still that attribute, but it makes it clear
# that they're not supposed to be used that way.
#staticmethod
def ping_system(IP):
subprocess.call(["ping",IP], shell=True) # OH GOD SECURITY FLAW HERE
# group this with Systems because maybe that's how I want it? It's an
# aesthetic choice. Note that this pings ANY system and requires an
# argument of an IP address!
#classmethod
def type_of_system(cls):
return cls.type_
# imagine I had a bunch of objects that inherited from System, each w/
# a different type_, but they all inherit this....
#property
def description(self):
return "Site {}, Device {} # {}".format(self._sitenum,
self._devicenum,
self._IP)
#description.setter
def description(self, *args):
if len(args) == 3:
self._sitenum, self._devicenum, self._IP = args
elif len(args) == 1 and len(args[0]) == 3:
self._sitenum, self._devicenum, self._IP = args[0]
else:
raise ValueError("Redefine description as Sitenum, Devicenum, IP")
Example:
computer = System(1, 1, '192.168.100.101')
System.ping_system('192.160.100.101') # works
computer.type_of_system # "Base system"
computer.description # "Site 1, Device 1 # 192.168.100.101"
new_description = [1, 2, '192.168.100.102']
computer.description = new_description
# invokes description.setter
computer._devicenum # is 2 after the setter does its magic.

How do I call a parent class's method from a child class in Python?

When creating a simple object hierarchy in Python, I'd like to be able to invoke methods of the parent class from a derived class. In Perl and Java, there is a keyword for this (super). In Perl, I might do this:
package Foo;
sub frotz {
return "Bamf";
}
package Bar;
#ISA = qw(Foo);
sub frotz {
my $str = SUPER::frotz();
return uc($str);
}
In Python, it appears that I have to name the parent class explicitly from the child.
In the example above, I'd have to do something like Foo::frotz().
This doesn't seem right since this behavior makes it hard to make deep hierarchies. If children need to know what class defined an inherited method, then all sorts of information pain is created.
Is this an actual limitation in python, a gap in my understanding or both?
Use the super() function:
class Foo(Bar):
def baz(self, **kwargs):
return super().baz(**kwargs)
For Python < 3, you must explicitly opt in to using new-style classes and use:
class Foo(Bar):
def baz(self, arg):
return super(Foo, self).baz(arg)
Python also has super as well:
super(type[, object-or-type])
Return a proxy object that delegates method calls to a parent or sibling class of type.
This is useful for accessing inherited methods that have been overridden in a class.
The search order is same as that used by getattr() except that the type itself is skipped.
Example:
class A(object): # deriving from 'object' declares A as a 'new-style-class'
def foo(self):
print "foo"
class B(A):
def foo(self):
super(B, self).foo() # calls 'A.foo()'
myB = B()
myB.foo()
ImmediateParentClass.frotz(self)
will be just fine, whether the immediate parent class defined frotz itself or inherited it. super is only needed for proper support of multiple inheritance (and then it only works if every class uses it properly). In general, AnyClass.whatever is going to look up whatever in AnyClass's ancestors if AnyClass doesn't define/override it, and this holds true for "child class calling parent's method" as for any other occurrence!
Python 3 has a different and simpler syntax for calling parent method.
If Foo class inherits from Bar, then from Bar.__init__ can be invoked from Foo via super().__init__():
class Foo(Bar):
def __init__(self, *args, **kwargs):
# invoke Bar.__init__
super().__init__(*args, **kwargs)
Many answers have explained how to call a method from the parent which has been overridden in the child.
However
"how do you call a parent class's method from child class?"
could also just mean:
"how do you call inherited methods?"
You can call methods inherited from a parent class just as if they were methods of the child class, as long as they haven't been overwritten.
e.g. in python 3:
class A():
def bar(self, string):
print("Hi, I'm bar, inherited from A"+string)
class B(A):
def baz(self):
self.bar(" - called by baz in B")
B().baz() # prints out "Hi, I'm bar, inherited from A - called by baz in B"
yes, this may be fairly obvious, but I feel that without pointing this out people may leave this thread with the impression you have to jump through ridiculous hoops just to access inherited methods in python. Especially as this question rates highly in searches for "how to access a parent class's method in Python", and the OP is written from the perspective of someone new to python.
I found:
https://docs.python.org/3/tutorial/classes.html#inheritance
to be useful in understanding how you access inherited methods.
Here is an example of using super():
#New-style classes inherit from object, or from another new-style class
class Dog(object):
name = ''
moves = []
def __init__(self, name):
self.name = name
def moves_setup(self):
self.moves.append('walk')
self.moves.append('run')
def get_moves(self):
return self.moves
class Superdog(Dog):
#Let's try to append new fly ability to our Superdog
def moves_setup(self):
#Set default moves by calling method of parent class
super(Superdog, self).moves_setup()
self.moves.append('fly')
dog = Superdog('Freddy')
print dog.name # Freddy
dog.moves_setup()
print dog.get_moves() # ['walk', 'run', 'fly'].
#As you can see our Superdog has all moves defined in the base Dog class
There's a super() in Python too. It's a bit wonky, because of Python's old- and new-style classes, but is quite commonly used e.g. in constructors:
class Foo(Bar):
def __init__(self):
super(Foo, self).__init__()
self.baz = 5
I would recommend using CLASS.__bases__
something like this
class A:
def __init__(self):
print "I am Class %s"%self.__class__.__name__
for parentClass in self.__class__.__bases__:
print " I am inherited from:",parentClass.__name__
#parentClass.foo(self) <- call parents function with self as first param
class B(A):pass
class C(B):pass
a,b,c = A(),B(),C()
If you don't know how many arguments you might get, and want to pass them all through to the child as well:
class Foo(bar)
def baz(self, arg, *args, **kwargs):
# ... Do your thing
return super(Foo, self).baz(arg, *args, **kwargs)
(From: Python - Cleanest way to override __init__ where an optional kwarg must be used after the super() call?)
There is a super() in python also.
Example for how a super class method is called from a sub class method
class Dog(object):
name = ''
moves = []
def __init__(self, name):
self.name = name
def moves_setup(self,x):
self.moves.append('walk')
self.moves.append('run')
self.moves.append(x)
def get_moves(self):
return self.moves
class Superdog(Dog):
#Let's try to append new fly ability to our Superdog
def moves_setup(self):
#Set default moves by calling method of parent class
super().moves_setup("hello world")
self.moves.append('fly')
dog = Superdog('Freddy')
print (dog.name)
dog.moves_setup()
print (dog.get_moves())
This example is similar to the one explained above.However there is one difference that super doesn't have any arguments passed to it.This above code is executable in python 3.4 version.
In this example cafec_param is a base class (parent class) and abc is a child class. abc calls the AWC method in the base class.
class cafec_param:
def __init__(self,precip,pe,awc,nmonths):
self.precip = precip
self.pe = pe
self.awc = awc
self.nmonths = nmonths
def AWC(self):
if self.awc<254:
Ss = self.awc
Su = 0
self.Ss=Ss
else:
Ss = 254; Su = self.awc-254
self.Ss=Ss + Su
AWC = Ss + Su
return self.Ss
def test(self):
return self.Ss
#return self.Ss*4
class abc(cafec_param):
def rr(self):
return self.AWC()
ee=cafec_param('re',34,56,2)
dd=abc('re',34,56,2)
print(dd.rr())
print(ee.AWC())
print(ee.test())
Output
56
56
56
In Python 2, I didn't have a lot luck with super(). I used the answer from
jimifiki on this SO thread how to refer to a parent method in python?.
Then, I added my own little twist to it, which I think is an improvement in usability (Especially if you have long class names).
Define the base class in one module:
# myA.py
class A():
def foo( self ):
print "foo"
Then import the class into another modules as parent:
# myB.py
from myA import A as parent
class B( parent ):
def foo( self ):
parent.foo( self ) # calls 'A.foo()'
class department:
campus_name="attock"
def printer(self):
print(self.campus_name)
class CS_dept(department):
def overr_CS(self):
department.printer(self)
print("i am child class1")
c=CS_dept()
c.overr_CS()
If you want to call the method of any class, you can simply call Class.method on any instance of the class. If your inheritance is relatively clean, this will work on instances of a child class too:
class Foo:
def __init__(self, var):
self.var = var
def baz(self):
return self.var
class Bar(Foo):
pass
bar = Bar(1)
assert Foo.baz(bar) == 1
class a(object):
def my_hello(self):
print "hello ravi"
class b(a):
def my_hello(self):
super(b,self).my_hello()
print "hi"
obj = b()
obj.my_hello()
This is a more abstract method:
super(self.__class__,self).baz(arg)

Categories