첫 번째 컨텍스트 :트리 구조에서 재귀 적으로 작동 : "전체"트리의 상태를 얻으려면 어떻게해야합니까?
부 프로젝트로서 파이썬에서 컴퓨터 대수학 시스템을 구축하여 방정식을 풀 때 걸리는 단계를 산출합니다.
지금까지 대수 식과 방정식을 식 트리로 구문 분석 할 수있었습니다. 그것은이 같은 (실제 코드-수 있습니다 실행되지 않음) 구조화 된 것 :
# Other operators and math functions are based off this.
# Numbers and symbols also have their own classes with 'parent' attributes.
class Operator(object):
def __init__(self, *args):
self.children = args
for child in self.children:
child.parent = self
# the parser does something like this:
expr = Add(1, Mult(3, 4), 5)
이 위에을, 나는 표현을 단순화하기 위해 반복적으로 작동 할 일련의 기능을 가지고있다. 그것들은 순전히 기능적이지는 않지만, 작동을위한 가변성에 의존하는 것을 피하고, 대신 내가 작업하고있는 노드의 수정 된 복사본을 반환합니다. 각 기능은 다음과 같습니다.
def simplify(node):
for index, child in enumerate(node.children):
if isinstance(child, Operator):
node.children[index] = simplify(node)
else:
# perform some operations to simplify numbers and symbols
pass
return node
"단계별 설명"부분에 문제가 있습니다. 내 "단순화"기능이 모두 중첩 된 생성기가되어 뭔가를 해결하는 데 필요한 단계를 "양보"하고 싶습니다. 그러니까 기본적으로, 각 기능은 작업을 수행 할 때마다, 나는 이런 식으로 뭔가를 할 수 있도록하고 싶습니다 :이 라이브러리에 의존 무엇이든 그래서 yield (deepcopy(node), expression, "Combined like terms.")
출력 할 수있는 뭔가 같은 :
5x + 3*4x + 3
5x + 12x + 3 Simplified product 3*4x into 12x
17x + 3 Combined like terms 5x + 12x = 17x
그러나, 각 기능 만 node
에 대한 지식을 가지고 있지만, 전체적으로는 expression
이 무엇인지 모릅니다.
그래서 내 질문입니다 : 각 "단계"전체 식에 대한 지식을 갖도록 전체 식 트리의 "상태"를 유지하는 가장 좋은 방법은 무엇입니까?
는 여기에 내가 가지고 올 한 솔루션입니다 :
- 자리에 모든 작업을 수행하고 하나 방정식에 대한 포인터를 저장하는 클래스의 전역 변수 또는 인스턴스 변수를 사용합니다. 나는 단위 테스트가 더 힘들 기 때문에 나는 이것을 좋아하지 않는다. 왜냐하면 지금부터 내가 먼저 클래스를 설정해야하기 때문이다. 보다 기능적인 접근법의 다른 장점을 잃게됩니다.
- 모든 함수에 표현식의 루트를 전달하십시오. 그러나이 중 하나는 표현을 업데이트하기 위해 모든 작업을 반복해야한다는 것을 의미하거나 변경 가능성에 의존해야합니다.
- 최상위 함수가 내가 산출하는 각 단계에 따라 표현식 트리를 '재구성'합니다. 예를 들어, 내가
5x + 4x = 9x
을 산출하면 최상위 기능을 (5x + 4x) 노드를 찾아 '9x'로 대체하십시오. 이것은 최상의 솔루션처럼 보이지만 어떻게 각 단계를 '재구성'하는 것이 가장 좋습니까?
두 가지 최종 관련 질문 :이 중 하나가 의미가 있습니까? 나는 지금 내 시스템에 카페인이 많고 내가 분명히하고 있는지 전혀 모른다.
가변성에 대해 너무 걱정합니까? 이것은 조숙 한 최적화의 경우입니까?
루트 노드를 전달할 수 있습니다. 당신은 연속 통과 스타일을 들여다 볼 수 있습니다. 그러나 이것을 고려하십시오 : 각 단계가 전체 구조를 관찰해야하는 경우 재귀가이를 수행하는 가장 간단한 방법이 아닐 수도 있습니다. – Marcin