面向对象
面向过程面向对象
面向过程
与面向对象对应的就是面向过程编程(Procedure Oriented Programming),简称OPP
。
就是分析解决问题所需的步骤,然后用函数将这些步骤一步一步实现,使用的时候一个一个一次调用。
面向过程最重要的是模块化
的思想方法。
面向对象
面向对象编程(Object Oriented Programming),简称OOP
。
面向对象将对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
面向对象的设计思想是抽象出Class(类)
,根据Class创建实例(Instance)。
其三个特点是封装
、继承
和多态
。
类和实例
定义:
1、类(class)是用来描述具有相同属性和方法的对象的集合。它定义了集合中每个对象共有的属性和方法。
2、实例(Instance)是根据类创建出来的一个个具体的对象,每个对象都有相同的方法,但各自的数据可能不同。
类的内容
类的内容可以写类的全局变量,方法等
例子:
class en(object): name = "hewj" sex = "man" def hell0(self): print("hello world") ren = Ren() print(type(ren)) print(ren.name) print(ren.sex) ren.hell0() ren.name = "美女" #自由的给实例变量绑定属性。 print(ren.name)
输出结果:
<class '__main__.Ren'>
hewj
man
hello world
美女
py代码解释:
- `class`后面紧接着类名,类名通常是大写开头的单词
- object默认是所有类的父类,不写默认继承object
- ren = Ren(),就是把类Ren 实例化
- 以上打印a的类型就是一个Ren的类
- 调用类的方法和变量,直接实例化类的后面直接用“.”调用就可以。
- 如果想给实例a添加变量或者赋值,可以直接用“.”加变量赋值就可以了。
类的构造器
__init__ 构造函数,在生成对象时调用。
由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__方法,在创建实例的时候,就把no, name,score等属性绑上去:
例子:
class Student(object):
def __init__(self, no, name, score):
self.no = no
self.name = name
self.score = score
def hello(self):
print("number {0}".format(self.no))
print("hello {0}".format(self.name))
print("你的成绩 {0}".format(self.score))
student = Student(1101, "hewj", 100)
student.hello() #调用hello 函数
print("###########")
print(student.no)
print(student.name)
print(student.score)
输出结果:
py代码解析:
__init__
方法第一个参数永远是self
,表示创建的实例本身。
在创建实例的时候必须传入与该方法匹配的参数,self
不需要传。
类的私有变量
在python中,如果实例的变量名以__
(双下划线)开头,就变成了一个私有变量,只有内部可以访问,外部不能访问。
同样是上面的类,传入相同的参数
student = Student(1101, "hewj", 100)
print(student.score)
student.score = 60
print(student.score)
输出:
可见通过外部代码可以自由的修改一个实例的属性。通过私有变量可以限制外部代码的访问。 私有变量的访问和修改可以通过在 类中增加方法来实现 ,通过私有变量,可以提高代码的健壮性。
例如:获取分数和修改分数
class Student(object):
def __init__(self, no, name, score):
self.__no = no
self.__name = name
self.__score = score
def get_score(self):
return self.__score
def set_score(self, score):
self.__score = score
student = Student(1101, "hewj", 100)
print(student.get_score())
student.set_score(1200)
print(student.get_score())
输出结果:
- 变量名类似
__xx__
这样双下划线开头和结尾的是特殊变量,可以直接访问,不是私有变量。 - 变量名类似
_xx
这样一个下划线开头的外部可以访问,但是按照约定俗成的规定,虽然可以被访问,但不要随意访问。 - 私有变量可以通过
_类名_变量名
方式访问。但是不建议使用。
print(student._Student__score) ##输出 100
其实外部不能直接访问__score
原因是python解释器对外将__score
改成了_Student__score
。
数据封装
数据封装
是面向对象编程的一个重要特点。任何程序,只要封装好,对外只提供接口,使用方便且安全。
实例本身拥有数据,那么访问数据可以直接通过在类的内部定义访问数据的函数,而不用从外部的函数访问,这样就实现了数据的封装。
封装数据的函数和类本身是关联起来的,我们称之为类的方法。
例如:学生类中添加打印学生信息的函数。
class Student(object):
def __init__(self, no, name, score):
self.no = no
self.name = name
self.score = score
def hello(self):
print("number {0}".format(self.no))
print("hello {0}".format(self.name))
print("你的成绩 {0}".format(self.score))
student = Student(1101, "hewj", 100) #实例化并传入参数
student.hello() #通过实例的变量调用 类的内部函数
继承和多态
继承,顾名思义就知道是它的意思;
多态:使得我们在使用类似东西时不用考虑它们细微的区别。
举个例子:你现在有一个现有的A类,现在需要写一个B类,但是B类是A类的特殊版,我们就可以使用继承,B类继承A类时,B类会自动获得A类的所有属性和方法,A类称为父类,B类称为子类,子类除了继承父类的所有属性和方法,还可以自定义自己的属性和方法,大大增加了代码的复用性。
在我们本章的第一节中,我们可以继承了object类,object类是所有类的父类,所有的类都默认继承object类;它是一个超级类,如果其他类没有指定,默认继承object。
Python类的继承注意事项:
- 在继承中类的构造(__init()方法)不会自动调用,它需要在子类的构造中亲自调用。
- Python总是首先子类中的方法,如果子类没有找到,才回去父类中查找。
例子:
class Animal(object):
def __init__(self):
print("你现在实例初始化一个Animal")
def run(self):
print("Animal can run.")
class Bird(Animal):
def fly(self):
print("Bird can fly.")
class Cat(Animal):
def __init__(self):
print("我是一只猫")
def jiao(self):
print("miao miao miao")
def run(self):
print("我是一只猫,跑来跑去")
animal = Animal()
bird = Bird()
cat = Cat()
print("#############")
animal.run()
bird.run()
cat.run()
输出的结果:
py代码解释:
1、对于Bird(类),Animal(类)是Bird的父类;Bird(类)是Animal的字类。Cat(类)也类似
2、如果子类没有定义__init__()方法,子类初始化的时候就会调用父类的方法;如 bird = Bird()
3、但是当子类定义了__init__()方法,子类就不会调用父类的__init__()方法。如 cat = Cat()
4、当子类和父类均有相同的方法时,优先调用子类的方法。 如 cat.run() 和 animal.run() 的对比
5、若子类中没有,再去父类中寻找。如 bird.run() 和 animal.run() 的对比
对于前面定义的Animal类执行命令:
print(isinstance(bird, Bird)) #输出结果:True print(isinstance(bird, Animal)) #输出结果:True |
上面结果说明Bird
的实例bird
的数据类型是Bird
,同时也是Animal
。
也就是说,在继承关系中如果一个实例的数据类型是某个子类,那么它的数据类型也可以被看做是父类。