将子类传递给导入的库

时间:2010-08-18 07:50:05

标签: python

我有一个库,它返回一些半抽象对象的集合。

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

它只填充对象的属性,这些项/集合类旨在在调用者代码中进行子类化。

所以会有一些脚本

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

问题是,将MyItem(和任何其他子类)传递给Provider的优雅和pythonic解决方案是什么?

我可以将其作为Provider(item1=MyItem)传递,将其存储为self.item1,然后将其实例化为self.item1()而不是Item1(),但这看起来很难看。另外,我会在客户端代码中调用可怕的长构造函数。

其他选项是覆盖模块级别的类,如mylib.Item1 = MyItem,但这会导致许多意外且难以调试的问题。此外,可能有几个不同的提供程序类使用相同的项目基类,但需要来自客户端的不同子类。

也许某种形式的类注册表和工厂而不是实际的类?因此,Item1()会尝试根据某些上下文来确定要实例化的类,但我不确定它是如何工作的。

3 个答案:

答案 0 :(得分:1)

<强> 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()

输出:

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

答案 1 :(得分:0)

你会认为这很难看吗?

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)

答案 2 :(得分:0)

<强> 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()

输出:

Collection1([Base Item2, Subclass Item1])