Assign nested function to variable with parameter - python-2.7

disclaimer: My title may not be accurate as far as what I would like to accomplish, but I can update if someone can correct my terminology
I have 2 functions, each with a separate purpose and usable on its own, but occasionally I would like to combine the two to perform both actions at once and return a single result, and to do this I would like to assign to a variable name
I know I can create a 3rd function that does basically what I want as it is really simple.. though it's become a bit of a challenge to myself to find a way of doing this
def str2bool(string):
return string.lower() in ("yes", "true", "t", "1")
def get_setting(string):
if string == 'cat':
return 'yes'
else:
return 'no'
VALID_BOOL = str2bool(get_setting)
print VALID_BOOL('cat')
So basically I would like to assign the combination of the 2 functions to a variable that I can call and pass in the string parameter to evaluate
In my real world code, get_setting() would retrieve a user setting and return the value, I would then like to test that value and return it as a boolean
Again I know I can just create a 3rd function that would get the value and do the quick test.. but this is more for learning to see if it can be done as I'm trying to do.. and so far my different variations of assigning and calling aren't working, is it even possible or would it turn too complex?

Using lambda is easy, but i don't know if it is exactly what you are looking for.
Example:
f = lambda astring : str2bool(get_setting(astring))
Outputs:
>>> f('cat')
True

Related

Python - null object pattern with generators

It is apparently Pythonic to return values that can be treated as 'False' versions of the successful return type, such that if MyIterableObject: do_things() is a simple way to deal with the output whether or not it is actually there.
With generators, bool(MyGenerator) is always True even if it would have a len of 0 or something equally empty. So while I could write something like the following:
result = list(get_generator(*my_variables))
if result:
do_stuff(result)
It seems like it defeats the benefit of having a generator in the first place.
Perhaps I'm just missing a language feature or something, but what is the pythonic language construct for explicitly indicating that work is not to be done with empty generators?
To be clear, I'd like to be able to give the user some insight as to how much work the script actually did (if any) - contextual snippet as follows:
# Python 2.7
templates = files_from_folder(path_to_folder)
result = list(get_same_sections(templates)) # returns generator
if not result:
msg("No data to sync.")
sys.exit()
for data in result:
for i, tpl in zip(data, templates):
tpl['sections'][i]['uuid'] = data[-1]
msg("{} sections found to sync up.".format(len(result)))
It works, but I think that ultimately it's a waste to change the generator into a list just to see if there's any work to do, so I assume there's a better way, yes?
EDIT: I get the sense that generators just aren't supposed to be used in this way, but I will add an example to show my reasoning.
There's a semi-popular 'helper function' in Python that you see now and again when you need to traverse a structure like a nested dict or what-have-you. Usually called getnode or getn, whenever I see it, it reads something like this:
def get_node(seq, path):
for p in path:
if p in seq:
seq = seq[p]
else:
return ()
return seq
So in this way, you can make it easier to deal with the results of a complicated path to data in a nested structure without always checking for None or try/except when you're not actually dealing with 'something exceptional'.
mydata = get_node(my_container, ('path', 2, 'some', 'data'))
if mydata: # could also be "for x in mydata", etc
do_work(mydata)
else:
something_else()
It's looking less like this kind of syntax would (or could) exist with generators, without writing a class that handles generators in this way as has been suggested.
A generator does not have a length until you've exhausted its iterations.
the only way to get whether it's got anything or not, is to exhaust it
items = list(myGenerator)
if items:
# do something
Unless you wrote a class with attribute nonzero that internally looks at your iterations list
class MyGenerator(object):
def __init__(self, items):
self.items = items
def __iter__(self):
for i in self.items:
yield i
def __nonzero__(self):
return bool(self.items)
>>> bool(MyGenerator([]))
False
>>> bool(MyGenerator([1]))
True
>>>

Is it possible to use User Defined Attributes to get values at runtime?

What I really would like to do is cache/memoize certain function arguments and results. I understand in d there's User Defined Attributes, but it appears theres no way to get runtime values with it. Am I mistaken? Is there another similar design pattern I could use here to get similar results?
#memoize("expensiveCalc")
int expensiveCalc(string foo){
///bar
}
So memoize is actually a function that gets called. However, it utilizes the value of my arguments to quickly hash parameters and call the actual function.
Similar to this:
def memoize(iden, time = 0, stale=False, timeout=30):
def memoize_fn(fn):
def new_fn(*a, **kw):
#if the keyword param _update == True, the cache will be
#overwritten no matter what
update = kw.pop('_update', False)
key = make_key(iden, *a, **kw)
res = None if update else memoizecache.get(key)
if res is None:
# okay now go and actually calculate it
res = fn(*a, **kw)
memoizecache.set(key, res, time=time)
return res
new_fn.memoized_fn = fn
return new_fn
return memoize_fn
For what you're trying to do, you'll want a wrapper template rather than a UDA. Phobos actually has one for memoization: http://dlang.org/phobos/std_functional.html#memoize
UDAs in D are used to add information to a function (or other symbol, types and variables too), but they don't actually modify it. The pattern is to have some other code read all the names with reflection, look at the UDAs, and generate the new code that way. If you want to get runtime values from a UDA, you'd write a function that reads it with compile time reflection, then returns the value. Calling that function at runtime gives the UDA there. If you'd like to know more, I can write it up, but I think std.functional.memoize will do what you want here. Remember, UDAs in D add information, they don't change or create code.

Python input, ifstatement, return

I have to create a function that takes an input, and returns a corresponding Grade.
So for example if the user inputs A+ output is 90%
or
if the input is A output is 80%
or
if the input is B output is 70%
I have some sort of Idea on how to do this... but I am having trouble on wrapping my head around on how I can return the statement??
def percent (percentage):
if ( percentage )== A+
return ("90%")
elif (percentage)== A
return ("80%")
Is this the correct way of going about it?
OK, so first, welcome to Python. Second, this is Pythonic way of doing this - define a dict:
grades = {'A+': "90%", 'A': "80%", ...}
then
return grades[precentage]
will do the job.
You need to protect against the case where the grade is not in the dict, for example, if the user entered some mistake, like G. There are a few ways to go about that:
A simple if:
if precentage in grades:
return grades[precentage]
else:
return "bad precentage"
After you get used to Python you will be more aesthetic about your code and will want to do better than state twice bote grades and precentage, so you can do simply:
return grades.get(precentage, "bad precentage")
Or using a special dict with default values:
import collections
grades = collections.defaultdict(lambda: "bad precentage", [("A+", "90%"), ("A", "80%")])
then
grades[precentage]
will automatically return "bad precentage" upon bad input.
#user2829744 You don't want to have to repeatedly call if statements based on what the percentage is, that would make the code unnecessarily long.
Instead, you want to have a list or tuple (a variable which stores multiple elements) that the program can compare the user's inputted value to, and then calculate the percentage mark.
Take this for example:
def percentage(per):
grades=["A+","A","B","C","D","E","F"]
percentage=("90%","80%","70%","60%","50%","40%","30%")
for i in range(7):
if per.upper()==grades[i]:
return percentage[i]
d="a"
print(percentage(d))
What happens is that i counts up to the number seven, and if the value of i in grades (let's say i is 5, then that would be grades[5] which would be an "E") then the function returns the value of i in the percentage tuple. In my case, the interpreter outputs 80%
Logically, your way of going about it (by actually dealing with every grade possible in separate if statements) would work too, however like I said your code would be longer and chances are you'd make a few typos along the way that you'd have to edit. Of course, my code has a few problems too, like what if the user enters a grade which I don't have in the tuple. This is easily fixable though as you would just need to tell the interpreter what to do if that happens.
A bit brief I know, but I hope this helps
You could do something like this
user_input = int(input("percentage: ")
if user_input < 0 and user_input > 10:
print('F")
And then you can just duplicate the code and change the numbers and the return grade
Hope it helps :)

Django schedule: Difference between event.get_occurrence() and event.get_occurrences()?

Based on django-schedule. I can't find the guy who made it.
Pardon me if I'm missing something, but I've been trying to get an events occurrences, preferably for a given day.
When I use event.get_occurrence(date), it always returns nothing. But when I use event.get_occurrences(before_date, after_date), suddenly the occurrences on the previously attempted date show up.
Why won't this work with just one datetime object?
This difference is probably in the actual design of these two methods. Frankly, get_occurrence is rather flawed, in general. A method like this should always return something, even if it's just None, but there's scenarios where it doesn't return at all. Namely, if your event doesn't have an rrule, and the date you passed get_occurrence isn't the same as your event's start, then no value is returned.
There's not really anything that can be done about that. It's just flawed code.
Based on the above comment especially in the case when the event doesn't return and occurrence, the following snippet below can force the retrieval of an occurrence especially when you are sure that it exists
from dateutil.relativedelta import relativedelta
def custom_get_occurrence(event,start_date):
occurrence = event.get_occurrence(start_date)
if occurrence is None:
occurrences = event.get_occurrences(start_date, start_date+relative_delta(months=3)
result = filter(lambda x: x.start==start_date,occurrences)
occurence = result[0]
The above code resolves issue that might occur when the default get_occurrence doesn't return a result.

String formatting issue when using a function

I have what I believe to be an embarrassingly simple problem, but three hours of googling and checking stackoverflow have not helped.
Let's say I have a very simple piece of code:
def secret_formula(started):
jelly_beans = started*500
jars = jelly_beans/1000
crates = jars/100
return jelly_beans,jars,crates
start_point = 10000
print("We'd have {} beans, {} jars, and {} crates.".format(secret_formula(start_point)))
What happens is I get the "IndexError: tuple index out of range". So I just print the secret_formula function to see what it looks like, and it looks like this:
(5000000, 5000.0, 50.0)
Basically, it is treating the output as one 'thing' (I am still very new, sorry if my language is not correct). My question is, why does it treat it like this and how do I make it pass the three outputs (jelly_beans, jars, and crates) so that it formats the string properly?
Thanks!
The format function of the string take a variable number of argument. The secret_formula function is returning a tuple. You want to convert that to a list of arguments. This is done using the following syntax:
print("We'd have {} beans, {} jars, and {} crates.".format(*secret_formula(start_point)))
The important par is the * character. It tell that you want to convert the following iterable into a list of argument to pass to the function.