Fixing right alignment of string formatting - python

I'm trying to align the output of the list like shown:
But it keeps coming out like this:
My code for all of this is:
subject_amount = int(input("\nHow many subject do you want to enrol? "))
class Subject:
def __init__(self, subject_code, credit_point):
self.subject_code = subject_code
self.credit_point = credit_point
subjects = []
for i in range(1, (subject_amount + 1)):
subject_code = input("\nEnter subject " + str(i) + ": ")
credit_point = int(input("Enter subject " + str(i) + " credit point: "))
subject = Subject(subject_code, credit_point)
subjects.append(subject)
print ("\nSelected subjects: ")
i, total = 0, 0
print("{0:<} {1:>11}".format("Subject: ", "CP"))
while(i < subject_amount):
print("{0:<} {1:14}".format(subjects[i].subject_code, subjects[i].credit_point))
total += subjects[i].credit_point
i = i + 1
print("{0:<} {1:>11}".format("Total cp: ", total))
I've tried changing the values for the spacing as well with no results.
Any feedback on the rest of my code is also greatly appreciated.

You can't do this using plain Python formatting because the amount of padding depends on both strings. Try defining a function such as:
def format_justified(left, right, total):
padding = total - len(left)
return "{{0}}{{1:>{}}}".format(padding).format(left, right)
then simply use:
print(format_justified("Total cp:", total, 25))
where 25 is the total line width you want.

Related

How to ask the user of a program for a random objects corresponding value in a list?

I have a list which looks like this: [1 H 1.0079, 2 He 4.0026, 3 Li 6.941, 4 Be 9.01218, ...]
I want to ask the user of the program for the corresponding atomic number to the atom. So the program will take a random atomic symbol and ask the user what's the atoms atomic number.
Code so far:
class Atom:
def __init__(self, number, weight, atom):
self.number = nummer
self.atom = atom
self.weight = weight
def __str__(self):
return self.atom + " " + str(self.weight)
def __repr__(self):
return str(self.number) + " " + self.atom + " " + str(self.weight)
def atom_listan():
atom_file = open('atomer2.txt', 'r')
atom_lista = []
number = 1
for line in atom_fil:
data = line
weight = float(data.split()[1])
atom = data.split()[0]
new_atom1 = Atom(number, weight, atom)
atom_lista.append(new_atom1)
atom_lista.sort(key=lambda x: x.vikt)
atom_lista[17], atom_lista[18] = atom_lista[18], atom_lista[17]
atom_lista[26], atom_lista[27] = atom_lista[27], atom_lista[26]
atom_lista[51], atom_lista[52] = atom_lista[52], atom_lista[51]
atom_lista[89], atom_lista[90] = atom_lista[90], atom_lista[89]
atom_lista[91], atom_lista[92] = atom_lista[92], atom_lista[91]
atom_fil.close()
for i in range(len(atom_lista)):
atom_lista[i].number = i + 1
return atom_lista
Code so far where I create a list consisting of the elements information. I have tried using the random.choice module but I don't really know how to get only the atomic symbol from the list with random.choice and also have the corresponding atomic number to the random atom be the correct answer.
You can get the atomic symbol like this if you have the list of elements as you mentioned in the question.
import random
a=["1 H 1.0079", "2 He 4.0026", "3 Li 6.941", "4 Be 9.01218"]
random_choice = random.choice(a)
random_atom = random_choice.split(" ")[1]
print(random_atom)
Try this. Clearly you could put it into a loop. I just used a part of your List.
import random
elements = ['1 H 1.0079', '2 He 4.0026', '3 Li 6.941', '4 Be 9.01218']
choose = random.choice(elements)
splitted = choose.split(' ')
print('The element symbol is : ', splitted[1])
attempt = input('Enter the Atomic Number ')
if (attempt == splitted[0]):
print('Correct')
else:
print('Wrong')

python how do I add a score on the same object 3 times in a row?

I have a problem adding scores to an object with a for loop.
what I'm trying to achieve is this:
enter test num: 1
enter test score: 58
enter test num: 2
etc...
and then print out the three test numbers and the average, but I can't seem to get it to set the test num nor the score.
this is the error I get after tring to add test 1 and test 1 score:
Traceback (most recent call last):
File "d:\pyproj\Lecture 5\Main.py", line 27, in <module>
studentArray()
File "d:\pyproj\Lecture 5\Main.py", line 25, in studentArray s = student.setTestScore(test,score)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: student.setTestScore() missing 1 required positional argument: 'result'
Main.py
from student import student
def studentArray():
classSize = int(input("how big is the class? "))
classList = []
num=0
while not(num == classSize):
firstName = input("\nWhat's the students first name? ");
lastName = input("\nWhat's the students last name? ");
homeAddress = input("\nWhat's the students home address? ");
schoolAddress = input("\nWhat's the students school address? ");
courseName = input("\nWhat course is the students taking? ");
courseCode = input("\nWhat's the course code? ");
classList.append(student(firstName,lastName,homeAddress,schoolAddress,courseName,courseCode));
num+=1
for s in classList:
for i in range(len(classList)):
test = int(input("enter test number: "))
score = int(input("enter test score: "))
s.setTestScore(test,score)
print("\n",s)
studentArray()
studentclass.py:
from Course import Course
class student:
def __init__(self,first, last, home, school,courseName,courseCode):
self.firstName = first
self.lastName = last
self.homeAddress = home
self.schoolAddress = school
self.courseName = courseName
self.courseCode = courseCode
Course(courseName,courseCode)
self.testResults = []
def setTestScore(self,test,result):
if test < 1 | result < 0 | test > 100:
print("Error: Wrong test results.")
else:
self.testResults.append(result)
def average(self):
average = 0;
total = 0;
for result in self.testResults:
total += result
average = total / 3.0;
return average;
def __str__(self):
testAString = ""
for testResult in self.testResults:
testAString += str(testResult) + " "
result = "Student name:\n"+self.firstName + " " + self.lastName+"\n";
result += "Course name:\n"+self.courseName+"\n";
result += "Course Code: "+ self.courseCode+"\n";
result += "Test results:\n"+testAString+"\n";
result += "Average:\n", str(self.average()), "\n";
result += "Home Address:\n"+self.homeAddress+"\n";
result += "School Address:\n"+ self.schoolAddress;
return result;
Courseclass.py:
class Course:
def __init__(self,course,code):
self.course = course
self.code = code
def setCourseName(self,name):
self.course = name
def setCourseCode(self, code):
self.course = code
Issue is you are trying to run setTestScore function without instantiating the class. Either make it a staticmethod or call it from an object
for s in classList:
for i in range(len(classList)):
test = int(input("enter test number: "))
score = int(input("enter test score: "))
s.setTestScore(test,score)
print("\n"+s)
PS: Line
classList = [classSize]
creates a new list and adds classSize to the list as the first element. I assume you want to create a list with size of classSize. You do not need to specify length when creating lists in python.
Also,
testResults = []
this initalization is outside of init, which makes testResults a class variable, means it will be shared within all classes. I would advise you to move it inside init function
Editing upon your edit, you are trying to concat string with a tuple
result += "Average:\n", str(self.average()), "\n";
What you should do is:
result += "Average:\n" + str(self.average()) + "\n";
In python you don't need to end lines with ;
also you need to create an instance of the class and on that instance you can use the class methods
look in the code I added comments on every change
Main.py
from student import student
def studentArray():
classSize = int(input("how big is the class? "))
classList = []
num = 0
while num != classSize:
firstName = input("\nWhat's the students first name? ")
lastName = input("\nWhat's the students last name? ")
homeAddress = input("\nWhat's the students home address? ")
schoolAddress = input("\nWhat's the students school address? ")
courseName = input("\nWhat course is the students taking? ")
courseCode = input("\nWhat's the course code? ")
new_student = student(firstName, lastName, homeAddress, schoolAddress, courseName, courseCode)
classList.append(new_student)
number_of_test = int(input("\nHow many tests did the student had? "))
for i in range(number_of_test):
test = int(input("enter test number: "))
score = int(input("enter test score: "))
new_student.setTestScore(test, score)
num += 1
for s in classList:
print("\n" + str(s))
studentArray()
studentclass.py
from Course import Course
class student:
def __init__(self, first, last, home, school, courseName, courseCode):
self.firstName = first
self.lastName = last
self.homeAddress = home
self.schoolAddress = school
self.courseName = courseName
self.courseCode = courseCode
self.testResults = []
Course(courseName, courseCode)
def setTestScore(self, test, result):
if test < 0 or result < 0 or result > 100:
print("Error: Wrong test results.")
else:
self.testResults.append(result) # append to the list
def average(self):
average = 0
total = 0
for result in self.testResults:
total += result
average = total / 3.0
return str(average) # str the average
def __str__(self):
testAString = ""
for testResult in self.testResults:
testAString += str(testResult) + " " # str the testResult
result = "Student name:\n" + self.firstName + " " + self.lastName + "\n"
result += "Course name:\n" + self.courseName + "\n"
result += "Course Code: " + self.courseCode + "\n"
result += "Test results:\n" + testAString + "\n"
result += "Average:\n" + self.average() + "\n"
result += "Home Address:\n" + self.homeAddress + "\n"
result += "School Address:\n" + self.schoolAddress
return result
There are several issues with your code, most of them involve try to concatenate strings and non string types, as well as a few type errors along the way. You are also using the bitwise | instead of or which are not the same thing.
Starting with your student class:
use the actual or keyword instead of using bitwise |, it may be providing accurate results for some answers but it is not operating in the way you think it is.
in your __str__ method there are a few instances where you are trying to contatenate a string and an int.
in your setTestScores function you want to append the result to the testResults list.
Here is an example fix for those problems:
class student:
testResults = []
def __init__(self,first, last, home, school,courseName,courseCode):
self.firstName = first
self.lastName = last
self.homeAddress = home
self.schoolAddress = school
self.courseName = courseName
self.courseCode = courseCode
Course(courseName,courseCode)
def setTestScore(self,test,result):
if test < 1 or result < 0 or test > 100:
print("Error: Wrong test results.")
else:
self.testResults.append(result)
def average(self):
average = 0
total = 0
for result in self.testResults:
total += result
average = total / 3.0
return average
def __str__(self):
testAString = ""
for testResult in self.testResults:
testAString += str(testResult) + " "
result = "Student name:\n"+self.firstName + " " + self.lastName+"\n"
result += "Course name:\n"+self.courseName+"\n"
result += "Course Code: "+ self.courseCode+"\n"
result += "Test results:\n"+testAString+"\n"
result += "Average:\n" + str(self.average()) +"\n"
result += "Home Address:\n"+self.homeAddress+"\n"
result += "School Address:\n"+ self.schoolAddress
return result
Next you have the studentArray function.
you don't need to specify the size of the classList since lists can be dynamically appended to.
you need to convert your instance to a string before concatenating it with the new line character.
Here is an example fix for that.
def studentArray():
classSize = int(input("how big is the class? "))
classList = []
num=0
while not(num == classSize):
firstName = input("\nWhat's the students first name? ")
lastName = input("\nWhat's the students last name? ")
homeAddress = input("\nWhat's the students home address? ")
schoolAddress = input("\nWhat's the students school address? ")
courseName = input("\nWhat course is the students taking? ")
courseCode = input("\nWhat's the course code? ")
s = student(firstName,lastName,homeAddress,schoolAddress,courseName,courseCode)
classList.append(s)
num+=1
for s in classList:
for i in range(len(classList)):
test = int(input("enter test number: "))
score = int(input("enter test score: "))
s.setTestScore(test,score)
print("\n"+str(s))
Making these adjustments this was the output of your code.
how big is the class? 1
What's the students first name? a
What's the students last name? b
What's the students home address? 10
What's the students school address? 12
What course is the students taking? art
What's the course code? 1
enter test number: 1
enter test score: 88
Student name:
a b
Course name:
art
Course Code: 1
Test results:
88
Average:
29.333333333333332
Home Address:
10
School Address:
12
finally if you want to add more test scores you need add another question that asks how many tests were taken in the class and then iterate based on the response.
num_tests = int(input('how many tests'))
for s in classList:
for i in range(num_tests):
test = int(input("enter test number: "))
score = int(input("enter test score: "))
s.setTestScore(test,score)

Saving the output of a list to a file

I came across a project geared toward starters like myself - creating a CLI passwordcreator.
I have with the help of a few guides completed the generator and added a few of my own features, however there is one feature I can't seem to figure out how to implement; saving the output to a file.
In the terminal the passwords shows up perfectly fine line by line, however if I try to save the output to a file it only saves the last password, and it seperates each letter by line.
My code is below, together with examples of output from both the terminal and a .txt file.
import string
import random
from os import system, name
letters = list(string.ascii_letters)
digits = list(string.digits)
special_characters = list("!##$%^&*()£")
characters = list(string.ascii_letters + string.digits + '!##$%^&*()£')
def clear():
if name == 'nt':
_ = system('CLS')
else:
_ = system('clear')
def generate_random_password():
clear()
length = int(input("Enter password length: "))
amount = int(input('Enter amount of passwords: '))
letters_count = int(input("Enter letter count: "))
digits_count = int(input("Enter digits count: "))
special_characters_count = int(input("Enter special characters count: "))
character_count = letters_count + digits_count + special_characters_count
if character_count > length -1:
print("Characters total count is greater than desired password length")
exit()
clear()
password = []
print("Following passwords saved to Passwords.txt, please move the file before generating new passords, as a new generation will overwrite existing")
print('\n')
for pwd in range(amount):
password = []
for c in range(digits_count):
password.append(random.choice(digits))
for c in range(letters_count):
password.append(random.choice(letters))
for c in range(special_characters_count):
password.append(random.choice(special_characters))
if character_count < length:
random.shuffle(characters)
for c in range(length - character_count):
password.append(random.choice(characters))
random.shuffle(password)
if str(password) < str(length):
return()
else:
print("".join(password))
with open('Passowrds.txt', 'w') as file:
for line in ("".join(password)):
file.write(line)
file.write('\n')
#file = open('Passwords.txt', 'w')
#str1 = repr(password)
#file.write('\n' + str1 + '\n')
#file.close
#f = open('Passwords.txt', 'r')
#if f .mode == 'r':
# contents=f.read
generate_random_password()
This is what the output from the terminal looks like:
Following passwords saved to Passwords.txt, please move the file
before generating new passords, as a new generation will overwrite
existing
gtBVA3QDcUohDc£TfX(zVt*24
KD8PnMD£)25hvHh#3xj79$qZI
Dx^*2£srcLvRx5g3B3(nq0H&9
&r6^3MEsaV1RuDHzxq*(h3nO)
However what is saved in the .txt file looks like this:
&
r
6
^
3
M
E
s
a
V
1
R
u
D
H
z
x
q
*
(
h
3
n
O
)
The reason why your script is saving only 1 password is because you are opening the file to be written (which clears the contents of the file) for every password you are generating.
You want to do something along the lines of:
passwords = []
for _ in range(num_passwords):
password = ...
passwords.append(password)
with open("password.txt", "w") as f:
f.writelines(passwords)
Although there is nothing terrible about the way you're using the random library, I recommend taking a look at random.sample (without replacement) or random.choices (with replacement).
Also, using shuffling your characters list isn't adding additional randomness to your random.choice.
You don't have to convert the strings to lists in order to run choice:
>>> import random
>>> random.choice("abc")
'b'
A fuller example:
def generate_random_password():
clear()
length = int(input("Enter password length: "))
amount = int(input("Enter amount of passwords: "))
letters_count = int(input("Enter letter count: "))
digits_count = int(input("Enter digits count: "))
special_characters_count = int(input("Enter special characters count: "))
character_count = letters_count + digits_count + special_characters_count
if character_count > length - 1:
print("Characters total count is greater than desired password length")
exit()
clear()
passwords = []
for _ in range(amount):
chosen_digits = random.choices(digits, k=digits_count)
chosen_letters = random.choices(letters, k=letters_count)
chosen_special_characters = random.choices(
special_characters, k=special_characters_count
)
extra_characters_count = length - character_count
extra_characters = random.choices(characters, k=extra_characters_count)
password = (
chosen_digits
+ chosen_letters
+ chosen_special_characters
+ extra_characters
)
random.shuffle(password)
passwords.append("".join(password))
with open("Passwords.txt", "w") as f:
f.writelines(passwords)

Python formatting print

I'm having some formatting issues with my call to print function. For lack of knowledge of better ways to format, i've ended up with an issue. here is what it should look like
However the actual result of my print returns this.
def tupleMaker(inputString):
s1 = inputString.split()
# Adding the surname at the end of the string
s2 = [s1[len(s1) - 1]]
# Number of other names(no surname)
global noOfNames
noOfNames = len(s1) - 4
# Adding all the other names
for i in range(noOfNames):
s2.append((s1[i + 3]))
# Adding the Reg number
s2.append(s1[0])
# Adding the Degree scheme
s2.append(s1[2])
# Adding the year
s2.append("Year " + s1[1])
# Making it a tuple
t = ()
for i in range(len(s2)):
t = t + (s2[i],)
return t
def formatting(t):
s1 = ""
for i in range(len(t)):
s1 += t[i]
if (i == 0):
s1 += ", "
elif (i == len(t) - 4):
s1 += " "
else:
s1 += " "
#print(t[0] + ", ", end="")
#for i in range(noOfNames):
#print (t[i+1], end= " ")
#print(format(t[1+noOfNames], "<32s"))
#print(format(thenames, "<32d") + format(regNo, "<7d") + format(degScheme, ">6s") + format(year, ">1s")
print("")
print(s1)
I would recommend looking at using pythons built in string.format() function a small tutorial is located here: https://pyformat.info/

New Hangman Python

I am working on a Hangman game, but I am having trouble replacing the dashes with the guessed letter. The new string just adds on new dashes instead of replacing the dashes with the guessed letter.
I would really appreciate it if anyone could help.
import random
import math
import os
game = 0
points = 4
original = ["++12345","+*2222","*+33333","**444"]
plusortimes = ["+","*"]
numbers = ["1","2","3"]
#FUNCTIONS
def firstPart():
print "Welcome to the Numeric-Hangman game!"
def example():
result = ""
ori = random.choice(original)
for i in range(2,len(ori)):
if i % 2 == 0:
result = result + ori[i] + ori[0]
else:
result = result + ori[i] + ori[1]
return ori
# def actualGame(length):
#TOP LEVEL
firstPart()
play = raw_input("Do you want to play ? Y - yes, N - no: ")
while (play == "Y" and (points >= 2)):
game = game + 1
points = points
print "Playing game #: ",game
print "Your points so far are: ",points
limit = input("Maximum wrong guesses you want to have allowed? ")
length = input("Maximum length you want for the formulas (including symbols) (must be >= 5)? ")
result = "" #TRACE
ori = random.choice(original)
for i in range(2,len(ori)):
if i % 2 == 0:
result = result + ori[i] + ori[0]
else:
result = result + ori[i] + ori[1]
test = eval(result[:-1])
v = random.choice(plusortimes) #start of randomly generated formula
va = random.choice(plusortimes)
formula = ""
while (len(formula) <= (length - 3)):
formula = formula + random.choice(numbers)
formula2 = str(v + va + formula)
kind = ""
for i in range(2,len(formula2)):
if i % 2 == 0:
kind = kind + formula2[i] + formula2[0]
else:
kind = kind + formula2[i] + formula2[1]
formula3 = eval(kind[:-1])
partial_fmla = "------"
print " (JUST TO TRACE, the program invented the formula: )" ,ori
print " (JUST TO TRACE, the program evaluated the formula: )",test
print "The formula you will have to guess has",length,"symbols: ",partial_fmla
print "You can use digits 1 to 3 and symbols + *"
guess = raw_input("Please enter an operation symbol or digit: ")
a = 0
new = ""
while a<limit:
for i in range(len(formula2)):
if (formula2[i] == partial_fmla[i]):
new = new + partial_fmla[i]
elif (formula2[i] == guess):
new[i] = guess
else:
new[i] =new + "-"
a = a+1
print new
guess = raw_input("Please enter an operation symbol or digit: ")
play = raw_input("Do you want to play ? Y - yes, N - no: ")
The following block seems problematic:
elif (formula2[i] == guess):
new[i] = guess
else:
new[i] =new + "-"
Python does not allow modification of characters within strings, as they are immutable (cannot be changed). Try appending the desired character to your new string instead. For example:
elif formula2[i] == guess:
new += guess
else:
new += '-'
Finally, you should put the definition of new inside the loop directly under, as you want to regenerate it after each guess.

Categories