面向对象

1.优缺点:

面向过程:
	核心:过程
    优点:复杂度的问题流程化,进而简单化
    缺点:牵一发而动全身,可扩展性差
    
面向对象:
	核心:对象
    优点:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中。
    缺点:编程的复杂程度提高了;无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果。

2.初识--类:

2.1.模板:

class student:
    print("大傻逼")                                # 类在定义阶段会执行代码
    school = "家里蹲大学"                          #在类里面定义的公有的数据

    def __init__(self, name, age, sex):           #在类调用的时候会执行__init__函数,该函数只能返回None,默认将对象做第一个参数传给self
        self.name = name
        self.age = age
        self.sex = sex

    def info_print(self):                        #在类里面定义的公有的功能
        print(self.school)
        print(self.name)
        print(self.sex)
        print(self.age)
        return True

stu1 = student('egon', 18, '男')     # 实例化:调用类,建一个对象stu1,可以建立无数个对象

print(stu1.__dict__)                 # dict可以查看对象里面的东西,以字典的形式呈现
stu1.money1 = 100                    # 向对象里面添加数据,和stu1.__dict__['money1']=100作用相同
stu1.age=20                          # 修改对象内的数据
print(stu1.__dict__)

print(stu1.school)
stu1.school ="不在家里蹲"            #对象值的查找是先找对象内,没有的话再找class里面
print(stu1.school)

stu1.info_print()                   #调用类的函数属性,执行info_print()函数,相当于student.info_print(stu1)

2.2.内置属性

类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类(在讲继承时会讲)
类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
类名.__dict__# 类的属性,以字典形式呈现
类名.__module__# 类定义所在的模块
对象名.__class__# 实例对应的类(仅新式类中)

2.3.属性查找顺序

#会先从对象自己的名称空间里找,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常。  

3.绑定方法与非绑定方法

3.1绑定方法

# 1.绑定给对象的方法:调用者自动传入对象
# 默认就是这种方法

# 2.绑定给类的方法:调用者自动传入类
# classmethod 提供了一种新的造对象的方法
class fun1:
    @classmethod                   #会自动将类传给from_conf()
    def from_conf(cls):              
        return cls(settings.name)   #从settings文件中导入名字
obj=fun1.from_conf()                #新的实例化方法,相当于obj=fun1(settings.name)

3.2非绑定方法(静态方法):

# 不会自动传参
class fun1:
     @staticmethod         #不会自动传入参数
     def id():
         print("dsfs")
         return True
obj=fun1()
obj.id()                  #调用过程不会自动传递参数

4.类的3大特性:

4.1封装

4.1.1隐藏属性

模板:
class student:
    __school = "家里蹲大学"             #相当于_student__school="家里蹲大学"
    def __inin(self,name):
        self.__name=name               #相当于self._student__name=name
    def __func(self):
        pass
    print(__school)                   #相当于print(_student__school)
    
#1.在属性前面加__即可隐藏属性,无法调用student.school和student.func(),这种转变是在定义阶段统一发生的
#2.但可以通过student._student__school和student._student__func()访问(外部访问)
#3.这种方式的隐藏对外不对内,print(__school) 仍可以执行

意义:
	将数据隐藏起来这不是目的。隐藏起来然后对外提供操作该数据的接口,然后我们可以在接口附加上对该数据操作的限制,以此完成对数据属性操作的严格控制。

4.1.2property

模板1:
class student:
    @property                 #用func替代func()
    def func(self):
        pass
stu1=student()
#1.property是一个装饰器,用func替代func(),可以用stu1.func来调用func()函数。用来修饰一些看上去像数据的功能
#2.只能用在类里面
#3.只能用stu1.func来调用,不能用student.func来调用


模板2:
class people:
    def __init__(self, name):
        self.__name = name

    @property                 #将这三个功能整合给name属性,除了'name'和函数体代码,其它都是固定格式
    def name(self):
        return self.__name
    
    @name.setter              #name.setter不可修改
    def name(self, name):
        self.__name = name
        print(self.__name)

    @name.deleter             #name.deleter不可修改
    def name(self):
        print("不给删")

p1 = people("egon")           #实例化
print(p1.name)                #固定的查看格式
p1.name ='df'                 #固定的修改格式
del p1.name                   #固定的删除格式
#函数的装饰方式和调用方式都是固定的
#本质就是以固定的方式来调用函数体代码,通常用来实现查看,修改,删除功能,但函数体代码可以自定义
#也可以不用装饰器,用name=property(getname,setname,delname)的形式来完成封装,参数是按位置传递的

4.2.继承

4.2.1模板:

class people:            #定义父类,用于存放子类中共同的数据和功能
    school="家里蹲"
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex

class student(people):   #定义子类,并引用父类,python支持多个父类,用class student(people,people1,...)来应引用
    def __init__(self,name,age,sex,height,weight):
        people.__init__(self,name,age,sex)                  #引用父类中相同的部分来定义对象
        self.height=height                                  #定义子类中独有的部分
        self.weight=weight

stu1=student("egon",18,"男",182,99)                         #实例化
print(stu1.school)                                          #家里蹲
#通过继承,子类可以访问父类中的属性,可以解决类部分代码冗余的问题
#一个子类可以有多个父类,但一般不在定义阶段声明多个父类
#数据的访问关系一定是先自身找,再到上一级的父类去找
#继承是类的概念,和对象无直接关系

访问的优先级:
新式类:(最高父项为object,python3默认都是新式类)
	非菱形:一个分支一个分支的来     菱形:广度优先(后访问共同父项)
经典类:(最高父项不为object)
	非菱形:一个分支一个分支的来     菱形:深度优先(先访问共同父项)

4.2.2调用父类的方式:

#1.指名道姓的调用方式
fun2.fun(self)                #用这一句替换下面super().fun()

#2.super()   调用super(),会参照最初发起属性查找的类的mro,来确定自己的"父类",认为mro中自己后面的类是自己的'父类'
#模板:
class fun1:
    def fun(self):
        super(fun1, self).fun()    #python中super()可以不传参
class fun2:
    def fun(self):
        print("父类")
class fun3(fun1,fun2):
    pass
fun3.mro()           #[<class '__main__.fun3'>, <class '__main__.fun1'>, <class '__main__.fun2'>, <class 'object'>]
obj=fun3()
obj.fun()             #会正常输出"父类"

#注:2种调用方式尽量不要混用

4.3多态

# 1.多态性指可以在不考虑类型的情况下直接使用对象
#	本质就是一类对象都有共同的属性
# 2.鸭子
# 	多态在定义时并没有强制,靠的是一种规范,可以没有共同父类
# 	鸭子指:只要像,它就是(只要有相同属性,就是同一个大类)
# 3.metaclass方法
#	本来父类可有可无,没有实际作用,用此方法来进行限制
#模板:
import abc
class animal(metaclass=abc.ABCMeta):     #统一子类标准,没有say()会报错(本来共同父类可以没有)
    @abc.abstractmethod
    def say(self):
        print("都会叫")
class people(animal):
    def say(self):
        pass
class dog(animal):
    def say(self):
        pass

5.组合

定义:
	类的属性也是类,就称为组合

补充

uuid模块:
	import uuid
    res=uuid.uuid3(uuid.NAMESPACE_DNS,"egon")#基于命名空间和名字的MD5散列值来生成UUID,保证唯一性
	res = uuid.uuid4()                      #基于随机数返回随机字符串
    res =uuid.uuid1()                       #基于时间戳返回随机字符串
    print(res)