• 面向对象


    1、
    class GirlFriend(object):
    #定义女朋友类:
    eyes = 2
    #类属性(静态属性),是属于当前类的
    #当前类的所有对象,所共有的特征
    sex = "女"
    """
    说明
    """
    #初始化方法
    def __init__(self,name,age,height,weight):
    #实例属性
    self.name = "qwe"
    self.age = age
    self.height = height
    self.weight = weight
    #函数属性
    def xiyifu(self):
    #定义洗衣服功能:
    print(self.name,"洗衣服")
    def chuitu(self):
    #定义捶腿功能:
    print("捶腿")
    def tiwolianji(self):
    #定义替我联机功能:
    print("打怪升级")

    2、
    #调用类属性,需要使用类名去调用(对象名也可以调用,但是不建议)
    # print(GirlFriend.name)

    3、
    #类名不能调用实例属性,也不要去调用实例方法
    print(GirlFriend.eyes)

    4、
    #可以在对象创建时,就让他拥有不同的属性值
    girl_1 = GirlFriend("迪丽热巴",18,170,170)
    #通过对象调用类属性,没问题
    #但是不能修改
    print(girl_1.eyes)

    5、
    #如果通过对象去修改类属性,会创建一个新的实例属性,这个实例属性在对象中会覆盖掉类属性
    girl_1.eyes = 3
    GirlFriend.eyes = 3
    print("girl1的",girl_1.eyes)

    6、
    #实例属性的增加
    girl_1.money = 100

    7、
    #实例属性的删除
    del girl_1.name

    8、
    #实例属性的修改
    girl_1.age = 19

    9、
    #实例属性的查看
    print(girl_1.age)

    10、
    #修改某个对象的实例属性,对当前类的其他对象,没有任何影响
    #如果,在类中做了修改,所有对象都会发生改变
    girl_1.chuitu()
    girl_1.tiwolianji()
    # girl_1.name = "迪丽热巴"
    #在类的外部,给对象添加属性
    # girl_1.money = 100
    # print(girl_1.money)

    girl_2 = GirlFriend("baby",35,120,250)
    print(girl_2.name)
    print("girl2的",girl_2.eyes)

    11、
    #定义天使:
    #光圈,翅膀,有眼睛,有腿等等,漂亮,善良,会飞,有法力,能打坏人,能救人,治疗
    #类是一个模板(里面放了一些属性和方法)
    #对象(也叫当前类的一个实例),是通过类创建出来的,用来完成具体工作

    12、
    #设计程序的思路:
    #首先,根据需求,来设计类,这个过程被称为"抽象",从真实存在的事务当中,抽象出共同的属性和方法

    13、
    # #类名,大家约定俗成,首字母大写
    # class Person:
    # def __init__(self):
    # #放属性
    # self.name = "小明"
    # self.age = 18
    # #方法和属性,只关心完成当前工作所需要的
    # def eat(self):
    # #具体的工作(算法)
    # print("人可以吃东西")
    # #self:哪个对象调用了当前方法,self就代表谁
    # def run(self):
    # print(self.name)
    # print("人会跑")
    #
    # #创建对象(实例化)
    # 小明 = Person()
    # 小明.run()
    # print(小明.name,小明.age)

    14、
    # class Hero:
    # def __init__(self,name,HP,MP,ATK):
    # self.name = name
    # self.hp = HP
    # self.mp = MP
    # self.atk = ATK
    # def jineng1(self):
    # print("电光毒龙钻")
    # self.hp -= 20
    #
    # def jineng2(self):
    # print("摸鸡头下蛋")
    #
    # alex = Hero("alex",100,200,250)
    # bigB = Hero("元宝",200,50,300)
    # alex.at = 123123123
    # del alex.jineng1
    # alex.jineng1()
    # if alex.hp <= 0:
    # del alex
    # alex.atk = 20
    # print(alex.name)

    15、
    # 创建一个英雄类:
    # • 包含英雄的各项属性:例如血量魔法值等等(注意哪些应该是类属性,哪些应该作
    # 为实例属性)
    # • 英雄有自残的能力,自残后会掉血
    # class Hero:
    # def __init__(self,hp):
    # self.hp = hp #血量
    # self.mp = 200 #魔法值
    # def zican(self):
    # print("我钻我自己")
    #自身数量值减1
    # self.hp -= 1

    16、
    # • 创建一个狗类:
    # • 包含名字,颜色,品种,年龄,性别等属性
    # • 有一个自我介绍的方法,打印自身的属性信息(我叫XXX。。。)
    # • 狗有看家的能力,狗有叫的能力,在看家方法中调用叫的方法
    # class Dog:
    #定义狗类:
    # def __init__(self,name,color,type,age,sex):
    #实例化姓名、颜色、品种、年龄、性别
    # pass
    # def ziwojieshao(self):
    # print("我叫",self.name,)
    # def kanjia(self):
    #类里面的方法相互调用:
    # self.jiao()
    # def jiao(self):
    # print("汪~汪~")
    # douding = Dog()
    # douding.kanjia()

    17、
    num = 0
    class Hero:
    num = 0
    def __init__(self):
    self.name = "abc"
    Hero.num += 1 #数量自加1
    def run(self):
    print("会跑")
    for i in range(10):
    "循环调用10圈"
    alex = Hero()
    bigB = Hero()
    a = Hero()
    print(Hero.num)

    18、
    ## 面向过程(函数式编程)

    通过数学逻辑去解决问题(设计算法,得到想要的结果)

    函数式编程:提高了代码的复用性,提高了维护性

    ## 面向对象

    python中 万物皆对象

    面向过程,的程序,执行效率高

    面向对象,的开发效率高

    类:一类具有相同特征的事物的总称

    对象:通过类,创建的一个具体事务,用来完成工作

    基础数据结构(列表,元组...)是数据的封装,函数是算法的封装

    类:是抽象出来的,数据和算法都能封装,可维护性更高,能处理更复杂的问题,代码逻辑更清晰

    创建类和对象的格式

    过程描述:

    1,抽象

    2,通过抽象出的内容来设计类

    3,class 类名:

    ​ 属性

    ​ def __init__(self):

    ​ self.XXX = XXX

    ​ 方法

    ​ 函数定义一样

    4,创建对象:

    对象名 = 类名()

    5,调用对象的属性和方法使用万能的点.

    创建对象时:

    1,在内存中开辟一块空间

    2,自动调用init方法
    python27day18面向对象--------------------------------------------------------------------------------------------
    1、
    #方法和函数究竟有什么区别

    class Person:
    def abc(self):
    pass

    a = Person()
    print(type(a.abc))
    print(type(Person.abc))
    #通过对象去调用时,是方法
    #其他情况,比方说通过类名调用,或者放在类外的时候叫函数

    2、
    #例一:
    class Baooy:
    def __init__(self,name,girlFriend = None):
    self.name = name
    self.girlFriend = girlFriend
    def eat(self):
    if self.girlFriend:
    print(f"{self.name}带着他的女朋友{self.girlFriend}去吃饭")
    else:
    print("单身狗,吃狗粮")
    def movie(self):
    if self.girlFriend: #加self确认的
    print(f"{self.name}带着他的女朋友{self.girlFriend}去看电影") #打印时一定加上self
    else:
    print("单身狗,回家看")
    a = Baooy("zs","zs1")
    a.eat() #对象调用函数属性:
    a.movie()

    3、
    # class Person:
    # def __init__(self,name,age):
    # self.name = name
    # self.hp = 100
    # def play(self,tool):
    # print(self.name,"钻",tool.name)
    # tool.hp -= 20
    # print(tool.name,"还有",tool.hp,"点血")
    # def kanjia(self,tool):
    # tool.kanjia()
    # class Dog:
    # def __init__(self,name,hp):
    # self.name = name
    # self.hp = hp
    # def kanjia(self):
    # print("汪~汪~~")
    #
    # alex = Person("Alex",83)
    # bigB = Person("宝元",76)
    # alex.play(bigB)
    # xiaohei = Dog("小黑",20)
    # bigB.kanjia(xiaohei)

    4、
    #关联关系就是在一个类的方法当中,引入了另一个对象(另一个类的对象)
    # 定义一个英雄类和一个反派类
    # • 两个类都包含名字、血量,攻击力(ATK),和一个技能(skill)
    # • 两派对象互殴
    # • 血量为0死亡,删除对象(del 对象名)
    import random
    class Hero:
    def __init__(self,name,hp,atk):
    self.name = name
    self.hp = hp
    self.atk = atk
    def skill(self,tool): #tool = alex
    print(self.name,"对",tool.name,"使出了波动拳") #name = 宝元,tool = alex
    tool.hp -= self.atk * random.randint(1,5)/2
    class Boss:
    def __init__(self,name,hp,atk): #name = alex
    self.name = name
    self.hp = hp
    self.atk = atk
    def skill(self,tool):
    print(self.name,"对",tool.name,"使出了独孤九剑") #name = alex、tool = bigB、tool.name = bigB.name = 宝元
    tool.hp -= self.atk * random.randint(1,5)/2
    bigB = Hero("宝元",200,15)
    alex = Boss("alex",150,20)
    while True:
    bigB.skill(alex)
    alex.skill(bigB)
    if bigB.hp <= 0:
    print("游戏结束")
    del bigB #删除Hero的实例
    break
    if alex.hp <= 0:
    print("游戏结束")
    del alex #删除Boss的实例
    break
    结果: 宝元 对 alex 使出了波动拳
    alex 对 宝元 使出了独孤九剑
    宝元 对 alex 使出了波动拳
    alex 对 宝元 使出了独孤九剑
    宝元 对 alex 使出了波动拳
    alex 对 宝元 使出了独孤九剑
    宝元 对 alex 使出了波动拳
    alex 对 宝元 使出了独孤九剑
    宝元 对 alex 使出了波动拳
    alex 对 宝元 使出了独孤九剑
    游戏结束

    5、
    # class Father(object):
    # #在py3中,如果一个类,没有显式的继承任何一个类,那么他默认继承object
    # # def __init__(self,name,age):
    # # self.name = name
    # # self.age = age
    # def livelikeyemen(self):
    # print("打妈妈")
    # class Son:
    # def __init__(self,f):
    # self.f = f
    # def abc(self):
    # self.f.livelikeyemen()
    # #父类方法重写
    # def livelikeyemen(self):
    # print("打妹妹")
    # daming = Father()
    # xiaoming = Son(daming)
    # xiaoming.abc()

    6、
    # class Anm(object):
    # """定义动物类"""
    # def __init__(self,name,age):
    # """实例化姓名和年龄"""
    # self.name = name
    # self.age = age
    # def run(self):
    # """定义跑的方法"""
    # print("123")
    # class Dog(Anm):
    # """定义狗类继承动物类"""
    # #如果子类也有自己的初始化方法,可能会出错
    # #解决方式,在子类的init方法里面,调用父类的init方法用super()
    # def __init__(self,name,age):
    # self.xihuanshi = True
    # super().__init__(name,age)
    # def jump(self):
    # print("跳")
    # def run(self):
    # print("abc")
    # """调用动物类的跑方法"""
    # Anm.run(self)
    # """运行动物类的跑方法"""
    # super().run()
    # class Cat(Dog):
    # """定义猫类继承狗类"""
    # def __init__(self):
    # """调用狗类里面的init方法用super()"""
    # super().__init__()
    # def jiao(self):
    # print("喵喵~~~")
    # a = Dog("动物",20)
    # a.run()

    7、
    class 蛇:
    def __init__(self):
    self.ya = 2
    def panta(self):
    print("pan")
    def run(self):
    print("123")
    class 蜘蛛:
    def __init__(self):
    eyes = 8
    jiao = 8
    def 吐丝(self):
    print("cici")
    def run(self):
    print("456")
    class 人(蜘蛛,蛇):
    pass
    # def __init__(self, name,age):
    # self.name = name
    # self.age = age
    # super().__init__()
    xiaoming = 人()
    xiaoming.run()

    8、
    # 类之间的关系

    ## 依赖关系:执行某个动作的时候,需要其他类的对象来帮助你完成这个动作
    就是将一个类的对象或者类名放到另一个类的方法当中就叫依赖
    此时,类之间的关系是最轻的,因为随时可以更换其他对象

    9、
    class Person:
    def play(self,tools):
    tools.run()
    print("我要打游戏了")
    class Compture:
    def run(self):
    print("电脑已经打开,DNF已登录")
    class Phone:
    def run(self):
    print("王者荣耀已经登陆")
    xiaoMing = Person()
    xmPhone = Phone()
    hwCom = Compture()
    xiaoMing.play(xmPhone) #一个类的对象或者类名放到另一个类的方法当中
    xiaoMing.play(hwCom) #一个类的对象或者类名放到另一个类的方法当中
    结果: 王者荣耀已经登陆
    我要打游戏了
    电脑已经打开,DNF已登录
    我要打游戏了

    10、
    ## 组合关系:将一个类的对象,放到另一个类的属性中(作为一个组成部分)
    一对一关系
    一对多关系
    一对一关系:
    class Baooy:
    def __init__(self,name,girlFriend = None):
    self.name = name
    self.girlFriend = girlFriend
    def eat(self):
    if self.girlFriend:
    print(f"{self.name}带着他的女朋友{self.girlFriend.name}去吃饭")
    else:
    print("单身狗,吃狗粮")
    def movie(self):
    if self.girlFriend:
    print(f"{self.name}带着他的女朋友{self.girlFriend.name}去看电影")
    else:
    print("单身狗不配看电影")
    class Girl:
    def __init__(self,name):
    self.name = name
    bao = Baooy("宝哥")
    friend = Girl("唐艺昕")
    bao.eat()
    bao.movie()
    bao.girlFriend = friend
    bao.eat()
    bao.movie()
    结果: 单身狗,吃狗粮
    单身狗不配看电影
    宝哥带着他的女朋友唐艺昕去吃饭
    宝哥带着他的女朋友唐艺昕去看电影

    11、
    ## 继承关系:在不改变现有类的情况下,扩展这个类,子类可以获得父类的所有属性和方法
    通过继承创建的新类称为"子类"或"派生类",被继承的类称为"基类"、"父类"或"超类"
    在python中,同时支持单继承与多继承
    增加了类的耦合性(耦合性不宜多,宜精)
    减少了重复代码
    使得代码更加规范化,合理化

    单继承:子类可以继承父类的属性和方法,修改父类,所有的子类都会受影响。

    python有两个判断继承的函数
    isinstance()用于检查实例类型:isinstance(对象,类型)
    issubclass()用于检查类继承:issubclass(子类,父类)

    继承的格式:

    class 子类名(父类名):

    子类可以定义自己的方法,也可以定义和父类同名的方法(方法重写),这时,子类方法会覆盖掉父类的同名方法、

    super()关键字在当前类中调用父类方法

    super()关键字:
    ·子类如果编写了自己的构造方法,但没有显式调用父类的构造方法,而父类构造函数初始化了一些属性,就会出现问题
    ·如果子类和父类都有构造函数,子类其实是重写了父类的构造函数,如果不显式调用父类构造函数,父类的构造函数就不会被执行
    ·解决方式:调用超类构造方法,或者使用super函数super(当前类名,self).__init__()

    因此,如果子类和父类都拥有自己的初始化方法,需要在子类的初始化方法中调用父类的init方法

    多重继承:包含多个间接父类
    多继承
    ·有多个直接父类
    ·大部分面向对象的编程语言(除了C++)都只支持单继承,而不支持多继承
    ·多继承不仅增加了编程的复杂度,而且很容易导致一些莫名的错误
    ·Python虽然在语法上明确支持多继承,但通常推荐如果不是很有必要,则尽量不要使用多继承,而是使用单继承
    ·这样可以保证编程思路更清晰,而且可以避免很多麻烦
    ·如果多个直接父类中包含了同名的方法
    ·此时排在前面的父类中的方法会“遮蔽”排在后面的父类中的同名方法

    class YeYe:
    def __init__(self):
    print("初始化爷爷")
    class Qinba(YeYe):
    def __init__(self):
    print("进入亲爸类")
    YeYe.__init__(self)
    print("初始化亲爸")
    class GanDie(YeYe):
    def __init__(self):
    print("进入干爹类")
    YeYe.__init__(self)
    print("初始化干爹")
    class ErZi(Qinba,GanDie):
    def __init__(self):
    Qinba.__init__(self)
    GanDie.__init__(self)
    print("初始化儿子")
    bigB = ErZi()
    结果: 进入亲爸类
    初始化爷爷
    初始化亲爸
    进入干爹类
    初始化爷爷
    初始化干爹
    初始化儿子

    12、
    调用方式为

    ```
    父类名.__init__(self)
    ```

    如果只是想操作另一个类的对象,用依赖

    如果两个类当中存在has a 的关系,用组合

    如果是is a 的关系,用继承(尽量少用继承,多用组合)

    13、
    新式类:继承了object的类,就叫新式类

    经典类:没有继承object的类

    py3中,所有的类都是新式类

    py2中,如果没有显式继承,那么这个类就没有集成任何类,所以有经典类,也有新式类

    # class Boy:
    # def __init__(self,name,tools = None):
    # self.name = name
    # self.girl = tools
    # def play(self):
    # if self.girl:
    # print(self.name,"玩",self.girl.name)
    # else:
    # print("单身狗玩自己吧")
    #
    # class Girl:
    # def __init__(self,name):
    # self.name = name

    # class Hero:
    # def __init__(self,wuqi,hujia):
    # self.wuqi = wuqi
    # self.hujia = hujia
    # def skill(self,tool):
    # print(f"用{self.wuqi.name}打{tool.name}")

    #组合关系:将一个类的对象,作为另一类的属性

    #一对多关系
    class Person:
    def __init__(self):
    self.girl = []
    def bamei(self,g1):
    self.girl.append(g1)
    def play(self):
    for i in self.girl:
    print(i.name,end=" ")
    i.play()
    class Girl:
    def __init__(self,name,age):
    self.name = name
    self.age = age
    def play(self):
    print("陪玩")
    girl1 = Girl("小丽",18)
    girl2 = Girl("贾玲",30)
    girl3 = Girl("韩红",50)
    bigB = Person()
    bigB.bamei(girl3)
    bigB.bamei(girl1)
    bigB.play()
    结果: 韩红 陪玩
    小丽 陪玩

    class Boy:
    def __init__(self):
    self.girl_list = []
    def baMei(self,girl):
    self.girl_list.append(girl)
    def happy(self):
    for i in self.girl_list:
    i.play()
    class Girl:
    def __init__(self,name):
    self.name = name
    def play(self):
    print(f"{self.name}和你一起玩")
    bao = Boy()
    friend1 = Girl("唐艺昕")
    friend2 = Girl("迪丽热巴")
    friend3 = Girl("杨颖")
    bao.baMei(friend1)
    bao.baMei(friend2)
    bao.baMei(friend3)
    bao.happy()
    结果: 唐艺昕和你一起玩
    迪丽热巴和你一起玩
    杨颖和你一起玩

    14、
    # 定义一个用户类,用户名和密码是这个类的属性,实例化两个用户,分别有不同的用户名和密码
    # 登陆成功之后才创建用户对象
    # 设计一个方法 修改密码
    # class User:
    # def __init__(self,name,pw):
    # self.name = name
    # self.pw = pw
    # def rPassW(self):
    # newPW = input("请输入新密码")
    # self.pw = newPW
    # num = 0
    # while True:
    # userName = input("请输入用户名")
    # userPW = input("请输入密码")
    # if userName == "alex" and userPW == "123123":
    # xiaoming = User("xiaoming","123abc")
    # xiaoli = User("xiaoli","123456")
    # break
    # else:
    # print("输入有误!,请重新输入!")
    # num += 1

    15、
    # 定义一个列表的操作类:Listinfo
    # 包括的方法:
    # 1 列表元素添加: add_key(keyname) [keyname:字符串或者整数类型]
    # 2 列表元素取值:get_key(num) [num:整数类型]
    # 3 列表合并:update_list(list) [list:列表类型]
    # 4 删除并且返回最后一个元素:del_key()
    # list_info = Listinfo([44,222,111,333,454,'sss','333'])
    # class ListInfo:
    # def __init__(self, lis):
    # self.lis = lis
    # def add_Key(self, keyname):
    # self.lis.append(keyname)
    # def get_key(self,num):
    # return self.lis[num]
    # def update_list(self, new_list):
    # self.lis + new_list
    # def del_key(self):
    # return self.lis.pop()

    15、
    # class A:
    # Country = ['中国'] # 静态变量/静态属性 存储在类的命名空间里的
    # def __init__(self,name,age,country): # 绑定方法 存储在类的命名空间里的
    # self.name = name
    # self.age = age
    # def func1(self):
    # print(self)
    # a = A('alex',83,'印度')
    # b = A('wusir',74,'泰国')
    # a.Country[0] = '日本'
    # print(a.Country)
    # print(b.Country)
    # print(A.Country)
    结果: ['日本']
    ['日本']
    ['日本']
    python27day20面向对象--------------------------------------------------------------------------------------------
    封装”就是将抽象得到的数据和行为相结合,形成一个有机的整体
    ·元组,列表,字典等等:数据的封装,通过引用去使用数据
    ·函数:算法的封装
    ·没有函数,功能靠每一行代码去直接执行·耦合度太高,复用性太差,开发效率太低

    封装的目的是简化编程和增强安全性
    ·使用者不必关心该类具体的实现细节
    ·通过接口(万能的点)
    ·还可以给予的特定的访问权限来使用类的成员
    ·明确区分内外:
    ·类的实现者可以修改内部封装的东西而不影响外部调用者
    ·外部调用者只需要知道自己可以使用该类对象的哪些功能

    私有属性,私有方法
    ·“双下划线”开始的是私有成员,在类外部不可以直接用属性或方法名调用,子类中也不能访问到这个数据
    ·可以提供外界访问的接口
    ·将不需要对外提供的内容都隐藏起来
    ·把属性都隐藏,提供公共方法对其访问
    ·双下滑线开头的属性在继承给子类时,子类是无法覆盖的

    class Abc:
    def __init__(self):
    self.__name = "abc"
    def __set(self,x):
    self.__name = x
    def get_name(self):
    print(self.__name)
    a = Abc()
    print(a.__name) #直接访问找不到
    结果:AttributeError: 'Abc' object has no attribute '__name' (AttributeError:“Abc”对象没有属性“u name”)
    a.get_name() #通过类里面的函数属性可以找到
    结果:abc

    破解私有属性和私有方法:
    ·在名称前加上_类名,即_类名__名称
    ·其实加双下划线仅仅是一种变形操作
    ·类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式

    class Abc:
    def __init__(self):
    self.__name = "abc"
    def __set(self):
    print("111")
    def get_name(self):
    print(self.__name)
    a = Abc()
    a._Abc__set()
    结果:111

    多态体现1:python是一种多态语言,不关心对象的类型
    ·对于弱类型的语言来说,变量并没有声明类型,因此同一个变量完全可
    以在不同的时间引用不同的对象
    ·毫无疑问,在python中对象是一块内存,内存中除了包含属性、方法之
    外,还包含了对象类型,我们通过引用来访问对象,比如a=A(),首先
    python创建一个对象A,然后声明一个变量a,再将变量a与对象A联系起
    来。变量a是没有类型的,它的类型取决于其关联的对象

    class Bird:
    def move(self,field):
    print("鸟在%s上自由地飞翔" %field)
    class Dog:
    def move(self,field):
    print("狗在%s里飞快的奔跑" %field)
    x = Bird()
    x.move("天空")
    x = Dog()
    x.move("草地")
    结果: 鸟在天空上自由地飞翔
    狗在草地里飞快的奔跑

    同一个变量x:在执行同一个move()方法时,由于x指向的对象不同,因此呈现
    出不同的行为特征,这就是多态。

    多态体现2:一类事物有多种形态(polymorphic)
    ·一个抽象类有多个子类,但方法实现不同
    ·例如:动物类有多个子类,每个子类都重新实现了父类的某个方法,但
    方法的实现不同(休息的方法)
    ·此时需要有继承,需要有方法重写

    栈Stack和队列Queue实现put和get方法:
    class Stack:
    def __init__(self):
    self.lis = []
    def put(self,num):
    self.lis.append(num)
    def get(self):
    if self.lis != []:
    return self.lis.pop()
    class Queue:
    def __init__(self):
    self.lis = []
    def put(self,num):
    self.lis.append(num)
    def get(self):
    if self.lis != []:
    return self.lis.pop(0)

    # 数据结构:数据在内存中的存放顺序

    栈/队列
    栈:FILO--3,2,1
    队列:FIFO--1,2,3
    l = []
    l.put(1)
    l.put(2)
    l.put(3)

    l.get()
    l.get()
    l.get()

    多态:
    体现一:python中一个引用,可以指向不同类型的对象
    体现二:一类事物,有多种形态
    多态性:
    在继承和方法重写的基础上,定义一个统一的接口,不关心传入对象的类型,只关心实现了哪些方法

    python崇尚鸭子类型
    ·不关心类型,不需要继承,只关注方法实现,这种情况被称为鸭子类型
    ·“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子
    ·在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的

    总结:Python本身就是支持多态性的
    ·增加了程序的灵活性(通用性),以不变应万变,不论对象千变万化,使用者都是同一种形式去调用
    ·增加了程序的可扩展性,通过继承某个类创建了一个新的类,接口使用者无需更改自己的代码,还是用原方法调用

    对比:
    ·多态强调的是:一类事物不同的形态
    ·多态性强调的是:同一操作,作用对象不同,表现出不同实现方式(只关心行为结果)

    class Car:
    def __init__(self,color):
    self.color = color
    def run(self):
    print(self.color,"小汽车在跑")
    class Cat:
    def __init__(self,name):
    self.name = name
    def run(self):
    print("猫咪",self.name,"在跑")
    a = Car("红色")
    a.run()
    结果:红色 小汽车在跑
    b = Cat("白色")
    b.run()
    结果:猫咪 白色 在跑

    有时通过单一对象方便集中管理资源
    ·单例模式是保证一个类仅有一个实例的设计模式
    ·保证了在程序的不同位置都可以且仅可以取到同一个对象实例:如果实例不存在,会创建一个实例;如果已存在就会返回这个实例。

    设计模式:处理特定问题,可重用解决方案
    创建单例模式:
    class Danli:
    ins = None
    def __new__(cls, *args, **kwargs):
    if cls.ins == None:
    cls.ins = object.__new__(cls)
    return cls.ins
    def __init__(self):
    pass
    class Boy(Danli):
    pass
    class Girl(Danli):
    pass
    xiaoming = Danli()
    print(id(xiaoming))
    结果:35486800
    xiaoHong = Danli()
    print(id(xiaoHong))
    结果:35486800

    工厂模式是不直接暴露对象创建细节,而是通过一个共用类创建对象的设计模式,需要4步:创建基类-创建子类-创建工厂类-使用工厂模式

    class Girl:
    pass
    class Boy:
    pass
    class Dog:
    pass
    class Cat:
    pass
    class Alex:
    pass
    class Gongchang:
    def re_Per(self,arg):
    if arg == "G":
    return Girl()
    elif arg == "B":
    return Boy()
    print("没有")
    约束:指的是对类的约束
    在一些重要的逻辑,与用户数据相关等核心部分,要建立一种约束,避免发生此类错误

    类的约束有两种解决方式:
    方式一:在父类建立一种约束(通过抛出异常)
    提取⽗类,在⽗类中定义好⽅法,在这个⽅法中抛⼀个异常。这样所有的⼦类都必须重写这个⽅法.
    否则. 访问的时候就会报错
    方式二:引入抽象类的概念

    举例:
    公司让小明给他们的网站完善一个支付功能,小明写了两个类,QQ支付和支付宝支付
    但是上面这样写不太放方便,也不合理,老大说让他整改,统一一下付款的方式,小明开始加班整理,使用归一化设计
    后来小明接了大项目,公司招了一个新的程序员春哥接替小明的工作,老大给春哥安排了任务,
    让他写一个微信支付的功能,春哥随意给微信支付类中的付钱方法起了一个方法名
    后来接手这个项目的程序员,也可能随意起名

    class Payment:
    def pay(self,money):
    raise Exception("子类必须实现pay方法")

    class QQpay(Payment):
    def pay(self,money):
    print(f"使用QQ支付{money}")

    class Alipay(Payment):
    def pay(self,money):
    print(f"使用Ali支付{money}")

    class Wechat(Payment):
    def zhifu(self,money):
    print(f"使用微信支付{money}")

    def pay(obj,money): #obj = Wechat() #归一化设计:
    obj.pay(money) #obj = Wechat()
    obj1 = QQpay()
    obj2 = Alipay()
    obj3 = Wechat()
    pay(obj3,300)
    结果:Exception: 子类必须实现pay方法
    pay(obj2,200)
    结果:使用Ali支付200

    解决方式二:
    用抽象类(制定一种规范)的概念,建立一种约束
    基类如下设置,子类如果没有定义父类里面的方法,在实例化对象时就会报错

    from abc import ABCMeta,abstractmethod
    class Abc123(metaclass=ABCMeta): #设置元类是metaclass是ABCMeta
    @abstractmethod
    def abc(self):
    pass
    @abstractmethod
    def dfg(self):
    pass
    class Qwer123(Abc123): #子类继承父类、父类里面的所有属性和方法子类里面必须有:
    def abc(self):
    print("123")
    def dfg(self):
    print("345")
    a = Qwer123()

    # 设置一个类的metaclass(元类)是ABCMeta
    # 那么这个类就变成了一个抽象类(接口类)
    # 这个类的功能就是建立一个规范
    # 由于该⽅案来源是java和c#. 所以不常用

    解决方式二:
    详解:
    Python本身不提供抽象类和接口机制,要想实现抽象类,可以借助abc模块。ABC是Abstract Base Class(抽象父类)的缩写
    abc.ABCMeta是用来生成抽象基础类的元类。由它生成的类可以被直接继承,但是抽象类不能直接创建对象(只能被继承)
    @abstractmethod表明抽象方法,如果子类不具备@abstractmethod的方法,那么就会抛出异常

    类方法:
    指一个类中通过@classmethod修饰的方法
    第一个参数必须是当前类对象,该参数名一般约定为“cls”,通过它来传递类的属性和方法(不能传实例的属性和方法)
    调用:实例对象和类对象都可以调用
    类方法是将类本身作为对象进行操作的方法

    使用场景分析:
    假设我有一个学生类和一个班级类,想要实现的功能为:
    执行班级人数增加的操作、获得班级的总人数
    学生类继承自班级类,每实例化一个学生,班级人数都能增加
    最后,我想定义一些学生,获得班级中的总人数
    因为我实例化的是学生,但是如果我从学生这一个实例中获得班级总人数,在逻辑上显然是不合理的
    同时,想要获得班级总人数,如果生成一个班级的实例也是没有必要的
    版一:
    class Class:
    pass
    class Student(Class):
    __num = 0
    def __init__(self,name):
    self.name = name
    Student.set_num()
    @classmethod
    def get_num(cls):
    return cls.__num
    @classmethod
    def set_num(cls):
    cls.__num += 1
    s = Student("qwe")
    print(Student.get_num())
    结果:1

    版二:
    class Student:
    __num = 0
    def __init__(self,name,age):
    self.name = name
    self.age = age
    Student.addNum()
    @classmethod
    def addNum(cls):
    cls.__num += 1
    @classmethod
    def getNum(cls):
    return cls.__num
    a = Student("qwe",11)
    print(Student.getNum())
    结果:1

    实例方法:对象调用,类名不建议调用
    实例属性:对象调用,类名不能调用
    类方法:通过类名去调用,对象也可以调用(尽量别)
    类属性:通过类名调用,对象也可以调用(尽量别)
    self,cls只能在类内使用,在类外无效

    静态方法:
    使用@staticmethod修饰的方法
    参数随意,没有“self”和“cls”参数,方法体中不能使用类或实例的任何属性和方法
    实例对象和类对象都可以调用
    详解:静态方法是类中的函数,不需要实例。静态方法主要是用来存放逻辑性的代码,逻辑上属于类,
    但是和类本身没有关系,也就是说在静态方法中,不会涉及到类中的属性和方法的操作。
    可以理解为,静态方法是个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护

    譬如,我想定义一个关于时间操作的类,其中有一个获取当前时间的函数

    import time
    class TimeTest(object):
    def __init__(self,hour,minute,second):
    self.hour = hour
    self.minute = minute
    self.second = second
    @staticmethod
    def showTime():
    return time.strftime("%H:%M:%S", time.localtime())
    print(TimeTest.showTime())
    结果:17:45:20
    t = TimeTest(2,10,10)
    nowTime = t.showTime()
    print(nowTime)
    结果:17:45:20

    上页中使用了静态方法(函数),然而方法体中并没使用(也不能使用)类或实例的属性(或方法)
    若要获得当前时间的字符串时,并不需要实例化对象,此时对于静态方法而言,所在类更像是一种名称空间
    其实,我们也可以在类外面写一个同样的函数来做这些事,但是这样做就打乱了逻辑关系,也会导致以后代码维护困难

    property:是一种特殊的属性,访问它时会执行一段功能(方法)然后返回值
    举例:
    BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解)
    成人的BMI数值:
    过轻:低于18.5
    正常:18.5-23.9
    过重:24-27
    肥胖:28-32
    非常肥胖, 高于32
    体质指数(BMI)=体重(kg)÷身高^2(m)
    shang:65kg÷(1.82×1.82)=19.623233908948194

    class People:
    def __init__(self,name,weight,height):
    self.name = name
    self.weight = weight
    self.height = height
    @property
    def bmi(self):
    return self.weight / (self.height**2)
    p1 = People("egon",75,1.85)
    print(p1.bmi)
    结果:21.913805697589478

    为什么要用property:
    将一个类的方法定义成属性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的
    这种特性的使用方式**遵循了统一访问的原则**

    属性一般具有三种访问方式,获取、修改、删除
    我们可以根据这几个属性的访问特点,分别将三个方法定义为对同一个属性的获取、修改、删除
    只有在属性定义property后才能定义setter,deleter

    class Person:
    def __init__(self,age):
    self.__age = age
    @property
    def age(self):
    return self.__age
    @age.setter
    def age(self,num):
    self.__age = num
    xiaoli = Person(100)
    print(xiaoli.age)
    结果:100
    xiaoli.age = 120
    print(xiaoli.age)
    结果:120

    property(get_AAA,set_AAA,delete_AAA)
    #内置property三个参数与get,set,delete一一对应

    class Student(object):
    def __init__(self,name,score):
    self.name = name
    self.__score = score
    def get_score(self):
    return self.__score
    def set_score(self,score):
    if 100 > score > 0:
    raise ValueError("invalid score")
    self.__score = score
    s = Student("Bob",59)
    print(s.name)
    结果:Bob
    s.set_score(60)
    print(s._Student__score)
    结果:ValueError: invalid score
    s.set_score(101)
    print(s._Student__score)
    结果:101

    只有@property定义只读,加上@setter定义可读可写,加上@deleter定义可读可写可删除

    class Student(object):
    def __init__(self,name,score):
    self.name = name
    self.__score = score
    @property
    def score(self):
    return self.__score
    @score.setter
    def score(self,score):
    if 100 > score > 0:
    print("数据有误!")
    self.__score = score
    @score.deleter
    def score(self):
    if 200 > score > 100:
    del self.__score
    s = Student("Bob",59)
    print(s.name)
    结果: 数据有误!
    Bob
    print(s.score)
    结果:59
    s1 = Student("Bob1",201)
    print(s1.score)
    结果:201
    del s1.score
    print(s1.score)
    结果:201
    s1 = Student("Bob1",101)
    print(s1.score)
    结果:101
    del s1.score
    print(s1.score)
    结果:AttributeError: 'Student' object has no attribute '_Student__score'

    结果:AttributeError: 'Student' object has no attribute '_Student__score'--AttributeError:“Student”对象没有“Student”score属性

    反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)

    python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

    有四个可以实现自省的函数:hasattr,getattr,setattr,delattr

    应用于对象的反射:
    class Girl:
    num = 0
    def __init__(self):
    self.name = "Alex"
    def run(self):
    print("人会跑")
    xiaohong = Girl()
    print(hasattr(xiaohong,"name"))
    结果:True
    print(getattr(xiaohong,"run"))
    结果:<bound method Girl.run of <__main__.Girl object at 0x0000000002717DA0>>
    print(getattr(xiaohong,"name1","没有"))
    结果:没有
    setattr(xiaohong,"name","宝元")
    print(getattr(xiaohong,"name"))
    结果:宝元
    setattr(xiaohong,"run","宝元")
    print(getattr(xiaohong,"run"))
    结果:宝元
    综合用法:
    getattr(obj, "age", setattr(obj, "age", "18"))

    应用于类的反射:
    class Foo(object):
    staticField = "old boy"
    def __init__(self):
    self.name = "wupeiqi"
    def func(self):
    return "func"
    @staticmethod
    def bar():
    return "bar"
    print(getattr(Foo,"staticField"))
    结果:old boy
    print(getattr(Foo,"func"))
    结果:<function Foo.func at 0x00000000027288C8>
    print(getattr(Foo,"bar"))
    结果:<function Foo.bar at 0x0000000002728AE8>

    应用于当前模块的反射:
    每当程序员导入新的模块,sys.modules(是一个字典)都将记录这些模块
    import sys
    def s1():
    print("s1")
    def s2():
    print("s2")
    this_module = sys.modules[__name__]
    print(hasattr(this_module,"s1"))
    结果:True
    a = getattr(this_module,"s2")
    a()
    结果:s2

    反射的应用举例:
    当我们打开浏览器,访问一个网站,单击登录就跳转到登录界面,单击注册就跳转到注册界面
    但是,你单击的其实是一个个的链接,每一个链接都会有一个函数或者方法来处理

    class User:
    def login(self):
    print("欢迎来到登录页面")
    def register(self):
    print("欢迎来到注册页面")
    def save(self):
    print("欢迎来到存储页面")

    没学反射之前的解决方式:
    while True:
    choose = input(">>>").strip()
    if choose == "login":
    obj = User()
    obj.login()
    elif choose == "register":
    obj = User()
    obj.register()
    elif choose == "save":
    obj = User()
    obj.save()

    学了反射之后的解决方式:
    user = User()
    while True:
    choose = input(">>>").strip()
    if hasattr(user,choose):
    func = getattr(user,choose)
    func()
    else:
    print("输入错误")
    内置方法:
    Python 的对象天生拥有一些神奇的方法,它们总被双下划线所包围

    __new__(cls[, ...])
    __new__ 是在一个对象实例化的时候所调用的第一个方法

    __init__(self[, ...])
    构造器,当一个实例被创建的时候调用的初始化方法

    __del__(self)
    析构器,当一个实例被销毁的时候调用的方法(建议不要重写)

    __len__
    通过len(obj)调用,返回值必须设置为int类型

    __hash__ 通过hash(obj)调用(一种消息摘要算法)
    hash() 用于获取取一个对象(非可变数据类型)的哈希值

    __str__
    打印对象时调用

    __eq__
    比较两个对象
    def __eq__(self,obj):
    if self.a == obj.a and self.b == obj.b:
    return True

    异常(Exception)是一个事件,该事件可能会在程序执行过程中发生,影响了程序的正常执行
    raise语句显式的抛出异常
    Python解释器自己检测到异常并引发它

    一般情况下,在Python无法正常处理程序时就会发生异常

    异常是Python对象,表示一个错误

    当Python程序发生异常时我们需要捕获处理它,否则程序会终止执行

    常见异常:
    SyntaxError语法错误
    IndentationError多打一个空格
    NameError 使用一个还未被赋予对象的变量
    TypeError 传入对象类型与要求的不符合 (int + str)
    IOError 输入/输出异常;基本上是无法打开文件
    ImportError 无法引入模块或包;基本上是路径问题或名称错误
    IndexError 下标索引超出序列边界
    KeyError 试图访问字典里不存在的键

    处理异常
    程序员编写特定的代码,专门用来捕捉这个异常(这段代码与程序逻辑无关,与异常处理有关)
    如果捕捉成功则进入另外一个处理分支,执行你为其定制的逻辑,使程序不会崩溃

    异常处理的方式1
    num1=input('>>: ') #输入一个字符串试试
    if num1.isdigit():
    int(num1) #我们的正统程序放到了这里,其余的都属于异常处理范畴
    elif num1.isspace():
    print('输入的是空格,就执行我这里的逻辑')
    elif len(num1) == 0:
    print('输入的是空,就执行我这里的逻辑')
    else:
    print('其他情情况,执行我这里的逻辑')

    num = int(input("请输入:"))
    for i in range(10):
    try:
    num = 5 / num
    except ZeroDivisionError:
    print("除数不能为0")
    except TypeError:
    print("类型错误")
    except KeyError:
    print("不存在的键")
    print(i)

    异常处理,可以捕获异常对象,然后作相应处理,让程序继续执行
    如果代码没出现异常,程序正常执行
    如果出现了是常,except 会尝试捕获,如果捕获成功,执行except下面的内容

    for和else的组合:
    for i in range(10):
    print(i)
    else:
    print(234)

    while和else的组合:
    while True:
    print(1)
    break
    else:
    print(234)

    try:
    被检测的代码块
    except 异常类型:
    try中一旦检测到异常,就执行这个位置的逻辑

    如果你不想在异常发生时结束你的程序,只需在try里捕获它
    首先,执行 try 子句 (在 try 和 except 关键字之间的部分)
    如果没有异常发生,except 子句在 try 语句执行完毕后就被忽略了
    如果在 try 子句执行过程中发生了异常,那么该子句其余的部分就会被忽略
    如果异常匹配于 except 关键字后面指定的异常类型,就执行对应的 except 子句。
    然后继续执行 try 语句之后的代码

    万能异常:
    except ... as ...
    使用exception as e:查看异常,以及是否按要求捕获到

    try:
    print(1/0)
    raise FileNotFoundError
    except Exception as e: #万能异常
    print(e)

    多分支+万能异常

    发生的异常中,有一些异常是需要不同的逻辑处理的,剩下的异常统一处理掉即可
    dic = {1: login,2: register,3: dariy,4: article,5: comment,}
    print('''欢迎访问博客园系统:
    1,登录
    2,注册
    3,访问日记页面
    4,访问文章页面
    5,访问评论页面''')
    try:
    choice = int(input('请输入:'))
    dic[choice]()
    except ValueError:
    print('请输入数字....')
    except KeyError:
    print('您输入的选项超出范围...')
    except Exception as e:
    print(e)

    try...except...else组合:
    与循环中的else类似,try代码中,只要出现了异常,则不会执行else语句,如果不出现异常,则执行else语句
    伪代码:
    try:
    print('扣第一个人钱')
    print('给第二个人加钱')
    except ValueError:
    print('必须输入数字。。。')
    else:
    print('转账成功')

    try...excet...finally组合:
    finally:最后一定要执行的语句块
    try:
    dic = {'name': 'shang'}
    print(dic[1])
    except KeyError:
    print('出现了keyError错误....')
    finally:
    print('正常执行')

    finally应用场景:
    1. 关闭文件的链接链接,数据等链接时,需要用到finally
    f = open('file',encoding='utf-8')
    try:
    '''各种操作'''
    print(f.read())
    '''但是发生错误了, 此时没关闭文件句柄,所以'''
    finally:
    f.close()

    函数中,finally也会在return之前先执行
    def func():
    try:
    return 1
    finally:
    print('finally')
    func()

    循环中
    while 1:
    try:
    break
    finally:
    print('finally')

    总结:finally一般是做收尾工作
    在一些重要环节出错之前必须一定要做的比如关闭链接的问题时,最好是用上finally作为最后一道防线,收尾。

    断言
    表示一种强硬的态度,只要assert后面的代码不成立,直接报错,下面的代码就不让你执行
    assert 条件
    代码
    代码
    ....... (类似if)

    自定义异常:
    python中提供的错误类型可能并不能解决所有错误

    如果以后你在工作中,出现了某种异常无法用已知的错误类型捕获(万能异常只能捕获python中存在的异常),
    那么你就可以尝试自定义异常,只要继承BaseException类即可

    自定义异常:
    class HelloError(Exception): #自定义异常类HelloError
    def __init__(self,n):
    self.n=n
    try:
    n=input("请输入数字:")
    if not n.isdigit():
    raise HelloError(n)
    except HelloError as hi:
    print("HelloError:请输入字符。 您输入的是:",hi.n)
    else:
    print("未发生异常")
  • 相关阅读:
    Java代码输出到txt文件(申请专利贴源码的必备利器)
    Vmware10组建局域网
    Ubuntu14.04更换阿里云源
    Ubuntu16.04如何彻底删除Apache2
    HustOJ平台搭建
    Centos 7 联想Y430P无线网卡驱动安装 过程参考
    Windows远程CentOS桌面
    centos 7 查看系统/硬件信息及运维常用命令+联想Y430P无线网卡驱动安装
    zookeeper工作原理、安装配置、工具命令简介
    centos 7 安装五笔输入法
  • 原文地址:https://www.cnblogs.com/zhang-da/p/11825001.html
Copyright © 2020-2023  润新知