I am going through functions in Learning Python, this one is giving me a little trouble understanding, was wondering if anyone could help me understand it better, more specifically the if test(arg, res)
When I run the first function, it doesn't matter what I put as the first argument, then the second argument has to be a list, and it just spits the list back as written. I'm confused on when you combine the functions and print them together how it gives the max and min.
def minmax(test, *args):
res = args[0]
for arg in args[1:]:
if test(arg, res):
res = arg
return res
def lessthan(x, y): return x < y
def grtrthan(x, y): return x > y
print(minmax(lessthan, 4, 2, 1, 5, 6, 3))
print(minmax(grtrthan, 4, 2, 1, 5, 6, 3))
You seem to be misunderstanding how the starred function argument works. When you call your function as minmax(something, [1, 2, ...]), args becomes a tuple of one element equal to [1, 2, ...]. Therefore the body of the loop never gets executed and the value of test does not matter. The function is supposed to be invoked as minmax(something, 1, 2, ...). This way args gets the value (1, 2, ...) and the loop goes through its elements.
Clarification: The answer is based on what you wrote. Your code snippet is correct and works exactly as intended.
I haven't read that book so I don't know the context, but it looks that function (minmax) is not well named. It does not return two values, it only returns one -- and which one depends on the testing function you give it. If you pass in the lessthan function:
print(minmax(lessthan, 4, 2, 1, 5, 6, 3))
you'll get 1, and if you pass in the grtrthan function:
print(minmax(grtrthan, 4, 2, 1, 5, 6, 3))
you'll get 6.
Related
When calling the function below, I can provide values that will be used instead of the default parameters in the function (see below).
cerebro.addstrategy(GoldenCross, fast=10, slow=25)
This works great for a small number of known parameters, but I am moving up to more complex systems. Essentially, I need to pass a fast_1, fast_2, fast_3, etc.... The total amount of these parameters will change (always around 100, but it can vary). Is there a statement that I can write that will dynamically add X amount of parameters to my function call?
I have tried using a for statement in the function call, but I received a syntax error.
I understood your question of two ways:
You want to call your function passing to it different parameters (that are optional), you can accomplish it like this:
def add(first, second=0, third=3):
return (first+second+third)
number_list = list(range(1, 200)) # Generates a list of numbers
result = [] # Here will be stored the results
for number in number_list:
# For every number inside number_list the function add will
# be called, sending the corresponding number from the list.
returned_result = add(1,second=number)
result.insert(int(len(result)), returned_result)
print(result) # Can check the result printing it
You want your function handles any number of optional parameters, as you don't know any way to determine how many they are, you can send a list or parameters, like this:
def add(first,*argv):
for number in argv:
first += number
return first
number_list = (list(range(1, 200))) # Generates a list of numbers
result = add(1,*number_list) # Store the result
print(result) # Can check the result printing it
Here you can find more information about *args
how about using *?
def addstrategy(GoldenCross, *fast, slow = 25): can be an example.
>>> def foo(a, *b, c = 36):
print(a, b, c)
>>> foo(1, 2, 3, 4, 5)
1 (2, 3, 4, 5) 36
You need to initialize fast in this case, however.
Two ways: Either use a variable number of arguments using * on the parameter or treat the parameter as an iterable.
def fun1(positional, optional="value", *args):
print(args) # args here is a tuple, since by default variable number of args using * will make that parameter a tuple.
def fun2(positional, args, optional="value"):
print(args) # args here will be dependant on the argument you passed.
fun1("some_value", "value", 1, 2, 3, 4, 5) # args = (1, 2, 3, 4, 5)
fun2("some_value", [1, 2, 3, 4, 5]) # args = [1, 2, 3, 4, 5]
I am trying to create a function that will take a tuple and remove the first instance of a value. For example:
print(Remove((0, 1, 2, 1, 3), 1))
should return (0, 2, 1, 3).
I am using functional programming and not using any predefined functions. I'm allowed to use only lambda, filter, map, and reduce but nothing else. I can't use list.remove or for-loops.
I assume a filter function will work best for this. I have figured out that the following function will work to remove all instances of the value E. I now need to know how to just remove the first instance of E.
def Remove(T,E):
return tuple(filter(lambda x: x!=E, T))
This can be done with simple recursion
If the input tuple, t, is empty, return the empty result
(inductive) Otherwise t is not empty - t has at least one element. If the first element of t matches the element to remove, x, return the tail of the tuple
(inductive) Otherwise, t is not empty and the first element of t does not match the element to remove, x. Create a new tuple with the first element of t and the recursive result
Numbered comments below correspond to the explanation above -
def remove(t, x):
if not t: # 1
return ()
elif t[0] == x: # 2
return t[1::]
else: # 3
return (t[0], *remove(t[1::], x))
print(remove((0, 1, 2, 1, 3), 1))
# (0, 2, 1, 3)
Python has an eccentric syntax for interacting with elements of collections. By defining a few helper functions, we can establish a robust and consistent way of writing this kind of program -
def is_empty(x):
return not x
def head(x):
if is_empty(x)
raise RuntimeError("head called on empty input")
else:
return x[0]
def tail(x):
if is_empty(x)
raise RuntimeError("tail called on empty input")
else:
return x[1::]
def remove(t, x):
if is_empty(x):
return ()
elif head(t) == x:
return tail(t)
else:
return (head(t), *remove(tail(t), x))
print(remove((0, 1, 2, 1, 3), 1))
# (0, 2, 1, 3)
numbers = (2, 3, 1, 4, 2, 3, 6)
e = 3 # element to remove
nums_removed = tuple(
filter(
lambda x, found=[False, True]: not (not found[0] and x == e and found.reverse() is None),
numbers
)
)
print(nums_removed)
Output:
(2, 1, 4, 2, 3, 6)
However, I can't understand why someone would want to write code so bad. It's like going from USA to USA via India.
The point is to use functional programming when it produces a simpler and more beautiful code and use anything else that is already available to make life easier.
I ended up writing a lambda function which I myself don't really understand completely, but it works. I kept trying different approaches to see what works because I was bored. You can't have local variables inside lambda functions, so I used a mutable default argument found to save function state. I posted it as an answer as soon as it worked.
If someone wants to add an explanation to my answer, feel free to edit it.
I am trying to code a recursive function that generates all the lists of numbers < N who's sum equal to N in python
This is the code I wrote :
def fn(v,n):
N=5
global vvi
v.append(n) ;
if(len(v)>N):
return
if(sum(v)>=5):
if(sum(v)==5): vvi.append(v)
else:
for i in range(n,N+1):
fn(v,i)
this is the output I get
vvi
Out[170]: [[1, 1, 1, 1, 1, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5]]
I tried same thing with c++ and it worked fine
What you need to do is to just formulate it as a recursive description and implement it. You want to prepend all singleton [j] to each of the lists with sum N-j, unless N-j=0 in which you also would include the singleton itself. Translated into python this would be
def glist(listsum, minelm=1):
for j in range(minelm, listsum+1):
if listsum-j > 0:
for l in glist(listsum-j, minelm=j):
yield [j]+l
else:
yield [j]
for l in glist(5):
print(l)
The solution contains a mechanism that will exclude permutated solutions by requiring the lists to be non-decreasing, this is done via the minelm argument that limits the values in the rest of the list. If you wan't to include permuted lists you could disable the minelm mechanism by replacing the recursion call to glist(listsum-j).
As for your code I don't really follow what you're trying to do. I'm sorry, but your code is not very clear (and that's not a bad thing only in python, it's actually more so in C).
First of all it's a bad idea to return the result from a function via a global variable, returning result is what return is for, but in python you have also yield that is nice if you want to return multiple elements as you go. For a recursive function it's even more horrible to return via a global variable (or even use it) since you are running many nested invocations of the function, but have only one global variable.
Also calling a function fn taking arguments v and n as argument. What do that actually tell you about the function and it's argument? At most that it's a function and probably that one of the argument should be a number. Not very useful if somebody (else) is to read and understand the code.
If you want an more elaborate answer what's formally wrong with your code you should probably include a minimal, complete, verifiable example including the expected output (and perhaps observed output).
You may want to reconsider the recursive solution and consider a dynamic programming approach:
def fn(N):
ways = {0:[[]]}
for n in range(1, N+1):
for i, x in enumerate(range(n, N+1)):
for v in ways[i]:
ways.setdefault(x, []).append(v+[n])
return ways[N]
>>> fn(5)
[[1, 1, 1, 1, 1], [1, 1, 1, 2], [1, 2, 2], [1, 1, 3], [2, 3], [1, 4], [5]]
>>> fn(3)
[[1, 1, 1], [1, 2], [3]]
Using global variables and side effects on input parameters is generally consider bad practice and you should look to avoid.
I am trying to code "1024" using python basic library. In the process I try to make a list [0, 2, 4, 4] become [0, 2, 8, 0]. So here is my test code. It's very easy one.
def merger(a, b):
if a == b:
a += b
b = 0
numlist = [0, 2, 4, 4]
merger(numlist[0], numlist[1])
merger(numlist[1], numlist[2])
merger(numlist[2], numlist[3])
print (numlist)
So when I try to conduct merge. I expected the output [0, 2, 8, 0]. However it gives me [0, 2, 4, 4] instead. I think maybe it's because I just changed the local variable of my function a b rather than the actual parameter? But If I want this to happen, what should I do? Thx!
I think I want to know generally if I want a function not return anything but just change value of the variable I passed as parameter. How can I achieve it?
You can pass the list and indexes to the function:
def merger(l, a, b):
if l[a] == l[b]:
l[a] += l[b]
l[b] = 0
numlist = [0, 2, 4, 4]
merger(numlist, 0, 1)
merger(numlist, 1, 2)
merger(numlist, 2, 3)
print(numlist)
As list object will be passed by reference and any changes on the list inside the function will be effective after the function call.
I have a Python function that takes a list as a parameter. If I set the parameter's default value to an empty list like this:
def func(items=[]):
print items
Pylint would tell me "Dangerous default value [] as argument". So I was wondering what is the best practice here?
Use None as a default value:
def func(items=None):
if items is None:
items = []
print items
The problem with a mutable default argument is that it will be shared between all invocations of the function -- see the "important warning" in the relevant section of the Python tutorial.
I just encountered this for the first time, and my immediate thought is "well, I don't want to mutate the list anyway, so what I really want is to default to an immutable list so Python will give me an error if I accidentally mutate it." An immutable list is just a tuple. So:
def func(items=()):
print items
Sure, if you pass it to something that really does want a list (eg isinstance(items, list)), then this'll get you in trouble. But that's a code smell anyway.
For mutable object as a default parameter in function- and method-declarations the problem is, that the evaluation and creation takes place at exactly the same moment. The python-parser reads the function-head and evaluates it at the same moment.
Most beginers asume that a new object is created at every call, but that's not correct! ONE object (in your example a list) is created at the moment of DECLARATION and not on demand when you are calling the method.
For imutable objects that's not a problem, because even if all calls share the same object, it's imutable and therefore it's properties remain the same.
As a convention you use the None object for defaults to indicate the use of a default initialization, which now can take place in the function-body, which naturally is evaluated at call-time.
In addition and also to better understand what python is, here my little themed snippet:
from functools import wraps
def defaultFactories(func):
'wraps function to use factories instead of values for defaults in call'
defaults = func.func_defaults
#wraps(func)
def wrapped(*args,**kwargs):
func.func_defaults = tuple(default() for default in defaults)
return func(*args,**kwargs)
return wrapped
def f1(n,b = []):
b.append(n)
if n == 1: return b
else: return f1(n-1) + b
#defaultFactories
def f2(n,b = list):
b.append(n)
if n == 1: return b
else: return f2(n-1) + b
>>> f1(6)
[6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1]
>>> f2(6)
[1, 2, 3, 4, 5, 6]