美文网首页
【第29天】python全栈从入门到放弃

【第29天】python全栈从入门到放弃

作者: 36140820cbfd | 来源:发表于2019-08-20 11:56 被阅读0次

    今天的主要内容是面向对象汇总

    1.type(obj) obj是一个对象,那么type它就得到它的类型。 type(对象)的结果是对象实例化之前对应的类,type(类)结果是type。

    代码块
    class Student:
        pass
    
    s=Student()
    print(type(s))    #<class '__main__.Student'>
    print(type(Student))    #<class 'type'>
    

    类名+()就是一个实例化

    new()创造了一个对象的空间,一些简单的初始化

    2. type是所有类的元类,object是所有类的父类

    类也是被创建出来的,type创建类, type(类名) =type

    代码块
    from abc import  ABCMeta
    class A(metaclass=ABCMeta):
        pass
    
    a=A()
    print(type(a))
    print(type(A))  #ABCMeta创建了这个A类,那么ABCMeta就是A的元类
    
    # 如果没有指明ABCMeta,那么 type就是这个类的 元类
    
    # type(类)的结果就是创建这个类的元类,大多数情况下就是type,除非你指定metaclass
    
    代码块
    class Saler:
    
        def __init__(self,name,sex,ident):
    
            self.name = name
    
            self.sex = sex
    
            self.ident = ident
    
        def sale(self):
    
            print('%s卖东西'%self.name)
    
        def add_goods(self):
    
            pass
    
    alex = Saler('alex',None,'looser')
    
    print(type(alex))  #Saler
    
    print(type(Saler))  #type
    

    3 什么时候使用面向对象?

    python当中一切皆对象 基础数据类型 都是对象

    类型和自定义类的关系 类型和类是一个东西

    代码量大,功能比较复杂,角色多的时候,比如(qq 好友 陌生人 群 组

    复杂的电商程序

    公司/学校的人事管理/功能的系统

    4 面向对象的好处

    我的代码的清晰度更高了

    可读性 无论是开发者 还是调用者 都能明确的分辨出每个角色拥有的方法和属性

    增强了代码可扩展性

    增加复用性

    更加规范

    5 类是什么时候被加载的,以及类名是什么时候生效的?

    类从一创建就被加载,但是类中的函数只用调用才执行。

    代码块
    class Person:
        ROLE='student'
        # print(Person.ROLE)   name 'Person' is not defined
        print(ROLE)
    
        def func(self):
            print('我是一个函数')
            return 'bye'
    
    p=Person()
    print(Person.func)     #<function Person.func at 0x037C94B0>
    print(p.func())    #我是一个函数      bye
    

    思考5.1:为什么print(Person.ROLE)会报错?

    因为这个时候class类还没有加载完成,只有加载完成才会有Person,此时还不存在,所以报错。

    思考5.2:为什么Person.func和a.func两个内存地址不一样?

    a.func指向class.func的地址,所以不一样。

    6 对象与组合

    对象

    对象:类实例化对象的过程,就是构造new,初始化init

    对象可以通过指针找到类的空间中的内容,指向类

    对象本身存储了一些只属于对象的属性

    组合

    组合:一个类实例化对象作为另外一个类对象的属性就是组合

    7 单继承(单继承子类调用父类方法)

    代码块
    class Foo:
    
        def __init__(self):
    
            self.func()
    
        def func(self):
    
            print('Foo.func')
    
    
    class Son(Foo):
    
        def func(self):
    
            print('我是儿子')
    
    s = Son()   #先执行父类的__init__(),再执行self.func()
    

    子类有,父类没有,调用子类的

    子类没有,父类有,调用父类的

    子类有,父类也有,调用子类的

    子类有,父类有,想调用父类,怎么办:

    super().父类方法(参数)参数里面不用传self

    父类名.父类方法(self,其它参数)

    8 多继承的继承顺序

    代码块
    class A:
    
        def func(self):
    
            print('A')
    
    class B(A):
    
        def func(self):
    
            super().func()
    
            print('B')
    
    class C(A):
    
        def func(self):
    
            super().func()
    
            print('C')
    
    class D(B,C):
    
        def func(self):
    
            super().func()
    
            print('D')
    
    d = D()
    
    d.func()  #ACBD  广度优先
    
    b= B()
    
    b.func()  #   AB
    
    print(D.mro())  #[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
    #类的继承顺序是DBCA
    

    新式类(度优先 - C3算法)和经典类

    代码块
    
    
    mro方法查看继承顺序
    
    py3 默认继承object  所以py3都是新式类
    
    super().func() 遵循mro算法,在类的内部不用传子类名和self
    
    py2 需要主动继承object,默认不继承
    
    super(子类名,self).func() 必须传子类名和self
    
    经典类 : 深度优先
    
    py2 不继承object,默认都是经典类,也可以手动继承object,没有mro
    
    

    9 多态(一种类型的多种形态 多个子类去继承父类,那么每一个子类都是这个父类的一种形态)

    10封装

    广义的封装 : 把方法和属性都封装在一个类里,定义一个规范来描述一类事物.

    狭义的封装 : 私有化 只能在类的内部访问

    __静态变量,私有方法 ,私有的对象属性,私有的类方法,私有的静态方法

    在内存中存储 类名_名字

    为什么在类的内部可以使用双下划线访问 : 在类的内部使用,你就知道你在哪个类中

    在子类中可以访问访问父类的私有变量么?不行

    私有 : 不能在类的外部使用也不能被继承

    11 property的使用(把方法伪装成属性)

    property装饰器函数,内置函数,帮助你将类中的方法伪装成属性,特性

    调用方法的时候不需要主动加括号

    让程序的逻辑性更合理

    代码块
    class A:
        def __init__(self, name):
    
            self.__name = name
    
    
        @property
        def name(self):
    
            return self.__name
    
        @name.setter
        def name(self, new_name):
            self.__name = new_name
    
        @name.deleter
        def name(self):
            del self.__name
    
    a = A('alex')
    a.name = 123
    print(a.name)
    
    # del a.name  # 语法
    # #
    # print(a.name)
    

    @方法名.setter

    (self,变量,新的值)

    装饰器,修改被property装饰的属性的时候会调用被这个装饰器装饰的方法,除了self之外还有一个参数,被修改的值

    @方法名.deleter

    装饰器,当要删除被property装饰的属性的时候会调用被这个装饰器装饰的方法

    12类方法classmethod(通过类调用,不通过对象)

    代码块
    class Goods:
    
        __discount = 0.8
    
        def __init__(self,price):
    
            self.__price = price
    
        @property
    
        def cost(self):
    
            return self.__price * Goods.__discount
    
        @classmethod
    
        def change_discount(cls,num):
    
            cls.__discount = num
    
    Goods.change_discount(10)  #不用通过对象,通过类名就可以直接调用
    
    a=Goods(5)
    
    print(a.cost)  #50
    

    13静态方法

    如果一个类里面的方法 既不需要用到self中的资源,也不用cls中的资源.

    相当于一个普通的函数

    但是你由于某种原因,还要把这个方法放在类中,这个时候,就将这个方法变成一个静态方法

    某种原因:

    你完全想用面向对象编程 ,所有的函数都必须写到类里

    某个功能确确实实是这个类的方法,但是确确实实没有用到和这个类有关系的资源

    14反射

    反射 - 从某个指定的命名空间中,用字符串数据类型的变量名来获取变量的值

    类名反射: 静态属性 类方法 静态方法

    对象反射 :对象属性 方法

    模块 : 模块中的方法

    代码块
    import  sys
    class Student:
        def __init__(self,name,age):
            self.name=name
            self.age=age
            self.school='北京大学'
    
        def study(self):
            print('%s%s在%s上大学'%(self.name,self.age,self.school))
    
    res=sys.modules['__main__']
    s2=getattr(res,'Student')('alex',18)   #实例化
    
    
    s2.study()
    getattr(s2,'study')()
    # s2.study()与getattr(s2,'study')()是同一个
    print(s2.study==getattr(s2,'study'))   #是同一个东西
    

    15 双下方法(内置方法/魔术方法/双下方法)

    代码块
    __名字__不是被直接调用的
    
    间接调用 : 内置函数/面向对象中特殊语法/python提供的语法糖
    
    __str__ : str(obj),要求必须实现了__str__,要求这个方法的返回值必须是字符串str类型
    
    print %sstr
    
    __call__  : 相当于 对象()  用类写装饰器
    
    __len__ : len(obj),要求obj必须实现了__len__,要求这个方法的返回值必须是数字int类型
    
    __new__ : 在实例化的过程中,最先执行的方法,在执行init之前,用来创造一个对象,构造方法
    
    __init__  : 在实例化的过程中,在new执行之后,自动触发的一个初始化方法,每个对象都会自动执行这个方法,没有就去父类中找__init__
    

    16语法糖

    代码块
    x=5
    
    y =6
    
    print(x.__add__(y))   #11
    
    print(x+y)# 语法糖  11
    
    代码块
    class MyType:
    
        def __init__(self,s):
    
            self.s = s
    
        def __add__(self, other):# __sub__ __mul__ __div__
    
                return self.s.count('*') + other.s.count('*')
    
    obj1 = MyType('asjkfhk***17264****')
    
    obj2 = MyType('asjkfhk***17***')
    
    print(obj1.__add__(obj2) )    #13
    
    print(obj1 + obj2)   #语法糖
    

    17 str和repr区别

    name='wangsiyu'
    print(name) #wangsiyu 一个没有引号
    print(repr(name)) #'wangsiyu' 一个有引号

    代码块
    __str__: str(obj)
    
    要求必须实现了__str__,要求这个方法的返回值必须是字符串str类型
    
    print %s     str
    
    __repr__: 是__str__的备胎.如果有__str__方法,那么# print %s str都先去执行__str__方法,并且使用__str__的返回值
    
    如果没有__str__,那么print %s str都会执行repr
    
    repr(obj),%r
    
    
    代码块
    class A:
    
        def __init__(self,name):
    
            self.name = name
    
        def __str__(self):
    
            return '**%s**'%self.name
    
        def __repr__(self):
    
            return self.name
    
    class B(A):
    
        def __init__(self,name):
    
            self.name = name
    
        def __repr__(self):
    
            return '***'
    
    b = B('alex')  #实例化一个B类
    print(str(b),repr(b))   #**alex** ***
    
    print('%s | %r'%(b,b))  #**alex** | ***
    
    print('---%r---'%('abc'))    #r代表repr
    
    print('---%s---'%('abc'))    #s代表str
    
    在子类中使用__str__,先找子类的__str__,没有的话要向上找,只要父类不是object,就执行父类的__str__
    
    但是如果除了object之外的父类都没有__str__方法,就执行子类的__repr__方法,
    
    如果子类也没有,还要向上继续找父类中的__repr__方法.一直找不到 再执行object类中的__str__方法
    

    18内置方法

    代码块
    abs()
    
    dict()把一个数据转为字典
    
    help()
    
    min()取出列表最小
    
    bool()有就是True,没有就是False
    
    dir()打印当前所有变量
    
    hex()将一个数字转为16进制
    
    sorted()排序
    
    ascii()
    
    oct()转为8进制
    
    bin()转为2进制
    
    eval()把字符串转为数字计算
    
    ord()返回ACSII表位置
    
    chr() 和ord()正好相反
    
    map() reduce()  filter()
    
    callable() 是否可以被调用
    
    tuple()转为元祖
    
    
    别跑,点个赞再走

    相关文章

      网友评论

          本文标题:【第29天】python全栈从入门到放弃

          本文链接:https://www.haomeiwen.com/subject/vodusctx.html