NOTE:文章中的代码缩进不知道怎么搞,直接粘贴使用会报错
面向对象编程(Object Oriented Programming简称OOP)
- OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
- 面向对象的设计思想是抽象出Class,根据Class创建Instance
面向对象的三大特点:
- 数据封装
- 继承
- 多态
类(Class)和实例(Instance)
- 类是抽象的模板
- 实例是根据类创建出来的一个个具体的"对象"
note:每个对象都拥有相同的方法,但各自的数据可能不同 - 定义类通过
Class
关键字:
class Student(object):
pass
- 类名是大写字母开头的单词,
()
里表示该类是从哪个类继承下来的,没有合适的类就用object
类,这是所有类最终都会继承的类
- 创建实例是通过类名+()实现的:
>>> bart = Student()
- 类可以起到模板的作用
可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去,通过定义一个特殊的__init__
方法来实现:
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
note:__init__
方法的第一个参数永远是self
,表示创建的实例本身,但是在调用是不用传递该参数。除此之外类的方法和普通函数没有什么区别,可以使用默认参数、可变参数、关键字参数和命名关键字参数
数据封装
- 实例本身就拥有数据,要访问这些数据,没有必要从外面的函数去访问,直接在类的内部定义访问数据的函数,这样,就把“数据”给封装起来了。
- 这些封装数据的函数是和类本身是关联起来的,我们称之为类的方法
- 定义方法
除了第一个参数是self
外,其他和普通函数一样
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
def print_score(self):
print('%s: %s' % (self.name, self.score))
- 调用方法
只需要在实例变量上直接调用,除了self
不用传递,其他参数正常传入:
>>> bart.print_score()
Bart Simpson: 59
数据封装的优势:
- 调用容易,不用知道内部实现的细节
- 可以给类增加新的方法
访问限制
- 要让内部属性不被外部访问,可以把属性的名称前加上两个下划线
__
,实例的变量名如果以__
开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问
note:__xxx__
是特殊变量,可以直接访问,不是private变量,注意区分
class Student(object):
def __init__(self, name, score):
self.__name = name
self.__score = score
def print_score(self):
print('%s: %s' % (self.__name, self.__score))
- 要想外部访问内部变量,可以通过给类增加方法来实现
继承和多态
在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)
- 继承的好处:
- 子类获得了父类的全部功能
- 我们对代码做一点改进,子类和父类都存在相同的方法时,之类的方法会覆盖父类的方法,这就是多态
- 多态的好处(“开闭原则”):
- 对扩展开放:允许新增子类
- 对修改封闭:不需要修改依赖父类的任何函数
- 动态语言的“鸭子类型”
不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子
也就是不同的对象只要有相同的方法,那么就可以认为是一种“类型”
获取对象信息
type()
-
isinstance()
返回值是True或者False -
dir()
获得一个对象的所有属性和方法
- 类似
__xxx__
的属性和方法在Python中都是有特殊用途的
-
getattr()
、setattr()
、hasattr()
- 对于
getattr()
可以传入一个default参数,如果属性不存在,就返回默认值
>>> getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404
实例属性和类属性
- 类的属性直接在Class中定义,该属性归该类所有,因此所有的实例都可以访问类的属性
- 千万不要把实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性