function call behaves differently in a class vs w/o class in python3 - python-3.x

Here is my code:
#Check if the value has only allowed characters
def checkStr(value):
return (set(value) <= allowed)
#Enter parameter
def enterParam (msg)
value=input(msg)
if len(value) == 0:
print("Cannot be empty, try again")
enterParam(msg)
if not checkStr(value):
print("incorrect symbols detected, try again")
enterParam(msg)
return value
Now my question is:
This works OK inside the body of the script, but as soon as i put inside a class like below the eclipse/pydev starts complaining about enterParam and checkStr not being defined. What am i doing wrong?
class ParamInput:
#Check if the value has only allowed characters
def checkStr(self, value):
return (set(value) <= allowed)
#Enter parameter
def enterParam (self, msg)
value=input(msg)
if len(value) == 0:
print("Cannot be empty, try again")
enterParam(msg) #<==== not defined
if not checkStr(value): #<====not defined
print("incorrect symbols detected, try again")
enterParam(msg) #<====not defined
return value

You need to call the methods as self.enterParam() and self.checkStr().
(Also note that the Python style guide PEP 8 recommends to name methods like enter_param() and check_str() -- CamelCase is only used for class names in Python.

Related

Why print function doesn't work in method: get_details() and None is returned for print(x.increment_odometer)?

class Car:
def __init__(self,make,model,year):
self.make=make
self.model=model
self.year=year
self.odometer_reading=0
def get_details(self): #SELF allows access of attributes and methods of a class
details=print((f'The make is: {self.make}, the model is: {self.model}, & the year is: {self.year}\n'))
#return details without print function works? i.w. details=rest of the line without print + return details (next line)
def read_odometer(self): #reading the value (default)
print(f'\nReading: {self.odometer_reading}')
def update_odometer(self,mileage):
if mileage>=self.odometer_reading:
print('\nReading has been changed')
self.odometer_reading=mileage
else:
print('\nCan, not change ')
def increment_odometer(self,miles):
self.odometer_reading+=miles
x.get_details() #trying to modify print(x.get_details()) which does work. Why does print need to be supplied here?
#incrementing the odometer
print(x.increment_odometer(50)) #why is this none?
I am learning classes and am confused about some aspects:
Why is "return details" line needed for method get_details()? Normally a simple function call having def f(): print('a') works, hence the confusion.
print(x.increment_odometer(50)) is None. Perhaps a function return needed in increment_odometer() method?
Confusing points having been commented in the code. Please englighten me.
Sincerely.

I am new to python coding and i do not understand how to use a variable from another method

Here is what i have tried:
I do not understand how can i use a variable from another method of same class. Also please explain how can i use a variable from a method in different class. I tried searching but could not find a solution. So what i did to pass the test cases is to copy code from calculate_percentage and paste it in find_grade method. It worked but i think this is the worst method. So please tell a possible solution.
Thanks
#!/bin/python3
#Enter your code here. Read input from STDIN. Print output to STDOUT
class Student:
def __init__(self,roll,name,marks_list):
self.roll=roll
self.name=name
self.marks_list=marks_list
def calculate_percentage(self):
length=len(self.marks_list)
sum=0
for i in self.marks_list:
sum+=i
percent=sum/length
return int(percent)
def find_grade(self,percent):
if percent>=80:
return 'A'
elif percent>=60 and percent<80:
return 'B'
elif percent>=40 and percent<60:
return 'C'
elif percent<40:
return 'F'
if __name__ == '__main__':
roll=int(input())
name=input()
count=int(input())
marks=[]
for i in range(count):
marks.append(int(input()))
s=Student(roll,name,marks)
print(s.calculate_percentage())
print(s.find_grade())
i am getting the error:
print(s.find_grade())
TypeError: find_grade() missing 1 required positional argument: 'percent'
Thanks for every one who answered but i found the answer:
i just need to put self.percent
or percent=self.calculate_percentage() to call the method and use the variables
The assumption would be that the marks are x/100 scale while otherwise your percentage will be incorrect.
As said above, you need to pass the variable percent back to the function since it is not known in the class, it is only returned.
print(s.find_grade(s.calculate_percentage()))
or if the percentage is a class variable you can rewrite it into the class like this:
from statistics import mean
class Student2:
def __init__(self,roll,name,marks_list):
self.roll=roll
self.name=name
self.marks_list=marks_list
def calculate_percentage(self):
self.percent=mean(marks)
return int(self.percent)
def find_grade(self):
if self.percent>=80:
return 'A'
elif self.percent>=60 and self.percent<80:
return 'B'
elif self.percent>=40 and self.percent<60:
return 'C'
elif self.percent<40:
return 'F'
percent = int(0)
# test variables
vRoll = 2
vName = 'student'
vCount= 2
vMarks= [100, 75]
# main
if __name__ == '__main__':
roll=vRoll
name=vName
count=vCount
marks=vMarks
s2=Student2(roll,name,marks)
print(s2.calculate_percentage()) # 87
print(s2.find_grade()) # A

It asks to give the values but instead of giving an answer. It is giving me None

Here I created a module.
class Employee:
def __init__(self):
self.name = input("Enter your name: ")
self.account_number = int(input("Enter your account number: "))
def withdraw(self): # it receives values from for
if withdraw1 > current_balance:
print ("You have entered a wrong number: ")
else:
print ("The current balance is: ", current_balance - withdraw1)
import TASK2 # I am importing the module I created
c = TASK2.Employee()
def for(self):
c.withdraw1 = int(input("enter number: "))
c.current_balance = int(input("Enter the current balance: "))
d = method(c.withdraw) # here I am trying to pass the values to withdraw
print (d)
The problem I get is that although it asks for the values instead of giving me an answer it gives me None.
Here's my take on your code.
# TASK2.py
class Employee:
def __init__(self):
self.name = input("Enter your name: ")
self.account_number = int(input("Enter your account number: "))
# make sure you initialise your member variables!
self.withdraw_val = 0 # withdraw1 is ambiguous, so I use withdraw_val instead
self.current_balance = 0
# receives values from for ### no it doesn't, right now, it GIVES values TO your "for" function
def withdraw(self):
if self.withdraw_val > self.current_balance: # remember to use "self." to
# access members within the class
print ("You have entered a wrong number: ")
else:
# again, remember "self."
print ("The current balance is: ", self.current_balance - self.withdraw_val)
# TASK2sub.py
import TASK2
c = TASK2.Employee()
def for_employee(employee): # (1) don't use "self" outside a class
# it's contextually unconventional
# (2) "for" is a keyword in Python, don't use it for naming
# variables/functions, it'll mess things up
employee.withdraw_val = int(input("Enter value to withdraw: "))
employee.current_balance = int(input("Enter the current balance: "))
return employee.withdraw_val # not entirely sure what you want to return
# but you should definitely return something
# if you're going to assign it to some variable
d = for_employee(c.withdraw()) # "for_employee" function needs a return statement
# ".withdraw()" method should also require a return statement
print(d)
Note: I'll be referring to your original for function as for_employee from now on. Also note that I'm still hazy about what you're trying to accomplish and that there is most probably a more suitable name for it.
Since your original for_employee function didn't return anything, it returns None by default. (This explains the output you saw.)
I think you're misunderstanding how functions work in general. For example,
d = for_employee(c.withdraw())
print(d)
Your comment for the .withdraw() method is inaccurate.
"it receives values from for"
More accurately, c.withdraw() will first be computed, then whatever it returns is passed into the for_employee function as a parameter. Instead of "receiving values from", the withdraw method "gives values to" the for_employee function.
Something more reasonable would be
c.withdraw() # on a line by itself, since it doesn't return anything
d = for_employee(c) # pass the entire object, since you'll be using self.withdraw_val and whatnot
print(d)
Another issue is with conventional naming. This is what I get from the IDLE (with Python 3.7) when defining a function named for
>>> def for(a): return a
SyntaxError: invalid syntax
Again, for is a keyword in Python, don't use it for naming your variables, functions, or classes.
With self, it's less severe (but I could see that it's confusing you). self is more of a convention used in class methods. But for_employee isn't a class method. So conventionally speaking, the parameter shouldn't be named self.
(I find the code spaghetti-ish, it might benefit if you refactor the code by moving the for_employee method into the class itself. Then it would completely make sense to use self.)

how to pass many arguments through a command function (do_)

I want to code a simple command that could take 3 arguments for a text adventure game.
Basically at the prompt, I would type 'use key unlock door' and it would run a particular block.
Here is what I coded but it does not work:
def do_use(self, tool, action, object):
if tool == 'key':
if action == 'unlock':
if object == 'door':
print("seems like it works!")
else:
print("nope 1")
else:
print("nope 2")
else:
print("nope 3")
Notes: the rest of the commands work fine. I imported cmd
and the following is the main code:
class Game(cmd.Cmd):
def __init__(self):
cmd.Cmd.__init__(self)
....
if __name__ == "__main__":
g = Game()
g.cmdloop()
At the prompt, when I type:
>>> use key unlock door
I get the following error message:
TypeError: do_use() takes exactly 4 arguments (2 given)
The code would work if it would print:
seems like it works!
Any help will be appreciated.
Reading that documentation, it looks like all of the commands just take in a single string, and you have to parse the string yourself. Your command is defined as taking 4 arguments (including self), and cmd is calling it with self, input, which is 2. I think could get the result you want with the following:
def do_use(self, user_input):
args = user_input.split()
if len(args) != 3:
print "*** invalid number of arguments"
else:
tool, action, obj = args
# Do the rest of your code here

Defining six functions and printing an output in python

So the problem is to define these six functions
def sphereVolume(r):
def sphereSurface(r):
def cylinderVolume(r,h):
def cylinderSurface(r,h):
def coneVolume(r,h):
def coneSurface(r,h):
And the write a program that prompts the user for the values of r and h, call the six functions, and print the results.
I have not tested this code because I am on a computer currently that does not have scite or python, however I've created this code on a notepad.
from math import pi
def sphereVolume():
volume1=((4/3)*pi*r)**3))
return volume1
def sphereSurface():
area1=(4*pi*r**2)
return area1
def cylinderVolume():
volume2=(pi*r**2*h)
return volume2
def cylinderSurface():
area2=(2*pi*r**2+2*pi*r*h)
return area2
def coneVolume():
volume3=((1/3)*pi*r**2*h)
return volume3
def coneSurface():
area3=(pi*r+pi*r**2)
return area3
main():
def main():
r=int (input("Enter the radius:"))
h=int (input("Enter the heights:"))
print ("Sphere volume:",sphereVolume(r),volume1)
print ("Sphere Surface:",sphereSurface(r),area1)
print ("Cylinder Volume:" , cylinderVolume(r,h),volume2)
print ("Cylinder Surface:",cylinderSurface(r,h),area2)
print ("Cone Volume:",coneVolume(r,h),volume3)
print ("Cone Surface:",coneSurface(r,h),area3)
Am I using the functions properly? Or is there a lot that I need to change?
There are many syntax errors in your code:
volume1=((4/3)*pi*r)**3)) (You don't need extra bracket at the end)
main(): (You called this function before you declared it, only call it after you've declared it and given it attributes)
print ("Sphere volume:",sphereVolume(r),volume1)
print ("Sphere Surface:",sphereSurface(r),area1)
print ("Cylinder Volume:" , cylinderVolume(r,h),volume2)
print ("Cylinder Surface:",cylinderSurface(r,h),area2)
print ("Cone Volume:",coneVolume(r,h),volume3)
print ("Cone Surface:",coneSurface(r,h),area3)
At first glance, this may all look right, however for each function you print, you give it a set of arguments that aren't meant to be there (e.g sphereVolume has the argument r). They shouldn't be there because you programmed them NOT to take in arguments, so you should change your functions to take in the arguments, otherwise you get the error:
print ("Sphere volume:",sphereVolume(r),volume1)
TypeError: sphereVolume() takes 0 positional arguments but 1 was given
So your functions should look like this:
from math import pi
def sphereVolume(r):
volume1=((4/3)*pi*r)**3
return volume1
def sphereSurface(r):
area1=(4*pi*r**2)
return area1
def cylinderVolume(r,h):
volume2=(pi*r**2*h)
return volume2
def cylinderSurface(r,h):
area2=(2*pi*r**2+2*pi*r*h)
return area2
def coneVolume(r,h):
volume3=((1/3)*pi*r**2*h)
return volume3
def coneSurface(r,h):
area3=(pi*r+pi*r**2)
return area3
You need to give them a set of arguments to work with, otherwise it's incorrect to put the variable r and h inside the functions, because- in simple terms- they haven't been given permission to be there.
Finally, you need to remove the extra variables you got from your functions that you printed out in main(). As they are local variables you can't access them unless they are returned. I'm guessing what you tried to do is that you wanted for instance in this line
print ("Sphere volume:",sphereVolume(r),volume1)
to print the value of volume1. You've already done that! When you said return volume1 at the end of the function, that meant if ever you print this function elsewhere, the only argument that will be accessed from the function is the one you returned, which in this case is volume1. Do the same likewise for all the other local variables you tried printing out by deleting them.
I've tested this code, but just so you don't have to look at everything I wrote if you don't want to, the fully working code is this:
from math import pi
def sphereVolume(r):
volume1=((4/3)*pi*r)**3
return volume1
def sphereSurface(r):
area1=(4*pi*r**2)
return area1
def cylinderVolume(r,h):
volume2=(pi*r**2*h)
return volume2
def cylinderSurface(r,h):
area2=(2*pi*r**2+2*pi*r*h)
return area2
def coneVolume(r,h):
volume3=((1/3)*pi*r**2*h)
return volume3
def coneSurface(r,h):
area3=(pi*r+pi*r**2)
return area3
def main():
r=int (input("Enter the radius:"))
h=int (input("Enter the heights:"))
print ("Sphere volume:",sphereVolume(r))
print ("Sphere Surface:",sphereSurface(r))
print ("Cylinder Volume:" , cylinderVolume(r,h))
print ("Cylinder Surface:",cylinderSurface(r,h))
print ("Cone Volume:",coneVolume(r,h))
print ("Cone Surface:",coneSurface(r,h))
main()
You need to add arguments to your functions for r and h.
You have an extra paren for:
volume1=((4/3)*pi*r)**3))
You need to fix:
main():

Resources