Python Saving File if a function is true - python

I am writing a save function; which writes a list to a new text file if functions are true. However it's not working as I expected. Currently it does not print anything when the save function is called.
The savedata function calls the duplicate function:
My "d" is a list like so:
[ 'ABB'
'CAB'
'BCA']
duplicate=[]
list=[]
def dup():
l=len(d)
for i in range(l):
column.append([x[i] for x in d])
for col in column:
for i in range(0,len(col)-1):
if col[i] == col[i+1]:
print(str(col[i]) + " is a duplicate in column " + str(column.index(col)+1) + " position(index) " + str(col.index(col[i+1])+1))
return False
else:
return True
Now when i print duplicate() KNOWING i do have duplicates in the list, it should return False, however it returns True. Why is this?

You're not calling the function in your if condition, what it's actually checking for is if duplicate has been defined (in this case, yes, as a function).
Use if duplicate():. Also, I don't see where you're defining d. Perhaps that will raise an error.

Related

Python if statement always returns false, even though input is true

So I'm writing a program (A sort of "custom if statement") that checks if your input is true or false. This is the script I have right now:
v=line[3:] # Remove "if " from the line, so you only have the question and the consequence
i=v.split(': ') # Make a list with the first item being the question and the second item being the consequence.
for r in i:
if r==i[1]: # Check which item in the list is the question and which is the consequence
c=r
question=i[0]
consequences=c.split(' | ')
for x in consequences:
self.consequences+=f'\n{x}' # Create a variable with all of the consequences, each in one line
Answer=False # reate the Answer variable with the default value False
def checkVal(question):
global Answer
if question:
b=open('if.BaRT','w+')
b.write(self.consequences)
b.close()
self.run('if.BaRT')
os.remove('if.BaRT')
else:
pass # Check if the question is true or false
if Answer==True:
print("True!")
else:
print("False!") # Finally check if the question is true or not and if it is, print "True!" and if it's not, print "False!"
I'm expecting this to work, but then when i input something that's true, for example: __name__=="__main__", so my input looks like this:
if __name__=="__main__": print("Hello!")
this is the output:
False!
How do I fix this so it prints it accurately?
Edit: consequences added
I have replaced your exec with eval to get rid of your global variable (still not good coding practise, but if this is what you need...). Also, the for is not needed.
PS: the variables i, v and c should have better names.
line='if __name__=="__main__": print("Hello!")'
v=line[3:] # Remove "if " from the line, so you only have the question and the consequence
i=v.split(': ') # Make a list with the first item being the question and the second item being the consequence.
c=i[1]
question=i[0]
consequences=c.split(' | ')
_consequences=''
for x in consequences:
_consequences+=f'\n{x}'
Answer=eval(f"{question}") # Check if the question is true or false
if Answer==True:
exec( _consequences)
print("True!")
else:
print("False!") # Finally check if the question is true or not and if it is, print "True!" and if it's not, print "False!"

return function delete some data and print function add None in the output

when I use the print function it returns None.
when I replace it with return some of the data is deleted
def email_list(domains):
for domain in domains:
for user in domains[domain]:
return("{}#{}".format(user,domain))
print(email_list({"gmail.com": ["clark.kent", "diana.prince", "peter.parker"], "yahoo.com": ["barbara.gordon", "jean.grey"], "hotmail.com": ["bruce.wayne"]}))`
You are probably looking for this -
def email_list(domains):
lst = []
for domain in domains:
for user in domains[domain]:
lst.append("{}#{}".format(user,domain))
return lst
print(email_list({"gmail.com": ["clark.kent", "diana.prince", "peter.parker"], "yahoo.com": ["barbara.gordon", "jean.grey"], "hotmail.com": ["bruce.wayne"]}))
OUTPUT :
['clark.kent#gmail.com', 'diana.prince#gmail.com', 'peter.parker#gmail.com', 'barbara.gordon#yahoo.com', 'jean.grey#yahoo.com', 'bruce.wayne#hotmail.com']
In your code, the function would end on the first iteration itself. However, you are looking for first creating a list and at last after you are done with your looping, only then return the list.

Using Python one liner containing print statement produce list of None`s

ts_file = "ts_nfl_04_red_zone_conversion"
ts_title = [print(i + ' ', end="") for i in ts_file[7:].upper().split("_")]
Result:
04 RED ZONE CONVERSION [None, None, None, None]
What produce this list of None statement and how I can avoid it?
Many thanks.
You can use replace instead:
>>> ts_file[7:].upper().replace("_", " ")
You could instead join the elements resulting from the splitting the string:
ts_title = (' ').join(ts_file[7:].upper().split("_"))
# '04 RED ZONE CONVERSION'
List comprhension isn't really necessary here as a print statement returns a None type. You can just loop through the string like this:
for i in ts_file[7:].upper().split("_"): print(i + " ", end="")
You produced a list of None because you created one. That's what a list comprehension is for: creating lists. However, expressions aren't automatically printed unless you're in the interactive interpreter and have returned the expression to the top level, which means you wouldn't actually see this output given that you're saving it to a variable.
Anyway, you're supposed to use a regular loop in this situation, as follows:
ts_file = "ts_nfl_04_red_zone_conversion"
for i in ts_file[7:].upper().split("_"):
print(i + ' ', end="")
However, you can of course still use a comprehension and create an empty list by rearranging it slightly, saving it to a variable so that it isn't automatically printed in the interactive interpreter:
ts_file = "ts_nfl_04_red_zone_conversion"
ts_title = [None for i in ts_file[7:].upper().split("_") if print(i + ' ', end="")]
As mentioned in the comments, print returns a None and is not intended be used in a list comprehension.
if you want a one-liner to achieve your desired result, you can do something like
print(' '.join(ts_file[7:].upper().split("_")))
As mentioned by others, print() does not return anything. Hence, None is printed. If you are wondering why the elements are properly printed, and then followed by 4 None's, its because of how functions work.
A function is called and once every statement inside has been executed, a value is returned, but only if the function returns something.
In your case, print(i + ...) called the print function on i, print was executed, meaning that it printed i to the console, and then its value was returned, which is None, since print() does n't return anything.
Coming to the solution, you could use the .join() method or the replace() method:
a = ts_file[7:].upper().replace("_", " ")
print(a)
or
a = (' ').join(ts_file[7:].upper().split("_"))
print(a)
The output:
04 RED ZONE CONVERSION
You could also do another thing, if you did n't care about what was stored in ts_title:
As soon as you assign ts_title with your list comprehension:
ts_title = [print(i + ' ', end="") for i in ts_file[7:].upper().split("_")]
if you run your script, you will get the expected output on the screen, just as I had explained at the start of the answer.

Function Not Printing Desired Output

I am having issues with creating a function that takes a list of tuples and then returns one string which is the first character of each tuple. Below is my current code, but nothing it happening, I do not get a syntax error. Any help would be appreciated.
lst_of_tups = ([('hello', 'all'), ('music', 'playing'), ('celebration', 'station')])
def build_string(lst_of_tups):
final_str = ""
for tup in list_of_tups:
for item in tup:
final_str = final_str + item[0]
return final_str
print build_string
**** expected output: hampcs****
those string manipulation functions are error-prone: they define lots of variables, can return within inner loops, have unexpected side-effects...
Once you're used to list comprehensions, you can create such programs easily & with great execution performance (string concatenation is slow). One way:
def build_string(lst_of_tups):
return "".join([x[0] for y in lst_of_tups for x in y])
basically, it's just 2 loops (flattening the data) within a list comprehension to extract each first character from every string, joined together using str.join to rebuild the string.
Once you reach a return statement in a function, the function ends for good. The line
print build_string
cannot be reached. (Another problem is that the name build_string is not defined.)
Use your function like this:
result = build_string(lst_of_tups) # calls your function and puts the return value in the result variable
print result # print the result
Of course, the intermediary variable result is not necessary, you could just issue print build_string(lst_of_tups) as well.

Better / More pythonic way to process the results of a function with multiple return values

The code below works, but looks very ugly. I'm looking for a more pythonic way to write the same thing.
The goal:
React on a result of a function that returns multiple values.
Example function
def myfilterfunc(mystr):
if 'la' in mystr:
return True, mystr
return False, None
This returns True and a string (if the string cointains "la"), or False and nothing.
In a second function, I'm passing myfilterfunc as an optional parameter
def mymainfunc(mystr,filterfunc=None):
This function fills a returnlist.
If no function is given, the result is not filtered and added as is.
If a filter function is given, if the filter function returns
True, a returned string is added. (This is just an example that would
easily work with one return value, but I'm trying to get the systax
right for a more complicated setup)
if filterfunc:
tmp_status,tmp_string = filterfunc(mystr[startpos:nextitem])
if tmp_status:
returnlist.append(tmp_string)
else:
returnlist.append(mystr[startpos:nextitem])
Any idea how I can write this without using temporary variables to store the return values of the function?
Full "working" test code below
def string2list(mystr,splitlist,filterfunc=None):
returnlist = []
startpos = 0
nextitem = -1
matched = True
while matched:
matched = False
for sub in splitlist:
if startpos == 0:
tmpi = mystr.find(sub)
else:
tmpi = mystr.find(sub,startpos + 1)
if (tmpi > 0) and ((nextitem < 0) or (nextitem > tmpi)):
nextitem = tmpi
matched = True
if filterfunc:
tmp_status,tmp_string = filterfunc(mystr[startpos:nextitem])
if tmp_status:
returnlist.append(tmp_string)
else:
returnlist.append(mystr[startpos:nextitem])
startpos = nextitem
nextitem = -1
return returnlist
def myfilterfunc(mystr):
if 'la' in mystr:
return True,mystr
return False,''
splitlist = ['li','la']
mytext = '''
li1
li2
li3
fg4
fg5
fg6
la7
la
la
tz
tz
tzt
tz
end
'''
print string2list(mytext,splitlist)
print
print string2list(mytext,splitlist,myfilterfunc)
If this is going to happen often you can factor out the uglyness:
def filtered(f, x):
if f:
status, result = f(x)
return result if status else x
else:
return x
used like
returnlist.append(filtered(filterfunc, mystr[startpos:nextitem]))
so that if you have many similar optional filters the code remains readable. This works because in Python functions/closures are first class citizens and you can pass them around like other values.
But then if the logic is about always adding (either the filtered or the unfiltered) why not just write the filter to return the input instead of (False, "") in case of failure?
That would make the code simpler to understand...
returnlist.append(filterfunc(mystr[startpos:nextitem]))
I think there are two better approaches to your problem that don't involve using two return values.
The first is to simply return a Boolean value and not a string at all. This works if your filter is always going to return the string it was passed unmodified if it returns a string at all (e.g. if the first value is True). This approach will let you avoid using temporary values at all:
if filterfunc:
if filterfunc(mystr[startpos:nextitem]):
returnlist.append(mystr[startpos:nextitem])
(Note, I'd suggest renaming filterfunc to predicate if you go this route.)
The other option will work if some filterfunc might return a different second value than it was passed under some situations, but never the 2-tuple True, None. In this approach you simply use the single value as both the signal and the payload. If it's None, you ignore it. If it's anything else, you use it. This does require a temporary variable, but only one (and it's a lot less ugly).
if filterfunc:
result = filterfunc(mystr[startpos:nextitem])
if result is not None:
returnlist.append(result)

Categories