上海幕墙精制钢 發表於 2020-3-2 22:53:00

python类变量与__init__声明变量的区别

<div><span style="font-size: 16px"><strong>类变量</strong>:可在类的所有实例之间共享的变量</span></div>
<div><span style="font-size: 16px"><strong>实例类对象</strong>:类的实例是调用类对象来创建的。如:par = Parent(),par就是类Parent的一个实例类对象。</span></div>
<div><span style="font-size: 16px"><strong>实例变量</strong>(成员变量):同一个类对象可以创建多个实例类对象,类定义中有self标志的变量就是实例变量</span></div>
<div><span style="font-size: 16px">&nbsp;</span></div>
<div><span style="color: rgba(77, 77, 77, 1); font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; font-size: 16px">一个例子,看下面的代码有个小问题</span></div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MyObject(object):
    x </span>= 1
    <span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">(self):
      objectNum </span>= 99
    <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> changeNum(self, anotherNum):
      self.objectNum </span>=<span style="color: rgba(0, 0, 0, 1)"> anotherNum
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> showNum(self):
      </span><span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">self.num = </span><span style="color: rgba(128, 0, 0, 1)">"</span>, self.objectNum)</span></pre>
</div>
</div>
<div><span style="font-size: 16px">什么问题呢,看似构造函数__init__中的变量object在实例化对象的时候会自动创建并初始化为99,其实不然,这里用一个小的测试代码就可以发现问题。</span></div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">obj =<span style="color: rgba(0, 0, 0, 1)"> MyObject()
obj.showNum()
Traceback (most recent call last):
File </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">class.py</span><span style="color: rgba(128, 0, 0, 1)">"</span>, line 24, <span style="color: rgba(0, 0, 255, 1)">in</span> &lt;module&gt;<span style="color: rgba(0, 0, 0, 1)">
    obj.showNum()
File </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">class.py</span><span style="color: rgba(128, 0, 0, 1)">"</span>, line 20, <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> showNum
    </span><span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">self.num = </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, self.objectNum)
AttributeError: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">MyObject</span><span style="color: rgba(128, 0, 0, 1)">'</span> object has no attribute <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">objectNum</span><span style="color: rgba(128, 0, 0, 1)">'</span></span></pre>
</div>
</div>
<div><span style="font-size: 16px">报错了,提示实例化对象MyObject并没有objectNum这个普通成员变量,为什么呢?</span></div>
<div><span style="font-size: 16px">问题就在于,在Python中,类的成员变量必须使用self.propertName进行声明,这样才能完成创建,因为self的含义就是代表实例对象;</span></div>
<div><span style="font-size: 16px">在这个类中,objectNum和self.objectNum就是两个完全不同的东西:</span></div>
<div><span style="font-size: 16px">定义在__init__函数中的变量objectNum在这里是一个局部变量,不是类变量</span></div>
<div><span style="font-size: 16px">&nbsp;</span></div>
<div><span style="font-size: 16px">接下来我们可以再写一段代码,调用changNum()方法,来生成这个成员变量self.objectNum:</span></div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">obj =<span style="color: rgba(0, 0, 0, 1)"> MyObject()
obj.changeNum(</span>10<span style="color: rgba(0, 0, 0, 1)">)
obj.showNum()
</span>&gt;&gt;&gt; self.num =10</span></pre>
</div>
</div>
<div><span style="font-size: 16px">能看到成功返回结果,</span></div>
<div><span style="font-size: 16px">由于在changeNum()方法中,有self.objectNum = anotherNum的赋值,而__init__中,没有创建类普通成员变量self.objectNum, 而是创建了一个临时变量objectNum,所以在这里,虽然changeNum()没有被自动调用(因为不是__init__()函数),但是其实充当了创建类成员变量和初始化的作用,&nbsp;但是python并不会在创建新的实例化对象的时候自动调用它。</span></div>
<div><span style="font-size: 16px">&nbsp;</span></div>
<div><span style="color: rgba(77, 77, 77, 1); font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; font-size: 16px">所以通过实验得到3个结论:</span></div>
<div><span style="font-size: 16px"><strong><span style="color: rgba(255, 0, 0, 1)">1.python中的"构造函数"非常的自由,如果不考虑自动调用,任何类方法都可以去创建类成员变量:</span></strong></span></div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ExampleClass:
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> createObjectProperty(self, value):
self.newObjectProperty </span>= value</span></pre>
</div>
</div>
<div><span style="font-size: 16px">如上面的代码,这里声明一个类方法,传入参数self 和 value,调用这个方法,就可以生成一个普通成员变量newObjectProperty,并对其赋初值value</span></div>
<div><span style="color: rgba(255, 0, 0, 1); font-size: 16px"><strong>2.如果想要找到真正意义上的成员变量,那么只需要在__init__(self)中声明self.objectProperty即可</strong></span></div>
<div><span style="color: rgba(255, 0, 0, 1); font-size: 16px"><strong>3.python中的self不能隐式调用,如果你不想生成一个临时变量而是创建一个类成员变量,那么就应该使用self.variableName</strong></span></div>
<div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MyObject(object):
    x </span>= 1
    <span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">(self):
      self.objectNum </span>= 99
    <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> changeNum(self, anotherNum):
      self.objectNum </span>=<span style="color: rgba(0, 0, 0, 1)"> anotherNum
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> showNum(self):
      </span><span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">self.num = </span><span style="color: rgba(128, 0, 0, 1)">"</span>, self.objectNum)</span></pre>
<div><span style="font-size: 16px">obj = MyObject()</span></div>
<div><span style="font-size: 16px"># obj.changeNum(10)</span></div>
<div><span style="font-size: 16px">obj.showNum()</span></div>
<div><span style="font-size: 16px">&gt;&gt;&gt;self.num =&nbsp;&nbsp;99</span></div>
</div>
</div>
</div>
<div><span style="font-size: 16px">知道了成员变量的问题之后,再来讨论一下类变量</span></div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MyObject(object):
    x </span>= 1
    <span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">(self):
      self.objectNum </span>= 99
    <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> changeNum(self, anotherNum):
      self.objectNum </span>=<span style="color: rgba(0, 0, 0, 1)"> anotherNum
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> showNum(self):
      </span><span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">self.num = </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, self.objectNum)




obj </span>=<span style="color: rgba(0, 0, 0, 1)"> MyObject()


</span><span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(MyObject.x)
</span>&gt;&gt;&gt; 1</span></pre>
</div>
<p>&nbsp;</p>
</div>
<div><span style="font-size: 16px">在声明类T的时候,我们在所有的方法之外(但是仍在类的作用域中声明了一个变量classNum),从命名的角度来看,我们希望这是一个类变量,但我们不希望这次又是一个成员变量,测试发现它确实可以由类名直接访问再试一下能否修改:</span></div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">MyObject.x = 100
<span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(MyObject.x)
</span>&gt;&gt;&gt; 100</span></pre>
</div>
</div>
<div><span style="font-size: 16px">发现可以修改</span></div>
<div><span style="font-size: 16px">下面我们验证一下其是否能被所有实例化对象访问和修改,并且是否具有全局性。</span></div>
<div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">t1 =<span style="color: rgba(0, 0, 0, 1)"> MyObject()
</span><span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(t1.x)
</span>&gt;&gt;&gt; 1<span style="color: rgba(0, 0, 0, 1)">
t2 </span>=<span style="color: rgba(0, 0, 0, 1)"> MyObject()
</span><span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(t2.x)
</span>&gt;&gt;&gt; 1<span style="color: rgba(0, 0, 0, 1)">
MyObject.x </span>= 1000
<span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(t1.x)
</span>&gt;&gt;&gt; 1000
<span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(t2.x)
</span>&gt;&gt;&gt; 1000<span style="color: rgba(0, 0, 0, 1)">
t1.x </span>= 2000
<span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(t2.x)
</span>&gt;&gt;&gt;1000
<span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(t1.x)
</span>&gt;&gt;&gt;2000
<span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(MyObject.x)
</span>&gt;&gt;&gt;1000</span></pre>
</div>
</div>
</div>
<div><span style="font-size: 16px">&nbsp;</span></div>
<div><span style="font-size: 16px">从以上结果看出类名.类变量名修改其值会导致实例化对象的值全部被改变,但是用实例化对象名.类变量名修改其值,就仅仅改变自己,不会真的改变类变量的数值。</span></div>
<div><span style="font-size: 16px">我们来检查一下内存,看一段代码:</span></div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">t2 =<span style="color: rgba(0, 0, 0, 1)"> MyObject()
t1 </span>=<span style="color: rgba(0, 0, 0, 1)"> MyObject()


</span><span style="color: rgba(0, 0, 255, 1)">print</span>(MyObject.x <span style="color: rgba(0, 0, 255, 1)">is</span><span style="color: rgba(0, 0, 0, 1)"> t1.x)
</span>&gt;&gt;&gt;<span style="color: rgba(0, 0, 0, 1)">True
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(MyObject.x <span style="color: rgba(0, 0, 255, 1)">is</span><span style="color: rgba(0, 0, 0, 1)"> t2.x)
</span>&gt;&gt;&gt;<span style="color: rgba(0, 0, 0, 1)">True
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(t2.x <span style="color: rgba(0, 0, 255, 1)">is</span><span style="color: rgba(0, 0, 0, 1)"> t1.x)
</span>&gt;&gt;&gt;<span style="color: rgba(0, 0, 0, 1)">True
</span>---------------------------------------<span style="color: rgba(0, 0, 0, 1)">
t2 </span>=<span style="color: rgba(0, 0, 0, 1)"> MyObject()
t1 </span>=<span style="color: rgba(0, 0, 0, 1)"> MyObject()

t2.x </span>= 10
<span style="color: rgba(0, 0, 255, 1)">print</span>(MyObject.x <span style="color: rgba(0, 0, 255, 1)">is</span><span style="color: rgba(0, 0, 0, 1)"> t1.x)
</span>&gt;&gt;&gt;<span style="color: rgba(0, 0, 0, 1)">True
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(MyObject.x <span style="color: rgba(0, 0, 255, 1)">is</span><span style="color: rgba(0, 0, 0, 1)"> t2.x)
</span>&gt;&gt;&gt;<span style="color: rgba(0, 0, 0, 1)">False
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(t2.x <span style="color: rgba(0, 0, 255, 1)">is</span><span style="color: rgba(0, 0, 0, 1)"> t1.x)
</span>&gt;&gt;&gt;<span style="color: rgba(0, 0, 0, 1)">False
</span>--------------------------------------<span style="color: rgba(0, 0, 0, 1)">
t2 </span>=<span style="color: rgba(0, 0, 0, 1)"> MyObject()
t1 </span>=<span style="color: rgba(0, 0, 0, 1)"> MyObject()

MyObject.x </span>= 100<span style="color: rgba(0, 0, 0, 1)">
t2.x </span>= 10
<span style="color: rgba(0, 0, 255, 1)">print</span>(MyObject.x <span style="color: rgba(0, 0, 255, 1)">is</span><span style="color: rgba(0, 0, 0, 1)"> t1.x)
</span>&gt;&gt;&gt;<span style="color: rgba(0, 0, 0, 1)">True
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(MyObject.x <span style="color: rgba(0, 0, 255, 1)">is</span><span style="color: rgba(0, 0, 0, 1)"> t2.x)
</span>&gt;&gt;&gt;<span style="color: rgba(0, 0, 0, 1)">False
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(t2.x <span style="color: rgba(0, 0, 255, 1)">is</span><span style="color: rgba(0, 0, 0, 1)"> t1.x)
</span>&gt;&gt;&gt;False</span></pre>
</div>
</div>
<div><span style="font-size: 16px">看得出来在最开始的时候MyObject.x和实例化对象t1.x与t2.x内存是同一处的,但当直接修改了实例化对象t2.x的数值后t2.x内存的数值便与其他两个不同,所以直接修改实例化对象的数值会指向新的内存空间,并且不受类变量改变而改变。</span></div>
<div><span style="font-size: 16px">总结:</span></div>
<div><span style="box-sizing: border-box; outline: 0; margin: 0; padding: 0; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; overflow-wrap: break-word; font-size: 16px; color: rgba(243, 59, 69, 1)"><span style="box-sizing: border-box; outline: 0; margin: 0; padding: 0; font-weight: bold; overflow-wrap: break-word">一个类<span style="box-sizing: border-box; outline: 0; margin: 0; padding: 0; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; overflow-wrap: break-word; font-size: 16px; color: rgba(51, 153, 234, 1)"><span style="box-sizing: border-box; outline: 0; margin: 0; padding: 0; font-weight: bold; overflow-wrap: break-word">=<span style="box-sizing: border-box; outline: 0; margin: 0; padding: 0; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; overflow-wrap: break-word; font-size: 16px; color: rgba(243, 59, 69, 1)"><span style="box-sizing: border-box; outline: 0; margin: 0; padding: 0; font-weight: bold; overflow-wrap: break-word">类变量<span style="color: rgba(77, 77, 77, 1); font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; font-size: 16px">(可以没有)<span style="box-sizing: border-box; outline: 0; margin: 0; padding: 0; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; overflow-wrap: break-word; font-size: 16px; color: rgba(51, 153, 234, 1)">+<span style="box-sizing: border-box; outline: 0; margin: 0; padding: 0; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; overflow-wrap: break-word; font-size: 16px; color: rgba(243, 59, 69, 1)"><span style="box-sizing: border-box; outline: 0; margin: 0; padding: 0; font-weight: bold; overflow-wrap: break-word">构造函数<span style="color: rgba(77, 77, 77, 1); font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; font-size: 16px">(必须有,没有的话默认调用)<span style="box-sizing: border-box; outline: 0; margin: 0; padding: 0; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; overflow-wrap: break-word; font-size: 16px; color: rgba(51, 153, 234, 1)">+<span style="box-sizing: border-box; outline: 0; margin: 0; padding: 0; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; overflow-wrap: break-word; font-size: 16px; color: rgba(243, 59, 69, 1)"><span style="box-sizing: border-box; outline: 0; margin: 0; padding: 0; font-weight: bold; overflow-wrap: break-word">成员函数<span style="color: rgba(77, 77, 77, 1); font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; font-size: 16px">(自己定义,可以没有)</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></div>
<div>
<p><strong><span style="font-size: 16px">构造函数中定义了类的成员变量,类的成员变量一定是在构造函数中以self.开头的变量!</span></strong></p>
<p><strong><span style="font-size: 16px">成员函数中可以调用成员变量和类变量!成员函数的形参在类的实例调用该函数时传递,成员函数的局部变量在该成员函数内部定义。调用成员函数和调用普通函数一样,只是成员函数由该函数对应的类调用,即需要写成xxxx.func()而不是直接使用func()!</span></strong><br><br></p>

</div><br><br>
来源:https://www.cnblogs.com/Xy--1/p/12398718.html
頁: [1]
查看完整版本: python类变量与__init__声明变量的区别