开发者

Passing subclasses to imported library

I have library which returns collections of some semi-abstract objects.

class Item1(object):
    pass
class Item2(object):
    pass
class Collection1(object):
    pass 

class Provider(object):
    def retrieve_collection(self):
        col = Collection1()
        col.add(Item1())
        col.add(Item2())
        return col

It开发者_运维知识库 just populates attributes of the objects, and these item/collection classes are intended to be subclassed in caller code.

So there would be some script

from mylib import Provider, Item1
class MyItem(Item1):
    pass
provider = Provider()
col = provider.retrieve_collection()

And the question is, what is elegant and pythonic solution to pass MyItem (and any other subclasses) to Provider?

I can pass it as Provider(item1=MyItem), store it as self.item1, and then instantiate it as self.item1() instead of Item1(), but this seems fugly. Plus I'll have horrible, long constructor calls all over client code.

Other option would be to override classes on module level, like mylib.Item1 = MyItem, but this can lead to many unexpected and hard to debug problems. Besides, there could be several different provider classes which use same item base classes, but which would require different subclasses from client.

Maybe some form of classes registry and factories instead of actual classes? So Item1() would try to figure which class to instantiate based on some context, but I'm not sure how that would work.


mylib.py

class Item1(object):
    def __repr__(self):
        return "Base Item1"
class Item2(object):
    def __repr__(self):
        return "Base Item2"
class Collection1(set):
    pass 

class Provider(object):
    Item1=Item1
    Item2=Item2
    def retrieve_collection(self):
        col = Collection1()
        col.add(self.Item1())
        col.add(self.Item2())
        return col

from mylib import Provider

class MyProvider(Provider):
    class Item1(Provider.Item1):
        def __repr__(self):
            return "Subclass Item1"

p=Provider()
print p.retrieve_collection()

p=MyProvider()
print p.retrieve_collection()

Output:

Collection1([Base Item2, Base Item1])
Collection1([Base Item2, Subclass Item1])


Would you consider this as fugly?

class Provider(object):
    def retrieve_collection(self, type0=Item1, type1=Item2):
        col = Collection1()
        col.add(type0())
        col.add(type1())
        return col


col = provider.retrieve_collection(MyItem)


mylib.py

class Item1(object):
    def __repr__(self):
        return "Base Item1"
class Item2(object):
    def __repr__(self):
        return "Base Item2"
class Collection1(set):
    pass 

class Provider(object):
    Item1=Item1
    Item2=Item2
    def retrieve_collection(self):
        col = Collection1()
        col.add(self.Item1())
        col.add(self.Item2())
        return col

def ProviderFactory(**kw):
    return type('Provider', (Provider,)+Provider.__bases__, kw)

from mylib import ProviderFactory, Item1

class Item1(Item1):
    def __repr__(self):
        return "Subclass Item1"

MyProvider=ProviderFactory(Item1=Item1)


p=MyProvider()
print p.retrieve_collection()

Output:

Collection1([Base Item2, Subclass Item1])
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜