面向对象总结:
面向对象编程:
1.面向对象编程与面向过程编程
面向过程:
核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么…基于该思想编写程序就好比在设计一条流水线
优点:复杂的问题流程化,进而简单化
缺点:可扩展性差
面向对象:
核心是对象二字,对象指的是特征与技能的结合体,基于该思想编写程序就好比在创造一个世界,程序员就是这个世界的上帝,在上帝眼里一切事物均是对象
优点:可扩展性性高
缺点:编程的复杂度相对于面向过程要高
2.定义类
类就是一系列属性和方法的结合体
class OldboyStudent:
school='oldboy'
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def choose_course(self,course):
pass
# 类你也可以把它理解成是一个容器,你往里面存了很多名字,
# 存不是我们首要的目的,取才是!
# 如果你要访问类里面的名字
# print(OldBoy.__dict__)
# print(OldBoy.__dict__['school'])
# print(OldBoy.school) python给你提供了访问属性的简便操作 统一采用句点符
# 只要是句点符操作的左边一定是一个容器(名称空间) 比如: 模块,类,对象
3.实例化对象
调用init完成实例化 self.name = name,这种语法不是在获取属性而是在往对象里面新增属性
obj = OldBoy('jason')
print(obj.__dict__) # 查看对象独有的属性
print(obj.school) # 还可以查看类里面共有的属性
-
产生一个空对象
-
调用init实例化(将空对象和传入的参数一并传给init)
-
将实例化好的对象返回出来
4.属性查找
先从对象自己的名称空间找,如果没有则去类名称空间中找,如果还没有则去父类中找...
补充:
# python中一切皆对象
l = list([1,2,3])
obj1 = OldBoy('egon')
print(type(l))
print(type(obj1))
# 你定义一个类 可不可以认为就是定义了一个新的数据结构
# 你定义一个列表之后,是不是配套的有一堆相应的操作该列表的方法?append pop ...
# 那对象刚好也有对应的绑定方法
5.绑定给对象的方法
在类中定义的函数,叫方法,类可以调用但是需要手动传入self
该方法在没有被任何装饰器修饰的前提下,其实就是给对象用的而且是绑定给对象的绑定方法
绑定特点:谁来调就会将谁当作第一个参数自动传入
6.封装
1、什么是封装 “装”的意思就往一个容器中放入一系列属性 “封”的意思就是藏起来,在内部可以看到,但对外部是隐藏的
2、为什么要用封装
将复杂的操作封装成简单的接口,并严格控制接口的调用过程
3、如何用封装 但凡是双下划线开头(不能是双下划线结尾)的属性,会被隐藏起来,类内部可以直接使用 而类外部无法直接使用,即封装是对外不对内的
这种隐藏的特点:1、只是一种语法上的变形,会将__开头的属性变形为:_自己的类名__属性名(__n=1 #_Foo__n=1)2、该变形只在类定义阶段发生一次,在类定义阶段之后新增的__开头的属性并不会发生变形3、隐藏是对外不对内的4、在继承中,父类如果不想让子类覆盖自己的同名方法,可以将方法定义为私有的
class Teacher:
def __init__(self,name,age):
# self.__name=name
# self.__age=age
self.set_info(name,age)
def tell_info(self):
print('姓名:%s,年龄:%s' %(self.__name,self.__age))
def set_info(self,name,age):
if not isinstance(name,str):
raise TypeError('姓名必须是字符串类型')
if not isinstance(age,int):
raise TypeError('年龄必须是整型')
self.__name=name
self.__age=age
t=Teacher('egon',18)
t.tell_info()
t.set_info('egon',19)
t.tell_info()
1.继承与派生
1.什么是继承
继承就是一种新建类的方式,新建的类称为子类或者派生类,被继承的类称之为父类或者基类或者超类
子类会继承所有父类的属性和方法,即可以直接使用这些属性和方法
2.为什么要用继承
减少代码冗余
3.如何使用
class Parent1:
pass
class Parent2:
pass
class Son1(parent1):
pass
# python支持多继承,一个类可以有多个父类,但在java中只能有一个
class Son2(parent1,parent2):
pass
print(Son1.__bases__) # 查看当前类的所有的基类
print(Son2.__bases__)
# 那你是否会好奇想看看我们定义的Parent类它有没有偷偷摸摸的继承谁呢?
print(Parent1.__bases__)
print(Parent2.__bases__)
# 切换python解释器3.x >>> 2.x得出一个结论
"""
在python3中,如果没有显示地继承任何类,那默认继承object类
在python2中,如果没有显示地继承任何类,也不会继承object类
在python中类分为两种:
新式类:
但凡继承object的类,或者该类的子类都是新式类
>>>:在python3中所有的类都是新式类
经典类
没有继承object类,以及该类的子类都是经典类
也就意味着经典类和新式类这对儿概念只在python2中有
python3中只有新式类
"""
4.基于继承减少代码冗余的案例+派生/衍生
对象与对象之间总结相似的特征与技能得到类类与类之间总结相似的属性和特征得到父类
http://www.cnblogs.com/linhaifeng/articles/7340153.html
# 代码实例
import pickle
class OldboyStudent:
school = 'oldboy'
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def choice_course(self):
print('%s is choosing course'%self.name)
def save(self):
with open(self.name,'wb') as f:
pickle.dump(self,f)
class OldboyTeacher:
school = 'oldboy'
def __init__(self,name,age,sex,level):
self.name = name
self.age = age
self.sex = sex
self.level = level
def score(self):
print('%s is score'%self.name)
def save(self):
with open(self.name,'wb') as f:
pickle.dump(self,f)
stu = OldboyStudent('alex',30,'male')
stu.save()
tea = OldboyTeacher('egon',18,'male',10)
tea.save()
# 回过头来看,上面的代码是否存在相似的部分。我们刚好学过解决类之间解决代码冗余的方式
class OldboyPeople:
school = 'oldboy'
def save(self):
with open(self.name, 'wb') as f:
pickle.dump(self, f)
# 初步继承类抽取,思考继承之后对象查找属性和方法的顺序
stu.save()
stu.school
# 刚刚只是讲属性和方法抽成了父类,但是init里面也有重复的代码,应该也可以抽取
class OldboyPeople:
school = 'oldboy'
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def save(self):
with open(self.name, 'wb') as f:
pickle.dump(self, f)
# 先不考虑老师和学生init中不同的,先全部继承这个父类统一的init,发现也可以使用到父类的init
# 派生概念
# 在子类能够使用父类所有的属性和方法的同时,自身还有一些额外的属性和方法
# 小思考:如果派生的属性和方法恰巧和父类的一样,那在查找属性和方法的时候先找到谁呢? >>> 还是按查找顺序来
# 再回过头来看老师的init中有额外的level参数,不应该在父类中添加默认参数,只能自己重写init方法,但是又有重复的代码出现
def __init__(self,name,age,sex,level):
OldboyPeople.