Python中的对象类型转换(设计建议)

时间:2011-04-14 13:00:08

标签: python oop casting

假设有一个名为get_pack()的库函数,它返回一个Pack对象:

class Pack(object):
    def __init__(self, name, weight):
        self.name = name
        self.weight = weight
        ...

我想要做的是将这个对象包装到我的对象中,让我们说具有一些有用功能的CommercialPack:

class CommercialPack(Pack):
    def get_delivery_price(self, distance):
        return self.weight * PER_KM_PRICE * distance
    ...

然后创建一个返回CommercialPack而不是Pack的函数。在Delphi或Java等其他语言中,您可以动态地输入该对象。所以我希望有类似的东西:

def get_commercial_pack():
    return CommercialPack(get_pack())

然后你就拥有了你所需要的一切,没有麻烦。因为我希望我的CommercialPack对象具有Pack对象具有的所有属性和功能。我只想将它包装在我的新课程中。基本上我不想做这样的事情:

class CommercialPack(object):
    def __init__(self, pack):
        self.name = pack.name
        self.weight = pack.weight
        ...

OR

class CommercialPack(object):
    def __init__(self, pack):
        self.pack = pack

我正在寻找一个优雅的解决方案,就像我说的那样,某种类型的演员或我在Python中可以优雅地做的任何事情。

非常感谢。

3 个答案:

答案 0 :(得分:4)

这对你有用吗?

#!/usr/bin/python
PER_KM_PRICE = 10

class Pack(object):
    def __init__(self, name, weight):
        self.name = name
        self.weight = weight

    def test_fn(self):
        print "test"

class CommercialPack(Pack):
    def __init__(self, pack):
        self.pack = pack

    def get_delivery_price(self, distance):
        return self.weight * PER_KM_PRICE * distance

    def __getattr__(self, attr):
        return getattr(self.pack,attr)

你可以使用它:

>>> p = Pack(10, 20)
>>> cp = CommercialPack(p)
>>> cp.weight
20
>>> cp.get_delivery_price(10)
2000
>>> cp.test_fn()
test

答案 1 :(得分:2)

也许是这样的

class CommercialPack(object):
    def __init__(self, pack):
        self.__dict__.update(pack.__dict__)

如果你不介意在包和商品包之间共享状态,你甚至可以这样做

class CommercialPack(object):
    def __init__(self, pack):
        self.__dict__ = pack.__dict__

在您的示例中应该没问题,因为您没有保留对包对象的任何其他引用

例如

PER_KM_PRICE = 100

class Pack(object):
    def __init__(self, name, weight):
        self.name = name
        self.weight = weight


class CommercialPack(Pack):
    def __init__(self, pack):
        self.__dict__ = pack.__dict__

    def get_delivery_price(self, distance):
        return self.weight * PER_KM_PRICE * distance

def get_pack():
    return Pack("pack", 20)

cp = CommercialPack(get_pack())
print cp.get_delivery_price(3)

答案 2 :(得分:1)

注意:这是附近this answer的副本(希望在上面。)

所以你不想复制Pack的字段的无聊列表,但想要添加一点。有一个easy way to delegate resolution of unknown names使用__getattr__

class CommercialPack(object):
  def __init__(self, pack):
  self.pack = pack
  self.bar = 10

class CommercialPack(object):
  def __init__(self, pack):
    self.pack = pack
    self.bar = 10

  def __getattr__(self, name):
    return getattr(self.pack, name) # not called for bar!

现在神奇的作品:

>>> p = Pack('I am foo')
>>> p.foo
'I am foo'
>>> cp = CommercialPack(p)
>>> cp.foo
'I am foo'
>>> cp.bar
10
>>> _

因此,您可以向CommercialPack添加方法和任何其他属性,并透明地访问Pack的那些属性。

请注意,如果您添加Pack中已存在的名称,则CommercialPack的属性将隐藏同名Pack的属性。但您始终可以通过pack属性访问它。