目录
一、面向对象编程
1、定义类
# 类:存放多个对象共有的数据与功能的容器
# 类体代码在类定义阶段就会立即执行
class Student:
# 1、定义属性
stu_school="oldboy"
# 2、定义__init__方法(会在调用类时自动触发执行,必须返回None)
# 应用场景:用于对象初始化自己独有的数据,也可以存放想要在调用类时就立刻执行的代码
def __init__(self,name,age,gender):
self.stu_name=name # self.__dict__["stu_name"]=name
self.stu_age=age
self.stu_gender=gender
# 3、定义方法
# 3.1、绑定给对象的方法(调用者是对象,对象调用时自动将该对象当作第一个参数传入)
def tell_info(self):
print("学生信息:名字{},年龄{},性别{}".format(self.stu_name,self.stu_age,self.stu_gender))
def set_info(self,name,age,gender):
self.stu_name=name
self.stu_age=age
self.stu_gender=gender
print("=======================>")
# 3.2、绑定给类的方法(调用者是类,类调用时自动将该类当作第一个参数传入)
# 应用场景:新的造对象方式
@classmethod
def from_conf(cls):
import settings
return cls(settings.name,settings.age,settings.gender)
# 3.3、非绑定方法(调用者是类、对象,不会自动传参)
# 应用场景:类体代码不需要类也不需要对象,还要放在类内部
@staticmethod
def create_id():
import uuid
return uuid.uuid4()
2、调用类生成对象
# 调用类生成对象,又称之为实例化,发生了三件事
# 1、先产生一个空对象
# 2、自动调用类中的__init__方法,然后将空对象以及括号中的参数传给__init__
# 3、返回初始化完的对象
stu_obj1=Student("aaa",18,"male")
stu_obj2=Student("bbb",19,"male")
stu_obj3=Student("ccc",20,"female")
print(stu_obj1.__dict__)
3、属性查找与绑定方法
Student.stu_school
Student.tell_info(stu_obj1)
Student.from_conf()
Student.create_id()
stu_obj1.stu_school
stu_obj1.tell_info()
stu_obj1.creat_id()
二、封装
1、定义
# 封装是什么:抽象得到的数据和功能相结合,形成一个有机的整体(我们称之为类)
# 为何要用封装:用来解决对象与对象之间代码重复的问题
2、隐藏属性
'''
隐藏属性:
在属性名前加__前缀
在只发生一次(检查类体代码语法时会将__属性名统一变形为_类名__属性名)
对外不对内(类外__属性名不能直接访问,类内__属性名依旧可以访问)
为何隐藏属性:
隐藏属性,在类外部无法直接访问
类内提供相应的接口来允许外部间接的操作数据
接口之上可以附加额外的逻辑来对数据的操作进行严格的限制
'''
class Foo():
def __init__(self,name):
self.__name=name
def get_name(self):
print(self.__name)
def set_name(self,val):
if type(val) !=str:
print("请输入字符类型")
return
self.__name=val
obj=Foo("Cang")
# obj.__name
obj.get_name()
obj.set_name("Yuan")
3、@property装饰器
# @property的使用:将方法变成属性调用
class Foo():
def __init__(self,name):
self.__name=name
@property # 实现一个name相关的getter功能
def name(self):
print(self.__name)
@name.setter # 实现一个name相关的setter功能
def name(self,val):
if type(val) !=str:
print("请输入字符类型")
return
self.__name=val
@name.deleter # 实现一个name相关的deleter功能
def name(self):
del self.__name
obj1=Foo("Cang")
obj1.name
obj1.name="Yuan"
del obj1.name
# @property的原理
class Foo:
def __init__(self,name):
self.__name=name
def get_name(self):
print(self.__name)
def set_name(self,val):
if type(val) !=str:
print("请输入英文字符")
return
self.__name=val
def del_name(self):
del self.__name
name=property(fget=get_name, fset=set_name, fdel=del_name, doc=None)
obj1=Foo("Cang")
obj1.name
obj1.name="Yuan"
del obj1.name
三、继承
1、定义
# 继承是什么:一种创建新类的方式,新建的类称为子类或派生类,父类可称为基类或超类
# 为何要用继承:用来解决类与类之间代码冗余的问题
# 多继承的优缺点(python支持多继承,新建的类可以继承一个或多个父类)
# 优点:子类可以同时遗传多个父类的属性,最大限度的重用代码
# 缺点:
# 违反人的思维习惯,继承表达的是一种什么"是"什么的关系
# 代码的可读性会变差,扩展性变差,有可能会引发可恶的菱形问题
# 不建议使用多继承,如果不可避免多个父类的继承,应该使用Minxins
class Parent1:
pass
class Parent2:
pass
class Sub1(Parent1): # 单继承
pass
print(Sub1.__bases__) # 查看自己的父类 (<class '__main__.Parent1'>,)
class Sub2(Parent1,Parent2): # 多继承
pass
print(Sub2.__bases__) # 查看自己的父类 (<class '__main__.Parent1'>, <class '__main__.Parent2'>)
# ps:经典类与新式类
# python2中
# 新式类:继承object类的子类,以及该子类的子类子子类...
# 经典类:没有继承object类的子类,以及该子类的子类子子类...
# python3中
# 没有继承任何类,那么就会默认继承object类,所以python3中的类都是新式类
2、实现继承
class Student:
school="oldboy"
def __init__(self,name,age,gender):
self.name=name
self.age=age
self.gender=gender
def choose_course(self):
print("学生{}选课".format(self.name))
class Teacher:
school="oldboy"
def __init__(self,name,age,gender,level,salary):
self.name=name
self.age=age
self.gender=gender
self.level=level
self.salary=salary
def score(self):
print("老师{}打分".format(self.name))
class OldboyPeople:
school="oldboy"
def __init__(self,name,age,gender):
self.name=name
self.age=age
self.gender=gender
class Student(OldboyPeople):
def choose_course(self):
print("学生{}选课".format(self.name))
stu_obj=Student("Cany",18,"male")
print(stu_obj.__dict__)
class Teacher(OldboyPeople):
def __init__(self,name,age,gender,level,salary):
# OldboyPeople.__init__(self,name,age,gender)
# super()得到一个特殊的对象
# 按照最初的mro来找,从当前类所在位置的下一个找起
super().__init__(name,age,gender)
self.level=level
self.salary=salary
def score(self):
print("老师{}打分".format(self.name))
tea_obj=Teacher("Yuan",23,"female",2,8000)
print(tea_obj.__dict__)
tea_obj.school
# 属性查找顺序
# 先从对象自己这找
# 再从类的mro找起
3、属性查找
3.1、单继承下的属性查找
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()
class Foo:
def f1(self):
print("Foo.f1")
def f2(self):
print("Foo.f2")
Foo.f1(self) # 调用当前类中的f1
class Bar(Foo):
def f1(self):
print("Bar.f1")
obj=Bar()
obj.f2()
class Foo:
def __f1(self):
print("Foo.f1")
def f2(self):
print("Foo.f2")
self.__f1() # 调用当前类中的f1
class Bar(Foo):
def f1(self):
print("Bar.f1")
obj=Bar()
obj.f2()
3.2、菱形问题与MRO介绍
class A:
def test(self):
print("from A")
class B(A):
def test(self):
print("from B")
class C(A):
def test(self):
print("from C")
class D(B,C):
def test(self):
print("from D")
print(D.mro()) # D,B,C,A
obj=D()
obj.test()
3.3、非菱形下的属性查找
class E:
def test(self):
print("from E")
class F:
def test(self):
print("from F")
class B(E):
def test(self):
print("from B")
class C(F):
def test(self):
print("from C")
class D:
def test(self):
print("from D")
class A(B,C,D):
def test(self):
print("from A")
print(A.mro()) # A,B,E,C,F,D,object
obj=A()
obj.test()
3.4、广度优先(python3)
class G:
def test(self):
print("from G")
class E(G):
def test(self):
print("from E")
class F(G):
def test(self):
print("from F")
class B(E):
def test(self):
print("from B")
class C(F):
def test(self):
print("from C")
class D(G):
def test(self):
print("from D")
class A(B,C,D):
def test(self):
print("from A")
print(A.mro()) # A,B,E,C,F,D,G,object
obj=A()
obj.test()
4、mixins机制
# Mixins机制是一种规范,用来解决多继承下的可读性问题
class Vehicle:
pass
class FlyMixin: # Mixin类的命名一般以mixin,able,ible为后缀
pass # 不依赖于子类的实现
class CivilAircraft(FlyMixin,Vehicle): # 子类即便没有继承这个mixin类,也可以照样工作,就是缺少某个功能
pass
class Helicopter(FlyMixin,Vehicle):
pass
class Car(Vehicle):
pass
5、组合
import pickle
import uuid
class School:
schoo_name="oldboy"
def __init__(self,addr):
self.id=uuid.uuid4()
self.addr=addr
self.classes=[]
def relate_classes(self,class_obj):
self.classes.append(class_obj)
def tell_classes(self):
for i in self.classes:
i.tell_course()
def save(self):
with open(r"{}.pkl".format(self.id),mode="wb") as f:
res=pickle.dumps(self.addr)
f.write(res)
def read(self):
with open(r"{}.pkl".format(self.id),mode="rb") as f:
res=f.read()
print(pickle.loads(res))
class Class():
def __init__(self,name):
self.class_name=name
self.class_course=None
def relate_course(self,course_obj):
self.class_course=course_obj
def tell_course(self):
self.class_course.tell_info()
class Course():
def __init__(self,name,period,price):
self.course_name=name
self.course_period=period
self.course_price=price
def tell_info(self):
print("<课程名:{} 周期:{} 价钱:{}>".format(self.course_name,self.course_period,self.course_price))
course_obj1=Course("python全栈开发","6mons",20000)
class_obj1=Class("脱产18期")
class_obj1.relate_course(course_obj1)
school_obj1=School("魔都")
school_obj1.relate_classes(class_obj1)
school_obj1.save()
school_obj1.read()
四、多态
1、多态思想
# 什么是多态:同一种事物有多种形态
class Animal:
def say(self):
print("动物的基本发声。。。")
class People(Animal):
def say(self):
super().say()
print("嘤嘤嘤")
class Dog(Animal):
def say(self):
super().say()
print("汪汪汪")
class Pig(Animal):
def say(self):
super().say()
print("哼哼哼")
obj1=People()
obj2=Dog()
obj3=Pig()
def animal_say(obj): # 定义统一的接口,接收传入的动物对象
obj.say()
animal_say(obj1)
animal_say(obj2)
animal_say(obj3)
2、python推崇的是鸭子类型
class Cpu:
def read(self):
print("cpu read")
def write(self):
print("cpu write")
class Mem:
def read(self):
print("mem read")
def write(self):
print("mem write")
class Txt:
def read(self):
print("txt read")
def write(self):
print("txt write")
obj1=Cpu()
obj2=Mem()
obj3=Txt()
def read(obj):
obj.read()
read(obj1)
五、面向对象高级
1、反射
'''
反射是基于字符串的事件驱动
以字符串的形式导入模块
以字符串的形式操作模块中成员
hasattr()
getattr()
setattr()
delattr()
'''
mode_name=input("请输入要导入的模块名:").strip()
m=__import__(mode_name,fromlist=True)
func_name=input("请输入要操作的函数名:").strip()
f=getattr(m,func_name,None)
f()
2、内置方法
# 什么是内置方法
# 定义在类内部的,以__开头__结尾的,在某种情况下会自动触发执行的方法
# 为何用内置方法
# 为了定制化我们的类或对象
# 如何用内置方法
# __str__:打印对象时会自动触发执行,并将返回值(必须是str类型)打印出来
# __del__:回收对象时(程序运行中del或程序运行完回收对象)会自动触发执行
3、元类
3.1、元类介绍
# 元类就是实例化产生类的类
# 关系:元类 ————实例化————> 类 ————实例化————> 对象
# 查看内置的元类
# 1、type是内置的元类
# 2、用class关键字定义的所有类、内置的类都是由元类type实例化产生的
3.2、class机制分析
# class People:
# def __init__(self,name,age):
# self.name=name
# self.age=age
# def say(self):
# print("名字:{}年龄:{}".format(self.name,self.age))
# 1、类名
class_name="People"
# 2、类的基类
class_bases=(object,)
# 3、执行类体代码拿到类的名称空间
class_dic={}
class_body="""
def __init__(self,name,age):
self.name=name
self.age=age
def say(self):
print("名字:{}年龄:{}".format(self.name,self.age))
"""
exec(class_body,{},class_dic)
# 4、调用元类
People=type(class_name,class_bases,class_dic)
3.3、定制元类控制类的产生
class Mymeta(type):
def __new__(cls, *args, **kwargs):
# 造Mymeta的对象
return type.__new__(cls, *args, **kwargs)
def __init__(self,x,y,z):
if not z.get("__doc__"):
raise TypeError("必须写文档注释")
def __call__(self, *args, **kwargs):
people_obj=self.__new__(self, *args, **kwargs)
self.__init__(people_obj,*args, **kwargs)
return people_obj
class People(metaclass=Mymeta): # Mymeta(类名,基类,类的名称空间)
"""aaaaaaa""" # type.__call__(self, *args, **kwargs)
def __new__(cls, *args, **kwargs): # 会调用Mymeta中的__new__方法,返回一个空对象
return object.__new__(cls) # 调用Mymeta中的__init__方法,然后传参空对象、类名、基类、类的名称空间
def __init__(self,name,age): # 会返回初始化完成的对象
self.name=name
self.age=age
obj=People("Cang",18) # People("Cang",18)
# Mymeta.__call__(self, *args, **kwargs)
# 会调用People中的__new__方法,返回一个空对象
# 会调用People中的__init__方法,然后传参空对象、类名、基类、类的名称空间
# 会返回初始化完成的对象
3.4、元类下的属性查找
"""
type
|
6
|
Mymeta
|
5
|
Teacher ——2——> Foo ——3——> Bar ——4——> object
|
1
|
obj.n
"""