Динамическое добавление методов извне класса с помощью декоратора

#python #decorator

#python #декоратор

Вопрос:

У меня возникли проблемы с двумя вещами. Добавление метода извне, который ссылается на self . т.е.

 class A(object):
  def __init__(self, name): 
    self.name=name

def my_name_is(self):
  print("my name is %s" %(self.name))

setattr(A, my_name_is.__name__, classmethod(my_name_is))
a = A('bob')
a.my_name_is() 
  

Потому что он пытается ссылаться на имя attr ‘A’, а не ‘a’.

Другой вариант — добавление функции с помощью декоратора, т.Е. Что-то вроде

 @addMethod(A)
def say_hello_to(x):
  print("hello %s" %x)
  

скорее какой-то эквивалент

 def addMethod(cls, f) 
  setattr(cls, f.__name__, classmethod(f))
  

Комментарии:

1. Почему вы используете classmethod , если хотите ссылаться self ?

2. Просто примечание, str.format() предпочтительнее % форматирование.

3. У вас случайно нет ссылки на сообщение или дополнительной информации об этом? (str.format vs %)

4. docs.python.org/2/library/stdtypes.html#str.format

5. Я имею в виду, почему str.format() считается предпочтительнее% интерполяции

Ответ №1:

Вопрос 1: то, что вы ищете, — это метод, а не classmethod . В этом случае будет работать простое назначение:

 A.my_name_is = my_name_is
  

Вопрос 2. выражение, следующее за @ , должно возвращать вызываемое, т. Е. addMethod(A)
Должно быть вызываемым. Это можно сделать следующим образом:

 def addMethod(cls):
  def method_assigner(f):
     setattr(cls, f.__name__, f)
     return f
  return method_assigner
  

Тогда это работает:

 @addMethod(A)
def say_hello_to(x):
  print("hello %s" %x)
  

(В этом примере x будет получено значение self when say_hello_to вызывается. Я не уверен, что точно понимаю роль x в ваших центрах сертификации, но, надеюсь, это прояснит, как достичь того, чего вы хотите. Возможно, вы хотите def say_hello_to(self, x):... ?).

Комментарии:

1. да, вы правы, say_hello_to(self, x) является правильным.

2. ps. Как я мог бы определить их, чтобы не ссылаться на self в исходном объявлении функции или, возможно, динамически добавлять self с помощью addMethod?

3. функция, которую вы назначаете классу, должна быть оболочкой f , которая принимает self и *a,**kw и передает *a,**kw f .