как я добавляю код к существующей функции, или прежде или после?
например, у меня есть класс:
class A(object):
def test(self):
print "here"
как я редактирую метапрограммирование остроумия класса так, чтобы я сделал это
class A(object):
def test(self):
print "here"
print "and here"
возможно, некоторый способ добавить другую функцию для тестирования?
добавьте другую функцию такой как
def test2(self):
print "and here"
и измените оригинал на
class A(object):
def test(self):
print "here"
self.test2()
существует ли способ сделать это?
Вы можете использовать декоратор для изменения функции, если хотите. Однако, поскольку это не декоратор, применяемый во время первоначального определения функции, вы не сможете использовать синтаксический сахар @
для его применения.
>>> class A(object):
... def test(self):
... print "orig"
...
>>> first_a = A()
>>> first_a.test()
orig
>>> def decorated_test(fn):
... def new_test(*args, **kwargs):
... fn(*args, **kwargs)
... print "new"
... return new_test
...
>>> A.test = decorated_test(A.test)
>>> new_a = A()
>>> new_a.test()
orig
new
>>> first_a.test()
orig
new
Обратите внимание, что это изменит метод и для существующих экземпляров.
EDIT: изменен список args для декоратора на лучшую версию с использованием args
и kwargs
Выше было много действительно хороших предложений, но одно я не видел, это передача функции с вызовом. Это может выглядеть примерно так:
class A(object):
def test(self, deep=lambda self: self):
print "here"
deep(self)
def test2(self):
print "and here"
Используя это:
>>> a = A()
>>> a.test()
here
>>> a.test(test2)
here
and here
Если ваш класс A наследуется от объекта, вы можете сделать что-то вроде:
def test2():
print "test"
class A(object):
def test(self):
setattr(self, "test2", test2)
print self.test2
self.test2()
def main():
a = A()
a.test()
if __name__ == '__main__':
main()
Этот код не интересует, и вы не можете использовать self в своем новом добавленный вами метод. Мне этот код показался забавным, но я никогда не буду его использовать. Я не люблю динамически изменять сам объект.
Это самый быстрый и понятный способ.
Почему бы не использовать наследование?
class B(A):
def test(self):
super(B, self).test()
print "and here"
Типичный способ добавить функциональность в функцию - использовать декоратор (используя функцию wraps):
from functools import wraps
def add_message(func):
@wraps
def with_additional_message(*args, **kwargs)
try:
return func(*args, **kwargs)
finally:
print "and here"
return with_additional_message
class A:
@add_message
def test(self):
print "here"
Конечно, все зависит от того, чего вы пытаетесь достичь. Я часто использую декораторы, но если бы я хотел выводить дополнительные сообщения, я бы сделал что-то вроде
class A:
def __init__(self):
self.messages = ["here"]
def test(self):
for message in self.messages:
print message
a = A()
a.test() # prints "here"
a.messages.append("and here")
a.test() # prints "here" then "and here"
Это не требует мета-программирования, но опять же, ваш пример, вероятно, сильно упрощен по сравнению с тем, что вам нужно сделать на самом деле. Возможно, если вы опишите более подробно ваши конкретные потребности, мы сможем лучше определить, каким должен быть подход Pythonic.
EDIT: Поскольку похоже, что вы хотите вызывать функции, вы можете иметь список функций вместо списка сообщений. Например:
class A:
def __init__(self):
self.funcs = []
def test(self):
print "here"
for func in self.funcs:
func()
def test2():
print "and here"
a = A()
a.funcs.append(test2)
a.test() # prints "here" then "and here"
Обратите внимание, что если вы хотите добавить функции, которые будут вызываться всеми экземплярами A
, то вам следует сделать funcs
полем класса, а не полем экземпляра, например,
class A:
funcs = []
def test(self):
print "here"
for func in self.funcs:
func()
def test2():
print "and here"
A.funcs.append(test2)
a = A()
a.test() # print "here" then "and here"