Pythonic alternatives to if/else statements - python

I'm trying to avoid a complex web of if/elif/else statements.
What pythonic approaches can I use to accomplish my goal.
Here's what I want to achieve:
My script will receive a slew of different urls,
youtube.com, hulu.com, netflix.com, instagram.com, imgur.com, etc, etc possibly 1000s of different domains.
I will have a function/set of different instructions that will be called for each distinct site.
so....
if urlParsed.netloc == "www.youtube.com":
youtube()
if urlParsed.netloc == "hulu.com":
hulu()
and so on for 100s of lines....
Is there anyway to avoid this course of action...if xyz site do funcA, if xyz site do funcB.
I want to use this as a real world lesson to learn some advance structuring of my python code.
So please feel free to guide me towards something fundamental to Python or programming in general.

Use a dispatch dictionary mapping domain to function:
def default_handler(parsed_url):
pass
def youtube_handler(parsed_url):
pass
def hulu_handler(parsed_url):
pass
handlers = {
'www.youtube.com': youtube_handler,
'hulu.com': hulu_handler,
}
handler = handlers.get(urlParsed.netloc, default_handler)
handler(urlParsed)
Python functions are first-class objects and can be stored as values in a dictionary just like any other object.

You can use a dict
myDict = {"www.youtube.com": youtube, "hulu.com": hulu}
...
...
if urlParsed.netloc in myDict:
myDict[urlParsed.netloc]()
else:
print "Unknown URL"

Related

how to compare two lists in different functions in Python?

I am making a Django web Application and i am facing a problem in comparing two different lists in different functions
def test(request,slug):
n=request.user
choice=TestOptions.objects.filter(choice=slug).first()
que=questions.objects.filter(Subject=choice)
question=[]
un=['a','b','c','d','e']
for q in que:
if q not in question:
question.append(q)
else:
continue
sampling = random.sample(question, 5)
print("--------------SamPLING111")
print(sampling)
print("--------------SamPLING111")
correctAnswers=[]
for j in sampling:
correctAnswers.append(j.answer)
marks(correctAnswers)
d = dict(zip(un,sampling))
return render(request,"code/test.html",{'questions':d})
def acceptAnswer(request):
answers=[]
if request.method=="POST":
answers.append(request.POST['a'])
answers.append(request.POST['b'])
answers.append(request.POST['c'])
answers.append(request.POST['d'])
answers.append(request.POST['e'])
score(answers)
return render(request,"code/dub.html")
def marks(correct):
list1=[]
l1=correct
def score(and):
list2=[]
l2=ans
function test is passing a list and function acceptAnswer is passing another list my job is to compare those two lists
how can I compare l1 and l2?
I am not 100 percent what you are trying to do with these lists, but in order to compare them I would just return them. Here is a quick example:
def marks(correct):
list1 = []
l1 = correct
return l1
def score(answer):
list2 = []
l2 = answer
return l2
numbers = [1,2,3]
numbers2 = [1,2,3]
numbers3 = [3,4,5]
print(marks(numbers) == score(numbers2)) # True
print(marks(numbers2) == score(numbers3)) # False
Hopefully this helps!
Rather than continue with comments I figured I'd elaborate in an answer though it isn't an exact answer to your question I think it is the real answer.
You really have two issues. One is a design issue ie how to make your program work correctly and the other is an implementation issue about the scope of variables and how to deal with it.
I can see in your profile you're a university student and given the nature of the code it seems very likely you're writing your web app for the purposes of learning maybe even an assignment.
If you were doing this outside of a university I'd expect you were seeking practitioner type skills in which case I'd suggest the answer would be to design your application the way Django expects you to, which I would say would translate into storing state information in a database.
If this is a lab however you may not have covered databases yet. Labs sometimes have students doing silly things because they can't teach everything at the same time. So your Prof may not expect you to use a database yet.
Inside a web application you have to consider that the web is request response and that you can get requests from a lot of different sources so you have state management concerns that classical desktop applications don't have. Who is supposed to see these tests and who is supposed to see the marks and what is the order these things happen? Should anyone be able to create a test? Should anyone be able to take a test? You might not care yet, eventually you'll want to care about sessions. If people are taking their own tests you could store data in a user session but then other people wouldn't see those tests. Generally the correct way to store this sort of state is in a database where you can access it according to what you know about the current request. If this is some sort of basic intro app your Prof may be happy with you doing something kludgy for now.

How do you include a command in a dictionary?

I'm creating a smart Chatbot. That part of information is irrelevant, however. What I'm trying to do is call on an instruction from within a dictionary - I'll show you:
dictionary = ["command1": "print("I just called command1!")]
dictionary["command1"]
Sort of like that. Obviously you cannot do that. I want to be able to have a dictionary of different commands which will run when you use dictionary[whatever_command you want_in_here]
Do you see what I mean?
I could use functions, but clearly that would take up a whole lot of space and lots of code which I cannot afford when there are so many responses in my Chatbot.
I really need to know how to do this in a simple way.
Store instructions as anonymous functions:
dictionary = {
"command1": lambda: print("I just called command1!"),
"command2": lambda: print("I just called command2!")
}
command = input('Enter command: ')
dictionary[command]()
If you're just looking to print strings, you're much better off doing something like:
dictionary = {"command1": "I just called command1!"}
print(dictionary["command1"])
but if you need to parse actual functions, you can, as #Uriel Eli said in the other answer, using a lambda.
mylist = []
dictionary = {"command1": lambda: print("I just called command1"), "command2": lambda: mylist.append("Here's an appended string!")}
dictionary["command1"]()
dictionary["command2"]()

Python: Elegant way to reference a function that will be declare later

I wrote a simple command-line tool in Python. To simplify the logic, I use a dict for storing the commands and handlers, something like this:
#!/usr/bin/env python
# some code here
DISPACHERS = {
"run": func_run
"list": func_list
}
# other code
The problem is, I have to put this piece of code after the function declarations, which is not the standard practice I have seen in other languages (i.e. constants in one block, variables after, and then the functions).
I could use strings for storing the function, and retrieve it using something like getattr(__main__, "func_run"), so I can stick with my preference, but I wonder if that's a "proper" way.
Any idea?
=== Update ===
Since it's a simple python script that handles some automation tasks of another project, so it would be better to keep it in a single file (no other module) if possible.
Use a decorator to enumerate the functions.
dispatchmap = {}
def dispatcher(name):
def add_dispatcher(func):
dispatchmap[name] = func
return func
return add_dispatcher
...
#dispatcher('run')
def func_run(...):
...

Is it OK to send the whole POST as a JSON object?

I am using GAE with python, and I am using many forms. Usually, my code looks something like this:
class Handler(BaseHandler):
#...
def post(self):
name = self.request.get("name")
last_name = self.request.get("last_name")
# More variables...
n = self.request.get("n")
#Do something with the variables, validations, etc.
#Add them to a dictionary
data = dict(name=name, last_name=last_name, n=n)
info = testdb.Test(**data)
info.put()
I have noticed lately that it gets too long when there are many inputs in the form (variables), so I thought maybe I could send a stringified JSON object (which can be treated as a python dictionary using json.loads). Right now it looks like this:
class Handler(BaseHandler):
#...
def post(self):
data = validate_dict(json.loads(self.request.body))
#Use a variable like this: data['last_name']
test = testdb.Test(**data)
test.put()
Which is a lot shorter. I am inclined to do things this way (and stop using self.request.get("something")), but I am worried I may be missing some disadvantage of doing this apart from the client needing javascript for it to even work. Is it OK to do this or is there something I should consider before rearranging my code?
There is absolutely nothing wrong with your short JSON-focused code variant (few web apps today bother supporting clients w/o Javascript anyway:-).
You'll just need to adapt the client-side code preparing that POST, from being just a traditional HTML form, to a JS-richer approach, of course. But, I'm pretty sure you're aware of that -- just spelling it out!-)
BTW, there is nothing here that's App Engine - specific: the same considerations would apply no matter how you chose to deploy your server.

Redis key management

So im working with redis in a python app. any advice on key management? i try and keep all redis calls in one location but something seems off with hardcoding keys everywhere. tips?
I use a set of wrapper classes that handle key generation, something like:
public User Get(string username) {
return redis.Get("user:"+username);
}
I have an instance of each of these classes globally available, so just need to call
Server.Users.Get(username);
That's in .NET of course, but something similar should work in any language. An additional advantage of this approach over using a generic mapping tool is that it provides a good place to put things like connection sharing and indexing.
Well, key names are comparable to classes and attributes in your application, so some degree of 'repetition' will happen.
However, if you find you're repeating a lot of code to actually build your keys, then you might want to look at a mapper. In Python there's Redisco.
Or if you need something simpler, in Ruby there's Nest (porting it to Python should be trivial). It allows you to DRY up your references to keys:
users = Nest.new("User")
user = users[1]
# => "User:1"
user[:name]
# => "User:1:name"
redis.set(user[:name], "Foo")
# or even:
user[:name].set("Foo")
user[:name].get
# => "Foo"

Categories

Resources