Python中的类、对象、继承

zehua360 8年前
   <h3><strong>类</strong></h3>    <p>Python中,类的命名使用帕斯卡命名方式,即首字母大写。</p>    <p>Python中定义类的方式如下:</p>    <pre>  <code class="language-python">class 类名([父类名[,父类名[,...]]]):      pass  </code></pre>    <p>省略父类名表示该类直接继承自 object ,类的实例化如下:</p>    <pre>  <code class="language-python">class Person():      def __init__(self):          pass    person=Person()  </code></pre>    <p>__init__() 是类的构造函数,在实例化时调用,它的参数 self 表示类实例。</p>    <h3><strong>类中的字段</strong></h3>    <p>字段的访问级别:</p>    <ul>     <li> <p>Python中以双下划线开头的字段访问级别是private;</p> </li>     <li> <p>Python中以下划线开头的字段访问级别是protected;</p> </li>     <li> <p>Python中未以下划线开头的字段的访问级别是public;</p> </li>    </ul>    <p>上述访问级别更多的 <strong>是一种编程约定</strong> ,即便是以双下划线开头的字段,在类的外部也是可以访问的,但不建议这么做。示例代码如下:</p>    <pre>  <code class="language-python">class Person():      age = 24      _name = 'person'      __family_name = 'securate'        def __init__(self):          print('Person init')  </code></pre>    <p>Person类成员:</p>    <p><img src="https://simg.open-open.com/show/de4aa1da137f084200b7e74ce4d40592.png"></p>    <p>在上图中,我们可以看到类中并没有出现一双下划线开头的字段 <strong>__family_name</strong> ,而多出一个 <strong>_Person__family_name</strong> 。说明类实例不可以直接访问 <strong>__family_name</strong> ,但可以通过 实例名._Person__family_name 的方式来访问。</p>    <p>上述三种类型的变量均可以通过类或类实例进行访问。通过 self 定义的变量只能通过类实例进行访问,如 self.country ,变量 country 只能通过类实例进行访问。</p>    <h3><strong>类中的方法</strong></h3>    <p>Python中方法名均为小写字母,不同单词间以下划线进行分割。</p>    <p><strong>方法的覆盖</strong></p>    <p>Python类中没有方法的重载,对于具有相同名称的方法,后面的定义会覆盖掉前面的定义;子类会覆盖父类中同名的方法。在Person类中定义两个同名方法 say :</p>    <pre>  <code class="language-python">    def say(self, message):          print(message)      def say(self, info):          print('second: '+info)      person=Person()  person.say('invoke')  </code></pre>    <p>程序执行结果:</p>    <p><img src="https://simg.open-open.com/show/9fa7f108292e684d3fb560797961a1f2.png"></p>    <p>从程序运行结果可知,调用的是定义在后面的 say(self, info) 方法。</p>    <p><strong>特殊方法</strong></p>    <p>以双下划线开头和结尾的方法属于特殊方法,如: __init__(self) 、 __call__(self) 等内置方法。在我们自己定义方法时不建议采取这种方式。</p>    <p><strong>方法的访问级别</strong></p>    <ul>     <li>Python中以双下划线开头的方法访问级别是private;</li>     <li>Python中以下划线开头的方法访问级别是protected;</li>     <li>Python中未以下划线开头的方法的访问级别是public;</li>    </ul>    <p>和字段类似,上述访问级别也只 <strong>是一种编程约定</strong> ,即便是以双下划线开头的方法,在类的外部也是可以访问的,但不建议这么做。</p>    <p><strong>实例方法</strong></p>    <p>定义方法时,没有装饰器修饰且 <strong>带有参数</strong> 的(可以不是self),即为实例方法。</p>    <p>类外部通过类实例来调用,类内部通过 self.方法名 来调用。</p>    <pre>  <code class="language-python">def method(self):      pass  </code></pre>    <p><strong>@classmethod</strong></p>    <p>@classmethod是Python中的 装饰器 。</p>    <p>使用 @classmethod 修饰的方法,必须要带参数(默认参数名是cls),该参数表示类自身。可以通过类自身或者类实例调用 @classmethod 修饰的方法。在 @classmethod 修饰的方法中无法访问实例成员,但可以通过cls或者类名访问类中的字段。</p>    <p><strong>@staticmethod</strong></p>    <p>使用 @staticmethod 修饰的方法可以没有参数,可以通过类或者类实例调用。在 @staticmethod 修饰的方法中,无法访问类中的实例成员,可以通过类名访问类中的字段。</p>    <h3><strong>继承</strong></h3>    <p>定义一个Chinese类,继承自Person类:</p>    <pre>  <code class="language-python">class Chinese(Person):      def __init__(self):          pass    chinese=Chinese()  </code></pre>    <p>Chinese中的字段:</p>    <p><img src="https://simg.open-open.com/show/7194a2e6e6f3e6f4f67109819dc8c640.png"></p>    <p>从Chinese类型的实例中,我们可以看到Chinese类继承了除 country 之外的所有字段。</p>    <p>子类还会继承父类中的函数, 若子类没有实现自己的构造函数( __init__(self) ),那么在实例化子类时会调用父类的构造函数。</p>    <h3><strong>子类间的类型转换</strong></h3>    <pre>  <code class="language-python">class Person():      def __init__(self):          pass      def convert(self, class_type):          if issubclass(class_type, Person):              return (Chinese)(self)          elif issubclass(class_type, Janapese):              return (Janapese)(self)    class Chinese(Person):      def __init__(self, convert=None):          print(convert)      def cn_method(self):          print('chinese')      class Japanese(Person):      def __init__(self):          pass  </code></pre>    <p>执行类型转换:</p>    <pre>  <code class="language-python">jap = Japanese()  cn = jap.convert(Chinese)  cn.cn_method()  </code></pre>    <p>类型转换结果如下图:</p>    <p><img src="https://simg.open-open.com/show/c5ee1eab21e9be447c1e89296b4faef9.png"></p>    <p>可以看到,根据Japanese实例得到了Chinese类型实例。这里的转换只是获取了Chinese类型的实例cn,而原有的Japanese类型实例依然存在于内存中。</p>    <p>程序执行结果如下图:</p>    <p><img src="https://simg.open-open.com/show/6bc6d8902ac8c29926371a9993ac5c4c.png"></p>    <p><strong>参考文章</strong>:</p>    <p><a href="/misc/goto?guid=4959723704316009289" rel="nofollow,noindex">飘逸的python - @staticmethod和@classmethod的作用与区别</a></p>    <p><a href="/misc/goto?guid=4959723704407303132" rel="nofollow,noindex">Difference between @staticmethod and @classmethod in Python</a></p>    <p> </p>    <p>来自:http://www.cnblogs.com/Cwj-XFH/p/6027687.html</p>    <p> </p>