Python: как «объединить» два класса - PullRequest
6 голосов
/ 12 марта 2012

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

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 settings\Bureau\merge.py", line 22, in <module>
    print instb.getattB()
  File "D:\Documents and settings\Bureau\merge.py", line 16, in getattB
    return self.getatt()
AttributeError: B instance has no attribute 'getatt'

И я ожидал получить «a» для вызова instb.gettattB ()

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

Ответы [ 5 ]

6 голосов
/ 14 марта 2012

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

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'

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

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

2 голосов
/ 12 марта 2012

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

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 , но звоните быстро.

1 голос
/ 12 марта 2012

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

1 голос
/ 12 марта 2012

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

  1. a инициализируется вне конструктора в 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()
0 голосов
/ 17 августа 2015

У меня были проблемы с вызовом различных конструкторов, использование 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...