How do I use dictionaries to make functions easily accessable - python

I declared 3 functions earlier, this is just a goofy text based cookie clicker-esque game.
dostuff={"" : turn() , "help" : helpf() , "invest" : invest() }
while done != True:<br>
do = input("What do you want to do? ")
do = do.lower()
if do == "" or do == "help" or do == "invest":
dostuff[do]
elif do == "quit":
done = True
So when I use dostuff["turn"] it does nothing (the function is supposed to print some things). I have the same problem with the other options.

Your parentheses must be omitted in the dict, and then put at the end of the dict call. You define a function, which becomes a python object. You reference the object with the dict, and then you call the function with the object reference followed by parentheses:
def one():
print("one")
def two():
print("two")
do_stuff = {
"one": one,
"two": two
}
do_stuff["one"]()
prints:
"one"
You can take this concept of executing calls with string inputs a lot farther by familiarizing yourself with the builtin functions of python.
https://docs.python.org/2/library/functions.html
For example, you can create a class and call its methods or properties using text based input with the getattr method:
class do_stuff():
def __init__(self):
pass
def one(self):
print("one")
def two(self):
print("two")
doer = do_stuff()
inp = "one"
getattr(doer, inp)()
prints->
"one"

Related

Switch Implementation of Object calling function in python

I am trying to implement the switch in Dictionary in Python. But when I call the method
chooices.get(x, "Ther is no program") It call all the Function in the statment rather than calling x function.
I have read this implementation
Replacements for switch statement in Python?
but it was not helpful in my case as my function has print statement
Main file contain the code
from Day1.Day1 import Day1
from Day2.TipCalculator import TipCalculator
def choose():
print("Choose From the following Program:\n")
day1 = Day1()
day1.day1()
day2 = TipCalculator()
day2.day2()
x = int(input());
chooices={
1: day1.program1(),
2: day2.program1(),
}
chooices.get(x, "Ther is no program")
choose()
Day1 Class contain code
class Day1:
def day1(self):
print('1. Band name Generator\n')
def program1(self):
print('Welcome to Band Name Generator.\n')
cityName=input('What\'s is the name of city you grew up?\n')
petName = input('What\'s your pet\'s name?\n')
print('Your Band Name could be : '+cityName+" "+petName)
Class Tip Calculator Code
class TipCalculator:
def day2(self):
print("2. Tip Calculator For Bill.\n")
def program1(self):
print('Welcome to tip calculator.\n')
I just need the implementation Of switch statement which call Requested Program just like switch. I know Its possible through If-else but Dictionary mapping seems too be good alternative of switch
Overview: the interpretor creates a closure for the variables that the child function uses that are non local. In this example the child variable, value is 22 and stored in the closure cell.
def parent(arg_1, arg_2):
value=22
my_dict = {'chocolate':'yummy'}
def child():
print(2*value)
print(my['chocolate'])
print(arg_1 + arg_2)
return child
new_function=parent(3,4)
print(cell.cell_contents for cell in new_function.__closure__])
If you don't have a lot of variants, the if/elif/else statements can be streamlined using a helper function for the switch. This is only syntactic candy but it may be sufficient for small value sets.
def switch(v): yield lambda *c: v in c
Example usage:
x = int(input())
for case in switch(x):
if case(1): day1.program1()
elif case(2): day2.program1()
else: print("there is no program")
supporting multiple values for the same method call:
x = int(input())
for case in switch(x):
if case(1,5): day1.program1()
elif case(2,3,4): day2.program1()
else: print("there is no program")
you can also use it in a more C-like style
x = int(input())
for case in switch(x):
if case(1,5):
day1.program1()
break
if case(2,3,4):
day2.program1()
break
else:
print("there is no program")
If you have python 3.10 or higher, a proper switch analogue was implmemented called "match" which should work quite well in replacing any nested if statments the other answers may have.
If you dont have 3.10, and you are okay with a pretty hacky solution, mine uses the ideas from withhacks (specifically from AnonymousBlocksInPython). I have recently created my own version of a switch statment in python that acts more like how i am used to in C#. You can expand this as much as you want, way past single line arguments or assignments.
It uses context managers so that you can treat each case as its own code block with indentation and all. It will never enter the cases if the case value does not match the switch value so for code that is extremely system taxing, you can be sure it is not running code that does not need to be.
import sys
class CaseReturn(Exception):pass
class Case:
def __init__(self, caseVal): self._caseVal_ = caseVal
def _trace_(self,frame,event,arg): raise CaseReturn
def __enter__(self):
if self._caseVal_ == Switch._singleton_._switch_: return
sys.settrace(lambda *args, **keys: None)
sys._getframe(1).f_trace= self._trace_
def __exit__(self,ExType,ExVal,ExTrace):
if ExType is None: raise CaseReturn
return ExType is CaseReturn
class Switch:
_singleton_:'Switch' = None
def __init__(self, switchVal,Default=None): self._switch_ = switchVal
def __enter__(self):Switch._singleton_ = self
def __exit__(self,ExType,ExVal,ExTrace):
Switch._singleton_ = None
return ExType is CaseReturn
with Switch(2):
with Case(1):
print('This should not make it')
with Case(2):
print('I made it')
with Case(3):
print('This should never be called')
You can easily extend this out to check multiple cases by just changing the caseVal to a list and doing if Switch._singleton_._switch_ in self._caseVal_:
One caveat is, you cannot make the Case statments one-liners like:
Case(0): print('I am one line')
That will not work and end up calling the code in that case no matter what.
I hope this is useful to you or anyone who is searching for custom Switch statments!

Way to call method depending on variable?

I already have a working, but in my oppinion not beautiful solution for a part of a long script.
My script uses several similar methods, that differ too much to combine. However I came to a point where I want to call one of those methods depending on a given variable.
The names of the methods are build up like this:
def read_A():
#doing sth
def read_B():
#doing sth else
def read_C():
etc.
Now I would like to call those methods in a pythonic way, when the letter ('A', 'B', 'C', ...) is given as a variable.
A non-pythonic solution would be:
if var == "A":
read_A()
if var == "B":
read_B() .....
And I hope to find a more pythonic solution that allows me to call those methods simply like this:
var = "A"
read_var() #This would call the method 'read_A()'
Please mind that the code above is only an image of what I hope to do, it is not a working example!
I dont see an issue with just using
if var == 'A':
read_a()
but if you'd like to make it more 'pythonic' you could map your variables to the methods using a dictionary and execute it based on the result of what's stored in your dictionary:
def read_a():
print('Running method read_a')
def read_b():
print('Running method read_b')
switch = {'A': read_a, 'B': read_b}
case = 'A'
switch.get(case)()
>> 'Running method read_a'
case = 'B'
switch.get(case)()
>> 'Running method read_b'
Stick the functions in a dictionary, and use the dictionary to dispatch to the chosen one:
read = {'A': read_a, 'B': read_b, 'C': read_c}
choice = 'A'
read[choice]()
On that last line, you lookup the function that matches your choice in the dictionary, then you immediately call it.
you may use next construction:
def execute_func(x):
return {
'0':read_A(),
'1':read_B()
}[x]
Set your variables instead '0' and '1' or more and pass your params to execute_func().
You can do it in this way if you have many functions named read_a, read_b...etc, instead of writing huge dictionary.
def read_a():
print('Running method read_a')
def read_b():
print('Running method read_b')
def read_c():
print("running method read_c")
def read_d():
print("running method read_d")
............
............
def read_z():
print("running method read_z")
def _read_var(var):
method = "read_{}".format(var.lower())
try:
eval(method)()
except NameError:
raise NotImplementedError
var = "A"
_read_var(var)# will invoke read_a method
"""
modified from
https://stackoverflow.com/questions/65163600/how-to-call-a-class-method-given-its-name
"""
class MyClass(object):
def __init__(self):
pass
def call_method_by_string(self, method_name):
getattr(self, method_name)() # call local method based on string
def get_year(self):
print("here")
if __name__ == "__main__":
mc = MyClass()
mc.call_method_by_string(method_name="get_year")

How to use the def function in IF or ELSE/ ELIF satement in python?

I have a sub program that uses a def option, so if i ever want to repeat the program. Eg:
def op1():
print ("Something Something")
So I just write in the program:
op1()
which makes the program run.
Now I have a lot of subprograms each one with a different def so I can run them by easily.
eg:
def op1():
def op2():
def op3():
So I wanted to know how can I use this in if-else statement.
eg:
option = input ("Enter either A, B or C here: ")
if option == A:
def op1():
else:
def op2():
or even
if option == A:
def op1():
elif:
def op2():
elif:
def op3():
Something like that, but it doesn't work. Can anyone help, Please?
Also I'm using the newer version of python if that helps 3.5.0.
You do not need to define functions conditionally.
def op1():
print('1')
def op2():
print('2')
def op3():
print('3')
if option == 'A':
op1()
elif option == 'B'::
op2()
else:
op3()
You need to define your functions first but if you have multiple choices you can store references to functions in a dict then call based on what the user enters, using dict.get with a default function will act like your if/elif else logic:
def op1():
return '1'
def op2():
return '2'
def op3():
return "3"
option_fs = {"A": op1, "B": op2}
option = input("Enter either A, B or C here: ").upper()
print(option_fs.get(option, op3)())

Calling a function in a class of another program - Python

As the title says, how do you call a function in a class of another program?
Class.py
class Object:
def __init__(self, mood):
self.__mood = mood
def set_mood(self, mood):
self.__mood = mood
def check_mood(self):
if random.randint(1, 3) == 1:
self.__mood = 'happy'
elif random.randint(1, 3) == 2:
self.__mood = 'hungry'
elif random.randint(1, 3) == 3:
self.__mood = 'sleepy'
def get_mood(self):
return self.__mood
Generator.py
from test import Object
import test
mood = 'happy'
ani = Object.test(mood)
print("This is your mood: " + get_mood())
Mood is set as a default value of "happy". I need that to change based on the random integer roll in test so that when mood is displayed, it isn't always displayed as "happy"
You have to explicitly call check_mood to change the object's attribute. See code below.
from random import randint
class Foo(object):
def __init__(self, mood):
self.__mood = mood
self.__selection = {
1:'happy',
2:'hungry',
3:'sleepy',
4:'angry',
5:'bored'
}
def check_mood(self):
m = randint(1,5)
self.__mood = self.__selection[m]
def get_mood(self):
return self.__mood
mood = 'happy'
f = Foo(mood)
print 'This is your previous mood:', f.get_mood()
f.check_mood() # This rerolls the mood.
print 'This is your current mood:', f.get_mood()
# This is your previous mood: happy
# This is your current mood: bored
Otherwise, if you want it to change "behind-the-scenes", I suggest calling check_mood inside get_mood (or just get rid of check_mood entirely and put its code inside get_mood).
However, the way get_mood is defined makes it modify the original self.__mood, rendering the original passed-in argument as lost once you call get_mood.
There are... a lot of problems with this. Lets start with your Object class. You probably don't want to name something Object - it is too similar to object the Python builtin, and doesn't provide any real information about what the class does. Additionally, you probably don't want to call the instance variable __mood - this will invoke name mangling which is probably not something you want. You probably don't even want the single underscore; that represents a "private" data member (and there isn't a clear reason why this should be private). You don't need getter and setter functions in Python because you can access attributes directly, but if you do want finer grained control use a property instead. Lastly, we don't need to keep redefining the random variable in your check_mood function - in fact it will probably introduce bugs. Lets look at this alternate definition instead.
person.py
import random
class Person(object):
_mood = None
def __init__(self, mood):
self.mood = mood
#property
def mood(self):
return self._mood
#mood.setter
def mood(self, new_mood):
self._mood = new_mood
def check_mood(self):
rand_mood = random.randint(1, 3)
if rand_mood == 1:
self.mood = 'happy'
elif rand_mood == 2:
self.mood = 'hungry'
else:
self.mood = 'sleepy'
That's a little better. Lets look at your other file now.
from person import Person
myPerson = Person("happy")
print("This is your mood: ", myPerson.mood)
This should print out the mood of the Person.
In your code you don't ever create an instance of an Object - you just call some test() function on your Object class, not an instance of it. Then when you called get_mood() it doesn't work because that is an instance function - it can only be called on instances of your Object class.

Calling functions from main python

I have some python 3.4 code that works fine:
def run():
m = 0
while m != 1:
p = input('Please choose p: ')
p = makeInt(p)
#Some other code
print(p)
m = makeInt(input('Enter 1 if you would like to quit: '))
def makeInt(i):
try:
i = int(i)
except ValueError:
i = input('Incorrect input! Enter your answer: ')
i = makeInt(i)
return i
#Some other functions
if __name__ == '__main__':
run()
I want to put all this code in a class (Except possibly if __name__ ==...) When I put all the code including if __name__ ==... in a class like so:
class Foo(object):
def run(self):
m = 0
while m != 1:
p1 = input('Please choose p: ')
p1 = self.makeInt(p1)
#Some other code
print(p1)
m = self.makeInt(input('Enter 1 if you would like to quit: '))
def makeInt(self, i):
try:
i = int(i)
except ValueError:
i = input('Incorrect input! Enter your answer: ')
i = self.makeInt(i)
return i
#Some other functions and stuff
if __name__ == '__main__':
run()
I get the following error: TypeError: run() missing 1 required positional argument: 'self'. When I remove the self argument from run() it runs until makeInt() is called and then I get: NameError: name 'makeInt' is not defined. I get the same error if I take the if statement out of the class and call Foo.run(). I have some other code earlier in this program that works when I call functions of a class from another function in that same class. I realize I don't have to put all my code in a class, but in this case I want to. Why am I getting these errors and what can I do to put my working code in a class?
As others mentioned, by putting your functions in a class, you've made them methods, that means they need an instance of this class as first argument. So you can indeed call your run method using Foo().run() as Foo() will create an instance of Foo.
Another way (e.g. if you don't need the class for anything else than encapsulation) is to make them static, using the staticmethod decorator:
class Foo(object):
#staticmethod
def run():
...
#staticmethod
def makeInt(i):
...
if __name__ == '__main__':
Foo.run() # don't need an instance as run is static
In Python, a method can be static, i.e. no need for any special argument, a class method, i.e. first argument is the class itself, or a standard method, i.e. the first argument is an instance of the class.
Since you wrap your code within a class, your run() is a method now. You should remove your main from your class by unindenting it and initialize an instance of your class:
if __name__ == '__main__':
Foo().run()
It thinks the guard is a part of your class due to the indentation: you have your guard indented to the same level as the other class members. Unindent the
if __name__ == '__main__'
Also change it to be
if __name__ == '__main__':
main()
and then instantiate a new object of type Foo in your newly created main() function
def main():
newFoo = Foo()
newFoo.run()

Categories

Resources