1.初识面向对像
1.三大编程范式(编程的三种方法/风格)
面向过程编程
定义:面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。即把一个大的问题细分成小的问题,执行时候从第一步执行到最后一步。
优点:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。
缺点:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。
函数式编程
定义:数学层面的函数和编程层面函数两者和二为一的编程
面向对象编程(OOP)
定义:面向对象”是一种编程范式,对函数进行分类和封装,让开发“更快更好更强...
优点:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现,一刀砍死3个人,这个游戏就失去平衡。
应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。
在python 中面向对象的程序设计并不是全部。
面向对象编程可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
编程步骤:
1)把构成问题的事务分解、抽象成各个对象;
2)结合这些对象的共有属性,抽象出类;
3)类层次化结构设计--继承 和 合成;
4)用类和实例进行设计和实现来解决问题。
(说明:三中编程方法没有高低之分,各有优劣)
2.面向对象的介绍
面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用
1.1类
定义:把一类事物的相同的特征和动作整合到一起就是类(如 人、狗、老虎))是一个抽象的概念,在python中类是一个模板,模板里可以包含多个函数,函数里实现一些功能
1.2类的创建:
class Foo: #clss 为关键字,表示要创建类,Foo是类的名称 def __init__(self,参数1,参数2): #self为特殊参数,必填 self.对象的属性1 = 参数1 self.对象的属性2 = 参数2 def 方法名(self):pass def 方法名2(self):pass 对象名 = Foo (1,2) #对象就是实例,代表一个具体的东西 #类名() : 类名+括号就是实例化一个类,相当于调用了__init__方法 #括号里传参数,参数不需要传self,其他与init中的形参一一对应 #结果返回一个对象 对象名.对象的属性 #查看对象的属性,直接用 对象名.属性名 即可 对象名.方法名() #调用类中的方法,直接用 对象名.方法名() 即可
1.3类的两种作用(属性引用和实例化)
1.3.1属性引用(类名.属性)
类有两种属性:数据属性和函数属性
1. 类的数据属性是所有对象共享的
2. 类的函数属性是绑定给对象用的
class Person: #定义一个人类 role = 'person' #类属性----静态属性 人的角色属性都是人 def walk(self): #这里的函数叫做方法---动态属性.self必须写。 print("person is walking...") print(Person.role) #查看类属性,查看人的role属性 print(Person.walk) #查看类方法,引用人的走路方法,注意,这里不是在调用,用类名去调用方法名,打印出来的是内存地址
1.3.2实例化(对象名 = 类名(参数))
实例化的过程就是类——>对象的过程,
class Person: #定义一个人类 role = 'person' #人的角色属性都是人 def __init__(self,name): self.name = name # 每一个角色都有自己的昵称; def walk(self): #人都可以走路,也就是有一个走路方法 print("person is walking...") egg = Person('egon') #实例化:类名(参数) 就等于在执行Person.__init__() #执行完__init__()就会返回一个对象。这个对象类似一个字典,存着属于这个人本身的一些属性和方法。 print(egg) #返回的是一个对象 print(egg.name) #查看属性直接 对象名.属性名 print(egg.walk()) #调用方法, 对象名.方法名()
原本我们只有一个Person类,在这个过程中,产生了一个egg对象,有自己具体的名字、攻击力和生命值。
关于self,在实例化时自动将对象/实例本身传给__init__的第一个参数,是固定的,你也可以给他起个别的名字,但是正常人都不会这么做。
1.4 类的增删改查
1.5类的补充
我们定义的类的属性到底存到哪里了?有两种方式查看 dir(类名):查出的是一个名字列表 类名.__dict__:查出的是一个字典,key为属性名,value为属性值
print(Person.__name__, type(Person.__name__)) #查看类的名字(这里的类名是字符串类型的) print(Person.__dict__) #查出的是一个字典,key为属性名,value为属性值 print(Person.__doc__) # 就是把注释显示出来,文档字符串 print(dir(Person)) #查看类的方法,以列表的形式显示出来 print(Person.__module__) #类定义所在的模块 print(Person.__class__) # 实例对应的类(仅新式类中) print(isinstance(egg,Person)) #判断对象 是否是类的实例 print(Person.__bases__) # 类所有父类构成的元组(在讲继承时会讲))
2.1对象/实例:
定义:就是基于类而创建的一个具体的事物(具体存在的)也是特征和动作整合到一起,在python中对象是根据模板创建的实例,通过实例对象可以执行类中的函数。
对象的使用
对象的属性 属性引用
对象的增删该查
对象与实例性
对象之间的交互
类命名空间与对象、实例的命名空间
面向对象的组合用法
面向对象的小结
3面向对象的三大特性
3.1继承
定义:继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
python中类的继承分为:单继承和多继承
class ParentClass1: #定义父类 pass class ParentClass2: #定义父类 pass class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass pass class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类 pass
查看继承
print( SubClass1.__bases__ ) #__base__只查看从左到右继承的第一个子类 >>>(<class '__main__.ParentClass1'>,) print(SubClass2.__bases__) #__bases__是查看所有继承的父类 >>>(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>) ##如果没有指定基类,python的类会默认继承object类,object是所有python类的基类,它提供了一些常见方法(如__str__)的实现。 print(ParentClass1.__bases__) >>>(<class 'object'>,) print(ParentClass2.__bases__) >>>(<class 'object'>,)
经典类:在python2中,class Dad: 不会继承object,这样的类叫做经典类(它叫经典类,不是因为它经典,而是因为它比较老)
新式类:在python3中,python会默认继承object类(一切皆对象),class Dad 就相当于python2中的 class Dad(object) #新式类
而且python3中没有经典类了
派生:子类在父类方法和属性的基础上产生了新的方法和属性。
1.在父类的基础上产生子类,产生的子类就叫做派生类
2.父类里没有的方法,在子类中有了,这样的方法就叫做派生方法。
3.父类里有,子类也有的方法,就叫做方法的重写(就是把父类里的方法重写了)
说明:
1.子类可以使用父类的所有属性和方法
2.如果子类有自己的方法,就执行自己的;如果子类没有自己的方法,就会找父类的。
3.如果子类里面没有找到,父类里也没有找到,就会报错
4.如果子类中实现了调用父类的方法
在类内:super(子类,self).方法名() supper().__init__(参数)
在类外:super(子类名,对象名).方法名()
class Animal: ''' 人和狗都是动物,所以创造一个Animal基类 ''' def __init__(self, name, aggressivity, life_value): self.name = name # 人和狗都有自己的昵称; self.aggressivity = aggressivity # 人和狗都有自己的攻击力; self.life_value = life_value # 人和狗都有自己的生命值; def eat(self): print('%s is eating'%self.name) class Dog(Animal): ''' 狗类,继承Animal类 ''' def bite(self, people): ''' 派生:狗有咬人的技能 :param people: ''' people.life_value -= self.aggressivity class Person(Animal): ''' 人类,继承Animal ''' def attack(self, dog): ''' 派生:人有攻击的技能 :param dog: ''' dog.life_value -= self.aggressivity egg = Person('egon',10,1000) ha2 = Dog('二愣子',50,1000) print(ha2.life_value) print(egg.attack(ha2)) print(ha2.life_value)
子类中调用父类的方法
方法一:父类名.父类方法()
#_*_coding:utf-8_*_ __author__ = 'Linhaifeng' class Vehicle: #定义交通工具类 Country='China' def __init__(self,name,speed,load,power): self.name=name self.speed=speed self.load=load self.power=power def run(self): print('开动啦...') class Subway(Vehicle): #地铁 def __init__(self,name,speed,load,power,line): Vehicle.__init__(self,name,speed,load,power) self.line=line def run(self): print('地铁%s号线欢迎您' %self.line) Vehicle.run(self) line13=Subway('中国地铁','180m/s','1000人/箱','电',13) line13.run()
方法二:super()
class Vehicle: #定义交通工具类 Country='China' def __init__(self,name,speed,load,power): self.name=name self.speed=speed self.load=load self.power=power def run(self): print('开动啦...') class Subway(Vehicle): #地铁 def __init__(self,name,speed,load,power,line): #super(Subway,self) 就相当于实例本身 在python3中super()等同于super(Subway,self) super().__init__(name,speed,load,power) self.line=line def run(self): print('地铁%s号线欢迎您' %self.line) super(Subway,self).run() class Mobike(Vehicle):#摩拜单车 pass line13=Subway('中国地铁','180m/s','1000人/箱','电',13) line13.run()
3.2多态
3.3封装
封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
所以,在使用面向对象的封装特性时,需要:
- 将内容封装到某处
- 从某处调用被封装的内容
在程序中:务必保证先定义类,后产生对象
这与函数的使用是类似的,先定义函数,后调用函数,类也是一样的,在程序中需要先定义类,后调用类
不一样的是,调用函数会执行函数体代码返回的是函数体执行的结果,而调用类会产生对象,返回的是对象
继承
定义:
组合:
定义:
多态
反射
封装
元类