LINUX.ORG.RU

Как добавить метод в уже созданный класс?

 ,


0

1

Вот есть какой то класс:

class A:
    ...

Потом (в другом модуле) нам нужно его проагрейдить, скажем добавить метод __getitem__

def foo(self, i):
    ...
A.__getitem__ = foo
del foo

Вопрос - как это сделать Ъ? Ну что бы там правильное имя метода было (в справке) и вообще как то изящно.

Зная специфику ЛОР-а, сразу хочу заметить что исходный класс генерится сторонней вундервафлей (swig-ом). Я могу конечно потом пропатчить сгенерированный им питоний файл и напихать методов прмяо в тушку класса, но пока мне это представляется еще большим извращением.

cats tailgunner, true_admin.

★★★★★

Последнее исправление: AIv (всего исправлений: 1)

Ответ на: комментарий от tailgunner

А чем setattr лучше приведенного

A.__getitem__ = foo
? Только тем что это можно завернуть в какую то ф-ю, которая там настроит foo как надо... С т.з. стиля меня это все равно бесит (как мин то, что нужно создавать ф-ю с левым именем).

AIv ★★★★★
() автор топика
Ответ на: комментарий от AIv

Так тебе надо просто добавить метод, или добавить метод особо кошерным способом, или добавить метод с подвыподвертом?

С т.з. стиля меня это все равно бесит (как мин то, что нужно создавать ф-ю с левым именем).

Лямбду передай (ну или я не понимаю, что тебе нужно).

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Мне надо добавить дцать методов;-( ну и хочется сделать это красиво, я поудмал что м.б. есть какой то Ъ стандартный способ.

Лямбда это кошерно, но там не все к сожалению в лямбду ложится - могут быть циклы, условия и пр.

AIv ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

Я кажется придумал - делаем левый класс с пачкой ф-й, а потом апдейтим словарь целевого класса его словарем;-)

class A:
 ...
class B:
 def __getitem__(self, i): 
  ...
A.__dict__.update(B.__dict__)
del B

AIv ★★★★★
() автор топика
Ответ на: комментарий от AIv

Самый Ъ-стандартный способ, который я знаю - это setattr.

там не все к сожалению в лямбду ложится - могут быть циклы, условия и пр.

Если там что-то сложное - оно вообще должно быть в файле библиотечного кода.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Самый Ъ-стандартный способ, который я знаю - это setattr.

setattr(A, '__getitem__', foo)

так?

Если там что-то сложное - оно вообще должно быть в файле библиотечного кода.

Ну...я пока не дошел до таких высот проектирования, я делаю библиотечную ф-ю когда код дублируется хотя бы дважды.

AIv ★★★★★
() автор топика

В Python'е отлично работает множественное наследование, так что:

#!/usr/bin/env python

class A(object):
    def __init__(self):
        print "A.__init__"

    def m1(self, a):
        print "m1(%s)" % a

class A_ext(object):
    def __init__(self):
        print "A_ext.__init__"

    def m2(self, a):
        print "m2(%s)" % a

class SuperA(A_ext, A):
    def __init__(self):
        A.__init__(self)
        A_ext.__init__(self)

a = SuperA()
a.m1("1")
a.m2("2")

print isinstance(a, A)
print isinstance(a, A_ext)

rymis ★★
()
Ответ на: комментарий от rymis

Поясню: если A класс, созданный swig-ом, а вам хотелось бы добавить в него методов, то создаете класс A_ext с нужными методами и SuperA унаследованный от обоих классов.

rymis ★★
()
Ответ на: комментарий от AIv

setattr(A, '__getitem__', foo)

Да.

я делаю библиотечную ф-ю когда код дублируется хотя бы дважды.

Смотри сам, что тебе легче менять, если понадобится патчить класс другими функциями.

tailgunner ★★★★★
()

А что если создать новый класс, унаследовав его от A, и уже в него дописать/переопределить нужные тебе методы?

gnunixon ★★★
()
Ответ на: комментарий от rymis

поясню - swig понятия не имеет про SuperA, он как делал A так и делает A.

Была какая то фенька, можно было списко родительских классов патчить динамически... т.е. можно A_ext загнать родителем в A.

AIv ★★★★★
() автор топика
Ответ на: комментарий от AIv

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

rymis ★★
()
Ответ на: комментарий от AIv

Можете, если не трудно, объяснить почему нельзя этот класс, созданный swig, записать в родители другому классу с вашими функциями?

MLP_Fan ★★
()
Ответ на: комментарий от rymis

свигу пофигу на имя вообще то. Он работает с адресом объекта класса в памяти, мне бы не хотелось в это лезть - я не понимаю до конца как это работает.

AIv ★★★★★
() автор топика
Последнее исправление: AIv (всего исправлений: 1)
Ответ на: комментарий от theNamelessOne

Точно! Полез в Россума смотреть как эта мулька называется, опередили;-)

Да, это еще один вариант. Свиг правда A делает наследником object - ну наверное множ.наследование это съест.

AIv ★★★★★
() автор топика
Ответ на: комментарий от MLP_Fan

У Вас есть фунцкция f() возвращаюя класс A. Как бы Вы класс A не наследовали, f() об этом ничегшо не знает.

AIv ★★★★★
() автор топика
Ответ на: комментарий от AIv

Извини, я питон не знаю, только присматриваюсь, но интересна проблема. А какая разница, собственно, знает она что-то или не знает? Что она должна «знать» вообще? Это что-то питон-специфичное?

filequest
()
Ответ на: комментарий от filequest

Вангану следующее : - нам нужно поведение a - оно не реализовано в классе A, но функция вернет экземпляр класса A. - соответственно - либо нам надо пилить обертку, которая преобразует в экземпляр реализующего a наследника A, либо проапгрейдить A.

alex4321
()
Ответ на: комментарий от alex4321

Именно так. Но обертки пилить в данном случае сложнее чем апргрейдить A.

AIv ★★★★★
() автор топика
Ответ на: комментарий от theNamelessOne

Не работает в данном случае наследование - A имеет кой-какие свои методы, которые надо перекрыть (а не наоборот).

Остаеися апгрейд словаря, вполне рабочее решение. Всем спасибо!

AIv ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.