Python之面向对象编程

博客围绕Python编程展开,介绍了两大编程思想——面向过程和面向对象。阐述了类的定义和对象的产生,强调Python中先有类才能产生对象,还提及类在定义阶段执行类体代码及局部名称空间情况,最后提到属性的查找顺序。

一、面向编程思想

首先在编程中,有两大编程思想,两大范式分别是 面向过程、面向对象
这两大范式是新的技术吗?不是一门新的技术栈,它只是一种编程思想

'''
面向过程编程:
    过程即流程 面向过程就是按照固定的流程解决问题
    eg:截止到模块与包知识内容使用的几乎都是面向过程编程
        如:注册、登录、转账等
        需要按照指定的每一步步骤来依次执行,并随着步骤的深入,问题的解决越来越简单
        提出问题>>>>:指定出该问题的解决方案
    '得出面向过程编程可以把复杂的问题简单化、进而流程化,但是拓展性一般,牵一发而动全身'

面向对象编程:
    在生活中:对象就是‘特征’与‘技能’的结合体
    在程序中:对象就是盛放数据‘属性’和‘方法’的结合体
    # 属性简单理解为就是变量,而方法就是函数,或者叫功能
    
    对象即容器 数据与功能的结合体(在python中一切皆为对象)
        eg:游戏人物。。。
        面向对象编程有点类似于造物主的感觉,我们只需要创造出该人物以及人物具备的功能
        至于该对象后续战绩如何与程序员无关
    ‘得出面向对象编程拓展性较强,不过编程复杂度变高了’
'''
面向过程编程相当于让你给出一个问题的具体解决方案
面向对象编程相当于让你创造出一些事物之后不用管

上述两种编程思想没有优劣之分,仅仅是使用的场景不同
甚至于很多时候是两者混合使用,只不过占比不同

1.面向过程

'''
做一个简约注册功能,来体会一下面向过程:
    我们都知道注册需要有用户名、密码,
    有了用户名和密码需要检验是否符合规则,
    最后给数据写入到文件中。
'''
# 我们把所有的功能都用一个个的函数封装起来
# 输入的用户名和密码
def register():
    username = input('username>>>:').strip()
    password = input('password>>>:').strip()

    return {
        'username': username,
        'password': password,
    }


# 用来检验符合规定
def inspect(userinfo):
    # 这里做一个标志位,为了到时候检验不合格提示,不然会一直走
    yan = True
    # 这里我就只做一个大概的验证即可,具体可自行添加
    if len(userinfo.get('username')) == 0:
        yan = False
        print('当前用户名为空!')
    if len(userinfo.get('password')) == 0:
        yan = False
        print('当前密码为空!')

    return {
        'userinfo': userinfo,
        'yan': yan
    }


# 检验完成后,输出到文件中
def standard(yanz):
    # 当验证不合格的时候提示
    if yanz.get('yan') == False:
        print('用户名或密码不合格!')
    else:
        # 验证通过的时候,写入到文件中
        with open(r'userinfo.txt', 'w', encoding='utf-8') as f:
            import json
            json.dump(yanz.get('userinfo'), f, ensure_ascii=False)

        print(f"用户注册成功!")


def main():
    userinfo = register()
    yanz = inspect(userinfo)
    standard(yanz)


if __name__ == '__main__':
    main()

2.面向对象

'''
做一个简约的选课系统来一步步推导面向对象
'''
'最初版本'
# 首先是一个学生的大概信息
stu_name = 'jack'
stu_age = 18
stu_gender = 'male'
stu_courses = []

# 学生名称、科目名称
def choose_course(stu_name,stu_courses,course):
    stu_courses.append(course)
    print(f"{stu_name}选课成功!科目为:{stu_courses}")

choose_course(stu_name,stu_courses,'python')  
# 得到的结果:jack选课成功!科目为:python

'如果多个学生就需要多个相同的参数来,如:'
stu_name1 = 'tom'
stu_age1 = 20
stu_gender1 = 'male'
stu_courses1 = []
choose_course(stu_name1,stu_courses1,'linux')  
# 得到的结果:tom选课成功!科目为:linux

这样容易搞混淆,我们可以把每一个学生都弄成一个字典的形式来表现出来
'''版本2,把学生信息都整合成一个个的字典'''
# 每个学生的大概信息
stu1_dict = {
    'name': 'jack',
    'age': 18,
    'gender': 'male',
    'courses': []
}

stu2_dict = {
    'name': 'tom',
    'age': 20,
    'gender': 'male',
    'courses': []
}
# 选课
def choose_course(stu_dict,course):
    stu_dict['courses'].append(course)
    print(f"{stu_dict.get('name')}选课成功!科目为:{stu_dict.get('courses')}")

choose_course(stu1_dict,'python')  # 得到的结果:jack选课成功!科目为:python
choose_course(stu2_dict,'linux')  # 得到的结果:jack选课成功!科目为:linux

'''
版本2的虽然优化了,但是面向对象在程序中是由属性和功能的结合体,
现在缺少了选课功能
'''

'''版本3,给每一个学生字典中添加上选课功能'''
def choose_course(stu_dict, course):
    stu_dict['courses'].append(course)
    print(f"{stu_dict.get('name')}选课成功!科目为:{stu_dict.get('courses')}")


stu1_dict = {
    'name': 'jack',
    'age': 18,
    'gender': 'male',
    'courses': [],
    'choose_course': choose_course,
}

stu2_dict = {
    'name': 'tom',
    'age': 20,
    'gender': 'male',
    'courses': [],
    'choose_course': choose_course,
}

# 接下来就直接调用每个学生字典中的选课功能来选课
stu1_dict['choose_course'](stu1_dict, 'python')  
# 得到的结果:jack选课成功!科目为:python
stu2_dict['choose_course'](stu2_dict, 'linux')  
# 得到的结果:jack选课成功!科目为:linux
'''这样一个简约的面向对象就制造出来了'''

'''
其实版本3中对于面向对象的表现,还是不完全是,因为每个学生信息本质上也是独立的,
不算通用的,所以也可以优化一下
'''
def choose_course(stu_dict, course):
    stu_dict['courses'].append(course)
    print(f"{stu_dict.get('name')}选课成功!科目为:{stu_dict.get('courses')}")

# 数据属性和功能的结合体
Student = {
    'school': '北京大学',
    'choose_course': choose_course,
}

stu1_dict = {
    'name': 'jack',
    'age': 18,
    'gender': 'male',
    'courses': [],
}

stu2_dict = {
    'name': 'tom',
    'age': 20,
    'gender': 'male',
    'courses': [],
}

# 接下来就直接调用同属北京大学的选课功能的学生来选课
Student.get('choose_course')(stu1_dict, 'python')  
# 得到的结果:jack选课成功!科目为:python
Student.get('choose_course')(stu2_dict, 'linux')  
# 得到的结果:jack选课成功!科目为:linux
# print(stu2_dict.get('courses'),stu1_dict.get('courses'))

二、类的定义和对象的产生

1.对象与类的概念

'''
什么是对象,什么是类?
    1.对象:是数据属性与功能的结合体
    2.类:是一系列相似的数据属性与功能的结合体
    通俗的说类就是一些列相同数据属性和功能的对象的结合体
'''

'''
问题来了,到底是先有对象还是先有类呢?
    1.在生活中:
        先有人,再有人类(群体),那么就是先有对象(人),在有类(群体)
    2.程序中:
        '一定是先有类,然后调用类,产生对象!'
'''

2.类与对象的创建

面向对象并不是一门新的技术,针对面向对象设计的新语法格式
python中一定是先有类,才能借助类调佣产生对象

2.1、语法格式

'''
# 语法格式
    class 类名():
        类体公共数据属性
        类体公共功能
    
1.用关键字class定义类
2.类名的命名与变量名几乎一致,需要首字母推荐大写(用于区分)
3.数据:变量名与数据值绑定(变量名=变量值),功能(方法)其实就是函数


函数的函数名后面的小括号不能取消,但是类名后面的小括号是可以去掉的,
但是不建议去掉,后续会有作用
'''

2.2、类的定义与调用

类在定义阶段就会执行类体代码,但是属于类的局部名称空间,外界无法直接调用

	class Student():
    # 类体 公共数据属性
    school = '哈佛大学'

    # 类体公共功能
    def choose_course(self):
        print('学生选课功能')

    print('hello')

'''
类体函数如果不调用时,是不会执行函数体代码。
定义类完成后发生了哪些事情?
    1.类一旦完成定义,会立马执行类体代码
    2.会产生类的名称空间,其实就是一个大字典,然后把类中得名字都丢到类的名称空间中。
    3.把类的名称空间绑定给 类名.__dict__中
'''

'''查看名称空间的方法'''
print(Student.__dict__)  # 查看类体所有名称空间,是以字典的形式返回
print(Student.__dict__.get('school'))  # 使用字典的取值方式,获取名字
print(Student.__dict__.get('choose_course'))  # 使用字典的取值方式,获取名字

'''在面向对象编程中,类和对象访问数据或者功能,可以采用句点符号'''
print(Student.school)  # 哈佛大学
print(Student.choose_course)  
# <function Student.choose_course at 0x0000011C0E22A940>

'''
类实例化产生对象>>>>类名加括号就会产生对象,
并且每执行一次就会产生一次全新的对象,
并且产生的对象之间都是互相独立的,互不影响
'''
# 类名加括号>>>>对象
stu1 = Student()  # <__main__.Student object at 0x000001F792F16B50>
stu2 = Student()  # <__main__.Student object at 0x000001F792F16AF0>
print(stu1, stu2)  # 变量名stu1接收类名加括号之后的返回值

# 通过对象.__dict__得到的是空字典,这个并不是真正的字典
print(stu1.__dict__,stu2.__dict__)  # {} {}目前对象是空的

# 通过对象点类内的变量名 >>>得到的是类内变量名绑定的数据值
print(stu1.school)  # 哈佛大学
print(stu1.choose_course)  # 拿到类的公共功能函数体代码

# 类名修改类体代码中的变量名绑定的数据值
Student.school = '北京大学'  # 修改类体变量名对应的数据值
Student.name = 'test'  # 如果类体不存在此变量名时则添加
print(stu1.school)  # 北京大学
print(stu1.name)  # test
print(Student.__dict__)

'''我们习惯将类或者对象句点符号后面的东西称为属性名或者方法名'''

3.定制对象的独有数据

在默认情况下,调用类产生一个对象,它是一个空对象,没有一个数据
因此,我们需要给每一个对象添加数据

'''只是定义类'''
'''推导流程1,手动将每个对象添加独有数据'''
class Student():
    # 类体公共数据
    school = '哈佛大学'  # 其实就是变量名对应的变量值(数据值)

    # 类体公共功能
    def choose_course(self):
        print('学生选课功能')

stu1 = Student()
stu2 = Student()
print(stu1, stu2)
# 查看对象名称空间
print(stu1.__dict__, stu2.__dict__)  # {} {} 
# 对象与对象之间是互相隔离的,互不影响的
'''我们需要给空对象定制自己的独有属性'''
# 不推荐用双下dict开头的属性、功能等
# stu1.__dict__['name'] = 'jack'
# stu1.__dict__['age'] = 18
# stu1.__dict__['gender'] = 'male'

# 推荐使用:点语法
stu1.name = 'jack'
stu1.age = 18
stu1.gender = 'male'
print(stu1.__dict__)  # {'name': 'jack', 'age': 18, 'gender': 'male'}

'''推导流程2,将添加对象独有数据的代码封装成函数'''
def init(stu_obj,name,age,gender,course=None):
    if course is None:
        course = []
    stu_obj.name = name
    stu_obj.age = age
    stu_obj.gender = gender
    stu_obj.courses = course

init(stu1,'jack',18,'male','python')
init(stu2,'tom',20,'male','linux')
print(stu1.__dict__) # {'name': 'jack', 'age': 18, 'gender': 'male', 'courses': 'python'}
print(stu2.__dict__) # {'name': 'tom', 'age': 20, 'gender': 'male', 'courses': 'linux'}


'''推导流程3,给学生对象添加独有数据只有学生才能调用'''
class Student():
    # 类体公共数据
    school = '哈佛大学'  # 其实就是变量名对应的变量值(数据值)

    # 类体公共功能
    '''它有特殊含义,在类里面必须叫__init__,然后调用类的时候才会触发执行'''
    '''
    类里面一定要用这个吗,不一定非要用这个,也就是说你如果需要提前定制对象的属性
    你就写这个方法,如果不需要就不写,可以自定义
    '''
    def __init__(self, name, age, gender, course=None):
        self.name = name
        self.age = age
        self.gender = gender
        self.courses = course

'''调用类的时候有__init__功能的,它会把调用对象自己当成第一个参数传给__init__方法'''
stu1 = Student('jack', 18, 'male', 'python')
# {'name': 'jack', 'age': 18, 'gender': 'male', 'courses': 'python'}
stu2 = Student('tom',20,'male','linux')
# {'name': 'tom', 'age': 20, 'gender': 'male', 'courses': 'linux'}

print(stu1.__dict__, stu2.__dict__)

三、属性的查找顺序

'''
属性的查找顺序分为两大类
类属性:在类里面定义的属性就是雷属性
对象属性:就是对象自己独有的属性
'''

class Student():
    school = '北京大学'

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


stu = Student('jack', 18)

'''类的'''
# 1.查找
print(Student.__dict__)
print(Student.__dict__['school'])  # 北京大学
print(Student.school)  # 北京大学

# 2.增加
Student.x = 'xxx'
Student.z = 666
print(Student.__dict__)

# 3.改
Student.school = '哈佛大学'
print(Student.__dict__)
print(Student.school)  # 哈佛大学

# 4.删除
del Student.z
del Student.x
print(Student.__dict__)

'''对象的增删改查'''
# stu.name = 'jack'
# stu.age = 19
print(stu.name)  # jack
print(stu.age)  # 19
print(stu.school)  # 哈佛大学
# print(stu.__dict__['school'])  # 使用__dict__会报错
'''
如果使用的是点语法,那么,对象查找属性的时候,先从对象自己的名称空间中查找,
查找不到,就去产生这个对象的类中去查找

如果使用的是__dict__取值,只能够取到对象自己名称空间中的属性,不会去类中查找
'''

print(stu.__dict__)

# 增加
stu.x = 666
print(stu.__dict__)  # {'name': 'jack', 'age': 18, 'x': 666}

# 改
stu.x = 888
print(stu.__dict__)  # {'name': 'jack', 'age': 18, 'x': 888}

# 删除
del stu.x
print(stu.__dict__)  # {'name': 'jack', 'age': 18}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值