Приведение типов объектов в Python (проектное предложение) - PullRequest
2 голосов
/ 14 апреля 2011

Допустим, есть библиотечная функция 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 ]

4 голосов
/ 14 апреля 2011

Будет ли это работать для вас?

#!/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
2 голосов
/ 14 апреля 2011

Возможно, что-то вроде этого

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)
1 голос
/ 14 апреля 2011

Примечание: это дубликат этого ответа поблизости (надеюсь выше.)

Так что вы не хотите копировать скучный список полей пакета, но хочу добавить немного.Существует простой способ делегировать разрешение неизвестных имен с использованием __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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...