2014-01-15 5 views
2

Я работаю в среде динамического программирования, где мне может понадобиться определить (или переопределить) функцию класса. Поэтому считаю, что это, например:Назначение функции Python за пределами определения класса вызывает исключение аргумента

def func(self): 
    print("hello2 \n") 

class ManClass: 
    def __init__(self): 
     pass 
    def func1(self): 
     print("hello1\n") 

a = ManClass() 

a.func1() 
hello1 

a.func2 = func 
>>> a.func2() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: func() takes exactly 1 argument (0 given) 

Если func2() была определена внутри класса - a.func2() была бы истолковано как ManClass.func2 (а) - но теперь, когда я назначаю его снаружи, это, кажется, ждет аргумента. Как это исправить, но что более важно, почему это различие в том, как эти два определения взаимосвязаны?

ответ

2

Вы не добавили func к классу, вы добавили его в экземпляр. Вместо этого попробуйте ManClass.func2 = func.

a.func2 = func добавляет func к a экземпляру класса как атрибут экземпляра под названием func2, а не в качестве метода члена экземпляра (который на самом деле просто специальная обработка ГОО членов на основной объект класса).

В качестве альтернативы вы также можете добавить метод элемента в один экземпляр, используя MethodType, как указывает @jonrsharpe в его ответе.

+0

О, хватит, ты прав. Атрибуты/функции класса и экземпляра «разные». Я должен был знать, что я делаю неправильно. Большое спасибо ! – user1922297

2

Это различие между функцией и связанным методом, где «bound» относится к экземпляру self. Чтобы устранить проблему, вам нужно сделать функцию автономной MethodType:

from types import MethodType 

a.func2 = MethodType(func, a) 

Это связывает func к ManClass например a, что позволяет ему получить доступ атрибуты любого экземпляра. Обратите внимание, что этот влияет только на a, другие ManClass экземпляры сохранят первоначальное определение класса, если оно не будет так же исправлено.

Когда вы просто прикрепить функцию

a.func2 = func 

вы все еще можете получить доступ к нему:

a.func2(None) # will print "hello2 \n" 

Но это не получает неявный объект параметра экземпляр self и просто воспринимает его как стандартный позиционная аргумент.

Смежные вопросы