• 初识面向对象


    面向对象总结

    一,初识

    class Person(object):
        # 类属性:静态属性 默认这个类所有对象都有的,不能更改的属性可以放在这里
        # 一般不用对象调用类属性,对象不能修改类属性,一旦修改:
        # 会在实例属性中新增被修改的类属性,将真实的类属性覆盖
        language = '语言'
        mind = '感情'
        def __init__(self,name,age,sex):
            # 实例属性
            # 可以用对象修改实例属性,只会修改这个对象自己的,对其他对象没影响
            # 如果在类内部修改实例属性,所有的对象的这个属性的值都会被修改
            self.name = name
            self.age = age
            self.sex = sex
        def eat(self):
            print('会吃饭')
        def run(self):
            print('会跑')
    
    pp1 = Person('alex',83,'男')
    pp2 = Person('baoyuan',18,'男')
    
    一般不用对象调用类属性,对象不能修改类属性,一旦修改:
    会在实例属性中新增被修改的类属性,将真实的类属性覆盖
    pp1.mind = 'buqingchu'
    print(pp1.mind) # buqingchu
    print(pp1.__dict__) # {'name': 'alex', 'age': 83, 'sex': '男', 'mind': 'buqingchu'}
    
    可以用对象修改实例属性,只会修改这个对象自己的,对其他对象没影响
    pp1.name = 'ALEX'
    print(pp1.name,pp2.name) # ALEX baoyuan
    
    pp1.hooby = '女'
    print(pp1.__dict__)
    # {'name': 'ALEX', 'age': 83, 'sex': '男', 'hooby': '女'}
    print(pp2.__dict__)
    # {'name': 'b
    

    二,类之间的关系

    1.依赖关系/ 关联关系

    • 依赖关系也叫关联关系
    • 就是在一个类的方法中调用了另一个类的对象
    • 或者说:将一个类的对象放在另一个类的方法中
    # 定义一个英雄类和一个反派类
    # • 两个类都包含名字、血量,攻击力(ATK),和一个技能(skill)
    # • 两派对象互殴
    # • 血量为0死亡,删除对象(del 对象名)
    class Hero:
        def __init__(self,name,hp,atk):
            self.name = name
            self.hp = hp
            self.atk = atk
        def skill(self,tool):
            print(f'{self.name}攻击了{tool.name}{self.atk}滴血')
            tool.hp = tool.hp - self.atk
    
    class Fan:
        def __init__(self,name,hp,atk):
            self.name = name
            self.hp = hp
            self.atk = atk
        def skill(self, tool):
            print(f'{self.name}攻击了{tool.name}{self.atk}滴血')
            tool.hp = tool.hp - self.atk
    
    baoyuan = Hero('宝哥哥',100,50)
    alex = Fan('大烧饼',70,20)
    
    while True:
        baoyuan.skill(alex)
        alex.skill(baoyuan)
        if alex.hp <= 0:
            del alex
            print('游戏结束')
            break
        if baoyuan.hp <= 0:
            del baoyuan
            print('游戏结束')
            break
    

    2.组合关系

    • 将一个类的对象放在另一个类的属性中
    class Boy:
        def __init__(self,name,girlFriend=None):
            self.name = name
            self.tool = girlFriend
        def dinner(self):
            if self.tool:
                print(f'{self.name}和{self.tool.name}共进晚餐')
            else:
                print('单身狗吃什么吃')
    
    class Girl:
        def __init__(self,name):
            self.name = name
    
    alex = Boy('alex')
    tang = Girl('tang')
    baoyuan = Boy('baoyuan',tang)
    
    alex.dinner()
    baoyuan.dinner()
    

    3.继承关系--三大特性之一

    • 继承是在不改变现有类的情况下扩展这个类
    • 子类可以获得父类的全部属性和方法
    • 子类可以定义自己的方法,也可以定义和父类重名的方法(方法重写),这时子类方法会覆盖掉父类的同名方法,因此如果子类和父类都拥有自己的初始化方法,需要在子类的初始化方法中调用父类的init方法
    • 如果只是想操作另一个类的对象,用依赖
    • 如果两个类当中存在has a的关系,用组合
    • 如果两个类当中存在is a的关系,用继承(尽量少用继承,多用组合)
    class Father:
        def livelikeyemen(self):
            print('打妈妈')
    
    class Son(Father):
        def abc(self):
            print(123)
        # 父类方法重写
        def livelikeyemen(self):
            print('打妹妹')
    
    class Animal:
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def run(self):
            print('会跑')
    
    class Dog(Animal):
        # 如果子类也有自己的初始化方法会报错
        # 解决方式:在子类的init方法里面,调用父类的init方法
        def __init__(self,name,age):
            self.kengutou = False
            Animal.__init__(self,name,age)
            # 也可以写成:super().__init__()
        def jump(self):
            print('会跳')
    
    class Cat(Animal):
        def __init__(self):
            self.xihuanyu = True
        def jiao(self):
            print('喵喵')
    
    anm = Animal('动物',18)
    gg = Dog('小黑',11)
    print(gg.name,gg.age)
    cc = Cat()
    

    三,三大特性

    1.封装

    a.概念

    • 封装就是将抽象得到的数据和行为相结合形成一个整体
    • 封装就是将复杂的事物封装成一个整体,对外只有简单的接口
    • 目的:简化编程,增强安全性,明确区分内外

    b.私有属性和私有方法

    • 在类的属性和方法名字前面加上两个下划线,就变成私有属性和方法
    • 在类的外部不能直接调用私有属性和私有方法,子类也不能访问
    • 可以提供外部访问的接口
    • 私有属性和私有方法在继承给子类时,子类是无法覆盖的
    • 破解方法(一般不用):在名字前面加上一个下划线+类名(如:a._A__N) ; 因为在底层代码中就是按上述命名的,所以可以这样破解
    class Animal:
        def __init__(self):
            self.__name = '动物'
            self.__age = '18'
    
        def get_name(self):
            return '宠物'
    
        def get_age(self,num):
            if isinstance(num,int):
                if 0 < num < 200:
                    return num
    
    class Dog(Animal):
        pass
    
    dog = Animal()
    print(dog.get_name())
    print(dog.get_age(188))
    

    2.多态

    a.多态概念

    • 体现1:一类事物可以有多种形态
    • 体现2:python中一个引用可以指向不同数据类型
    class Bird:
        def move(self,field):
            print(f'鸟在{field}自由地飞翔')
    class Dog:
        def move(self,field):
            print(f'狗在{field}飞快地奔跑')
    b = Bird()
    b.move('天空')
    d = Dog()
    d.move('草地')
    

    b.多态性概念

    • 不同类的对象作为同一个外部函数的参数时得到不同的结果
    • 在多态的基础上定义统一的接口,就是在类外部单独定义一个函数
    • 在继承和方法重写的基础上,定义统一的接口,不关心传入对象的类型,只关心实现了哪些方法
    # 继承+方法重写+类外部统一接口
    class Car:
        def __init__(self,color):
            self.color = color
        def run(self):
            print(f"{self.color}汽车在跑")
    
    class Cat(Car):
        def run(self):
            print(f"{self.color}小猫在跑")
    
    def run(tool):
        tool.run()
    
    car = Car('红色')
    cat = Cat('红色')
    run(car)
    run(cat)
    

    c.鸭子类型

    • python很崇尚鸭子类型
    • 和多态性很类似,但是不需要继承和方法重写
    class Car():
    
        def __init__(self,color):
            self.color = color
        def run(self):
            print(f'{self.color}的小汽车在跑')
    
    class Cat():
    
        def __init__(self,name):
            self.name = name
        def run(self):
            print(f'猫咪{self.name}在跑')
    
    qiche = Car('红色')
    maomi = Cat('小猫咪')
    
    def run(tools):
        tools.run()
    
    run(qiche)
    run(maomi)
    

    四,设计模式

    • 在处理问题时使用的可重用的解决方法

    1.单例模式

    • 一个类只能创建一个对象的就是单例
    • 不管创建多少对象,都是同一个
    • 作用:比如闯关游戏,每一关都由不同的程序员制作,如果是非单例的,每个人创建的对象都是一个新的,那就造成:每打完一个关卡获得的经验值,金币或者更新的装备,到下一关就都变成初始值了;如果是单例模式,第一关创建的对象经过一个关卡的升级,这些数值到下一关还存在
    class Person(object):
        ins = None
        # 创建对象时,为新对象开辟空间这些都是双下new做的,双下init其实就是把属性赋值而已
        def __new__(cls,*args,**kwargs):
            if not cls.ins:
                cls.ins = object.__new__(cls)
            return cls.ins
    alex = Person()
    baoyuan = Person()
    # 这个类的意思就是,重写object的双下new方法:如果创建对象时看看ins有没有值,如果有就用已经有的;如果没有就执行object的双下new(这个就跟没重写一样).
    # 1. 创建alex这个对象时调用双下new方法,"if not cls.ins:"这个判断可以理解为"if cls.ins = None:";
    # 2. 第一次创建对象时cls.ins肯定是None,然后执行cls.ins=object.__new__(cls)就是运行object的双下new方法(结果就是创建一个新的对象空间)然后将结果赋值给cls.ins;最后将cls.ins的值return给调用双下new的地方
    # 3. 如果创建对象时cls.ins有值,就直接将cls.ins的值return给调用双下new的地方
    # 这样就保证了不管创建多少对象,都是同一个对象
    
    
    # 注意if下面两种写法的不同:
    
    # 此时不管if成立与否都必须return
    if cls.ins == None:
        cls.ins = object.__new__(cls)
    return cls.ins
    
    # 此时只有if不成立时才return
    if cls.ins == None:
        cls.ins = object.__new__(cls)
    else:
        return cls.ins
    

    2.工厂模式

    class Cat:
        pass
    class Dog:
        pass
    
    class Gongchang:
        def choice(self,arg):
            if arg == 'C':
                return Cat()
            if arg == 'D':
                return Dog()
            print('错误')
    

    五,约束

    • 约束指的是对类的约束,规定在类中必须实现哪些方法

    1.方式一: 提取父类并在父类中抛出异常

    class QQpay:
        def pay(self):
            pass
    class Zhifubao:
        def pay(self):
            pass
    class Weixin:
        def zhifu(self):
            pass
    wx = Weixin()
    def jiekou(tool):
        tool.pay()
    jiekou(wx) # 报错
    # 因为接口中叫pay(),所以类中方法名字要相同
    
    # 提取父类,在父类的方法中设置抛出异常
    class Father:
        def pay(self):
            raise Exception('听话,别闹!!!')
    class QQpay(Father):
        def pay(self):
            print('qq支付')
    class Zhifubao(Father):
        def pay(self):
            print('支付宝支付')
    class Weinxin(Father):
        def zhifu(self):
            print('微信支付')
    def jiekou(tool):
        tool.pay()
    qq = QQpay()
    zfb = Zhifubao()
    wx = Weinxin()
    jiekou(wx)  # 执行时抛出异常.
    # 执行时,先执行wx.pay(),pay()方法在Weixin类中没有,就去父类找,
    # 执行父类的pay()方法时,直接抛出异常
    

    2.方式二: 定义抽象类

    • 类都是继承于object
    • 类都是由元类(metaclass)创造的. mataclass默认值是Type(普通类的元类),把抽象类的元类ABCMeta的值赋给metaclass,就能创造抽象类
    # 定义抽象类,抽象类中的方法都pass,
    # 但是继承这个抽象类的类都必须实现,起到约束作用
    from abc import ABCMeta,abstractmethod
    class Aaa(metaclass=ABCMeta):
        @abstractmethod
        def abc(self):
            pass
        @abstractmethod
        def dfg(self):
            pass
    
    # 下面定义一个类继承上面的抽象类
    # 抽象类中的方法都要在此类中实现,有一个不实现就报错
    class Bbb(Aaa):
        def abc(self):
            print('123')
    bb = Bbb() # TypeError: Can't instantiate abstract class Bbb with abstract methods dfg
    

    六,特殊方法

    1.@classmethod类方法

    • 一个类通过@classmethod修饰的方法
    • 类方法就是将类本身作为对象进行操作的方法
    • 第一个参数必须是当前类对象,该参数名约定为cls,通过cls来传递类的属性和方法(不能传递实例的属性和方法)
    • 实例对象和类对象都可以调用(类对象就是类,因为万物皆对象),但是推荐使用类名调用,因为这个方法是属于类的
    • self和cls只能在类内使用,在类外无效
    • 实例方法:对象调用,类名不建议调用
    • 实例属性:对象调用,类名不能调用
    • 类方法:通过类名调用,对象也可以调用,但是不建议
    • 类属性:通过类名调用,对象也可以调用,但是不建议
    class Student:
        __num = 0
        def __init__(self,name,age):
            self.name = name
            self.age = age
            Student.set_num()
        
        @classmethod
        def get_num(cls):
            return cls.__num
        @classmethod
        def set_num(cls):
            cls.__num += 1
    

    2.@staticmethod静态方法

    • 使用@staticmethod修饰的方法
    • 就是在类中定义的一个普通函数
    • 当前类对于静态方法来说,只是相当于一个名称空间
    • 参数随意,没有self和cls参数,方法体中不能由类或实例的任何属性和方法
    • 实例对象和类对象都可以调用
    • 为了代码模块化,代码应该是由若干个类组成的,但是有时需要用一些函数,和任何类和对象都没有关系的普通函数,这些函数会破坏代码的模块化,这样设置静态方法,将这些函数放进类中,对类和这种函数也没有影响
    class Student:
        __num = 0
        def __init__(self,name,age):
            self.name = name
            self.age = age
            Student.set_num()
    
        @classmethod
        def get_num(cls):
            return cls.__num
        @classmethod
        def set_num(cls):
            cls.__num += 1
    
        @staticmethod
        def aaa(a,b,c):
            # 这个就是一个普通函数,跟当前类和对象没有任何关系
            print('aaa')
    
    a = Student()
    
    Student.aaa()
    a.aaa()
    # 这两种调用方式都可以
    

    3.@property

    • 将一个方法伪装成属性去调用
    • 用@property修饰方法
    • 一定现有property,才能有setter和deleter
    • 为了遵循同意访问的原则
    class Square:
        def __init__(self,long,wide):
            self.long = long
            self.wide = wide
        def area(self):
            return self.long*self.wide
    
    s = Square(10,20)
    print(s.area()) 
    
    # 上面的实现方法没问题,但是面积这一类比较习惯作为属性,所以可以用property
    
    class Square:
        def __init__(self,long,wide):
            self.long = long
            self.wide = wide
        # 将一个方法伪装成属性
        @property
        def area(self):
            return self.long*self.wide
    
    s = Square(10,20)
    print(s.area) # s.area()会报错
    
    # BMI
    class Bmi:
        def __init__(self,tizhong,shengao):
            self.tizhong = tizhong
            self.shengao = shengao
    
        @property
        def bmi(self):
            return self.tizhong/self.shengao**2
    bb = Bmi(65,1.82)
    print(bb.bmi)
    
    class Person:
        def __init__(self, age):
            self.__age = age
    
        @property
        def age(self):
            return self.__age # 把self.__age换成18试试
    
        @age.setter
        def age(self, num):
            if 0 < num < 100:
                self.__age = num
    
        # @age.deleter
        # def age(self):
        #     print('就不删除')
    
        @age.deleter
        def age(self):
            print('已删除')
            del self.__age
    
    xiaoli = Person(10)
    print(xiaoli.age)
    xiaoli.age = 12
    print(xiaoli.age)
    del xiaoli.age
    print(xiaoli.age)
    
    # 只有@property定义只读,加上@setter定义可读可写,再加上@delter定义可读可写可删除
    

    七,反射

    • 以字符串的形式操作对象的相关属性
    • 一切皆对象==>一切都可以用反射
    class Girl:
        num = 0
        def __init__(self):
            self.name = 'alex'
    
        def run(self):
            print('人会跑')
    
    xiaohong = Girl()
    print(hasattr(xiaohong,'num'))
    print(hasattr(xiaohong,'run'))
    
    print(getattr(xiaohong,'name'))
    print(getattr(xiaohong,'run')) # 内存地址
    print(getattr(xiaohong,'name1','没有')) # 没有
    print(getattr(xiaohong,'name','没有')) # alex
    
    setattr(xiaohong,'name','baoyuan')
    print(getattr(xiaohong,'name'))
    
    例题:
    # 当我们打开浏览器,访问一个网站,单击登录就跳转到登录界面,单击注册就跳转到注册界面
    # 但是,你单击的其实是一个个的链接,每一个链接都会有一个函数或者方法来处理
    class User:
        def login(self):
            print('登录页面')
        def register(self):
            print('注册页面')
        def save(self):
            print('存储页面')
    
    # 不用反射的方法:
    # while Ture:
    #     choose = input('<<<').strip()
    #     if choose == 'login':
    #         uu = User()
    #         uu.login()
    #     elif choose == 'register':
    #         uu = User()
    #         uu.register()
    #     elif choose == 'save':
    #         uu = User()
    #         uu.save()
    
    # 反射方法:
    uu = User()
    while True:
        choose = input('<<<').strip()
        if hasattr(uu,choose):
            func = getattr(uu,choose)
            func()
        else:
            print('输入错误')
    
    
    class Person:
        a = 0
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def func(self):
            print(111)
    
    pp = Person('alex',83)
    # 1.
    # hasattr(对象名,'属性')===>判断该对象是不是有该属性
    print(hasattr(pp,'name'))
    
    # 2.
    # getattr(对象名,'属性',[默认值])===>获取该对象的该属性的值(相当于 查)
    # 默认值可写可不写:如果该对象有该属性,则可以print出来.
    #               如果没有,显示默认值,不写默认值则报错
    print(getattr(pp,'name'))
    print(getattr(pp,'sex','没有'))
    # print(pp.sex)
    
    # 3.
    # setattr(对象名,'属性',值)===>设置该对象的该属性的值(相当于 改)
    # 如果该对象有该属性,则修改成后面的值;如果没有,就增加该属性,该属性的值就是后面的值
    setattr(pp,'name','baoyuan')
    print(pp.name)
    setattr(pp,'sex','女')
    print(pp.__dict__)
    print(pp.sex)
    print(getattr(pp,'sex','XX'))
    
    # 4.
    # delattr(对象名,'属性')===>删除该对象的该属性(相当于 删)
    delattr(pp,'name')
    # print(pp.name)
    
    
    class Person:
        a = 0
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def func(self):
            print(111)
    
    pp = Person('alex',83)
    # 1.
    # hasattr(对象名,'属性')===>判断该对象是不是有该属性
    # print(hasattr(pp,'name'))
    
    # 2.
    # getattr(对象名,'属性',[默认值])===>获取该对象的该属性的值(相当于 查)
    # 默认值可写可不写:如果该对象有该属性,则可以print出来.
    #               如果没有,显示默认值,不写默认值则报错
    # print(getattr(pp,'name'))
    # print(getattr(pp,'sex','没有'))
    # print(pp.sex)
    
    # 3.
    # setattr(对象名,'属性',值)===>设置该对象的该属性的值(相当于 改)
    # 如果该对象有该属性,则修改成后面的值;如果没有,就增加该属性,该属性的值就是后面的值
    # setattr(pp,'name','baoyuan')
    # print(pp.name)
    # setattr(pp,'sex','女')
    # print(pp.__dict__)
    # print(pp.sex)
    # print(getattr(pp,'sex','XX'))
    
    # 4.
    # delattr(对象名,'属性')===>删除该对象的该属性(相当于 查)
    # delattr(pp,'name')
    # print(pp.name)
    
    

    八,异常

    1.概念

    • Exception:是影响程序正常执行的一个事件.产生异常之后,程序会停止运行
    • 目的:捕获异常,这样不影响程序继续执行
    • 异常也是对象,有异常类:Exception
    • 常见的异常全部都是Exception(异常类)的子类

    2.处理异常的方式

    • 处理方式一:通过算法来进行判断,有缺陷存在大量与业务逻辑无关的代码,导致代码量增大,重复代码增多

    • 处理方式二:

      try:
          需要进行一场检测的代码
      except 异常类的类名:
          捕获异常之后的处理方式
      else:
          如果try下面的子句没有产生异常,就执行else后面的内容
      finally:
          无论是否出现异常,是否正常捕获,都会执行(即使遇到return,break也会先执行)
      
    try:
        num = 5/0
        print(345) # 不执行
    
    except ZeroDivisionError:
        print('除数不能为0')
    
    
    print('123')
    # 异常处理可以捕获异常对象,然后做相应处理,让程序继续执行
    # 如果代码没出现异常,程序正常执行
    # 如果出现异常,except会尝试捕获,
    #   如果捕获成功执行except下面的内容
    #   如果捕获不成功(如:错误类型不匹配),依然会抛出异常
    

    3.万能异常

    • 可以捕获python定义好的所有异常对象
    • 通过exception:所有异常类的父类
    while True:
    
        try:
            num = int(input('请输入:'))
            num = 5 / num
            print(num)
            break
        except Exception as b:
            print(f'出现了异常:{b}')
            continue
    # 运行结果:
    # 请输入:0
    # 出现了异常:division by zero
    
    try:
        num = int(input('请输入:'))
        num = 5 / num
        print(num)
        
    except Exception as b:
        print(f'出现了异常:{b}')
        
    else:
        print('只有上面全部正常运行结束,才执行我')
    finally:
        print('不管上面运行正常与否,都会执行我..如:关闭文件,需要在return或break执行前需要执行的')
    

    4.断言

    • 表示一种强硬的态度,只要assert后面的条件不成立,就抛出异常,让当前程序终止运行(后面的代码就不执行)
    • 一般用来调试程序
    print(111)
    print(111)
    print(111)
    assert False
    print(111)
    print(111)
    print(111)
    print(111)
    

    5.自定义异常

    • 创建一个类,将他的父类设置为exception,那么这个类就是一个自定义异常类
    • 通过这个类,我们可以定义自己的异常对象(需要主动抛出)

    九,内置方法

    class Girl:
        def __init__(self):
            self.name = "alex"
        # def __del__(self):
        #     print("对象死了")
        def __len__(self):
            return 10
        def __hash__(self):
            return 100
        def __str__(self):
            return self.name
        def __eq__(self, other):
            if self.name == other.name:
                return True
            else:
                return False
    a = Girl()
    b = Girl()
    a.name = "bigB"
    print(len(b))
    # print(hash("123"))
    

    十, 零散知识点

    1. 模型与抽象类

    1.1 模型

    • 一旦有一个类继承了models.Model,那它就是一个模型。

    • 成为了模型就会自动的为它在数据库中创建一张表。

    • 比如:Django认证系统中内置的用户模型类User;

    1.2 抽象类

    什么是抽象类?我们来看下面的代码:

    class XXX(object):
        ...
        class Meta:
            abstract = True # 这里定义了是抽象类
    

    1.3 抽象模型

    我们知道了什么是模型,什么是抽象类,这里说一下抽象模型。

    继承了models.Model就是模型,Django会自动地在数据库中为其创建一张表。但是有一些模型只是声明了一些公共字段,没有必要为它在数据库中创建一张表,这时就在它的class Meta中加入abstract=True。这样在做数据迁移时,就不会为他单独创建一张表。这样的模型被Django官方定义为抽象模型。

    比如:Django认证系统中内置的抽象用户模型类AbstractUser;

    代码如下:

    class AbstractUser(AbstractBaseUser, PermissionsMixin):
        """
        An abstract base class implementing a fully featured User model with
        admin-compliant permissions.
    
        Username and password are required. Other fields are optional.
        """
        username_validator = UnicodeUsernameValidator()
    
        username = models.CharField(
            _('username'),
            max_length=150,
            unique=True,
            help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
            validators=[username_validator],
            error_messages={
                'unique': _("A user with that username already exists."),
            },
        )
        first_name = models.CharField(_('first name'), max_length=30, blank=True)
        last_name = models.CharField(_('last name'), max_length=150, blank=True)
        email = models.EmailField(_('email address'), blank=True)
        is_staff = models.BooleanField(
            _('staff status'),
            default=False,
            help_text=_('Designates whether the user can log into this admin site.'),
        )
        is_active = models.BooleanField(
            _('active'),
            default=True,
            help_text=_(
                'Designates whether this user should be treated as active. '
                'Unselect this instead of deleting accounts.'
            ),
        )
        date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
    
        objects = UserManager()
    
        EMAIL_FIELD = 'email'
        USERNAME_FIELD = 'username'
        REQUIRED_FIELDS = ['email']
    
        class Meta:
            verbose_name = _('user')
            verbose_name_plural = _('users')
            abstract = True
    
        def clean(self):
            super().clean()
            self.email = self.__class__.objects.normalize_email(self.email)
    
        def get_full_name(self):
            """
            Return the first_name plus the last_name, with a space in between.
            """
            full_name = '%s %s' % (self.first_name, self.last_name)
            return full_name.strip()
    
        def get_short_name(self):
            """Return the short name for the user."""
            return self.first_name
    
        def email_user(self, subject, message, from_email=None, **kwargs):
            """Send an email to this user."""
            send_mail(subject, message, from_email, [self.email], **kwargs)
    
    
    class User(AbstractUser):
        """
        Users within the Django authentication system are represented by this
        model.
    
        Username and password are required. Other fields are optional.
        """
        class Meta(AbstractUser.Meta):
            swappable = 'AUTH_USER_MODEL'
    

    十一,习题

    # 一、选择题
    #
    # Python中定义私有属性的方法是(D)。
    # A.使用private关键字
    # B.使用public关键字
    #
    # C.使用__XX__定义属性名
    # D.使用__XX定义属性名
    #
    # 2.
    # 下列选项中,不属于面向对象程序设计的三个特征的是(A)。
    #
    # A.抽象
    # B.封装
    # C.继承
    # D.多态
    #
    # 3.
    # 以下C类继承A类和B类的格式中,正确的是(C)。
    #
    # A. 
    # class C A, B: 
    # B.
    # class C(A:B)
    # C.
    # class C(A, B)
    # D.
    # class C A and B:
    #
    # 4.
    # 下列选项中,与class
    # Person等价的是(C)。
    #
    # A.
    # class Person(Object)
    # B.
    # class Person(Animal)
    # C.
    # class Person(object)
    # D.
    # class Person: object
    #
    # 二、判断题
    #
    # 继承会在原有类的基础上产生新的类,这个新类就是父类。(N)
    # 带有两个下划线的方法一定是私有方法。(N)
    # 子类能继承父类的一切属性和方法。(N)
    # 子类通过重写继承的方法,覆盖掉跟父类同名的方法。(Y)
    # 如果类属性和实例属性重名,对象也可以访问类属性的值。(N)
    # 使用类名获取到的值一定是类属性的值。(Y)
    #
    # 三、填空题
    #
    # 如果属性名的前面加上了两个_下划线______,就表明它是私有属性。
    # 在现有类基础上构建新类,新的类称作子类,现有的类称作___父类_________。
    # 父类的___私有____属性和方法是不能被子类继承的,更不能被子类访问。
    # Python语言既支持单继承,也支持____多_______继承。
    # 子类想按照自己的方式实现方法,需要__重写_____从父类继承的方法。
    # 子类通过___继承_______可以成功地访问父类的成员。
    #
    # 四、简答题
    #
    # 请简述如何保护类的属性。
    # 将需要保护的类的属性设置为私有属性
    
    # 什么是继承?
    # 在不改变类的基础上对这个类进行扩展
    
    # 请简述私有属性无法访问的原理。
    # 在底层代码中,私有属性的名字是下划线+类名+私有属性名,起到封装作用
    #
    # 五
    # 编程题
    #
    # 1.
    # 简述面向对象中为什么要有继承?
    # 简化代码
    # 2.
    # Python继承时,查找成员的顺序遵循什么规则?
    # C3算法,MRO
    # 3.
    # 需求:
    # 房子有户型,总面积(私有)和家具名称列表
    # 新房子没有任何的家具
    # 家具有名字和占地面积,其中
    # 床:占4平米
    # 衣柜:占2平面
    # 餐桌:占1.5平米
    # 将以上三件家具添加到房子中
    # 打印房子时,要求输出: 户型,总面积,剩余面积,家具名称列表
    #
    
    # class House:
    #     def __init__(self, mold, __area):
    #         self.mold = mold
    #         self.__area = __area
    #         self.furniture_lst = []
    #     def add_fur(self, tools):
    #         self.furniture_lst.append(tools.name)
    #     def area(self):
    #         return self.__area
    #     def surplus(self, tools):
    #         surplus_area = self.area() - tools.area
    #         return surplus_area
    # class Furniture:
    #     def __init__(self, name, area):
    #         self.name = name
    #         self.area = area
    # bed = Furniture('床',4)
    # kas = Furniture('衣柜',2)
    # board = Furniture('餐桌',1.5)
    # hou = House('三居室',100)
    # hou.add_fur(bed)
    # hou.add_fur(kas)
    # hou.add_fur(board)
    # hou.surplus(bed)
    # hou.surplus(kas)
    # print(hou.mold,hou.area(),hou.surplus(board),hou.furniture_lst)
    
    class House:
        def __init__(self,huxing,area):
            self.huxing = huxing
            self.__area = area
            self.jiaju_lst = []
            self.shengyumianji = self.__area
        def add_jiaju(self,tool):
            if tool.area < self.shengyumianji:
                self.jiaju_lst.append(tool)
                self.shengyumianji -= tool.area
        def show(self):
            print(f'{self.huxing},总面积:{self.__area},剩余面积:{self.shengyumianji}')
            for i in self.jiaju_lst:
                print(i.name)
    class Jiaju:
        def __init__(self,name,area):
            self.name = name
            self.area = area
    jia = House('三居室',120)
    chuang = Jiaju('床',4)
    yigui = Jiaju('衣柜',2)
    canzhuo = Jiaju('餐桌',1.5)
    jia.add_jiaju(chuang)
    jia.add_jiaju(yigui)
    jia.add_jiaju(canzhuo)
    jia.show()
    # 4.
    # 当买车时,有很多种品牌可以选择,比如北京现代、别克、凯迪拉克、特斯拉等,
    # 那么此时该怎样进行设计程序呢?能否根据用户出入的品牌名称来返回对应的汽车对象
    class xiandai:
        def func(self):
            print('北京现代')
    class bieke:
        def func(self):
            print('别克')
    class tesila:
        def func(self):
            print('特斯拉')
    class Fac:
        def choice(self,arg):
            if arg == 'x':
                return xiandai()
            if arg == 'b':
                return bieke()
            if arg == 't':
                return tesila()
            print('无效输入')
    arg = input('请输入品牌首字母:')
    ff = Fac()
    ff.choice(arg).func()
    
    
    # class House:
    #     def __init__(self,apartment,area):
    #         self.apartment = apartment
    #         self.__area = area
    #         self.ajlist = []
    #         self.shengyumianji = self.__area
    #     def add(self,tool):
    #         if tool.area < self.shengyumianji:
    #             self.ajlist.append(tool)
    #             self.shengyumianji -= tool.area
    #     def show(self):
    #         print(f"{self.apartment},总面积是{self.__area},剩余面积是{self.shengyumianji}")
    #         for i in self.ajlist:
    #             print(i.name)
    #
    #
    # class Furniture:
    #     def __init__(self,name,area):
    #         self.name = name
    #         self.area = area
    #
    # wojia = House("独栋别墅",2000)
    # chuang = Furniture("大通铺",4)
    # yigui = Furniture("品如的衣柜",2)
    # wojia.add(chuang)
    # wojia.add(yigui)
    # wojia.show()
    
    # 1,定义一个银行职员类,尝试根据用户输入来调用银行职员的方法
    #
    # 举例:
    #
    # 用户可以选择查询余额,取款,存款,贷款,办理借记卡,办理信用卡等操作,
    # 银行职员对象根据用户输入来调用自身的方法(使用反射)
    class Clerk:
        def balance(self):
            print('余额')
        def draw(self):
            print('取款')
        def saving(self):
            print('存款')
        def loan(self):
            print('贷款')
    
    cc = Clerk()
    while True:
        choose = input('<<<').strip()
        if hasattr(cc,choose):
            func = getattr(cc,choose)
            func()
        else:
            print('输入错误')
    
    #
    # 2,简述类方法与静态方法的区别,子类能否调用父类的静态方法?
    # 类方法就是将类作为对象进行操作的方法
    # 静态方法就是一个在类中的普通函数
    # 可以
    # 静态方法中如果想要调用所在类的类属性,能否调用的到?
    # 可以
    # 3,定义一个特工类,特工有真实的姓名,年龄,身高体重肤色等信息。但这些信息应该对外隐藏。
    # 再定义各项属性的取值/设置/删除的方法,外界访问到的并不是真实信息,同时将这些方法伪装成属性
    class Agent:
        def __init__(self,name,age,height):
            self.__name = name
            self.__age = age
            self.__height = height
    
        @property
        def name(self):
            return self.__name
        @name.setter
        def name(self,arg):
            self.__name = arg
        @name.deleter
        def name(self):
            print('已删除')
            del self.__name
    
    aa = Agent('alex',83,50)
    print(aa.name)
    aa.name = 'baoyuan'
    print(aa.name)
    del aa.name
    print(aa.name)
    
    
    #
    # 4,编写一个飞机驾驶员类,要求战斗机飞行员,民航驾驶员,滑翔机驾驶员都必须实现其中的方法(使用两种方式来做约束)
    # 方式一:通过父类抛出异常方式进行约束
    class Pilot:
        def func(self):
            raise Exception('听话,别闹')
    class Zd(Pilot):
        def func(self):
            print('战斗机飞行员')
    class Mh(Pilot):
        def func(self):
            print('民航驾驶员')
    class Hx(Pilot):
        def func(self):
            print('滑翔机驾驶员')
    
    def jiekou(tool):
        tool.func()
    zd = Zd()
    mh = Mh()
    hx = Hx()
    jiekou(hx)
    
    # 方式二:通过抽象类的方式进行约束
    from abc import ABCMeta,abstractmethod
    class Pilot(metaclass=ABCMeta):
        @abstractmethod
        def func(self):
            pass
    class Zd(Pilot):
        def func(self):
            print('战斗机飞行员')
    class Mh(Pilot):
        def func(self):
            print('民航驾驶员')
    class Hx(Pilot):
        def func(self):
            print('滑翔机驾驶员')
    zd = Zd()
    #
    # 5,将反射用到的函数整理成笔记,尝试用自己话来描述每个函数的作用
    class Person:
        a = 0
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def func(self):
            print(111)
    
    pp = Person('alex',83)
    # 1.
    # hasattr(对象名,'属性')===>判断该对象是不是有该属性
    # print(hasattr(pp,'name'))
    
    # 2.
    # getattr(对象名,'属性',[默认值])===>获取该对象的该属性的值(相当于 查)
    # 默认值可写可不写:如果该对象有该属性,则可以print出来.
    #               如果没有,显示默认值,不写默认值则报错
    # print(getattr(pp,'name'))
    # print(getattr(pp,'sex','没有'))
    # print(pp.sex)
    
    # 3.
    # setattr(对象名,'属性',值)===>设置该对象的该属性的值(相当于 改)
    # 如果该对象有该属性,则修改成后面的值;如果没有,就增加该属性,该属性的值就是后面的值
    # setattr(pp,'name','baoyuan')
    # print(pp.name)
    # setattr(pp,'sex','女')
    # print(pp.__dict__)
    # print(pp.sex)
    # print(getattr(pp,'sex','XX'))
    
    # 4.
    # delattr(对象名,'属性')===>删除该对象的该属性(相当于 查)
    # delattr(pp,'name')
    # print(pp.name)
    
    
    # 1,编写一个计算减法的方法,当第一个数小于第二个数时,抛出“被减数不能小于减数"的异常
    
    def func(a,b):
        if a < b:
            raise Exception('被减数不能小于减数')
        else:
            return a-b
    
    print(func(1,2))
    
    
    class Js(Exception):
        def __init__(self,a,b):
            self.a = a
            self.b = b
    
    def jianfa(a,b):
        try:
            print(a-b)
            if a < b:
                raise Js(a,b)
        except Js:
            print('JisuanError:被减数不能小于减数')
    
    jianfa(1,2)
    
    # 2,info = ['http://xxx.com','http:///xxx.com','http://xxxx.cm'....]任意多的网址.定义
    # 一个方法get_page(listindex) listindex为下标的索引,类型为整数。 函数调用:任意输入一个整
    # 数,返回列表下标对应URL的内容,用try except 捕获列表下标越界
    
    def get_page(listindex):
        info = ['http://xxx.com', 'http:///xxx.com', 'http://xxxx.cm']
        listindex = int(input("请输入网址序号:"))
        try:
            print(info[listindex])
        except IndexError:
            print('请输入有效序号')
    
    get_page(1)
    # 3,让一个人类对象,可以使用len()方法获得身高属性的值
    #
    class Person:
        def __init__(self,name,length):
            self.name = name
            self.length = length
        def __len__(self):
            return self.length
    pp = Person('alex',1)
    print(len(pp))
    # 4,定义人类对象,用print直接打印时可以获得该对象的属性信息
    #
    class Person:
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def __str__(self):
            return self.name+'
    '+str(self.age)
    pp = Person('alex',83)
    print(pp)
    # 5,尝试捕获
    # KeyError
    
    dic = {1:'alex',2:'wusir',3:'baoyuan'}
    num = int(input('请输入序号:'))
    try:
        print(dic[num])
    except KeyError:
        print('请输入有效序号')
    
  • 相关阅读:
    Interesting Finds: 2008.06.12
    8月19号
    8月22号
    8月20号
    8月21号
    第七章 Nginx配置虚拟主机
    第六章 Nginx配置文件详解
    第五章 Nginx搭建上传作业平台
    sqlserver2005提供的xml数据类型操作xml串
    事必躬亲利与弊
  • 原文地址:https://www.cnblogs.com/richard_A/p/12157142.html
Copyright © 2020-2023  润新知