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])
精彩评论