zoukankan      html  css  js  c++  java
  • 20181213(面向对象编程,初步)

     

    一、面向过程与面向对象的编程

    1、面向过程的编程:将复杂问题拆分成若干小问题,按照步骤流程一一解决。也可以说是将复杂问题流程化,为其制定一个固定的实现流程。

    优点:复杂问题简单化

    缺点:可拓展性差,维护性差。一旦某一步骤出现问题,后续步骤可能无法进行。

    应用场景:对扩展性要求较低的软件,如系统内核、脚本程序。

    2、面向对象的编程:OOP(Object Oriented Programming)。将程序看作是一堆对象的集合,通过对象之间交互来实现功能。面向对象编程的本质就是使用不同的对象来完成程序。

    优点:不用考虑实现步骤,从具体的执行者变成指挥者。扩展性高,对象与整体流程耦合度低;对象与对象之间的耦合度也低。可维护性高。

    缺点:相比面向过程,更为复杂,无法预知执行结果。

    应用场景:需要较高的扩展性(直接面向消费级用户的程序)。 对于不需要扩展性的程序,使用面向对象的编程思维反而会使问题复杂。

     

    二、类与对象

    面向对象思想中最核心的概念就是 类与对象:

    对象:一切皆对象,对象指的是具备某些特征与技能的结合体,是具体的物体(如我的手机)。对象本质上就是一种存放数据的容器。

    类:类就是类型、类别、分类。类是一个抽象概念,是一些具备相同特征和技能对象的集合体。

    类与对象的关系:

    类的作用是表示对象与对象之间的相同点,通过类就能大致了解一个对象的特征。

    对象是属于某个类的实例。

     

    在现实世界,先有对象,后有类。

    在程序中,先有类,后有对象。

     

    类名要按照大驼峰的方式来书写,例如 ThisIsPerson 每个单词首字母都大写。在类中描述对象的特征和行为。

    class Person:  # 此处没有括号
       # 用变量来描述共同特征
       name = "alex"
       sex = "man"
       age = 22

    # 得到对象,通过调用类得到对象,也称之为实例化 或 创建对象
    obj = Person()
    print(obj)
    输出结果为:
    <__main__.Person object at 0x00000202FF209400>  #Person类下的一个对象,内存地址是0x00000202FF209400

    # 使用对象的属性(也就是特征)
    print(obj.name)
    print(obj.sex)
    print(obj.age)
    输出结果为:
    alex
    man
    22

    类中的增删查改:

    class Person:  
       name = "alex"
       
    print(Person.name) # 查
    Person.name = "egon" # 改
    print(Person.name)
    Person.age = 22 # 增
    print(Person.age)
    del Person.name  #删

    只要对类的属性进行了修改,就会立刻反映给所有对象,而对象却无需修改。

     

    每个对象的内存地址都是不同的,在创建对象时,计算机会申请一个新的内存空间,并将对象中的内容存进去

    存储属性的位置有两个,分别是类中和对象中. 当每个对象的某个特征都相同时则放到类中. 当每个对象的某个特征都不同时则放到对象中.

    #通过__dict__可以获取一个对象中包含的内容
    print(obj.__dict__)
    # 获取类中包含的内容
    print(Student.__dict__)

    当对象中不存在时,会到类中去寻找,类中没有,就去父类中查找。
    如果对象中存在这个属性,优先访问对象中的属性
    属性查找顺序:对象---->

     

    当创建一个类的时候,会产生名称空间,存储类中的名称和值的绑定关系. 当创建一个对象的时候,会产生名称空间,存储对象中的名称和值的绑定关系.

    类还有一个作用就是作为对象的模板, 所有属于同一个类的对象,都具备类的共同属性.

    即使我们什么都不写,类中也会存在一些自带的属性,是从父类中继承的.

     

    三、初始化函数

    初始化函数应该与类是一个整体,应该将函数放入类中。 通常对象一旦创建就应该进行初始化,创建与初始化进行绑定。

    初始化要用到init方法,该方法是对象产生之后才会执行,只用来为对象进行初始化操作。

    class Person:
       # 初始化函数名称是固定的,该函数会在调用类时自动执行
       # self形参必须有,但会自动获取,无需实参。self名称可自定义,但不建议修改,毕竟约定俗成。
       def __init__(self,name,age):
           print("执行了__init__")
           print(self)  # self就是要进行初始化的对象,系统会自动传值
           self.name = name
           self.age = age

    p1 = Person("alex",33)  #从类Person中获取一个名叫p1的对象,对应的参数是"alex",33
    print(p1.__dict__)  #结果是一个字典

    输出结果:
    执行了__init__
    <__main__.Person object at 0x000001DD789E9400> #类Person下一个对象的内存地址
    {'name': 'alex', 'age': 33}


    __init__方法
    强调:
     1、该方法内可以有任意的python代码
     2、一定不能有返回值

     

    四、绑定方法

    方法的定义:为了方便理解把函数称之为方法。

    绑定方法:绑定方法是把对象与函数进行绑定。调用函数就变成了调用函数的方法。绑定方法就是将数据与处理数据的函数绑定在一起。

    绑定方法分为两种,一种是绑定给对象的,一种是绑定给类的。

    默认是绑定给对象的。

    class Student:  #建立一个Student的类
       school = "BeiJing"  #类的共同属性是学校名叫BeiJing

       def __init__(self,name,sex,age): # 初始化函数,注意参数与定义的方法。
           self.name = name
           self.sex = sex
           self.age = age

       def sayHi(self):  #与函数的初始化同级
           print("hello my name is %s my age %s my sex %s" %(self.name,self.age,self.sex))
       # 默认情况下,在类中定义的函数都是绑定方法,共同点是都会将对象作为第一个参数self。即对象必定要有,并以参数身份传入函数中。


    stu1 = Student("egon","male",22)

    # 当用对象来调用类中的方法时,默认把对象传入方法中
    # 用类名来调用时,则需要手动传入对象
    stu1.sayHi()
    Student.sayHi(stu1)

    输出结果:
    hello my name is egon my age 22 my sex male
    hello my name is egon my age 22 my sex male

    print(stu1.sayHi)
    # 这是一个绑定方法,本质上是Student类中的sayHi函数绑定给了地址为。。。的对象
    # 只要拿到对象,就同时拿到了数据和处理数据的方法
    输出结果:
    <bound method Student.sayHi of <__main__.Student object at 0x000002471E089B38>>

     

    绑定给类的方法:

    使用一个装饰器classmethod,必须有一个参数cls用来表示当前类,参数名可以自定义,但不建议修改(约定俗成,没有理由)。

    class Student:
       school = "BeiJing"

       def __init__(self,name,sex,age):
           self.name = name
           self.sex = sex
           self.age = age

       @classmethod
       def print_school_name(self):
           print("学校名称为:%s" %Student.school)

       @classmethod  # 将此函数绑定给类,参数为cls
       def print_school(cls):
           print(cls.school)

    stu1 = Student("kevin","male",11)
    stu1.print_school()   # 调用的是加了装饰器的函数
    Student.print_school()  # 没有传参,直接调用函数
    输出结果为:
    BeiJing

    Student.print_school_name()
    stu1.print_school_name()
    输出结果为:
    学校名称为:BeiJing
    学校名称为:BeiJing

     

    当要处理的数据包含在类中时,就应该绑定给类。 当要处理的数据包含在对象中时,就应该绑定给对象。

    总结:

    对象绑定方法,可以使用对象来调用,也可以使用类名来调用

    在对象调用时会自动传入对象自己,类调用时不会自动传参

    类的绑定方法,对象和类都能调用,并且都会自动传入这个类

    类的绑定方法和对象的绑定方法的异同点
    相同点:
      1.都会自动传值
      2.都可以被类和对象调用
    不同点:
    1.对象绑定方法在对象调用时,传的是对象自己,而类绑定方法自动传的是类自己.
    2.第一个参数 一个cls 一个是self

     

    五、非绑定方法

    非绑定方法:即在类中的函数,既不绑定给类,也不绑定给对象。 特点:没有自动传参的效果,类和对象都能调用,就是一个普通函数。 应用场景:当你的这个功能既不需要访问类的数据,也不需要访问对象的数据,就可以作为一个非绑定方法。

     

    class Teacher:

       def __init__(self,name,sex):
           self.name = name
           self.sex = sex
       # @staticmethod 用于定义一个非绑定方法
       @staticmethod
       def test_func(num):
           print("run %s" %num)

    Teacher.test_func(1)
    输出结果:
    run 1

     

     

    六、数据存取练习
    import json

    class Student:

       school = "beijing"

       def __init__(self,name,sex,age,classes):  #初始化
           self.name = name
           self.age = age
           self.sex = sex
           self.classes = classes


       def save(self):  # 默认绑定给对象的函数
           dic = {"name":self.name,"sex":self.sex,
                  "age":self.age,"classes":self.classes}  # 需要自己去创建字典
           with open(self.name,"wt",encoding="utf-8") as  f:  # 文件名就是学生名
               json.dump(dic,f)  # 序列化数据

       @classmethod  # 类函数
       def get_obj(cls,name):  # 传入名字,调取储存的数据
           with open(name,"rt",encoding="utf-8") as  f:
               dic = json.load(f)
           obj = cls(dic["name"],dic["sex"],dic["age"],dic["classes"])
           return obj


    stu1 = Student("阿尔法","man",20,"py5期")
    stu2 = Student("张三","woman",20,"py5期")

    stu1.save()
    stu2.save()


    stu = Student.get_obj("阿尔法")
    print(stu)
    print(stu.__dict__)
    print(stu.name)
    输出结果为:
    <__main__.Student object at 0x000001CC57B10940>
    {'name': '阿尔法', 'age': 20, 'sex': 'man', 'classes': 'py5期'}
    阿尔法

     

     

  • 相关阅读:
    关于SDK-manager中我们需要下载哪些?
    不只是撸代码搞鸡汤,也有故事!
    [Selenium]如何通过Selenium实现Ctrl+click,即按住Ctrl的同时进行单击操作
    【设计模式】单例模式
    【Java多线程】线程池学习
    【leetcode】147 Insertion Sort List
    【webssh】shellinabox搭建
    【SpringMVC】一次处理项目中文乱码的经历
    【Java多线程】JUC包下的工具类CountDownLatch、CyclicBarrier和Semaphore
    【leetcode】3 SUM
  • 原文地址:https://www.cnblogs.com/realadmin/p/10116521.html
Copyright © 2011-2022 走看看