Class and external method call - python

I am going through a data structures course and I am not understanding how a Class can call a method that's in another Class.
The code below has 2 classes: Printer and Task.
Notice that class Printer has a method called startNext, and this has a variable self.timeRemaining that gets assigned the result of newTask.getPages() * 60/self.pagerate.
How can newTaks reference the getPages() method from the Task class?
The code that passes this object to the Printer class never references the Task class.
The code works, since this is what the course gives out but, I just cannot understand how that method is accessed.
Code:
from pythonds.basic.queue import Queue
import random
class Printer:
def __init__(self, ppm):
self.pagerate = ppm
self.currentTask = None
self.timeRemaining = 0
def tick(self):
if self.currentTask != None:
self.timeRemaining = self.timeRemaining - 1
if self.timeRemaining <= 0:
self.currentTask = None
def busy(self):
if self.currentTask != None:
return True
else:
return False
def startNext(self, newTask):
self.currentTask = newTask
self.timeRemaining = newTask.getPages() * 60/self.pagerate
class Task:
def __init__(self, time):
self.timeStamp = time
self.pages = random.randrange(1, 21)
def getStamp(self):
return self.timeStamp
def getPages(self):
return self.pages
def waitTime(self, currentTime):
return currentTime - self.timeStamp
def simulation(numSeconds, pagesPerMinute):
labPrinter = Printer(pagesPerMinute)
printQueue = Queue()
waitingTimes = []
for currentSecond in range(numSeconds):
if newPrintTask():
task = Task(currentSecond)
printQueue.enqueue(task)
if (not labPrinter.busy()) and (not printQueue.isEmpty()):
nextTask = printQueue.dequeue()
waitingTimes.append(nextTask.waitTime(currentSecond))
labPrinter.startNext(nextTask)
labPrinter.tick()
averageWait = sum(waitingTimes)/len(waitingTimes)
print "Average Wait %6.2f secs %3d tasks remaining." % (averageWait, printQueue.size())
def newPrintTask():
num = random.randrange(1, 181)
if num == 180:
return True
else:
return False
for i in range(10):
simulation(3600, 5)

If I understand clearly your question, it is because you are adding task object to Queue list. Then when you are getting object (list item) back, you are getting again Task object:
#creating Task object and adding to Queque list
task = Task(currentSecond)
printQueue.enqueue(task)
class Queue:
def __init__(self):
#list of task objects
self.items = []
def enqueue(self, item):
#you are inserting Task object item to list
self.items.insert(0,item)
def dequeue(self):
#returns task object
return self.items.pop()
So then you can call startNext() method from Printer class, because the dequeue() method is returning Task object.
And because of the object in startNext() is type of Task, you can call getPages() method on that object.
Is it sufficient answer?

Related

Implement a queue with 2 stacks python and analyze the running time

I've been going over some of the many coding interview questions.
I was wondering about implementing a queue using two stacks in Python. I'm working on algorithm question to implement a queue with two stacks for purposes of understanding both data structures.
I have the below:
class QueueTwoStacks:
def __init__(self):
self.in_stack = []
self.out_stack = []
def enqueue(self, item):
self.in_stack.append(item)
def dequeue(self):
if len(self.out_stack) == 0:
# Move items from in_stack to out_stack, reversing order
while len(self.in_stack) > 0:
newest_in_stack_item = self.in_stack.pop()
self.out_stack.append(newest_in_stack_item)
# If out_stack is still empty, raise an error
if len(self.out_stack) == 0:
raise IndexError("Can't dequeue from empty queue!")
return self.out_stack.pop()
What is the runtime analysis for this one?
Why is it true that we can get O(m)O(m) runtime for mm function calls.
Am I assuming have a stack implementation and it gives O(1)O(1) time push and pop?
I appreciate your explanation for this. thank you.
Yes. We can Optimize for the time cost of m function calls on your queue. This optimization can be any mix of enqueue and dequeue calls.
Assume you already have a stack implementation and it gives O(1)O(1) time push and pop.
#
#
class Stack():
def __init__(self):
self.stk = []
def pop(self):
"""raises IndexError if you pop when it's empty"""
return self.stk.pop()
def push(self, elt):
self.stk.append(elt)
def is_empty(self):
return len(self.stk) == 0
def peek(self):
if not self.stk.is_empty():
return self.stk[-1]
class Queue():
def __init__(self):
self.q = Stack() # the primary queue
self.b = Stack() # the reverse, opposite q (a joke: q vs b)
self.front = None
def is_empty(self):
return self.q.is_empty()
def peek(self):
if self.q.is_empty():
return None
else:
return self.front
def enqueue(self, elt):
self.front = elt
self.q.push(elt)
def dequeue(self):
"""raises IndexError if you dequeue from an empty queue"""
while not self.q.is_empty() > 0:
elt = self.q.pop()
self.b.push(elt)
val = self.b.pop()
elt = None
while not self.b.is_empty() > 0:
elt = self.b.pop()
self.q.push(elt)
self.front = elt
return val
# Now let's test
class TestQueueTwoStacks(unittest.TestCase):
def setUp(self):
self.q = Queue()
def test_queuedequue(self):
"""queue up 5 integers, check they are in there, dequeue them, check for emptiness, perform other blackbox and whitebox tests"""
self.assertTrue(self.q.is_empty())
self.assertTrue(self.q.q.is_empty())
self.assertTrue(self.q.b.is_empty())
l = range(5)
for i in l:
self.q.enqueue(i)
self.assertEqual(4, self.q.peek())
self.assertEqual(l, self.q.q.stk)
s = []
l.reverse()
for i in l:
elt = self.q.dequeue()
s.append(elt)
self.assertTrue(self.q.is_empty())
self.assertTrue(self.q.q.is_empty())
self.assertTrue(self.q.b.is_empty())
l.reverse()
self.assertEqual(s, l)
self.assertEqual([], self.q.b.stk)
self.assertEqual([], self.q.q.stk)
if __name__ == "__main__":
# unittest.main()
suite = unittest.TestLoader().loadTestsFromTestCase(TestQueueTwoStacks)
unittest.TextTestRunner(verbosity=2).run(suite)

Provide a list of methods in a class for use outside of it

How can I provide a list of methods in a class for use outside of it?
What I'm looking for
When I create an object from a class extending a higher class, I want to get a list of specific methods, some "meta data" of them, and to able to call them outside the class.
Example:
def params(params):
def params_fn(f):
def params_dec(*args, **kwargs):
for i in params:
f.__setattr__(i, params[i])
return f(*args, **kwargs)
return params_dec
return params_fn
class Channel:
queue = None
# some code & docs omitted
def __init__(self, queue):
self.queue = queue
def start(self):
while True:
if not self.check():
break
class channelA(Channel):
extra_methods = ['get_users', 'get_groups']
def start(self):
# omitted
pass
def __internal_method(self, d):
# omitted
pass
#params({"name": "Get users", "desc": "Get a list of users", "icon": "user-plus"})
def get_users(self):
# omitted
return [i for i in self.queue if i.type = 1]
#params({"name": "Get groups", "desc": "Get a list of groups", "icon": "group-plus"})
def get_groups(self):
# omitted
return [i for i in self.queue if i.type = 2]
q = []
ch = channelA(q)
# some code goes here
# it may be something like
# fns = ch.get_extra_fns()
# or anything similar
for fnName in fns:
print("Callable name:", fnName)
print("Name:", fns[fnName].name)
print("Description:", fns[fnName].desc)
print("Icon ID:", fns[fnName].icon)
print("Result:")
print(ch.call(fns[fnName])())
Is it possible to achieve something like this?
You don't need a wrapper for your decorated methods, since you only set attributes of the method-object. To identify your methods, I would suggest to set a special attribute for these methods, iterate over all class methods and pick those, that have this special method set:
def special(**kw):
def mark(function):
function.is_special = True
function.keywords = kw
return function
return mark
class Channel:
def __init__(self, queue):
self.queue = queue
def start(self):
while True:
if not self.check():
break
class ChannelA(Channel):
def start(self):
# omitted
pass
#special(icon="users.png")
def get_users(self):
# omitted
return [i for i in self.queue if i.type == 1]
#special(hint="don't feed the trolls")
def get_groups(self):
# omitted
return [i for i in self.queue if i.type == 2]
ch = ChannelA(q)
for methodname in dir(type(ch)):
method = getattr(ch, methodname)
if getattr(method, 'is_special', False):
print("Callable name:", method.__name__)
print("Keywords:", method.keywords)
print("Result:", method())
def get_extra_fns(self):
fns = {}
for i in self.extra_methods:
fns['i'] = self.__getattribute__(i)
return fns
Python 3:
import types
import inspect
class A:
def a(self):
pass
class B(A):
def b(self, bool_param, int_param):
pass
b = B()
for member_name in dir(B):
member = getattr(B, member_name)
if isinstance(member, types.FunctionType):
member(b, True) # as illustrated by you... this is hardcoded
argspec = inspect.getargspec(member)
args_for_call = {}
for argname in argspec.args:
if argname == 'bool_param':
args_for_call['bool_param'] = True
if argname == 'int_param':
args_for_call['int_param'] = 3
member(b, **args_for_call) # This is less hardcoded

Print dict with custom class as values wont call their string method?

I was messing around with classes in python and wrote 2 little ones:
class ClaElement:
start = None
end = None
basesLeft = None
orientation = None
contig = None
size = None
def __init__(self, contig, start, end, orientation, basesLeft=None):
self.contig = contig
self.start = start
self.end = end
self.orientation = orientation
self.basesLeft = basesLeft
self.size = self.end - self.start
def __str__(self):
return "{ClaElement: "+str(self.contig)+"_"+str(self.start)+"_"+str(self.end)+"_"+str(self.orientation)+"}"
def getSize(self):
return self.size
class ClaCluster:
contig = None
clusterElements = []
def __init__(self, contig, firstElement):
self.contig = contig
self.addElement(firstElement)
def addElement(self, claElement):
self.clusterElements.append(claElement)
def getFirst(self):
return self.clusterElements[0]
def getLast(self):
return self.clusterElements[-1]
def getElements(self):
return self.clusterElements
def getContig(self):
return self.contig
def __str__(self):
return "{ClaCluster: "+str(self.contig)+" "+str(len(self.clusterElements))+" elements}"
And my test-main:
from ClaElement import ClaElement
from ClaCluster import ClaCluster
if __name__ == '__main__':
ele = ClaElement("x",1,2,"left")
claDict = dict()
cluster = ClaCluster("x", ele)
claDict["hello"] = cluster
print(claDict)
print(claDict["hello"])
print(ele)
This leads to the following output:
{'hello': <ClaCluster.ClaCluster object at 0x7fe8ee04c5f8>}
{ClaCluster: x 1 elements}
{ClaElement: x_1_2_left}
Now my question is why is the output of my first print the memory address even though I provided a functioning string-method for my class ClaCluster? Is there a way to get the method invoked when I am printing the dictionary or do I have to iterate by hand?
The __str__() method of the built-in dict type uses the __repr__() method of your class, not __str__(). Simply rename your method, and all should work fine.

I cannot understand a case of passing an object as a parameter

I have a class Node with a function defined
class Node(object):
def __init__(self, index, state = None, input = None, directed_neighbours=False):
"""
Parameters
----------
index : int
Node index. Must be unique in the graph.
"""
self._input = input
self.state = state
#self._status = 'active'
self._index = int(index)
self._neighbours = set()
self._port_count = 0
self._ports = []
if directed_neighbours:
self._predecessors = set()
self._successors = self._neighbours
self._directed_neighbours = True
else:
self._successors = self._neighbours
self._predecessors = self._neighbours
self._directed_neighbours = False
#property
def setStatus(self, status):
self._status = status
I have another function
def init(node):
node.setStatus('active')
Now, I have a class
class DistAlgo:
def __init__(self, name, initFunc, states, messages, sendFunc, receiveFunc, stoppingCheck):
self.name = name
#self.inputGraph = inputGraph
self.initFunc = initFunc
self.states = states
self.messages = messages
self.sendFunc = sendFunc
self.receiveFunc = receiveFunc
self.comm_round = 0
self.stoppingCheck = stoppingCheck
def run(self, inputGraph):
for node in inputGraph.nodes:
print('hello', node)
node.state = self.initFunc(node)
<....more code...>
When I create an object of DistAlgo
myalgo = DistAlgo('BMM', init, states, messages, send, receive, stoppingCheck)
and then call its run function:
myalgo.run(problemGraph)
I get an error in the init function above, as:
TypeError: setStatus() missing 1 required positional argument: 'status'
I surely am doing more than one thing wrong I guess, as this is my first Python try. Please point them out!
Properties work a bit differently:
#property
def status(self):
return self._status
#status.setter
def status(self, status):
self._status = status
Now you can set the value with an assignment:
node.status = 'active'

How to create new class instances dynamically at runtime in python?

I am trying to solve this problem:
Imagine a (literal) stack of plates. If the stack gets too high, it
might topple. There- fore, in real life, we would likely start a new
stack when the previous stack exceeds some threshold. Implement a data
structure SetOfStacks that mimics this. SetOf- Stacks should be
composed of several stacks, and should create a new stack once the
previous one exceeds capacity. SetOfStacks.push() and
SetOfStacks.pop() should behave identically to a single stack (that
is, pop() should return the same values as it would if there were just
a single stack). Bonus: Implement a function popAt(int index) which
performs a pop operation on a specific sub-stack.
So I wrote the code:
#!/bin/env python
from types import *
class Stack:
def __init__(self):
self.items = []
self.capacity = 3
self.stackscount = 0
def create(self):
id = self.stackscount + 1
id = str(id) + "_stack"
# How to create a new instance of Stack class at runtime ?
# the __init__ must be run too.
def push(self, item):
if self.size() <= self.capacity:
self.items.append(item)
else:
self.create()
def pop(self):
return self.items.pop()
def popAt(self):
pass
def peek(self):
return self.items[len(self.items)-1]
def size(self):
return len(self.items)
s = Stack()
s.push(10)
How do I create a new s type object dynamically at runtime? I searched on the internet and found that using new.instance or new.classobj is the solution but when I did so my new object did not seem to have items from __init__ function. In python3, type() seems to be the answer but the docs doesn't have any examples.
You've confused yourself by referring to a "type object". In Python that means the class itself, not its instances.
To create new Stack objects, simply do what you're already doing: call the Stack class. You can append them to a list:
stacks = [Stack() for _ in range(5)]
However, as jon points out, that won't solve your problem since you haven't defined the SetOfStacks class.
You could simply use a parent-child relation : when a Stack is full, it creates a child and delegate next pushes to it. It could lead to :
class Stack:
def __init__(self, parent = None, id=None):
self.stackscount = 0
self.capacity = 3
self.items = []
self.parent = parent
self.id = id
self.child = None
def create(self):
id = self.stackscount + 1
id = str(id) + "_stack"
return Stack(self, id)
def push(self, item):
if self.size() <= self.capacity:
self.items.append(item)
else:
if self.child is None:
self.child = self.create()
self.child.push(item)
def pop(self):
if self.child is not None:
item = self.child.pop()
if len(self.child.items) == 0:
self.child = None
else:
item = self.items.pop()
return item
def popAt(self):
pass
def peek(self):
if self.child is not None:
item = self.child.peek()
else:
item = self.items[len(self.items)-1]
return item
def size(self):
l = len(self.items)
if self.child is not None:
l += self.child.size()
return l
s = Stack()
s.push(10)
popAt is still to be implemented, but I tested it and it correctly creates new stacks when pushing and empties and removes them when popping.
The implementation of popAt will require some evolutions to current pop implementation, to allow removing an intermediate stack :
def pop(self):
if self.child is not None:
item = self.child.pop()
if len(self.child.items) == 0:
self.child = self.child.child
if self.child is not None:
self.child.parent = self
else:
item = self.items.pop()
return item
def popAt(self, stacknumber):
s = self
for i in range(stacknumber):
s = s.child
if s is None:
return None
if len(s.items) == 0:
return None
item = s.items.pop()
if len(s.items) == 0 and s.parent is not None:
s.parent.child = s.child
if s.child is not None:
s.child.parent = s.parent
return item
The type() function is indeed what you are looking for. Documentation can be found here: https://docs.python.org/2/library/functions.html#type
You can call it like this:
# Bases is a tuple of parent classes to inherit
bases = Stack,
# Dict contains extra properties for the class, for example if you want to add a class variable or function
dict_ = {}
# Construct the class
YourClass = type('YourClass', bases, dict_)
# Create an instance of the class
your_instance = YourClass()
It looks like you are just looking at instance creation though:
class Stack(object):
def create(self):
id = self.stackscount + 1
id = str(id) + "_stack"
# How to create a new instance of Stack class at runtime ?
# the __init__ must be run too.
stack = Stack()

Categories

Resources