day14 面向对象基础

1.面向对象编程介绍

1、面向过程编程
核心是过程二次,过程指的是解决的步骤,即先干啥、再干啥、后干啥
基于该思想写程序就在设计一条条的流水线

优点:复杂的问题流程化、进而简单化
缺点:牵一发而动全身,扩展性差

2、面向对象编程
核心是对象二字,对象指的是盛放相关的数据与功能的容器
基于该思想编写程序就是在创造一个个的容器把相关的东西盛到一起

优点:扩展性强
缺点:加大了编程的复杂度
# 版本一

# stu1_name = 'lem'
# stu1_age = 18
# stu1_gender = 'male'
# stu1_courses = []
#
# stu2_name = 'lam'
# stu2_age = 19
# stu2_gender = 'female'
# stu2_courses = []
#
#
# def choose_course(stu_name, stu_courses, course):
#     stu_courses.append(course)
#     print(f'{stu_name}选课成功 {stu_courses}')
#
#
# choose_course(stu1_name, stu1_courses, "python+go开发")
# choose_course(stu2_name, stu2_courses, "linux运维")


# 版本二

stu1_dic = {
    'name': 'lem',
    'age': 18,
    'gender': 'male',
    'courses': [],
}

stu2_dic = {
    'name': 'lam',
    'age': 19,
    'gender': 'female',
    'courses': [],
}


def choose_course(stu_dic, course):
    stu_dic['courses'].append(course)
    print(f'{stu_dic["name"]}选课成功 {stu_dic["courses"]}')


choose_course(stu1_dic, "python+go开发")
choose_course(stu2_dic, "linux运维")


# 版本三

def choose_course(stu_dic, course):
    stu_dic['courses'].append(course)
    print(f'{stu_dic["name"]}选课成功 {stu_dic["courses"]}')


stu1_dic = {
    'name': 'lem',
    'age': 18,
    'gender': 'male',
    'courses': [],
    'choose_course': choose_course,
}

stu2_dic = {
    'name': 'lam',
    'age': 19,
    'gender': 'female',
    'courses': [],
    'choose_course': choose_course,
}

stu1_dic['choose_course'](stu1_dic, "python+go开发")  # 谁来调用就传自己
stu2_dic['choose_course'](stu2_dic, "linux运维")

2.类与对象的定义与使用

# 类 是用来解决对象之间代码冗余问题
class Student:
    """
    学生的类
    """
    school = 'SH'

    def choose_course(self, stu_dic, course):
        stu_dic['courses'].append(course)
        print(f'{stu_dic["name"]}选课成功 {stu_dic["courses"]}')
        
        
# print(Student.__dict__)

# 类定义阶段发生的三件事
# 1、会执行类体代码
# 2、会产生一个类的名称空间,用来将类体代码运行过程中产生的名字都丢进去
# 3、将名称空间的内存地址绑定给类名

# 调用类也发生了三件事
# 1、会创建空对象(调用__new__方法来创建的空对象)
# 2、会自动触发类中__init__函数的运行,__init__(空对象,'lem',18,'male'),完成对象的初始化操作 注意 __init__ 不能有返回值
# 3、返回该对象,赋值给stu1_dic

stu1_dic = Student()
stu2_dic = Student()

# print(stu1_dic.__dict__)
# print(stu2_dic.__dict__)


# 先去stu1_dic.__dict__中找school,没有的话去Student__dict__中找school
# if 'school' in stu1_dic.__dict__:
#     print(stu1_dic.__dict__['school'])
# else:
#     print(Student.__dict__['school'])

# print(stu1_dic.__dict__)
# stu1_dic.choose_course('python+go高级开发')

stu1_dic.name = "lem"
stu1_dic.age = 18
stu1_dic.gender = "male"
stu1_dic.course = []

stu2_dic.name = "lam"
stu2_dic.age = 19
stu2_dic.gender = "female"
stu2_dic.course = []

print(stu1_dic.__dict__)
print(stu2_dic.__dict__)
print(Student.__dict__)

print(stu1_dic.name)
# 类 是用来解决对象之间代码冗余问题
class Student:
    """
    学生的类
    """
    school = 'SH'
    
    def __init__(self, name, age, gender, course=None):
        if course is None:
            course = []
        self.name = name
        self.age = age
        self.gender = gender
        self.course = course

    def choose_course(self, course):
        self.course.append(course)
        print(f'学生{self.name} 选课成功 {self.course}')

3.属性查找

# 类中有两种属性
# 1、数据属性
# print(Student.school)

# 2、函数属性
# print(Student.choose_course)
# Student.choose_course(stu1_dic, 'python+go开发')


# 但是类中的属性其实是为对象准备
# 1.类的属性是直接共享给所有对象用的
print(Student.school, id(Student.school))
print(stu1_dic.school, id(stu1_dic.school))
print(stu2_dic.school, id(stu2_dic.school))

Student.school = 'xx'
print(stu1_dic.school)
print(stu2_dic.school)

stu1_dic.school = 'xxx'
print(Student.school)
rint(stu2_dic.school)

4.绑定方法与非绑定方法

# 2.类的函数属性是绑定给对象用的
print(Student.choose_course)
print(stu1_dic.choose_course)
print(stu2_dic.choose_course)

stu1_dic.choose_course("python+go开发")
stu2_dic.choose_course("linux运维")
class Mysql:
    def __init__(self, ip, port):
        self.id = self.create_id()
        self.ip = ip
        self.port = port

    def tell_info(self):  # 绑定对象,自动传对象本身
        print(f"")

    @classmethod
    def from_conf(cls):  # 绑定类,自动传类本身
        return cls(settings.IP, settings.PORT)

    @staticmethod
    def create_id():  # 不绑定任何对象,单纯的函数
        import uuid
        return uuid.uuid4()


# print(Mysql.from_conf)
# print(Mysql.create_id)
obj = Mysql.from_conf()
# print(obj.create_id)
print(obj.__dict__)
"""
类中定义的函数分为两大类

一:绑定方法:绑定给谁就应该由谁来调用,谁来调用就会将自己当做第一个参数自动传入

绑定给对象

绑定给类

二:非绑定方法:不与任何人绑定,意味着谁都可以来调用,但是无论谁来调用就是一个普通函数 每天自动传参的效果


"""


# class Mysql:
#     def __init__(self, ip, port):
#         self.id = self.create_id()
#         self.ip = ip
#         self.port = port
#
#     def tell_info(self):
#         print(f"")
#
#     @classmethod
#     def from_conf(cls):
#         return cls(settings.IP, settings.PORT)
#
#     @staticmethod
#     def create_id():
#         import uuid
#         return uuid.uuid4()
#
# obj =  Mysql.from_conf()
# print(obj.create_id)
# # print(Mysql.from_conf)
# print(Mysql.create_id)
# obj = Mysql.from_conf()
# print(obj.create_id)
# print(obj.__dict__)



# ===========================

# 隐藏属性

# 隐藏属性的真正目的就是为了不让使用者在类外部直接操作属性

# class People:
#     __country = 'CHINA'
#
#     def __init__(self, name, age):
#         self.__name = name
#         self.age = age
#
#     def __tell(self):
#         print('====tell')
#
#
# obj = People('hin_a', 18)

# print(People.__country)
# print(People.__tell)

# print(obj.__name)

# print(People.__dict__)
# print(obj.__dict__)

# print(obj._People__name)
# print(obj._People__country)
# print(obj._People__tell)


# __开头的属性隐藏有四个夜店:
# 1、并不是真正的隐藏,只是一种语法意义上的变形
# 2、该变形操作只在类定义阶段扫描语法时发生一次,类定义之后__开头属性并不会变形
# 3、该隐藏对外不对内

# class People:
#     def __init__(self, name, age):
#         self.__name = name  # self._People__name = name
#         self.age = age
#
#     def tell(self):
#         print(self.__name)  # self._People__name


# obj = People('hin_a', 18)
# obj.__gender = 'male'
# print(obj.__gender)
# print(obj.__dict__)
# obj.tell()


# 1、隐藏数据属性的目的:为了严格控制某一属性的操作
class People:
    def __init__(self, name, age):
        self.__name = name  # self._People__name = name
        self.age = age

    def get_name(self):
        print("名字:%s"%self.__name)

    def set_name(self, v):
        if type(v) is not str:
            print("名字必须是str类型")
            return
        self.__name = v

    def del_name(self):
        del self.__name

obj = People('hin_a', 18)

# obj.get_name()
# obj.set_name(123)
# obj.get_name()


# 2、隐藏函数属性的目的:隔离复杂度

property的用法

# 用法一

class People:
    def __init__(self, name, age):
        self.__name = name  # self._People__name = name
        self.age = age

    def get_name(self):
        return "名字:%s"%self.__name

    def set_name(self, v):
        if type(v) is not str:
            print("名字必须是str类型")
            return
        self.__name = v

    def del_name(self):
        del self.__name
        print('删除成功')

    name = property(get_name, set_name, del_name)
#
obj = People('hin_a', 18)

# print(obj.name)
# obj.name = 123
del obj.name


# 用法二
class People:
    def __init__(self, name, age):
        self.__name = name  # self._People__name = name
        self.age = age

    @property
    def name(self):
        return "名字:%s" % self.__name

    @name.setter
    def name(self, v):
        if type(v) is not str:
            print("名字必须是str类型")
            return
        self.__name = v

    @name.deleter
    def name(self):
        del self.__name
        print('删除成功')


#
obj = People('hin_a', 18)

# print(obj.name)
# obj.name = 123
# del obj.name

python中一切皆对象