以下代码允许我按照元类的工作方式进行操作。但是,什么时候
第21行和第22行未注释,Metaclass.__init__
将失败,因为self
参数未传递给包装方法。是什么导致VerboseFunction.__call__
未将所需的Metaclass
实例传递给初始化程序?
import sys, types
def sign(prefix, argcount=None):
f = sys._getframe(1)
print('{}.{}({})\n'.format(prefix, f.f_code.co_name,
', '.join(repr(f.f_locals[name])
for name in f.f_code.co_varnames[:f.f_code.co_argcount
if argcount is None else min(argcount, f.f_code.co_argcount)])))
class VerboseMetaclass(type):
def __new__(cls, name, bases, classdict):
sign('VerboseMetaclass')
for key in sorted(classdict):
classdict[key.encode()] = value = classdict.pop(key)
classdict[key] = cls.wrap('{}.{}'.format(name, key), value)
return super().__new__(cls, name, bases, classdict)
def wrap(key, value):
sign('VerboseMetaclass')
## if isinstance(value, types.FunctionType):
## return VerboseFunction(key, value)
return value
class VerboseFunction:
def __init__(self, name, func):
vars(self).update(locals())
def __call__(self, *args, **kwargs):
if self.name.endswith('.__init__'):
print('SPECIAL !!!')
name = self.call(args, kwargs)
print('[ -> ] {!s}\n'.format(name))
try:
value = self.func(*args, **kwargs)
print('[ <- ] {!s} [return {!r}]\n'.format(name, value))
return value
except:
value = sys.exc_info()[1]
print('[ <- ] {!s} [raise {!r}]\n'.format(name, value))
raise
def call(self, args, kwargs):
args = tuple('{!r}'.format(item) for item in args)
kwargs = tuple('{!s}={!r}'.format(key, kwargs[key])
for key in sorted(kwargs))
return '{}({})'.format(self.name, ', '.join(args + kwargs))
class Metaclass(type, metaclass=VerboseMetaclass):
@classmethod
def __prepare__(metacls, name, bases):
sign('Metaclass')
return super().__prepare__(name, bases)
def __new__(cls, name, bases, classdict):
sign('Metaclass')
for key, value in {'__new__': cls.new, '__init__': cls.init}.items():
if key in classdict:
classdict[key.encode()] = classdict[key]
classdict[key] = value
return super().__new__(cls, name, bases, classdict)
def __init__(self, name, bases, classdict):
sign('Metaclass')
return super().__init__(name, bases, classdict)
def __call__(self):
sign('Metaclass')
return super().__call__()
def new(cls):
sign('Metaclass')
return vars(cls)[b'__new__'](cls)
def init(self):
sign('Metaclass')
return vars(self.__class__)[b'__init__'](self)
class Test(metaclass=Metaclass):
def __new__(cls):
sign('Test')
return super().__new__(cls)
def __init__(self):
sign('Test')
return super().__init__()
def run(self):
sign('Test')
Test().run()
答案 0 :(得分:2)
可以修改VerboseMetaclass
类,并且可以删除VerboseFunction
类。 VerboseMetaclass.wrap
应更改如下,并添加wrap_function
。
@classmethod
def wrap(cls, key, value):
sign('VerboseMetaclass')
if isinstance(value, types.FunctionType):
return cls.wrap_function(key, value)
return value
def wrap_function(name, func):
sign('VerboseMetaclass')
@functools.wraps(func)
def verbose_function(*args, **kwargs):
args_str = tuple(repr(item) for item in args)
kwargs_str = tuple('{!s}={!r}'.format(*pair)
for pair in sorted(kwargs.items()))
signature = '{}({})'.format(name, ', '.join(args_str + kwargs_str))
print('[ -> ] {}\n'.format(signature))
try:
value = func(*args, **kwargs)
print('[ <- ] {!s} [return {!r}]\n'.format(signature, value))
return value
except:
value = sys.exc_info()[1]
print('[ <- ] {!s} [raise {!r}]\n'.format(signature, value))
raise
return verbose_function
编辑:此代码的完成后的第二稿可以在下面看到。此示例的目的是观察创建,实例化和监视类及其实例所涉及的“机制”。大部分代码也是自我监控的(VerboseMetaclass
除外),因此可以看到代码本身是如何运行的。通过将类的元类设置为Metaclass
,您自己的类及其实例也将打印出监视消息。 Test
类提供了一个示例。
import types, functools, sys
class VerboseMetaclass(type):
def __new__(cls, name, bases, classdict):
for key in sorted(filter(
lambda name: isinstance(name, str), classdict)):
classdict[key] = cls.wrap('{}.{}'.format(name, key), classdict[key])
return super().__new__(cls, name, bases, classdict)
@classmethod
def wrap(cls, name, value):
if isinstance(value, types.FunctionType):
return cls.wrap_function(name, value)
if isinstance(value, classmethod):
return classmethod(cls.wrap_function(name, value.__func__))
if isinstance(value, staticmethod):
return staticmethod(cls.wrap_function(name, value.__func__))
try:
return VerboseData(name, value)
except NameError:
return value
def wrap_function(name, func):
@functools.wraps(func)
def verbose_function(*args, **kwargs):
args_str = tuple((object.__repr__(item)
if isinstance(item, VerboseData)
else repr(item)) for item in args)
kwargs_str = tuple('{!s}={!r}'.format(*pair)
for pair in sorted(kwargs.items()))
signature = '{}({})'.format(name, ', '.join(args_str + kwargs_str))
print('[ -> ] {}\n'.format(signature))
try:
value = func(*args, **kwargs)
print('[ <- ] {!s} [return {!r}]\n'.format(signature, value))
return value
except:
value = sys.exc_info()[1]
print('[ <- ] {!s} [raise {!r}]\n'.format(signature, value))
raise
return verbose_function
class VerboseData(metaclass=VerboseMetaclass):
def __init__(self, name, value):
vars(self).update(locals())
def __repr__(self):
return repr(self.value)
def __get__(self, instance, owner):
value = self.value
if isinstance(value, (property, VerboseData)):
value = value.__get__(instance, owner)
print('[ get ] {!s} = {!r}\n'.format(self.name, value))
return value
def __set__(self, instance, value):
print('[ set ] {!s} = {!r}\n'.format(self.name, value))
if isinstance(self.value, (property, VerboseData)):
self.value.__set__(instance, value)
else:
self.value = value
def __delete__(self, instance):
print('[ XX ] {}\n'.format(self.name))
if isinstance(self.value, (property, VerboseData)):
self.value.__delete__(instance)
else:
del self.value
def __iter__(self):
return iter(self.value)
class Metaclass(VerboseMetaclass, metaclass=VerboseMetaclass):
@classmethod
def __prepare__(metacls, name, bases):
return super().__prepare__(name, bases)
def __new__(cls, name, bases, classdict):
for key, value in {'__new__': cls.new, '__init__': cls.init}.items():
if key in classdict:
classdict[key.encode()] = classdict[key]
classdict[key] = value
return super().__new__(cls, name, bases, classdict)
def __init__(self, name, bases, classdict):
return super().__init__(name, bases, classdict)
def __call__(self, *args, **kwargs):
return super().__call__(*args, **kwargs)
def new(cls, *args, **kwargs):
for base in cls.__mro__:
try:
return vars(base)[b'__new__'](cls, *args, **kwargs)
except KeyError:
pass
return object.__new__(cls, *args, **kwargs)
def init(self, *args, **kwargs):
for base in self.__class__.__mro__:
try:
return vars(base)[b'__init__'](self, *args, **kwargs)
except KeyError:
pass
return object.__init__(self)
if __name__ == '__main__':
class Test(metaclass=Metaclass):
def __new__(cls):
return super().__new__(cls)
def __init__(self):
return super().__init__()
def run(self):
pass
Test().run()
答案 1 :(得分:0)
你只是迷失在自己设计的迷宫中,无论是我还是我:)
您的错误可以建模为:
class VerboseFunction:
def __init__(self, name, func):
self.name, self.func = name, func
def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)
class Metaclass:
def __init__(self):
pass
# Comment out the line below
__init__ = VerboseFunction('Metaclass.__init__', __init__)
print(Metaclass())
这意味着您在没有自我实例的情况下直接调用Metaclass.__init__()
。