面向对象

面向对象

一:面向过程

  是一种编程思想。将一个复杂的问题流程化(为其制定一个固定的实现流程),从而变得简单化

  优点:复杂的问题简单化

  缺点:由于实现流程固定,一旦中间步骤发生了修改,将导致整体都需要修改

     牵一发而动全身,扩展性差,维护性差

  使用场景:对扩展性要求较低的软件,比如系统的内核,脚本程序(比如运维工程师写的程序,其目的就是安装一个程序)Apache HTTP服务器

二:面向对象(OOP:Object Oriented Programing的简称,就是面向对象的缩写)

  是一种编程思想,即编写代码的方式方法。将程序看作是一堆对象的集合,实现功能的方式就是对象之间交互来实现。

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

  1.什么是对象?

    一切皆对象

    对象指的是,具备某些特征和技能的结合体,是实实在在存在的具体物体(描述完之后就能立刻找到对应的物体)

  2.什么是类?

    类就是类型、对象

    类是一个抽象概念,不是实际存在的,是根据一些具备相同特征和技能的对象抽取得到的,比如说人类。

    类的作用:用于标识对象与对象之间的不同,通过类就能大致了解一个对象的特征和行为

    类与对象之间的关系:

      类包含了一系列相同特征和技能的对象

      对象属于某个类的实例

  3.先有类还是先有对象?

    在生活中先有对象再根据对象的特征和技能得到一个类型,但是,在程序中先有类,才能通过类来产生对象,要先确定具备什么特征和什么行为才能产生对象。

  优点:

    1.不用考虑繁琐的实现步骤,从一个操作工变成了boss

    2.扩展性高,当需要一个新功能时,添加一个具备新功能的对象,命令他去完成任务

    3.各个对象之间耦合度低,当一个对象出现问题不会对其他对象产生影响

    4.可维护性高

  缺点:

    1.面向对象的复杂度比面向过程高

    2.无法预测执行结果,就像LOL游戏过程,一定不能把过程写死,每个英雄的行为都是不固定的

  4.使用场景

    当需要较高的扩展性时(直接与用户发生交互的程序例如qq,微信)

    对于不需要扩展的程序而言,使用面对对象反而增加了复杂度

面向对象编程的本质就是使用不同的对象来完成程序。

  5.使用方法

    注意:类名要按照大驼峰的方式来书写(ThisIsPerson每个单词的首字母都大写)

    在类中描述对象的特征和行为:   

class Person:
    # 用变量来描述特征
    name = "李四"
    sex = "man"
    age = 20

# 得到对象 通过调用类 ,也称之为实例化 或 创建对象
obj = Person()
print(obj)
#<__main__.Person object at 0x00000279452B7C50>
# 模块名为main 其包含一个Person类 通过Person类产生了一个对象 地址为0x00000279452B7C50
# 这是一个Person类的对象 其地址为0x00000279452B7C50

# 使用对象的属性(说的就是特征)
print(obj.name)
print(obj.age)
print(obj.sex)
class Student:
    name = "盖伦"
    sex = "man"
    age = 18
    # 学生的学校 由于每个学生的学校都是相同 所以将其放到类中
    school = "Tsinghua"

# 创建了两个学生对象
stu1 = Student()
stu2 = Student()
print(stu1)
print(stu2)
# 每个对象内存地址都是不同的 , 在创建对象时,计算机会申请一个新的内存空间,并将对象中的内容存进去
print(id(stu1.name))
print(id(stu2.name))
# 由于name的值时声明在类中的,所以每个对象使用的都是同一份
print(stu1.name)
print(stu2.name)
# 为对象单独制定属性
stu1.name = "韩信"
stu2.name = "陈大炮"
print(stu1.name)
print(stu2.name)
# 每个对象的name属性都不同,则意味需要给每个对象单独指定name

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

# 通过__dict__可以获取一个对象中包含的内容
stu1.age = 30
print(stu1.__dict__)
print(stu2.__dict__)

# 获取类中包含的内容
print(Student.__dict__)
类与对象

  6.属性的访问顺序

    当对象中不存在时会到类中去查找,如果对象中存在这个属性,优先访问对象中的属性。

    查找顺序为:对象——>类

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

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

      类还有另一个作用,就是:作为对象的模板,所有属于同一类的对象,都具备类中的公共内容。

      即使我们什么都不写,类中也存在一些自带的属性,是从父类得到的。

  7.初始化函数

    init用于初始化对象,它会在创建对象时,自动执行,并传入调用类时传递的参数,第一个参数表示要初始化的对象本身。

    self(第一个)参数不需要手动传递

    self表示对象自己,是一个形式参数,名字可以随便取,但是不建议修改。

# 作为一个人 一旦出生 性别必须要指定
# 带有__开头__结尾的函数 是一些特殊内置函数,会在某个时间点自动触发执行
class Person:
    # 初始化函数名称是固定  该函数会在调用类是时自动执行,self参数必须有,表示要进行初始化的对象,系统会自动传值
    def __init__(self,name,age):
        self.name = name
        self.age =age

p1 = Person("小仙女",18)
p2 = Person("张艺兴",20)
print(p1.__dict__)
print(p2.__dict__)

  8.绑定方法

    绑定方法就是把对象和函数进行绑定。那么,调用函数就变成了调用对象的方法。

    对象本质上就是一种存放数据的容器,函数就是用于处理数据的代码,绑定方法就是将数据与处理数据的函数绑定到一起

class Student:
    school = "BeiJing"
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age
    def learning(self):
        print("正在学习..")
    def sayHI(self):
        print("hello my name is %s my age:%s my sex:%s" % (self.name,self.age,self.sex))
    # 默认情况下 在类中定义的函数都是绑定方法,共同点是,都会将对象作为第一个参数self
stu1 = Student("一个学生","man",18)
stu1.sayHI()

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

print(stu1.sayHI)
#<bound method Student.sayHI of <__main__.Student object at 0x000001784F889C50>>
# 这是一个绑定方法,本质上是Student类中的sayHI函数 现在把这个函数绑定给了地址为0x000001784F889C50的对象
stu2 = Student("李四","",19)
stu2.sayHI()
print(stu2.sayHI)
如何绑定

只要拿到对象,就同时拿到了数据和处理数据的方法。

       为什么要绑定?

    问题一,传递参数必须手动传递,很有可能在传参顺序发生错误

    问题二,当要处理的数据特别多时就不能再定义为变量了,你可以使用列表存储需要处理的数据,但是每次处理都需要先获取数据,再传递给处理数据的函数。所以要将处理的数据与处理数据的函数进行绑定。简化代码,提高效率。

class Student:
    school = "beijing"
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
#绑定方法分为两种 一种是绑定给对象的,一种绑定给类的。
# 绑定给类的方法 使用一个装饰器叫classmethod,必须有一个参数,表示当前类,参数名也可以自己定义,建议不要修改
   
    # 这是绑定给类的方法
    @classmethod
    def print_school(cls):  # 输出类里面叫school的属性
        print(cls.school)

    # 这是绑定给对象的方法
    def sayHello(self):
        print(self.name, " 说: 你好")
类的绑定方法,对象和类都能调用,并且能够自动传入这个类
 Student.print_school()  #类的调用

stu1 = Student("印度阿三","woman",20) #对象的调用
stu1.print_school()

注意:

  对象绑定方法可以使用对象来调用,也可以使用类名来调用,在对象调用时会自动传入对象自己,类调用时不会自动传参。

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

# 有一个Dog类  每一个Dog对象都应该会叫 会跑  请用面向对象来完成
class Dog:
    def __init__(self,nikename,gender,age):
        self.nikename = nikename
        self.gender = gender
        self.age = age

    def run(self):
        print("不好了 ",self.nikename,"跑了 ")

    def bark(self):
        print("",self.nikename,"在瞎叫...")

d1 = Dog("大金毛","母的",2)
d2 = Dog("大黄","公的",3)

d1.run()
d2.bark()
练习

类的绑定方法和对象的绑定方法的相同与不同:

  相同点:

    1.都会自动传值

    2.都可以被类和对象调用

  不同点:

    1.对象绑定方法在对象调用时,传的是对象自己,而类绑定方法中传的是类自己

    2.第一个参数,一个叫cls,一个叫self

  9.非绑定方法

  在类中,即不绑定给类也不绑定给对象。

  特点:

    没有自动传入参数的效果,类和对象都能调用,就是一个普通函数。但是当你的这个功能不需要访问类的数据,也不需要访问对象的数据,就可以作为一个非绑定方法。

class Teacher:
    def __init__(self,name,sex):
        self.name = name
        self.sex = sex

    # @staticmethod 用于定义个非绑定方法
    @staticmethod
    def test_func(num):
        print("test_func run!")
        print(num)

Teacher.test_func(1)

t1 = Teacher("矮根","")
t1.test_func(100)
print(t1.test_func)
非绑定方法
原文地址:https://www.cnblogs.com/liuxiaolu/p/10116105.html