# Get all possible subsets from a set of distinct integers using OOP

An assignment at school required me to write a program for this task:

1. Create a class and define two methods in the class.
2. Method f1 is used to pass an empty list and the sorted list is taken from the user to method f2.
3. Method f2 is used to compute all possible subsets of the list.
4. Then the result is returned from the function and printed.
5. Exit

Here is my solution to this task, using Python:

class sub:
def f1(self, s1):
return self.f2([], sorted(s1))

def f2(self, current, s1):
if s1:
return self.f2(current, s1[1:]) + self.f2(current + [s1], s1[1:])
return [current]
a = []
n = int(input("Enter number of elements of list: "))
for i in range(0,n):
b = int(input("Enter element: "))
a.append(b)
print ("Subsets: ")
print (sub().f1(a))


NOTE - Method f2 is a recursive function.

Here are some example inputs and outputs:

Enter number of elements of list: 2
Enter element: 4
Enter element: 5
Subsets:
[[], , , [4, 5]]

Enter number of elements of list: 4
Enter element: 3
Enter element: 5
Enter element: 7
Enter element: 28
Subsets:
[[], , , [7, 28], , [5, 28], [5, 7], [5, 7, 28], , [3, 28], [3, 7], [3, 7, 28], [3, 5], [3, 5, 28], [3, 5, 7], [3, 5, 7, 28]


So, I would like to know whether I could make this program shorter and more efficient.

Any help would be highly appreciated.

• Sorry if you've felt passed over when I removed the performance tag. Performance is not an issue in your case, this tag is meant for code where the runtime is critical and/or should be reduced. – AlexV May 21 at 8:12
• @AlexV - Ohh... Now I know. Removed it. Thank you :) – Justin May 21 at 8:17
• Just so that you've heard about it: There is a tag wiki for each tag (I guess - have not checked them all) describing precisely what the tag is about. – AlexV May 21 at 8:26
• Never do this in production code. A function is more than sufficient. OOP is just clutter for generating a power set. Be aware that whatever you got this from is teaching you un-Pythonic patterns and going against the normal idioms of the language. – jpmc26 Jul 14 at 10:11

I. This chunk of code:

a = []
n = int(input("Enter number of elements of list: "))
for i in range(0,n):
b = int(input("Enter element: "))
a.append(b)


is mostly C-like (or Pascal-like etc). You can replace it with more Pythonic:

a = input('Enter elements splitted by ":" ').split(' ')

II. Here:

print (sub().f1(a))

You are creating a sub instance within the print function. It is a bad idea because it will disappear after print. You should create it before you print something (and, yes, classes names in Python are in CamelCase):

waka = Sub()
print(waka.f1(a))


III. I prefer to create __init__() function each time I create a class. It is not really necessary but in most cases, it is the first one is creating in the new class:

class Sub(object):
def __init__(self):
pass


IV. If it is your homework you should do with recursion, the code is pretty OK. In another case, I recommend you to use Python itertools module (you should avoid recursion as much as possible):

    def f2(self, current, s1):
return [
e
for e in itertools.chain.from_iterable([
[sorted(l) for l in itertools.combinations(s1, length)]
for length in range(1, len(s1))
])
]


So here is the result code for recursion version:

class Sub(object):
def __init__(self):
pass

def f1(self, s1):
return self.f2([], sorted(s1))

def f2(self, current, s1):
if s1:
return self.f2(current, s1[1:]) + self.f2(current + [s1], s1[1:])
return [current]

a = input('Enter elements splitted by " ": ').split(' ')
waka = Sub()
print(waka.f1(a))

• Upvoted! Thanks for the very detailed response! Some really good stuff in here! – Justin May 21 at 15:30
• I don't think the outer [] are needed within the chain.from_iterable, and list(...) instrad of [e for e in... ] – Maarten Fabré May 21 at 21:54