python随用随学-元类

2019/04/10 10:10
阅读数 12

<section id="nice" data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px; padding: 10px; word-spacing: 0px; word-break: break-word; word-wrap: break-word; text-align: left; line-height: 1.75; color: #595959; font-family: Optima-Regular, Optima, PingFangTC-Light, PingFangSC-light, PingFangTC-light; letter-spacing: 2px; background-image: linear-gradient(90deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%), linear-gradient(360deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%); background-size: 20px 20px; background-position: center center;"><h2 data-tool="mdnice编辑器" style="margin-top: 40px; margin-bottom: 20px; font-weight: bold; color: black; font-size: 24px; text-align: left; margin: 20px 10px 0px 0px;"><span style="font-size: 18px; font-weight: bold; display: inline-block; padding-left: 10px; border-left: 5px solid #DEC6FB; color: #595959;">python中的一切都是对象</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">按着我的逻辑走:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: #595959; list-style-type: circle;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; font-size: 14px; font-weight: normal; color: #595959;">首先接受一个公理,<strong style="color: #595959; font-weight: bold;"><span>「</span>python中的一切都是对象<span>」</span></strong>.不要问为什么,吉大爷(Guido van Rossum,python之父)人当初就是这么设计的,不服去找他评理!</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; font-size: 14px; font-weight: normal; color: #595959;">类是python语言的一个元素</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; font-size: 14px; font-weight: normal; color: #595959;">那么类也是一个对象</section></li></ul> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">是的,类也是一个对象,因为python中万物皆对象. 只不过类这个对象具有创建对象的能力.</p> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">那么问题来了,既然类也是一个对象,那本质上它和其他对象没有啥区别,我们可以对它进行一下操作:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: #595959; list-style-type: circle;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; font-size: 14px; font-weight: normal; color: #595959;">可以赋值给一个变量</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; font-size: 14px; font-weight: normal; color: #595959;">可以拷贝</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; font-size: 14px; font-weight: normal; color: #595959;">可以增加属性</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; font-size: 14px; font-weight: normal; color: #595959;">可以当做入参传递给函数</section></li></ul> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">而且因为类也是一个对象,所以可以在程序运行的时候进行动态的传递.</p> <pre class="custom" data-tool="mdnice编辑器" style="margin-top: 10px; margin-bottom: 10px;"><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; background: #282c34; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;"><span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">def</span> <span class="hljs-title" style="color: #61aeee; line-height: 26px;">choose_class</span><span class="hljs-params" style="line-height: 26px;">(name)</span>:</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> name == <span class="hljs-string" style="color: #98c379; line-height: 26px;">'foo'</span>: <span class="hljs-class" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">class</span> <span class="hljs-title" style="color: #e6c07b; line-height: 26px;">Foo</span>:</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">pass</span>

    <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> Foo
<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">else</span>:
    <span class="hljs-class" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">class</span> <span class="hljs-title" style="color: #e6c07b; line-height: 26px;">Bar</span>:</span>
        <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">pass</span>

    <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> Bar

Myclass = choose_class(<span class="hljs-string" style="color: #98c379; line-height: 26px;">'foo'</span>)

print(Myclass) print(Myclass()) </code></pre>

<p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">看一个简单的例子.首先<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">choose_class()</code>函数中动态的创建了类,然后将类作为返回值 然后我们通过一个变量Myclass接收了这个返回值.</p> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">看下面两个print,第一个打印的是我们创建出的类. 第二个打印的是我们创建的类创建的对象.</p> <pre class="custom" data-tool="mdnice编辑器" style="margin-top: 10px; margin-bottom: 10px;"><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; background: #282c34; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;">&lt;<span class="hljs-class" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">class</span> '<span class="hljs-title" style="color: #e6c07b; line-height: 26px;">__main__</span>.<span class="hljs-title" style="color: #e6c07b; line-height: 26px;">choose_class</span>.&lt;<span class="hljs-title" style="color: #e6c07b; line-height: 26px;">locals</span>&gt;.<span class="hljs-title" style="color: #e6c07b; line-height: 26px;">Foo</span>'&gt; &lt;<span class="hljs-title" style="color: #e6c07b; line-height: 26px;">__main__</span>.<span class="hljs-title" style="color: #e6c07b; line-height: 26px;">choose_class</span>.&lt;<span class="hljs-title" style="color: #e6c07b; line-height: 26px;">locals</span>&gt;.<span class="hljs-title" style="color: #e6c07b; line-height: 26px;">Foo</span> <span class="hljs-title" style="color: #e6c07b; line-height: 26px;">object</span> <span class="hljs-title" style="color: #e6c07b; line-height: 26px;">at</span> 0<span class="hljs-title" style="color: #e6c07b; line-height: 26px;">x0000017102113208</span>&gt; </span></code></pre> <h2 data-tool="mdnice编辑器" style="margin-top: 40px; margin-bottom: 20px; font-weight: bold; color: black; font-size: 24px; text-align: left; margin: 20px 10px 0px 0px;"><span style="font-size: 18px; font-weight: bold; display: inline-block; padding-left: 10px; border-left: 5px solid #DEC6FB; color: #595959;">使用type创建类</span></h2> <blockquote data-tool="mdnice编辑器" style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; text-size-adjust: 100%; line-height: 1.55em; font-weight: 400; border-radius: 6px; color: #595959; font-style: normal; text-align: left; box-sizing: inherit; border-left: none; border: 1px solid #DEC6FB; background: #F6EEFF;"><span style="color: #DEC6FB; font-size: 34px; line-height: 1; font-weight: 700;">❝</span> <p style="padding-top: 8px; padding-bottom: 8px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px; margin: 0px; line-height: 26px; color: #595959;"><strong style="color: #595959; font-weight: bold;"><span>「</span><code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">class type(object)</code><span>」</span></strong> <strong style="color: #595959; font-weight: bold;"><span>「</span><code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">class type(name, bases, dict)</code><span>」</span></strong> With one argument, return the type of an object. The return value is a type object and generally the same object as returned by <code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">object.__class__.</code> The isinstance() built-in function is recommended for testing the type of an object, because it takes subclasses into account.</p> <span style="float: right; color: #DEC6FB;">❞</span></blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">type这个类一看就很特别,因为首字母是小写的...它可以用来创建一个类...</p> <pre class="custom" data-tool="mdnice编辑器" style="margin-top: 10px; margin-bottom: 10px;"><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; background: #282c34; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;">Foo = type(<span class="hljs-string" style="color: #98c379; line-height: 26px;">'Foo'</span>, (object,), {<span class="hljs-string" style="color: #98c379; line-height: 26px;">'bar'</span>:<span class="hljs-literal" style="color: #56b6c2; line-height: 26px;">True</span>})

print(Foo)

foo = Foo()

print(foo) print(foo.bar) </code></pre>

<p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">这里的代码和下面的类创建代码是类似的</p> <pre class="custom" data-tool="mdnice编辑器" style="margin-top: 10px; margin-bottom: 10px;"><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; background: #282c34; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;"><span class="hljs-class" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">class</span> <span class="hljs-title" style="color: #e6c07b; line-height: 26px;">Foo</span><span class="hljs-params" style="line-height: 26px;">(object)</span>:</span>&nbsp;&nbsp;&nbsp; bar = <span class="hljs-literal" style="color: #56b6c2; line-height: 26px;">True</span> </code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;"><strong style="color: #595959; font-weight: bold;"><span>「</span>向类中添加方法<span>」</span></strong></p> <pre class="custom" data-tool="mdnice编辑器" style="margin-top: 10px; margin-bottom: 10px;"><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; background: #282c34; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;">Foo = type(<span class="hljs-string" style="color: #98c379; line-height: 26px;">'Foo'</span>, (object,), {<span class="hljs-string" style="color: #98c379; line-height: 26px;">'bar'</span>: <span class="hljs-literal" style="color: #56b6c2; line-height: 26px;">True</span>})

<span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">def</span> <span class="hljs-title" style="color: #61aeee; line-height: 26px;">get_bar</span><span class="hljs-params" style="line-height: 26px;">(self)</span>:</span> print(self.bar)

FooChild = type(<span class="hljs-string" style="color: #98c379; line-height: 26px;">'FooChild'</span>, (Foo,), {<span class="hljs-string" style="color: #98c379; line-height: 26px;">'get_bar'</span>: get_bar}) print(hasattr(FooChild,<span class="hljs-string" style="color: #98c379; line-height: 26px;">'get_bar'</span>)) myfoo = FooChild() print(myfoo) myfoo.get_bar() </code></pre>

<h2 data-tool="mdnice编辑器" style="margin-top: 40px; margin-bottom: 20px; font-weight: bold; color: black; font-size: 24px; text-align: left; margin: 20px 10px 0px 0px;"><span style="font-size: 18px; font-weight: bold; display: inline-block; padding-left: 10px; border-left: 5px solid #DEC6FB; color: #595959;">元类</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">简单来说,元类就是用来创建类的类. 比如我们上面使用的type就是一个python内置的元类.</p> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">比如我们来干一件神器的事情</p> <figure data-tool="mdnice编辑器" style="margin: 0; margin-top: 10px; margin-bottom: 10px;"><img src="https://imgkr.cn-bj.ufileos.com/26d9da59-24ee-4c2e-803d-36a1fe7d94b0.png" alt style="width: 100%; border-radius: 6px; display: block; margin: 20px auto; height: 100%; object-fit: contain;"></figure> <h3 data-tool="mdnice编辑器" style="margin-top: 40px; margin-bottom: 20px; color: black; font-size: 16px; font-weight: bold; text-align: center;"><span style="border-bottom: 2px solid #DEC6FB; color: #595959;"><code>__metaclass__</code>属性(python3不再支持)</span></h3> <blockquote data-tool="mdnice编辑器" style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; text-size-adjust: 100%; line-height: 1.55em; font-weight: 400; border-radius: 6px; color: #595959; font-style: normal; text-align: left; box-sizing: inherit; border-left: none; border: 1px solid #DEC6FB; background: #F6EEFF;"><span style="color: #DEC6FB; font-size: 34px; line-height: 1; font-weight: 700;">❝</span> <p style="padding-top: 8px; padding-bottom: 8px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px; margin: 0px; line-height: 26px; color: #595959;"><strong style="color: #595959; font-weight: bold;"><span>「</span>NOTE!!!<span>」</span></strong> python3中不再支持<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__metaclass__</code>属性,而是在定义类的时候使用<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">metaclass=XXXX</code>参数</p> <span style="float: right; color: #DEC6FB;">❞</span></blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">在写一个类的时候,如果我们指定了<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__metaclass__</code>属性,就说明我们指明了这个类的元类.</p> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">比如我们定义一个类:</p> <pre class="custom" data-tool="mdnice编辑器" style="margin-top: 10px; margin-bottom: 10px;"><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; background: #282c34; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;"><span class="hljs-class" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">class</span> <span class="hljs-title" style="color: #e6c07b; line-height: 26px;">MyClass</span><span class="hljs-params" style="line-height: 26px;">()</span>:</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">pass</span> </code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">类在定义的时候,它在内存中还没有生成,知道它会被调用,python会做以下的事情:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; list-style-type: decimal; color: #595959;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; font-size: 14px; font-weight: normal; color: #595959;">在MyClass中寻找<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__metaclass__</code>属性,如果有,python会在内存中创建一个名字叫MyClass的类对象(注意,是类!对象)</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; font-size: 14px; font-weight: normal; color: #595959;">如果在MyClass中没有找到<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__metaclass__</code>属性,那么会在它的父类中继续寻找</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; font-size: 14px; font-weight: normal; color: #595959;">如果父类里还没有,那么回到模块底层去找</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; font-size: 14px; font-weight: normal; color: #595959;">如果模块底层还没有,Python会使用type作为元类来创建这个类.</section></li></ol> <h3 data-tool="mdnice编辑器" style="margin-top: 40px; margin-bottom: 20px; color: black; font-size: 16px; font-weight: bold; text-align: center;"><span style="border-bottom: 2px solid #DEC6FB; color: #595959;">自定义元类</span></h3> <h4 data-tool="mdnice编辑器" style="margin-top: 40px; margin-bottom: 20px; font-weight: bold; color: black; font-size: 18px;"><span>使用函数定义元类</span></h4> <pre class="custom" data-tool="mdnice编辑器" style="margin-top: 10px; margin-bottom: 10px;"><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; background: #282c34; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;"><span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">def</span> <span class="hljs-title" style="color: #61aeee; line-height: 26px;">upper_attr</span><span class="hljs-params" style="line-height: 26px;">(future_class_name, future_class_parents, future_class_attr)</span>:</span> attrs = ((name, value) <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">for</span> name, value <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">in</span> future_class_attr.items() <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">not</span> name.startswith(<span class="hljs-string" style="color: #98c379; line-height: 26px;">'__'</span>)) uppercase_attr = dict((name.upper(), value) <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">for</span> name, value <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">in</span> attrs) <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> type(future_class_name, future_class_parents, uppercase_attr)

<span class="hljs-class" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">class</span> <span class="hljs-title" style="color: #e6c07b; line-height: 26px;">MyMetacalss</span><span class="hljs-params" style="line-height: 26px;">(object, metaclass=upper_attr)</span>:</span> bar = <span class="hljs-string" style="color: #98c379; line-height: 26px;">'bip'</span>

print(hasattr(MyMetacalss, <span class="hljs-string" style="color: #98c379; line-height: 26px;">'bar'</span>)) print(hasattr(MyMetacalss, <span class="hljs-string" style="color: #98c379; line-height: 26px;">'BAR'</span>))

c = MyMetacalss() print(c.BAR)

</code></pre>

<h4 data-tool="mdnice编辑器" style="margin-top: 40px; margin-bottom: 20px; font-weight: bold; color: black; font-size: 18px;"><span>使用class来定义元类</span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">先看一下文档中<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__new__</code>方法的定义.</p> <blockquote data-tool="mdnice编辑器" style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; text-size-adjust: 100%; line-height: 1.55em; font-weight: 400; border-radius: 6px; color: #595959; font-style: normal; text-align: left; box-sizing: inherit; border-left: none; border: 1px solid #DEC6FB; background: #F6EEFF;"><span style="color: #DEC6FB; font-size: 34px; line-height: 1; font-weight: 700;">❝</span> <p style="padding-top: 8px; padding-bottom: 8px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px; margin: 0px; line-height: 26px; color: #595959;"><strong style="color: #595959; font-weight: bold;"><span>「</span><code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">object.__new__(cls[, ...])</code><span>」</span></strong> Called to create a new instance of class cls.<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__new__()</code>is a static method (special-cased so you need not declare it as such) that takes the class of which an instance was requested as its first argument. The remaining arguments are those passed to the object constructor expression (the call to the class). The return value of<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__new__()</code>should be the new object instance (usually an instance of cls). Typical implementations create a new instance of the class by invoking the superclass’s <code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__new__()</code> method using <code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">super().__new__(cls[, ...])</code> with appropriate arguments and then modifying the newly-created instance as necessary before returning it. If <code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__new__()</code>returns an instance of cls, then the new instance’s <code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__init__()</code>method will be invoked like<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__init__(self[, ...]),</code>where self is the new instance and the remaining arguments are the same as were passed to<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__new__()</code>. If <code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__new__()</code> does not return an instance of cls, then the new instance’s <code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__init__()</code>method will not be invoked. <code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__new__()</code> is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation.</p> <span style="float: right; color: #DEC6FB;">❞</span></blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">明白了<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__new__</code>方法,那改写起来就简单了</p> <pre class="custom" data-tool="mdnice编辑器" style="margin-top: 10px; margin-bottom: 10px;"><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; background: #282c34; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;"><span class="hljs-class" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">class</span> <span class="hljs-title" style="color: #e6c07b; line-height: 26px;">Upper</span><span class="hljs-params" style="line-height: 26px;">(type)</span>:</span> <span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">def</span> <span class="hljs-title" style="color: #61aeee; line-height: 26px;">__new__</span><span class="hljs-params" style="line-height: 26px;">(cls, name, bases, attrs)</span>:</span> attr = ((name, value) <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">for</span> name, value <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">in</span> attrs.items() <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">not</span> name.startswith(<span class="hljs-string" style="color: #98c379; line-height: 26px;">'__'</span>)) uppercase_attr = dict((name.upper(), value) <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">for</span> name, value <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">in</span> attr) <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> type.__new__(cls, name, bases, uppercase_attr) </code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">还有一种写法是通过调用父类的<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__new__()</code>方法来返回类对象. 如果子类需要重写<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__new__()</code>方法的话,一般要调用父类的<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__new__()</code>方法.</p> <pre class="custom" data-tool="mdnice编辑器" style="margin-top: 10px; margin-bottom: 10px;"><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; background: #282c34; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;"><span class="hljs-class" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">class</span> <span class="hljs-title" style="color: #e6c07b; line-height: 26px;">Upper</span><span class="hljs-params" style="line-height: 26px;">(type)</span>:</span> <span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">def</span> <span class="hljs-title" style="color: #61aeee; line-height: 26px;">__new__</span><span class="hljs-params" style="line-height: 26px;">(cls, name, bases, attrs)</span>:</span> attr = ((name, value) <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">for</span> name, value <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">in</span> attrs.items() <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">not</span> name.startswith(<span class="hljs-string" style="color: #98c379; line-height: 26px;">'__'</span>)) uppercase_attr = dict((name.upper(), value) <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">for</span> name, value <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">in</span> attr) <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> super(Upper,cls).__new__(cls, name, bases , uppercase_attr) </code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">另外通过上面的文档,我们也能知道一个对象创建的时候会有那些操作.</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; list-style-type: decimal; color: #595959;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; font-size: 14px; font-weight: normal; color: #595959;">调用<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__new__()</code>方法来创建内存空间</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; font-size: 14px; font-weight: normal; color: #595959;">之后调用<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: #595959;">__init__()</code>方法来初始化参数.</section></li></ol> <figure data-tool="mdnice编辑器" style="margin: 0; margin-top: 10px; margin-bottom: 10px;"><img src="https://imgkr.cn-bj.ufileos.com/9a0e2aac-5e1c-4025-b5e2-ddde0df5eeb8.png" alt style="width: 100%; border-radius: 6px; display: block; margin: 20px auto; height: 100%; object-fit: contain;"></figure> <hr data-tool="mdnice编辑器" style="margin: 0; margin-top: 10px; margin-bottom: 10px; height: 1px; padding: 0; border: none; border-top: 2px solid #d9b8fa;"> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; line-height: 26px; color: #595959; margin: 10px 0px; letter-spacing: 2px; font-size: 14px; word-spacing: 2px;">参考资料:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; list-style-type: decimal; color: #595959;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; font-size: 14px; font-weight: normal; color: #595959;"><a href="https://www.jianshu.com/p/cb9c92705a19" style="text-decoration: none; word-wrap: break-word; color: #664D9D; font-weight: normal; border-bottom: 1px solid #664D9D;">python中的元类-简书</a></section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; font-size: 14px; font-weight: normal; color: #595959;"><a href="https://www.cnblogs.com/tkqasn/p/6524879.html" style="text-decoration: none; word-wrap: break-word; color: #664D9D; font-weight: normal; border-bottom: 1px solid #664D9D;">深刻理解Python中的元类(metaclass)以及元类实现单例模式</a></section></li></ol> </section>

原文出处:https://www.cnblogs.com/thecatcher/p/12422646.html

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部