What I need help on is getting the stations to change to the next station in the list if the user presses 3.
class Radio:
def __init__(self):
self.stations=["STATIC","97.2", "99.6", "101.7", "105.3", "108.5"]
self.stationStart=self.stations[0]
def seekNext(self):
self.stationsStart
It starts at static but I want it to change every single one and then start over again. I tried something like this:
stations=["STATIC","97.2", "99.6", "101.7", "105.3", "108.5"]
a =input("enter 3 to seek next")
while a !="0":
if a =="3":
print(stations[-1])
I only end up getting the last station cannot figure out how to list the rest of the stations.
There are a couple of reasonable ways to do what you want.
The easiest would be to make your class store an index into your list, rather than an list item directly. That way you can increment the index and wrap it around using the % modulus operator:
class Radio:
def __init__(self):
self.stations=["STATIC","97.2", "99.6", "101.7", "105.3", "108.5"]
self.station_index = 0
def seek(self):
print("Currently tuned to", self.stations[self.station_index])
print("Seeking...")
self.station_index = (self.station_index + 1) % len(self.stations)
print("Now tuned to", self.stations[self.station_index])
A "fancier", and possibly more Pythonic way to solve the problem would be to use the cycle generator from the itertools module in the Python standard library. It returns an iterator that yields the values from your list, starting over when it reaches the end. Though you usually only deal with iterators in for loops, it's easy to use the iterator protocol by hand too. In our case, we just want to call next on the iterator to get the next value:
import itertools
class Radio:
def __init__(self):
self.stations = itertools.cycle(["STATIC","97.2", "99.6", "101.7", "105.3", "108.5"])
self.current_station = next(self.stations)
def seek(self):
print("Currently tuned to", self.current_station)
print("Seeking...")
self.current_station = next(self.stations)
print("Now tuned to", self.current_station)
index = 0
if a=="3":
index = (index+1)%6
print(stations[index])
Define a variable in init with the actual position "self.pos = 0", and call this function when you required
def seekNext(self):
if(self.pos == (len(self.stations)-1)):
self.pos = 0
else:
self.pos += 1
print(self.stations[self.pos])
Related
I'm trying to use classes to condense some repeating functions, I'm probably missing something key. Using the adafruit motorkit library. It has a class called MotorKit(), then Motorkit has a motor<1-4> methods(?) each with a settable attribute of throttle for each of the 4 motors a board can control, and every one of my motors is controlling gates and will work the same way.
so what i have now is this:
board1=MotorKit(address=0x60)
def openMotor1():
board1.motor1.throttle = 1 #open output gate at full speed
time.sleep(.1)
board1.motor1.throttle = 0.1 #apply minimal voltage to keep output gate open and from bouncing
def openMotor2():
board1.motor2.throttle = 1
time.sleep(.1)
board1.motor2.throttle = 0.1
...
<for 12 motors>
I have 3 boards at different addresses, 4 motors on each board. So i have 12 of the exact same function. Then i have another 12 functions to close the motors in a similar way. The motors and addresses will be enumerated in a .config file ultimately, as the number of motors in use will change.
So i'm imaging I should be able to do this with a class so i'm not repeating the exact same code over and over again? However every attempt at a class doesn't work. Here's the rough idea of what I'm trying to do, i know this isn't proper syntaxed code, i'm just trying to depict my thought process, since none of my code has worked. The <>'s represent a variable i want inserted:
class MotorClass:
def __ init __ (self, MotorNumber, addy):
board<address> = MotorKit(address=addy)
# example: board0x60=Motorkit(address=0x60)
def open(self):
board<address>.motor<MotorNumber>.throttle = 1
#example: board0x60.motor1.throttle = 1
time.sleep(.1)
board<address>.motor<MotorNumber>.throttle = 0.1
which I would then call like this
#Motor<X>=MotorClass(<MotorNumber>,<BoardAddress>)
Motor5=MotorClass(1,0x61) #so Motor5 might be the motor #1 on board #2 # bus address 0x61
Motor5.open #would then the openMotor1() function i defined above except applying to board2.
How can i do this? or something with a similar intent?
You could always just pass the appropriate motor as an argument to a single function:
def openMotor(m):
m.throttle = 1
time.sleep(.1)
m.throttle = 0.1
openMotor(board1.motor1)
# etc
One brute force way:
class MotorClass(MotorKit):
def __init__(self, address):
MotorKit.__init__(self,address)
self.motors = [self.motor1,self.motor2,self.motor3,self.motor4]
def throttle(self, idx, value):
self.motors[idx].throttle = value
You might use set_throttle to avoid confusion.
I think using a dictionary to keep all the motor instances would help:
class MotorClass:
def __init__(self, board_address_list, number_of_motor_per_board):
self.all_motor = {} # {(board_id, motor_id): motor instance}
for i, a in enumerate(board_address_list):
board = MotorKit(address=a)
for x in range(1, 1+number_of_motor_per_board):
self.all_motor[(i, x)] = getattr(board , 'motor' + str(x)) # equivalent to board.motorx
To open:
def open_motor(self, motor):
motor.throttle = 1
time.sleep(.1)
motor.throttle = 0.1
def open_all(self):
for m in self.all_motor.values():
self.open_motor(m)
def open_one(self, board_id, motor_id):
m = self.all_motor[(board_id, motor_id)]:
self.open_motor(m)
In fact if you just want to start all motors given all the board addresses:
for a in addresses:
board = MotorKit(address=a)
for x in range(1, 1+number_of_motor_per_board):
motor_start_function(getattr(board , 'motor' + str(x)))
I was working on building a randomized character generator for Pathfinder 3.5 and got stuck.
I am using the Populate_Skills(Skill_String, Draw, Skill_List, Class_Skill): function to populate a randiomized list of skills with their class based points total, class bonus, and point buy. So modelling the action of a player picking skills for their character.
As an example below, Wizards.
I pick Knowledge_Arcana as a skill and spend one of my skill point pool (Calculated by taking my intelligence modifier +2) on it. So that skill now equals my intelligence modifier(+1 in this case), class skill bonus as a wizard (+3), plus the point I spent(+1) for a total of 5.
The problem is while the function prints the correct result of 5, the outstanding variables do not populate with the final total. To continue our example I'd run the function on Knowledge_Arcana, get a +5, and then check the Knowledge_Arcana after the function call and get just +1. Conversely, if I write out the function as just an if statement it works. Example is next to the function for comparison.
Does anyone know why Im getting the different result?
## Creating the lists and breaking into two separate sections
Int_Mod = 1
Skill_Ranks = 3
Rand_Class = 'Wizard'
Knowledge_Arcana = Int_Mod
Knowledge_Dungeoneering = Int_Mod
Wizard_Class_Top_Skills = ["Knowledge_Arcana"]
Wizard_Class_Less_Skills = ["Knowledge_Dungeoneering"]
Class_Skill = 3
Important_Skills_Weighted = .6
Less_Important_Skills_Weighted = .4
Important_Skills_Total_Weighted = round(Skill_Ranks*Important_Skills_Weighted)
Less_Skill_Total_Weighted = round(Skill_Ranks*Less_Important_Skills_Weighted)
Wiz_Draw =['Knowledge_Arcana', 'Knowledge_Dungeoneering']
def Populate_Skills(Skill_String, Draw, Skill_List, Class_Skill):
if Skill_String in Draw:
Skill_List = Skill_List + Class_Skill + Draw.count(Skill_String)
print(Skill_String, Skill_List)
else:
print('Nuts!')
## Function Calls
Populate_Skills('Knowledge_Arcana', Wiz_Draw, Knowledge_Arcana, Class_Skill)
Populate_Skills('Knowledge_Dungeoneering', Wiz_Draw, Knowledge_Dungeoneering, Class_Skill)
print(Knowledge_Arcana,Knowledge_Dungeoneering)
Edited to be a MRE, I believe. Sorry folks, Im new.
You are passing in a reference to a list and expect the function to modify it; but you are reassigning the variable inside the function which creates a local variable, which is then lost when the function is exited. You want to manipulate the same variable which the caller passed in, instead.
def Populate_Skills(Skill_String, Draw, Skill_List, Class_Skill):
if Skill_String in Draw:
Skill_List.extend(Class_Skill + Draw.count(Skill_String))
print(Skill_String, Skill_List)
else:
print('Nuts!')
Alternatively, have the function return the new value, and mandate for the caller to pick it up and assign it to the variable.
def Populate_Skills(Skill_String, Draw, Skill_List, Class_Skill):
if Skill_String in Draw:
Skill_List = Skill_List + Class_Skill + Draw.count(Skill_String)
print(Skill_String, Skill_List)
else:
print('Nuts!')
return Skill_List
Skill_List = Populate_Skills('Knowledge_Arcana', Wiz_Draw, Knowledge_Arcana, Class_Skill)
# etc
You should probably also rename your variables (capital letters should be used for classes and globals; regular Python functions and variables should use snake_case) and avoid using global variables at all. The entire program looks like you should probably look into refactoring it into objects, but that's far beyond the scope of what you are asking.
I am trying to use a while loop to create object to populate a list of a user defined type until a certain condition is met. I want to assign a value to each object based on the number of iterations the loop has completed. For example:
class WalkingPeeps:
def___init___(self):
self.location = 0
def leftAt(self,time):
self.tleft = time
def changePos(self):
self.location += random.choice([1, -1])
objectList =[]
location_reached = False
time = 0
while not location_reached
objectList.append(WalkingPeeps())
for x in objectList:
x.tleft = time
if x.location == 20:
location_reached = True
time+=1
print("Person left at: ",x.tleft)
print("Person arrived at: ", time)
However, when it runs, it just set the time the object was created to one less than when the person reached 20. Any pointers? Hints? Thanks in advance.
In python, loops do not define their own scope. When you write
for x in objectList: ...
There variable x is created. At each step in the loop, the variable is updated. When the loop ends, the variable is not destroyed. Therefore, when you print x.tleft, you're printing the time on the last x, which by definition is 20, since you break the loop only when x.tleft == 20.
Furthermore, since you loop over every single element at each phase and update its time, you're setting each elements time to the most reccent time. Therefore, all elements have time == 20, when you terminate. What you mean, I believe, is to only update the last element
What I think you want to print, to check that your loop is working is,
for obj in objectList:
print( obj.tleft )
You would then see the expected behaviour
You also have many errors, including some syntax errors and some that make the code enter an infinite loop. This is the version I worked with, in good faith (try and make sure that the the only bugs in your code are the one's you're asking about!)
class WalkingPeeps: pass # None of the methods were relevant
objectList =[]
location_reached = False
time =0
while not location_reached:
objectList.append(WalkingPeeps())
x = objectList[-1]
x.tleft = time
# you need to check tleft, not location; location is never set
if x.tleft == 20:
location_reached = True
time+=1
print("Person left at: ",x.tleft)
print("Person arrived at: ", time)
for person in objectList: print(person.tleft)
A far more readable and concise version of this code would be:
class WalkingPerson:
def __init__(self,time=0):
self.time=time
objectList = [WalkingPerson(t) for t in range(20)]
Question: write a program which first defines functions minFromList(list) and maxFromList(list). Program should initialize an empty list and then prompt user for an integer and keep prompting for integers, adding each integer to the list, until the user enters a single period character. Program should than call minFromList and maxFromList with the list of integers as an argument and print the results returned by the function calls.
I can't figure out how to get the min and max returned from each function separately. And now I've added extra code so I'm totally lost. Anything helps! Thanks!
What I have so far:
def minFromList(list)
texts = []
while (text != -1):
texts.append(text)
high = max(texts)
return texts
def maxFromList(list)
texts []
while (text != -1):
texts.append(text)
low = min(texts)
return texts
text = raw_input("Enter an integer (period to end): ")
list = []
while text != '.':
textInt = int(text)
list.append(textInt)
text = raw_input("Enter an integer (period to end): ")
print "The lowest number entered was: " , minFromList(list)
print "The highest number entered was: " , maxFromList(list)
I think the part of the assignment that might have confused you was about initializing an empty list and where to do it. Your main body that collects data is good and does what it should. But you ended up doing too much with your max and min functions. Again a misleading part was that assignment is that it suggested you write a custom routine for these functions even though max() and min() exist in python and return exactly what you need.
Its another story if you are required to write your own max and min, and are not permitted to use the built in functions. At that point you would need to loop over each value in the list and track the biggest or smallest. Then return the final value.
Without directly giving you too much of the specific answer, here are some individual examples of the parts you may need...
# looping over the items in a list
value = 1
for item in aList:
if item == value:
print "value is 1!"
# basic function with arguments and a return value
def aFunc(start):
end = start + 1
return end
print aFunc(1)
# result: 2
# some useful comparison operators
print 1 > 2 # False
print 2 > 1 # True
That should hopefully be enough general information for you to piece together your custom min and max functions. While there are some more advanced and efficient ways to do min and max, I think to start out, a simple for loop over the list would be easiest.
I have a python function (call it myFunction) that gets as input a list of numbers, and, following a complex calculation, returns back the result of the calculation (which is a number).
The function looks like this:
def myFunction( listNumbers ):
# initialize the result of the calculation
calcResult = 0
# looping through all indices, from 0 to the last one
for i in xrange(0, len(listNumbers), 1):
# some complex calculation goes here, changing the value of 'calcResult'
# let us now return the result of the calculation
return calcResult
I tested the function, and it works as expected.
Normally, myFunction is provided a listNumbers argument that contains 5,000,000 elements in it. As you may expect, the calculation takes time. I need this function to run as fast as possible
Here comes the challenge: assume that the time now is 5am, and that listNumbers contains just 4,999,999 values in it. Meaning, its LAST VALUE is not yet available. This value will only be available at 6am.
Obviously, we can do the following (1st mode): wait until 6am. Then, append the last value into listNumbers, and then, run myFunction. This solution works, BUT it will take a while before myFunction returns our calculated result (as we need to process the entire list of numbers, from the first element on). Remember, our goal is to get the results as soon as possible past 6am.
I was thinking about a more efficient way to solve this (2nd mode): since (at 5am) we have listNumbers with 4,999,999 values in it, let us immediately start running myFunction. Let us process whatever we can (remember, we don't have the last piece of data yet), and then -- exactly at 6am -- 'plug in' the new data piece -- and generate the computed result. This should be significantly faster, as most of the processing will be done BEFORE 6am, hence, we will only have to deal with the new data -- which means the computed result should be available immediately after 6am.
Let's suppose that there's no way for us to inspect the code of myFunction or modify it. Is there ANY programming technique / design idea that will allow us to take myFunction AS IS, and do something with it (without changing its code) so that we can have it operate in the 2nd mode, rather than the 1st one?
Please do not suggest using c++ / numpy + cython / parallel computing etc to solve this problem. The goal here is to see if there's any programming technique or design pattern that can be easily used to solve such problems.
You could use a generator as an input. The generator will only return when there is data available to process.
Update: thanks for the brilliant comment, I wanted to remove this entry :)
class lazylist(object):
def __init__(self):
self.cnt = 0
self.length = 5000000
def __iter__(self):
return self
def __len__(self):
return self.length
def next(self):
if self.cnt < self.length:
self.cnt += 1
#return data here or wait for it
return self.cnt #just return a counter for this example
else:
raise StopIteration()
def __getitem__(self, i):
#again, block till you have data.
return i+1 #simple counter
myFunction(lazylist())
Update: As you can see from the comments and other solutions your loop construct and len call causes a lot of headaches, if you can eliminate it you can use a lot more elegant solution. for e in li or enumerate is the pythonic way to go.
By "list of numbers", do you mean an actual built-in list type?
If not, it's simple. Python uses duck-typing, so passing any sequence that supports iteration will do. Use the yield keyword to pass a generator.
def delayed_list():
for val in numpy_array[:4999999]:
yield val
wait_until_6am()
yield numpy_array[4999999]
and then,
myFunction(delayed_list())
If yes, then it's trickier :)
Also, check out PEP8 for recommended Python code style:
no spaces around brackets
my_function instead of myFunction
for i, val in enumerate(numbers): instead of for i in xrange(0, len(listNumbers), 1): etc.
subclass list so that when the function tries to read the last value it blocks until another thread provides the value.
import threading
import time
class lastblocks(list):
def __init__(self,*args,**kwargs):
list.__init__(self,*args,**kwargs)
self.e = threading.Event()
def __getitem__(self, index):
v1 = list.__getitem__(self,index)
if index == len(self)-1:
self.e.wait()
v2 = list.__getitem__(self,index)
return v2
else:
return v1
l = lastblocks(range(5000000-1)+[None])
def reader(l):
s = 0
for i in xrange(len(l)):
s += l[i]
print s
def writer(l):
time.sleep(10)
l[5000000-1]=5000000-1
l.e.set()
print "written"
reader = threading.Thread(target=reader, args=(l,))
writer = threading.Thread(target=writer, args=(l,))
reader.start()
writer.start()
prints:
written
12499997500000
for numpy:
import threading
import time
import numpy as np
class lastblocks(np.ndarray):
def __new__(cls, arry):
obj = np.asarray(arry).view(cls)
obj.e = threading.Event()
return obj
def __array_finalize__(self, obj):
if obj is None: return
self.e = getattr(obj, 'e', None)
def __getitem__(self, index):
v1 = np.ndarray.__getitem__(self,index)
if index == len(self)-1:
self.e.wait()
v2 = np.ndarray.__getitem__(self,index)
return v2
else:
return v1
l = lastblocks(np.asarray(range(5000000-1)+[None]))
def reader(l):
s = 0
for i in xrange(len(l)):
s += l[i]
print s
def writer(l):
time.sleep(10)
l[5000000-1]=5000000-1
l.e.set()
print "written"
reader = threading.Thread(target=reader, args=(l,))
writer = threading.Thread(target=writer, args=(l,))
reader.start()
writer.start()
Memory protection barriers are a general way to solve this type of problem when the techniques suggested in the other answers (generators and mock objects) are unavailable.
A memory barrier is a hardware feature that causes an interrupt when a program tries to access a forbidden area of memory (usually controllable at the page level). The interrupt handler can then take appropriate action, for example suspending the program until the data is ready.
So in this case you'd set up a barrier on the last page of the list, and the interrupt handler would wait until 06:00 before allowing the program to continue.
You could just create your own iterator to iterate over the 5,000,000 elements. This would do whatever you need to do to wait around for the final element (can't be specific since the example in the question is rather abstract). I'm assuming you don't care about the code hanging until 6:00, or know how to do it in a background thread.
More information about writing your own iterator is at http://docs.python.org/library/stdtypes.html#iterator-types
There is a simpler generator solution:
def fnc(lst):
result = 0
index = 0
while index < len(lst):
while index < len(lst):
... do some manipulations here ...
index += 1
yield result
lst = [1, 2, 3]
gen = fnc(lst)
print gen.next()
lst.append(4)
print gen.next()
I'm a little bit confused about not being able to investigate myFunction. At least you have to know if your list is being iterated or accessed by index. Your example might suggest an index is used. If you want to take advantage of iterators/generators, you have to iterate. I know you said myFunction is unchangeable, but just want to point out, that most pythonic version would be:
def myFunction( listNumbers ):
calcResult = 0
# enumerate if you really need an index of element in array
for n,v in enumerate(listNumbers):
# some complex calculation goes here, changing the value of 'calcResult'
return calcResult
And now you can start introducing nice ideas. One is probably wrapping list with your own type and provide __iter__ method (as a generator); you could return value if accessible, wait for more data if you expect any or return after yielding last element.
If you have to access list by index, you can use __getitem__ as in Dan D's example. It'll have a limitation though, and you'll have to know the size of array in advance.
Couldn't you simply do something like this:
processedBefore6 = myFunction([1,2,3]) # the first 4,999,999 vals.
while lastVal.notavailable:
sleep(1)
processedAfter6 = myFunction([processedBefore6, lastVal])
If the effects are linear (step 1 -> step 2 -> step 3, etc) this should allow you to do as much work as possible up front, then catch the final value when it's available and finish up.