How To Set A Range That Has An Unknown Starting Index - python

I am wondering how I can define a function that allows the range to be set to whatever the starting index is for a certain list. For example:
def pTrend(stock):
pTrend = []
for x in range(0, len(stock)):
if x > 0:
print('This')
if x < 0:
print('That')
I have lists of stock data, and the first one is from range(0, 250) and the next is from (250, 500) and etc.. how could i create a function that sets the start at the range = to the particular index of each stock i will be plugging in?

I don't consider it good form to have functions maintain state like this. If possible, you should try and have the caller code maintain the state for you. For example, have the caller code maintain a cumsum variable that you pass to pTrend as the offset.
def pTrend(stock, offset):
pTrend = []
for i in range(len(stock)):
i += offset
...
This is in effect, what enumerate (as mentioned in this comment) does:
def pTrend(stock, offset):
for i, s in enumerate(stock, offset):
...
Now, in your caller code, you have:
cumsum = 0
for stock in stocks:
... = pTrend(stock, cumsum)
cumsum += len(stock)
Alternatively, define a class and have it keep track of the cumsum variable for you.
class Foo:
def __init__(self):
self.cumsum = 0
def pTrend(self, stock):
pTrend = []
for i, s in enumerate(stock, self.cumsum):
...
self.cumsum += len(stock)
Initialise an object:
f = Foo()
And call pTrend as f.pTrend(stock) as you would usually.

Related

Iteration for the last value of iteration in Python

How can I define a function in python in such a way that it takes the previous value of my iteration where I define the initial value.
My function is defined as following:
def Deulab(c, yh1, a, b):
Deulab = c- (EULab(c, yh1, a, b)-1)*0.3
return (Deulab,yh1, a,b)
Output is
Deulab(1.01, 1, 4, 2)
0.9964391705626454
Now I want to iterate keeping yh1, a ,b fixed and start with c0=1 and iterate recursively for c.
The most pythonic way of doing this is to define an interating generator:
def iterates(f,x):
while True:
yield x
x = f(x)
#test:
def f(x):
return 3.2*x*(1-x)
orbit = iterates(f,0.1)
for _ in range(10):
print(next(orbit))
Output:
0.1
0.2880000000000001
0.6561792000000002
0.7219457839595519
0.6423682207442558
0.7351401271107676
0.6230691859914625
0.7515327214700762
0.5975401280955426
0.7695549549155365
You can use the generator until some stop criterion is met. For example, in fixed-point iteration you might iterate until two successive iterates are within some tolerance of each other. The generator itself will go on forever, so when you use it you need to make sure that your code doesn't go into an infinite loop (e.g. don't simply assume convergence).
It sound like you are after recursion.
Here is a basic example
def f(x):
x += 1
if x < 10:
x = f(x)
return x
print (f(4))
In this example a function calls itself until a criteria is met.
CodeCupboard has supplied an example which should fit your needs.
This is a bit of a more persistent version of that, which would allow you to go back to where you were with multiple separate function calls
class classA:
#Declare initial values for class variables here
fooResult = 0 #Say, taking 0 as an initial value, not unreasonable!
def myFoo1(x):
y = 2*x + fooResult #A simple example function
classA.fooResult = y #This line is updating that class variable, so next time you come in, you'll be using it as part of calc'ing y
return y #and this will return the calculation back up to wherever you called it from
#Example call
rtn = classA.myFoo1(5)
#rtn1 will be 10, as this is the first call to the function, so the class variable had initial state of 0
#Example call2
rtn2 = classA.myFoo1(3)
#rtn2 will be 16, as the class variable had a state of 10 when you called classA.myFoo1()
So if you were working with a dataset where you didn't know what the second call would be (i.e. the 3 in call2 above was unknown), then you can revisit the function without having to worry about handling the data retention in your top level code. Useful for a niche case.
Of course, you could use it as per:
list1 = [1,2,3,4,5]
for i in list1:
rtn = classA.myFoo1(i)
Which would give you a final rtn value of 30 when you exit the for loop.

Python create an iterator/generator with feedback

Is it possible to create a iterator/generator which will decide on the next value based on some result on the previous iteration?
i.e.
y = None
for x in some_iterator(ll, y):
y = some_calculation_on(x)
I would like the logic of choosing the next x to depend on the calculation result allowing different logic for different results, much like in a search problem.
I also want to keep the how to choose the next x and the calculation on x as separate as possible.
Did you that you can send to a generator using generator.send? So yes, you can have a generator to change its behaviour based on feedback from the outside world. From the doc:
generator.send(value)
Resumes the execution and “sends” a value into the generator function.
The value argument becomes the result of the current yield expression.
The send() method returns the next value yielded by the generator
[...]
Example
Here is a counter that will increment only if told to do so.
def conditionalCounter(start=0):
while True:
should_increment = yield start
if should_increment:
start += 1
Usage
Since iteration with a for-loop does not allow to use generator.send, you have to use a while-loop.
import random
def some_calculation_on(value):
return random.choice([True, False])
g = conditionalCounter()
last_value = next(g)
while last_value < 5:
last_value = g.send(some_calculation_on(last_value))
print(last_value)
Output
0
0
1
2
3
3
4
4
5
Make it work in a for-loop
You can make the above work in a for-loop by crafting a YieldReceive class.
class YieldReceive:
stop_iteration = object()
def __init__(self, gen):
self.gen = gen
self.next = next(gen, self.stop_iteration)
def __iter__(self):
return self
def __next__(self):
if self.next is self.stop_iteration:
raise StopIteration
else:
return self.next
def send(self, value):
try:
self.next = self.gen.send(value)
except StopIteration:
self.next = self.stop_iteration
Usage
it = YieldReceive(...)
for x in it:
# Do stuff
it.send(some_result)
It's possible but confusing. If you want to keep the sequence of x values and the calculations on x separate, you should do this explicitly by not involving x with an iterator.
def next_value(x):
"""Custom iterator"""
# Bunch of code defining a new x
yield new_x
x = None
while True:
x = next_value(x)
x = some_calculation_on(x)
# Break when you're done
if finished and done:
break
If you want the loop to execute exactly i times, then use a for loop:
for step in range(i):
x = next_value(x)
x = some_calculation_on(x)
# No break
def conditional_iterator(y):
# stuff to create new values
yield x if (expression involving y) else another_x
for x in conditional_iterator(y):
y = some_computation(x)

Printing None instead of nothing when interacting linked list

I have a linked list where I iterate within a range and return all of the square numbers that can be represented as integers within this range. Instead of just returning just the numbers that this can be done to it will return None in between for example 9, None, None...,16, None, None..., 25 I wanting it to just return 9, 16, 25 etc etc
class Squares:
def __init__(self, start, end):
self.__start = start - 1
self.__end = end -1
def __iter__(self):
return SquareIterator(self.__start, self.__end)
class SquareIterator:
def __init__(self, start, end):
self.__current = start
self.__step = 1
self.__end = end
def __next__(self):
if self.__current > self.__end:
raise StopIteration
else:
self.__current += self.__step
x = self.__current - self.__step + 1
self.__current - self.__step + 1
if str(x).isdigit() and math.sqrt(x) % 1 == 0:
return x
You need to make your __next__ function continue to loop until it gets to the target value:
def __next__(self):
# We're just going to keep looping. Loop breaking logic is below.
while True:
# out of bounds
if self.__current > self.__end:
raise StopIteration
# We need to get the current value
x = self.__current
# increase the state *after* grabbing it for test
self.__current += self.__step
# Test the value stored above
if math.sqrt(x) % 1 == 0:
return x
The reason you should be storing x, then incrementing is that you have to increment no matter what, even if you don't have a perfect square.
It is unclear why you are complicating things; there is a simple way:
import math
class Squares:
def __init__(self, start, end):
self.__start = start
self.__end = end
self.__step = 1
def __iter__(self):
for x in range(self.__start, self.__end, self.__step):
if math.sqrt(x) % 1 == 0:
yield x
s = Squares(0, 100)
for sq in s:
print(sq, end=' ')
output:
0 1 4 9 16 25 36 49 64 81
from the comments:
Mind you, it would likely be much easier to avoid the dedicated
iterator class, and just implement __iter__ for Squares as a generator
function. Explicit __next__ involves all sorts of inefficient state
management that Python does poorly, and isn't all that easy to follow;
__iter__ as a generator function is usually very straightforward; every time you hit a yield it's like the return from __next__, but all
your state is function local, no special objects involved (generators
take care of saving and restoring said local state). – ShadowRanger>
it probably doesn't even need a Squares class. A generator function
named squares would do what's needed; pass it start, stop and step and
use them as local variables, rather than attributes of some
unnecessary self. Only real advantage to the class is that it could be
iterated repeatedly without reconstructing it, a likely uncommon use
case
def squares_from(start, stop, step=1):
"""returns a generator function for the perfect squares
in the range comprised between start and stop, iterated over using step=step
"""
for x in range(start, stop, step):
if math.sqrt(x) % 1 == 0:
yield x
for sq in squares_from(0, 100):
print(sq, end=' ')

how to make output an input in python

>>> import math
#defining first function
>>> def f(a):
return a-math.sin(a)-math.pi/2
#defining second fuction
>>> def df(a):
return 1-math.cos(a)
#defining third function which uses above functions
>>> def alpha(a):
return a-f(a)/df(a)
How to write a code in which alpha(a) takes a starting value of a=2, and the solution of alpha(2) will become the input the next time. For eg: let's suppose alpha(2) comes to 2.39 , hence the next value would be alpha(2.39) and go on {upto 50 iterations}. Can somebody please help me a bit. thanks in advance.
You can let the program iterate with a for loop, and use a variable to store the intermediate results:
temp = 2 # set temp to the initial value
for _ in range(50): # a for loop that will iterate 50 times
temp = alpha(temp) # call alpha with the result in temp
# and store the result back in temp
print(temp) # print the result (optional)
print(temp) will print the intermediate results. It is not required. It only demonstrates how the temp variable is updated throughout the process.
You can objectify it.
import math
class inout:
def __init__(self, start):
self.value = start
def f(self, a):
return a-math.sin(a)-math.pi/2
def df(self, a):
return 1-math.cos(a)
def alpha(self):
self.value = self.value-self.f(self.value)/self.df(self.value)
return self.value
Then create an inout object and each time you call its alpha method it will give the next value in the series.
demo = inout(2)
print(demo.alpha())

How can I create an indefinite iterations of objects in python?

I'm new to python and am trying to create a program to test some methods of object creation. Currently, I'm writing a program that involves creating objects, giving them a unique numeric variable, and assigning them to a list for future referencing. Here's what I wrote to create the variable names:
def getRectangleName():
rectName = list("Rectangle")
SPAWNEDOBJECTLIST.append(len(SPAWNEDOBJECTLIST))
rectName.append(str(len(SPAWNEDOBJECTLIST)))
return rectName
and then that's passed onto something to turn that string into a variable name. I tried eval(), learned this was Bad for some reason and it didn't work anyway, and tried some workarounds to no avail.
I figure there's plenty of games that have an indefinite number of characters on the screen. Is there an established way of making iterations of objects like this?
The objects themselves have an X and Y so that they act as reference points for the display of rectangles on screen(the idea in the future is to have each one move around on their own, so simply making lists of X and Y to draw rectangles isn't useful).
Edit: The problem is that I don't know how to give each object its own variable to put it on a list for future referencing.
Edit2: I don't think I'm asking the right question, actually, or using the right terminology. I need to be able to have an indefinite number of objects created on the fly after the program is already running, and be able to reference them individually.
The problem is that I don't know how to give each object its own variable to put it on a list for future referencing.
Whenever you think you need variables you didn't type into your program, you're doing something wrong. You don't need to assign something to a variable to put it on a list:
x = [1, 2, 3] # Note how I don't assign 1, 2, or 3 to variables.
x.append(4) # 4 doesn't get a variable either.
x.append(make_a_rectangle()) # We create a rectangle and stick it on the list.
do_stuff_with(x[4]) # We pass the rectangle to a function.
x = [] # New list.
for i in xrange(n):
x.append(make_a_rectangle()) # This happens n times.
# At this point, we have n rectangles, none of them associated with their own
# variable, none of them with a name.
If you think you need names for things (and quite often, you don't really need the names), you can use a dict:
x = {}
x['foo'] = make_a_rectangle()
do_stuff_with(x['foo'])
It's not a great idea to combine the function of managing the rectangles -- accessing, adding, or deleting them -- with the idea of being rectangles. You never know when you might need to maintain multiple lists, or change from unordered lists to organized ones.
Until you really need more, keep the management functions simple: use built-in lists or dictionaries. Use lists if you just care about ordering, or only need to know you have a bunch of stuff:
class Rectangle (object):
def __init__(self, top, bottom, left, right):
self.Top = top
self.Left = left
self.Right = right
self.Bottom = bottom
list_of_rects = [Rectangle(10,0,0,10), Rectangle(20, 10, 10 ,20)]
# how many rects?
len(list_of_rects)
# result: 2
# where is this particular rect?
fred = Rectangle(30,20,20, 30)
list_of_rects.insert(fred, 1)
list_of_rects.index(fred)
# result: 1
#remove an item from the list:
list_of_rects.remove(fred)
#search the list:
right_of_5 = [rect for rect in list_of_rects if rect.Left > 5]
If you need to get access to the individual rects for some reason -- 'what's the rectangle of the goal' or something -- you have two choices:
1) the code that needs the rect just keeps a reference to it:
class Goal(object):
def __init__(self, rect):
self.Rect = rect
goalrect = Rectangle (0,0,20,20)
mygoal = Goal(goalrect)
list_of_rects.append(goalrect)
# now goalrect always knows about it's own rect, but the list can keep track of it too...
2) Or, use a dictionary:
named_rects = {}
named_rects['goal'] = Rectangle(0,0,20,20)
You get all the same abilities with a dictionary that you do with a list -- add, delete, and find -- except dictionaries don't preserve order, so you can't manage things like priority:
# add to the dict:
named_rects['new_rect'] = Rectangle(90,90,95,95)
# remove
del named_rects['new_rect']
# find = is there a known key?
if 'new_rect' in named_rects: print new_rect
# search:
right_of_5 = [rect for rect in named_rects.items() if rect.Left > 5]
There are cases where you need fancier things than plain old lists and dicts -- but always try it with the free stuff first :)
If you dynamically want to create variables and add them to class instances, use this
class MainClass:
def __setattr__(self, name, value):
self.__dict__[name] = value
def getRectangleNameGenerator(N = 10):
X = 0
while X <= N:
X += 1
yield "Rectangle" + str(X)
RectangleName = getRectangleNameGenerator()
ClassInstances = {next(RectangleName) : MainClass}
ClassInstances[next(RectangleName)] = MainClass
ClassInstances["Rectangle1"].Temp = 10
print ClassInstances["Rectangle1"].Temp
If the class is going to have only X and Y,
class MainClass:
X, Y = 0, 0
def getRectangleNameGenerator(N = 10):
X = 0
while X <= N:
X += 1
yield "Rectangle" + str(X)
RectangleName = getRectangleNameGenerator()
ClassInstances = {next(RectangleName) : MainClass}
ClassInstances[next(RectangleName)] = MainClass
ClassInstances["Rectangle1"].X = 11
print ClassInstances["Rectangle1"].X
If you really want to refer to your rectangle instances by name, I would suggest to keep a dictionary at class level. Something like this:
#! /usr/bin/python3
from threading import Lock
import random
class Rectangle:
instances = {}
lock = Lock ()
#classmethod
def forName (cls, name):
return cls.instances [name] if name in cls.instances else None
#classmethod
def push (cls, inst):
with cls.lock:
name = None
while not name or name in cls.instances:
name = ''.join (random.choice ('abcdefghij') for i in range (16) )
cls.instances [name] = inst
return name
def __init__ (self):
self.name = Rectangle.push (self)
names = [Rectangle ().name for i in range (5) ]
for name in names:
print (name, Rectangle.forName (name) )

Categories