Why may this construction be not working? - python-3.x

I receive, that first iteration 1 is not a number.
numbers = ['1', 'apple', '2', '3', '4', '5']
print ('Your numbers are...')
for f in numbers:
if f.isalpha():
print ('This is not a number!') # (It actually isn't.)
break
print (f)
else:
print ('Here are your numbers!')

You're seeing this...
Your numbers are...
Then you hit the first iteration, f = '1' and print (f):
1
Then you get to the second iteration, f = 'apple' and print ('This is not a number!')...
This is not a number!
This is to be expected.
Your output would be clearer with this program:
#!/usr/bin/env python3
numbers = ['1', 'apple', '2', '3', '4', '5']
print ('Your numbers are...')
for f in numbers:
if f.isalpha():
print('{} is not a number!'.format(f))
break
else:
print('Here are your numbers: {}'.format(numbers))

Related

Is this a safe way to use eval() in python?

I understand that running eval on user input is very dangerous, does limiting the input like I've done in the code below eliminate all the danger?
q=''
safe=['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '+', '-', '*', '/', '(', ')', '.']
while True:
i= input('input = ')
if i == 'exit':
exit('Shutting Down.')
elif i in safe:
q += i
elif i == '=':
print(eval(q))
else:
print('no')
If this still contains vulnerabilities, is there some way to add the symbols to a string of numbers and calculate the answer? I know I can simply use float() for converting the string numbers to actual numbers but I have no idea how I could add '+' as just a + so it can be used in a calculation.
Edit: Switched the code since I accidentally uploaded the wrong code
If you want to check the entire input string, you can put the safe characters in a set then compare the input to the safe set.
Try this code:
safe=['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '+', '-', '*', '/', '(', ')', '.']
safeall = set(safe) # all safe characters
while True:
i= input('input = ').strip()
if i == 'exit':
exit('Shutting Down.')
if safeall & set(i) == set(i): # if input in safe characters
print('Safe')
print(eval(i))
else:
print('Not Safe')
Output
input = test123
Not safe
input = ##$$%%
Not safe
input = 12 + 67
Safe
79
input = exit
Shutting Down.

How to determine "event" output to print on the outcome of a random dice roll?

I'm trying to have certain strings print out depending on which dice roll is made.
I have tried making lists for what rolls get which event, but even at that no event prints out only what i have rolled.
import random
def dice_roll():
d20_roll = random.randint(1,20)
print("You rolled " +str(d20_roll))
def dice_choice():
event = str(d20_roll)
bad_list = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
'11', '12']
good_list = ['13', '14', '15', '16', '17', '18']
gag_list = ['19', '20']
if event == bad_list:
print('bad_list stuff')
elif event == good_list:
print('good_list stuff')
else:
if event == print gag_list:
print("gag_list stuff")
dice_choice()
dice_roll()
I expect the output to be any of the three options the random roll will make.
What I receive is just the result of the dice_roll itself, without the choice.
First, check your indentation, your call to dice_choice() seems to be inside dice_choice() itself, second, there is a syntax error in your test if event == print gag_list:, third, you are testing whether a string equals a list, instead you should test whether the string is in the list, your code should be like this:
import random
def dice_roll():
d20_roll = random.randint(1,20)
print("You rolled " +str(d20_roll))
def dice_choice():
event = str(d20_roll)
bad_list = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']
good_list = ['13', '14', '15', '16', '17', '18']
gag_list = ['19', '20']
if event in bad_list: # check using `in` not `===`
print('bad_list stuff')
elif event in good_list:
print('good_list stuff')
elif event == gag_list:
print("gag_list stuff")
dice_choice()
dice_roll()
Example Output:
You rolled 11
bad_list stuff

Python 3.6 - How to search through a 2D list and return true or false if an item matches user input

I am using EDX to start learning python and I am stuck in a project that requires me to create a tic tac toe game.
I believe I have managed to complete most of the functions but when I tried to run the function that checks whether a position is available to be marked as X or O, I always get a false reading. It returns true only for the 7 and not for the rest of the items.
board = [['7', '8', '9'], ['4', '5', '6'], ['1', '2', '3']]
location = input(" Turn, select a number (1, 9): ")
def available(location, board):
for row in board:
for col in row:
if col==location:
return True
else:
return False
print(available(location,board))
I decided to separate the function from the rest of the code. The code above should be able to search the 2D list and if it finds the number that the user has entered to return true or false. When it does that another function is executed to change that number to X or O depending the player. I tried to run the function without the function and with print instead of return and works fine.
board = [['7', '8', '9'], ['4', '5', '6'], ['1', '2', '3']]
location = input(" Turn, select a number (1, 9): ")
for row in board:
for col in row:
if col==location:
print("True")
else:
print("False")
Any idea what I am doing wrong?
Let's look at your if else statement.
When the input number is not 7, we do not return true, instead we go to the else and immediately return false without checking the rest of the numbers.
The solution is to remove the else, and just return false only after iterating through every cell.
When you change the returns to prints this bug disappears because you are no longer returning, and therefore execution doesn't stop early.
def available(location, board):
for row in board:
for col in row:
if col==location:
return True
return False
The key insight here is that returning from a function, exits the function.
To overcome the problem you identified, you could for instance flatten your list by using a list comprehension and check for the existence of location in it:
board = [['7', '8', '9'], ['4', '5', '6'], ['1', '2', '3']]
location = input(" Turn, select a number (1, 9): ")
def available(location, board):
#collect all elements from all sublists in a list
allfields = [i for j in board for i in j]
#location element of this list?
if location in allfields:
return True
return False
print(available(location,board))
You can use any for a more Pythonic version.
def available(location, board):
return any(any(i == location for i in row) for row in board)

How with open works?

Today I was trying to open a file and build some list from the data of the file. I am using the with statement. But I have the following doubt:
If I write the following code:
def Preset_wheel_filler(self):
"""
Complete the Preset_wheel and also apply preset values when one
preset is selected.
"""
with open('Preset.txt', 'r') as PresetFile:
Presets = [line.split()[1:] for line in PresetFile if 'name:'
in line.split()]
with open('Preset.txt', 'r') as PresetFile:
channel_list = ['1', '2', '3', '4', '5', '6', '7', '8']
Preset_values = [line.split() for line in PresetFile for
y in channel_list if y in line.split()]
print(len(Preset_values))
The length of the last list created is 16. (Which is correct)
Now, if I rearrange the code like this:
def Preset_wheel_filler(self):
"""
Complete the Preset_wheel and also apply preset values when one
preset is selected.
"""
with open('Preset.txt', 'r') as PresetFile:
Presets = [line.split()[1:] for line in PresetFile if 'name:'
in line.split()]
channel_list = ['1', '2', '3', '4', '5', '6', '7', '8']
Preset_values = [line.split() for line in PresetFile for
y in channel_list if y in line.split()]
print(len(Preset_values))
The printed length is 0.
My question is: Why should I write the with open statement twice?
Thanks in advance.
Files are stream based. Once you read all the data in the file its position pointer is at the end and nothing can be read anymore. You "could" seek to 0 to fix that, but - you have the full line in the first go, simply parse both things from it.
PresetFile.seek(0) # goes back to the beginning of the file.
See https://docs.python.org/3/tutorial/inputoutput.html#methods-of-file-objects
for details on how to use seek and maybee peek into https://docs.python.org/3/library/functions.html#open
again.

Matrix input from a text file(python 3)

Im trying to find a way to be able to input a matrix from a text file;
for example, a text file would contain
1 2 3
4 5 6
7 8 9
And it would make a matrix with those numbers and put it in matrix = [[1,2,3],[4,5,6],[7,8,9]]
And then this has to be compatible with the way I print the matrix:
print('\n'.join([' '.join(map(str, row)) for row in matrix]))
So far,I tried this
chemin = input('entrez le chemin du fichier')
path = input('enter file location')
f = open ( path , 'r')
matrix = [ map(int,line.split(','))) for line in f if line.strip() != "" ]
All it does is return me a map object and return an error when I try to print the matrix.
What am I doing wrong? Matrix should contain the matrix read from the text file and not map object,and I dont want to use external library such as numpy
Thanks
You can use list comprehension as such:
myfile.txt:
1 2 3
4 5 6
7 8 9
>>> matrix = open('myfile.txt').read()
>>> matrix = [item.split() for item in matrix.split('\n')[:-1]]
>>> matrix
[['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9']]
>>>
You can also create a function for this:
>>> def matrix(file):
... contents = open(file).read()
... return [item.split() for item in contents.split('\n')[:-1]]
...
>>> matrix('myfile.txt')
[['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9']]
>>>
is working with both python2(e.g. Python 2.7.10) and python3(e.g. Python 3.6.4)
rows=3
cols=3
with open('in.txt') as f:
data = []
for i in range(0, rows):
data.append(list(map(int, f.readline().split()[:cols])))
print (data)

Resources