I'm sure there is a term for what I'm looking for, or if there's not, there is a very good reason what I'm trying to do is in fact silly.
But anyway. I'm wondering whether there is a (quasi) built-in way of finding a certain class instance that has a property set to a certain value.
An example:
class Klass(object):
def __init__(self, value):
self.value = value
def square_value(self):
return self.value * self.value
>>> a = Klass(1)
>>> b = Klass(2)
>>> instance = find_instance([a, b], value=1)
>>> instance.square_value()
1
>>> instance = find_instance([a, b], value=2)
>>> instance.square_value()
4
I know that I could write a function that loops through all Klass instances, and returns the ones with the requested values. On the other hand, this functionality feels as if it should exist within Python already, and if it's not, that there must be a very good reasons why it's not. In other words, that what I'm trying to do here can be done in a much better way.
(And of course, I'm not looking for a way to square a value. The above is just an example of the construct I'm trying to look for).
Use filter:
filter(lambda obj: obj.value == 1, [a, b])
Filter will return a list of objects which meet the requirement you specify. Docs: http://docs.python.org/library/functions.html#filter
Bascially, filter(fn, list) iterates over list, and applies fn to each item. It collects all of the items for which fn returns true, puts then into a list, and returns them.
NB: filter will always return a list, even if there is only one object which matches. So if you only wanted to return the first instance which matches, you'd have to to something like:
def find_instance(fn, objs):
all_matches = filter(fn, objs)
if len(all_matches) == 0:
return False # no matches
else:
return all_matches[0]
or, better yet,
def find_instance(fn, objs):
all_matches = filter(fn, objs)
return len(all_matches) > 0 and all_matches[0] # uses the fact that 'and' returns its second argument if its first argument evaluates to True.
Then, you would call this function like this:
instance = find_instance(lambda x: x.value == 1, [a, b])
and then instance would be a.
A more efficient version of Ord's answer, if you are looking for just one matching instance, would be
def find_instance(fn, objs):
all_matches = (o for o in objs if fn(objs))
return next(all_matches, None)
instance = find_instance(lambda x: x.value == 1, [a, b])
This will stop the search as soon as you find the first match (good if your test function is expensive or your list is large), or None if there aren't any matches.
Note that the next function is new in Python 2.6; in an older version, I think you have to do
try:
return all_matches.next()
except StopIteration:
return None
Of course, if you're just doing this once, you could do it as a one-liner:
instance = next((o for o in [a, b] if o.value == 1), None)
The latter has the advantage of not doing a bunch of function calls and so might be slightly faster, though the difference will probably be trivial.
Related
I have a problem where I need to produce something which is naturally computed recursively, but where I also need to be able to interrogate the intermediate steps in the recursion if needed.
I know I can do this by passing and mutating a list or similar structure. However, this looks ugly to me and I'm sure there must be a neater way, e.g. using generators. What I would ideally love to be able to do is something like:
intermediate_results = [f(x) for x in range(T)]
final_result = intermediate_results[T-1]
in an efficient way. While my solution is not performance critical, I can't justify the massive amount of redundant effort in that first line. It looks to me like a generator would be perfect for this except for the fact that f is fundamentally much more suited to recursion in my case (which at least in my mind is the complete opposite of a generator, but maybe I'm just not thinking far enough outside of the box).
Is there a neat Pythonic way of doing something like this that I just don't know about, or do I just need to just capitulate and pollute my function f by passing it an intermediate_results list which I then mutate as a side-effect?
I have a generic solution for you using a decorator. We create a Memoize class which stores the results of previous times the function is executed (including in recursive calls). If the arguments given have already been seen, the cached versions are used to quickly lookup the result.
The custom class has the benefit over an lru_cache in that you can see the results.
from functools import wraps
class Memoize:
def __init__(self):
self.store = {}
def save(self, fun):
#wraps(fun)
def wrapper(*args):
if args not in self.store:
self.store[args] = fun(*args)
return self.store[args]
return wrapper
m = Memoize()
#m.save
def fibo(n):
if n <= 0: return 0
elif n == 1: return 1
else: return fibo(n-1) + fibo(n-2)
Then after running different things you can see what the cache contains. When you run future function calls, m.store will be used as a lookup so calculation doesn't need to be redone.
>>> f(8)
21
>>> m.store
{(1,): 1,
(0,): 0,
(2,): 1,
(3,): 2,
(4,): 3,
(5,): 5,
(6,): 8,
(7,): 13,
(8,): 21}
You could modify the save function to use the name of the function and the args as the key, so that multiple function results can be stored in the same Memoize class.
You can use your existing solution that makes many "redundant" calls to f, but employ the use of function caching to save the results to previous calls to f.
In other words, when f(x1) is called, it's input arguments and corresponding return values are saved, and the next time it is called, the result is simply pulled from the cache
see functools.lru_cache for the standard library solution to this
ie:
from functools import lru_cache
#lru_cache
intermediate_results = [f(x) for x in range(T)]
final_result = intermediate_results[T-1]
Note, however, f must be a pure function (no side-effects, 1-to-1 mapping) for this to work properly
Having considered your comments, I'll now try to give another perspective on the problem.
So, let's consider a concrete example:
def f(x):
a = 2
return g(x) + a if x != 0 else 0
def g(x):
b = 1
return h(x) - b
def h(x):
c = 1/2
return f(x-1)*(1+c)
I
First of all, it should be mentioned that (in our particular case) the algorithm has form of: f(x) = p(f(x - 1)) for some p. It follows that f(x) = p^x(f(0)) = p^x(0). That means we should just apply p to 0 x times to get the desired result, which can be done in an iterative process, so this can be written without recursion. Though I believe that your real case is much harder. Moreover, it would be too boring and uninformative to stop here)
II
Generally speaking, we can divide all possible solutions into two groups: the ones that require refactoring (i.e. rewriting functions f, g, h) and the ones that do not. I have little to offer from the latter one (and I don't think anyone can). Consider the following, however:
def fk(x, k):
a = 2
return k(gk(x, k) + a if x != 0 else 0)
def gk(x, k):
b = 1
return k(hk(x, k) - b)
def hk(x, k):
c = 1/2
return k(fk(x-1, k)*(1+c))
def printret(x):
print(x)
return x
f(4, printret) # see what happens
Inspired by continuation-passing style, but that's totally not it.
What's the point? It's something between your idea of passing a list to write down all the computations and memoizing. This k carries additional behavior with it, such as printing or writing to list (you can make a function that writes to some list, why not?). But if you look carefully you'll see that it lefts inner code of these functions practically untouched (only input and output to function are affected), so one can produce a decorator associated with a function like printret that does essentially the same thing for f, g, h.
Pros: no need to modify code, much more flexible than passing a list, no additional work (like in memoizing).
Cons: Impure (printing or modifying sth), not so flexible as we would like.
III
Now let's see how modifying function bodies can help. Don't be afraid of what's written below, take your time and play with that thing a little.
class Logger:
def __init__(self, lst, cur_val):
self.lst = lst
self.cur_val = cur_val
def bind(self, f):
res = f(self.cur_val)
return Logger([self.cur_val] + res.lst + self.lst, res.cur_val)
def __repr__(self):
return "Logger( " + repr({'value' : self.cur_val,'lst' : self.lst}) + " )"
def unit(x):
return Logger([], x)
# you can also play with lala
def lala(x):
if x <= 0:
return unit(1)
else:
return lala(x - 1).bind(lambda y: unit(2*y))
def f(x):
a = 2
if x == 0:
return unit(0)
else:
return g(x).bind(lambda y: unit(y + a))
def g(x):
b = 1
return h(x).bind(lambda y: unit(y - b))
def h(x):
c = 1/2
return f(x-1).bind(lambda y: unit(y*(1+c)))
f(4) # see for yourself
Logger is called a monad. I'm not very familiar with this concept myself, but I guess I'm doing everything right) f, g, h are functions that take a number and return a Logger instance. Logger's bind takes in a function (like f) and returns Logger with new value (computed by f) and updated 'logs'. The key point - as I see it - is the ability to do whatever we want with collected functions in the order the resulting value was calculated.
Afterword
I'm not at all some kind of 'guru' of functional programming, I believe I'm missing a lot of things here. But what I've understood is that functional programming is about inversing the flow of the program. That's why, for instance, I totally agree with your opinion about generators being opposed to functional programming. When we use generator gen in, say, function func, we yield values one by one to func and func does sth with them in e.g. a loop. The functional approach would be to make gen a function taking func as a parameter and make func perform computations on 'yielded' values. It's like gen and func exchanged their places. So the flow is inversed! And there are plenty of other ways of inversing the flow. Monads are one of them.
itertools islice gets a generator, start value and stop value. it will give you the elements between the start value and stop value as a generator. if islice is not clear you can check the docs here https://docs.python.org/3/library/itertools.html
intermediate_result = map(f, range(T))
final_result = next(itertools.islice(intermediate_result, start=T-1, stop=T))
Suppose I have a datatype, for example:
List = Datatype('List')
List.declare('cons', ('car', IntSort()), ('cdr', List))
List.declare('nil')
List = List.create()
And I have an instance, by:
s.check()
instance = s.model()[var]
How can i ask which constructor my instance has?
I know I could do something like this:
for i in range(List.num_constructors()):
if List.recognizer(i)(instance):
break
return List.constructor(i)
But this is not a very practical way when the number of constructors is large.
How can i ask this?
Python interface defines recognizers is_cons, is_nil for you, which you can then use for simplifying your code. Something like:
from z3 import *
List = Datatype('List')
List.declare('cons', ('car', IntSort()), ('cdr', List))
List.declare('nil')
List = List.create()
# constructors
cons = List.cons
car = List.car
cdr = List.cdr
nil = List.nil
# recognizers
def is_cons (x): return simplify(List.is_cons(x))
def is_nil (x): return simplify(List.is_nil(x))
def valToConstructor(l):
if is_cons(l):
return "Found cons"
elif is_nil(l):
return "Found nil"
else:
raise Exception('Unexpected list value: {}'.format(l))
# example:
ex1 = nil
ex2 = cons (0, cons (1, ex1))
print valToConstructor(ex1)
print valToConstructor(ex2)
When run, this produces:
Found nil
Found cons
Note that you cannot skip the exception case in valToConstructor since this function might be called with a symbolic value as well; and the recognizers would not fire for those values. But if you always call it with values you get out of a model, it should work just fine.
Directly accessing the constructor
You can also use the decl function for the underlying AST:
>>> ex1.decl()
nil
>>> ex2.decl()
cons
But you have to be careful when the object you're passing is a symbolic value; as in that case decl returns its name:
>>> ex3 = Const('ex3_name', List)
>>> ex3.decl()
ex3_name
But perhaps this is precisely what you're looking for.
I have a function that returns a variable list of values and I know you can do this by using a tuple. To assign these variables you can then do something like a, b = func(..). However, if there is only one value returned you have to do a, = func(..) [notice the ,] rather than a = func(..). To achieve the latter you can include a test to see if there is one value to be returned or more (see example below) but I wonder if there is no easier or less verbose way to do this.
def foo(*args):
returnvalues = []
for arg in args:
arg += 100
returnvalues.append(arg)
if len(returnvalues) == 1:
return returnvalues[0]
else:
return tuple(returnvalues)
def baz(*args):
returnvalues = []
for arg in args:
arg += 100
returnvalues.append(arg)
return tuple(returnvalues)
a = foo(10)
b, c = foo(20, 30)
print(f'a={a}, b={b}, c={c}')
a, = baz(10)
b, c = baz(20, 30)
print(f'a={a}, b={b}, c={c}')
#
a=110, b=120, c=130
a=110, b=120, c=130
I believe you are referring to "tuple unpacking". Also known as destructive assignment. The word "tuple" is a bit of a misnomer as you can use any iterable / iterator. So returning a list is fine.
def f():
return [1]
(a,) = f()
b, = f()
You can also use list syntax on the left hand side. There's no difference to the byte code that is generated. It does make unpacking a single item look less like a syntax error in the case of b and slightly less verbose than a.
[c] = f()
I would avoid returning the value itself and not a list in the special case where only one argument is passed. The reason for this is it makes the code harder to be used in a generic manner. Any caller of the function needs to know how many arguments it's passing or check the return value (which is clumsy). For example:
result = f()
if isinstance(result, (list, tuple)):
smallest = min(result)
else:
smallest = result
# as opposed to this when you always return a list / tuple
smallest = min(f())
You can assign the returning value of such a function to a single variable, so that you can use it as a list or tuple:
a = baz(10, 20, 30)
print(', '.join(map(str, a))) # this outputs 110, 120, 130
Essentially, I would like to know if I should be attempting to avoid side effects in functions if possible, or if side effects are acceptable in certain situations. I would like to have a function which pops and returns a key from a dictionary and am curious if the function should return just the key:
def popkey(d):
k, v = d.popitem()
return k
mykey = popkey(d)
or if it should also return the modified dictionary:
def popkey(d):
k, v = d.popitem()
return k, d
mykey, d = popkey(d)
More specifically, I have something like the following, where I need keep looking through the dictionary, so I wanted to pop the keys as they are paired with the elements from a list.
def pop_nearest(d, pt):
"""Pops the key in `d` which is nearest to pt."""
to_pop = min(d.iterkeys(), key=lambda a: abs(a - pt))
d.pop(to_pop)
pts = [1,3,5,7,9]
for pt in pts:
nearest_pt = pop_nearest(d, pt)
# do some other stuff
There is no need to return the parameter, since you already have a reference to it at the call site.
If you choose to implement pop_nearest as a method in a dict subclass, then it's sometimes a good idea (depending on what you are trying to achieve) to return self so you can chain calls.
class MyDict(dict):
...
def pop_nearest(self, pt):
...
return self
...
x = mydict.pop_nearest(1).pop_nearest(2)
You don't need to return the modified dictionary. It is modified in the function like you would think since it is a reference/pointer to the actual object and not a deep copy and will exist in its modified form in the calling function after pop is called. Returning the key should be sufficient and work how you want it to.
I have a function that works exactly how I want it to, but for my course work, I have to turn this function into a class that:
Must have a function called solveIt,
returns the following two values:
a boolean that is True if you've solved this knapsack problem, and
the knapsack object with the correct values in it.
The class must have a __str__() function that returns a string like this. The first line is the size, and the second is a comma-separated list of the elements:
10
4,1,9,2,0,4,4,4,3,7
I dont understand classes that well, so any help will be appreciated. Here is the function I have right now:
from itertools import combinations
def com_subset_sum(seq, target):
if target == 0 or target in seq:
print(target)
return True
for r in range(len(seq),1,-1):
for subset in combinations(seq, r):
if sum(subset) == target:
print(subset)
return True
return False
print(com_subset_sum([4,1,9,2,0,4,4,4,3,7],10))
One obvious way to transform a function to a class is to turn the function parameters (or some of them) into object attributes. For example:
class Knapsack(object):
def __init__(self, seq, target):
self.seq = seq
self.target = target
self.solution = None
def solveIt(self):
if self.target == 0 or self.target in self.seq:
self.solution = (target,)
return True, self.solution
for r in range(len(self.seq),1,-1):
for subset in combinations(self.seq, r):
if sum(subset) == self.target:
self.solution = subset
return True, self.solution
return False, ()
Now you can do this:
>>> knapsack = Knapsack([4,1,9,2,0,4,4,4,3,7],10)
>>> print(knapsack.solveIt())
(True, (4, 1, 2, 0, 3))
And then, adding a __str__ method is simple:
def __str__(self):
if self.solution is None:
self.solveIt()
return '{}\n{}'.format(len(self.seq),
','.join(map(str, self.solution)))
The reason I added that self.solution is so that calling __str__ over and over won't keep calculating the results over and over. You could just as easily drop that member and write this:
def __str__(self):
solved, solution = self.solveIt()
return '{}\n{}'.format(len(self.seq),
','.join(map(str, solution)))
Either way, I'm not sure how this is better than the function. (In fact, it's strictly worse: with the function, you can always use functools.partial to bind in just the sequence, or both the sequence and the target, or of course bind in neither, whereas with the class, you always have to bind in both.)
Maybe your professor has given you some kind of hints on how you'd want to use this object that might help? Or maybe your professor is just an idiot who doesn't know how to come up with a good motivating assignment for teaching you about classes…