2012-03-12 3 views
4

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

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

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

+2

Я не» Понимаете, что вы пытаетесь сделать, можете ли вы представить полный пример ожидаемого результата? Используйте 'class A (object)' и 'class B (object)', хотя, по крайней мере, если вы планируете поддерживать Python 2.X. –

+1

# Это не работает - как он не работает? – KevinDTimm

+0

Пожалуйста, разместите вывод, который вы получите при запуске кода. – ewok

ответ

2

Лучший ответ в комментариях, это было полезно для меня, поэтому я решил показать его в ответе (спасибо 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' 

Мой класс C атрибуты inerhite и методы класса А и класса В и мы добавляем атрибут гр. С C при создании экземпляра (instc = C («ARGS»)) INIT для А вызов, но не для B.

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

1

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

  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() 
+0

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

+0

Назначение значения 'self' просто неверно, и оно не выходит за пределы области тела ... –

+0

Я не думаю, что можно динамически установить родительский класс. Родитель должен быть объявлен для того, чтобы компилятор смог найти атрибуты суперкласса. Если 'B' не объявлен подкласс' A', вы не сможете получить доступ к 'a' – ewok

1

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

1

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

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

Но метод в классе А не может получить доступ к 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 но назвать быстрым.

+0

Да, я думаю, что это единственный способ сделать то, что я хочу. Я присвою атрибут и метод B классу A. Как (в классе B) self.a = self.parent.a и def getatt (self): return self.parent.getatt() Я ищу более быстрый способ но ... Спасибо – user1062526

+0

Это просто в основном повторяет новый синтаксис для динамического наследования, где Python дает вам возможность начать. 'insta = A()' 'instb = type ('B', (A,), {})'. Просто объявите статический метод класса B, который принимает произвольный кортеж длины других классов и возвращает тип ([новое имя класса], [кортеж классов, включая B], [членов, которые вы хотите добавить во время выполнения]). –

+0

@ sr2222, Отлично, я пытаюсь 'instb = type (" ", (object, B, insta .__ class__), insta .__ dict __)()' может сделать то же самое, что лучше работать. – showns

0

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