学习目标:
面向对象编程学习内容:
1、 [面向对象编程介绍(上)] 2、 [面向对象基础介绍(下)]学习时间:
2小时学习产出:
1、 [面向对象编程介绍(上)] 1、了解面向过程和面向对象
*面向过程:根据业务逻辑从上到下写代码,强调步骤和过程,每一步都亲自实现
*面向对象:将数据与函数绑定到一起,进行封装,这样能够更快速的开发程序,减少了重复代码的重写过程
*面向对象(object-oriented ;简称: OO) 至今还没有统一的概念 我这里把它定义为: 按人们 认识客观世界的系统思维方式,
采用基于对象(实体) 的概念建立模型,模拟客观世界分析、设 计、实现软件的办法
*面向对象编程(Object Oriented Programming-OOP) 是一种解决软件复用的设计和编程方法。 这种方法把软件系统中相近相似的操作逻辑和操作 应用数据、状态,以类的型
式描述出来,以对象实例的形式在软件系统中复用,以达到提高软件开发效率的作用。
2、类和对象
(1)、类:
*具有相同属性和行为事物的统称
*类是创建对象的模板
(2)、对象
*某一具体事物,可以直接使用;
(3)、类的构成
*类的名称:类名
*类的属性:一组数据
*类的方法:允许对进行操作的方法(行为)
3、类的抽象
*拥有相同(或者类似)属性和行为的对象都可以抽像出一个类
方法:
*1、一般名词都是类(名词提炼法)
4、定义类:
(1)、格式:
class 类名:
方法列表
(2)、说明:
*定义类时有2种形式:新式类和经典类,上面代码中的Hero为新式类,前两行注释部分则为经典类;
*object 是Python 里所有类的最顶级父类;
*类名 的命名规则按照"大驼峰命名法";
*info 是一个实例方法,第一个参数一般是self,表示实例对象本身,当然了可以将self换为其它的名字,其作用是一个变量 这个变量指向了实例对象
5、创建对象
(1)、格式:
对象名=类名()
(2)、说明
*当创建一个对象时,就是用一个模子,来制造一个实物
*在方法内通过seif获取对象属性
(3)__init__()方法
*__init__()方法,在创建一个对象时默认被调用,不需要手动调用
*__init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递过去。
(4)、无参数的__init__()方法
*通过一个类,可以创建多个对象,就好比 通过一个模具创建多个实体一样
*__init__(self)中,默认有1个参数名字为self,如果在创建对象时传递了2个实参,那么__init__(self)中出了self作为第一个形参外还需要2个形参,例如__init__(self,x,y)
*例如:
def __init__(self, name, skill, hp, atk, armor):
...
taidamier = Hero("泰达米尔", "旋风斩", 2600, 450, 200)
*注意:
*在类内部获取 属性 和 实例方法,通过self获取;
*在类外部获取 属性 和 实例方法,通过对象名获取。
*如果一个类有多个对象,每个对象的属性是各自保存的,都有各自独立的地址;
*但是实例方法是所有对象共享的,只占用一份内存空间。类会通过self来判断是哪个对象调用了实例方法。
6、__str__()方法
*这个方法是一个魔法方法 (Magic Method) ,用来显示信息
*该方法需要 return 一个数据,并且只有self一个参数,当在类的外部 print(对象) 则打印这个数据
说明:
*在python中方法名如果是__xxxx__()的,那么就有特殊的功能,因此叫做“魔法”方法
*当使用print输出对象的时候,默认打印对象的内存地址。如果类定义了__str__(self)方法,那么就会打印从在这个方法中 return 的数据
*__str__方法通常返回一个字符串,作为这个对象的描述信息
7、__del__()方法
*创建对象后,python解释器默认调用__init__()方法;
*当删除对象时,python解释器也会默认调用一个方法,这个方法为__del__()方法
*当有变量保存了一个对象的引用时,此对象的引用计数就会加1
*当使用del() 删除变量指向的对象时,则会减少对象的引用计数。如果对象的引用计数不为1,那么会让这个对象的引用计数减1,当对象的引用计数为0的时候,则对象才会被真正删除(内存被回收)
8、小项目:存放家具
9、继承介绍以及单继承
(1)、继承
*在程序中,继承描述的是多个类之间的所属关系。
*如果一个类A里面的属性和方法可以复用,则可以通过继承的方式,传递到类B里。
*那么类A就是基类,也叫做父类;类B就是派生类,也叫做子类。
(2)、单继承:子类只继承一个父类
*虽然子类没有定义__init__方法初始化属性,也没有定义实例方法,但是父类有。所以只要创建子类的对象,就默认执行了那个继承过来的__init__方法
*子类在继承的时候,在定义类时,小括号()中为父类的名字
*父类的属性、方法,会被继承给子类
10、多继承:子类继承多个父类
*多继承可以继承多个父类,也继承了所有父类的属性和方法
*注意:如果多个父类中有同名的 属性和方法,则默认使用第一个父类的属性和方法(根据类的魔法属性mro的顺序来查找)
*多个父类中,不重名的属性和方法,不会有任何影响
11、子类重写父类的同名属性和方法
*如果子类和父类的方法名和属性名相同,则默认使用子类的 叫 子类重写父类的同名方法和属性
*子类的魔法属性__mro__决定了属性和方法的查找顺序
12、子类调用父类同名属性和方法
*调用父类方法格式:父类类名.父类方法(self)
*无论何时何地,self都表示是子类的对象。在调用父类方法时,通过传递self参数,来控制方法和属性的访问修改。
13、多层继承
*调用父类方法格式:父类类名.父类方法(self)
14、super()的使用
*子类继承了多个父类,如果父类类名修改了,那么子类也要涉及多次修改。而且需要重复写多次调用,显得代码臃肿。
*使用super() 可以逐一调用所有的父类方法,并且只执行一次。调用顺序遵循 mro 类属性的顺序
*注意:如果继承了多个父类,且父类都有同名方法,则默认只执行第一个父类的(同名方法只执行一次,目前super()不支持执行多个父类的同名方法)
2、 [面向对象基础介绍(下)]
1、私有权限
*面向对象三大特性:封装、继承、多态
(1)、封装的意义:
*将属性和方法放到一起做为一个整体,然后通过实例化对象来处理;
*隐藏内部实现细节,只需要和对象及其属性和方法交互就可以了;
*对类的属性和方法增加 访问权限控制
(2)、私有权限:在属性名和方法名 前面 加上两个下划线 __
*类的私有属性 和 私有方法,都不能通过对象直接访问,但是可以在本类内部访问
*类的私有属性 和 私有方法,都不会被子类继承,子类也无法访问;
*私有属性 和 私有方法 往往用来处理类的内部事情,不通过对象处理,起到安全作用。
(3)、总结
*Python中没有像C++中 public 和 private 这些关键字来区别公有属性和私有属性
*Python是以属性命名方式来区分,如果在属性和方法名前面加了2个下划线'__',则表明该属性和方法是私有权限,否则为公有权限。
(4)、修改私有属性的值
*如果需要修改一个对象的属性值,通常有2种方法
/*对象名.属性名 = 数据 ----> 直接修改
/*对象名.方法名() ----> 间接修改
*私有属性不能直接访问,所以无法通过第一种方式修改,一般的通过第二种方式修改私有属性的值:定义一个可以调用的公有方法,在这个公有方法内访问修改。
*现代软件开发中,通常会定义get_xxx()方法和set_xxx()方法来获取和修改私有属性值。
2、多态
*所谓多态:定义时的类型和运行时的类型不一样,此时就成为多态 ,多态的概念是应用于Java和C#这一类强类型语言中,而Python崇尚“鸭子类型”。
*鸭子类型:虽然我想要一只"鸭子",但是你给了我一只鸟。 但是只要这只鸟走路像鸭子,叫起来像鸭子,游泳也像鸭子,我就认为这是鸭子
*Python的多态,就是弱化类型,重点在于对象参数是否有指定的属性和方法,如果有就认定合适,而不关心对象的类型是否正确
3、类属性和实例属性
(1)、类属性:
*类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本,这个和C++中类的静态成员变量有点类似。对于公有的类属性,在类外可以通过类对象和实例对象访问
*例如:
class People(object):
address = '山东' # 类属性
def __init__(self):
self.name = 'xiaowang' # 实例属性
self.age = 20 # 实例属性
(2)、实例属性(对象属性)
(3)、总结:
*如果需要在类外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。
4、静态方法和类方法
(1)、类方法:
*是类对象所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数(当然可以用其他名称的变量作为其第一个参数,但是大部分人都习惯以'cls'作为第一个参数的名字,就最好用'cls'了),能够通过实例对象和类对象去访问。
*例如:
class People(object):
# 私有类属性
__country = 'china'
#类方法,用classmethod来进行修饰
@classmethod
def get_country(cls):
return cls.__country
p = People()
print(p.get_country()) #可以用过实例对象引用
print(People.get_country()) #可以通过类对象引用
*类方法还有一个用途就是可以对类属性进行修改:
(2)、静态方法
*需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数,可以通过对象和类来访问。
*例如:
class People(object):
country = 'china'
@staticmethod
#静态方法
def get_country():
return People.country
*总结:
*从类方法和实例方法以及静态方法的定义形式就可以看出来,类方法的第一个参数是类对象cls,那么通过cls引用的必定是类对象的属性和方法;
*实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可能是实例属性(这个需要具体分析),不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。
*静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类实例对象来引用
(3)、__new__方法
*__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供
*__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例
*__init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值
*我们可以将类比作制造商,__new__方法就是前期的原材料购买环节,__init__方法就是在有原材料的基础上,加工,初始化商品环节
5、 设计模式:单例模式
(1)、单例是什么
*确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,单例模式是一种对象创建型模式。
*创建单例时,只执行1次__init__方法