Trouble defining user inputs in functions - python

I'm following the Microsoft introduction to Python course for beginners on edX, I'm having trouble in their second module where they ask you to create function that adds the "Doctor" title to a user inputted name.
This is the advice they provide:
Define function make_doctor() that takes a parameter name
get user input for variable full_name
call the function using full_name as argument
print the return value
create and call make_doctor() with full_name argument from user input - then print the return value
This is what I have so far:
def make_doctor(name):
full_name = print("Doctor" + input().title())
return full_name
print(name)
Would appreciate any help.

Python is an off-side rule language:
Python Reference Manual (link)
Leading whitespace (spaces and tabs) at the beginning of a logical
line is used to compute the indentation level of the line, which in
turn is used to determine the grouping of statements.
In contrast to others such as curly-bracket languages, indentation is (generally) not stylistic, but required in order to group statements. Therefore, your code should look like this:
def make_doctor(name):
return "Doctor" + name
full_name = input()
print(make_doctor(full_name))

def make_doctor(name):
# add the Doctor title to the name parameter
d_name = 'Doctor '+name
# print the return value
print(d_name)
return d_name
# get the user input for the variable full_name
full_name=input('Enter your full name: ')
# pass full_name as an argument to make_doctor function
doc = make_doctor(full_name)
# print return value
print(doc)

def make_doctor(name):
full_name = input()
return full_name
print('Doctor ' + full_name)

Related

Hello, when i try to print from my class, i get this error:

Code:
class Passangers():
def __init__(self, passangerNames, nationalities, age, gender):
self.passangerNames = passangerNames
self.nationalities = nationalities
self.age = age
self.gender = gender
def data_base_update(self):
passanger_list = self.passangerNames + " " + self.nationalities + " " + self.age + "" + self.gender
passangers_return = Passangers("fdgfdg", "dfgdfgdf", "dfgfdg", "dfgfdgff",)
print(passangers_return.data_base_update)
Error:
<bound method Passangers.data_base_update of <__main__.Passangers object at 0x00000241A2467C70>>
I get this, but i dont get the print message
Make sure you actually call the method. The way you are doing it, you are just referencing the function object. Instead do, print(passangers_return.data_base_update())
In addition, if you are wanting to get passanger_list back from the function, add return passanger_list at the bottom of the function. Or you can return the string directly by placing the string concatenation you assigned to passanger_list directly after return. To continue, you should use f-strings. They allow you to embed variables and expressions inside strings: return f"{self.x=}" for example.
For your case:
def data_base_update(self):
return f"{self.passangerNames} {self.nationalities} {self.age} {self.gender}"
Pro Tip
You can use __str__ (or __repr__) to display the string representation of your object!
def __str__(self):
return f"{self.passangerNames} {self.nationalities} {self.age} {self.gender}"
Now you can just pass your variable holding the instance to print and get the return value from __str__ (or __repr__) as output!

How to print actual name of variable class type in function?

I'm trying to return variable name, but i keep getting this:
<classes.man.man object at (some numbers (as example:0x03BDCA50))>
Below is my code:
from classes.man import man
def competition(guy1, guy2, counter1=0, counter2=0):
.......................
some *ok* manipulations
.......................
if counter1>counter2:
return guy1
bob = man(172, 'green')
bib = man(190, 'brown')
print(competition(bob , bib ))
Epilogue
If anyone want to, explain please what I can write instead of __class__ in example below to get variable name.
def __repr__(self):
return self.__class__.__name__
Anyway, thank you for all of your support
There are different ways to approach your problem.
The simplest I can fathom is if you can change the class man, make it accept an optional name in its __init__ and store it in the instance. This should look like this:
class man:
def __init__(number, color, name="John Doe"):
self.name = name
# rest of your code here
That way in your function you could just do with:
return guy1.name
Additionnally, if you want to go an extra step, you could define a __str__ method in your class man so that when you pass it to str() or print(), it shows the name instead:
# Inside class man
def __str__(self):
return self.name
That way your function could just do:
return guy1
And when you print the return value of your function it actually prints the name.
If you cannot alter class man, here is an extremely convoluted and costly suggestion, that could probably break depending on context:
import inspect
def competition(guy1, guy2, counter1=0, counter2=0):
guy1_name = ""
guy2_name = ""
for name, value in inspect.stack()[-1].frame.f_locals.items():
if value is guy1:
guy1_name = name
elif value is guy2:
guy2_name = name
if counter1 > counter2:
return guy1_name
elif counter2 > counter2:
return guy1_name
else:
return "Noone"
Valentin's answer - the first part of it at least (adding a name attribute to man) - is of course the proper, obvious solution.
Now wrt/ the second part (the inspect.stack hack), it's brittle at best - the "variables names" we're interested in might not necessarily be defined in the first parent frame, and FWIW they could as well just come from a dict etc...
Also, it's definitly not the competition() function's responsability to care about this (don't mix domain layer with presentation layer, thanks), and it's totally useless since the caller code can easily solve this part by itself:
def competition(guy1, guy2, counter1=0, counter2=0):
.......................
some *ok* manipulations
.......................
if counter1>counter2:
return guy1
def main():
bob = man(172, 'green')
bib = man(190, 'brown')
winner = competition(bob, bib)
if winner is bob:
print("bob wins")
elif winner is bib:
print("bib wins")
else:
print("tie!")
Python prints the location of class objects in memory if they are passed to the print() function as default. If you want a prettier output for a class you need to define the __repr__(self) function for that class which should return a string that is printed if an object is passed to print(). Then you can just return guy1
__repr__ is the method that defines the name in your case.
By default it gives you the object type information. If you want to print more apt name then you should override the __repr__ method
Check below code for instance
class class_with_overrided_repr:
def __repr__(self):
return "class_with_overrided_repr"
class class_without_overrided_repr:
pass
x = class_with_overrided_repr()
print x # class_with_overrided_repr
x = class_without_overrided_repr()
print x # <__main__.class_without_overrided_repr instance at 0x7f06002aa368>
Let me know if this what you want?

Accessing instance variables, AttributeError

I have a few related questions about instance variables in Python. I will put the first (main) question in a comment inside the code itself and ask the related ones afterwards:
class Employee:
def __init__(self, first, last, pay):
self.first = first
self.last = last
self.email = first + '.' + last + '#email.com'
self.pay = pay
def fullname(self):
return '{} {}'.format(self.first, self.last)
#classmethod
def from_string(cls, emp_str):
first, last, pay = emp_str.split(',')
return cls(first, last, pay)
emp_str_1 = 'John,Doe,70000'
emp_1 = Employee.from_string(emp_str_1)
print(emp_1.fullname(), emp_1.pay, emp_1.email) #<--- This works
print(emp_1.fullname().pay.email) #<--- Why can't I do this??
Also, why is it called a "str object" by the error message:
AttributeError: 'str' object has no attribute 'pay'
Isn't emp_1 an instance of Employee?
Last question, (this may just be a PyCharm issue) PyCharm does not attempt to warn me that this code will break before I try and run it, why?
In Python, concatenation can be done using +
print(emp_1.fullname(), emp_1.pay, emp_1.email) # THIS WILL WORK,
because you are just passing Strings. [ NOT RELATED to this question, just additional info : In case if you integers or boolean to print, then it will fail unless you explicitly typecast it with str())
print(emp_1.fullname().pay.email) # THIS IS NOT WORKING,
because '.' operator is used to access instance methods and variables.
If you use, emp_1.fullname(), it is calling the fullname() method which is returning some string.
But if you use emp_1.fullname().pay - emp_1.fullname() is a call to the Method and fullname() method doesn't have any variables like 'pay'. So the correct way to use is emp_1.pay.
I would suggest to use print like,
print("Name :{}:, Pay :{}: , Mail :{}:".format(emp_1.fullname(), emp_1.pay, emp_1.email)) # BECAUSE format will typecast in case if your pay is INTEGER OR FLOAT

Writing dictionary output to file - Python

I have a small program to track monthly balances. This worked fine as is, and then I added in the section to write to a .txt file at the bottom. I did some searching but can't figure out a way to make it work. Basically I want to keep appending to this test.txt file. Every time I enter a new month/account/balance I want that appended to the file.
The alternative is to append to the test.txt file after 'exit', so it doesn't do it every loop. Not sure which way is more efficient
***EDIT****
This updated code now creates test.txt file but the file is blank after each loop
Secondary question - I have heard this would be better off using a Class for this, but I haven't any idea how that would look. If someone wants to demonstrate that would be awesome. This isn't homework, this is strictly learning on my own time.
Any ideas? Thanks
# create program to track monthly account balances
savings = []
def add_accounts(date, account, balance):
savings.append({'date': date, 'account': account, 'balance':
balance})
def print_accounts():
print(savings)
while True:
date = input('Enter the date, type exit to exit program: ')
if date == 'exit':
break
account = input('Enter the account: ')
balance = int(input('Enter the balance: '))
add_accounts(date, account, balance)
print_accounts()
with open('test.txt', 'a') as f:
for row in savings():
print (row)
f.write(str(savings[-1]))
file.close()
The problem with your original code is that print_accounts() doesn't return anything, yet you attempt to perform operations on its (nonexistent) return value.
Here is a version of your program made using classes, and with a few corrections:
class Account:
def __init__(self, id, date, balance):
self.id = id
self.date = date
self.balance = balance
def getString(self):
return self.id + "," + self.date + "," + str(self.balance)
savings = []
def add_account(date, account, balance):
savings.append(Account(date, account, balance))
def print_accounts():
for account in savings:
print(account.getString())
while True:
date = input("Enter the date, type exit to exit program: ")
if date.lower() == "exit":
break
else:
account = input('Enter the account: ')
balance = int(input('Enter the balance: '))
add_account(date, account, balance)
print_accounts()
with open("test.txt", "w") as file:
for account in savings:
file.write(account.getString() + "\n")
Some explanation regarding the class: The Account class has 3 fields: id, date, and balance. These fields are defined in the constructor (__init__()). The class also has a method, getString(), which I use to get the string representation of each instance.
Over all, the following changes have been made:
Create an Account class, which serves as the template for the object which holds the data of each account.
Use a loop to print accounts and write them to the file.
Turn date into lowercase before checking to see if it is equal to "exit". This is a minor change but a good habit to have.
Removed f.close(), as it is unnecessary when using a with open() statement.
Created a custom string representation of each instance of Account, consistent with what you would otherwise get.
That last one is achieved via defining the getString method in the account class. There is nothing special about it, it is merely what we use to get the string representation.
A better but quite more advanced way to achieve that is by overriding the __str__ and __repr__ methods of the base object. These are essentially hidden functions that every class has, but which python defines for us. The purpose of these two specific ones is to give string representations of objects. The default code for them doesn't produce anything meaningful:
<__main__.Account object at 0x0000000003D79A58>
However, by overriding them, we can use str() on instances of Account, and we will get a string representation in the exact format we want. The modified class will look like so:
class Account:
def __init__(self, id, date, balance):
self.id = id
self.date = date
self.balance = balance
def __repr__(self):
return self.id + "," + self.date + "," + str(self.balance)
def __str__(self):
return self.__repr__()
This also eliminates the need to loop through savings when writing to the file:
with open("test.txt", "w") as file:
for account in savings:
file.write(account.getString() + "\n")
Turns into:
with open("test.txt", "w") as file:
file.write(str(savings))
This wouldn't have worked before, as str() would have given us the gibberish data you saw earlier. However, now that we have overridden the methods, it works just fine.
Try this code (use -1 to exit):
savings = []
def add_accounts(date, account, balance):
savings.append({'date': date, 'account': account, 'balance':
balance})
def print_accounts():
print(savings)
while True:
date = input('Enter the date, type exit to exit program: ')
if date == -1:
break
account = input('Enter the account: ')
balance = int(input('Enter the balance: '))
add_accounts(date, account, balance)
print_accounts()
with open('test.txt', 'a') as f:
for row in savings:
print (row)
f.write(str(savings[-1]))
f.close()

Using Input in User Defined Functions!(Python)

I am wondering, is there a way to use the input() function inside a user-defined function? I tried doing this
def nameEdit(name):
name = input()
name = name.capitalize
return name
Using input is fine. However, you aren't calling name.capitalize; you're just getting a reference to the method and assigning that to name. [Further, as pointed out by Bob, your function doesn't need a name argument.] The correct code would be
def nameEdit():
name = input()
name = name.capitalize()
return name
or more simply:
def nameEdit():
return input().capitalize()
Are you talking about asking for input from a user from a method? If so then this would be what you're looking for:
def nameEdit():
name = input("Enter your name: ")
name = name.capitalize()
return name

Categories