How to use a String Input as a Variable Call In Python? - python

item =["Item_name","Price"]
stop = input("Enter your message: ")
if stop[:3] == "add":
item2 = stop[4:]
I have a code something like this and I want to get the variable item based on a user input. For example, the user types inputs "add item", it should output item[0] and item[1], but I don't know how to do it.

Breaking it down into small pieces is the easiest way to keep it from getting out of hand when you need to add more commands -- trying to parse a command string with slices is going to get complicated quickly! Instead, try splitting the command into words, and then associating each word with the thing you want to do with it.
from enum import Enum
from typing import Callable, Dict
class Command(Enum):
"""All the commands the user might input."""
ADD = "add"
# other commands go here
class Parameter(Enum):
"""All the parameters to those commands."""
ITEM = "item"
# other parameters go here
item = ["Item_name","Price"]
def add_func(param: Parameter) -> None:
"""Add a thing."""
if param == Parameter.ITEM:
print(item)
COMMAND_FUNCS: Dict[Command, Callable[[Parameter], None]] = {
"""The functions that implement each command."""
Command.ADD: add_func,
}
# Get the command and parameter from the user,
# and then run that function with that parameter!
[cmd, param] = input("Enter your message: ").split()
COMMAND_FUNCS[Command(cmd)](Parameter(param))

Related

Input from user to print out a certain instance variable in python

I have created a class with programs:
class Program:
def __init__(self,channel,start, end, name, viewers, percentage):
self.channel = channel
self.start = start
self.end = end
self.name = name
self.viewers = viewers
Channel 1, start:16.00 end:17.45 viewers: 100 name: Matinee:The kiss on the cross
Channel 1, start:17.45 end:17.50 viewers: 45 name: The stock market today
Channel 2, start:16.45 end:17.50 viewers: 30 name: News
Channel 4, start:17.25 end:17.50 viewers: 10 name: Home building
Channel 5, start:15.45 end:16.50 viewers: 28 name: Reality
I also have created a nested list with the programs:
[[1,16:00, 17,45, 100, 'Matinee: The kiss on the cross'],[1,17:45, 17,50, 45,'The stock market today'],[2,16:45, 17,50, 30,'News'], [4,17:25, 17,50, 10,'Home building'],[5,15:45, 16,50, 28,'Reality']
Now we want the user to be able to write the name of a program:
News
The result should be:
News 19.45-17.50 has 30 viewers
I thought about how you could incorporate a method to avoid the program from crashing if the input is invalid/ not an instance variable
I have tried this:
Check_input():
print('Enter the name of the desired program:')
while True: #Continue asking for valid input.
try:
name = input('>')
if name == #is an instance?
return name
else:
print('Enter a program that is included in the schedule:') #input out of range
except ValueError:
print('Write a word!') #Word or letter as input
print('Try again')
I wonder if I should separate all the program-names from the nested list and check if the user enters a name in the list as input? (Maybe by creating a for-loop to iterate over?)
I also have a question regarding how to print out the selected program when the user enters the correct name? I understand how to rearrange them into the correct order to create the sentence. However, I don't know how to access the correct program in the "memory"
Do you have any suggestions how to combat the problem?
All help is much appreciated!
I wonder if I should separate all the program-names from the nested list and check if the user enters a name in the list as input? (Maybe by creating a for-loop to iterate over?)
Well if all your programs have a unique name then the easiest approach would probably be to store them in a dictionary instead of a nested list like:
programs = {
"News": Program("2", "16:45", "17:50", "News", "30", "60"),
"Reality": <Initialize Program class object for this program>,
...
}
Then you could just use the get dictionary method (it allows you to return a specific value if the key does not exist) to see if the asked program exists:
name = input('>')
program = programs.get(name, None)
if program:
print(program)
else:
# raise an exception or handle however you prefer
And if your programs don't have a unique name then you will have to iterate over the list. In which case I would probably return a list of all existing objects that have that name. A for loop would work just fine, but I would switch the nested list with a list of Program objects since you already have the class.
I also have a question regarding how to print out the selected program when the user enters the correct name? I understand how to rearrange them into the correct order to create the sentence. However, I don't know how to access the correct program in the "memory" Do you have any suggestions how to combat the problem.
I would say that the most elegant solution is to override the __str__ method of your Program class so that you can just call print(program) and write out the right output. For example:
class Program:
def __init__(self,channel,start, end, name, viewers, percentage):
self.channel = channel
self.start = start
self.end = end
self.name = name
self.viewers = viewers
def __str__(self):
return self.name + " " + self.start + "-" + self.end + " has " + self.viewers + " viewers"
should print out
News 19.45-17.50 has 30 viewers
when you call it like:
program = programs.get(name, None)
if program:
print(program)

How do I use an input to print a class definition?

I am trying to code something basic in python just for fun and I encountered an issue,
# Employee is a class with the initialization being self, name, status
e1 = Employee("Tom, Lincoln", "Present")
e2 = Employee("Sam, Bradley", "Absent")
print(e1.status)
# printing e1 status will make "Present" or "Absent"
while True:
try:
cmd = input("Cmd: ")
if cmd == "status_check":
who = input("Who: ")
# putting in e1 or e2 will get their respective statuses
I've tried everything I can think off like, making it so that it gets a number out of the input("Who: ") input so I can better use eval or exac, but doing that makes it so I cant run e1.status because all it has is a 1 and I can't make a "e" appear in front of it so I can't run e1.status. I've also tried using just eval or exac but that didn't get the wanted result because I would have to type my code in the input("Cmd: "). That's isn't the only things I've tried but those are some that come to mind.
I'm just stumped here.
If you want to map names to values, you don't want separate variables. You want a dictionary.
Rather than
e1 = Employee("Tom, Lincoln", "Present")
e2 = Employee("Sam, Bradley", "Absent")
Consider
employees = {
'e1': Employee("Tom, Lincoln", "Present"),
'e2': Employee("Sam, Bradley", "Absent"),
}
To access an employee, write
print(employees["e1"].status)
and then you can use the input string to subscript employees as well.
who = input("Who: ")
print(employees[who].status)
one other approach is to use sys module:
import sys
# class definitions etc
while True:
try:
cmd = input("Cmd: ")
if cmd == "status_check":
who = input("Who: ")
atr = getattr(sys.modules[__name__], who)
print(atr.status)

Changing string to avoid duplication in a systematic manner?

Take the list Usernames as shown below.
Usernames = ["johnsmith"]
I have the variable NewUsername and I need to check if its value is already contained in the list. If not, an integer will be concatenated to the end of it.
Examples:
NewUsername = "alexsmith"
Usernames = ["johnsmith", "alexsmith"]
NewUsername = "johnsmith"
Usernames = ["johnsmith", "alexsmith", "johnsmith1"]
NewUsername = "johnsmith"
Usernames = ["johnsmith", "alexsmith", "johnsmith1", "johnsmith2"]
Now, I know I can do this with something like this, but it would only check for the first 'level' of duplicate names.
if NewUsername in Usernames:
NewUsername = NewUsername + "1"
Usernames.append(NewUsername)
Question: How can I handle all duplications in a similar manner?
Maybe is a bit elaborate, but you could use a custom child class of a list. To give you an idea:
from collections import Counter
class UsernameList(list):
def __init__(self, *args):
super(UsernameList, self).__init__()
self._ucount = Counter()
for e in args[0]:
self.append(e)
def append(self, el):
if isinstance(el, str):
if self._ucount[el] == 0:
super(UsernameList, self).append(el)
else:
fixel = el + str(self._ucount[el])
super(UsernameList, self).append(fixel)
self._ucount.update([fixel])
self._ucount.update([el])
else:
raise TypeError("Only string can be appended")
Now you could do:
Usernames = UsernameList(["johnsmith"]) #Username is ["johnsmith"]
Usernames.append("johnsmith") #Username becomes ["johnsmith", "johnsmith1"]
Usernames.append("johnsmith") #Username becomes ["johnsmith", "johnsmith1", "johnsmith2"]
Apart the new __init__ and append methods, UsernameList has all the methods of a list, and works exactly as a list. Don't bother about the counter attribute, it's there to keep track of the usernames inputed and add the correct number in case of repetitions.
To have something more consistent you may need to override other methods: i'm just giving you an idea, far from writing a full working code here.
You may have a look at the docs for more details on which methods you may need to override.

How to add values to a dictionary of class in python

It's my first time posting here. I'm currently facing a problem where my goal is for user to have a command where my dictionary of classes will add exp to the class argument. (I'm kinda bad at english if you want some clarification, Please let me know)
class Stats:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
stre = {1: Stats(name='Excercise', exp=0, description="This is a description"),
2: Stats(name='Gym', exp=0, description="Gym description")}
def statsComm():
command_list = ["stre", "inte", "will"]
print("Select Command {}".format(command_list))
command = input("> ")
if command == 'stre':
for key, value in stre.items():
print(value.exp)
while True:
print("Enter Command {}".format(command_list))
command = input("> ")
if command == 'stats':
statsComm()
Currently it prints the right thing. But I don't know how to add value to exp of an individual class when they enter a command. Thank you :D
You can specify individual classes within the for loop as follows:
for key, value in stre.items():
if value.name == 'Exercise':
value.exp += 1

Missing 1 required positional argument (object created and dictionary initialized)

I see this question has been asked before in different variations, but I feel as though I have implemented the feedback I have seen in those threads (mainly making sure the object is created as I have done in the second last night, and making sure the dictionary is initiated, which I feel I have done in the third line) and I am still receiving the error. Any advice would be very much appreciated. Thank you!
class Groceries:
def __init__(self, grocery_list):
self.grocery_list = {}
def add_item(self, item):
item = input("name: ")
purchased = input(False)
self.grocery_list[item] = purchased
something = Groceries()
something.add_item()
The error I get is:
Traceback (most recent call last):
File "intermediate_python.py", line 14, in <module>
something = Groceries()
TypeError: __init__() missing 1 required positional argument: 'grocery_list'
I tried to resolve this error by removing grocery_list from the def init statement (not sure why this would work, I was just playing around) and the error was moved to the next line with:
Traceback (most recent call last):
File "intermediate_python.py", line 15, in <module>
something.add_item()
TypeError: add_item() missing 1 required positional argument: 'item'
To initialise an instance of your Groceries class you need to provide the parameter "grocery_list" which is defined in your init method
class Groceries:
def __init__(self, grocery_list):
self.grocery_list = {}
Try create your instance using the following:
something = Groceries({"milk": 1, "butter": 1})
Alternatively, to allow for empty Groceries objects, you can add a default parameter to the init method, you should also be assigning the value of the parameter to the variable self.grocery_list instead of assigning it an empty dictionary:
class Groceries:
def __init__(self, grocery_list={}):
self.grocery_list = grocery_list
and also with your method add_item, again you need to pass a parameter or else removed the parameter (since you're asking for it as input)
def add_item(self):
item = input("name: ")
purchased = input("amount: ")
self.grocery_list[item] = purchased
something = Groceries({"milk": 0})
something.add_item()
>> name:
>>> milk
>> amount:
>>> 1
def __init__(self, grocery_list):
self.grocery_list = {}
Although you are passing a grocery_list to your constructor, you are not actually using it to set the value. You merely need to set self.grocery_list equal to the passed argument grocery_list to fix this as I do below.
def add_item(self, item):
item = input("name: ")
You are also trying to both pass item as an argument and input it manually in the function. This means that regardless of what input you send to add_item, you will always override that value with user input. You can fix this by making the item argument optional and checking if it was passed before prompting the user for input as I do below.
purchased = input(False)
self.grocery_list[item] = purchased
Also, it is unclear here why you are fetching input with an implicit conversion of the boolean value False to string as a second prompt after asking for the item name. It seems that you want to set some purchased value to True or False, but it is also unclear then why you are using a dictionary for making a list of groceries in the first place unless you intend to include the quantity as the dictionary value. If you just wanted to see if an item was on the grocery list you could use the set() type instead of dict(). This might serve as an example to help you move forward if you want to maintain quantities.
class Groceries:
def __init__(self, grocery_list={}):
self.grocery_list = grocery_list
def add_item(self, item='', qty=1):
if not item: item = input('name: ')
if item in self.grocery_list:
self.grocery_list[item] += qty
else:
self.grocery_list[item] = qty
def item_qty(self, item=''):
if not item: item = input('name: ')
return(self.grocery_list[item])
def print_all(self):
for key, val in self.grocery_list.items():
print(val, key)
something = Groceries()
something.add_item('apple') # add one apple to groceries
print(something.item_qty('apple'))
something.add_item('apple', 3) # add three apples to groceries
print(something.item_qty('apple'))
something.add_item() # add arbitrary item to groceries
something.print_all() # print all groceries
If you are creating an instance of the Groceries class (something = Groceries(*args)), at the end of the initialization, the Groceries.__init__() function gets called with the same argument list *args.
That means, when you write something = Groceries(), you are trying to call the __init__ function without arguments. On the other hand, the function has a required positional argument grocery_list (any positional argument is required if you didn't provide a default for it).
Since your code defines the grocery_list as an empty dictionary anyway, you don't need to have this an argument to your __init__ function, you can simply use:
def __init__(self):
self.grocery_list = {}
Which will fix the error.
Or you can have a default value and use:
def __init__(self, grocery_list={}):
self.grocery_list = grocery_list
Which would let you use __init__ without providing the grocery_list argument, and using {} in that case.
The exact same case holds for the add_item function: you are defining it with a required positional argument, and then you are trying to call it without any argument. Since you aren't passing any value to the function on the function call that you would later use, you can again remove the argument and simply use:
def add_item(self):

Categories