5.Python基础之面向对象

Python基础之面向对象

面向对象的三大特性

面向对象都具有三大特性:封装继承多态

类和对象的关系

类是多个对象归纳总结而来的,是一种概念,包含所有对象。

由对象总结出类的过程,叫做抽象化

对象是类的具体实现或者实施而来,他是真实的,特指某个事物。

由类制作出对象的过程,叫做实例化

类的组成

类中只有2种内容:成员属性和成员方法

成员属性:
    用于描述类的特征的变量就是成员属性

成员方法:
    用于描述类的功能的函数就是成员方法

类的书写规则

  1. 必须使用class关键字来声明一个类
  2. 类的名称需要符合驼峰命名法(规范)
  3. 类中只能存在2种内容,成员属性和成员方法,除此之外,所有的代码都禁止出现!
  4. 声明成员属性时,所有成员属性必须有值,如果没值会报错!,推荐使用None等值代替
  5. 成员方法只需要按照函数的规则声明即可

实例化对象

实例化对象格式

对象变量 = 类()

类的类型为 type

<class 'type'>

类的值就是类本身

<class '__main__.Person'>

对象的类型为类

<class '__main__.Person'>

对象的值,对象本身

<__main__.Person object at 0x020DC650>
class GirlFriend:
    #属性
    sex = '女'
    age = 18
    height = '170'
    weight = '50kg'

    #方法
    def guan(self):
        print('逛逛!~~~')

    def eat(self):
        print(self)
        print('吃吃~~~')

    def cry(self):
        print('呜呜呜呜~')

检测类和对象的成员

检测类成员

类名.__dict__

检测对象成员

对象.__dict__

类和对象成员的操作

类成员操作

访问类中成员
    类名.成员属性名
    类名.成员方法名()      (没有参数要求,所有方法都可以通过类访问)

修改类中成员
    类名.成员属性名 = 值
    类名.成员方法名 = 新值  (如果需要函数只能用lambda)

删除类中成员
    del 类名.成员属性名
    del 类名.成员方法名

添加类中成员
    类名.新成员属性名 = 值
    类名.新成员方法名 = 值  (如果需要函数只能用lambda)

对象成员操作

访问对象中成员
    对象变量.成员属性名
    对象变量.成员方法名()  (必须有一个用于接收对象本身的形参)

修改对象中成员
    对象变量.成员属性名 = 值
    对象变量.成员方法名 = 新值  (如果需要函数只能用lambda)

删除对象中成员
    del 对象变量.成员属性名
    del 对象变量名.成员方法名

添加对象中成员
    对象变量.新成员属性名 = 值
    对象变量.新成员方法名 = 值 (如果需要函数只能用lambda)
#访问
print(GirlFriend.sex)#属性
GirlFriend.eat(1)#方法

#修改
print(GirlFriend.age)
GirlFriend.age = 38#属性
print(GirlFriend.__dict__)

#定义一个函数
def mycry():
    print('小姑娘,你别哭,来叔叔给你棒棒糖吃~')
GirlFriend.cry = lambda : print('啊呜啊呜啊呜啊呜~')#方法
GirlFriend.cry = mycry#方法
GirlFriend.cry()

#添加
GirlFriend.hobby = '玩枪'#属性
print(GirlFriend.__dict__)
GirlFriend.upsky = lambda : print('111!')#方法
GirlFriend.upsky()

#删除
del GirlFriend.upsky
print(GirlFriend.__dict__)
del GirlFriend.cry
print(GirlFriend.__dict__)

关于self

他不是关键字,是一个随意书写的字符串而已

1.英文单词的意义 :自己
2.绑定类的方法,只能通过类来访问的方法,就是绑定类的方法
3.非绑定类的方法,就是可以通过对象访问的方法就是非绑定的方法
4.绑定类与非绑定类的方法不取决于语法,而取决于设计者如何设计该方法
5.一般情况下非绑定类的方法第一个参数写单词self,但是这不是唯一的单词,写什么都行,self不是关键字,不是关键字,不是关键字!
class Human:
    #属性 -> 成员属性(变量)
    ear = 2
    mouth = 1
    sex = 'man'
    age = 28
    name = '章旺'
    married = False
    color = 'yellow'
    hair = None
    #特征 -> 成员方法(函数)
    def walk(self):
        print('直立行走')
    def eat(self):
        print('吃饭饭')
    def sleep(self):
        print('睡觉觉')
    def playgame(self):
        print('打游戏!')

#查看类的值
print(Human)
#类的类型
print(type(Human))
#实例化对象操作
wangwang = Human()
#打印对象的值
print(wangwang)
#打印对象的类型
print(type(wangwang))
#检测类的成员(在类中声明的成员都可以看到)
print(Human.__dict__)
#检测对象中的成员
print(wangwang.__dict__)
print(wangwang.sex)

封装特性

封装就是对类和对象的成员访问进行限制,设定可以访问的方式和不可以访问的方式。

封装的三个级别:

私有化封装      -> private  英文单词而已不是关键字
受保护的封装    -> protected  英文单词而已不是关键字
公共的封装      -> public 英文单词而不是关键字

检测封装的三个位置:

类中/对象中
类外部/对象外部
子类中

私有化封装 private

私有化封装是最高级别的封装。私有化封装之后的成员,只能在类中/对象中访问,类的外部,子类中都不可以访问到。

私有化封装:在成员名称前添加2个_即可
例如:封装heart -> __heart

python将heart 改名为 _类名__成员名  

封装后的访问限制:
    类中/对象中      可以访问
    类外/对象外      不可以访问
    子类/子类对象     不可以访问

**注意:**在python中实现的封装操作,不是通过权限限制而是通过改名(name mangling 改名策略)实现的,名字变了找不到而已。

可以通过 对象.类名 __方法或类名.类名 __方法名访问到(但禁止这么干)

class Human:
    #属性
    age = 18
    #私有化封装成员属性[只能在当前结构中使用]
    __sex = '男'
    color = 'yellow'
    hair = '黑色'

    #方法
    def say(self):
        print('阿姨啊~~~')

    def walk(self):
        print('嗖嗖的~')

    #私有化成员方法[只能在当前类或者对象的结构中访问]
    def __niao(self):
        print('嘘嘘~~')

    #测试:自己访问自己的私有成员
    def demo(self):
        #访问私有方法niao
        self.__niao()
        print('测试私有成员的访问')

受保护的封装 protected

受保护的封装是一定级别的封装,封装之后,只有部分位置可以访问(类和子类),部分位置(类外)不可以访问。

受保护的封装: 在成员名称前添加1个_即可
例如:受保护 money -> _money

封装后的访问限制:
    类中/对象中      可以访问
    类外/对象外      可以访问(原则上类外不行,但是没实现)
    子类/子类对象     可以访问

**注意:**受保护的封装依旧是通过name mangling的方式修改了成员的名称而已。

可以通过对象.类名成员 或者类名.类名成员的方式访问(但也别这么干)

#python语法中没有受保护的语法,程序员约定一种操作来实现受保护

class Father:
    #属性
    sex = 'man'
    #受保护的
    _money = 1000
    color = 'yellow'
    #私有化
    __wife = '小泽亚'

    #方法
    def eat(self):
        print(Father._money)
        print('吃吃吃吃~~')

    def niao(self):
        print('哗哗哗哗~~')

class Son(Father):
    #添加一个子类的方法用于测试子类中的访问
    def test():
        #方式访问父类中私有成员
        #print(Father.wife)
        #print(Son.wife)
        #访问父类中公共的成员
        #print(Son.color)
        #访问受保护的成员
        print(Son._money)

Son.test()
#Father.eat(1)
#print(Father._money)
#受保护的定义
'''
私有化:只能载类或者对象的结构中访问
公共的:可以载任何位置访问
受保护:可以载当前类或者对象 和子类或者子类对象中访问

        类内   子类中    类外部
私有化:  √       X        X
受保护:  √       √        √(X类外部应该不能访问!)
公共的:  √       √        √    

'''

公共的封装 public

所有的成员默认都是公共的封装级别,可以在类中,类外,及子类中正常访问

类中/对象中            可以访问
类外/对象外            可以访问
子类/子类对象            可以访问

继承

继承就是可以获取另外一个类中的成员属性和成员方法。(并非所有成员)

**作用:**继承的作用是增加代码的复用性,节省不必要的重复代码,提高开发效率,同时可以设置类之间的关系。

继承的两个概念:

父类
    用于被继承的类,称之为父类,也叫做基类,或者超类
子类
    继承其他类的类,称之为子类,也叫做派生类

继承的格式

class 父类:
    pass
class 子类(父类):#继承操作的关键步骤
    pass

继承的特征

1.所有类都是继承自object类(object类对应的对象就是object对象,也是万物皆对象)
2.子类继承父类则可以访问父类的所有成员。(私有成员除外)
3.子类继承父类并不会将父类的所有成员复制到子类当中去,访问父类成员是间接通过父类来访问的,
4.子类可以具有自己独有的属性和方法
5.子类可以重载父类中的方法,只需要设置和父类指定成员相同的名称即可实现重载,重载之后的成员,子类只会访问当前类中的成员,而不会调用父类中同名的成员
6.子类中如果重载父类的方法,并且还想将重载的父类方法借调过来使用,可以在重载的方法中使用如下方法
[父类名.方法()](适合类)  或者  [super().方法()](适合对象)
#刘备类:父类-》被其他类继承的类称之为父类(超类,基类)
class LiuBei:
    #属性
    familyname = '刘'
    firstname = '备'
    sex = 'man'
    money = '$100'
    country = '蜀国'
    #私有成员
    __wife = ('甘夫人','糜夫人','孙尚香')
    #方法
    def say(self):
        print('你这个小子,险些损我一员大将')
    #f非绑定类的方法[对象访问]
    def drink(self):
        print(self)
        print('来,干了这杯酒')
    def walk(self):
        print('gogo,fire in the hole')
    #绑定类的方法
    def la():
        print('哗啦啦啦啦啦~~')
#刘禅类:子类-》继承其他类的类称之为子类(派生类)
class LiuChan(LiuBei):
    #子类独有的成员
    #属性
    weight = '180斤'
    #方法
    def douququ(self):
        print('此间乐,不思蜀')
    #重载父类方法
    def say(self):
        print('我爸爸是刘备')
    #重载父类的drink方法,但是还要将父类中操作拿过来使用
    def drink(self):
        print('举起筷子,夹一口菜')
        #喝酒 通过对象调用的方法的重载(推荐使用super().方法名())
        super().drink()#LiuBei.drink(self)#
    # 重载父类的drink方法,但是还要将父类中操作拿过来使用
    def la():
        print('准备好擦屁股纸!~')
        #调用父类的la方法(推荐使用类名.方法名)
        LiuBei.la()

#查看刘禅类
#print(LiuChan.__dict__)#继承操作不会将成员直接复制到子类中
#print(LiuChan.sex)
#LiuChan.walk(1)
#print(LiuChan.wife)

#result = issubclass(type,object)
#print(result)

#访问子类独有的成员
#LiuChan.douququ(1)
#print(LiuChan.weight)

#访问继承来的方法
#LiuChan.say(1)

#访问重载并且调用了父类的方法的方法
#LiuChan.la()

lc = LiuChan()
lc.drink()

单继承和多继承

**单继承:**每个类只能继承一个类的方式称为单继承。

**多继承:**每个类可以同时继承多个类的方式称为多继承。

python属于多继承语言!但是一般不用

多继承格式:

class 父类1:
    pass

class 父类2:
    pass

class 子类(父类1,父类2):
    pass

多继承之后,子类就具备了所有父类的成员(私有成员除外)

多个父类具有相同的成员时,子类继承[继承列表]中第一个类的方法

菱形继承/钻石继承


菱形继承格式

class A:
    pass

class B(A):
    pass

class C(A):
    pass

class D(B,C):
    pass

    A
   / \
  B   C
   \ /
    D

菱形继承存在的问题

如果BC类同时继承了A类,D类又继承了BC两个类的情况下(菱形继承),
在调用BC中某个同名方法(该方法都继承自A类)时会导致继承自A类的该方法被多次调用。产生逻辑问题!

所以python使用 super() 类来解决了多继承的菱形继承问题

MRO列表

Method Realtion Order 用来制作一个继承关系的列表

python3中使用C3算法来计算MRO列表(计算过程暂时忽略)

MRO列表的制作原则:

1.子类永远在父类的前面
2.如果继承了多个父类,那么按照()中的顺序在列表中摆放
3.如果多个类同时继承了一个父类,孙子类中只会选取第一个父类中的父类的该方法
#菱形继承
'''
        动物类

人类              鸟类

        鸟人类
'''
#动物类
class Animal:
    #属性
    pass

    #方法
    def say(self):
        print('Animal张开嘴')
        print('Animal合上嘴')
#人类
class Human(Animal):
    #属性
    pass
    #方法
    def say(self):
        print('人类张开嘴')
        #调用动物类的say方法
        super().say()
        print('人类合上嘴')
#鸟类
class Bird(Animal):
    #属性
    pass

    #方法
    def say(self):
        print('鸟类张开嘴')
        # 调用动物类的say方法
        super().say()
        print('鸟类合上嘴')
#鸟人类
class BirdHuman(Human,Bird):
    #属性
    pass

    #方法
    def say(self):
        print('鸟人类张开嘴')
        #鸟类的say
        #人类say
        super().say()
        print('鸟人类合上嘴')
#实例化鸟人对象
bh = BirdHuman()
bh.say()

#MRO(Method Resolution Order):方法解析顺序。 里面采用c3算法进行排序
#查看继承关系的mro列表
result = BirdHuman.mro()
print(result)

#MRO列表  C3算法  将继承关系的类做成一个列表
#1.子类永远在父类的前面
#2.如果同时继承多个类,谁在继承格式中考前,在列表中也靠前
#[鸟人类,人类,鸟类,动物类,Object]  MRO列表
#super() 永远获取MRO列表的下一个类

super()

super不是一个关键字,也是不是有函数,他是一个类

super()的作用不是查找父类,而是找MRO列表的下一个类

super()和父类没有任何实质性的关系,只是有时候能调用到父类而已。

在单继承的情况下,super()永远调用的是父类/父对象

格式:

super().方法()      #python3的格式

多继承按需操作,在没有必要的时候避免强行使用!

mixin 设计模式

该设计模式的主要作用是采用多继承方式,进行类的扩展。

优点:

  1. mixin可以在对类不做任何修改的情况下,扩展类的功能(添加父类)
  2. 可以方便的组织和维护各种不同组件的划分。
  3. 可以根据需要任意调整
  4. 可以避免创建更多的类,也可以避免继承导致的混乱
#水果类
class Fruit:
    pass
#礼物类和非礼物类
class Gift:
    pass
class NotGift:
    pass
#南方北方类
class South:
    pass
class North:
    pass
#爽和不爽的苹果
class Cool:
    pass
class NotCool:
    pass
#真实水果类
class Apple(Fruit,Gift,North,NotCool):
    pass
class Pear(Fruit,NotGift,North,NotCool):
    pass
class Banana(Fruit,NotGift,North,Cool):
    pass
class Orange(Fruit,Gift,South,NotCool):
    pass

魔术方法

常用魔术方法

魔术方法就是一个类/对象中的方法,和普通方法唯一的不同时,普通方法需要调用!而魔术方法是在特定时刻自动触发

1._init_
初始化魔术方法
触发时机:初始化对象时触发(不是实例化触发,但是和实例化在一个操作中)
参数:至少有一个self,接收对象
返回值:无
作用:初始化对象的成员
注意:使用该方式初始化的成员都是直接写入对象当中,类中无法具有
import random
class Human:
    #属性
    age = 1
    color = 'yellow'


    #方法
    def __init__(self,diyname):
        #为对象添加成员
        #print(self)
        self.hair = '自然卷'
        self.name = diyname
        #随机产生性别
        if random.randrange(0,2) == 1:
            self.sex = '男'
        else:
            self.sex = '女'

    def eat(self):
        print('吃卷饼啃猪蹄')

    def drink(self):
        print('喝自来水')


#实例化对象
zw = Human('雪饼')
print(zw.__dict__)

print(Human.__dict__)
2._new_
实例化魔术方法
触发时机: 在实例化对时触发
参数:至少一个cls 接收当前类
返回值:必须返回一个对象实例
作用:实例化对象
注意:实例化对象是Object类底层实现,其他类继承了Object的__new__才能够实现实例化对象。
没事别碰这个魔术方法,先触发__new__才会触发__init__ 
class Human:
    #属性
    age = 18
    sex = 'man'

    #方法
    def __new__(cls,diyname):
        #print('new方法被触发')
        print(cls)
        return object.__new__(cls)


    def __init__(self,diyname):
        pass

    def sleep(self):
        print('教室睡觉真香甜')


    def eat(self):
        print('吃蛋蛋炒饭!')



#实例化对象
sy = Human('小洋洋') #1.创建对象(new)  2.对对象进行初始化操作(init)
print(sy)

单例设计模式

class WangYingSong:
    #属性
    color = '黄色'
    age = 27
    name = '应松'
    #声明了一个类成员属性用于保存创建的对象
    obj = None
    #方法
    def __new__(cls):

        #检测是否已经制作国对象
        if cls.obj == None:#没有做过对象
            #实例化对象(存入当前类中)
            cls.obj = object.__new__(cls)
            return cls.obj
        else:#做过对象,直接将类中保存的对象返回
            return cls.obj
    def study(self):
        print('好好学习天天想上!~')

    def eat(self):
        print('吃肯德基全家捅!')

#实例化对象1
ys1 = WangYingSong()
print(ys1)

#实例化对象2
ys2 = WangYingSong()
print(ys2)

#实例化对象3
ys3 = WangYingSong()
print(ys3)
3._del_
析构魔术方法
触发时机:当对象没有用(没有任何变量引用)的时候被触发
参数:一个self 结婚搜对象
返回值:无
作用:使用完对象是回收资源
注意:del不一定会触发当前方法,只有当前对象没有任何变量接收时才会触发
class Human:

    #属性
    money = 1000
    sex = 'man'
    age = 18
    name = '小松松'
    def __init__(self,sign):
        self.sign = sign
    #方法
    def eat(self):
        print('吃开塞露')


    def drink(self):
        print('和糖水~')

    #del魔术方法  析构方法
    def __del__(self):
        print(self.sign ,'del方法被触发')

#实例化对象
ss = Human(0)
print(ss)
print('-------------------')
del ss
print('-------------------')

'''sss
#将对象赋值给另外一个变量
ceshi1 = Human(1)
ceshi2 = Human(2)
print('-------------------')
'''
#文件读取操作
'''
1.打开文件
2.读取文件
3.关闭文件
'''
class ReadFile:
    #打开文件(构造)
    def __init__(self,filename):
        os.chdir(r'F:\python\python基础(√)\15\14')
        #打开文件将文件io对象保存载对象成员
        self.fp = open(filename, 'r',encoding='UTF-8')

    #读取文件
    def fread(self):
        return self.fp.read()

    #关闭文件(析构)
    def __del__(self):
        print('关闭文件操作')
        self.fp.close()

#实例化对象
one = ReadFile('11.txt')

txt = one.fread()
print(txt)
4._call_
调用对象的魔术方法
触发时机:将对象当作函数调用时触发 对象()
参数:至少一个self接收对象,其余根据调用时参数决定
返回值:根据情况而定
作用:可以将复杂的步骤进行合并操作,减少调用的步骤,方便使用
注意:无
#call魔术方法
'''
触发时机:把对象当作函数调用的时候自动触发
功能:简化操作
参数:至少一个self接受当前对象,其他参数根据程序决定
返回值:根据程序决定
'''
class Human:
    #属性
    sex = 'man'
    age = 18
    color = 'yellow'
    #方法
    def eat(self):
        print('吃饭饭')

    def sleep(self):
        print('睡觉觉')

    #
    def __call__(self):
        print('call魔术方法被触发')

#实例化对象
bb = Human()
# print(bb)
#把对象当作函数调用的时候
bb()
#左蛋糕的类
class MakeCake:
    #和面
    def huomian(self):
        print('和面操作')

    #发酵
    def fajiao(self):
        print('发酵操作')

    #烘烤
    def hongkao(self):
        print('烘烤操作')

    #切形状
    def zaoxing(self):
        print('切形状')

    #抹奶油
    def monaiyou(self):
        print('抹奶油操作')

    #防水果
    def fangshuiguo(self):
        print('放水果操作')

    #打包
    def dabao(self):
        print('打包操作')
        return '完整的盒装蛋糕'

    #获取蛋糕的方法
    def __call__(self,who):
        print('制作者:',who)
        self.huomian()
        self.fajiao()
        self.hongkao()
        self.zaoxing()
        self.monaiyou()
        self.fangshuiguo()
        result = self.dabao()

        return result
#实例化对象
mc = MakeCake()

#用户获取蛋糕 
r = mc('从浩大厨')
print(r)
5._len_
触发时机:使用len(对象) 的时候触发
参数:一个参数self
返回值:必须是一个整型
作用:可以设置为检测对象成员个数,但是也可以进行其他任意操作
注意:返回值必须必须是整数,否则语法报错,另外该要求是格式要求。
#len魔术方法
'''
触发时机:使用len(对象)的时候自动触发 
功能:用于检测对象中或者类中某个内容的个数
参数:只有一个self接受当前对象
返回值:必须返回整型
'''
class Human:
    #属性
    sex = 'man'
    age = 18
    color = 'yellow'
    size = '36E'

    #方法
    def eat(self):
        print('猪蹄+炸鸡')

    def drink(self):
        print('白开水一壶!')

    #魔术方法__len__
    def __len__(self):
        print('len方法被触发')
        #去掉带有下划线开头和结尾的成员
        #获取所有带有下划线的成员
        result = {k:v for k,v in Human.__dict__.items() if not ( k.startswith('__') and k.endswith('__'))}
        print(result)
        return len(result)
        #获取所有的成员
        # alls = Human.__dict__
        # 获取用户定义的普通成员个数 相减
        # return len(alls) - len(result)

#实例化对象
mmf = Human()
print(mmf)

result = len(mmf)
print(result)
6._str_
触发时机:使用print(对象)或者str(对象)的时候触发
参数:一个self接收对象
返回值:必须是字符串类型
作用:print(对象时)进行操作,得到字符串,通常用于快捷操作
注意:无
#str魔术方法
'''
触发时机:使用print打印对象的时候或者str(对象)都可以触发
功能:定义对象转换为字符串的结果
参数:一个self接受对象
返回值:必须返回字符串类型
'''
class Human:
    #属性
    sex = 'man'
    age =18
    name = '王成'

    #方法
    def la(self):
        print('拉妹子啦,拉妹子拉~')

    def sa(self):
        print('谁显开始?')

    #魔术方法__str__
    def __str__(self):
        #print('str被触发')
        #return '老王拉斯你!'
        return self.name

#实例化对象
wc = Human()
print(wc)

result = str(wc)
print(result)
7._repr_
触发时机:在使用repr(对象)的时候触发
参数:一个self接收对象
返回值:必须是字符串
作用:将对象转使用repr化为字符串时使用,也可以用于快捷操作

repr函数和str函数处理字符串只有一个区别:

str的结果 字符串本身 (结果可以被eval执行)

如:x = ‘无图言Diao’ str() ->无图言Diao

rerpr的结果 字符串定义结构 (eavl不会执行repr结果)

如:x = ‘无图言Diao’ repr() ->‘无图言Diao’

备注: 在类中通常情况下__str__和__repr__ 设置相同即可

eval()

函数 将字符串当作python代码执行

格式:eval(字符串)

返回值:可以有返回值

#repr魔术方法
'''
触发时机:使用repr(对象)的时候触发
功能:定义repr函数的结果
参数:一个self接受当前对象
返回值:必须返回字符串类型
'''
class Human:
    #属性
    sex = 'woman'
    age = 18
    height = '178cm'

    #方法
    def think(self):
        print('大脑里面胡思乱想~')

    def dream(self):
        print('I have a dream')

    #__repr__魔术方法
    def __repr__(self):
        print('repr方法被触发')
        return '这是一个章旺的对象!'
    #设定__str__和__repr__的魔术方法相同
    __str__ = __repr__

#实例化对象
zw = Human()
result = repr(zw)
print(result)

#测试repr函数
var = '123'
print(var)
result = repr(var)
print(result,type(result))
8._bool_
触发时机: 使用bool(对象)的时候触发
参数:一个self接收对象
返回值:必须是布尔值
作用:根据实际情况决定,可以作为快捷方式使用
注意:仅适合于返回布尔值的操作
#bool魔术方法
'''
触发时机:使用bool(对象)的时候自动触发
功能:根据某个规则确定对象的布尔值转换结果
参数:一个self接受当前对象
返回值:必须是布尔类型
'''
class Human:
    #属性
    sex = 'woman'
    age = 18
    color = 'yellow'

    #方法
    def getMoney(self):
        print('好好学习天天赚钱~')


    def sendMoeny(self):
        print('随便花')

    #__ bool__魔术方法
    def __bool__(self):
        #print('bool方法被触发')
        #设置当前对象 男-》True 女 -》False
        if self.sex == 'man':
            return True
        return False
#实例化对象
bb = Human()

result = bool(bb)
print(result)
9._format_
触发时机:使用字符串.format(对象)时候触发
参数:一个self接收对象,一个参数接收format的{}中的格式,例如:>5
返回值:必须是字符串
作用:设置对象可以作为format的参数,并且自定义对象格式化的规则
注意:无
#format魔术方法

class Human:
    #属性
    name = '峰峰'
    sex = 'man'
    age = 18

    #方法
    def lang(self):
        print('峰峰划船一身浪~')

    def show(self):
        print('来,看看我的峰大步大!~')

    #__format__魔术方法
    def __format__(self,arg):
        #print('format方法被触发')
        #print(arg)

        #  >  <  ^
        #将arg(限定符号)进行拆分
        flag = arg[0] # @
        align = arg[1] # > < ^
        num = int(arg[2:])#  6
        #判断对其方式
        if align == '<':#左对齐
            result = self.name.ljust(num,flag)
        elif align == '>':#右对齐
            result = self.name.rjust(num, flag)
        elif align == '^':#剧中对其
            result = self.name.center(num, flag)
        return result

#实例化对象
sf = Human()

str1 = '{:#^10}去偷窥女宿舍~'#峰峰 -》 @@@@峰峰
#相当于arg=('#','^','10')
result = str1.format(sf)
print(result)

描述符相关的魔术方法

1._get_()
触发时机:在获取指定描述符操作的成员属性的值的时候触发
参数:1描述符对象本身,2描述符描述的属性所在的对象,描述符描述的对象的类
返回值:必须有,不然无法获取相应属性值
注意:仅在描述符中使用
2._set_()
触发时机:在设置或者添加指定描述符操作的成员属性的时候触发
参数:1描述符对象本身,2描述符描述的属性所在的对象,3要设置的值
返回值:无
注意:仅在描述符中使用
3._delete_()
触发时机:在删除指定描述符操作的成员属性的时候触发
参数:1描述符对象本身,2描述符描述的属性所在的对象
返回值:无
注意:仅在描述符中使用
#描述符相关的魔术方法

#描述符类
class Decription:

    #成员属性  共享值的操作
    def __init__(self):
        self.var = '张正阳'

    #定义三个操作
    #获取成员属性
    def __get__(self,obj,cls):#self描述符对象 obj 接受描述的成员属性username的对象e  cls 描述的成员属性username所在的类Email
        #print(obj,cl`s)
        #隐藏名字中间的一个字符
        result = self.var[0]+'*'+self.var[-1]
        return result


    #设置成员属性
    def __set__(self,obj,value):#self描述符对象 obj 接受描述的成员属性username的对象e value 设置的值
        #设置时候,默认添加思密达
        self.var = value+'思密达'


    #删除成员属性
    def __delete__(self,obj):#self描述符对象 obj 接受描述的成员属性username的对象e
        #删除self.var就可以删除username的访问操作
        #根据密码是否为空决定是否可以删除用户名
        if obj.password == '':
            del self.var
        else:
            pass


class Email:

    #属性
    #希望对用户名进行管控(不是权限管控,而是内容管控)
    username = Decription()#交接操作 将username的操作管控交给描述符类的一个对象
    password = '11123'

    #方法
    def login(self):
        print('登录操作')

    def logout(self):
        print('退出操作')


#实例化对象
e = Email()

#获取成员属性
#print(e.username)


#设置成员属性
#e.username = '章旺'
#print(e.username)


#删除成员属性
del e.username
print(e.username)
#描述符2

class Email:
    #属性
    #username = ''
 
    password = ''
    #方法
    def __init__(self):
        #设置var对象成员为描述符的三个方法工作
        self.var = '杨俊'

    def login(self):
        print('登录操作')

    def logout(self):
        print('退出操作')

    #获取属性的操作
    def getusername(self):
        result = self.var[0] + '*' +self.var[-1]
        return  result

    #设置属性的操作
    def setusername(self,value):
        self.var = value

    #删除属性的操作
    def delusername(self):
        #删除的时候对self。var进行操作
        del self.var
    #将username属性 交给property制定的函数管理
    username = property(getusername,setusername,delusername)   


#实例化对象
e = Email()

#获取成员属性
#print(e.username)

#设置成员属性
#e.username = '王健'
#print(e.username)

#删除成员属性
del e.username
print(e.username)
#描述符3

class Email:

    #属性
    #username = ''
    password = ''

    #方法
    def __init__(self):
        #为描述符添加的用于数据通讯的成员属性
        self.var = '匿名'

    def login(self):
        print('登录操作')

    def logout(self):
        print('退出操作')

    #获取操作
    @property
    def username(self):
        result = self.var[0] + '*' + self.var[-1]
        return result

    #设置操作
    @username.setter
    def username(self,value):
        self.var = value

    #删除操作
    @username.deleter
    def username(self):
        del self.var


#实例化对象
e = Email()

#获取用户名
#print(e.username)

#修改用户名
#e.username = '董伟'
#print(e.username)

#删除用户名
del e.username
print(e.username)

与属性操作相关的魔术方法

1._getattr_()
触发时机:获取不存在的对象成员时触发
参数:1接收当前对象的self,一个是获取成员名称的字符串
返回值:必须有值
作用:为访问不存在的属性设置值
注意:getattribute无论何时都会在getattr之前触发,触发了getattribute就不会在触发getattr了
2._setattr_()
触发时机:设置对象成员值的时候触发
参数:1个当前对象的self,一个是要设置的成员名称字符串,一个是要设置的值
返回值:无 过程操作
作用:接管设置操作,可以在设置前之前进行判断验证等行为
注意:在当前方法中无法使用成员=值的方式直接设置成员,否则会无限递归,必须借助object的设置方法来完成

object.__setattr__(参数1,参数2,参数3)
3._delattr_()
触发时机:删除对象成员时触发
参数:一个当前对象的self
返回值:无
作用:可以在删除成员时进行验证。
4._getattribute_()
触发时机:使用对象成员时触发,无论成员是否存在
参数:1个接收当前对象self,一个是获取的成员的名称字符串
返回值:必须有
作用:在具有封装操作(私有化时),为程序开部分访问权限使用
#与属性相关的魔术方法

class Man:
    #属性
    sex = 'man'
    age = 18
    color = 'yellow'
    name = '石志朋'

    #方法
    def __init__(self):
        self.gf = '白石茉莉奈'
        self.hobby = '看CCAV播放的小丁丁历险记!'

    def chou(self):
        print('pia,pia老婆我错了~~')

    def keng(self):
        print('坑娃娃的爸爸~')

    """
    #__getattr__()
    '''
    触发时机:访问一个不存在的成员属性的时候触发
    功能:1.防止访问不存在成员报错  2.可以为不存在的成员设置默认值
    参数:一个self接受对象  一个参数接受要访问的不存在的成员名
    返回值:可以有可以没有,但是如果有则是设置了访问的成员的值
    '''
    def __getattr__(self,attrname):
        #print(attrname)
        #通常载此处进行判断 决定返回什么值
        if attrname == 'height':
            return '175cm'
        elif attrname == 'weight':
            return '75kg'
        else:
            return '对不起不存在该属性'

    """

    """
    #__getattribute__()
    '''
    触发时机:访问对象成员时触发(无论是否存在!)
    功能:可以限制过滤制定成员的值的访问
    参数:一个self接受当前对象  一个接受要访问的成员名
    返回值:可以有,可以没有  推荐根据程序设定(一般有!)
    
    '''
    def __getattribute__(self,attrname):

        if attrname == 'name':
            #不能够通过当前对象访问成员(访问时绝对不允许使用[对象.成员名]的格式获取)触发递归!
            return object.__getattribute__(self,attrname)
        elif attrname == 'sex':
            return object.__getattribute__(self,attrname)
        else:
            return '对不起,成员不存在或者不允许访问'

    """

    #__setattr__
    '''
    触发时机:对成员属性进行设置的时候触发
    功能:限制或者过滤对象成员的修改
    参数:一个self接受当前对象  一个接受修改的成员名  一个要修改的成员值
    返回值:没有返回值!
    '''

    def __setattr__(self,attrname,value):
        #可以载设置成员属性时候进行判断
        if attrname == 'sex' or attrname == 'name':
            pass
        else:
            object.__setattr__(self,attrname,value)



    #__delattr__ 魔术方法
    def __delattr__(self, attrname):
        #根据删除的内容决定是否允许删除
        if attrname == 'hobby':
            pass
        else:
            object.__delattr__(self,attrname)

#实例化对象
szp = Man()

'''
#获取对象的成员属性(getattr魔术方法)
print(szp.height)
print(szp.weight)
print(szp.length)
'''

#获取对象的成员属性(getattribute)
#print(szp.color)

#设置成员属性
#szp.sex = 'no man no woman'
#print(szp.sex)

#szp.name = '失了志'
#print(szp.name)

#szp.color = 'black'
#print(szp.color)

#删除成员属性
print(szp.__dict__)
del szp.gf
print(szp.__dict__)
5._dir_()
触发时机:dir(对象)的时候触发
参数:1个接收当前对象self
返回值:必须为序列类型(列表,元组,集合等,)
作用:可以自定义成员列表的返回值
#dir魔术方法
class Human:

    #属性
    sex = 'man'
    age = 18
    name = '家晷'

    #方法
    def eat(self):
        print('吃凉菜')

    def drink(self):
        print('喝凉水')

    #__dir__
    def __dir__(self):
        #获取是哦有可以访问的成员
        lists = object.__dir__(self)
        #过滤魔术方法 只留下自定义成员
        newlists = []
        for i in lists:
            if i.startswith('__') and i.endswith('__'):
                pass
            else:
                newlists.append(i)

        return newlists

#实例化对象
qw = Human()

#获取当前对象中所有存在的成员
result = dir(qw)
print(result)

#查看所有内置函数 内置变量

'''
#方法一
print(dir(__builtins__))
#方法二
import builtins
print(dir(builtins))
'''

'''
dir 查看对象或者类的内置属性 方法 魔术方法
dir(对象) 对象的所有内置属性 方法 魔术方法 (包括类的)
dir(类)   类的所有内置属性 方法 魔术方法(只有类的)
'''

运算相关魔术方法(上帝模式)

比较运算相关魔术方法

1._lt_()
格式:
    def __lt__(self,other):
    return 数据

特征:
    触发时机:进行小于判断时自动触发
    参数:2个参数第一个是self,第二个判断的第二个对象
    返回值:返回值可以任意类型,推荐布尔值
    作用:定义小于号的行为:x < y 调用 x.lt(y)
2._le_()
格式:
    def __le__(self):
    return str

特征:
    触发时机:进行小于等于判断时自动触发
    参数:2个参数第一个是self,第二个判断的第二个对象
    返回值:返回值可以任意类型,推荐布尔值
    作用:定义小于等于号的行为:x <= y 调用 x.le(y)
3._gt_()
格式:
    def __gt__(self):
    return str

特征:
    触发时机:进行大于判断时自动触发
    参数:2个参数第一个是self,第二个判断的第二个对象
    返回值:返回值可以任意类型,推荐布尔值
    作用:定义大于号的行为:x > y 调用 x.gt(y)
4._ge_()
格式:
    def __ge__(self):
    return str

特征:
    触发时机:进行大于等于判断时自动触发
    参数:2个参数第一个是self,第二个判断的第二个对象
    返回值:返回值可以任意类型,推荐布尔值
    作用:定义大于等于号的行为:x >= y 调用 x.ge(y)
5._eq_()
格式:
    def __eq__(self):
    return str

特征:
    触发时机:进行等于判断时自动触发
    参数:2个参数第一个是self,第二个判断的第二个对象
    返回值:返回值可以任意类型,推荐布尔值
    作用:定义大于等于号的行为:x == y 调用 x.eq(y)
6._ne_()
格式:
    def __ne__(self):
    return str

特征:
    触发时机:进行不等于判断时自动触发
    参数:2个参数第一个是self,第二个判断的第二个对象
    返回值:返回值可以任意类型,推荐布尔值
    作用:定义不等号的行为:x != y 调用 x.ne(y)
#比较运算

class Myint(int):

    #__eq__ 相等魔术方法
    def __eq__(self,other):
        #print('eq方法被触发')
        #print(self,other)

        #自定义规则:如果2歌数都能被6整除 相等 其余都不想等
        if self % 6 == 0  and other % 6 == 0:
            return True
        else:
            return False

    #__gt__ 大于比较魔术方法
    def __gt__(self,other):
        #print('gt方法被触发')
        #print(self,other)

        if self % 5 > other % 5:
            return True
        else:
            return False

#实例化对象
no1 = Myint(24)
no2 = Myint(92)

#相等运算
#result = no1 == no2
#print(result)

#练习:只要各位数相等 就相等,其余都不想等


#大于运算
result = no1 > no2
print(result)

算术运算相关魔术方法

__add__(self, other)           定义加法的行为:+
__sub__(self, other)           定义减法的行为:-
__mul__(self, other)           定义乘法的行为:
__truediv__(self, other)       定义真除法的行为:/
__floordiv__(self, other)      定义整数除法的行为://
__mod__(self, other)           定义取模算法的行为:%
__divmod__(self, other)        定义当被 divmod() 调用时的行为
__pow__(self, other[, modulo]) 定义当被 power() 调用或 ** 运算时的行为
__lshift__(self, other)        定义按位左移位的行为:<<
__rshift__(self, other)        定义按位右移位的行为:>>
__and__(self, other)           定义按位与操作的行为:&
__xor__(self, other)           定义按位异或操作的行为:^
__or__(self, other)            定义按位或操作的行为:|

反运算相关魔术方法

__radd__(self, other)      与上方相同,当左操作数不支持相应的操作时被调用
__rsub__(self, other)      与上方相同,当左操作数不支持相应的操作时被调用
__rmul__(self, other)      与上方相同,当左操作数不支持相应的操作时被调用
__rtruediv__(self, other)  与上方相同,当左操作数不支持相应的操作时被调用
__rfloordiv__(self, other) 与上方相同,当左操作数不支持相应的操作时被调用
__rmod__(self, other)      与上方相同,当左操作数不支持相应的操作时被调用
__rdivmod__(self, other)   与上方相同,当左操作数不支持相应的操作时被调用
__rpow__(self, other)      与上方相同,当左操作数不支持相应的操作时被调用
__rlshift__(self, other)   与上方相同,当左操作数不支持相应的操作时被调用
__rrshift__(self, other)   与上方相同,当左操作数不支持相应的操作时被调用
__rand__(self, other)      与上方相同,当左操作数不支持相应的操作时被调用
__rxor__(self, other)      与上方相同,当左操作数不支持相应的操作时被调用
__ror__(self, other)       与上方相同,当左操作数不支持相应的操作时被调用
#其他魔术方法

#自定义我们自己的整型类
class Myint(int):

    #__add__加法的魔术方法(int类中本来就有)
    def __add__(self,other):
        #print('add方法被触发')
        #print(self,other)
        return int(self) - int(other)


    #__radd__反向加法的魔术方法(int类中本来就有)
    # def __radd__(self,other):
    #     #print('radd方法被触发')
    #     print(self,other)
    #     return int(self) * int(other)

#实例化对象
no1 = Myint(50)
#print(no1,type(Myint))

'''
#正向加法运算  __add__
result = no1 + 15
print(result)

#练习:自定义一个整型,相加时进行的运算为10位数相乘+个位数相减
'''

#反向加法运算 __radd__
result = 40 + no1
print(result)

#练习:自定义一个整型,反向相加运算时获取2个数值的各位数的乘积作为结果

赋值运算相关魔术方法

__iadd__(self, other)             定义赋值加法的行为:+=
__isub__(self, other)             定义赋值减法的行为:-=
__imul__(self, other)             定义赋值乘法的行为:=
__itruediv__(self, other)         定义赋值真除法的行为:/=
__ifloordiv__(self, other)        定义赋值整数除法的行为://=
__imod__(self, other)             定义赋值取模算法的行为:%=
__ipow__(self, other[, modulo])   定义赋值幂运算的行为:**=
__ilshift__(self, other)          定义赋值按位左移位的行为:<<=
__irshift__(self, other)          定义赋值按位右移位的行为:>>=
__iand__(self, other)             定义赋值按位与操作的行为:&=
__ixor__(self, other)             定义赋值按位异或操作的行为:^=
__ior__(self, other)              定义赋值按位或操作的行为:|=

一元运算相关魔术方法

__pos__(self)      定义正号的行为:+x
__neg__(self)      定义负号的行为:-x
__abs__(self)      定义当被 abs() 调用时的行为
__invert__(self)   定义按位求反的行为:~x

类型转换相关魔术方法 JIANG

__complex__(self)      定义当被 complex() 调用时的行为(需要返回恰当的值)
__int__(self)          定义当被 int() 调用时的行为(需要返回恰当的值)
__float__(self)        定义当被 float() 调用时的行为(需要返回恰当的值)
__round__(self[, n])   定义当被 round() 调用时的行为(需要返回恰当的值)
__index(self)__        1. 当对象是被应用在切片表达式中时,实现整形强制转换
                       2. 如果你定义了一个可能在切片时用到的定制的数值型,你应该定义 index
                       3. 如果 index 被定义,则 int 也需要被定义,且返回相同的值

上下文管理相关魔术方法

_enter_()_exit_()

enter(self)
    1. 定义当使用 with 语句时的初始化行为
    2. enter 的返回值被 with 语句的目标或者 as 后的名字绑定

exit(self, exctype, excvalue, traceback)
    1. 定义当一个代码块被执行或者终止后上下文管理器应该做什么
    2. 一般被用来处理异常,清除工作或者做一些代码块执行完毕之后的日常工作

容器类型相关魔术方法

__len__(self)                  定义当被 len() 调用时的行为(返回容器中元素的个数)
__getitem__(self, key)         定义获取容器中指定元素的行为,相当于 self[key]
__setitem__(self, key, value)  定义设置容器中指定元素的行为,相当于 self[key] = value
__delitem__(self, key)         定义删除容器中指定元素的行为,相当于 del self[key]
__iter__(self)                 定义当迭代容器中的元素的行为
__reversed__(self)             定义当被 reversed() 调用时的行为
__contains__(self, item)       定义当使用成员测试运算符(in 或 not in)时的行为

类的常用函数

issubclass()

检测一个类是否是另外一个类的子类

格式1:issubclass(被检测类,父类)
返回值:布尔值

格式1:issubclass(被检测类,(父类1,父类2,父类3...))
返回值:布尔值

注意:只要有一个类是当前被检测类的父类,那么最终结果就是True

isinstance()

检测一个对象是否是某个类的对象

格式1:isinstance(对象,类)
返回值:布尔值

格式2:isinstance(对象,(类1,类2,类3...))
返回值:布尔值

注意:只要一个类是当前对象的类,那么最终结果就是True

hasattr()

检测对象/类是否具有某个成员

格式:hasattr(对象/类,'成员名')
返回值:布尔值

getattr()

获取对象/类中的成员值

格式:getattr(对象,'成员名'[,成员不存在时的默认值])
返回值:成员的值

setattr()

设置或者添加对象/类中的成员

格式:setattr(对象,'成员名',值)
返回值:None

delattr()

删除对象/类中的成员

格式: delattr(对象,成员)
返回值:None

dir()

获取对象的成员名称列表

格式:dir(对象)
返回值:列表

property()

用于设置成员属性的修饰符

格式:成员属性 = property(获取的方法,设置的方法,删除的方法)
#issubclass() 检测一个类是否是另外一个或者一组类中的子类

class Father:
    pass

class Mother:
    pass

class LaoWang:
    pass

class Son(Father,Mother):
    pass

#检测
#result = issubclass(Son,Father)
#result = issubclass(Son,Mother)
#result = issubclass(Son,LaoWang)
result = issubclass(Son,(LaoWang,Mother))#检测是否是Mother或者Laowang的子类
print(result)


#isinstance() 检测某个对象是否是制定类的对象(类型检测)
a = 10
#result = isinstance(a,int)
#result = isinstance(a,float)
result = isinstance(a,(Father,int)) #检测a是否是Father或者int类的对象
print(result)


#hasattr() 检测类和对象是否有制定的成员

class Human:
    #属性
    sex = 'man'
    age = 19
    color = 'yellow'

    #方法

    def __init__(self):
        self.hair = '黑色'

    def eat(self):
        print('吃饭饭!')

wbq = Human()

#result = hasattr(wbq,'sex')
#result = hasattr(wbq,'age')
result = hasattr(wbq,'drink')
print(result)

result = hasattr(Human,'sex')
print(result)

#getattr() 获取对象/类成员的值
#已存在
#result = getattr(wbq,'age') # 相当于wbq.age
#不存在
result = getattr(wbq,'weight','90kg')#成员不存在时设置获取的默认值
print(result)

#setattr() 设置对象/类成员的值
print(wbq.age)
setattr(wbq,'age',29)#相当于wbq.age = 29
print(wbq.age)

#delattr() 删除对象/类成员的值 如果设置了就是对象的值 哪怕和类内名字一样 
print(wbq.hair)
delattr(wbq,'hair')
print(wbq.hair)

描述符

python中的描述符是用于描述对象中的属性。主要作用就是对属性操作提供限制,验证,管理等相关权限的操作。

描述符主要有三种操作需要设置:

get      获取属性的操作

set      设置属性的操作

delete   删除属性的操作

描述符方法1


#描述符类
class Description:
    #成员属性
    #name = ''

    #初始化方法
    def __init__(self):
        #为当前类/对象添加一个成员属性(当前类)来接收需要描述的成员属性(要描述的类)此处还没有接收(占位)
        self.name = None

    #get获取属性值的方法
    def __get__(self,obj,cls):# self 用于接收当前描述符类的对象 obj 接收用于管理的成员的对象  cls 用于接收管理成员的类
        print('获取方法被触发')
        self.name = str(self.name)
        return self.name[:4]

    #set设置属性值的方法
    def __set__(self,obj,val): #self 用于接收当前描述符类的对象 obj 接收用于管理的成员的对象 val 设置的值
        print('设置方法被触发')
        #print(self,obj,val)
        #在此处可以添加限制和判断(密码奇数时*2)
        if val %2 == 1:
            val *= 2
        #完成了(email)对象的属性值的设置
        self.name = val

    #delete删除属性值的方法
    def __delete__(self,obj): #self当前描述符类的对象 obj 接收用于管理的成员的对象

        #用户代为删除操作
        del self.name

#声明一个邮箱的类
class Email
    #属性

    #用户名
    account = 'conghao@zhiling.com'
    #密码(为密码设置了描述符 的对象) 这一步相当于吧password的所有传入了Description的对象当中
    password = Description()

描述符方法2:


#邮箱类
class Email:

    #成员属性
    #为username添加描述符
    #username = ''
    #设置邮箱账号最大的长度
    maxlength = 6
    #为描述符添加一个临时变量(在描述符中代替username进行操作)
    tmpusername = None    
    password = ''

    #成员方法
    #为username的描述符进行设置(添加方法)
    #获取username的描述符方法
    def getusername(self):
        print('获取操作被触发')
        #返回值之前进行值的修饰,两边添加星星
        if self.tmpusername != None:
            self.tmpusername = '★' + self.tmpusername + '★'
        #设置获取username的时候的值
        return self.tmpusername

    #设置username的描述符方法
    def setusername(self,val):
        print('设置操作被触发')
        #限制,根据Email类的最大账号长度对用户名进行截取之后在设置
        #检测val是否是字符串类型
        if isinstance(val,str):
            val = val[0:self.maxlength]
        self.tmpusername = val

    #删除username的描述符方法
    def delusername(self):
        print('删除操作被触发')
        #删除操作
        del self.tmpusername

    #为username设置描述符
    username = property(getusername,setusername,delusername)

3.属性修饰符


#邮箱类
class Email:

    #用户名
    username = ''
    #密码
    password = ''
    #使用描述符来操作昵称
    #昵称
    petname = '小乖乖'
    #为描述符设置临时变量
    __petname = None

    #成员方法(暂无)
    #描述符设置的三个部分  获取,设置和删除
    #处理petname获取操作
    @property
    def petname(self):
        print('获取操作被触发')
        return self.__petname

    #处理petname的设置操作
    @petname.setter
    def petname(self,val):
        print('设置操作被触发')
        #设置操作
        self.__petname = val

    #处理petname的删除操作
    @petname.deleter
    def petname(self):
        print('删除操作被触发')
        #删除操作
        del self.__petname

类的内置属性

_dict_

获取当前类/对象成员组成的字典

_doc_

获取当前类/对象的文档,和函数一样使用''' 定义即可

_name_

类.__name__是获取当前类名,如果直接写__name__则是获取模块的名称

_bases_

获取类的继承列表中所有父类组成的元组
#类和对象常用的属性

class Animal:
    pass
class Demo:
    pass

class Human(Animal,Demo):
    '''
    这是类的文档,一个人类的类
    介绍:
    成员:
    方法:
    '''
    #属性
    sex = 'man'
    age = 18
    color = 'yellow'

    #方法
    def sleep(self):
        print('睡觉觉')

    def hit(self):
        print('打豆豆')


dd =Human()

#__dict__ 获取对象或者类的自身成员
print(Human.__dict__)
print(dd.__dict__)
#__doc__ 获取类的文档
print(Human.__doc__)
print(dd.__doc__)

#__name__获取类名  (类来使用对象不行)
print(Human.__name__)

#__bases__ 获取一个类直接继承的所有父类元祖
print(Human.__bases__)

#__moudle__ 获取类的模块名称   __main__ 当前类文件直接执行的文件
print(Human.__module__)

装饰器

装饰器就是对函数或者方法或者类进行修饰

'''
#第一步:创建一个普通函数
def laxi():
    print('噗哧噗哧噗哧噗哧~~~')

#调用函数
laxi()
laxi()
'''

'''
#第二步:扩展函数的功能(不是装饰器)
#声明一个扩展函数
def decor(func):
    print('求神拜佛,祝愿一切顺利')
    func()#相当于调用laxi()
    print('拉稀成功,烧香还愿')
def laxi():
    print('噗哧噗哧噗哧噗哧~~~')
#将laxi函数传入decor函数中
laxi = decor(laxi)
#调用函数
laxi()
laxi()
'''

'''
#第三步:扩展函数的功能(不是装饰器),使用语法糖
#声明一个扩展函数
def decor(func):
    print('求神拜佛,祝愿一切顺利')
    func()#相当于调用laxi()
    print('拉稀成功,烧香还愿')
@decor #将laxi函数传入decor函数中#laxi = decor(laxi)
def laxi():
    print('噗哧噗哧噗哧噗哧~~~')
#调用函数
laxi()
laxi()
'''

'''
#第四步:实现基本的装饰器
def decor(func):#函数名随便写
    #声明内部函数来制作完整的装饰函数
    def _decor():#函数名随便写
        print('求神拜佛,祝愿一切顺利')
        func()#相当于调用laxi()
        print('拉稀成功,烧香还愿')
    return  _decor
@decor#laxi = decor(laxi)
def laxi():
    print('噗哧噗哧噗哧噗哧~~~')
#调用函数
laxi()
laxi()
laxi()
laxi()
'''

'''
#第五步:实现带有参数和返回值的哦装饰器
#装饰器
def decor(func):
    #这就是未来的拉稀函数
    def _decor():
        print('求神拜佛,祝愿一切顺利')
        #调用拉稀函数时接收拉稀函数本身的返回值
        result = func()#相当于调用laxi()
        print('拉稀成功,烧香还愿')
        #为装饰之后的函数返回一个值
        return result
    #返回内部函数作为未来的laxi函数
    return _decor
@decor
#拉稀函数
def laxi():
    print('噗哧噗哧噗哧噗哧~~~')
    return '热翔一碗'
#调用拉稀函数
jg = laxi()
print(jg)
'''

'''
#装饰器
def decor(func):
    #这就是未来的拉稀函数(原函数有什么形参,这里就要有什么形参)
    def _decor(who,weight):
        print('求神拜佛,祝愿一切顺利')
        #调用拉稀函数时接收拉稀函数本身的返回值
        result = func(who,weight)#相当于调用laxi()
        print('拉稀成功,烧香还愿')
        #为装饰之后的函数返回一个值
        return result
    #返回内部函数作为未来的laxi函数
    return _decor
@decor
#拉稀函数
def laxi(who,weight):
    print('噗哧噗哧噗哧噗哧~~~:'+who+'拉了'+weight+'斤便便')
    return '热翔一碗'
jg = laxi('马俊龙','10')
print(jg)
'''

'''
#第六步:收集参数装饰器(给装饰器内部的函数加参数)
def decor(func):
    #返回未来的拉稀函数
    def _decor(*who,*weight):
        print('求神拜佛,祝愿一切顺利')
        result = func(*who,**weight)
        print('拉稀成功,烧香还愿')
        return result
    #返回装饰之后的函数
    return _decor
@decor
def laxi(*who,**weight):
    print('噗哧噗哧噗哧噗哧~~~')
    print('参与拉屎的人有:',who)
    print('分别拉了多少:',weight)
    return  '热翔一大锅!'
#调用函数
jg = laxi('马俊龙','阎瑞龙','霍云瑞','曹睿','宋笑寒',mjl = '5斤',yrl = '2斤',hyr= '1吨',cr = '10克',sxh = '便秘')
print(jg)
'''

'''
#第七步:带有参数的装饰器(给装饰器加参数)
#定义装饰器(接收装饰器参数)
def decor(arg):
    #接收函数的参数
    def _decor(func):
        #未来的拉稀和吃饭函数的装饰
        def __decorla():#未来的拉稀函数
            print('求神拜佛,祝愿一切顺利')
            result = func()
            print('拉稀成功,烧香还愿')
            return result
        def __decorchi():#未来的吃饭函数
            print('我要开动了~')
            result = func()
            print('我吃完了~')
            return result
        #根据装饰器的参数返回不同的装饰结果
        if arg == 'la':
            return __decorla
        elif arg == 'chi':
            return __decorchi
    #返回装饰器的第一层
    return _decor
@decor('la')
def laxi():
    print('噗哧噗哧噗哧噗哧~~~')
    return  '热翔一碗'
@decor('chi')
def chifan():
    print('吧唧吧唧吧唧吧唧!~~~')
    return '空碗一个'
#调用laxi
jg = laxi()
print(jg)
#调用chifan
jg = chifan()
print(jg)
'''

'''
#第八步:将类作为装饰器参数传入进来
#祝愿祈福类
class Wish:
    #绑定类的方法
    def before():
        print('烧香拜服,祝愿一切顺利!')
    #绑定类的方法
    def after():
        print('拉稀成功,烧香还愿~')
#装饰器
def decor(cls):

    def _decor(func):
        #这是未来的拉稀函数
        def __decor():
            cls.before()
            result = func()
            cls.after()
            return result
        #返回装饰之后的函数
        return __decor
    return _decor
@decor(Wish)
def laxi():
    print('噗哧噗哧噗哧噗哧~~~')
    return '热翔一手'
#调用函数
jg = laxi()
print(jg)
'''

'''
#第九步:将类作为装饰器使用
class Decor:
    def __init__(self,arg):
        #存入对象
        self.arg = arg
    #此魔术方法用于接收原函数
    def __call__(self,func):
        #将原方法存到对象当中
        self.func = func
        #返回装饰之后的函数
        return self.mylaxi
    #装饰函数
    def mylaxi(self):
        print('烧香拜服,祝愿一切顺利!')
        #调用原函数
        result = self.func()
        print('拉稀成功,烧香还愿~')
        return result
@Decor(5)
def laxi():
    print('噗哧噗哧噗哧噗哧~~~')
    return '热翔一手'
jg = laxi()
print(jg)
'''

'''
#第十步:为类添加装饰器(单例模式)
#声明一个容器用于存放对象
obj = {}#假设存入的对象键名only  值为对象本身 {'only':对象}
def decor(cls):
    #装饰器的操作
    def _decor():
        if 'only' in obj:
            #对象已经创建
            return obj['only']
        else:
            #对象没有创建,创建对象并返回
            obj['only'] = cls()
            return obj['only']
    #返回装饰的操作
    return _decor
#当前类只能实例化一个对象
@decor
class LiXue:
    name = '小雪'
    sex = '女'
    age = '21岁'
    def stuPy():
        print('好好学习天天向上!')
#实例化第一个对象
one = LiXue()
print(one)
two = LiXue()
print(two)
three = LiXue()
print(three)
'''
#第十一步:多个装饰器嵌套
#装饰器1
def decor1(func):
    def _decor1():
        print('脱裤子,准备放炮')
        result = func()
        print('拉屎完毕,提裤子走人~')
        return result
    return _decor1
#装饰器2
def decor2(func):
    def _decor2():
        print('烧香拜佛,祝愿一切顺利!')
        result = func()
        print('操作成功,烧香还愿')
        return result
    return _decor2
@decor2
@decor1
def laxi():
    print('扑哧扑哧扑哧扑哧扑哧~~')
    return '热翔一大杯'
jg = laxi()
print(jg)

方法的分类

类和对象的方法一共分为三种:

实例方法/对象方法

只有实例化对象之后才可以使用的方法,该方法的第一个形参接收的一定是对象本身!

绑定类的方法/静态方法

无需实例化,可以通过类直接调用的方法,方法中的参数既不接收对象名也不接受类。 一般方法可以独立调用,跟类中其他成员关联不大

类方法

无需实例化,可以通过类直接调用的方法
但是方法的第一个参数接收的一定是类本身,这种方法一般情况下需要借助类中其他成员操作
#包含各种方法的类
class Person:
    #绑定类的方法,静态方法
    @staticmethod #可以省略不写
    def walk():
        print('走路方法,绑定类的方法')

    #非绑定类的方法  对象方法
    def say(self):
        print(self)
        print('说话功能,非绑定类方法')

    #类方法
    @classmethod #必须写
    def drink(cls):
        print(cls)
        print('喝水方法,类方法')

#调用非绑定类的方法(对象/实例方法)
tw = Person()
tw.say()

#绑定类的方法,静态方法
Person.walk()

#调用类方法
Person.drink()
class Cat:
    color = "orange"
    age = 2
    sex = "gong"

    def getFish(self):
        print(self)
        print('在抓鱼')
    def cry():
        print("miao")
    @classmethod
    def run(cls):
        print(cls)
        print("跑步")
    #静态方法
    @staticmethod
    def jump():
        print('跳跳跳')

#实例化对象
mimi = Cat()

#对象方法

mimi.getFish()
Cat.cry()

Cat.run()

Cat.jump()
mimi.jump()

抽象类

具有抽象方法的类就是抽象类。

抽象方法就是没有完成的方法。只有方法名称和参数,没有方法内容的方法。

作用:适合于领导指定开发规范及多人协作完成类。

abc abstract class 抽象类的缩写

抽象类的语法

#使用抽象类必须使用abc模块
import abc

#书写抽象类必须指定抽象类的元类  固定格式
class Human(metaclass = abc.ABCMeta):
	age = 10
    sex = "mu"
    color = "black"
    #定义一个抽象的实例方法/非绑定类的方法
    @abc.abstractmethod
    def smoking(self):
        pass

    #定义一个抽象的类方法
    @abc.abstractclassmethod
    def say(cls):
        pass

    #定义一个抽象的静态方法/绑定类的方法
    @abc.abstractstaticmethod    
    def cry():
        pass
import abc
class User(metaclass=abc.ABCMeta):
    #属性
    username =''
    userid = 0

    #方法
    #添加
    @abc.abstractmethod
    def add(self,name,pwd):
        pass
    #删除
    @abc.abstractclassmethod
    def dell(cls,uid):
        pass

    #修改
    @abc.abstractstaticmethod
    def modd():
        pass

    #查找
    def find(self):
        print("find")


class MUser(User):
    def add(self,name,pwd):
        print("添加")


class YUser(MUser):
    @classmethod
    def dell(cls,uid):
        print("删除")

class SUser(YUser):
    @staticmethod
    def modd():
        print("修改")

user = SUser()

user.add("123","12")

SUser.dell("12")

user.modd()

user.find()

抽象类的特征:

1.抽象类中可以包含具体的方法也可以包含抽象方法
2.抽象类中可以包含成员属性,而且属性没有抽象不抽象之分
3.抽象类无法实例化使用.
4.抽象类只能被其他类继承使用,(唯一的用法)
5.只有子类实现了抽象类的所有抽象方法之后,该子类才可以正常实例化使用。有一个抽象方法没有实现都不可以实例化
6.抽象类的作用是指定程序开发的标准(方法名,参数等)

多态

多态,多种状态!就是一个类,根据不同的情况,相同的方法产生不同的结果。

import abc

class Animal:
    @abc.abstractmethod
    def niao(self):
        pass
    @abc.abstractmethod
    def la(self):
        pass
    @abc.abstractmethod
    def jiao(self):
        pass



class Dog(Animal):

    def niao(self):
        print("抬起后腿尿")


    def la(self):
        print("蹲着拉")


    def jiao(self):
        print("汪汪叫")


class Cat(Animal):

    def niao(self):
        print("蹲着尿")

    def la(self):
        print("蹲着拉")

    def jiao(self):
        print("喵喵叫")

class Chick(Animal):

    def niao(self):
        print("站着尿")

    def la(self):
        print("站着拉")

    def jiao(self):
        print("打野老万")


class Action:

    def __init__(self,animal):
        self.animal = animal
    def niao(self):
        self.animal.niao()

    def la(self):
        self.animal.la()
    def jiao(self):
        self.animal.jiao()

xiaohei = Dog()
miao = Cat()
hua = Chick()


a = Action(xiaohei)

a.jiao()
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MelodyYN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值