Loading different classes dependant on list contents - python

I have three classes which I want to call and save them dependant on list contents. I want to figure out how to call two classes and call values within tow classes and save them, when I want to call them later, that classes remember and display what a user has been selected.
The code:
_list = [0, 1, 2, 3, 4]
class Data(object):
def __init__(self):
self.ID = 'Data_id'
self.first = 'Data_1'
self.second = 'Data_2'
self.third = 'Data_3'
class Value(object):
def __init__(self):
self.ID = 'Value_id'
self.first = 'Value_1'
self.second = 'Value_2'
self.third = 'Value_3'
class Base(object):
def __init__(self):
self.item = -1
if self.item == 1 or self.item == 2:
self.first_class = Data()
self.second_class = Value()
print('Item:', self.item, 'Class_ID: {}'.format( self.first_class.second))
print('Item:', self.item, 'Class_ID: {}'.format( self.second_class.first))
elif self.item == 2 or self.item == 4:
self.first_class = Data()
self.second_class = Value()
print('Item:', self.item, 'Class_ID: {}'.format( self.first_class.first))
print('Item:', self.item, 'Class_ID: {}'.format( self.second_class.third))
else:
self.first_class = Data()
self.second_class = Value()
print('Item:', self.item, 'Class_ID: {}'.format( self.first_class.ID))
print('Item:', self.item, 'Class_ID: {}'.format( self.second_class.ID))
run = Base()
for i in _list:
run.item = _list[i]
_list values changes every time, it could be None or any int number from 0 to 9 for example. The idea is to call two classes Data and Value every time an item from list is initialized. Then the values within the classes are called for example item 1 is called then the tow classes run and values are called.
print('Item:', self.item, 'Class_ID: {}'.format( self.first_class.first))
print('Item:', self.item, 'Class_ID: {}'.format( self.second_class.third))
After execution of for-loop, user want to run following code or to know which values from which class is called at item = 3
run.item = _list[3]
How can I achieve this behaviour?
I appreciate any help. In advance thanks.

___init___ is a special method which supposed to run exactly once when the class is initialized. When you call run = Base() the logic runs, self.item will be evaluated as -1
What your class does is basically this:
controls = [0,1]
class Controlled:
def __init__(self):
self.param = -1
if self.param == 0:
print(0)
elif self.param == 1:
print(1)
else:
print('This is not unexpected')
c = Controlled()
for p in controls:
c.param = p
If you run Controlled(), the self.param will be -1 every time during the initialization, the else branch will print the This is not unexpected message. The
for p in controls:
c.param = p
part basically just updates the class attribute but does not call anything, nothing will be printed or executed.
I think you wanted to implement something like this:
controls = [0,1]
class Controlled:
def __init__(self, param=-1):
self.param = param
if self.param == 0:
print(0)
elif self.param == 1:
print(1)
else:
print('This is not unexpected')
results = []
for p in controls:
results.append(Controlled(p))
When you call __init__(self, param=-1), the given parameter (p) will be taken into account and the init logic will run based on the given parameter.

Related

How come I see 'None' in output

Learning python from Udacity. Exercise is mentioned below. I cannot see where output 'None' is coming from. Is there something about classes that I am missing ? Thx in advance
Output is always
0
None
======= CODE BEGIN ==============
"""You can use this class to represent how classy someone
or something is.
"Classy" is interchangable with "fancy".
If you add fancy-looking items, you will increase
your "classiness".
Create a function in "Classy" that takes a string as
input and adds it to the "items" list.
Another method should calculate the "classiness"
value based on the items.
The following items have classiness points associated
with them:
"tophat" = 2
"bowtie" = 4
"monocle" = 5
Everything else has 0 points.
Use the test cases below to guide you!"""
class Classy(object):
def __init__(self):
self.items = []
self.classiness = 0
def getClassiness(self):
print(self.classiness)
def createList(self):
self.items.append(item)
def addItem(self, item):
if item=="tophat":
self.classiness+=2
elif item=="bowtie":
self.classiness+=4
elif item=="monocle":
self.classiness+=5
else:
self.classiness+=0
return self.classiness
# Test cases
me = Classy()
# Should be 0
print(me.getClassiness())
Your method getClassiness() is printing and the caller is also printing.
Maybe you meant to return a value rather than printing?
def getClassiness(self):
return self.classiness
class Classy(object):
def __init__(self):
self.items = []
self.classiness = 0
def getClassiness(self):
return self.classiness
def createList(self):
self.items.append(item)
def addItem(self, item):
if item=="tophat":
self.classiness+=2
elif item=="bowtie":
self.classiness+=4
elif item=="monocle":
self.classiness+=5
else:
self.classiness=0
Test cases
me = Classy()
Should be 0
print(me.getClassiness())

Proxy Class in Python 3

I wrote a simple Proxy class in python3, but I have a problem with "was_called" function
class Proxy:
last_invoked = ""
calls = {}
def __init__(self, obj):
self._obj = obj
def __getattr__(self, item):
attrs = dir(self._obj)
if item in attrs:
Proxy.last_invoked = item
if item in Proxy.calls.keys():
Proxy.calls[item] += 1
else:
Proxy.calls[item] = 1
if item in Proxy.calls.keys():
Proxy.calls[item] += 1
else:
Proxy.calls[item] = 1
return getattr(self._obj, item)
else:
raise Exception('No Such Method')
def last_invoked_method(self):
if Proxy.last_invoked == "":
raise Exception('No Method Is Invoked')
else:
return Proxy.last_invoked
def count_of_calls(self, method_name):
if method_name in Proxy.calls.keys():
return Proxy.calls[method_name]
return 0
def was_called(self, method_name):
if method_name in Proxy.calls.keys():
if Proxy.calls[method_name] > 0: return True
return False
class Radio():
def __init__(self):
self._channel = None
self.is_on = False
self.volume = 0
def get_channel(self):
return self._channel
def set_channel(self, value):
self._channel = value
def power(self):
self.is_on = not self.is_on
radio = Radio()
radio_proxy = Proxy(radio)
radio.number = 3
radio_proxy.number = 3
radio_proxy.power()
print(radio_proxy.was_called("number"))
print(radio_proxy.was_called("power"))
"was_called" function is work for functions and attributes that is in radio at first such as "power", but it's not work for new attributes that we add such as "number".
I expect for both print "True", because both of "power" and "number" is called. but first print return False!
What do you suggest?
def Proxy(class_type):
class ProxyClass(class_type):
def __init__(self, *args, **kwargs):
# Set your _calls and _last_invoked here, so that they are not class attributes (and are instead instance attributes).
self._calls = {}
self._last_invoked = ""
# Pass the arguments back to the class_type (in our case Radio) to initialize the class.
super().__init__(*args, **kwargs)
def __getattribute__(self, item):
# We must do this prelimary check before continuing on to the elif statement.
# This is since _calls and _last_invoked is grabbed when self._last_invoked/self._calls is called below.
if item in ("_calls", "_last_invoked"):
return super(ProxyClass, self).__getattribute__(item)
elif not item.startswith("_"):
self._last_invoked = item
self._calls[item] = 1 if item not in self._calls.keys() else self._calls[item] + 1
return super(ProxyClass, self).__getattribute__(item)
def __setattr__(self, item, val):
# Wait until _calls is initialized before trying to set anything.
# Only set items that do not start with _
if not item == "_calls" and not item.startswith("_"):
self._calls[item] = 0
super(ProxyClass, self).__setattr__(item, val)
def last_invoked_method(self):
if self._last_invoked == "":
raise Exception('No Method Is Invoked')
else:
return self._last_invoked
def count_of_calls(self, method_name):
return self._calls[method_name] if method_name in self._calls.keys() else 0
def was_called(self, method_name):
return True if method_name in self._calls.keys() and self._calls[method_name] > 0 else False
return ProxyClass
#Proxy
class Radio():
def __init__(self):
self._channel = None
self.is_on = False
self.volume = 0
def get_channel(self):
return self._channel
def set_channel(self, value):
self._channel = value
def power(self):
self.is_on = not self.is_on
radio = Proxy(Radio)()
radio.number = 3 # Notice that we are only setting the digit here.
radio.power()
print(radio._calls)
print(radio.number) # Notice that this when we are actually calling it.
print(radio._calls)
outputs:
{'is_on': 0, 'volume': 0, 'number': 0, 'power': 1}
3
{'is_on': 0, 'volume': 0, 'number': 1, 'power': 1}
A few modifications here and there, but you should be able to see the bigger idea by reading through the code. From here you should be able to modify the code to your liking. Also note that any variable that starts with _ is automatically removed from the _calls dictionary.
If you rather not use the decorator #Proxy, you may initialize your Radio class (as a proxy) like so:
# Second parentheses is where your Radio args go in.
# Since Radio does not take any args, we leave it empty.
radio_proxy = Proxy(Radio)()
Also, make sure to understand the difference between class attributes, and instance attributes.
Edit:
class Test:
def __init__(self, var):
self.var = var
self.dictionary = {}
def __getattribute__(self, item):
print("we are GETTING the following item:", item)
# If we don't do this, you end up in an infinite loop in which Python is
# trying to get the `dictionary` class to do `self.dictionary['dictionary'] = ...`
if item == "dictionary":
super(Test, self).__getattribute__(item)
else:
self.dictionary[item] = "Now we can use this!"
return super(Test, self).__getattribute__(item)
def __setattr__(self, item, key):
print("we are SETTING the following item:", item)
super(Test, self).__setattr__(item, key)
Notice:
test = Test(4)
outputs:
we are SETTING the following item: var
we are SETTING the following item: dictionary
then following it:
test.var
outputs:
we are GETTING the following item: var
we are GETTING the following item: dictionary

Class and external method call

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?

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()

Using a dictionary to control the flow of methods

I have a class Population that contains several method.
According to an input I want the run the method on an instance of the class Population in a given order.
To be a bit more accurate in what I am trying to achieve is quite the same than using is something like that:
stuff = input(" enter stuff ")
dico = {'stuff1':functionA, 'stuff2':functionC, 'stuff3':functionB, 'stuff4':functionD}
dico[stuff]()
Except that the functionA, functionB etc... are methods and not functions:
order_type = 'a'
class Population (object):
def __init__(self,a):
self.a = a
def method1 (self):
self.a = self.a*2
return self
def method2 (self):
self.a += 2
return self
def method3 (self,b):
self.a = self.a + b
return self
if order_type=='a':
order = {1:method1, 2:method2, 3:method3}
elif order_type=='b':
order = {1:method2, 2:method1, 3:method3}
else :
order = {1:method3, 2:method2, 3:method1}
my_pop = Population(3)
while iteration < 100:
iteration +=1
for i in range(len(order)):
method_to_use = order[i]
my_pop.method_to_use() # But obviously it doesn't work!
Hope I've made my question clear enough!
Note that one of my method need two arguments
Pass the instance explicitly as first argument:
method_to_use = order[i]
method_to_use(my_pop)
Full working code:
order_type = 'a'
class Population (object):
def __init__(self,a):
self.a = a
def method1 (self):
self.a = self.a*2
return self
def method2 (self):
self.a += 2
return self
def method3 (self):
self.a = 0
return self
if order_type=='a':
order = [Population.method1, Population.method2, Population.method3]
elif order_type=='b':
order = [Population.method2, Population.method1, Population.method3]
else :
order = [Population.method3, Population.method2, Population.method1]
my_pop = Population(3)
while iteration < 100:
iteration +=1
for method_to_use in order:
method_to_use(my_pop)
If you want to pass more than one argument, simply use the *args syntax:
if order_type=='a':
order = [Population.method1, Population.method2, Population.method3]
arguments = [(), (), (the_argument,)]
elif order_type=='b':
order = [Population.method2, Population.method1, Population.method3]
arguments = [(), (), (the_argument,)]
else :
order = [Population.method3, Population.method2, Population.method1]
arguments = [(the_argument, ), (), ()]
my_pop = Population(3)
while iteration < 100:
iteration +=1
for method_to_use, args in zip(order, arguments):
method_to_use(my_pop, *args)
The () is an empty tuple, hence *args will expand to no additional arguments, while (the_argument,) is a 1-element tuple that will pass the argument to the method.
Use getattr:
order = {1:'method1', 2:'method2', 3:'method3'} #values are strings
...
method_to_use = order[i]
getattr(mypop, method_to_use)()
You can use operator.methodcaller:
from operator import methodcaller
method_to_use = methodcaller('method' + str(i))
method_to_use(my_pop)

Categories

Resources