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…
Related
I have some simple code to find the indexes of 2 elements that add up to a sum. (assume sum exists in list)
class Solution(object):
def twoSum(self, nums, target):
compliment = []
for ind, item in enumerate(nums):
print(ind)
if item in compliment:
return [nums.index(target - item), ind]
compliment.append(target - item)
return [0, 0]
if __name__ == "__main__":
result = Solution()
final = result.twoSum([3, 3], 6)
#Why does this not work without removing the self parameter??
#final = Solution.twoSum([3, 3], 6)
print(str(final))
I'm trying to learn how to instantiate an object best in Python. In my main function, I thought I'd simplify it by doing it in 1 line instead of 2. You can see my 2 attempts to call the function in this class. The 2nd fails, unless I remove the self parameter from the function parameters. It's because I'm trying to pass 2 instead of 3 arguments.
Anyways, I'm confused why my two implementations are different and why one works and the other doesn't. I'm also not sure I even need self here at all. It seems like self is mostly used when you have __init__ and are defining variables for the class? Since I'm not doing that here, do I even need it at all?
The self parameter is only required (and will only work) for instance methods. Instance methods are also the default type. To use it without an instance, and without the self parameter, decorate it as a staticmethod:
class Solution(object):
#staticmethod
def twoSum(nums, target):
compliment = []
for ind, item in enumerate(nums):
print(ind)
if item in compliment:
return [nums.index(target - item), ind]
compliment.append(target - item)
return [0, 0]
if __name__ == "__main__":
final = Solution.twoSum([3, 3], 6)
print(str(final))
You can opt to either decorating your function with as a staticmethod or a classmethod in Python. In the case of the classmethod, you would need to have cls in the method signature. Here is a good discussion to distinguish the two:
What is the difference between #staticmethod and #classmethod?
BTW — for your code, I would highly suggest using a set instead of an array. It will make your code much more efficient. Checking if the target value was already seen in a set is a constant time operation on average.
I have found some nice examples (here, here) of implementing SICP-like streams in Python. But I am still not sure how to handle an example like the integral found in SICP 3.5.3 "Streams as signals."
The Scheme code found there is
(define (integral integrand initial-value dt)
(define int
(cons-stream initial-value
(add-streams (scale-stream integrand dt)
int)))
int)
What is tricky about this one is that the returned stream int is defined in terms of itself (i.e., the stream int is used in the definition of the stream int).
I believe Python could have something similarly expressive and succinct... but not sure how. So my question is, what is an analogous stream-y construct in Python? (What I mean by a stream is the subject of 3.5 in SICP, but briefly, a construct (like a Python generator) that returns successive elements of a sequence of indefinite length, and can be combined and processed with operations such as add-streams and scale-stream that respect streams' lazy character.)
There are two ways to read your question. The first is simply: How do you use Stream constructs, perhaps the ones from your second link, but with a recursive definition? That can be done, though it is a little clumsy in Python.
In Python you can represent looped data structures but not directly. You can't write:
l = [l]
but you can write:
l = [None]
l[0] = l
Similarly you can't write:
def integral(integrand,initial_value,dt):
int_rec = cons_stream(initial_value,
add_streams(scale_stream(integrand,dt),
int_rec))
return int_rec
but you can write:
def integral(integrand,initial_value,dt):
placeholder = Stream(initial_value,lambda : None)
int_rec = cons_stream(initial_value,
add_streams(scale_stream(integrand,dt),
placeholder))
placeholder._compute_rest = lambda:int_rec
return int_rec
Note that we need to clumsily pre-compute the first element of placeholder and then only fix up the recursion for the rest of the stream. But this does all work (alongside appropriate definitions of all the rest of the code - I'll stick it all at the bottom of this answer).
However, the second part of your question seems to be asking how to do this naturally in Python. You ask for an "analogous stream-y construct in Python". Clearly the answer to that is exactly the generator. The generator naturally provides the lazy evaluation of the stream concept. It differs by not being naturally expressed recursively but then Python does not support that as well as Scheme, as we will see.
In other words, the strict stream concept can be expressed in Python (as in the link and above) but the idiomatic way to do it is to use generators.
It is more or less possible to replicate the Scheme example by a kind of direct mechanical transformation of stream to generator (but avoiding the built-in int):
def integral_rec(integrand,initial_value,dt):
def int_rec():
for x in cons_stream(initial_value,
add_streams(scale_stream(integrand,dt),int_rec())):
yield x
for x in int_rec():
yield x
def cons_stream(a,b):
yield a
for x in b:
yield x
def add_streams(a,b):
while True:
yield next(a) + next(b)
def scale_stream(a,b):
for x in a:
yield x * b
The only tricky thing here is to realise that you need to eagerly call the recursive use of int_rec as an argument to add_streams. Calling it doesn't start it yielding values - it just creates the generator ready to yield them lazily when needed.
This works nicely for small integrands, though it's not very pythonic. The Scheme version works by optimising the tail recursion - the Python version will exceed the max stack depth if your integrand is too long. So this is not really appropriate in Python.
A direct and natural pythonic version would look something like this, I think:
def integral(integrand,initial_value,dt):
value = initial_value
yield value
for x in integrand:
value += dt * x
yield value
This works efficiently and correctly treats the integrand lazily as a "stream". However, it uses iteration rather than recursion to unpack the integrand iterable, which is more the Python way.
In moving to natural Python I have also removed the stream combination functions - for example, replaced add_streams with +=. But we could still use them if we wanted a sort of halfway house version:
def accum(initial_value,a):
value = initial_value
yield value
for x in a:
value += x
yield value
def integral_hybrid(integrand,initial_value,dt):
for x in accum(initial_value,scale_stream(integrand,dt)):
yield x
This hybrid version uses the stream combinations from the Scheme and avoids only the tail recursion. This is still pythonic and python includes various other nice ways to work with iterables in the itertools module. They all "respect streams' lazy character" as you ask.
Finally here is all the code for the first recursive stream example, much of it taken from the Berkeley reference:
class Stream(object):
"""A lazily computed recursive list."""
def __init__(self, first, compute_rest, empty=False):
self.first = first
self._compute_rest = compute_rest
self.empty = empty
self._rest = None
self._computed = False
#property
def rest(self):
"""Return the rest of the stream, computing it if necessary."""
assert not self.empty, 'Empty streams have no rest.'
if not self._computed:
self._rest = self._compute_rest()
self._computed = True
return self._rest
def __repr__(self):
if self.empty:
return '<empty stream>'
return 'Stream({0}, <compute_rest>)'.format(repr(self.first))
Stream.empty = Stream(None, None, True)
def cons_stream(a,b):
return Stream(a,lambda : b)
def add_streams(a,b):
if a.empty or b.empty:
return Stream.empty
def compute_rest():
return add_streams(a.rest,b.rest)
return Stream(a.first+b.first,compute_rest)
def scale_stream(a,scale):
if a.empty:
return Stream.empty
def compute_rest():
return scale_stream(a.rest,scale)
return Stream(a.first*scale,compute_rest)
def make_integer_stream(first=1):
def compute_rest():
return make_integer_stream(first+1)
return Stream(first, compute_rest)
def truncate_stream(s, k):
if s.empty or k == 0:
return Stream.empty
def compute_rest():
return truncate_stream(s.rest, k-1)
return Stream(s.first, compute_rest)
def stream_to_list(s):
r = []
while not s.empty:
r.append(s.first)
s = s.rest
return r
def integral(integrand,initial_value,dt):
placeholder = Stream(initial_value,lambda : None)
int_rec = cons_stream(initial_value,
add_streams(scale_stream(integrand,dt),
placeholder))
placeholder._compute_rest = lambda:int_rec
return int_rec
a = truncate_stream(make_integer_stream(),5)
print(stream_to_list(integral(a,8,.5)))
[Sorry, I'm new in Python. Although it seems to be a very basic question, I did my share of due diligence before asking this audience, trying to avoid really stupid questions].
I'm trying to figure out the correct idiom for returning an l-value from a function. Assume I've a container of 64 objects, and I want to be able to return a reference to these objects.
class ChessBoard:
def __init__(self):
self.squares = [None for x in range(64)]
square( row, col ):
return self.squares(row*8+col) <---- I'd like this to be l-value
Then, from outside the class I want to:
board = ChessBoard()
board.square(0,0) = Piece( Shapes.ROOK, Colors.White ) <-- I'm getting an error here
board.square(0,1) = Piece( Shapes.BISHOP, Colors.White )
... etc.
So, I would like the function 'at' to return a lvalue (Something like a reference in C++), but I can't find anything resembling a reference or a pointer in the language. If I stored a list in each square containing one Piece, it is possible I could do something like: board.square(0,0)[0] = Piece - but it seems crazy (or maybe not - as I said, I'm new to the language).
How would you approach this data structure?
In Python, everything is a reference. The only problem is that None is immutable, so you can't use the returned reference to change the value.
You also can't override the assignment operator, so you won't get this particular kind of behaviour. However, a good and very flexible solution would be to override the __setitem__ and __getitem__ methods to implement the subscription operator ([]) for the class:
class ChessBoard(object):
def __init__(self):
self.squares = [None] * 64
def __setitem__(self, key, value):
row, col = key
self.squares[row*8 + col] = value
def __getitem__(self, key):
row, col = key
return self.squares[row*8 + col]
Usage:
>>> c = ChessBoard()
>>> c[1,2] = 5
>>> c[1,2]
5
You can try something like this, at the cost of having to put bogus [:] indexers around:
class Board:
def __init__(self):
self.squares=[None for x in range(64)]
def square(self, row, col):
squares=self.squares
class Prox:
def __getitem__(self, i):
return squares[row*8+col]
def __setitem__(self, i, v):
squares[row*8+col]=v
return Prox()
Then you can do
b=Board()
b.square(2,3)[:]=Piece('Knight')
if b.square(x,y)[:] == Piece('King') ...
And so on. It doesn't actually matter what you put in the []s, it just has to be something.
(Got the idea from the Proxies Perl6 uses to do this)
As Niklas points out, you can't return an l-value.
However, in addition to overriding subscription, you can also use properties (an application of descriptors: http://docs.python.org/howto/descriptor.html) to create an object attribute, which when read from, or assigned to, runs code.
(Not answering your question in the title, but your "How would you approach this data structure?" question:) A more pythonic solution for your data structure would be using a list of lists:
# define a function that generates an empty chess board
make_chess_board = lambda : [[None for x in xrange(8)] for y in xrange(8)]
# grab an instance
b = make_chess_board()
# play the game!
b[0][0] = Piece(Shapes.ROOK, Colors.White)
b[0][1] = Piece(Shapes.BISHOP, Colors.White)
# Or use tuples:
b[0][0] = (Shapes.ROOK, Colors.White)
b[0][1] = (Shapes.BISHOP, Colors.White)
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.
I just learned yesterday from this site that I can:
class Seq(object):
def __init__(self, seq):
self.seq = seq
def __repr__(self):
return repr(self.seq)
def __str__(self):
return str(self.seq)
def all(self):
return Seq(self.seq[:])
def head(self, count):
return Seq(self.seq[:count])
def tail(self, count):
return Seq(self.seq[-count:])
def odd(self):
return Seq(self.seq[1::2])
def even(self):
return Seq(self.seq[::2])
def reverse(self):
return Seq(self.seq[::-1])
>>> s = Seq(range(0, 100))
>>> print s.head(10).odd().even().reverse()
[9, 5, 1]
I want to enumerate possible combination of those sequence method chains inside of class Seq, may sort of:
itertools.product([s.head,s.odd,s.even,s.reverse], repeat=4)
# may not just limited those 4 functions
how to use the itertools.product() to
1). generate invoke-able function chains list? just like this:
foo = s.head().odd().even().reverse()
2). generate eval()able chain strings then I can store in ascii file or eval() later or for logging purpose?
the head(), tail() may accept parameter, and even(), odd() is not need to, for example,
the paremeter of head() and tail() may from lists:
head_lmt = [10,20,30]
tail_lmt = [30,40,50]
foo = s.head().odd().tail().reverse()
^------------------------------------head_lmt 10 or 20 or 30
^-----------------------tail_lmt 30 or 40 or 50
If my Q1 is possible, how I can fill those parameter into the invoke-able list and the eval()-able string, a.k.a generate more specific invoke-able list and the eval()-able string?
Thanks!
Note that something like "s.head()" means a method which is "bound" to that specific instance of Seq, that is, "s." Something like "Seq.head()" means a method which is unbound, so one can still pass in different instances of Seq.
From there it simply requires basic functional composition and string concatenation.
def chain_method(from_method, to_method):
def inner(arg):
return to_method(from_method(arg))
return inner
possible_funcs = []
log_strings = []
for possible_combo in itertools.product([Seq.head,Seq.odd,Seq.even,Seq.reverse], repeat=4):
meta_method = possible_combo[0]
for method in possible_combo[1:]:
meta_method = chain_method(meta_method, method)
log_string = []
for method in possible_combo:
log_string.extend(['.', method.__name__, '()'])
possible_funcs.append(meta_method)
log_strings.append("".join(log_string))
I'm not sure what you mean by the examples for the additional parameters, though. How do you intend to combine the different parameter values with the different combinations of functions?