All of the lists are coming out empty? - python

I dont know if I am doing something wrong with the way I am laying out the functions or what. Basically I am trying to send a list of tickers to a database. I am taking the difference of two list so that the one that I send doesnt have the same tickers as the previous send. Can anyone help me?
tickList=[]
compareList=[]
newestList=[]
def searchTwit():
tweets = api.search("#stocks",count=100)
return tweets
def Diff(li1, li2):
return (list(list(set(li1)-set(li2)) + list(set(li2)-set(li1))))
def getTicker(tweets,list1,list2,anyList):
for tweet in tweets:
if "$" in tweet.text:
x = tweet.text.split()
for i in x:
if i.startswith("$") and i[1].isalpha():
i.strip(".")
i.upper()
list1.append(i)
anyList = Diff(list1,list2)
#print(newestList)
list2=list1
#print(list2)
list1.clear()
#print(list1)
return(anyList)
def retrieveTickers(list):
for i in list:
cursor.execute('INSERT INTO master.dbo.TickerTable (TickerName) VALUES (?);', (i))
conn.commit()
while True:
sleep(60 - time() %60)
print(f'This is ticklist {tickList}')
print(f'This is compareList{compareList}')
print(f'This is newestList {newestList}')
full_tweets=searchTwit()
getTicker(full_tweets,tickList,compareList,newestList)
retrieveTickers(newestList)

There are a few places that seem incorrect.
Python strings are immutable so this code block isn't doing what you think.
i.strip(".")
i.upper()
list1.append(i)
The string manipulation functions return new strings so you need to do this:
list1.append(i.strip(".").upper())
Its super unclear what you want retrieveTickers to do since its actually writing to a database. The function verb should match the action.
The diff function is convoluted. It can be simplified to
(set(li1) | set(li2)) - (set(li1) & set(li2))
but I don't see where you need these to be ordered so I would recommend changing the type you standardize on to set then diff can be written as:
li1.symmetric_difference(li2)
which probably doesn't need to be a function.
This block:
full_tweets=searchTwit()
getTicker(full_tweets,tickList,compareList,newestList)
retrieveTickers(newestList)
is also really really hard to follow. I think you are trying to manipulate the lists within the getTicker function. I strongly recommend not doing this. Instead return the information you need and if you need more than one data structure return them as a tuple. If I understand this correctly your function signature should probably look more like this:
new_tickers, already_seen_data = \
getTicker(full_tweets, already_seen_data)

Related

Trying to solve a number to mnemonics problem using recursion

Given a stringified phone number of non-zero length, write a function that returns all mnemonics for this phone number in any order.
`
def phoneNumberMnemonics(phoneNumber, Mnemonics=[''], idx=0):
number_lookup={'0':['0'], '1':['1'], '2':['a','b','c'], '3':['d','e','f'], '4':['g','h','i'], '5':['j','k','l'], '6':['m','n','o'], '7':['p','q','r','s'], '8':['t','u','v'], '9':['w','x','y','z']}
if idx==len(phoneNumber):
return Mnemonics
else:
new_Mnemonics=[]
for letter in number_lookup[phoneNumber[idx]]:
for mnemonic in Mnemonics:
new_Mnemonics.append(mnemonic+letter)
phoneNumberMnemonics(phoneNumber, new_Mnemonics, idx+1)
`
If I use the input "1905", my function outputs null. Using a print statement right before the return statement, I can see that the list Mnemonics is
['1w0j', '1x0j', '1y0j', '1z0j', '1w0k', '1x0k', '1y0k', '1z0k', '1w0l', '1x0l', '1y0l', '1z0l']
Which is the correct answer. Why is null being returned?
I am not very good at implementing recursion (yet?), your help is appreciated.
There are different recursive expressions of this problem, but the simplest to think about when you are starting out is a "pure functional" one. This means you never mutate recursively determined values. Rather compute fresh new ones: lists, etc. (Python does not give you a choice regarding strings; they're always immutable.) In this manner you can think about values only, not how they're stored and what's changing them, which is extremely error prone.
A pure-functional way to think about this problem is this:
If the phone number is the empty string, then the return value is just a list containing the empty string.
Else break the number into its first character and the rest. Recursively get all the mnemonics R of the rest. Then find all the letters corresponding to the first and prepend each of these to each member of R to make a new string (This is called a Cartesian cross product, which comes up often in recursion.) Return all of those strings.
In this expression, the pure function has the form
M(n: str) -> list[str]:
It's accepting a string of digits and returning a list of mnemonics.
Putting this thought into python is fairly simple:
LETTERS_BY_DIGIT = {
'0':['0'],
'1':['1'],
'2':['a','b','c'],
'3':['d','e','f'],
'4':['g','h','i'],
'5':['j','k','l'],
'6':['m','n','o'],
'7':['p','q','r','s'],
'8':['t','u','v'],
'9':['w','x','y','z'],
}
def mneumonics(n: str):
if len(n) == 0:
return ['']
rest = mneumonics(n[1:])
first = LETTERS_BY_DIGIT[n[0]]
rtn = [] # A fresh list to return.
for f in first: # Cartesian cross:
for r in rest: # first X rest
rtn.append(f + r); # Fresh string
return rtn
print(mneumonics('1905'))
Note that this code does not mutate the recursive return values rest at all. It makes a new list of new strings.
When you've mastered all the Python idioms, you'll see a slicker way to code the same thing:
def mneumonics(n: str):
return [''] if len(n) == 0 else [
c + r for c in LETTERS_BY_DIGIT[n[0]] for r in mneumonics(n[1:])]
Is this the most efficient code to solve this problem? Absolutely not. But this isn't a very practical thing to do anyway. It's better to go for a simple, correct solution that's easy to understand rather than worry about efficiency before you have a solid grasp of this way of thinking.
As others have said, using recursion at all on this problem is not a great choice if this were a production requirement.
The correct list (Mnemonics) was generated for the deepest call of the recursion. However, it was not passed back to previous calls.
To fix this, the Mnemonics not only needs to be returned in the "else" block, but it also needs to be set to equal the output of the recursive function phone Number Mnemonics.
def phoneNumberMnemonics(phoneNumber, Mnemonics=[''], idx=0):
number_lookup={'0':['0'], '1':['1'], '2':['a','b','c'], '3':['d','e','f'], '4':['g','h','i'], '5':['j','k','l'], '6':['m','n','o'], '7':['p','q','r','s'], '8':['t','u','v'], '9':['w','x','y','z']}
print(idx, len(phoneNumber))
if idx==len(phoneNumber):
pass
else:
new_Mnemonics=[]
for letter in number_lookup[phoneNumber[idx]]:
for mnemonic in Mnemonics:
new_Mnemonics.append(mnemonic+letter)
Mnemonics=phoneNumberMnemonics(phoneNumber, new_Mnemonics, idx+1)
return Mnemonics
I still feel that I'm lacking sophistication in my understanding of recursion. Advice, feedback, and clarifications are welcome.

How can I properly use variables returned in other function / method?

Please bare with me since I am just starting to learn coding, and Python is my first language to go.
I struggle and can't really get to understand how the functions work.
I can't manage to call it and use later on when I need it in another function.
Can someone please help me understand the depth of it ?
My code doesn't work and I can't manage to understand how to grab the results from a function, in order to use those results for the end purpose.
This is something I tried in the project I am working on:
manly_coded_bag = []
female_coded_bag = []
feminine_coded_words = [
"agree",
"affectionate",
"child",
"cheer",
]
masculine_coded_words = [
"active",
"adventurous",
"aggressive",
"ambitios",
]
explanations = {
"feminine-coded": (
"This job ad uses more words that are subtly coded as feminine than words that are subtly coded as masculine"
),
"masculine-coded": (
"This job ad uses more words that are subtly coded as masculine than words that are subtly coded as feminine."
)
def men_coded_words(masc_bag, text):
add_text = text
man_coded_bag = masc_bag
for word in masculine_coded_words:
if word in add_text:
man_coded_bag.append(word)
return man_coded_bag
def women_coded_words(fem_bag, text):
add_text = text
woman_coded_bag = fem_bag
for word in feminine_coded_words:
if word in add_text:
woman_coded_bag.append(word)
return woman_coded_bag
def analise_and_explain_results(text, count_man, count_fem):
count_man_words = count_man
count_man_words = len(man_coded_bag)
count_woman_words = count_fem
count_woman_words = len(woman_coded_bag)
coding_score = count_woman_words - count_man_words
strengths_of_coding = ""
if coding_score == 0:
if count_man_words:
strengths_of_coding = "neutral"
else:
strengths_of_coding = "empty"
elif coding_score > 0:
strengths_of_coding = "feminine-coded"
else:
strengths_of_coding = "masculine-coded"
return count_man_words, count_woman_words, strengths_of_coding
def get_results(text):
user_input = text
user_input = input("add text here:").lower()
res = analise_and_explain_results(text, man_coded_bag,
woman_coded_bag)
# i am trying to use the returned variable strengths_of_coding and
is not accesible.
explain_results = explanations[strengths_of_coding]
return res, explain_results
get_results("random text added here, really whatever for testing purposes")
Right, so when I am calling get_results('text'), I get this error and I know where it is coming from, "name 'strengths_of_coding' is not defined", but I just don't know how to access that variable...
I'm stuck here and a little bit frustrated because I understand it's a noob mistake, yet still I can't get the hang of it after a week of stress and frustration.
Any feedback is welcome.
So it's hard to explain everything if you barely have any knowledge in OOP or coding in general. But in python, the return value of a function can be anything. None, a integer, a list, tuple, dictionary, object. Can even be a class definition. Only by looking at it, will you know exactly. That is called duck-typing; "If it walks like a duck and it quacks like a duck, then it must be a duck"
In this case, your analise_and_explain_results function does not return one thing, but several since it does this:
return count_man_words, count_woman_words, strengths_of_coding
So it actually returns a tuple with those three values inside. And these variables are scoped to that specific function, you cannot use them outside that function anymore. Note: For the sake of simplicity; let's just stick to not using them outside of the function since it's bad practice.
In your code, you then do this:
res = analise_and_explain_results(user_input, man_coded_bag, woman_coded_bag)
Which means that res at this point is actually the tuple holding the three values you are interested in. You have several ways to resolve this. But this easiest to follow is to just assign the values of variables like this:
count_man_words, count_woman_words, strengths_of_coding = analise_and_explain_results(user_input, man_coded_bag, woman_coded_bag)
This basically unpacks the tuple into three different values since it basically does this:
a, b, c = (1, 2 ,3)
Where before you did:
d = (1, 2, 3)
Unpacking is easy, as long as the item you unpack holds as many items as you're trying to assign;
a, b, c = d
If you have trouble grasping OOP and python I would suggest you learn to walk, before you run, which you're doing now IMO.
Follow some tutorials or videos explaining OOP and python. Or combine them like they do on realpython.
strengths_of_coding is only defined inside the analise_and_explain_results function. When you return the values of that function, they are no longer attached to the names you used inside the function
return count_man_words, count_woman_words, strengths_of_coding can be also written as return (count_man_words, count_woman_words, strengths_of_coding) - it means the return value of the function is a tuple with 3 elements that are values of each of the variables, and that tuple is assigned to res in res = analise_and_explain_results(user_input, man_coded_bag, woman_coded_bag)
Value of variable called strengths_of_coding inside the function is available as res[2] in get_results after you do the assignment to res
res = analise_and_explain_results(user_input, man_coded_bag, woman_coded_bag) turns res into a tuple with 3 elements. strengths_of_coding is the 3rd element in this tuple. So, you access it as res[2]. In python, when you return multiple stuff to one variable, the variable turns into a tuple. You can provide multiple variables to take each return. e,g, count_man_words, count_woman_words, strengths_of_coding = analise_and_explain_results(user_input, man_coded_bag, woman_coded_bag). Or, if you only need that one return then, strengths_of_coding = analise_and_explain_results(user_input, man_coded_bag, woman_coded_bag)[2].
Sorry for a late answer. This is how I ended up fixing my code with the kind help from people who answered, I have came to understand where I was making mistakes.
This is how I fixed my code, using the example above, just in case someone else struggle with grasping the basics.
As a bonus for any new beginner finding this useful, something I learned from someone else.
The last print statement is a very useful way to debug your code:
print("results are: %s" % results)
For example adding it at the end, you can see if you ended up getting the right results, like in my example, or you can add it in your code to see what results you return in each functions and so on.
user_input = "Active, child, whatever random text, testing"
text = user_input.lower()
# declare the coded words, feminine and masculine
feminine_coded_words = [
"agree",
"affectionate",
"child",
"cheer",
]
masculine_coded_words = [
"active",
"adventurous",
"aggressive",
"ambitios",
]
# declare explanations to use when we explain the results to the user.
explanations = {
"feminine-coded": (
"This job ad uses more words that are subtly coded as feminine than words that are subtly coded as masculine"
),
"masculine-coded": (
"This job ad uses more words that are subtly coded as masculine than words that are subtly coded as feminine."
),
"neutral": ("this is neutral"),
"empty": ("empty text"),
}
# initiate two empty variable where we add our coded words, when we find them.
def men_coded_words(text):
add_text = text
manly_coded_bag = []
for word in masculine_coded_words:
if word in add_text:
manly_coded_bag.append(word)
return manly_coded_bag
def women_coded_words(text):
add_text = text
feminine_coded_bag = []
for word in feminine_coded_words:
if word in add_text:
feminine_coded_bag.append(word)
return feminine_coded_bag
def feminine_counted_words(text):
woman_coded_bag = women_coded_words(text)
return len(woman_coded_bag)
def masculine_counted_words(text):
man_coded_bag = men_coded_words(text)
return len(man_coded_bag)
def coding_score(text):
count_fem_words = feminine_counted_words(text)
count_masc_words = masculine_counted_words(text)
return count_fem_words - count_masc_words
def explain_results(text):
strengths_of_coding = ""
count_masc_words = masculine_counted_words(text)
coding_score_results = coding_score(text)
if coding_score_results == 0:
if count_masc_words:
strengths_of_coding = "neutral"
else:
strengths_of_coding = "empty"
elif coding_score_results > 0:
strengths_of_coding = "feminine-coded"
else:
strengths_of_coding = "masculine-coded"
return strengths_of_coding
def get_results(text):
strenght_of_coding = explain_results(text)
return explanations[strenght_of_coding]
results = get_results(text)
print("results are: %s" % results)

looping over optional arguments (strings) in python

I have lists of strings, some are hashtags - like #rabbitsarecool others are short pieces of prose like "My rabbits name is fred."
I have written a program to seperate them:
def seperate_hashtags_from_prose(*strs):
props = []
hashtags = []
for x in strs:
if x[0]=="#" and x.find(' ')==-1:
hashtags += x
else:
prose += x
return hashtags, prose
seperate_hashtags_from_prose(["I like cats","#cats","Rabbits are the best","#Rabbits"])
This program does not work. in the above example when i debug it, it tells me that on the first loop:
x=["I like cats","#cats","Rabbits are the best",#Rabbits].
Thisis not what I would have expected - my intuition is that something about the way the loop over optional arguments is constructed is causing an error- but i can't see why.
There are several issues.
The most obvious is switching between props and prose. The code you posted does not run.
As others have commented, if you use the * in the function call, you should not make the call with a list. You could use seperate_hashtags_from_prose("I like cats","#cats","Rabbits are the best","#Rabbits") instead.
The line hashtags += x does not do what you think it does. When you use + as an operator on iterables (such as list and string) it will concatenate them. You probably meant hashtags.append(x) instead.

How to continue iteration of JSON object/list with "for" loop nested in another "for" loop?

I'm trying to iterate through a JSON object/list to get the prices from the list. It works fine for the first "for" loop, but then for my program I need to have another "for" loop nested inside the first loop that effectively continues iterating again where the first loop left off.
edit: I apologise as I probably wasn't very clear as why I'm structuring this code this way. It probably isn't the best solution as I'm not very experienced with python but I'm trying to simulate the looping flow of price data based on historical prices from this JSON. So when the price is equal to something in the first loop, I was trying to continue the flow of data from where the last loop left off (the last price it read) in a nested loop with different if statements, now that the first one has been triggered. I understand this is probably a very poor way of getting around this problem and I'd be happy to hear suggestions on how to do it in a much simpler way.
for i in json:
time.sleep(1)
price = i['p']
if price == "0.00000183":
print("foo")
for i in json:
time.sleep(1)
price = float(i['p'])
if price == "0.00000181":
print("sold")
else:
continue
elif price == "0.00000185":
print ("sold")
break
else:
continue
Example segment of the JSON list:
[
{
"a":4886508,
"p":"0.00000182",
"q":"10971.00000000",
"f":5883037,
"l":5883037,
"T":1566503952430,
"m":1,
"M":1
},
{
"a":4886509,
"p":"0.00000182",
"q":"10971.00000000",
"f":5883038,
"l":5883038,
"T":1566503953551,
"m":1,
"M":1
},
{
"a":4886510,
"p":"0.00000182",
"q":"10971.00000000",
"f":5883039,
"l":5883039,
"T":1566503954431,
"m":1,
"M":1
}
]
You have 3 nested dicts inside the list and you’re using one value price to store all 3; therefore overwriting the value for every iteration.
I suggest using a simple list comprehension to get the price for each sub-dict.
[i['p'] for i in json]
This results in:
['0.00000182', '0.00000182', '0.00000182']
Although as a forewarning there is a builtin module called json so should you want to use that in the future you will need to use a more descriptive name; as well as your other naming conventions are very non informative in the first place consider better conventions.
P.S the price values are strings thus it’s meaningless to compare to int’s
Your sample code doesn't make much sense, so it's not clear what you're try to accomplish.
Ignoring that, if you use json.load() to read your file, the result will be a Python list of dictionaries (which are equivalent to JSON objects). Afterwards you can then just iterate through this list — you don't need to do anything else to go to the next dictionary/object.
Within each dictionary/object you can randomly access the key/value pairs it contains. If yoy want to iterate over them for some reason, you can used obj.keys(), obj.values(), or obj.items(), as you can with any dictionary.
Here's a small example of what I'm saying:
import json
filename = 'list_sample.json'
with open(filename) as json_file:
object_list = json.load(json_file)
for obj in object_list:
if obj['p'] == "0.00000183":
print("foo")
price = float(obj['p'])
print(price)
Use pandas
import pandas as pd
The question was how do I iterate through a json
I think the real question and goal is, how do I access my data from this object and gather insight from it.
That's the power of pandas. Now all of the information is available and easy to use.
If the data is inside a file, just as it's shown:
df = pd.read_json('file.json')
If the data is just a named object (e.g. data = [{...}, {...}, {...}])
df = pd.DataFrame(data)
Output of df:
Get p, or any of the other information:
p_list = df.p.tolist()
print(p_list)
>>> ['0.00000182', '0.00000182', '0.00000182']
You can write two loops using the same iterator object. You just need to create the iterator from your json list of dictionaries:
iterator = iter(json_data)
for i in iterator:
# stuff
for j in iterator: # start looping from where we left off
... # more stuff
Note that this only makes sense if the inner loop will be interrupted at some point by a break statement. Otherwise it will consume all of the iterator's contents and the outer loop will have nothing left. If you were expecting that, you should probably just break out of the outer loop and write the (formerly) inner loop at the same level:
for i in iterator:
if something():
break
for j in iterator: # iterate over the rest of the iterator's values
...
Note that I used json_data in my example code, rather than your variable name json. Using json as a variable name may be a bad idea because it may be the name of the module you're using to parse your data. Reusing the name may get confusing (json = json.load(filename) for instance can only be run once).
Apologies guys, I should've made it more clear that what I was looking for was probably simpler than what I made it out to be or how I described it. I basically just wanted to continue the second loop from where the first left off, with something like this which I have now found to be an alright solution.
elementCount = 0
for i in json:
time.sleep(1)
price = i['p']
elementCount = elementCount + 1
if price == "0.00000183":
print("foo")
for i in json[elementCount:]:
time.sleep(1)
price = float(i['p'])
if price == "0.00000181":
print("sold")
else:
continue
elif price == "0.00000185":
print ("sold")
break
else:
continue
I basically just didn't understand the format for continuing the iteration from a certain element in the list, like this [40:]. Thanks for all your answers and help.

Python doesn't show anything

It's my first Python program and my first excercise is that I just need to swap places in a tuple:
stamboom = [("Frans","Eefje"), ("Klaar","Eefje"), ("Eefje","Mattho"),
("Eefje","Salammbo"), ("Gustave","Mattho"), ("Gustave","Salambo")]
Is the tuple, and I need to swap Frans with Eefje (those are just names) and then swap the second tuple.
I read the whole data structure tutorial off Python and I thought I could do this like this:
#!/path/to/python
stamboom = [("Frans","Eefje"), ("Klaar","Eefje"), ("Eefje","Mattho"),
("Eefje","Salammbo"), ("Gustave","Mattho"), ("Gustave","Salambo")]
def switchplace(x):
stamboom[x], stamboom[x + 1] = stamboom[x + 1], stamboom[x]
return stamboom
map(switchplace, range(0, len(stamboom)))
It doens't give syntax errors but it doesn't show anything.
To show something you have to print it.
Change the last line to:
print map(switchplace,range(0,len(stamboom)))
That was very complicated code for a simple task. Check out something called list comprehension.
Change the code to:
stamboom = [("Frans","Eefje"), ("Klaar","Eefje"), ("Eefje","Mattho"),
("Eefje","Salammbo"), ("Gustave","Mattho"), ("Gustave","Salambo")]
stamboom = [(item[1], item[0]) for item in stamboom]
print stamboom
Update
I saw your solution in the comment. I don't know if there are more premisses to the excersise that I'm not aware of. But I would probably do this instead:
def switchplace(x):
return x[1], x[0]
stamboom = [("Frans","Eefje"),("Klaar","Eefje"),("Eefje","Mattho"), ("Eefje","Salammbo"),("Gustave","Mattho"),("Gustave","Salammbo")]
print map(switchplace, stamboom)
The iterable argument to map don't have to be a numeric range. It could be the list itself. But maybe I missed something and you already got it :)
Tuples are immutable in Python:
http://docs.python.org/reference/datamodel.html

Categories