python中的类与继承
<h1> Class </h1><p> </p>
<h2>类的定义以及实例的建立</h2>
<p>Python中,类通过 class 关键字定义。</p>
<p>例如最简单的一个类定义可以为:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person(object):
</span><span style="color: rgba(0, 0, 255, 1)">pass</span></pre>
</div>
<p>Python 的编程习惯,类名以大写字母开头,紧接着是(object),表示该类是从哪个类继承下来的。</p>
<p>例如上面的person类,我们可以创建很多实例:</p>
<div class="cnblogs_code">
<pre>zhangsan=<span style="color: rgba(0, 0, 0, 1)">Person()
lisi</span>=Person()</pre>
</div>
<h2> </h2>
<h2>实例的属性及方法</h2>
<p>Python是动态语言,对每一个实例,都可以直接给他们的属性赋值,即使类中并无定义,例如,给xiaoming这个实例加上name、gender和birth属性:</p>
<div class="cnblogs_code">
<pre>xiaoming =<span style="color: rgba(0, 0, 0, 1)"> Person()
xiaoming.name </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Xiao Ming</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
xiaoming.gender </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Male</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
xiaoming.birth </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1990-1-1</span><span style="color: rgba(128, 0, 0, 1)">'</span></pre>
</div>
<h3>__init__()</h3>
<p>如上所说,我们可以自由地给一个实例绑定各种属性,但是,现实世界中,一种类型的实例应该拥</p>
<p>有相同名字的属性。例如,Person类应该在创建的时候就拥有 name、gender 和 birth 属性。</p>
<p>所以在创建类时,我们可以使用__init__()方法,当创建实例时,__init__()方法被自动调用,我们就</p>
<p>能在此为每个实例都统一加上以下属性:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person(object):
</span><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, name, gender, birth):
self.name </span>=<span style="color: rgba(0, 0, 0, 1)"> name
self.gender </span>=<span style="color: rgba(0, 0, 0, 1)"> gender
self.birth </span>= birth</pre>
</div>
<p>__init__() 方法的第一个参数必须是 self(也可以用别的名字,但建议使用习惯用法),后续参数则</p>
<p>可以自由指定,和定义函数没有任何区别。</p>
<p>同时,创建实例时,就必须要提供除 self 以外的参数:</p>
<div class="cnblogs_code">
<pre>xiaoming = Person(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Xiao Ming</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Male</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1991-1-1</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
xiaohong </span>= Person(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Xiao Hong</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Female</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1992-2-2</span><span style="color: rgba(128, 0, 0, 1)">'</span>)</pre>
</div>
<h3>属性的访问限制(私有属性)</h3>
<p>我们可以给一个实例绑定很多属性,如果有些属性不希望被外部访问到怎么办?</p>
<p>Python对属性权限的控制是通过属性名来实现的,如果一个属性由双下划线开头(__),该属性就无</p>
<p>法被外部访问。例如:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person(object):
</span><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, name):
self.name </span>=<span style="color: rgba(0, 0, 0, 1)"> name
self._title </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Mr</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
self.</span><span style="color: rgba(128, 0, 128, 1)">__job</span> = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Student</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
p1</span>=Person(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">zhangsan</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(p1.name,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">\n</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(p1._title,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">\n</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">:
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(p1.<span style="color: rgba(128, 0, 128, 1)">__job</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">except</span><span style="color: rgba(0, 0, 0, 1)">:
</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)">Error</span><span style="color: rgba(128, 0, 0, 1)">"</span>)</pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">zhangsan
Mr
Error</span></pre>
</div>
<p>可以看出只有__job无法被访问,但是也有可以访问的办法,<code>__attribute</code> 变为 <code>_ClassName__attribute</code>,可以这样访问:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MyClass:
</span><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.</span><span style="color: rgba(128, 0, 128, 1)">__hidden</span> = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">I'm hidden</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
obj </span>=<span style="color: rgba(0, 0, 0, 1)"> MyClass()
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(obj._MyClass__hidden)<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 输出: I'm hidden</span></pre>
</div>
<h3>实例的方法</h3>
<p>虽然私有属性无法从外部访问,但是,从类的内部是可以访问的。除了可以定义实例的属性外,还可以定义实例的方法。</p>
<p>例如我们可以定义一个__name私有属性,同时创建一个get_name方法去访问__name:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person(object):
</span><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, name):
self.</span><span style="color: rgba(128, 0, 128, 1)">__name</span> =<span style="color: rgba(0, 0, 0, 1)"> name
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> get_name(self):
</span><span style="color: rgba(0, 0, 255, 1)">return</span> self.<span style="color: rgba(128, 0, 128, 1)">__name</span><span style="color: rgba(0, 0, 0, 1)">
p2</span>=Person(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Bob</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(p2.get_name())</pre>
</div>
<p>结果</p>
<div class="cnblogs_code">
<pre>Bob</pre>
</div>
<p>get_name(self) 就是一个实例方法,它的第一个参数是self。__init__(self, name)其实也可看做是一个特殊的实例方法。</p>
<p>在实例方法内部,可以访问所有实例属性,这样,如果外部需要访问私有属性,可以通过方法调用获得,这种数据封装的形式除了能保护内部数据一致性外,还可以简化外部调用的难度。</p>
<h3 id="J_CodeLang" class="code-head" data-lang="PYTHON" data-regular="1">python中实例方法也是属性</h3>
<p>我们在 class 中定义的实例方法其实也是属性,它实际上是一个函数对象,因为方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用 types.MethodType() 把一个函数变为一个方法:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> types
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> Pn_get_name(self):
</span><span style="color: rgba(0, 0, 255, 1)">return</span> str(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">This person's name is :</span><span style="color: rgba(128, 0, 0, 1)">"</span>+<span style="color: rgba(0, 0, 0, 1)">self.name)
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person(object):
</span><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, name):
self.name </span>=<span style="color: rgba(0, 0, 0, 1)"> name
p1</span>=Person(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Alice</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
p2</span>=Person(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Bob</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
<span style="color: rgba(255, 0, 0, 1)">p1.get_name</span></span><span style="color: rgba(255, 0, 0, 1)">=types.MethodType(Pn_get_name,p1)
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(p1.get_name(),<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">\n</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(p2.get_name())</pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre>This person<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">s name is :Alice </span>
<span style="color: rgba(0, 0, 0, 1)">
Traceback (most recent call last):
File </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">D:/pythonwork/practise/test.py</span><span style="color: rgba(128, 0, 0, 1)">"</span>, line 15, <span style="color: rgba(0, 0, 255, 1)">in</span> <module>
<span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(p2.get_name())
AttributeError: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Person</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)">get_name</span><span style="color: rgba(128, 0, 0, 1)">'</span></pre>
</div>
<p>给一个实例动态添加方法并不常见,直接在class中定义要更直观</p>
<h2> </h2>
<h2>类的属性及方法</h2>
<p>类是模板,而实例则是根据类创建的对象。绑定在一个实例上的属性不会影响其他实例,但是,类本身也是一个对象,如果在类上绑定一个属性,则所有实例都可以访问类的属性,并且,所有实例访问的类属性都是同一个,也就是说,实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。</p>
<p>定义类属性可以直接在 class 中定义:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person(object):
address </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Earth</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<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, name):
self.name </span>= name</pre>
</div>
<p>因为类属性是直接绑定在类上的,所以,访问类属性可以直接用类名访问,也可以使用实例访问,例如:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person(object):
address </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Earth</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<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, name):
self.name </span>=<span style="color: rgba(0, 0, 0, 1)"> name
p1</span>=Person(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">zhangsan</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(Person.address)
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(p1.address)</pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">Earth
Earth</span></pre>
</div>
<p>由于Python是动态语言,类属性也是可以动态添加和修改的:</p>
<div class="cnblogs_code">
<pre>Person.address = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">China</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(Person.address)
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(p1.address)</pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">China
China</span></pre>
</div>
<p>因为类属性只有一份,所以,当Person类的address改变时,所有实例访问到的类属性都改变了。</p>
<p><span style="color: rgba(255, 0, 0, 1)">注意</span>:如果在实例变量上修改类属性,则实际上是给实例绑定了一个与类属性同名的实例属性,而</p>
<p>访问时会优先访问实例属性:</p>
<div class="cnblogs_code">
<pre>p1.address=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">China</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(Person.address)
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(p1.address)</pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">Earth
China</span></pre>
</div>
<h3>类的方法</h3>
<p>和属性类似,方法也分实例方法和类方法。</p>
<p>在class中定义的全部是实例方法,实例方法第一个参数 self 是实例本身。</p>
<p>要在class中定义类方法,我们通过标记一个 @classmethod,该方法将绑定到 Person 类上,而非</p>
<p>类的实例。类方法的第一个参数将传入类本身,通常将参数名命名为 cls,下面例子中</p>
<p>的 cls.count 实际上相当于 Person.count。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person(object):
count </span>=<span style="color: rgba(0, 0, 0, 1)"> 0
@classmethod
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> how_many(cls):
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> cls.count
</span><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, name):
self.name </span>=<span style="color: rgba(0, 0, 0, 1)"> name
Person.count </span>= Person.count + 1
<span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)"> (Person.how_many())
p1 </span>= Person(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Bob</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">print</span> (Person.how_many())</pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">0
</span>1</pre>
</div>
<h2> </h2>
<h2>类的继承</h2>
<p>如果已经定义了Person类,需要定义新的Student和Teacher类时,可以直接从Person类继承,定义Student类时,只需要把额外的属性加上,例如score:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person(object):
</span><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, name, gender):
self.name </span>=<span style="color: rgba(0, 0, 0, 1)"> name
self.gender </span>=<span style="color: rgba(0, 0, 0, 1)"> gender
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Student(Person):
</span><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, name, gender, score):
<span style="color: rgba(255, 0, 0, 1)">super(Student, self).</span></span><span style="color: rgba(255, 0, 0, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)">(name, gender)</span>
self.score </span>= score</pre>
</div>
<p><span style="color: rgba(255, 0, 0, 1)">注意:</span></p>
<p>一定要用 super(Student, self).__init__(name, gender) 去初始化父类,否则,继承自 Person 的 Student 将没有 name 和 gender。</p>
<p>函数super(Student, self)将返回当前类继承的父类,即 Person ,然后调用__init__()方法,注意self参数已在super()中传入,在__init__()中将隐式传递,不需要写出(也不能写),另外下方会写出其他的写法。</p>
<h3>初始化父类的多种写法</h3>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> AAA(object):
</span><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, name):
self.name </span>=<span style="color: rgba(0, 0, 0, 1)"> name
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> get_name(self):
</span><span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(self.name)
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> self.name
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> BBB(AAA):
</span><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, age):
self.age </span>=<span style="color: rgba(0, 0, 0, 1)"> age
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 方式1</span>
super().<span style="color: rgba(128, 0, 128, 1)">__init__</span>(name=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">BBB</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 方式2</span>
super(BBB, self).<span style="color: rgba(128, 0, 128, 1)">__init__</span>(name=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">BBBC</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 方式3</span>
AAA.<span style="color: rgba(128, 0, 128, 1)">__init__</span>(self, name=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">BBBD</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> get_age(self):
</span><span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(self.age)
</span><span style="color: rgba(0, 0, 255, 1)">return</span> self.age</pre>
</div>
<p>其中方法3适用于多继承写法,python中如果两个父类的非继承自同一个“爷类” super()初始化似乎只会初始继承的第一个父类,因此这种情况,需要用第三种方式编写(<span style="color: rgba(255, 0, 0, 1)">也或许是我理解有问题,编码过程中具体问题具体分析</span>)</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> AAA():
</span><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, name):
self.name </span>=<span style="color: rgba(0, 0, 0, 1)"> name
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> get_name(self):
</span><span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(self.name)
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> self.name
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> BBB():
</span><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, name2):
self.name2 </span>=<span style="color: rgba(0, 0, 0, 1)"> name2
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> get_name2(self):
</span><span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(self.name2)
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> self.name2
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> CCC(AAA, BBB):
</span><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, age):
self.age </span>=<span style="color: rgba(0, 0, 0, 1)"> age
AAA.</span><span style="color: rgba(128, 0, 128, 1)">__init__</span>(self, name=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">CCC</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
BBB.</span><span style="color: rgba(128, 0, 128, 1)">__init__</span>(self, name2=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">CCC2</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> get_age(self):
</span><span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(self.age)
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> self.age
TEST </span>= CCC(2<span style="color: rgba(0, 0, 0, 1)">)
TEST.get_name()
TEST.get_name2()</span></pre>
</div>
<h3>python中的多态</h3>
<p>类具有继承关系,并且子类类型可以向上转型看做父类类型,如果我们从 Person 派生出 Student和</p>
<p>Teacher ,并都写了一个 同名的whoAmI() 方法,当我们调用实例的whoAmI() 方法时,总是先查找</p>
<p>它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止。</p>
<p>例如:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person(object):
</span><span style="color: rgba(0, 0, 255, 1)">pass</span>
<span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> Pstr(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)">This is Person class method</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Student(Person):
</span><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, name):
self.name </span>=<span style="color: rgba(0, 0, 0, 1)"> name
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> Pstr(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)">This is Student class method</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Teacher(Person):
</span><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, name):
self.name </span>=<span style="color: rgba(0, 0, 0, 1)"> name
p1</span>=Student(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Alice</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
p2</span>=Teacher(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Tom</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
p1.Pstr()
p2.Pstr()</span></pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre>This <span style="color: rgba(0, 0, 255, 1)">is</span> Student <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> method
This </span><span style="color: rgba(0, 0, 255, 1)">is</span> Person <span style="color: rgba(0, 0, 255, 1)">class</span> method</pre>
</div>
<h3 id="J_CodeLang" class="code-head" data-lang="PYTHON" data-regular="1">python中的多重继承</h3>
<p>除了从一个父类继承外,Python允许从多个父类继承,称为多重继承。</p>
<p>例如:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A(object):
</span><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, a):
</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)">init A...</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
self.a </span>=<span style="color: rgba(0, 0, 0, 1)"> a
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> B(A):
</span><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, a):
super(B, self).</span><span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">(a)
</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)">init B...</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> C(A):
</span><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, a):
super(C, self).</span><span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">(a)
</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)">init C...</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> D(B, C):
</span><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, a):
super(D, self).</span><span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">(a)
</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)">init D...</span><span style="color: rgba(128, 0, 0, 1)">'</span></pre>
</div>
<p><img src="https://img2018.cnblogs.com/blog/1699970/201906/1699970-20190603174727352-1435856199.jpg" alt="" width="232" height="169"></p>
<p>像这样,D 同时继承自 B 和 C,也就是 D 拥有了 A、B、C 的全部功能。多重继承通过 super()调用</p>
<p>__init__()方法时,A 虽然被继承了两次,但__init__()只调用一次:</p>
<p> 运行测试代码:</p>
<div class="cnblogs_code">
<pre>d=D(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">d</span><span style="color: rgba(128, 0, 0, 1)">'</span>)</pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">init A...
init C...
init B...
init D...</span></pre>
</div>
<h2> </h2>
<h2>类的定制</h2>
<p>我们可以使用一些特殊的方法来定制我们自己定义的类</p>
<h3 id="J_CodeLang" class="code-head" data-lang="PYTHON" data-regular="1">python中 __slots__</h3>
<p>由于Python是动态语言,任何实例在运行期都可以动态地添加属性。</p>
<p>如果要限制添加的属性,例如,Student类只允许添加 name、gender和score 这3个属性,就可以利用Python的一个特殊的__slots__来实现。</p>
<p>例如:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Student(object):
</span><span style="color: rgba(128, 0, 128, 1)">__slots__</span> = (<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">gender</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">score</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><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, name, gender, score):
self.name </span>=<span style="color: rgba(0, 0, 0, 1)"> name
self.gender </span>=<span style="color: rgba(0, 0, 0, 1)"> gender
self.score </span>= score</pre>
</div>
<p>进行操作:</p>
<div class="cnblogs_code">
<pre>>>> s = Student(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Bob</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">male</span><span style="color: rgba(128, 0, 0, 1)">'</span>, 59<span style="color: rgba(0, 0, 0, 1)">)
</span>>>> s.name = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Tim</span><span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> OK</span>
>>> s.score = 99 <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> OK</span>
>>> s.grade = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">A</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
Traceback (most recent call last):
...
AttributeError: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Student</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)">grade</span><span style="color: rgba(128, 0, 0, 1)">'</span></pre>
</div>
<p>__slots__的目的是限制当前类所能拥有的属性,如果不需要添加任意动态的属性,使用__slots__也能节省内存。</p>
<h3 id="J_CodeLang" class="code-head" data-lang="PYTHON" data-regular="1">python中 __str__和__repr__对于print的改变</h3>
<p>例如原本对于类中的实例直接打印:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Student(object):
</span><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, name):
self.name </span>=<span style="color: rgba(0, 0, 0, 1)"> name
p1</span>=Student(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Alice</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(p1)</pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre><<span style="color: rgba(128, 0, 128, 1)">__main__</span>.Student object at 0x000002672671EF98></pre>
</div>
<p>但是我们想让print实例的时候直接打印类名与实例名我们就可以使用__str__:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Student(object):
</span><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, name):
self.name </span>=<span style="color: rgba(0, 0, 0, 1)"> name
</span><span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__str__</span><span style="color: rgba(0, 0, 0, 1)">(self):
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Student: %s</span><span style="color: rgba(128, 0, 0, 1)">'</span> %<span style="color: rgba(0, 0, 0, 1)"> self.name
p1</span>=Student(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Alice</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(p1)</pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre>Student: Alice</pre>
</div>
<p>但是我们在命令交互行中直接输入变量p1却不是这样:</p>
<div class="cnblogs_code">
<pre>>>><span style="color: rgba(0, 0, 0, 1)">p1
</span><Student object at 0x0000023C8F331A58></pre>
</div>
<p>这是因为 Python 定义了__str__()和__repr__()两种方法,__str__()用于显示给用户,而__repr__()</p>
<p>用于显示给开发人员。</p>
<p>同理我们可以定义类的__repr__()例如直接:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 0, 128, 1)">__repr__</span> = <span style="color: rgba(128, 0, 128, 1)">__str__</span></pre>
</div>
<p>这样直接在命令交互中直接输入变量p1也是同样效果了</p>
<div class="cnblogs_code">
<pre>>>><span style="color: rgba(0, 0, 0, 1)">p1
Student: Alice</span></pre>
</div>
<h3 id="J_CodeLang" class="code-head" data-lang="PYTHON" data-regular="1">python3中__cmp__方法已经不再使用</h3>
<h3 class="code-head" data-lang="PYTHON" data-regular="1">在python2中该方法可实现对于sorted()函数改变,不再赘述</h3>
<div class="cnblogs_code"> </div>
<h3 id="J_CodeLang" class="code-head" data-lang="PYTHON" data-regular="1">python中 __len__对于len()的改变</h3>
<p>如果一个类表现得像一个list,要获取有多少个元素,就得用 len() 函数。</p>
<p>要让 len() 函数工作正常,类必须提供一个特殊方法__len__(),它返回元素的个数。</p>
<p>例如,我们写一个 Students 类,把名字传进去:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Students(object):
</span><span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__init__</span>(self, *<span style="color: rgba(0, 0, 0, 1)">args):
self.names </span>=<span style="color: rgba(0, 0, 0, 1)"> args
</span><span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__len__</span><span style="color: rgba(0, 0, 0, 1)">(self):
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> len(self.names)
ss </span>= Students(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Bob</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Alice</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Tim</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">print</span> (len(ss))</pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre>3 </pre>
</div>
<h3 id="J_CodeLang" class="code-head" data-lang="PYTHON" data-regular="1">类的实例的数学运算</h3>
<p>同以上特殊方法一样,我们可以利用</p>
<p>__add__对符号 + 进行改变</p>
<p>__sub__对符号 -进行改变</p>
<p>__mul__对符号 * 进行改变</p>
<p>__div__对符号 / 进行改变</p>
<p>例如:</p>
<p>我们创建一个分数的类:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Rational(object):
</span><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, p, q):
self.p </span>=<span style="color: rgba(0, 0, 0, 1)"> p
self.q </span>= q</pre>
</div>
<p>我们想实现符号+直接运用在我们创建的实例上我们需要这样写代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Rational(object):
</span><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, p, q):
self.p </span>=<span style="color: rgba(0, 0, 0, 1)"> p
self.q </span>=<span style="color: rgba(0, 0, 0, 1)"> q
</span><span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__add__</span><span style="color: rgba(0, 0, 0, 1)">(self, r):
</span><span style="color: rgba(0, 0, 255, 1)">return</span> Rational(self.p * r.q + self.q * r.p, self.q *<span style="color: rgba(0, 0, 0, 1)"> r.q)
</span><span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__str__</span><span style="color: rgba(0, 0, 0, 1)">(self):
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">%s/%s</span><span style="color: rgba(128, 0, 0, 1)">'</span> %<span style="color: rgba(0, 0, 0, 1)"> (self.p, self.q)
</span><span style="color: rgba(128, 0, 128, 1)">__repr__</span> = <span style="color: rgba(128, 0, 128, 1)">__str__</span><span style="color: rgba(0, 0, 0, 1)">
r1 </span>= Rational(1, 3<span style="color: rgba(0, 0, 0, 1)">)
r2 </span>= Rational(1, 2<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(r1+r2)</pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre>5/6</pre>
</div>
<h3 class="code-head" data-lang="PYTHON" data-regular="1">类的实例的类型转换</h3>
<p>如上,Rational类实现了有理数(分数)类的数学运算,但是,如果要把结果转为 int 或 float 怎么办?</p>
<p>我们对于整数和浮点数可以直接使用int()和float()函数直接转换,但是我们肯定无法直接使用在我们所创建的类的实例上,因此我们需要使用__int__()和__float__()</p>
<p>例如__int__:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Rational(object):
</span><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, p, q):
self.p </span>=<span style="color: rgba(0, 0, 0, 1)"> p
self.q </span>=<span style="color: rgba(0, 0, 0, 1)"> q
</span><span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__int__</span><span style="color: rgba(0, 0, 0, 1)">(self):
</span><span style="color: rgba(0, 0, 255, 1)">return</span> self.p//self.q #python3中//是整数结果</pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre>>>> <span style="color: rgba(0, 0, 255, 1)">print</span> int(Rational(7, 2<span style="color: rgba(0, 0, 0, 1)">))
</span>3</pre>
</div>
<h3 id="J_CodeLang" class="code-head" data-lang="PYTHON" data-regular="1">python中 @property</h3>
<p>对于Student类:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Student(object):
</span><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, name, score):
self.name </span>=<span style="color: rgba(0, 0, 0, 1)"> name
self.score </span>= score</pre>
</div>
<p>当我们想要修改一个 Student 的 scroe 属性时,可以这么写:</p>
<div class="cnblogs_code">
<pre>s = Student(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Bob</span><span style="color: rgba(128, 0, 0, 1)">'</span>, 59<span style="color: rgba(0, 0, 0, 1)">)
s.score </span>= 1000</pre>
</div>
<p>显然,直接给属性赋值无法检查分数的有效性。</p>
<p>如果利用两个方法:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Student(object):
</span><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, name, score):
self.name </span>=<span style="color: rgba(0, 0, 0, 1)"> name
self.</span><span style="color: rgba(128, 0, 128, 1)">__score</span> =<span style="color: rgba(0, 0, 0, 1)"> score
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> get_score(self):
</span><span style="color: rgba(0, 0, 255, 1)">return</span> self.<span style="color: rgba(128, 0, 128, 1)">__score</span>
<span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> set_score(self, score):
</span><span style="color: rgba(0, 0, 255, 1)">if</span> score < 0 <span style="color: rgba(0, 0, 255, 1)">or</span> score > 100<span style="color: rgba(0, 0, 0, 1)">:
</span><span style="color: rgba(0, 0, 255, 1)">raise</span> ValueError(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">invalid score</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
self.</span><span style="color: rgba(128, 0, 128, 1)">__score</span> = score</pre>
</div>
<p>这样一来,s.set_score(1000) 就会报错。</p>
<p>这种使用 get/set 方法来封装对一个属性的访问在许多面向对象编程的语言中都很常见。<span style="font-family: "Microsoft YaHei"">但是</span>写 s.get_score() 和 s.set_score() 没有直接写 s.score 来得直接。</p>
<p>而在Python中,python支持高阶函数,在函数式编程中我们介绍了装饰器函数,可以用装饰器函数@property。</p>
<p>把 get/set 方法“装饰”成属性调用:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Student(object):
</span><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, name, score):
self.name </span>=<span style="color: rgba(0, 0, 0, 1)"> name
self.</span><span style="color: rgba(128, 0, 128, 1)">__score</span> =<span style="color: rgba(0, 0, 0, 1)"> score
@property
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> score(self):
</span><span style="color: rgba(0, 0, 255, 1)">return</span> self.<span style="color: rgba(128, 0, 128, 1)">__score</span><span style="color: rgba(0, 0, 0, 1)">
@score.setter
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> score(self, score):
</span><span style="color: rgba(0, 0, 255, 1)">if</span> score < 0 <span style="color: rgba(0, 0, 255, 1)">or</span> score > 100<span style="color: rgba(0, 0, 0, 1)">:
</span><span style="color: rgba(0, 0, 255, 1)">raise</span> ValueError(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">invalid score</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
self.</span><span style="color: rgba(128, 0, 128, 1)">__score</span> = score</pre>
</div>
<p>现在再设置score会怎么样呢:</p>
<div class="cnblogs_code">
<pre>s = Student(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Bob</span><span style="color: rgba(128, 0, 0, 1)">'</span>, 59<span style="color: rgba(0, 0, 0, 1)">)
s.score </span>= 60
<span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)"> (s.score)
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">:
s.score </span>= 1000
<span style="color: rgba(0, 0, 255, 1)">except</span><span style="color: rgba(0, 0, 0, 1)">:
</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)">Error</span><span style="color: rgba(128, 0, 0, 1)">"</span>)</pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre>60<span style="color: rgba(0, 0, 0, 1)">
Error</span></pre>
</div>
<p>注意: <span style="color: rgba(255, 0, 0, 1)">第一个score(self)是get方法,用@property装饰,第二个score(self, score)是set方法,用@score.setter装饰,@score.setter是前一个@property装饰后的副产品。说明对 score 赋值实际调用的是 set方</span><span style="color: rgba(255, 0, 0, 1)">法。</span></p>
<p><span style="color: rgba(255, 0, 0, 1)">如果没有定义set方法即<span style="color: rgba(136, 136, 136, 1)">@score.setter</span>,就不能对“属性”赋值,这时,就可以创建一个只读“属性”。</span></p>
<h3 id="J_CodeLang" class="code-head" data-lang="PYTHON" data-regular="1">python中 __call__</h3>
<p>在Python中,函数其实是一个对象:</p>
<div class="cnblogs_code">
<pre>>>> f =<span style="color: rgba(0, 0, 0, 1)"> abs
</span>>>> f.<span style="color: rgba(128, 0, 128, 1)">__name__</span>
<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">abs</span><span style="color: rgba(128, 0, 0, 1)">'</span>
>>> f(-123<span style="color: rgba(0, 0, 0, 1)">)
</span>123</pre>
</div>
<p>由于 f 可以被调用,所以,f 被称为可调用对象。而所有的函数都是可调用对象。</p>
<p>一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法__call__()。</p>
<p>我们把 Person 类变成一个可调用对象:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person(object):
</span><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, name, gender):
self.name </span>=<span style="color: rgba(0, 0, 0, 1)"> name
self.gender </span>=<span style="color: rgba(0, 0, 0, 1)"> gender
</span><span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__call__</span><span style="color: rgba(0, 0, 0, 1)">(self, friend):
</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)">My name is %s...</span><span style="color: rgba(128, 0, 0, 1)">'</span> %<span style="color: rgba(0, 0, 0, 1)"> self.name)
</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)">My friend is %s...</span><span style="color: rgba(128, 0, 0, 1)">'</span> % friend)</pre>
</div>
<p>现在可以对 Person 实例直接调用:</p>
<div class="cnblogs_code">
<pre>>>> p = Person(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Bob</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">male</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span>>>> p(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Tim</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
My name </span><span style="color: rgba(0, 0, 255, 1)">is</span><span style="color: rgba(0, 0, 0, 1)"> Bob...
My friend </span><span style="color: rgba(0, 0, 255, 1)">is</span> Tim...</pre>
</div>
<p>单看 p('Tim') 你无法确定 p 是一个函数还是一个类实例,所以,在Python中,函数也是对象,对象和函数的区别并不显著。</p>
<p> </p>
</div>
<div id="MySignature" role="contentinfo">
<strong>喜欢的觉得有用的就点个赞吧,点波关注不迷路呦</strong><br><br>
来源:https://www.cnblogs.com/CYHISTW/p/10966448.html
頁:
[1]