[PYTHON] 파이썬 함수에 동적으로 추가
PYTHON파이썬 함수에 동적으로 추가
이전 또는 이후에 기존 함수에 코드를 추가하려면 어떻게합니까?
예를 들어, 나는 수업을 가지고 :
class A(object):
def test(self):
print "here"
내가 어떻게 그렇게 클래스 위트 metaprogramming 편집합니까
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()
이것을 할 수있는 방법이 있습니까?
해결법
-
==============================
1.원하는 경우 데코레이터를 사용하여 함수를 수정할 수 있습니다. 그러나 함수의 초기 정의시 적용된 데코레이터가 아니므로 @ 통사론 설탕을 사용하여 적용 할 수는 없습니다.
원하는 경우 데코레이터를 사용하여 함수를 수정할 수 있습니다. 그러나 함수의 초기 정의시 적용된 데코레이터가 아니므로 @ 통사론 설탕을 사용하여 적용 할 수는 없습니다.
>>> 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
기존 인스턴스에 대한 메소드도 수정한다는 점에 유의하십시오.
수정 : args 및 kwargs 사용하여 더 나은 버전으로 데코레이터에 대한 args 목록 수정
-
==============================
2.함수에 함수를 추가하는 일반적인 방법은 데코레이터를 사용하는 것입니다 (wraps 함수 사용).
함수에 함수를 추가하는 일반적인 방법은 데코레이터를 사용하는 것입니다 (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 접근 방식에 대해 더 자세히 설명 할 수 있습니다.
편집 : 당신이 함수를 호출하려는 것처럼 보이기 때문에, 당신은 메시지 목록 대신 함수 목록을 가질 수 있습니다. 예 :
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의 모든 인스턴스에서 호출 할 함수를 추가하려면 함수 필드를 인스턴스 필드가 아닌 클래스 필드로 만들어야합니다.
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"
-
==============================
3.위의 정말 좋은 제안이 많이 있지만, 내가 보지 못한 것은 호출이있는 함수를 전달하는 것입니다. 다음과 같이 보일 수 있습니다.
위의 정말 좋은 제안이 많이 있지만, 내가 보지 못한 것은 호출이있는 함수를 전달하는 것입니다. 다음과 같이 보일 수 있습니다.
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
-
==============================
4.이 대답을 사용하면 래퍼를 만들지 않고 원래 함수를 수정할 수 있습니다. 귀하의 질문에 대답하는 데 유용한 다음 두 가지 원시 파이썬 형식을 발견했습니다 :
이 대답을 사용하면 래퍼를 만들지 않고 원래 함수를 수정할 수 있습니다. 귀하의 질문에 대답하는 데 유용한 다음 두 가지 원시 파이썬 형식을 발견했습니다 :
types.FunctionType
과
types.CodeType
이 강령은 그 일을하는 것처럼 보입니다.
import inspect import copy import types import dill import dill.source #Define a function we want to modify: def test(): print "Here" #Run the function to check output print '\n\nRunning Function...' test() #>>> Here #Get the source code for the test function: testSource = dill.source.getsource(test) print '\n\ntestSource:' print testSource #Take the inner part of the source code and modify it how we want: newtestinnersource = '' testSourceLines = testSource.split('\n') linenumber = 0 for line in testSourceLines: if (linenumber > 0): if (len(line[4:]) > 0): newtestinnersource += line[4:] + '\n' linenumber += 1 newtestinnersource += 'print "Here2"' print '\n\nnewtestinnersource' print newtestinnersource #Re-assign the function's code to be a compiled version of the `innersource` code_obj = compile(newtestinnersource, '<string>', 'exec') test.__code__ = copy.deepcopy(code_obj) print '\n\nRunning Modified Function...' test() #<- NOW HAS MODIFIED SOURCE CODE, AND PERFORMS NEW TASK #>>>Here #>>>Here2
-
==============================
5.왜 상속을 사용하지 않습니까?
왜 상속을 사용하지 않습니까?
class B(A): def test(self): super(B, self).test() print "and here"
-
==============================
6.복사하여 붙여 넣기를 즐기십시오 !!!!!
복사하여 붙여 넣기를 즐기십시오 !!!!!
#!/usr/bin/env python def say(host, msg): print '%s says %s' % (host.name, msg) def funcToMethod(func, clas, method_name=None): setattr(clas, method_name or func.__name__, func) class transplant: def __init__(self, method, host, method_name=None): self.host = host self.method = method setattr(host, method_name or method.__name__, self) def __call__(self, *args, **kwargs): nargs = [self.host] nargs.extend(args) return apply(self.method, nargs, kwargs) class Patient: def __init__(self, name): self.name = name if __name__ == '__main__': jimmy = Patient('Jimmy') transplant(say, jimmy, 'say1') funcToMethod(say, jimmy, 'say2') jimmy.say1('Hello') jimmy.say2(jimmy, 'Good Bye!')
-
==============================
7.클래스 A가 객체에서 상속받는 경우 다음과 같이 할 수 있습니다.
클래스 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를 사용할 수 없습니다. 방금이 코드를 재미있게 보았지만 결코 사용하지 않을 것입니다. 역동적으로 객체 자체를 변경하는 것을 싫어합니다.
가장 빠르며 이해하기 쉽습니다.
from https://stackoverflow.com/questions/2789460/python-add-to-a-function-dynamically by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] 장고 : unique_together 오류 메시지를 재정의하는 방법? (0) | 2018.10.24 |
---|---|
[PYTHON] 파이썬 람다 문제 (0) | 2018.10.24 |
[PYTHON] 가져 오기 오류 : 'No module named'* does * exist (0) | 2018.10.24 |
[PYTHON] XML 요소를 통해 반복하는 효율적인 방법 (0) | 2018.10.24 |
[PYTHON] 파이썬을 이용한 이미지 컬러 검출 (0) | 2018.10.24 |