python学习【七】 面向对象编程

讲面向对象之前,这里先对前面使用到的编程方式做一个简单的总结:

  • 面向过程:这是最简单也最容易所使用的一种编程方式,只需要根据业务逻辑从上到下将代码垒起来就可以了,代码的执行过程也是从上到下执行。
  • 函数式编程:将实现某个业务逻辑的代码封装到一个函数中,当需要的时候只需要通过函数名调用即可。

面向对象

面向对象编程(Object Oriented Programming),简称OOP,它是一种程序设计思想。面向对象其实就是对类(Class)和对象(object)的使用。

  • 类:用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。就像人们对事物的分类一样。
  • 对象:对象是对类的实例化。

面向对象具有三大特性:封装、多态、继承。

下面用一个简单的实例对面向对象的特性进行介绍:

封装

假设现在要定一个人的类,我们就会想到人具有的相同属性(如:姓名、年龄、体重、身高等)和行为(如:说话、吃饭、走路等)。通过程序我们可以封装成下面的形式:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#通过class关键字创建类Pepole
class Pepole:
info='test'    #构造方法,又称为初始化方法。对类进行实例化时被调用。 def __init__(self,name,age): self.name=name self.age=age def say(self): print 'hi,my name is %s' % self.name def getAge(self): print 'My age is %d'%self.age

上面就是对人的定义,这里需要了解以下几点:

  1. 对于初始化的属性(name、age)必须赋值给self,否则在类中的其他地方将无法使用。
  2. self:形式参数,表示类实例化后的对象。每个方法的第一个形参必须是self。
  3. 对于info这样的变量要想在类中的其他地方使用,则需用通过类名进行调用。如:Pepole.info。

下面对Pepole进行实例化:

p1=Pepole('andy',18) 
p1.say()
p1.getAge()

p1为Pepole实例化后产生的对象。我们可以通过p1来调用类中的方法。输出结果如下:

hi,my name is andy
My age is 18

self的深入讲解

上面已经说了self是类实例化后的对象。可能你会存在一些困惑,这里只需要一个简单的例子就能解开你的困惑。代码如下:

class Pepole:

    def say(self):
        print self

p1=Pepole()
print 'p1:',p1
p1.say()

p2=Pepole()
print 'p2:',p2
p2.say()

执行结果:

p1: <__main__.Pepole object at 0x016F6CF0>
<__main__.Pepole object at 0x016F6CF0>
p2: <__main__.Pepole object at 0x017401B0>
<__main__.Pepole object at 0x017401B0>

通过上面的结果,就可以清楚的看出self等价于类实例化后的对象。

总结如下图所示:

继承

继承是子类自动共享父类中属性和方法的机制,这是类之间的一种关系。和现实生活中儿子可以继承父亲的一些特点一样。

例如:现在有一个人叫andy除了上面定义的共同特征外,他还会唱歌、跳舞。为了方便我们只需要创建一个有唱歌和跳舞的类就可以了,共同的部分可以从Pepole类中继承。因此,这里的Pepole就被称为“基类”,Andy被称为“派生类”。

代码如下:

class Andy(Pepole):

    def dancing(self):
        print 'I will dance'

    def singing(self): 
        print 'I will sing'

p3=Andy('andy',18)
p3.say()
p3.getAge()
p3.dancing()
p3.singing()

结果如下:

hi,my name is andy
My age is 18
I will dance
I will sing

在python中,一个类可以继承多个类。由于这一特性,派生类寻找基类的方式又分为两种:深度优先和广度优先。

  • 当类是经典类时,多继承情况下,会按照深度优先方式查找
  • 当类是新式类时,多继承情况下,会按照广度优先方式查找

经典类与新式类的区分如下:

类成员

类的成员可以分为三大类:字段、方法和属性。

字段

字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同,

  • 普通字段属于对象
  • 静态字段属于

普通字段与静态字段的区别如下图所示:

应用场景: 通过类创建对象时,如果每个对象都具有相同的字段和值,那么就使用静态字段

方法

方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。

  • 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self
  • 类方法(@classmethod):由调用; 至少一个cls参数;执行类方法时,自动将调用该方法的复制给cls
  • 静态方法(@staticmethod):由调用;无默认参数;

属性(@property) 

如果你已经了解Python类中的方法,那么属性就非常简单了,因为Python中的属性其实是普通方法的变种,使用方式与使用字段相似。

对于属性,有以下两个知识点:

1、属性的基本使用

class Foo:

    def func(self):
        pass

    # 定义属性
    @property
    def prop(self):
        pass
# ############### 调用 ###############
foo_obj = Foo()

foo_obj.func()
foo_obj.prop   #调用属性

属性的定义和调用要注意一下几点:

  • 定义时,在普通方法的基础上添加 @property 装饰器;
  • 定义时,属性仅有一个self参数
  • 调用时,无需括号
               方法:foo_obj.func()
               属性:foo_obj.prop

注意:属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象

        属性由方法变种而来,如果Python中没有属性,方法完全可以代替其功能。

2、属性的两种定义方式

装饰器 即:在方法上应用装饰器

静态字段 即:在类中定义值为property对象的静态字段

类成员修饰符

类的所有成员在上一步骤中已经做了详细的介绍,对于每一个类的成员而言都有两种形式:

  • 公有成员,在任何地方都能访问,我们平时使用的就是公有成员
  • 私有成员,只有在类的内部才能方法,私有成员命名时,以两个下划线开头。如:__name

私有成员和公有成员的访问限制不同

静态字段

  • 公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
  • 私有静态字段:仅类内部可以访问;

普通字段

  • 公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问
  • 私有普通字段:仅类内部可以访问;

注:如果想要强制访问私有字段,可以通过 【对象._类名__私有字段明 】访问(如:obj._C__foo),不建议强制访问私有成员。

类相关的内置方法

一、isinstance(obj,cls)

用于检查obj是否是类cls的实例化对象。

在介绍类的内置方法之前,先回忆一下之前我们是怎么查看一个变量是什么类型的。

例如:

>>> n1 = 10
>>> n2 = "str"
>>> type(n1)
<type 'int'>
>>> type(n2)
<type'str'>

因为一切事物皆是对象,因此这里n1和n2也是int和str的对象。上面用type()查看了变量的类型,但是却无法使用这个结果做其他操作(判断n1是否是int类型)。而isinstance()方法就是来解决这个问题的。

需求:有列表l1=['aa',11,22,'bb','cc','dd'],把l1中是str类型的存到str_list=[],把int类型的存入到int_list=[]。

l1=['aa',11,22,'bb','cc','dd']
str_list=[]
int_list=[]
for temp in l1:
if isinstance(temp,str):
str_list.append(temp)
if isinstance(temp,int):
int_list.append(temp)

print str_list
print int_list

结果为:

str_list: ['aa', 'bb', 'cc', 'dd']
int_list: [11, 22]

isinstance(obj,cls)不仅可以检查obj是否是cls的对象,还可以检查obj是否是cls的基类的对象。

例如:

class A:
    pass
class B(A):
    pass
b=B()
print isinstance(b,B)
print isinstance(b,A)

结果为:

True
True

总结:当类B继承类A时,对象b即是类B的实例也是类A的实例

二、issubclass(args1,args2)

用于判断args1是否是args2的派生类。

例如:

class A:
    pass
class B(A):
    pass
print issubclass(B,A)

结果为:

True

 

 

 

posted @ 2015-12-05 02:23  杜瑞龙  阅读(99)  评论(0)    收藏  举报