面向对象(一)之基本概念

面向对象与面向过程

面向过程的程序设计:核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么…面向过程的设计就好比精心设计好一条流水线,是一种机械式的思维方式。

优点:复杂度的问题流程化,进而简单化(一个复杂的问题,分成一个个小的步骤去实现,实现小的步骤将会非常简单)
缺点:一套流水线或者流程就是用来解决一个问题,生产汽水的流水线无法生产汽车,即便是能,也得是大改,改一个组件,牵一发而动全身。

面向对象的程序设计:核心是对象二字,对象是特征与技能的结合体,基于面向对象设计程序就好比在创造一个世界,你就是这个世界的上帝,存在的皆为对象,不存在的也可以创造出来,与面向过程机械式的思维方式形成鲜明对比,面向对象更加注重对现实世界的模拟,是一种“上帝式”的思维方式。

优点:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
缺点:(1). 编程的复杂度远高于面向过程,不了解面向对象而立即上手基于它设计程序,极容易出现过度设计的问题。一些扩展性要求低的场景使用面向对象会徒增编程难度。(2). 无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法准确地预测最终结果。

类与对象

类是现实世界或思维世界中的实体在计算机中的反映,它将数据以及这些数据上的操作封装在一起。是具有相同特征与行为个体集合的抽象。

对象是有特征、行为的具体个体,就是类的具体体现。

语法:

类的声明:类是抽象的,不是真实存在:具有相同特征(属性)和行为(方法)个体的集合的抽象
'''
class 类名:  # class定义类语法的关键字
    pass
'''
对象的产生: 对象具象的,是真实存在的:具有特征与行为的实际个体(类的实际体现:实例化)
'''
对象1 = 类名()
对象2 = 类名()
对象3 = 类名()
'''

类会随所属文件加载而加载(执行内部所有代码),形成类的名称空间

1.每个实例化出来的对象及类都有自己的名称空间
2.类与对象都可以通过.语法来拓展新功能
3.提前在类中属性的属性与方法,在对象一产生就可以使用这些属性和方法
4.对象查找属性的顺序:先找自身的,如果没有就找类的(只有访问权没有修改权)

对象查找属性的顺序

class People:
    # 类自带(不同在外界额外添加)的属性与方法
    identify = '人类'
    def sleep(self):
        print('睡觉')
p1 = People()
p2 = People()

p1.identify = '新人类'
print(p1.identify)  # 访问自己的
p1.__dict__.clear()  # 删除自己的后
print(p1.identify)  # 访问类的
print(p2.identify)  # p2没有自己的,访问类的
'''
输出:
新人类
人类
人类
'''
重点:属性的访问顺序:优先加载自身的名字,如果没有再考虑类的

名称空间操作

拥有名称空间的对象:就是具有__dict__属性,该属性就是指向对象的名称空间
    -- 文件 |(__init__.py文件) | 函数 |-- 可以为__dict__属性添加值,简化为.语法,也可以对__dict__整体赋值一个字典
    
import re
print(re.__dict__)

re.__dict__['name'] = 're模块'
print(re.__dict__['name'])
'''
输出:re模块
'''
re.__dict__['action'] = lambda x: x
print(re.__dict__['action'](1000))
'''
输出:1000
'''
def fn():
    pass
print(fn.__dict__)
'''
输出:{}
'''
fn.name = 'fn函数'
print(fn.name)
'''
输出:fn函数
'''
def test():
    print("可以成为fn功能的函数")
fn.action = test
fn.action()
'''
输出:可以成为fn功能的函数
'''

对象独有的名称空间: 在产生对象时就赋初值

__ init __ 方法会在实例化对象时被调用
1.会为实例化的对象形成空的名称空间
2.就是一个方法,可以被传参,在 类名(实参) 这种方式下调用并传参 __ init __ (self, 形参)
3.第一个self就是要产生的当前对象
重点:在方法内部,形参拿到了实参值,利用self.属性名 = 形参 = 实参值,对对象的名称空间添加属性

class Student:
    def __init__(self, stu_name, sex):
        self.name = stu_name
        self.sex = sex  # 通常建议参数名与新增的属性名同名

stu = Student('Bob', 'male')  # 实例化对象
print(stu.name, stu.sex)

类中法的第一个默认参数:对象方法

class A:
    # 对象方法
    def test(self, num):
        pass
a = A()

# 调用方法
# 二级优化
a.test(10)
# 一级优化
A.test(a, 10)
# 实现原理
A.__dict__['test'](a, 10)

总结:对象a传递给self,数字10传递给num
重点:方法的第一个参数一定是调用该方法的对象

类中@classmethod修饰的方法:类方法

class Tool:
    @classmethod
    def add(cls, n1, n2):  # 统一类与对象都可以调用类方法,一定有默认传入第一个参数
        return n1 + n2
    
# 建议
Tool.add(10, 20)  # 默认第一个传入自身 - Tool

# 不建议
tool = Tool()
tool.add(100, 200)   # 默认第一个传入自身所属类 - tool.__class__

属性与方法的总结

class Car:
    # 属于类的属性
    name = '车'

    # 属于对象的属性
    def __init__(self, name):
        self.name = name

    # 属于类的方法
    # 需求:获取车的名字
    @classmethod
    def get_class_name(cls):
        return cls.name

    # 属于对象的方法
    # 需求:获取对应车的名字
    def get_school_name(self):
        return self.name

# 先创建校区
publicbus = Car('公交车')
bicycle = Car('自行车')

# 类方法的使用
# 建议使用类调用
print(Car.get_class_name())
# 类方法拿对象调用并没有多少新增的意义,不建议拿对象调用
print(publicbus.get_class_name())
print(bicycle.get_class_name())

# 对象方法的使用
# 类调用对象方法,必须把要操作的对象手动传入,不建议使用
print(Car.get_school_name(publicbus))
print(Car.get_school_name(bicycle))
# 对象调用对象方法,默认将自身传入,建议使用
print(publicbus.get_school_name())
print(bicycle.get_school_name())
'''
输出:
车
车
车
公交车
自行车
公交车
自行车
'''

猜你喜欢

转载自blog.csdn.net/linwow/article/details/89457971