Search code examples
pythonpython-3.xpython-class

Why I can't inherit map in python?


I want to write a self defined class that inherit map class.

class MapT(map):
    def __init__(self, iii):
        self.obj = iii

But I can't initialize it.

# Example init object
ex = map(None,["","1","2"])

exp1 = MapT(ex)
# TypeError: map() must have at least two arguments.

exp1 = MapT(None,ex)
# TypeError: __init__() takes 2 positional arguments but 3 were given

How do I create a class that inherit map in python? Or why I can't inherit map in python?

add

What I want to achieve is add custom method for iterable object

def iter_z(self_obj):
    class IterC(type(self_obj)):
        def __init__(self, self_obj):
            super(iterC, self).__init__(self_obj)
            self.obj = self_obj
        def map(self, func):
            return iter_z(list(map(func, self.obj))) # I want to remove "list" here, but I can't. Otherwise it cause TypeError
        def filter(self, func):
            return iter_z(list(filter(func, self.obj))) # I want to remove "list" here, but I can't. Otherwise it cause TypeError
        def list(self):
            return iter_z(list(self.obj))
        def join(self, Jstr):
            return Jstr.join(self)
return IterC(self_obj)

So that I can do this:

a = iter_z([1,3,5,7,9,100])
a.map(lambda x:x+65).filter(lambda x:x<=90).map(lambda x:chr(x)).join("")
# BDFHJ

Instead of this:

"".join(map(lambda x:chr(x),filter(lambda x:x<=90,map(lambda x:x+65,a))))

Solution

  • You shouldn't be inheriting from the object you're wrapping. That's because your API is different from that type, and there's no good way to ensure you can build a new instance of the class properly. Your map situation is an example of this, your __init__ expects a different number of argumetns than map.__new__ does, and there's no good way to rationalize them.

    Instead of inheriting from the class, just wrap around it. This might limit the API of the type that can be used, but you're mostly focused on the iterator protocol, so probably __iter__ and __next__ are all you need:

    class IterZ:
        def __init__(self, iterable):
            self.iterator = iter(iterable)
    
        def __iter__(self):
            return self
    
        def __next__(self):
            return next(self.iterator)
    
        def map(self, func):
            return IterZ(map(func, self.iterator))
    
        def filter(self, func):
            return IterZ(filter(func, self.iterator))
    
        def join(self, Jstr):
            return Jstr.join(self.iterator)