python. почему не вызывается динамически созданный метод объекта

Phoenix

Что я не так делаю? Может как-то нужно сообщить, что abc - это не просто функция, а метод класса? (судя по тому, что ругается на 1 аргумент)
 
 class A:
a = 3


if __name__ == "__main__":
c = A

print c.a

def f(self,abc):
for i in range(a):
print abc

c.abc = f

c.abc(123)

 
 F:\igor\apps\devel\python\test>python test.py
3
Traceback (most recent call last):
File "test.py", line 16, in <module>
c.abc(123)
TypeError: f takes exactly 2 arguments (1 given)

Phoenix

Если заменить
c.abc =f
на
A.abc = f
то работает, но всё равно не понятно, почему так сделано.

kruzer25

то работает, но всё равно не понятно, почему так сделано.
Кажется, в заголовке этого треда написано о добавлении метода к классу, а не к объекту?

Phoenix

исправил.
вопрос остаётся.

pitrik2

исправил.
вопрос остаётся.
по-первых не испавил
должно быть:

A.abc = f

потому что мы добавляем функцию в класс "А" а не в объект "с"
во-вторых откуда ему знать что такое "a" в функциип "f"?
должно быть

for i in range(self.a):

conv3rsje

Может как-то нужно сообщить, что abc - это не просто функция, а метод класса?
Угадал :) Можно так:

def classwrap(obj):
def _wrap(f):
return lambda *a, **kw: f(obj, *a, **kw)
return _wrap

c = A
c.abc = classwrap(cf)

Сам подумай, как иначе ты обыкновенным присваиванием хочешь объяснить функции что надо получать какой-то конкретный объект в качестве первого аргумента?

Phoenix

просто возникает двусмысленность в записи
obj.method1(a,b,c)
Видимо это некоторый опыт c++ наводит на мысль, что obj будет передан первым аргументом в такой записи.
С lambda идею понял. Просто прописываем в саму вызываемую фунцию ссылку на объект.

Dmitriy82

new.instancemethod

rosali

> Видимо это некоторый опыт c++ наводит на мысль
и в С++ всё точно так же вообще то ;)

[xoft ~]$ cat test.cpp
#include <iostream>
using namespace std;

struct C
{
int x;
C: x(1) {}
int f(int y) {
return x+y;
}
int (*gint);
};

int g (int y) {
return y;
}

int main
{
C c;
c.g = g;
cout << c.f(2) << " " << c.g(2) << endl;
}

[xoft ~]$ ./test
3 2

Phoenix

ага. точно.
не знал.

klyv

а если хочется добавить функцию в один только объект, то так:
class C:
a = 5

c = C
class D(c.__class__):
def abc(self, abc):
for i in range(self.a):
print(abc)

c.__class__ = D
c.abc('a')

Phoenix

ага. вот это уже интереснее.
Т.е. хотя что-то и экземпляр класса, ничто не мешает сделать его экземляром другого, производного от изначального, класса.
Видимо, изначально я это и искал.

klyv

думаю, можно сделать экземпляром любого класса, я написал всё именно так для порядку, чтобы всё было честно - объект не перескочил в другую иерархию, все вызовы справедливы, объект можно использовать как раньше
Оставить комментарий
Имя или ник:
Комментарий: