Python: как "объединить" два класса

Я хочу добавить некоторые атрибуты и методы в различного класса. Методы и атрибуты, которые я должен добавить, одинаковы, но не класс для их назначения, поэтому я хочу создать класс, который назначает новые методы и атрибут для класса, заданного в аргументе. Я пытаюсь, но ничего не получается.: (Я знаю, что это очень неправильный способ попытаться назначить что-то себе, это просто показать, что я хочу сделать)

class A:
    def __init__(self):
        self.a = 'a'

    def getatt(self):
        return self.a

class B:
    def __init__(self, parent) :
        self = parent

        # This is working :
        print self.getatt()

    def getattB(self):
        return self.getatt()

insta = A()
instb = B(insta)

# This is not working :
print instb.getattB()

результат :

a
Traceback (most recent call last):
  File "D:Documents and settingsBureaumerge.py", line 22, in <module>
    print instb.getattB()
  File "D:Documents and settingsBureaumerge.py", line 16, in getattB
    return self.getatt()
AttributeError: B instance has no attribute 'getatt'

и я ожидал получил " а " за вызов instb.gettattB ()

чтобы возобновить, я хочу наследовать класс B от класса A, давая класс A в аргументе класса B, потому что мой класс B будет подклассом различного класса, а не всегда A.

5 ответов


лучший ответ в комментариях, это было полезно для меня, поэтому я решил показать его в ответе (спасибо sr2222): Путь к динамично объявить inherance в Python-это тип() встроенная функция. Для моего примера :

class A(object) :
    def __init__(self, args):
        self.a = 'a'
        self.args = args

    def getattA(self):
        return self.a, self.args

class B(object) :
    b = 'b' 
    def __init__(self, args) :
        self.b_init = args

    def getattB(self):
        return self.b

C = type('C', (A,B), dict(c='c'))

instc = C('args')

print 'attributes :', instc.a,  instc.args, instc.b, instc.c
print 'methodes :', instc.getattA(), instc.getattB()

print instc.b_init

код :

attributes : a args b c
methodes : ('a', 'args') b
Traceback (most recent call last):
  File "D:\Documents and settings\Bureau\merge2.py", line 24, in <module>
    print instc.b_init
AttributeError: 'C' object has no attribute 'b_init'

My class C inerhite атрибуты и методы класса A и класса B, и мы добавляем атрибут C. С экземпляром C (instc = C ('args'))init для вызова is, но не для Б.

очень полезно для меня, потому что я должен добавить некоторые атрибуты и методы (то же самое) в другом классе.


Я не уверен, что вы пытаетесь сделать, но код ниже дает мой вывод я думаю вы ожидаете. обратите внимание:

  1. a инициализируется вне конструктора в
  2. B объявляется как подкласс a

код:

class A:
    a='' #Initialize a

    def __init__(self):
        self.a = 'a'

    def getatt(self):
        return self.a

class B(A):  #Declare B as subclass
    def __init__(self, parent) :
        self = parent

        print self.getatt()

    def getattB(self):
        return self.getatt()

insta = A()
instb = B(insta)

print instb.getattB()

поскольку B не является подклассом A, в B нет пути к getatt () в A


Как насчет этого?

class A:
    def __init__(self):
        self.a = 'a'

    def getatt(self):
        return self.a

class B:
    def __init__(self, parent) :
        self.parent = parent

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

    def getattB(self):
        return self.parent.getatt()

insta = A()
instb = B(insta)

print instb.getattB()
print instb.getatt()

но метод в классе A не может получить доступ к attr в классе B.

иначе:

import functools
class A:
    def __init__(self):
        self.a = 'a'

    def getatt(self):
        return self.a

class B:
    def __init__(self, parent):
        for attr, val in parent.__dict__.iteritems():
            if attr.startswith("__"): continue
            self.__dict__[attr] = val
        for attr, val in parent.__class__.__dict__.iteritems():
            if attr.startswith("__"): continue
            if not callable(val): continue
            self.__dict__[attr] = functools.partial(val, self)

    def getattB(self):
        return self.getatt()

insta = A()
instb = B(insta)

print instb.__dict__
print instb.getattB()
print instb.getatt()

медленно с init но вызвать "скорую".


у меня возникли проблемы с вызовом разных конструкторов, используя super Не обязательно имеет смысл в таком случае, я решил наследовать и вызывать каждый конструктор для текущего объекта вручную:

class Foo(object):
    def __init__(self, foonum):
        super(Foo, self).__init__()
        self.foonum = foonum


class Bar(object):
    def __init__(self, barnum):
        super(Bar, self).__init__()
        self.barnum = barnum

class DiamondProblem(Foo, Bar):
    # Arg order don't matter, since we call the `__init__`'s ourself.
    def __init__(self, barnum, mynum, foonum):
        Foo.__init__(self, foonum)
        Bar.__init__(self, barnum)

        self.mynum = mynum