Why Python allows def functions inside for loop - python-2.7

I'm new at Python, but I tried something and it was ambiguous for me.
Why Python allows doing def of function inside a loop ? and how I can benefit from that ?
for i in range(2):
def f():
print 'f'
f()

Well because python is a high level programming language, you can actually return functions. The following a simple yet demonstrative function.
def multiplier(multiple):
def f(number):
return multiple * number
return f
you can use that function as follows:
double = multiplier(2)
print double(3)
which would print 6.
Same concept would apply for loops if you want to make multiple functions for example and store them in a list or any other purpose befitting your needs.
list_of_functions = [] #list of functions
for i in range(2):
def f(n):
def printer():
print "f"*n
return printer
list_of_functions.append(f(i+1))
Now you can call list_of_functions[0]() which would print 'f' and list_of_functions[1]() which would print 'ff'.

You can define functions anywhere! Because Python is dynamic in this way, you can create functions (and classes, and pretty much anything else) at runtime. It's difficult to come up with a simple example of why you'd want to do this without it seeming contrived, but use cases certainly do exist.
Let's say you're writing a simple processing framework. You'll allow users to type commands, which will cause certain functions to run. You can define those functions first, and then store them all in a dictionary, so that you can quickly look up the appropriate function to run when you get the user's input.
def define_functions(letters):
commands = {} # dictionary of commands
for letter in letters:
# Define functions dynamically
if letter == 'f':
def _function():
print('foo')
elif letter == 'b':
def _function():
print('bar')
elif letter == 'z':
def _function():
print('baz')
else:
def _function():
print('Unknown command')
# Add the new function to the dictionary with the key "n squared"
commands[letter] = _function
return commands
commands = define_functions('abcdefghijklmnopqrstuvwxyz')
# Now we have a dictionary of functions.
while True: # loop forever
# Ask for input and run the specified function!
func_name = raw_input('Enter the one-letter name of the function to run: ')
if func_name not in commands:
print("sorry, that function isn't defined.")
break
# Look up the function
func = commands.get(func_name)
# Call the function
func()

Related

Pass capitalised variables to django settings.configure() [duplicate]

Does python have the ability to create dynamic keywords?
For example:
qset.filter(min_price__usd__range=(min_price, max_price))
I want to be able to change the usd part based on a selected currency.
Yes, It does. Use **kwargs in a function definition.
Example:
def f(**kwargs):
print kwargs.keys()
f(a=2, b="b") # -> ['a', 'b']
f(**{'d'+'e': 1}) # -> ['de']
But why do you need that?
If I understand what you're asking correctly,
qset.filter(**{
'min_price_' + selected_currency + '_range' :
(min_price, max_price)})
does what you need.
You can easily do this by declaring your function like this:
def filter(**kwargs):
your function will now be passed a dictionary called kwargs that contains the keywords and values passed to your function. Note that, syntactically, the word kwargs is meaningless; the ** is what causes the dynamic keyword behavior.
You can also do the reverse. If you are calling a function, and you have a dictionary that corresponds to the arguments, you can do
someFunction(**theDictionary)
There is also the lesser used *foo variant, which causes you to receive an array of arguments. This is similar to normal C vararg arrays.
Yes, sort of.
In your filter method you can declare a wildcard variable that collects all the unknown keyword arguments. Your method might look like this:
def filter(self, **kwargs):
for key,value in kwargs:
if key.startswith('min_price__') and key.endswith('__range'):
currency = key.replace('min_price__', '').replace('__range','')
rate = self.current_conversion_rates[currency]
self.setCurrencyRange(value[0]*rate, value[1]*rate)

Python - Classes and objects

This may appear like a very trivial question but I have just started learning python classes and objects. I have a code like below.
class Point(object):
def __init__(self,x,y):
self.x = float(x)
self.y = float(y)
def __str__(self):
return '('+str(self.x)+','+str(self.y)+')'
def main():
p1 = Point(pt1,pt2)
p2 = Point(pt3,pt4)
p3 = Point(pt5,pt6)
p4 = Point(pt7,pt8)
parray = [p1,p2,p3,p4]
print " Points are", p1,p2,p3,p4
print "parray",parray
I m getting the below Output :
Points are (4.0,2.0) (4.0,8.0) (4.0,-1.0) (100.0,1.0)
parray - intersection.Point object at 0x7ff09f00a550, intersection.Point object at 0x7ff09f00a410, intersection.Point object at 0x7ff09f00a590
My question is why are the addresses of objects assigned to array while I get the values while printing the objects?
Can someone suggest a way to get the values returned by class in array in main function?
When you print an object as an individual argument to a print statement in Python 2 or the print() function in Python 3, Python calls str on the object before printing it out.
When you put the object inside a container like a list and print the list, the list gets str called on it, but it in turn calls repr on each of the items it contains, rather than str. To understand why, look at the list [1, '2, 3', 4] and imagine what it would look like if the quotation marks were not included in the output when it was printed. The quotation marks are part of the '2, 3' string's repr.
So to make your class work the way you want, either rename your __str__ method to __repr__ (which will also work for str calls, since the default implementation of __str__ is to call __repr__), or add an additional __repr__ method. Sometimes it's useful to have a __repr__ that returns a less ambiguous string than __str__ does (for instance, it might name the class as well as the arguments). One common convention is to make __repr__ return a string that could be evaled to get an equivalent object again. For your class, that could look like:
def __repr__(self):
return "{}({!r}, {!r})".format(type(self).__name__, self.x, self.y)
I'd also recommend using string formatting like this (or the older %s style if you prefer), rather than concatenating lots of strings together to build your result.
Python containers, e.g. lists use an objects __repr__ method when printing their contents, not their __str__, Define __repr__ instead:
def __repr__(self):
return '('+str(self.x)+','+str(self.y)+')'
If you want a more detailed explanation of __repr__ vs __str__ see here

I am trying to explain my gf how functions work.. heres the code in python but i cant get a way out

askForAge()
takeDecision()
def askForAge():
age = int(input("Enter Age: "))
def takeDecision():
if age>=12:
allowPermission
return
else:
considerPermission()
return
def allowPermission():
print("You are allowed in the park. Enjoy!")
def considerPermission():
if age<9:
print("You are not allowed in the park.")
elif age>=9 and age<12:
print("You need supervision.")
How does this not work? I am trying to explain functions to my gf. I calling the functions and defined them aswell.
You are using age as a local variable, it doesn't keep it's value once each function returns.
You need to mark age global so that multiple functions can work on it. Do this by declaring it outside of the functions with a dummy value, and prefix each function's body with global age.
In addition, you need to add parentheses to your call of allowPermission.

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
>>>

implement set union by typing a+b where a and b are two dictionaries

I want to implement the built in data type set in python using a class and dictionary in python. I have included certain basic functions, but i could not perform the union and intersection operations defined on it. I wish to just write c=a+b where a and b are two dictionaries c is yet another dictionary whose keys give the union of 'a' and 'b'. I tried with try and except as given in my code below, but i want a better solution. can anyone help me with this?
class My_Set:
def __init__(self,listt):
if listt:
self.dictionary={}
i=0
for x in listt:
self.dictionary[x]=len(x)
i=i+1
else:
self.dictionary={}
def is_element(self,element):
if element in self.dictionary:
return True
else:
return False
def remove(self,element):
if element in self.dictionary:
self.dictionary.pop(element)
else:
print 'element missing'
def add_element(self,element):
self.dictionary.update({element:len(element)})
#return self.dictionary
def union(self,other):
self.dictionary.update(other.dictionary)
return self.dictionary.keys()