간단한 TRS (Triumper Rewriting System)/Symbolic Algebra System을 Python으로 구현하는 방법을 실험하고 있습니다. 이 경우 클래스 인스턴스 인스턴스화 프로세스 중에 특정 경우에 피연산자를 가로 채고 수정할 수 있어야합니다. 필자가 생각해 낸 해결책은 클래스 객체 (type 'type')의 동작을 수정하는 메타 클래스를 만드는 것이 었습니다.Python : 클래스 인스턴스 초기화 전에 전달 된 인수 수정
class Preprocess(type):
"""
Operation argument preprocessing Metaclass.
Classes using this Metaclass must implement the
_preprocess_(*operands, **kwargs)
classmethod.
"""
def __call__(cls, *operands, **kwargs):
pops, pargs = cls._preprocess_(*operands, **kwargs)
return super(Preprocess, cls).__call__(*pops, **pargs)
예 케이스 중첩 연산 F 밖으로 확장하는 것 (F를 (a, b), c) -> F (A, B, C)
class Flat(object):
"""
Use for associative Operations to expand nested
expressions of same Head: F(F(x,y),z) => F(x,y,z)
"""
__metaclass__ = Preprocess
@classmethod
def _preprocess_(cls, *operands, **kwargs):
head = []
for o in operands:
if isinstance(o, cls):
head += list(o.operands)
else:
head.append(o)
return tuple(head), kwargs
그래서 지금 동작은 상속을 통해 실현 될 수있다 :
print F(F(1,2,3),4,5).operands
(1,2,3,4,5)
:
class Operation(object):
def __init__(self, *operands):
self.operands = operands
class F(Flat, Operation):
pass
이 원하는 동작에 이르게
그러나 이러한 전처리 클래스를 여러 개 결합하여 자연스러운 클래스 mro에 따라 피연산자를 순차적으로 처리하도록하겠습니다.
class Orderless(object):
"""
Use for commutative Operations to bring into ordered, equivalent
form: F(*operands) => F(*sorted(operands))
"""
__metaclass__ = Preprocess
@classmethod
def _preprocess_(cls, *operands, **kwargs):
return sorted(operands), kwargs
그리고 원하는대로 작동하지 않는 것 같습니다. 평평한 주문형 작업 유형 정의
class G(Flat, Orderless, Expression):
pass
결과는 첫 번째 전처리 슈퍼 클래스가 '활성'이됩니다.
print G(G(3,2,1),-1,-3).operands
(3,2,1,-1,-3)
어떻게 모든 전처리 클래스 '전처리 방법은 클래스 인스턴스화 전에 호출되도록 할 수 있습니다?
업데이트 :
나는 때문에 새로운 유래 사용자로 내 상태에 공식적으로 아직 내 질문에 대답 할 수없는 것.
class Preprocess(type):
"""
Abstract operation argument preprocessing class.
Subclasses must implement the
_preprocess_(*operands, **kwargs)
classmethod.
"""
def __call__(cls, *operands, **kwargs):
for cc in cls.__mro__:
if hasattr(cc, "_preprocess_"):
operands, kwargs = cc._preprocess_(*operands, **kwargs)
return super(Preprocess, cls).__call__(*operands, **kwargs)
나는 문제가 예상대로 super(Preprocess, cls).__call__(*operands, **kwargs)
는 CLS의 MRO를 통과하지 않는 것 같다 : 그래서, 나는 이것이 아마 내가 가지고 올 수있는 최고의 솔루션입니다 생각합니다.
할당자를 재정의하고 기준자를 검사하게하십시오. –
흠, 정확히 어떻게 작동할까요? Preprocess .__ call__ 메서드에서 cls 개체의 __bases__를 출력하면 (예상대로) (<클래스 '__main __. Flat'>, <클래스> __main __, 주문 없음>, <클래스 '__main __. 작업'>) – Nikolas
동적 유형의 객체를 반환해야합니다. 그래서 당신은 할당 자에서 그것을합니다. –