This is one way of doing this through subclassing:
class CustomDict(dict):
    def __init__(self, dic):
        self.dic = dic
    def __getitem__(self, items):
        values = []
        for item in items:
            values.append(self.dic[item])
        return values if len(values) > 1 else values[0]
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
new_d = CustomDict(d)
print(new_d['a'])
print(new_d['a', 'b'])
print(new_d['a', 'b', 'c'])
print(new_d['a', 'c', 'd'])
Output:
1
[1, 2]
[1, 2, 3]
[1, 3, 4]
Explanation:
The new_d is an object of the CustomDict class, it will always fall back to the parent class's methods (so that looping over the object and other things you might want to do to a dictionary work) except when one of the overriden methods (init, getitem) get called.
So when one uses new_d['a', 'b'] the overriden __getitem__ method gets called. The overriden method uses the __getitem__ of the self.dic (which is a normal dictionary) to actually access the dictionary values for every key given.