• 面向对象编程 类 后补充了元类 和单例


    1.面向过程编程(概念:)
    核心是"过程"二字,过程指的是解决问题的步骤,即先干什么再干什么
    基于该思想编写程序就好比在编写一条了流水线,是一种机械式的思维方式

    优点:复杂的问题流程化,进而简单化

    缺点:可扩展性差 现今社会客户的需求千变万化 对扩展性要求较高‘

    使用场景:不需要扩展 或者是随扩展性要求不高,例如:linux内核,shell,
    脚本

    案例:工厂流水线

    面向过程中我们关注的点,完成这个任务 具体的步骤 一步一步去完成

    2.面向对象:
    也是一种编程思想,什么是对象(在现实生活中实实在在存在的,具备自己特
    征和行为的事物,反过来说 对象就是特征和技能的结合体)

    如何来区分,如果能够精确的找到一个十五,他就是一个对象

    核心"对象"二字,对象指的是特征与技能的结合体

    基于该思想编写程序就好比在创造一个世界,你就是这个世界的上帝,是一
    种上帝式的思维逻辑

    优点:可扩展性强

    缺点:编程的复杂度高于面向过程

    面向对象编程:我们关注的点是,使用什么样的对象可以完成我的任务
    例如:把大象装进冰箱,什么样的对象可以帮我完成这个任务;只要找到这个
    这个对象,命令它来做事情,你从一个操作者 ,例如:西游记中如来完成传经的任务,
    所以找了唐僧几个对象来完成

    优点:1.对于指挥者(程序员)来说 不需要再关心具体的步骤
    2.扩展性,一个单独的个体的特征或者行为发生变化时 不会影响他人

    缺点:1.程序的复杂度变高,你首先需要设计出这些对象。注意:要避免一个过度设计
    的问题
    2.对程序的执行结果的可控性降低











    3.类与对象:

    类就是分类 类型的意思
    定义:一堆具备相同特征和行为的事物的抽像概念,不实际存在的

    生活中:类怎么来的,是通过对象特征和行为抽取而来的,所以先要有对象再有类

    编程中:必须要先有类,才能有对象,因为你必须先告诉程序,你这个对象有什么样的特征
    和行为

    类的作用:用于描述该类的对象具备什么样的特征和行为


    4.python中的类
    类的定义及其使用
    #yufa :class关键字 类名
    #类名规范 大写开头 驼峰命名法
    class SH01dboyStudent:
    #描述该类对象的特征
    school="上海01dboy"
    name="agon"
    age=18
    gender="unlnow"
    #在定义阶段
    #只要包含该类的py文件被执行 首先创建类的名称空间
    #执行代码 将产生的名臣俄国放入名称空间
    print("=============")

    #描述该类对象的行为 通过函数
    def say_hi(self):
    print("hello oldBoy")


    #使用类中的属性
    print(SH01dboyStudent.__dict__)
    print(SH01dboyStudent.name)
    #使用类中的函数
    print(SH01dboyStudent.say_hi)
    #使用类直接调用类中的函数时 与嗲用普通函数没有任何取别 self仅
    #仅是位置参数
    SH01dboyStudent.say_hi(10)


    5.创建对象和对象属性
    对象中不许有一个指向类的名称空间的地址(如果自己里有 就拿自己的 没有就去找类中的)

    #创建对象
    #语法在类名后加括号 与调用函数写法相同
    stu= SH01dboyStudent()
    #访问对象属性
    print(stu.school)
    print(SH01dboyStudent.school)
    #修改属性值
    stu.school="北京01dboy"
    print(stu.school)
    #增加属性
    stu.room_num=1008
    print(stu.room_num)
    #删除属性
    del stu.room_num
    print(stu.room_num)

    #对象与类的名称空间是独立的
    stu.school="北京01dboy"
    stu.room_num=1008
    print(stu.__dict__)
    print(SH01dboyStudent.__dict__)

    #如果对象的属性是相同的就应该放到类中 作为一个公共的数据
    stu.school

    #对象的属性查找顺序
    #对象自己的名称空间==>类的名称空间
    syul=SH01dboyStudent()
    syul.school="深圳01dboy"
    print(syul.school)
    print(syul.__dict__)


    class Dog:
    #作为一只狗 应该有昵称 age color gender
    #但是不能写到类中 因为每个狗是不一样的


    #__init__称之为初始化函数 它会在创建对象的时候自动执行
    #创建对象时
    #1.创建一个空对象
    #2.执行__init__函数 并且自动传入了这个对象

    #该函数的作用,就是为对象的属性赋初始值
    def __init__(self,name,color,age,gender):
    print("狗的颜色__init__执行了")
    print(a,b,)
    print(self)
    self.name=name

    pass
    dog1=Dog()
    print(dog1)
    dog1.name="大黄"
    dog1.age="1"

    dog2=Dog()
    print(dog2)
    dog2.name="二哈"
    dog2.age="2"

    #在创建对象时,传入参数
    #类内部定义的函数 其实是给对象使用的 而且是绑定给对象用 绑定给不同的对象就是不同的绑定方法
    dog1=Dog("大黄","黄色",2,"female")
    print(dog1.__dict__)
    #绑定方法的特殊之处在于,谁来调用 就会将随当作第一个阐述自动传入
    dog2=Dog("二哈","白色",1,"female")
    print(Dog(dog2))


    #1.使用场景 需要为每一个对象定制不同的属性值
    #2.__init__在创建对象后自动执行
    #3.第一个self参数 指的是这个对象本身 不需要手动传值

    #类的调用
    Dog.sheep(10)
    #对象调用
    dog1.sheep()
    #对于类而言 sleep就是一个普通函数
    #对对象而言 sleep就是一个绑定方法
    #绑定方法是什么’
    #是对象与类中的某个函数的绑定关系 就像生活中 我们都会吃饭 你吃了我不会饱 不同的对象绑定关系的方式也不同
    #问什么要把函数进行绑定 因为对象的行为通常都需要访问或修改这个对象的数据,如果没有对象直接调用函数是没
    # 有意义的 在函数中是访问不到对象的数据 所以将函数和对象进行了绑定

    #在使用绑定方法时 不需要关心self参数 会自动将这个对象进行传参





    补充&修改:

    上节课复习:
    1.什么是面向对象编程:
    是一种编程思想,核心是对象二字,对象是特征与技能的结合体,基
    于该思想编写程序,就好比创造一个世界,世界是又一个个具体存在
    的对象组成的,你就是这个世界的上帝,这一种上帝式的思维方式。
    优点:扩展性强
    缺点:编程的复杂度要高与面向过程

    2.类:
    对象是特征和技能的结合体,类则是一系列对象相同的特征与技能的
    结合体
    在现实世界中,先有一个个具体存在的对象,然后随着人类文明发展
    总结出的类
    在程序中一定先定义类,先调用类来产生对象


    面向对象是相对于面向过程更高程度的一种封装

    3.老男孩选课系统:
    在现实世界中具体存在的对象:
    对象一:
    特征:
    姓名="周铁蛋"
    年龄="38"
    性别="男"
    学校="01dboy"
    技能:
    选课

    对象二:
    特征:
    姓名="美男子"
    年龄="18"
    性别="男"
    学校="01dboy"
    技能:
    选课

    对象三:
    特征:
    姓名="张铜蛋"
    年龄="38"
    性别="女"
    学校="01dboy"
    技能:
    选课

    对象四:
    特征:
    姓名="egon"
    年龄="18"
    性别="男"
    学校="01dboy"
    等级=10
    技能:
    打分
    在现实世界中老男孩学生类
    相似的特征
    学校="01dboy"
    相似的技能
    选课



    class O1dboyStudent:
    #相似的特征
    school="O1dboy"

    def __init__(self,name, age, gender):
    obj.name = name
    obj.age = age
    obj.gender = gender
    #相似的技能
    def choose_course(self):
    print("is choosing course")
    print("=================")

    #类的用途:
    #用途一:类的本质就是一个名称空间,可以对该名称空间进行增删改查
    #用途二:调用类来产生对象
    #1.会产生一个空对象obj
    #2.会触发类中__init__方法,O1dboyStudent。__init__(obj)
    stu1=O1dboyStudent("周铁蛋","38","male")
    stu2=O1dboyStudent()
    stu3=O1dboyStudent()
    """
    stu1.name="周铁蛋"
    stu1.age="38"
    stu1.gender="male"
    print(stu1.__dict__)

    stu2.name="美男子"
    stu2.age="18"
    stu2.gender="male"
    print(stu2.__dict__)

    stu3.name="张铜蛋"
    stu3.age="18"
    stu3.gender="female"
    print(stu3.__dict__)
    """
    # def inie(obj,name,age,gender):
    # obj.name=name
    # obj.age=age
    # obj.gender=gender
    # init(stu1,"周铁蛋","38","male")

    #一切皆对象
    #在python中统一了类与类型的概念
    class Foo():
    pass
    obj=Foo()
    print(type(obj))
    l=list([1,2,3])
    #print(type(l))
    print(l)
    l.append(4)#
    list.append(1,4)
    print(l)
    #绑定方法:
    #在创建对象时,传入参数
    #类内部定义的函数 其实是给对象使用的 而且是绑定给对象用 绑定给不同的对象就是不同的绑定方法
    dog1=Dog("大黄","黄色",2,"female")
    print(dog1.__dict__)
    #绑定方法的特殊之处在于,谁来调用 就会将谁当作第一个参数自动传入
    dog2=Dog("二哈","白色",1,"female")
    print(Dog(dog2))


    #1.使用场景 需要为每一个对象定制不同的属性值
    #2.__init__在创建对象后自动执行
    #3.第一个self参数 指的是这个对象本身 不需要手动传值

    #类的调用
    Dog.sheep(10)
    #对象调用
    dog1.sheep()
    #对于类而言 sleep就是一个普通函数
    #对对象而言 sleep就是一个绑定方法
    #绑定方法是什么’
    #是对象与类中的某个函数的绑定关系 就像生活中 我们都会吃饭 你吃了我不会饱 不同的对象绑定关系的方式也不同
    #问什么要把函数进行绑定 因为对象的行为通常都需要访问或修改这个对象的数据,如果没有对象直接调用函数是没
    # 有意义的 在函数中是访问不到对象的数据 所以将函数和对象进行了绑定

    #在使用绑定方法时 不需要关心self参数 会自动将这个对象进行传参
    
    
    2. 元类:
    元类是什么?
    本质导航也是一个类,元类是用于实例化其他类
    一切皆对象,类也是对象 在使用上与函数对象无区别

    用于创建类的类 叫做元类 都是type
    主要控制类的创建__init__ 类的实例化__call__

    一个类必须具备的内容
    1.类名
    2.基类
    3.名称空间

    通过查看__class__ 可以看到我们定义的类是由type类实例化得来的

    class_name = "Dog"
    bases = (object,)
    pic_dict = {}
    class_body = """
    def __init__(self):
    print("xxxxx1")
    color="red"
    def talk(self):
    print("iiiiii4")
    print(self.color)
    return
    """
    exec(class_body, {}, pic_dict)
    # print(pic_dict)
    c = type(class_name, bases, pic_dict)
    p1=c()
    print(p1.talk())


    在默认情况下 所有的类都是通过type这个元类实例化的
    我们完全可以自己来实例化
    元类的作用?
    用于创建类的类,称之为元类

    举例:
    class MyMetaclass(type):
    #什么时候执行?MyMetaclass 定义一个类是系统会自动去调用元类的
    def __init__(cls,class_name,bases,namepace):
    #既然创建类时 会自动执行该方法 那么完全可以编写些逻辑在init中来控制类的创建
    if not class_name.istitle():
    raise TypeError("类名首字母需要大写!")
    if object not in bases:
    raise TypeError("需要显式继承object类")
    print(cls)
    print(class_name)
    print(bases)
    print(namepace)
    # 当解释器执行到这一行diamante时 自动调用了MyMetaclass
    class Foo(object,metaclass=MyMetaclass):#等同于Foo=MyMetaclass()
    attr=123
    pass



    class Bar:
    def __call__(self,*args,**kwargs):
    print("run call")
    b1=Bar()
    # 在调用对象的时候自动触发执行__call__
    b1()
    # 推到理论 b1是Bar的实例 调用b1 会触发Bar中的__call__
    #Bar 是type的实例 调用Bar 应当触发type中的__call__


    class MyMetaClass(type):
    def __call__(self, *args, **kwargs):
    # 做一个假需求:判断实例化参数是字符串类型
    #isinstance(args[0],str)
    if type(args[0])==str:
    raise TypeError("名字必须是字符串")
    print("12345678")
    # 建立一个self的空对象
    # 这是自定义元类时 必须要有的模板 以保证可以正常实例化产生对象
    obj=object.__new__(self)
    obj.__init__(*args, **kwargs)
    return obj

    class Foo(metaclass=MyMetaClass):
    def __init__(self,name):
    print(name)
    pass
    # 调用类 本质就是在调用__call__其返回值表示实例化得到的对象
    res=Foo(1)
    print(res)
    #调用一个类 创建一个空对象,调用__init__来完成对象的初始化,返回该对象

    #总结:
    #控制类的调用 也就是实例化过程 核心函数元类中的__call__
    #需要注意的是,在__call__中应当先完成基础的逻辑 1.创建空对象 2.执行__init__
    #3.返回该对象
    #在此基础上添加额外的业务逻辑




    #单例模式:
    #是一种设计模式 是设计模式中比较简单的一种
    #指的是 一个类有且仅有一个实例 就叫做单例

    #实现单例 就通过判断是否已经创建过对象

    # 为什么要使用单例这种模式
    #之前在创建对象时 每个对象中的数据不相同 对象实际上数据和处理数据的方法的结合体
    #当对象中的数据是相同的 共享的时候 使用单例

    #例子
    # u1=user("张三",29,"man")
    # u2=user("张三",29,"man")
    # u3=user("张三",29,"man")
    # 可以改写成u3=u2=u1,数据


    # 元类实现单例 就是拦截了元类中的__call__的正常执行 使得创建对象都必须经过自己判断的逻辑
    # 类中的__init__也被拦截了。



    # 很重要的单例模式举例:
    class MyMetaClass(type):
    instance=None
    def __call__(cls, *args, **kwargs):
    if not MyMetaClass.instance:
    #创建一个空对象
    MyMetaClass.instance=object.__new__(cls)
    print("创建了新的播放器!")
    #初始化对象
    MyMetaClass.instance.__init__(*args, **kwargs)
    #返回该对象
    return MyMetaClass.instance

    # 只能由一个播放器实例
    class CDPlayer(metaclass=MyMetaClass):
    def play(self,music):
    print("切换音乐",music)
    def __init__(self,music_name):
    self.music_name=music_name
    #两次实例化对象p1和p2 都是一个
    p2=CDPlayer('往后余生!908')
    p1=CDPlayer('往后余生!')
    p1.play('往后余生!')
    p2.play("二十五点")
    p1.play('离人愁!')



    2. 元类:
    元类是什么?
    本质导航也是一个类,元类是用于实例化其他类
    一切皆对象,类也是对象 在使用上与函数对象无区别

    一个类必须具备的内容
    1.类名
    2.基类
    3.名称空间

    通过查看__class__ 可以看到我们定义的类是由type类实例化得来的

    class_name = "Dog"
    bases = (object,)
    pic_dict = {}
    class_body = """
    def __init__(self):
    print("xxxxx1")
    color="red"
    def talk(self):
    print("iiiiii4")
    print(self.color)
    return
    """
    exec(class_body, {}, pic_dict)
    # print(pic_dict)
    c = type(class_name, bases, pic_dict)
    p1=c()
    print(p1.talk())


    在默认情况下 所有的类都是通过type这个元类实例化的
    我们完全可以自己来实例化
    元类的作用?
    用于创建类的类,称之为元类

    举例:
    class MyMetaclass(type):
    #什么时候执行?MyMetaclass 定义一个类是系统会自动去调用元类的
    def __init__(cls,class_name,bases,namepace):
    #既然创建类时 会自动执行该方法 那么完全可以编写些逻辑在init中来控制类的创建
    if not class_name.istitle():
    raise TypeError("类名首字母需要大写!")
    if object not in bases:
    raise TypeError("需要显式继承object类")
    print(cls)
    print(class_name)
    print(bases)
    print(namepace)
    # 当解释器执行到这一行diamante时 自动调用了MyMetaclass
    class Foo(object,metaclass=MyMetaclass):#等同于Foo=MyMetaclass()
    attr=123
    pass














  • 相关阅读:
    Printing a DataGridView on DotNet Framework
    对比.NET PetShop和Duwamish来探讨Ado.NET的数据库编程模式
    PetShop配置readme
    关于DGVPrinter.cs中的PrintRange
    foobar2000 0.9.5正式版放出
    Another DataGridView Printer
    getline及读文件总结
    C++中文件的读取操作,如何读取多行数据,如何一个一个的读取数据
    vector的clear和swap
    写程序前不需指定数组中的常量,而是动态编译中决定
  • 原文地址:https://www.cnblogs.com/yanhui1995/p/9829611.html
Copyright © 2020-2023  润新知