面向对象介绍
'''
面向过程:
核心是"过程"二字
过程的核心思想是将程序流程化
过程是”流水线“,用来分步骤解决问题
面向对象:
1、核心是”对象“二字
2、对象的终极奥义就是将程序”整合“
3、对象就是”容器“,用来盛放数据与功能
优点:
1、提升程序的解耦合程度,进而增强程序的可扩展性
缺点:
2、可扩展性差
4、python这门语言到底提供了什么语法来允许我们将数据与功能整合在一起?
5、类:
类是对象相似数据与功能的集合体
所以类体中常见的是变量与函数定义,但是类体其实是可以包含任意其他代码的
强调!!:类体代码是再类定义阶段就会立即执行,会产生类的名称空间
6、使用顺序
# 一、先定义类
class Student:
stu_school = 'oldboy'
def __init__(obj, x): #对象下面的属性
obj.stu_name = x
def tell_stu_info(stu_obj):
print('学生信息:名字:%s,年龄:%s 性别:%s'%(stu_obj['stu_name'],
stu_obj['stu_age'],
stu_obj['stu_gender']))
def set_info(stu_obj,x,y,z):
stu_obj['stu_name'] = x
stu_obj['stu_age'] = y
stu_obj['stu_gender'] = z
# 功能的定义
pass
# 属性访问的语法:
# 访问数据属性 print(Student.set_school)
# 访问函数属性 print(Student.set_info)
# 二、再调用类产生对象
stu1_obj = Student('hongwei')
print(stu1_obj.set_info)
print(stu1_obj.__dict__)
#调用类的过程由称之为实例化,发生了三件事
# 1、先产生一个空对象
# 2、python会调用类中的__init__方法,然后将空对象已经调用类括号内传入的参数一同传给init
# 3、返回初始完的对象
#总结__init__方法
# 1、会在调用类时自动触发执行,用来为对象初始化自己独有的数据
# 2、__init__内因该存放是为对象初始化属性的功能,但是是可以存放任意其他代码,想要在
# 类调用时就立刻执行的代码都可以放到该方法内
# 3、__init__方法必须返回Now
# 三、绑定方法:
#谁来调用绑定方法就会将谁当做第一个参数自动传入
stu1_obj.tell_stu_info()
'''
案例
class School:
school_name='ke'
def __init__(self,nickname,addr):
self.addr = addr
self.nickname = nickname
self.classes = []
def related_class(self,class_obj):
self.classes.append(class_obj)
def tell_class(self):
print(self.nickname)
for class_obj in self.classes:
class_obj.tell_course()
class Class:
def __init__(self,name):
self.name=name
self.coures = None
def related_course(self,course_obj):
self.coures = course_obj
def tell_course(self):
print('班级名:%s '%(self.name))
self.coures.tell_info()
class Course:
def __init__(self,name,period,price):
self.name = name
self.period = period
self.price = price
def tell_info(self):
print('<课程名:%s 周期:%s 价钱:%s >'%(self.name,self.period,self.price))
class Student:
pass
class_obj1 = Class('脱产14期')
class_obj2 = Class('脱产15期')
class_obj1.related_course('python全栈开发')
class_obj2.related_course('HCIE云计算')
school_obj1 = School('宏伟魔都校区','瑞昌')
school_obj2 = School('宏伟帝都校区','北京')
school_obj1.related_class(class_obj1)
school_obj2.related_class(class_obj2)
course_obj1 = Course('python全栈开发','6mons',2000)
course_obj2 = Course('HCIE云计算','6mons',2000)
class_obj1.related_course(course_obj1)
class_obj2.related_course(course_obj2)
封装
class Foo:
__x=111
def __init__(self,y):
self.__y = y
class People:
def __init__(self,name,weight,height):
self.name = name
self.weight = weight
self.height = height
@property
def bmi(self):
return self.weight / (self.height **2 )
obj = People('hw',85,1.86)
print(obj.bmi)
class People:
def __init__(self,name):
self.__name = name
def get_name(self):
return self.__name
def set_name(self,val):
if type(val) is not str:
print('必须传入str类型')
return
self.__name = val
def del_name(self):
print('不让删除')
name = property(get_name,set_name,del_name)
obj = People('kehongwei')
obj.name = 18
del obj.name
print(obj.name)
继承
'''
1、什么是继承
继承是一个类继承另一个类
python支持多继承
在python中,新建的类可以继承一个或多个父类
class a:
pass
class b:
pass
class c(a): #单继承
pass
class d(a,b): #多继承
pass
2、为何要用继承?:用来解决类与类之间代码冗余问题
3、多继承?
优点:子类可以同时遗传多个父类属性
缺点:
1、违背人的思维习惯
2、代码可读性变差
3、不建议使用多继承,扩展性变差
如果不可避免的用到多继承,应该使用mixins
4、如何实现继承(怎么使用)
# 基于继承解决类与类之间的冗余问题(在此基础上加上学生学号)
class Func:
school = '宏伟'
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
class Student(Func):
# school='宏伟'
# def __init__(self,name,age):
# self.name = name
# self.age = age
def choose_course(self):
print('%s 正向选课'%self.name)
# obj = Student('HW',18,'female')
# print(obj.__dict__)
# print(obj.school)
# obj.choose_course()
class Teacher(Func):
school = '宏伟'
def __init__(self,name,age,sex,salary):
Func.__init__(self,name,age,sex)
self.name = name
self.age = age
self.sex = sex
self.salary = salary
def choose_course(self):
print('%s 正向选课'%self.name)
obj2=Teacher('hh',9,'male',4000)
print(obj2.__dict__)
5、单继承背景下的属性查找
# 示例1
class Foo:
def f1(self):
print('FOO.F1')
def f2(self):
print('FOO.F2')
self.f1() #obj.f1()
Foo.f1(self) #想调用当前类的f1
class Bar(Foo):
def f1(self):
print('Bar.f1')
obj = Bar()
obj.f2()
# 示例2
class Foo:
def __f1(self):
print('FOO.F1')
def f2(self):
print('FOO.F2')
self.__f1()
class Bar(Foo):
def f1(self):
print('Bar.f1')
obj = Bar()
obj.f2()
6、多继承背景下的属性查找
1、先查找父类,父类没有就找父类的父类,总之就是先把父类这个分支找完
2、通过mro表来查找
7、如果多继承是菱形继承,经典类与新式类的属性查找顺序不一样
1、新式类与经典类
父类或者以上由boject就是新式类,否则就是经典类
2、深度优先与广度优先
1、经典类:深度优先。会在检索第一条分支的时候直接一条道走到黑
2、新式类:广度优先,会在检索最后一条分支的时候检索object
8、多继承
多继承要不要用?
要用,但是需规避几点问题
1、继承结构经历不要过于复杂
2、需要使用mixinx:要在多继承的背景下满足继承什么是什么的关系(单继承)=》mixinx
9、 mixins机制核心:
# mixins提升多继承的可读性
#满足人的思维,什么是什么
10、子类中重用父类属性有两种方式:
#方式一:指名道姓的调用
#方式二:super()调用父类提供给自己的方法 =》严格以来继承关系
#调用super()会得到一个特殊对象,该对象会参照发起属性查找的那个类的mro取重用父类属性
'''
多态
1、多态:指的是一类事务有多种形态
动物的多种形态:牛,马
文件的多种形态:文本文件,可执行文件
2、多态性:指在不考虑实例类型的情况下使用实例
举个栗子:老师.下课铃响了(),学生.下课铃响了(),老师执行的是下班操作,学生执行的是放学操作,虽然二者消息一样,但是执行的效果不同
3、为什么要用多态性(多态性的好处)
1.增加了程序的灵活性
以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(animal)
2.增加了程序额可扩展性
通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(animal)去调用
class Cat(Animal):
... def talk(self):
... print('say miao')
...
def func(animal):
... animal.talk()
...
cat1=Cat()
func(cat1)
say miao
'''
这样我们新增了一个形态Cat,由Cat类产生的实例cat1,使用者可以在完全不需要修改自己代码的情况下。使用和人、狗、猪一样的方式调用cat1的talk方法,即func(cat1)
'''
4、鸭子类型
如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子,程序也是如此
class TxtFile:
def read(self):
pass
def write(self):
pass
class DiskFile:
def read(self):
pass
def write(self):
pass
反射
print(dir(obj))
print(obj.__dict__[dir(obj)[-2]])
print(hasattr(obj,'name'))
print(setattr(obj,'bool','asd'))
print(getattr(obj,'name'))
delattr(obj,'name')
内置方法
元类
print(type())
class Mymeta(type):
def __init__(self, x, y, z):
if not x.capitalize():
raise NameError('类名的首字母必须大写!')
def __new__(cls, *args, **kwargs):
print(cls, args, kwargs)
return type.__new__(cls, *args, **kwargs)
class People(metaclass=Mymeta):
def __init__(self, name, age):
self.name = name
self.age = age
class Foo:
def __init__(self,x,y):
self.x = x
self.y = y
def __call__(self, *args, **kwargs):
return 123
obj = Foo(123123, 123123)
a = obj()
print(a)
class Mymeta(type):
def __call__(self, *args, **kwargs):
people_obj = self.__new__(self)
self.__init__(people_obj,*args, **kwargs)
people_obj.__dict__['xxx']=111
return people_obj
class People(metaclass=Mymeta):
def __init__(self, name, age):
self.name = name
self.age = age
def __new__(cls, *args, **kwargs):
return object.__new__(cls)
obj = People('hw', 18)
abc = People('hw', 19)
print(obj.__dict__)
print(abc.__dict__)
|