Error when calling function from another function [duplicate] - python

This question already has answers here:
How can I call a function within a class?
(2 answers)
Calling one method from another within same class in Python
(1 answer)
Closed 3 years ago.
I am having some trouble calling one function from inside another
Here is the code I have:
supported_timeframes = ['1m', '5m', '1h', '1d']
supported_indicators = ['SMA', ... ]
supported_sources = ['open', 'close']
indicator_values = {}
class Indicator:
def __init__(self):
self.indictor = '' # indicator
self.timeframe = '' # timeframe
self.period = 0 # look-back period
self.source = '' # open / close
def error(self, indicator, timeframe, period, source):
if timeframe not in supported_timeframes:
return 'timeframe not supported --', 'supported
timeframes:', supported_indicators
if indicator not in supported_indicators:
return 'indicator not found --', 'supported indicators:',
supported_indicators
if source not in supported_sources:
return 'source is not -- open -- or -- close'
else:
pass
def SMA(self, indicator, timeframe, period, source):
error()
# TODO get candle data from timeframe
# TODO calc requested indicator from candle data and append to
# indicator_values dict
# return indicator
for indicator in indicator_values:
return indicator
I have the function error first to check if wrong values have been entered into the parameters.
Then I want to call that function in def SMA(...) function because I am going to have many more functions that each calculate an indicator similar to the SMA one, so to keep things concise I am trying to call error() in each of them instead of copy and pasting the code within every time.
However when doing this, I get an error message within def SMA(...) that says error() is undefined.
Thank you so much in advance if you can help me out!

Unless I'm missing something, you just need to add self where you are calling error()
def SMA(self, indicator, timeframe, period, source):
self.error()

Related

How do I access the parameters of the function one by one?

So, I'm still learning how to code and I'm making this higher or lower game, and I made a function that pulls out info from a huge list with dictionaries inside it called "data":
Here is my code so far:
def choice_of_oponents(opponent1, opponent2):
"""
Gets the info on 2 people randomly and assigns them to the variables 'opponent1' and 'opponent2'
"""
opponent1 = random.choice(data)
opponent2 = random.choice(data)
def winner(opponent1, opponent2):
#This function is supposed to pull out the info stored in the parameters in the first function and determine the winner based on the data
I'm not sure how to write the second function or if it is even possible to pull out info from the parameters of the 1st function without making extra variables. Can someone help solve this?
Maybe what you're missing is the concept of return-ing the output of a function. Also, you don't need any inputs to your first function (note that you didn't use them anyway).
Try something like this:
def choice_of_opponents():
"""
Gets the info on 2 people randomly and assigns them to the variables
'opponent1' and 'opponent2'
"""
opponent1_result = random.choice(data)
opponent2_result = random.choice(data)
return opponent1_result, opponent2_result
def winner(opponent1, opponent2):
if opponent1 > opponent2:
return 1
elif opponent2 > opponent1:
return 2
else:
return 0 # A tie
op1, op2 = choice_of_opponents()
print(winner(op1, op2))

Updating local variable within function not working correctly [duplicate]

This question already has answers here:
Static variable in Python?
(6 answers)
Closed 1 year ago.
I'm trying to write a function that updates its local variable each time it is run but it is not working for some reason.
def max_equity(max_equity=0):
if current_equity() > max_equity:
max_equity = current_equity()
print(max_equity)
return max_equity
else:
print(max_equity)
return max_equity
and the function which it is calling
def current_equity():
for n in range(len(trade_ID_tracker)-1):
equity_container = 0
if (trade_ID_tracker[n,2]) == 0:
break
else:
if (trade_ID_tracker[n, 1].astype(int) == long):
equity_container += (df.loc[tbar_count,'Ask_Price'] - trade_ID_tracker[n, 2]) * trade_lots * pip_value * 1000
elif (trade_ID_tracker[n, 1].astype(int) == short):
equity_container += 0 - (df.loc[tbar_count,'Ask_Price'] - trade_ID_tracker[n, 2]) * trade_lots * pip_value * 10000
return (current_balance + equity_container)
but for some reason the max_equity() function prints current_equity() which I can only imagine means that either:
if current_equity() > max_equity:
is not doing it's job and is triggering falsely
or
max_equity = current_equity()
is not doing its job and max_equity starts at zero every time it is run.
In other words if I put max_equity() in a loop where current_equity() is
[1,2,3,4,5,4,3,2,1]
then max_equity() should return
[1,2,3,4,5,5,5,5,5]
But instead it returns
[1,2,3,4,5,4,3,2,1]
Here's a quick example test
ar = [1,2,3,4,5,4,3,2,1]
def stuff(max_equity=0):
if ar[n] > max_equity:
max_equity = ar[n]
print(max_equity)
else:
print(max_equity)
for n in range(len(ar)):
stuff()
Either way I'm kind of stumped.
Any advice?
local function variables are reset at each function call. This is essential for the behavior of functions as idempotent, and is a major factor in the success of the procedural programming approach: a function can be called form multiple contexts, and even in parallel, in concurrent threads, and it will yield the same result.
A big exception, and most often regarded as one of the bigger beginner traps of Python is that, as parameters are reset to the default values specified in the function definition for each call, if these values are mutable objects, each new call will see the same object, as it has been modified by previous calls.
This means it could be done on purpose by, instead of setting your default value as 0 you would set it as a list which first element was a 0. At each run, you could update that value, and this change would be visible in subsequent calls.
This approach would work, but it is not "nice" to depend on a side-effect of the language in this way. The official (and nice) way to keep state across multiple calls in Python is to use objects rather than functions.
Objects can have attributes tied to them, which are both visible and writable by its methods - which otherwise have their own local variables which are re-started at each call:
class MaxEquity:
def __init__(self):
self.value = 0
def update(max_equity=0):
current = current_equity()
if current > self.value:
self.value = current
return self.value
# the remainder of the code should simply create a single instance
# of that like ]
max_equity = MaxEquity()
# and eeach time yoiu want the max value, you should call its "update"
# method

Class method changing variable

I am kind of new to python and I am facing a lot of trouble because for some reason this value within my class method is updating by it self even though I didn't touch it. I can't even make it constant... Here is the relevant piece of code that does it.
the method that is called:
def swapping(self,pos,puzzle):
print('Old puzzle \n',puzzle)
# Getting Zero point index
zero = obj.null_pos(puzzle)
# Getting Index of varied position
var = puzzle[pos[0]][pos[1]]
#Swappping values
puzzle[zero[0,0],zero[0,1]] = var
puzzle[pos[0], pos[1]] = 0
new_puzzle = puzzle
print('New_puzzle \n',new_puzzle)
return new_puzzle
# The code has been snipped into relevant parts only
for i in range(len(child_node)):
# Check the hn of each node
print(child_node[i])
#where it occurs:
num_mispl = obj.misplaced_tiles(nod.swapping(child_node[i],new_puz))
# <-- new_puz #value changes and i didn't assign it to anything
temp_stor.append(num_mispl)

Using buttons with #interact

EDIT: Re-written for clarity Sept. 8 2019 1330 UTC
In a Jupyter notebook, I want to explore dates chosen by a date picker widget. The way of doing this I already knew was to use #interact and make the datepicker widget an argument to the interact function, like this:
def explore_dates(d1=widgets.DatePicker(value=pd.to_datetime('2018-07-10', format='%Y-%m-%d'), description='Date')):
But I need buttons "Next Holiday" and "Previous Holiday" to move from the selected date to the next holiday. I already have an array of holidays stored as datetime.datetime objects.
So I tried adding the button objects to the arguments to the #interact function, like this:
#interact
def explore_dates(d1=widgets.DatePicker(value=pd.to_datetime('2018-07-10', format='%Y-%m-%d'), description='Date'),
prev_button = widgets.Button(description="Prev Holiday"),
next_button = widgets.Button(description="Next Holiday")):
That didn't work. Error says the line with the button widget "cannot be transformed into a widget". Hmm, I thought it already was a widget...
My next thought was to put the button code inside the function, rather than as an argument:
def explore_dates(d1=widgets.DatePicker(value=pd.to_datetime('2018-07-10', format='%Y-%m-%d'), description='Date')):
prev_button = widgets.Button(description="Prev Holiday")
next_button = widgets.Button(description="Next Holiday")
prev_button.on_click(prev_holiday_callback)
next_button.on_click(next_holiday_callback)
box=widgets.HBox([prev_button,next_button])
display(box)
That got the buttons on the screen and I can push them and my callback routines run. But when the datepicker is set up (per above) as an argument to #interact, it appears that it is no longer possible to reset its date using its .value attribute. (See code above) trying to set d1.value results in an error.
I suppose I could get rid of #interact entirely, and just put the datepicker and both buttons into the mainline code. But I don't know how to reproduce the function of #interact at that point. Short of an infinite loop that waits for a click or observe event to come from one of the widgets, other than #interact, I don't know how to tell Python/Jupyter "hey, just chill out until a widget event causes a callback to wake up the code".
In case it's helpful, here are my callback routines for the buttons.
def button_click_common():
global button_flag
global button_date
global holidays
for i in range(len(holidays)):
if(holidays[i]<button_date): # haven't passed the prior holiday yet
continue
# Now holidays[i] has to either be same as or after button_date
prior_holiday = i-1 # prior holiday is the one we just passed that was prior
next_holiday = i # assume at first we are between dates
if holidays[i]==button_date:
next_holiday +=1 # if we were already on a holiday date, next becomes the following one
return prior_holiday, next_holiday
def prev_holiday_callback(_):
global button_flag
global button_date
global holidays
prior_holiday,_ = button_click_common()
button_date = holidays[prior_holiday]
button_flag = True
def next_holiday_callback(_):
global button_flag
global button_date
global holidays
_,next_holiday = button_click_common()
button_date = holidays[next_holiday]
button_flag = True
The idea here is that the callback updates button_date to the date of the next holiday, and sets the flag button_flag. Then code (not shown) in the explore_dates function was going to test the flag. But I can't figure out how to update the datepicker widget with the new date when it is defined as an argument to the #interact function.
Feels like I'm going about this wrong. Any advice or guidance welcome...
Thanks in advance!
I'm not sure I understand the exact aim you're trying to achieve, but interact works best with functions that take numeric inputs, rather than discrete inputs or python objects like dates.
I put together some code that would illustrate how I would use the forward and back buttons to update a datepicker, it's probably not exactly what you are looking for, but maybe you can describe the changes from there?
import ipywidgets as ipyw
from datetime import date
idx = 0
date_picker = ipyw.DatePicker()
date_picker.value = month_starts[idx]
start_button = ipyw.Button(description='Prev')
end_button = ipyw.Button(description='Next')
display(date_picker, start_button, end_button)
def change_date(button):
global idx
if button.description=='Prev':
if idx-1<0:
pass
else:
date_picker.value = month_starts[idx-1]
idx -= 1
elif button.description=='Next':
if idx+1>=len(month_starts):
pass
else:
date_picker.value = month_starts[idx+1]
idx += 1
start_button.on_click(change_date)
end_button.on_click(change_date)

How to I make a for/if loop that compares multiple rows and prints timestamps

I am currently trying to develop a code that compares the data within rows. The objective of the program is to make a comparison between the difference in speed and if there is a big difference in speed, I would like for it to print the timestamp. Here is what I wrote so far:
for row in cj1:
speed = row[1].speed
timestamp = row[0].timestamp
for i in range(1, row.length):
if speed is different =!:
Calculate acceleration
if acceleration > #certain amount:
print(timestamp)
Else:
timestamp = rows[i].timestamp
speed = rows[i].speed
It is a really rough code and I'm not too sure how to express it. Can anyone help?
If you just want to time how long code takes. You can use this context manager example.
from time import time, sleep
class Time(object):
def __enter__(self):
self.start = time()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.end = time()
self.interval = self.end - self.start
with Time() as t:
sleep(5) # <- your code here
print(t.interval)
5.001040935516357
UPDATE
So you can ask a better question next time. Here is some feedback:
for row in cj1:
speed = row[1].speed # <- There was no indent here.
timestamp = row[0].timestamp
for i in range(1, row.length):
if speed is different =!: # <- There was no indent here.
# `=!` with out another value is a syntax error.
Calculate acceleration # <- `Calculate` is not defined.
# Also no brackets are used,
# maybe `Calculate(acceleration)`?
if acceleration > #certain amount:
# `acceleration` is not defined.
# You can not compare greater than with a comment.
print(timestamp)
Else: # < - `Else` cannot be capitalised. you mean. `else`
timestamp = rows[i].timestamp
speed = rows[i].speed
Perhaps you should show a piece of your data, how does it look like?
In which format the values are?
The code you showed has wrong indentations etc. I suppose that data cannot be read like row[1].speed, or does that really work?
Edit:
Was that Calculate some kind of pseudocode? Please, try to formulate single rows in Python shell first to see that they are python code...

Categories