目录
(一)了解面向对象
面向对象编程(Object Oriented Programming(简称OOP))是相对于面向过程编程来说的,所以要先理解一下面向过程编程。
面向过程
面向过程是一种以“过程”为中心的编程思想,分析出解决问题所需的步骤,然后用函数把这些步骤一步步的实现,使用的时候一个个依次调用就好。
举个例子,我前面调试过的关于模拟自动取款机的代码,就是按照面向过程的思路来实现的功能。
我也调试过一个应用面向对象思维来实现模拟自动取款机的项目。除此之外,还有游戏编程。。。。参见专栏。。。
优点:性能比面向对象好,因为类调用时需要实例化,开销比较大,比较消耗资源。
缺点:不易维护、不易复用、不易扩展。
面向对象是一种以“对象”为中心的编程思想,把问题看成一个个对象,通过对象的属性和行为,将问题解决的。面向过程强调的是模块化,而面向对象强调的是把事物对象化。
面向对象的三大特性:
- 封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用性和安全性。
- 继承:复合自然界的分类规律,提高代码复用性。继承是多态的前提。
- 多态:父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。子类可以通过自定义来修改特性。多态提高了程序的拓展性。
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护 .
缺点:性能比面向过程差。
对于python,使用类来实现面向对象,下面我们简单了解一下python中的类。
(二)python中的类
python中的类可用于保存数据和代码。python也是通过类来实现面向对象的。
1)定义类
Python中的类(class)实际上就是数据类型。Python的所有内置数据类型都是类,Python提供了强大的工具,用于对类的所有行为进行控制。类可用class语句进行定义:
class MyClass:
body
body部分是由一系列Python语句组成,通常包含变量赋值和函数定义语句。不过赋值和函数定义语句都不是必需的,body可以只包含一条pass语句。
为了能够让类标识符足够醒目,按惯例每个单词首字母应该大写。类定义完之后,只要将类名称作为函数进行调用,就可以创建该类的对象,即类的实例。
新式类与经典类
对于Python2版本的,默认是经典类,继承object的为新式类。
对于Python3版本的,统一为新式类,不用继承object。
其中经典类继承为深度优先,新式类为广度优先。
2)初始化与实例化
通过在类的定义中包含初始化方法__init__,可以实现对实例的字段进行自动初始化,这个类所用到的属性一般在__init__()方法中创建并且初始化,一般不建议在__init__()方法之外中创建和初始化实例属性,因为可能没有初始化就被调用了,这样程序就会报错。
一般不推荐类外定义和修改,修改可以单独定义方法。
类的初始化,是完成程序执行前的准备工作。在这个阶段,静态的(变量,方法,代码块)会被执行。同时在会开辟一块存储空间用来存放静态的数据。初始化只在类加载的时候执行一次。
类的实例化,是指创建一个对象的过程。这个过程中会在堆中开辟内存,将一些非静态的方法,变量存放在里面。在程序执行的过程中,可以创建多个对象,既多次实例化。每次实例化都会开辟一块新的内存。
类就相当于一个模型(模子/印章),实例化类就是建立真实实物(产品/印章印出来的图案)。
每次创建类的新实例时,__init__函数都会运行,新建实例本身将作为函数的第一个参数self代入。Python的类只能包含一个__init__方法。下面的实例将会创建默认半径为1的圆:
>>> class Circle:
def __init__(self):
self.radius = 1
>>> my_circle = Circle()
>>> print(2 * 3.14 * my_circle.radius)
6.28
>>> my_circle.radius = 5
>>> print(2 * 3.14 * my_circle.radius)
31.400000000000002
>>> class Circle:
def __init__(self):
self.radius = 1
print("自动调用吗?")
>>> my = Circle()
自动调用吗?
按照惯例,__init__方法的第一个参数名始终是self,self指的是类实例化之后得类得本身。当__init__运行时,self会被置为新建的Circle实例。接下来就会用到类的定义。首先把Circle类赋值给my_circle来创建一个Circle实例对象。下一行代码是基于radius属性已经被初始化这一事实。radius字段的值可以被覆盖,这就导致了最后一行打印出的结果与上一条print语句的不一样了。
第二个Circle类演示了__init__()方法自动实例化。
3)类的属性
我们把实例化之后的类看作是一个对象,那么对象的属性就是对象具有的特点。
类属性与实例属性
我们有一个房子对象,房子的长宽高是固定的,那么我们就说长宽高是房子对象的类属性;在我们编写房子类的时候,我们采用赋值语句,所以类属性又叫类变量。
类变量(class variable),是与类关联的变量,而不是与类的实例关联,并且可供类的所有实例访问。
类变量在类定义后就存在,而且不需要实例化。类变量使得类的不同实例中拥有相同的变量。
类变量是在类体中,函数之外定义的。
如果我们让房子的主人自己定义房子有几个窗户,几扇门,那么房子主人定义好的窗户和门也是房子对象的实例属性;在这里窗户和门的数量都是一个变量,所以也可以叫做实例变量。
实例变量是在类体中的函数内定义的。
class House:
#定义类变量
lengh = 13
width = 7
high = 3
def __init__(self,windows,door):
self.windows = windows
self.door = door
house = House(6,2)
print("类House的类属性lengh、width、high分别为:{},{},{}".format(house.lengh,house.width,house.high))
print("类House的实例变量windows、door分别为:{}{}".format(house.windows,house.door))
输出如下:
类House的类属性lengh、width、high分别为:13,7,3
类House的实例变量windows、door分别为:62
类变量通过类定义代码中的赋值语句创建的,而不是在__init__函数中创建的。实例变量写在__init__中,系统会自动实例化,在其他函数中创建的实例变量,需要我们进行实例化之后才可以访问。类变量创建之后,就可以被类的所有实例看到。可以用类变量创建pi值,供Circle类的所有实例访问:
class Circle:
pi = 3.14159
def __init__(self,rad):
self.radius = rad
def area(self):
return self.radius * self.radius * Circle.pi
def manyround(self,number):
return self.radius * 2 * Circle.pi *number
c = Circle(5)
print(c.pi)
c.pi = 4
print(c.pi)
print(c.area())
c.pi = 3.14159
#实例化manyround()之后,使用实例变量number:
print(c.manyround(2))
输出:
类House的类属性lengh、width、high分别为:13,7,3
类House的实例变量windows、door分别为:62
3.14159
4
78.53975
62.8318
__class__属性会返回实例所属的类,例如:
>>> Circle
<class '__main__.Circle'>
>>> c.__class__
<class '__main__.Circle'>
名为Circle的类在系统内部是用一个抽象数据结构表