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>