Python(面向对象)

目录

一、面向对象编程

1、定义类

2、调用类生成对象

3、属性查找与绑定方法

二、封装

1、定义

2、隐藏属性

3、@property装饰器

三、继承

1、定义

2、实现继承

3、属性查找

3.1、单继承下的属性查找

3.2、菱形问题与MRO介绍

3.3、非菱形下的属性查找

3.4、广度优先(python3)

4、mixins机制

5、组合

 四、多态

1、多态思想

2、python推崇的是鸭子类型

 五、面向对象高级

1、反射

2、内置方法

3、元类

3.1、元类介绍

3.2、class机制分析

3.3、定制元类控制类的产生

3.4、元类下的属性查找


一、面向对象编程

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
"""
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值