自学python,关于with_metaclass的问题

关于with_metaclass的问题

研究了好几晚都搞不下来,网上所有资料都找遍了T_T

 

有劳各位bigmaster先看代码吧:
代码1:

class Tmeta(type):
    def __new__(cls, *args, **kwargs):
        return type.__new__(cls, *args, **kwargs)

def with_metaclass(meta, *bases):
    class metaclass(meta):
        def __new__(cls, name, bases, attrs):
            print(cls, name, bases, attrs)
            return meta(cls, name, bases, attrs)
    return type.__new__(metaclsss, 'withmeta', (), {})

# 原版会传入一个object对应with_metaclass参数*bases,不过我发现传不传入都对这个问题不影响
class Textclass(with_metaclass(Tmeta)):
    # 随便设一些属性,和属性应该没关系
    number = 666

    def __init__(self, name):
        self.name = name

    def say(self):
        print(f'my name is {self.name}')

t = Textclass('John')
t.say()

 

代码2:

class Tmeta(type):
    def __new__(cls, *args, **kwargs):
        return type.__new__(cls, *args, **kwargs)

class maclass(Tmeta):
    def __new__(cls, name, bases, attrs):
        print(cls, name, bases, attrs)
        return Tmeta(cls, name, bases, attrs)

Withmeta = type.__new__(maclsss, 'withmeta', (), {})

class Textclass(Withmeta):
    # 随便设一些属性,和属性应该没关系,试过textclass里面即使设成pass结果也是一样报错
    number = 666

    def __init__(self, name):
        self.name = name

    def say(self):
        print(f'my name is {self.name}')

t = Textclass('John')
t.say()

 

代码3(以下主要都是对代码1和代码2自己用其他类似写法的测试):

class Tmeta(type):
    def __new__(cls, *args, **kwargs):
        return type.__new__(cls, *args, **kwargs)

class maclass(Tmeta):
    def __new__(cls, name, bases, attrs):
        print(cls, name, bases, attrs)
        return Tmeta(cls, name, bases, attrs)

class Withmeta(metaclass=maclass)
    pass

class Textclass(Withmeta):
    number = 666

    def __init__(self, name):
        self.name = name

    def say(self):
        print(f'my name is {self.name}')

t = Textclass('John')
t.say()

 

代码4:

class Tmeta(type):
    def __new__(cls, *args, **kwargs):
        return type.__new__(cls, *args, **kwargs)

class maclass(Tmeta):
    def __new__(cls, name, bases, attrs):
        print(cls, name, bases, attrs)
        return Tmeta(cls, name, bases, attrs)

class Textclass(metaclass=maclass):
    number = 666

    def __init__(self, name):
        self.name = name

    def say(self):
        print(f'my name is {self.name}')

t = Textclass('John')
t.say()

 

问题

1.为什么只有代码2会报错?这里主要是为了搞懂代码1和代码2之间的不同。据我所知这个with_metaclass()相当于是个闭包,return type.__new__(metaclsss, 'withmeta', (), {})with_metaclass()的返回主体,猜测with_metaclass()传递完属性给Textclasstype.__new__(metaclsss, 'withmeta', (), {})就会消失,只在栈堆里保留这些属性作为freevars存在,也不知这个猜测是否正确。

 

2.如果把functionwith_metaclass()拆开来写,实现与代码1最近似(最好是完全相同)的结果,应该怎么写?这个问题主要是想清楚理解到底这with_metaclass()到底内部运作逻辑干了啥导致这样的结果以及彻底明白与代码2中的Withmeta都有些啥不一样

 

3.type__new__(metaclass, name, bases, ns)metaclass(name, bases, ns)除了调用的函数少了个__init__之外有啥不一样?主要是想知道type.__new__type()创建的class有什么不同。

 

最后在此先行对给予回答的bigmaster表示感谢!以及先声明一下我是非科班生野路子,完全靠网上资料自学从零开始只有一年,所以上面如果有啥名词写错了或者一些缩进等的小错误还望大家谅解,上面代码完全是手打的,所以上面缩进我也不知道有没有打错自己数着空格打的,预览好像是正确吧。最后先在此谢谢大家

希望有用
https://b23.tv/nxRXZkJ

img


你这是怎么不报错的😂

我的brother告诉我,我爸爸是b,但原来a才是他爸爸,而a是b的爸爸。当我把我brother从历史中抹除,一切恢复正常(当然深入的问题还有其他副原因,但我懂了)