zoukankan      html  css  js  c++  java
  • 上海 day20 -- 面向对象基础

    目  录

    • 面向对象的概念         

                    对比,面向过程的优缺点 以及使用场景

    • 类和对象的概念

    • 如何创建类和对象

    • 初始化方法  __init__

    • 设计属性以及属性的查找顺序

    • 绑定方法与非绑定方法

    • 小技巧:

                快速将导入模块置顶、初始化方法快速赋值

    ATM+ 购物车用到的模块回顾

    os
    
      与操作系统相关,通常用于操作目录,文件路径的处理
    
      之所以使用该模块 视为了路径可以跨平台
    
    sys
    
      指的是解释器相关的,
    
      .path 配置环境变量
    
      argv 接收命令行传入的参数
    
      exit() 退出解释器
    
    json
    
      一种序列化方式,序列化指的是将内存中数据转换为一种中间格式
    
      json最大优势就是可以跨平台,跨语言
    
    hashlib
    
      用于加密, 通常加密的结果无法反解,当然要保证安全需要加盐处理
    
      常用的是MD5这种算法
    
      另一种使用场景就是文件校验
    
    logging
    
      记录日志,日志本质上就是一个文本文件,我么 可以自己来写入 但是太麻烦
    
      logging封装了.
    
      四个核心角色
    
        logger
    
        filter
    
        handler
    
        formatter
    
    time
    
      时间相关的
    
      主要用于获取时间 以及时间格式的转换
    
      time.sleep 让程序休眠一段时间
    View Code

    一、面向对象编程思想 OOP和面向过程

    什么是面向对象

    面向对象是一种编程思想,是前辈们总结出的经验,指导程序员如何编写出更好的程序 ,

    核心是对象,程序就是一系列对象的集合, 程序眼负责调度控制这些对象来交互着完成任务:

     

    面向对象的三大优点

    1.扩展性

    2.灵活性

    3.重用性

     

    缺点:

    1.程序的复杂度提高了

    2.无法准确预知结果

     

    使用场景

    对扩展性要求较高的程序 ,通常是直接面向 用户的,例如:qq,微信

     

    什么是面向过程

    面向过程编程是这一种编程思想,它关注的核心是过程,过程是就是一步一步的执行步骤,既先干啥在干啥

    面向过程的优点

     

    优点:逻辑清晰 , 复杂问题简单化,流程化

    缺点:

     

    缺点: 扩展性差,可维护性差

    使用场景:

    对扩展性要求较低的程序例如:系统内核,git,计算器

     

    记住:不是所有程序都要面向对象,得分析具体需求

     

    二、面向对象中的两个概念:类和对象

    这是OOP中的最核心的两个概念

    既类型,类别 ,是一种抽象概念

    是一系列具备相同特征和相同行为的对象的集合

     

    对象

    就是具体存在的某个事物,具备自己的特征和行为

    对象就是特征和技能的结合体

     

    类和对象的关系

    类包含一系列对象

    对象属于某个类

    在生活中是先有对象再有类

    而在程序中是先有类才能有对象,我们必须先告诉计算机这类的对象有什么特征有什么行为

    总结出一个结论:(面向对象编程的思想步骤)

      在使用面向对象编程时,第一步就是思考需要什么样的对象,对象具备什么样的特征和行为,从而根据 这些信息总结出需要的类型

    三、类和对象的创建

    定义类的语法

    class 类的名称:
        # 类中的内容 描述属性和技能 
        #描述属性用变量
        #描述行为用函数 
    #类名称 书写规范  首先是见名知意 名称是大驼峰命名法  
    #驼峰就是单词首字母大写 , 大驼峰是第一个字母大写,小驼峰是第一个字母小写

    创建对象的语法:

    class Person:
        pass#创建对象 
    p = Person()

    代码示例:常用方法:__dict__ 查看名称空间   __class__ 查看对象所属的类      

    class Student:    # 类的创建
        name = 'aaa'
        age = 12
        print(locals())
    
    s1 = Student()  # 类的实例化   即对象的创建
    print(s1.name)
    
    s2 = Student()
    print(s2.name)
    
    print(s1.__dict__) # 查看对象的名称空间  __dict__  结果是字典形式
    print(s1.__class__)  # 查看对象所属的类  __class__   <class '__main__.Student'>
    print(Student.__dict__)  # 查看类的名称空间

    对象的属性操作

    属性的增删改查
    
    增加属性 
    对象变量名称.属性名称 = 属性值
    ​
    删除属性
    del 对象的变量名称.属性名称 
    ​
    修改 
    对象.属性 = 新的值 
    ​
    查看属性  访问的是对象的所有属性 
    print(对象.__dict__)
    ​
    访问对象的类信息
    print(对象.__class__)

    四、初始化方法 __init__  ******

    什么是初始化方法 __init__?

    用为对象的属性设置初始值的函数。

    初始化方法的引入?

    解释1:因为我们需要对实例化对象的独有属性进行初始化赋值,但是传统的赋值方法很繁琐,

    解释2:在类的实例(对象)化中,一些属性是必须存在的,我们就可以用初始化来完成。

    总结:

    初始化方法,本质上就是一个函数

    特点1: 当实例化 对象时,会自动执行init方法

    特点2:会自动将对象作为第一个参数传入,参数名称位self ,self可以是别的名字,但不建议改

    功能:用户给对象赋初始值

    练习:创建一个类具备几个属性,通过初始化方法来给他设置属性
    
    class Dog:
        def __init__(self,kind,color,age):
            self.kind = kind
            self.color = color
            self.age = age
    ​
    d1 = Dog("二哈","黑白",1)
    d1 = Dog("泰迪","棕色",2)
    ​
    ​
    注意:该函数不能有任何返回值/.... 只能是None  规定如此..

    对象的精髓就是讲数据和处理数据的函数整合到一起 ,这样一来拿到一个对象就同时拿到了需要处理的数据以及处理数据的函数

    小练习:序列化对象练习 -- 注意理解对象是数据和方法的结合体这一概念

    import os
    import time
    import pickle
    
    class Student:
        def __init__(self, name):
            self.name = name
    
        def say_hi(self):
            print('hello i am a student %s' % self.name)
    
        def save(self):
            with open(self.name, 'wb') as f:  # self.name 是实例化的人名,也就是对象的名字
                pickle.dump(self, f)  # 我们存入的是一个对象 self
    
        @staticmethod
        def get_file(name):
            with open(name, 'rb') as f:
                res = pickle.load(f)
                return res     # 返回值拿到的是一个对象
    
    
    stu = Student('jason')
    stu.save()
    stu.say_hi()
    
    res = stu.get_file('jason')  # res 我们存入的对象
    print(res)  # <__main__.Student object at 0x0331BBF0>
    print(res.name)  # jason     res.name 意思访问对象res里面的方法name,
    
    res2 = Student.get_file('jason')  # 类调用
    print(res2.name)

    五、属性的写法和查找顺序

    可以将类中的内容都称之为属性,变量称为数据属性,函数就叫函数属性
    
    类中可以声明变量来表示数据属性,为Student类添加数据属性和函数属性
    
    
    class Student:
        school = "Tsinghua" #数据属性
        
        def say_hello(self):#函数属性
            print("hello i am a student")
        
        def __init__ (self,name): #初始化函数
            self.name = name

    问题引出:属性的查找顺序

    """
    问题1:在类中声明的数据属性和创建对象后为增加的数据属性,有什么区别?
    
    类中的数据属性是所有对象共享的
    
    创建对象后为增加的数据属性,是这个对象特有的,去其他对象无关
    
    问题2:类中声明的数据属性和创建对象后为增加的数据属性,其访问属性是怎样的?
    
    优先查找对象自己的名称空间,如果没有则在类中找,如果类中也没有则到父类中找,直到找到为止,如果父类中也没有则抛出异常
    
    """
     
    练习: 描述一个老师类 需要包含 一个公共属性和 一个独特的属性 
    ​
    class Teacher:
        school = "oldboy"
        
    t1 = Teacher()
    t1.name = "jack"
    t1.age = 28

     六、绑定方法和非绑定方法

    什么是方法?

    先理清方法,函数,技能的关系:

    生活中对象的技能在程序中用函数表示

    函数在面向对象中称之为方法,换种称呼而已!

    如此说来,绑定方法也就是绑定函数

    为什么要绑定?

    在使用面向对象之前,数据与处理数据的函数是独立的没有任何联系,在调用函数时需要手动传入参数,如果要处理的数据有很多,参数的传递就是一个非常麻烦的事情,

    原始的处理方式:函数 传参

    问题1 调用函数时传入参数,如果要处理的数据有很多,编写了很多重复的代码,代码的阅读性很差

    问题2 后期如果每次处理的数据个数变多了,函数需要修改参数列表,导致以前写的所有代码都需要修改,扩展性非常差

    问题3 如果传入了错误的数据,比如需要整型却传入了字符串,造成函数无法正常工作

    绑定方法的处理方式:

    1.调用方法时传入对象,对象中包含了需要的所有数据,减少重复代码

    2.后期数据变化时,修改类对象中的属性,方法中增加相应的处理代码,而方法参数不会发生变化,提高了扩展性

    3.方法与对象进行绑定,没有对象则无法使用方法,并且在创建对象的初始化方法中,已经确定了各个属性数据时正确的,如此一来避免了传入使用错误数据执行函数造成的问题

    简单的说,就是将数据与处理数据的函数绑定在一起,没有数据则根本不需要处理数据的函数,反过来要执行处理数据的函数则必须提供要被处理的数据

    绑定方法

    绑定方法分为:绑定到对象的方法绑定到类的方法

    绑定到对象的方法----也称为‘对象绑定方法’

    提出问题:什么是对象绑定方法?

    '''
    对象绑定方法:需要访问到对象中的方法我们称之为对象绑定方法。就是这个方法需要访问对象本身
    
    '''

    提出问题:为什么要将对象本身自动传参并作为第一个参数?

    """
    对象本身是数据和功能的集合体,为什么会自动传参?因为对象是一个容器,
    里面有数据,一个函数就是用来处理数据的,所以它就自动帮我们传进去了。
    所以类里面的方法默认情况下绑定的就是对象
    """

    默认情况下类中的方法都是对象的绑定方法

    特点:

    当使用对象调用该函数时会自动传入对象本身,作为第一个参数

    当使用类名来调用时他就是一个普通函数,有几个参数就得传几个参数

     

     

    代码示例:

    class Student:
        def __init__(self,name,age,gender):
            self.name = name
            self.age = age
            self.gender = gender
    
        def say_hi(self):
            print(self)   # 谁调用这个函数self就是谁
            print('说点什么%s'%self.name)
    
    stu1 = Student('jack',18,'male')
    stu2 = Student('rose',28,'female')
    
    stu1.say_hi()  # 对象绑定方法调用时不需要再传入参数,它自动将传入对象本身并作为第一个参数。
    # print(stu1)
    # 类调用对象的方法
    Student.say_hi(stu1)  # 结果和print(stu1)是一样的,不同在于用类调用对象方法时需要传入参数对象数stu1
    # 为什么户自动传参,因为对象是一个容器,里面有数据,一个函数就是用来处理数据,所以它就自动帮我们传进去了。

    练习:写一个学生类,具备一个打招呼的技能 要能输出自己的名字信息

    class Student:
       
       def __init__(self,name):
           self.name = name
       
       def say_hi(self):
           print("hello my name is %s" % self.name)

    绑定到类的方法----也叫做‘类的绑定方法’

    提出问题:为什么要用类的绑定方法?

    class OldboyStudent:
        school = 'oldboy'
    
        def __init__(self,name):
            self.name = name
    
        def say_hi(self):
            print('hello i am from %s'%self.school)  # 通过对象直接调用类的属性
    
    stu1 = OldboyStudent('jason')
    # 记住我们直接用类调用对象的属性是必须要传入对象作为参数的
    OldboyStudent.say_hi(stu1)

    答:

    '''
    由上面代码可知:我们要访问类里面的数据  school= 'oldboy'还要传入一个对象是很不合理,
    所以say_hi方法可以不绑定对象,来绑定类。
    方法:在调用的方法上面添加 @classmethod
    '''

    代码改进:使用类的绑定方法

    class OldboyStudent:
        school = 'oldboy'
    
        def __init__(self,name):
            self.name = name
    
        @classmethod
        def say_hi(cls):
            print('hello i am from %s'%cls.school)  # 通过对象直接调用类的属性
    
    stu1 = OldboyStudent('jason')
    OldboyStudent.say_hi()  # hello i am from oldboy  不需要加参数直接调用
    stu1.say_hi()  # 被类绑定的方法无论是用对象调用还是用类调用结果都一样

    绑定类的方法用@classmethod来装饰

    特殊之处:不管用类还是对象调用,都会自动传入类本身,作为第一个参数

    特点:参数的第一个必须是cls表示当前类本身,使用类名来调用,调用时会自动传入类

    什么时候绑定给对象:当函数逻辑需要访问对象中的数据时

    什么时候绑定给类:当函数逻辑需要访问类中的数据时

    绑定到类的方法与绑定到对象的方法总结

    相同点:

    绑定对象调用时都有自动传参的效果

    绑定到谁给谁就由谁来调用

    不同点:

    绑定到类的方法自动传入当前类

    绑定到对象的方法自动传入当前对象

    非绑定方法

    特点:不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说。就是一个普通函数

    (或叫做静态方法,就是即不需访问类的数据,.也不需要访问对象的数据)

    语法:@staticmethod

    代码示例:

    class Student:
        def __init__(self,name):
            self.name = name
    
        @staticmethod   # 非绑定方法的装饰器
        def say():
            print('hello !')
    # 使用类调用
    Student.say()  # hello !
    # 使用对象调用
    stu = Student('jsaon')
    stu.say()  # hello !

    练习:

    """
    l练习:为学生类添加一个save方法 一个get方法
    
        save是将对象存储到文件中      get是从文件中获取对象
    """
    import pickle
    
    class Student:
        def __init__(self, name):
            self.name = name
    
        def say_hi(self):
            print('hello i am a student %s' % self.name)
    
        def save(self):
            with open(self.name, 'wb') as f:  # self.name 是实例化的人名,也就是对象的名字
                pickle.dump(self, f)  # 我们存入的是一个对象 self
    
        @staticmethod
        def get_file(name):
            with open(name, 'rb') as f:
                res = pickle.load(f)
                return res     # 返回值拿到的是一个对象
    
    
    stu = Student('jason')
    stu.save()
    stu.say_hi()
    
    res = stu.get_file('jason')  # res 我们存入的对象
    print(res)  # <__main__.Student object at 0x0331BBF0>
    print(res.name)  # jason     res.name 意思访问对象res里面的方法name,
    
    res2 = Student.get_file('jason')  # 类调用
    print(res2.name)
    练习1
    '''
    最后的小练习--设计王者荣耀的英雄,自定义属性
    '''

     

    小技巧:

    写代码中快速导入模块并置顶:

        写下模块名--->   Alt   + enter +enter

    在__init__方法中为对象快速赋初始值:用于属性较多的情况下

    class Hero:
        
        def __init__(self, name, level, blood, att, q_hurt, w_hurt, e_hurt):
            # 常规写法:
            # self,name = name
            # self.level = level
            # self,blood = blood
            # self.att = att
            # self.q_hurt = q_hurt
            # self.w_hurt = w_hurt
            # self.e_hurt = e_hurt
    
            # 简便写法:
            # print(locals())
            # lcs = locals()
            # lcs.pop("self")
            # self.__dict__.update(lcs)
  • 相关阅读:
    Mybatis全局配置文件
    Mybatis简介及入门
    数据库小结(1)
    Java提高——Java的内存回收(2)
    关于引入文件错误
    Java提高——JUC原子类
    swagger
    Java提高——多线程(五)生产消费者问题
    Java提高——多线程(四)等待、唤醒、线程中断、优先级和守护线程
    战略与战术
  • 原文地址:https://www.cnblogs.com/qinsungui921112/p/11239129.html
Copyright © 2011-2022 走看看