정말로 원하는 것을 말할 수 없습니다. 그러나 새로운 클래스마다 속성을 추가하는 메타 클래스는 원하는대로 작동 할 수 있습니다.
코드를 이해할 수있는 한, 새로운 인스턴스를 작성하면 (즉, 다른 인스턴스에 대한 참조를 얻을 때) 이전 클래스에 새 클래스에 대한 참조가 채워지지 않습니다. 두 번째에
하지만, dinamically
__new__
inisde 속성을 만드는 것은 해키 보인다 -하지만 당신은 단지 메타 클래스
__getattr__
훨씬 덜 복잡한 코드
__dir__
방법을 구현할 수 있습니다
간단한 버전은 자신의 인스턴스 클래스 작동하지만,하지를 - 인스턴스는 메타 클래스에 __getattr__
을 유발하지 않기 때문에 :
class Pipeable(type):
_classes = {}
def __new__(metacls, name, bases, namespace, **kwds):
cls = type.__new__(metacls, name, bases, namespace)
metacls._classes[name] = cls
return cls
def __getattr__(cls, attr):
classes = cls.__class__._classes
if attr not in classes:
raise AttributeError
def pipe_within(*args, **kwargs):
return cls(*args, op=classes[attr], **kwargs)
print('piping...')
return pipe_within
def __dir__(cls):
regular = super().__dir__()
return sorted(regular + list(cls.__class__._classes.keys()))
class Op(metaclass=Pipeable):
def __init__(self, op=None):
if op is not None:
print('piped!')
self.op = op
Op.Op()
(물론, 시간이 지남에 내가 메타 클래스에 사용하는 명명 규칙이 매개 변수를 포착합니다 - 대부분 자신의 방법을 사용하여 만든 수업을 같이 그 (것)들은 평범한 수업에서 "자기"가되는 것 대신에, 나는이 명명법을 따르기가 더 쉽다. 그래도 반드시 "올바른"것은 아닙니다.)
그런 다음 생성 된 클래스에 __dir__
및 __getattr__
을 직접 작성하여 인스턴스에 적용 할 수 있습니다. 그걸로 잡는 것은 당신이 이미 만들고있는 클래스가 __getattr__
또는 커스텀 __dir__
을 가지고 있다는 것입니다. 슈퍼 클래스에서도 래핑되어야합니다. 보장함으로써,하지만 "올바른 일을"-
class Pipeable(type):
_classes = {}
def __new__(metacls, name, bases, namespace, **kwds):
cls = type.__new__(metacls, name, bases, namespace)
metacls._classes[name] = cls
original__getattr__ = getattr(cls, "__getattr__", None)
if hasattr(original__getattr__, "_metapipping"):
# Do not wrap our own (metaclass) implementation of __getattr__
original__getattr__ = None
original__dir__ = getattr(cls, "__dir__") # Exists in "object", so it is always found.
# these two functions have to be nested so they can get the
# values for the originals "__getattr__" and "__dir__" from
# the closure. These values could be set on the class created, alternatively.
def __getattr__(self, attr):
if original__getattr__:
# If it is desired that normal attribute lookup have
# less precedence than these injected operators
# move this "if" block down.
try:
value = original__getattr__(self, attr)
except AttributeError:
pass
else:
return value
classes = self.__class__.__class__._classes
if attr not in classes:
raise AttributeError
def pipe_within(*args, **kwargs):
return cls(*args, op=classes[attr], **kwargs)
print('piping...')
return pipe_within
__getattr__._pipping = True
def __dir__(self):
regular = original__dir__(self)
return sorted(regular + list(self.__class__.__class__._classes.keys()))
__dir__.pipping = True
if not original__getattr__ or not hasattr(original__getattr__, "_pipping"):
cls.__getattr__ = __getattr__
if not hasattr(original__dir__, "_pipping"):
cls.__dir__ = __dir__
return cls
def __getattr__(cls, attr):
classes = cls.__class__._classes
if attr not in classes:
raise AttributeError
def pipe_within(*args, **kwargs):
return cls(*args, op=classes[attr], **kwargs)
print('piping...')
return pipe_within
__getattr__._metapipping = True
def __dir__(cls):
regular = super().__dir__()
return sorted(regular + list(cls.__class__._classes.keys()))
class Op(metaclass=Pipeable):
def __init__(self, op=None):
if op is not None:
print('piped!')
Op().Op()
그래서,이 긴 었죠 : 그리고, 우리는 우리의 __dir__
자신과 __getattr__
, 그래서 몇 가지 여분의 케어를 다시 포장하고 싶지 않아 계층의 모든 클래스와 인스턴스는 생성 순서에 관계없이 서로를 볼 수 있습니다. 복잡성을 만회 무엇 또한
이 제대로 클래스 계층 구조에
__getattr__
및
__dir__
의 다른 가능한 사용자 정의를 포장한다 - 당신이 그 어떤 정의를 얻을 수없는 경우,이 크기는 간단한의 순서가 될 수 있습니다
class Pipeable(type):
_classes = {}
def __new__(metacls, name, bases, namespace, **kwds):
cls = type.__new__(metacls, name, bases, namespace)
metacls._classes[name] = cls
def __getattr__(self, attr):
classes = self.__class__.__class__._classes
if attr not in classes:
raise AttributeError
def pipe_within(*args, **kwargs):
return cls(*args, op=classes[attr], **kwargs)
print('piping...')
return pipe_within
def __dir__(self):
regular = original__dir__(self)
return sorted(regular + list(self.__class__.__class__._classes.keys()))
cls.__getattr__ = __getattr__
cls.__dir__ = __dir__
return cls
def __getattr__(cls, attr):
classes = cls.__class__._classes
if attr not in classes:
raise AttributeError
def pipe_within(*args, **kwargs):
return cls(*args, op=classes[attr], **kwargs)
print('piping...')
return pipe_within
def __dir__(cls):
regular = super().__dir__()
return sorted(regular + list(cls.__class__._classes.keys()))
설명자가 기술자가 아닌 클래스에 있어야합니다. – user2357112