Can't run through a list in print function - python

I'm a beginner to python. I've written this code but I can't execute the for loop inside the print function to iterate through the list of marks:
class student:
def __init__(self, name, age, iden, lMark):
self.name=name
self.age=age
self.iden=iden
self.lMark=lMark
def printAve(self, obj):
for i in obj.lMark:
res+=i
av=res/len(lMark)
return av
def disInfo(self, obj):
print("the name is: ",obj.name)
print("the age is: ",obj.age)
print("the identity is: ",obj.iden)
print("the marks are: ", for i in lMark:
print(i))
def addStudent(self, n, a, i, l):
ob=student(n,a,i,l)
ls.append(ob)
return true
def searchStudent(self, _val):
for i in len(ls):
if ls[i]==_val:
return i
ls=[]
s=student("Paul", 23,14, list(15,16,17,20,12))
bool added = s.add("Van", 20, 12, list(12,18,14,16))
if added==True:
print("Student added successfully")
for i in range(ls.__len__())
s.disInfo(ls[i])
Can someone help me to solve this problem and explain me how to do?

You can't put a bare for loop in the argument list to print, and of course the embedded print doesn't return what it prints. What you can do is
print("the marks are:", ", ".join(lMark))
or perhaps
print("the marks are:", *lMark)
(Also, I believe you mean obj.lMark.)
To reiterate, if you call some code in the argument to print, that code should evaluate to the text you want print to produce; not do printing on its own. For example,
def pi()
return 3.141592653589793 # not print(3.141592653589793)
def adjective(arg):
if arg > 100:
return "big" # not print("big")
else:
return "small" # not print("small")
print(str(pi()), "is", adjective(pi()))
Notice how each function call returns something, and the caller does something with the returned value.

from statistics import mean
# classes are named LikeThis
# constants named LIKE_THIS
# other variables should be named like_this
# hungarian notation is not used in Python
class Student:
# instead of a global variable named ls,
# I'm using a class variable with a clear name instead
all_students = []
def __init__(self, name, age, iden, marks):
self.name = name
self.age = age
self.iden = iden
self.marks = marks
def printAve(self):
# you don't need to pass two arguments when you're only operating on a single object
# you don't need to reinvent the wheel, see the import statement above
return mean(self.marks)
def disInfo(self):
print("the name is:", self.name)
print("the age is:", self.age)
print("the identity is:", self.iden)
# you can't put a statement inside of an expression
# I'm guessing you want the marks all on the same line?
# the *args notation can pass any iterable as multiple arguments
print("the marks are:", *self.marks)
# this makes more sense as a classmethod
# clear variable names are important!
#classmethod
def addStudent(cls, name, age, iden, marks):
# I'm using cls instead of Student here, so you can subclass Student if you so desire
# (for example HonorStudent), and then HonorStudent.addStudent would create an HonerStudent
# instead of a plain Student object
cls.all_students.append(cls(name, age, iden, marks))
# note the capital letter!
return True
# again, this should be a classmethod
#classmethod
def searchStudent(cls, student):
# use standard methods!
try:
return cls.all_students.index(student)
except ValueError:
return None
# the literal syntax for lists in Python is `[1, 2, 3]`, _not_ `list(1, 2, 3)`.
# it also makes more sense to use Student.addStudent here, because just calling Student() doesn't add it
# to the list (although you could do that in __init__ if you always want to add them to the list)
Student.addStudent("Paul", 23, 14, [15, 16, 17, 20, 12])
# in Python, type annotations are optional, and don't look like they do in C or Java
# you also used `add` instead of `addStudent` here!
added: bool = Student.addStudent("Van", 20, 12, [12,18,14,16])
# don't need == True, that's redundant for a boolean value
if added:
print("Student added successfully")
# never call `x.__len__()` instead of `len(x)`
# (almost) never use `for i in range(len(x))` instead of `for item in x`
for student in Student.all_students:
student.disInfo()

First I answer your initial question, you can print a list in different ways, here are some of them.
You can iterate through it with a for loop and print every element on a different line:
for elem in self.lMark:
print(elem)
You can also append all values to a string and separate them by a character or something.
(Note: There will be a trailing space at the end.)
myString = ""
for elem in self.lMark:
myString = myString + str(elem) + " "
print(myString)
Better is this by doing it with strings-join method and a short version of the container iteration:
", ".join([str(i) for i in self.lMark])
There were some more issues in the code example.
Here is a running version of the script:
class Student:
def __init__(self, name, age, iden, lMark):
self.name=name
self.age=age
self.iden=iden
self.lMark=lMark
def printAve(self, obj):
for i in obj.lMark:
res+=i
av=res/len(self.lMark)
return av
def disInfo(self):
print("the name is: ",self.name)
print("the age is: ",self.age)
print("the identity is: ",self.iden)
print("the marks are: ", ", ".join([str(i) for i in self.lMark]))
class StudentList:
def __init__(self):
self.__list_of_students = []
def add(self, s):
self.__list_of_students.append(s)
return True
def get(self):
return self.__list_of_students
def search(self, name):
for s in self.__list_of_students:
if s.name == name:
return s
return None
ls = StudentList()
s=Student("Paul", 23,14, [15,16,17,20,12])
ls.add(s)
added = ls.add(Student("Van", 20, 12, [12,18,14,16]))
if added:
print("Student added successfully")
search_name1 = "Paula"
search_name2 = "Van"
if ls.search(search_name1):
print(search_name1, "is part of the list!")
else:
print("There is no", search_name1)
if ls.search(search_name2):
print(search_name2, "is part of the list!")
else:
print("There is no", search_name2)
for student in ls.get():
student.disInfo()
print("-"*10)
I would suggest to separate the list of students and the students to two different classes as shown in the code above.

You can unpack your list with the * operator:
print("the marks are: ", *lMark)

Try setting this as a function. i.e
def quantity():
for i in lMark:
print(i)
Then,
def disInfo(self, obj):
print("the name is: ",obj.name)
print("the age is: ",obj.age)
print("the identity is: ",obj.iden)
print("the marks are: ", + quantity)

Related

Using a class as a dictionary value in python

I'm new to to Python and could use some help. I'm trying to use several class parameters as a dictionary value and I don't know how to return the value with the class's parameter variables. Here's what I have so far:
import random
class Movie:
def __init__(self, title)
self.__title=title
def __str__(self):
return
questions={
"May the Force be with you.":Movie("Star Wars: Episode IV - A New Hope",1977,"George Lucas",["Sci-fi","Action"],121,"PG")
}
print("Here's a random selection of", 2,"questions:")
rset = random.sample(list(questions), 2)
print()
#Accumulator Start
total=0
qt=0
#Question Loop
for q in rset:
qt+=1
print("Question #",qt,":",q)
ans=input('Answer: ')
if ans.casefold()==Movie(self.__title).casefold():
print('Correct! The answer is:' ,questions[q])
print()
total+=1
else:
print("Incorrect. The answer is:", questions[q])
print()
I'd like the questions[q] to return class Movie if possible. Any suggestions?
You can't use self outside a class.
Just use questions[q] you can return a instance of Moive class, no need to return a class itself in the situation.
The attribute start with __ treat as private in python, which can't access from outside.
code:
import random
class Movie:
def __init__(self, title, releaseYear, director, genre, length, rating):
self.title=title
self.releaseYear=releaseYear
self.director=director
self.genre=genre
self.length=length
self.rating=rating
def __str__(self):
return
questions={
"May the Force be with you.":Movie("Star Wars: Episode IV - A New Hope",1977,"George Lucas",["Sci-fi","Action"],121,"PG"),
"test":Movie("test_title",1978,"test_director",["test1","test2"],99,"test_rating")
}
#Determine quantity
quantity=int(input("How many questions? "))
print()
print("Here's a random selection of", quantity,"questions:")
rset = random.sample(list(questions), quantity)
print()
#Accumulator Start
total=0
qt=0
#Question Loop
for q in rset:
qt+=1
print(f"Question # {qt}:{q}")
ans=input('Answer: ')
if ans.casefold()==questions[q].title.casefold():
print('Correct! The answer is:' ,questions[q].title.casefold())
print()
total+=1
else:
print("Incorrect. The answer is:", questions[q].title.casefold())
print()
result:
How many questions? 2
Here's a random selection of 2 questions:
Question # 1:test
Answer: a
Incorrect. The answer is: test_title
Question # 2:May the Force be with you.
Answer: Star Wars: Episode IV - A New Hope
Correct! The answer is: star wars: episode iv - a new hope
Yes, that is possible. However, Python dicts are unordered. So return the value of a dict via index does not make sense, But if you want, you can do:
value_at_index = dic.values()[index]
Instead, you will want to return the value via key, for your code:
value = questions["May the Force be with you."]
but right now, for your str method, you did not return anything. Keep in mind that str should return a string. For example you want to return the title, you code would be like:
import random
class Movie:
def __init__(self, title, releaseYear, director, genre, length, rating):
self.__title = title
self.__releaseYear = releaseYear
self.__director = director
self.__genre = genre
self.__length = length
self.__rating = rating
def __str__(self):
return self.__title
questions = {
"May the Force be with you.": Movie("Star Wars: Episode IV - A New Hope", 1977, "George Lucas",
["Sci-fi", "Action"], 121, "PG")
}
# Determine quantity
print(questions)
for keys in questions:
print(questions[keys])
Which will output:
{'May the Force be with you.': <__main__.Movie object at 0x00000268062039C8>}
Star Wars: Episode IV - A New Hope
Process finished with exit code 0

I am looking to create instances of a class from user input

I Have this class:
class Bowler:
def __init__(self, name, score):
self.name = name
self.score = score
def nameScore(self):
return '{} {}'.format(self.name, self.score)
I need to get user input until a blank line is entered. Then use the data I got to create instances of a class. I was thinking something like:
def getData():
name, score = input("Please enter your credentails (Name score): ").split()
B1 = Bowler(name, score)
print(B1.nameScore())
But then I would somehow have to loop it until I get a blank user input. Also I would somehow have to create B2 B3 B4 etc in the loop.
Sorry I am still really new to programming, maybe I am looking at this from the wrong angle.
What you're looking for are Python Lists. With these you will be able to keep track of your newly created items while running the loop. To create a list we simply defined it like so:
our_bowlers = []
Now we need to alter our getData function to return either None or a new Bowler:
def getData():
# Get the input
our_input = input("Please enter your credentails (Name score): ").split()
# Check if it is empty
if our_input == '':
return None
# Otherwise, we split our data and create the Bowler
name, score = our_input.split()
return Bowler(name, score)
and then we can run a loop, check for a new Bowler and if we didn't get anything, we can print all the Bowlers we created:
# Get the first line and try create a Bowler
bowler = getData()
# We loop until we don't have a valid Bowler
while bowler is not None:
# Add the Bowler to our list and then try get the next one
our_bowlers.append(bowler)
bowler = getData()
# Print out all the collected Bowlers
for b in our_bowlers:
print(b.nameScore())
This is my code to do what you want:
class Bowler:
def __init__(self, name, score):
self.name = name
self.score = score
def nameScore(self):
return '{} {}'.format(self.name, self.score)
def getData():
try:
line = input("Please enter your credentails (Name score): ")
except SyntaxError as e:
return None
name, score = line.split()
score = int(score)
B = Bowler(name, score)
print(B.nameScore())
return B
if __name__ == '__main__':
bowlers = list()
while True:
B = getData()
if B == None:
break
bowlers.append(B)
for B in bowlers:
print(B.nameScore())
In addition, I recommend you to modify your input for it's inconvenient now

Boolean attribute in python object

It requires isgood to be a string only. I want it to be boolean.
Also self.__isgood = goodornot should throw an error, why not?
class Animal:
Name = ""
isgood = None
def setisgood(self,goodornot):
self.__isgood = goodornot
def nameset(self,name):
self.Name = name
dog = Animal()
dog.setisgood(False)
dog.nameset("jaang")
print("Your pet is:"+dog.isgood)
So then convert it to a string.
print("Your pet is: {}".format(dog.isgood))
print("Your pet is:"+dog.isgood)
is attempting to concatenate a boolean and a string, which cannot be done. In order to do so, you either need to convert dog.isgood into a string
print("Your pet is:" + str(dog.isgood))
like TheoretiCAL suggested in the comments, or use format
print("Your pet is:{}".format(dog.isgood))
like Ignacio Vazquez-Abrams answer, or
print("Your pet is:%s" % dog.isgood)
or,
print("Your pet is:", dog.isgood)
All of these examples will result in the following output:
Your pet is:False
Edit:
Thank you juanpa for pointing this out. The spacing on the class is incorrect and should be causing an issue (I guess I assumed initially that it was just a copy paste thing).
class Animal:
def __init__(self):
self.Name = ""
self.isgood = None
def setisgood(self,goodornot):
self.isgood = goodornot
def nameset(self,name):
self.Name = name
dog = Animal()
dog.setisgood(False)
dog.nameset("jaang")
print("Your pet is:", dog.isgood)

How can I turn a user input into a global function? (Python)

I'm trying to create my own text game, as instructed in Ex 45 of Learning Python the Hard Way, but I'm a bit stuck. I have my own inventory system set up and I need to figure out how to display a list of the inventory any time the user types "inventory" (I also want to do similar things for "help")... I know that I could add an if-statement after every raw_input for it, but I wanted to see if there was some global function or code that I could use to make this a lot easier on me.
I've searched and searched but I have no idea how to phrase the question or what I could possibly do to fix this. Here's my inventory set-up, with how I'm using to call it:
class Item(object):
def __init__(self, name, quantity=1):
self.name = name
self.raw = name.strip().lower()
self.quantity = quantity
def recalc(self):
self.netValue = self.quantity * self.value
class Container(object):
def __init__(self, name):
self.name = name
self.inside = {}
def __iter__(self):
return iter(self.inside.items())
def __len__(self):
return len(self.inside)
def __contains__(self, item):
return item.raw in self.inside
def __getitem__(self, item):
return self.inside[item.raw]
def __setitem__(self, item, value):
self.inside[item.raw] = value
return self[item]
def add(self, item, quantity=1):
if quantity < 0:
print "ERROR."
if item in self:
self[item].quantity += quantity
self[item].recalc()
else:
self[item] = item
inventory = Container("Inventory")
And here's what I'm using to call it when inventory is typed:
print "Inventory: [" + ",".join((item[1].name for item in inventory)) + "]"
You could create a function for each valid user input, such as inventory
Then, you could do:
input = raw_input('...')
self.method = getattr(<your class>, input)
self.method()
which would call
def inventory(self, ...):
pass
you could use a dictionary combined with lambdas, this would be compact and fast
from __future__ import print_function
#store commands
inputLookup = {"Inventory" : lambda: print ("Inventory: [" + ",".join((item[1].name for item in inventory)) + "]"), "other text" : lambda: 3} #and so on
text = input() #replace with hover you get input
inputLookup[text]() # call the function from dictionary at that command
the import will change all your print statements to a print() however.
For lambdas you can also do.
def f():
print "Inventory: [" + ",".join((item[1].name for item in inventory)) + "]"
inputLookup = {"Inventory": lambda: f()}
text = input()
try:
inputLookup[text]
except:
print "that is not a valid input" #or something
this will allow you to use the old print statment
yes, you should never use recursion to the same function in this manner, you'll generate a large stack. Also, those print statements are in a weird place.
def func1():
print "Uh oh."
print "You're outside the house and it's quiet."
print "You EXAMINE and find a ROCK."
While True:
userinput1 = raw_input(">>> ")
if userinput1 == "inventory":
print "Inventory: [" + ",".join((item[1].name for item in inventory)) + "]"
elif userinput1 == "pick up":
if rock not in inventory: # so they can't pick up infinite rocks
inventory.add(rock)
print "You picked up a ROCK."
else:
print "you've already picked up the rock"
elif userinput1 == "examine":
print "Man's best friend."
else:
print "Let's go on about our way then."
break
I failed to see you were just starting out. I would stay away from lambda's for the moment, as they're a bit more advanced, sorry for the confusion. Before, if you look at your if/elif/else tree, there was no way for the else statement to be called, so i've edited it a bit, i hope it functions the way you intended. Also, are inventory and rock globals? if not you would need to declare or reference them in the function. (although as a future note, staying a way from globals is generally good)
hmm...i assume you mean items like the rock and such.
Items = {'rock': Rock(), 'item2': Item2(), 'item3' : item3()} #where Item() is creating the object
Inventory.add(Items[itemname]) # adds the item
You could make Items as a global so you can access it everywhere. This is ok for now, but as you learn, you should generally stay away from globals.

Global Name Not Defined in Python

Am new to Python OOP. Please dont be harsh. Here is my code which calculates which is the fastest time of an athlete from a list and displays them. But When Running, I get this error:
z= add.mylist.min()
NameError: global name 'add' is not defined
My Code:
class Athlete:
def add(self):
list=[]
mylist=[]
for i in range(2):
self.name = raw_input("Enter name: ")
self.fastest_time = input("time: ")
list.append(self.name)
mylist.append(self.fastest_time)
print "Names: ",list
print "Fastest times: ",mylist
def display(self):
z= add.mylist.min()
w= add.mylist.index(z)
print "Minimum time: ",z
print "Name of athelte with fastest time: ",list[w]
x = Athlete()
x.add()
x.display()
You need to refer to methods on the instance with the self parameter. In addition, your add() method needs to return the mylist variable it generates, you cannot refer to method local variables as attributes on methods:
def display(self):
mylist = self.add()
z = min(mylist)
w = mylist.index(z)
def add(self):
list=[]
mylist=[]
for i in range(2):
self.name = raw_input("Enter name: ")
self.fastest_time = input("time: ")
list.append(self.name)
mylist.append(self.fastest_time)
print "Names: ",list
print "Fastest times: ",mylist
return mylist
That is what self is for, as a reference point to find instance attributes and other methods on the same object.
You may want to rename list to something that does not shadow the built-in type.
Martijn has already answered your question, so here are some remarks and code style tips:
New-style classes derive from object
You have both athlete names and their times, those belong together as key-value pairs in a dictionary instead of two separate lists
Don't use print statements inside class methods, a class method should return an object that you then can print
what if you have more then 2 athletes for which you want to enter the time? If you make the number of athletes an argument of your function, you can add a variable number of athlethes
give descriptive variable names (not mylist) and don't use names of builtin functions (like list) as variable name
variables that you want to use throughout your class can be initalized in an __init__method.
For printing, use the format function instead of using commas
use if __name__ == '__main__' so that your Python file can act as either reusable modules or as standalone program
Taking these into account, I would rewrite your code to something like this:
from collections import defaultdict
class Athlete(object): # see (1)
def __init__(self): # see (6)
self.athlete_times = defaultdict(str) # see (2)
def add_athletes_and_times(self, n): # see (4)
for i in range(n):
self.name = raw_input("Enter name: ")
self.fastest_time = input("time (in seconds): ")
self.athlete_times[self.fastest_time] = self.name
def get_fastest_time(self):
return min(self.athlete_times) # see (3)
if __name__ == '__main__': # see (8)
x = Athlete()
x.add_athletes_and_times(2)
for fast_time in x.athlete_times:
print "The fastest time of athlete {0} is {1} seconds.".format(
x.athlete_times[fast_time], fast_time) # see (7)
fastest_time = x.get_fastest_time()
print "The overall fastest time is: {0} seconds for athlete {1}.".format(
fastest_time, x.athlete_times[fastest_time])

Categories

Resources