python OOP面向对象笔记


OOP面向对象编程

  • 以模块化解决工程问题,以模块化的思想编程
  • 以宏观构想组成的模块
  • 面向对象 VS 面向编程
  • 由 过程化 转向 对象化

面向对象名词

  • oo 面向对象
  • ooa 分析
  • ood 设计
  • oop 编程
  • ool 是实现
  • 过程: ooa–>ood–>ool

类与对象

  • 类:抽象,侧重于共性
  • 对象:具象,侧重于个体

类的内容(成员)

  • 动作:由函数实现,函数名括号中需加 self
  • 属性:即是变量
  • is-a 语句

类的定义

  • class 关键字
  • 类名:遵循大驼峰规则(每个单词首字母大写)
  • pass 关键字:占位符
#定义 学生类
class Student():
    pass  # 占位符
#定义 学生对象
​
xiaoming = Student()
print(xiaoming)
<__main__.Student object at 0x000002D389E774A8>
#定义 更完整的学生类
class StudentCareful():
    #定义类的属性
    name = 'wanglihong'
    age = 20
    course = 'Python'
    #定义类中的动作
    def study_python(self):
        print('I like program')
        
#定义一个对象
xiaobai = StudentCareful()
xiaobai.study_python()
print(xiaobai.name)
print(xiaobai.age)
I like program
wanglihong
20

self

  • 不是关键字,即可替换单词
  • 在运用中替代实例化自身
  • 实例化时,self即是实例化自身,无需传入参数.类中函数内参数必要时,实例化才可传参,否则报错
#用 self的案例
class Student1():
    #定义类的属性
    name = '哈佛大学'
    age = 20
    #定义类的动作
    def sayHello(self):
        print('I like music')
       
#实例化类
xiaobai = Student1()
xiaobai.sayHello()#不用 self的案例
class Student1():
    #定义类的属性
    name = '哈佛大学'
    age = 20
    #定义类的动作
    def sayHello(happy):      #此处用happy替代self则不会报错,但不推荐
        print('I like music')
        
#实例化类
xiaobai = Student1()
xiaobai.sayHello()
​
​
I like music
I like music
#实例化传参的案例
class Student1():
    #定义类的属性
    name = '哈佛大学'
    age = 20
    #定义类的动作
    def sayHello(self):
        print('I like music')
        
#实例化类
xiaobai = Student1()
a = 'play basketball'
xiaobai.sayHello(a)    #此时类中只需要一个参数,但此时传入的是self(xiaobai)自身和a两个参数,则会报错
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-e8cd7f79f524> in <module>()
     11 xiaobai = Student1()
     12 a = 'play basketball'
---> 13 xiaobai.sayHello(a)    #此时类中只需要一个参数,但此时传入的是self(xiaobai)自身和a两个参数,则会报错

TypeError: sayHello() takes 1 positional argument but 2 were given

类的变量作用域的问题

  • 类变量
  • 实例变量
    • 实例变量可调用类变量

1.实例变量 调用 类的变量 (此时实例变量还没单独定义/赋值)

class Student2():
    name = '哈佛大学'
    age  = 18
    def play_game(self):
        print('My age is {} from {}'.format(self.age,self.name))
        
#实例化类
xiaoming = Student2()
xiaoming.play_game()

2.实例变量 调用 类的变量 (此时实例变量单独定义/赋值)

class Student3():
    name = '哈佛大学'
    age  = 18
    def play_game(self,n,m):  #此时在实例化时就可传入参数n,m的值
        self.name = n
        self.age = m
        print('My age is {} from {}'.format(self.age,self.name))
        
#实例化类
xiaoming = Student3()
xiaoming.play_game('清华大学',20)  #此时调用的是实例单独定义/赋值的参数  
print('My age is {} from {}'.format(xiaoming.age,xiaoming.name))
print('My age is {} from {}'.format(Student3.age,Student3.name))
My age is 18 from 哈佛大学
My age is 20 from 清华大学
My age is 20 from 清华大学
My age is 18 from 哈佛大学

访问类的属性

  • 运用类的方法:
    • class
    • 类名.属性名
  • 意义:直接运用类中的方法,无需实例化
  • 用 类名._dict_ 访问类中所有成员(即属性和方法).
#运用类的方法案例
class StudentManage():
    school = '哈佛大学'
    status  = '年轻人'
    course = '编程'
    #定义类的动作
    def draw_words(self):
        print('My status is {} from {}'.format(self.status,self.school))
       
    #静态方法的运用(无需传入参数self)
    def play_study(): #此处运用类本身无需传入任何参数(静态)
        print('I like {} and My school is {}'.format(StudentManage.course,__class__.school)) #此处两种类的方法均可运用
        
#实例化类
xiaoming = StudentManage()
xiaoming.draw_words()
#运用类的方法
StudentManage.play_study()  #注意:类的方法与实例化类运用的区别
    
 
My status is 年轻人 from 哈佛大学
I like 编程 and My school is 哈佛大学
#访问类中所成员(以字典形式)
class Person(object):  
    name = 'nothing'
    age = 'unkonw'
    def play_game(self):
        print('I can coding')
print(Person.__dict__)   #访问该类中的所有成员
{'__module__': '__main__', 'name': 'nothing', 'age': 'unkonw', 'play_game': <function Person.play_game at 0x00000293C0ED6598>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}

构造函数

  • 在类实例化时,执行初始化的操作
  • 在实例化时,第一个被默认执行的函数
  • 运用特殊的名称和方法,必须要有self
  • 实例化时,调用构造函数时,直接填入类的括号中传入参数
#构造函数实例
class StudentManage1():
    course = '中国慕课'
    age = 18
    def solo1(self):
        print('i like {} and I am {}'.format(self.course,self.age))
        
    #构造函数
    def __init__(self):  #运用__init__特殊名称,且必须加入self
        print('爱生活,爱编程!')
        
#实例化类
xiaobai = StudentManage1()  #在实例化执行时,首先默认自动执行
print('************')
xiaobai.solo1()
    
爱生活,爱编程!
************
i like 中国慕课 and I am 18
#实例化时,调用构造函数时,直接填入类的括号中传入参数
class Person():
    #定义构造函数
    def __init__(self,name,age):
        print('My name is {},I am {}'.format(name,age))
#实例化类时直接传入name和age
a = Person('马云',18)
My name is 马云,I am 18

面向对象三大特征

  • 1.继承
  • 2.封装
  • 3.多态

1. 继承

  • (可联想财产继承的关系)
  • 子类可以运用父类定义的属性和方法
  • 作用:减少代码量,增加代码的复用性.也可以设置类与类之间的关系
  • 子类的实现
    • 父类,超类(superclass),基类(baseclass):被继承的类
    • 子类:继承的类
  • 所有的类都需要父类
    • 在定义类时,括号内所填入的内容就是父类
    • Python中父类可以有多个,即子类可以继承多个父类
    • 若括号内不填父类,则系统自动给予object为父类.
  • 特征:
    • 子类继承父类后,可直接访问除私有成员外的所有内容.
      子类对父类而言,存在引用调用的关系.
    • 子类可设定特有成员的属性和方法
    • 子类和父类的成员属性和方法可能相同,优先使用子类
    • 子类如果想要调用父类的方法时,可使用 父类名.父类成员进行
      调用父类成员,也可以用super().父类成员的格式来调用
class Person1():
    name = 'nothing'
    age = 'unkonw'
    def action(self):
        print('WO WOW')class Person2(Person1):
    name = 'everthing'
    age = 'konw'
    def play(self):
        print('i can {}'.format(super().name))  #通过super().父类成员名来调用
        print('i can {}'.format(Person1.name))  #通过 父类名.父类成员名来调用
a = Person2()
​
a.play()
i can nothing
i can nothing
#类的定义
class Person1():
    name = 'nothing'
    age = 'unkonw'
    
#类定义加入系统父类(object)表达含义相同
class Person2(object):
    pass
#子类与父类的运用
class Person(object):  #括号中object系统默认父类,可填可不填
    name = 'nothing'
    age = 'unkonw'
    def play_game(self):
        print('I can coding')
        
class Bird(object):
    def action(self):
        print('I can fly')
        
class Teacher(Person):   #此时子类Teacher继承了父类object的属性和内容
    pass
xiaoming = Teacher()
xiaoming.play_game() #调用父类的成员方法
print(xiaoming.name) #可运用父类的属性nameprint(issubclass(Teacher,Person))   #检验父子类关系
I can coding
nothing
True
class Person(object):  #括号中object系统默认父类,可填可不填
    name = 'nothing'
    age = 'unkonw'
    def play_game(self):
        print('I can coding')
        
class Bird(object):
    def action(self):   #定义类动作时self一定要填
        print('I can fly')
        
#此时定义一个可继承Person和Bird的类Birdhero
class BirdHero(Person,Bird):
    pass  
xiaoniao = BirdHero()
#运用父类所继承的属性
print(xiaoniao.age)
xiaoniao.action()
unkonw
I can fly
#子类可调用父类的成员方法
#子类如果想要扩充父类的方法时,可使用 父类名.父类成员进行
#调用父类成员,也可以用super().父类成员的格式来调用
#定义父类
class Person():
    sex = 'typical'    
    age = 'None'
    def __init__(self):
        print('我是Person')
        
    def action(self):
        print('sleep ...')
    def work():
        print('make some money!')
    
#定义子类
class Teacher(Person):
    name = 'vary'
    age = 'same'
    def make_test(self):
        print('do not make cheat')
    #此时运用父类work动作,且将make_test()扩充给父类
    def work(self):  
        #调用父类
        Person.work() #调用父类成员的方法一:父类名.方法名称,#此括号中的self指代子类 Teacher,即运用父类自身(静态方法)
        
        super().action()  #调用父类成员方法二:super().方法名称  
        #super().work()   #注意用super().调用父类的方法是,需要传入参数,即父类方法需要self,此时这句运用会报错! 
        
        self.make_test()     #运用子类本身
        
        
        Person.__init__(self)  #类名.成员名称,调用父类的构造函数
        super().__init__()    #super().成员名称, 调用父类的构造函数
a = Teacher()
a.work()
我是Person
make some money!
sleep ...
do not make cheat
我是Person
我是Person

检验父子类关系函数(issubclass)

  • 返回True/False
#检验父子类关系函数
print(issubclass(BirdHero,Person))
print(issubclass(BirdHero,Bird))
True
True

构造函数的继承

  • 构造函数默认继承,若子类无构造函数,则默认自动调用父类的构造函数
  • 若子类有构造函数,则不在调父类的构造函数
  • 若套用多层父子类,则从子类向上一级父类逐次查找,若查找到则停止,无需继续向上查找
#若子类无构造函数时
#定义一个父类
class Person():
    name = 'nothing'
    #定义构造函数
    def __init__(self,name,age):
        self.name = name  #赋值
        self.age = age
        print('My name is {},I am {}'.format(name,age))
#定义一个子类
class Student(Person):
    name = 'LL'
    pass#实例化类时直接传入name和age
a = Student('马云',18)  #在实例化时传入构造函数所需参数#注意两种输出的区别
print(a.name)  
print(Person.name)
print(Student.__dict__)  #__dict__ 查找该类中的所有成员
My name is 马云,I am 18
马云
nothing
{'__module__': '__main__', 'name': 'LL', '__doc__': None}
#若子类有构造函数时
class Person():
    #定义构造函数
    def __init__(self,name,age):
        print('My name is {},I am {}'.format(name,age))
        
#定义一个子类
class Student(Person):
    #定义子类构造函数
    def __init__(self):
        print('I like public libraries')
        
#实例化类
​
a = Student()  #此时子类有构造函数,则不再调用父类的构造函数
print(Student.__mro__)  #查询类的所有子父类
I like public libraries
(<class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>)

单继承与多继承

  • 单继承:每一类只能继承一类
    • 优点:父子类继承关系逻辑清晰
    • 缺点:功能不能无线扩展
  • 多继承:每一类可以继承多个类
    • 优点:功能可无线扩展
    • 缺点:父子类继承关系层级混乱
    • 种类:钻石继承/菱形继承
      -多继承中的MRO算法
    • 计算原则:
      • 输出时子类在父类前面
      • 子类有多个父类时,根据子类括号中最左边的一个父类为最优先,由左往右
    • 多个子类继承一个父类时,则其孙子类继承第一个父类的父类
#自定义实例区别
#多继承实例
#菱形继承/钻石继承的形式
class Person():
    age = '18'
    def __init__(self,name):  #构造函数
        self.name = name
        print('I can sleep')
class Driver(Person):
    def __init__(self,name):
        self.name = name
        print('I have car')
class Teacher(Person):
    def __init__(self,name):
        self.name = name
        print('do not cheat')
#class Oldman(Person,Teacher):  #此种继承方法会报错,无法以此种方式访问 Person的构造函数
class Oldman(Driver,Teacher):  #根据MPO计算方法,对自动匹配括号中第一个
    pass
a = Oldman('xiaobai')  
print(a.age)   #可以访问Person的属性
print(Oldman.__mro__)  # __mro__ 逐个查找上级父类,等级由左往右输出
I have car
18
(<class '__main__.Oldman'>, <class '__main__.Driver'>, <class '__main__.Teacher'>, <class '__main__.Person'>, <class 'object'>)

super的运用

  • super不是关键字,是一个类
  • super作用是获取MRO(MethodResolutionOrder)列表中的第一个类
  • super与父类无实质性关系,但可调用父类
  • super的使用方法,在子类构造函数中调用父类构造函数
  • 可使用 _mro_ 向上查询所有父类
#super运用案例
class A():
    pass
class B(A):
    def __init__(self):
        print('B')
class C(A):
    def __init__(self,name):
        self.name = name
        print('我是{}'.format(name))
        print('C')
class D(B,C):
    def __init__(self,name):
        #运用super调用父类B
        super().__init__()
        
        #运用父类名.成员名称调用父类C
        C.__init__(self,name)
        print('D')#实例化a       
a = D('xiaobai')
​
B
我是xiaobai
C
D

2.封装

  • 含义:对类中成员的访问限制
  • 封装的三个级别
    • 公开 public
    • 受保护 protect
    • 私有 private
  • 判断对象的位置
    • 内部
    • 外部
    • 子类中

1.私有 (private)

  • 私有成员是最高级的封装,只能在当前类或对象中访问
  • 运用方法:
    • 在名称前面加两个下划线(__名称)
  • 实质是系统通过 mangling技术自动将名称更改,导致无法正常访问
    可通过__class__attributename访问.
#私有成员的封装运用
class Animal():
    name = 'None'
    __age = 'infinite'   #此时age被私有封装设置
    def action(self):
        print('I can move')
a = Animal
print(a.__age)  #此时会报错,应为被私有封装了
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-6-71e6e1305f37> in <module>()
      6         print('I can move')
      7 a = Animal
----> 8 print(a.__age)  #此时会报错,

AttributeError: type object 'Animal' has no attribute '__age'
#访问上面私有的成员
print(a.__dict__)  #先访问Animal中的所有成员查找更改后的名称#查看可知更改后的名称为 _Animal__age
#再次访问
print(a._Animal__age)  
{'__module__': '__main__', 'name': 'None', '_Animal__age': 'infinite', 'action': <function Animal.action at 0x00000253FA7FDD08>, '__dict__': <attribute '__dict__' of 'Animal' objects>, '__weakref__': <attribute '__weakref__' of 'Animal' objects>, '__doc__': None}
infinite

2.受保护(protect)

  • 对对象成员一定级别的封装,只可在类或子类中进行访问,不可在外部访问
  • 运用方法:
    • 在名称前加一个下划线

3.公开(public)

  • 对成员无任何操作,任何地方都可访问

3.多态

  • 含义:同一个对象在不同情况下有不同的状态表现
  • 一种设计思想
  • 多态性:一种调用方式,多种执行结果
  • 多态:同一事物可以拥有多种形态.如动物可分类为:人类,鸟类,猪类

MiXin设计模式

  • 一种设计思想,不是语法
  • 多采用多继承的方式对类的功能进行扩展
  • 只有一个父类,其他MiXin类只是添加其功能
  • 注意事项:
    • 表示单一功能而不是物品
    • 所执行的职务必须单一,若有多种功能,则可写多个MiXin类
    • MiXin不能依赖子类的实现
    • 只是一个功能,无论子类有无继承该MiXin类,对其本身的整体工作并不影响.
  • 优点:
    • 使用MiXin类可以不对其子类产生任何影响,有无都可以,只是缺少功能而已
    • 便于实现不同功能组件的划分
    • 可以根据需要任意调整类的功能组合
    • 可以避免创建许多新的类,导致继承混乱.
#MiXin模式思想的运用class Person():
    def work(self):
        print('I can work')
class Bird():
    def fly(self):
        print('I can fly')
class Fish():
    def swim(self):
        print('I can swim')class Superman(Person,Bird,Fish):   #此时运用MiXin仅调用方法
        pass
​
​
a = Superman()
print(Superman.__mro__)   #通过Mro算法,向上按顺序查询所有父类
#无用MiXin模式,运用多继承,观察区别class Person():
    def work(self):
        print('I can work')
class Bird(Person):  #此时加入父类,MiXin下没有
    def fly(self):
        print('I can fly')
class Fish(Person):
    def swim(self):
        print('I can swim')class Superman(Bird,Fish): 
        pass
​
​
a = Superman()
print(Superman.__mro__)  #通过Mro算法,向上按顺序查询所有父类
(<class '__main__.Superman'>, <class '__main__.Person'>, <class '__main__.Bird'>, <class '__main__.Fish'>, <class 'object'>)
(<class '__main__.Superman'>, <class '__main__.Bird'>, <class '__main__.Fish'>, <class '__main__.Person'>, <class 'object'>)

相关函数

https://www.runoob.com/python/python-built-in-functions.html #内置函数大全解析

  • issubclass :判断父子类的关系
  • isinstance :检测一个对象是否为一个类的实例
  • hasattr :检验一个对象是否有成员xxx
  • getattr :获取已有类成员属性的值
  • setattr :更改或创建类中成员得属性
  • delattr :删除类中属性
  • dir :获取对象所有列表

类中成员属性操作符

  • 三种方法
    • 1.使用类实现描述器
    • 2.使用属性描述符
    • 3.property函数
      • property(fget,fset,fdel,fdoc)
        • fget:获取
        • fset:添加或修改
        • fdel:删除
        • fdoc:建立文档
  • 三种方法得各个优点:
    • 无论哪种修饰符都是为了对成员属性进行相应的控制
      • 类的方式:适合多个类中多个属性共用一个描述符
      • property:对当前类使用,可控制一个类多种属性
      • 属性修饰符:适用于当前类中,控制一个类中的一个属性
#使用 类的方式 实现对类中成员属性操作
#编写新得类得方法使小写字母变为大写class Teacher():
    def __init__(self,name,age):
        self.name = name
        self.age = age
        
        #设置使成员name均为大写得函数,并自生调用
        self.set_name(name)
    def introduce(self):
        print('My name is {},I am {}'.format(self.name,self.age))
        
    def set_name(self,name): 
        self.name = name.upper()  #str.upper()  转为大写  
#实例化类
xiaobai = Teacher('xiaobai',18)
xiaohuang = Teacher('xiaohuang',18)
#调用类的方法
xiaobai.introduce()
xiaohuang.introduce()
        
My name is XIAOBAI,I am 18
My name is XIAOHUANG,I am 18
#  property实例
#用property操作 替代 传统上片段操作
#功能:使输入得姓名都转化为大写
class Teacher():
    def fget(self):
        return self._name * 2  #打印2次姓名
    def fset(self,name):
        #将姓名字母转换为大写
        self._name = name.upper()  #此时不能将值赋给self.name,会出现迭代错误
    def fdel(self):      
        print('NoName')
        
    name = property(fget,fset,fdel,'对name操作')
​
xiaoming = Teacher()
xiaoming.name = 'xiaoming'
print(xiaoming.name)
XIAOMINGXIAOMING

类中成员属性的函数

  • 名称两边用两个下划线包裹
    • _dict_: 用字典的形式返回类中成员
    • _doc_:返回类的说明文档
    • _name_:返回类的名称
    • _bases_ :以元组的方式返回其所有父类.
      • _base_:返回其第一个父类
#实例化类中成员属性函数
class Person():
    """
    这是关于人自身的类   #类中三引号中的内容为说明文档
    """
    name = 'NO1'
class Bird(Person):
    name = 'niao'class Firsh(Bird):
    name = 'yu'
    
class Superman(Firsh,Bird):
    pass
a = Firsh()
#__dict__
print(Firsh.__dict__)#__doc__
print(Person.__doc__)#__name__
print(Person.__name__)#__base__
print(Superman.__bases__)
print(Bird.__base__)
{'__module__': '__main__', 'name': 'yu', '__doc__': None}

    这是关于人自身的类   #类中三引号中的内容为说明文档
    
Person
(<class '__main__.Firsh'>, <class '__main__.Bird'>)
<class '__main__.Person'>

类中的魔术方法

  • 含义:不用认为调用,在满足条件时,特殊的时刻自动触发
  • 类中定义的特殊函数
  • 名称两边用两个下划线包裹
    • 操作类:

      • _init_:构造函数
      • _new_:对象实例化方法,一般不使用
      • _call_:对象当函数类型使用时触发
      • _str_:对象当字符串使用时触发
      • _repr_:返回字符串
        • 与__str__有区别
    • 描述符相关

      • _get_
      • _set_
      • _delete_
    • 属性类操作相关

      • _getattr_
        • (获取)
        • 对成员访问时触发
        • 填入参数:
          • self:获取当前对象
          • 第二个参数,填任意名称,代表触发函数的接入参数
        • 功能:若访问不到该类中的属性,则自动触发函数.否则,返回该类中原有属性
        • 函数中的内容可自行设置
      • _setattr_
        • (修改)
        • 对成员属性设置时触发
        • 填入参数:
          • self:用来获取当前对象
          • 被设置的属性名称,以字符串形式出现
          • 需要对属性名称设置的值
        • 作用:进行属性设置时,对其验证或修改
        • 注意:该方法不能对属性直接进行赋值操作,否则进入死循环
      • _delattr_
        • (删除)
        • 对成员属性进行删除
        • 填入参数
          • self:获取当前对象
          • 删除的key
        • 作用:删除成员属性(可选择性删除)
        • 通过 if else 语句,进行删除拦截
    • 运算类操作

      • _gt_
        • 进行大小判断的时候触发函数
        • 填入参数:
          • self:获取当前对象
          • 第二个参数是第二个对象
          • 返回任意值,推荐布尔值.
#魔术方法:操作类实例
class Person():
    def __init__(self):
        print('WO 是构造函数')
    def __call__(self):
        print('call 当函数时触发')
    def __str__(self):
        return '我是字符串'
    def __repr__(self):
        return 'wocao '
t = Person()
t()  #对象当函数类型使用时触发
print(t) #对象当字符串使用时触发
t
WO 是构造函数
call 当函数时触发
我是字符串
wocao 
#魔术方法:属性类实例
# __getattr__实例:
class A():
    name = 'Nothing'
    age = 18
    
    def __getattr__(self,name):
        print('I love music')
        name = '卧槽'
        return name
        
a = A()
print(a.s)
I love music
卧槽
#魔术方法:属性类实例
# __setattr__实例(全面版):
#设置属性时触发
class F():
    def __init__(self,name):
        self.name = name
        
    def __setattr__(self, key, value):
        
        print(self)
        print(key)
        print(value)
        
                #以下三种方法均可
        #super().__setattr__(key,value)  #调用父类魔法函数实现.注意传入两个参数
        self.__dict__[key] = value       #直接赋值
        #object.__setattr__(self,key,value)  #调用父类,注意传入三个参数
        
        #self.name = value       #不能使用此种该方法赋值,会出现迭代错误
a = F('alex')  #属性被赋值时,直接调用print(a.name)
<__main__.F object at 0x00000206D270B470>
name
alex
alex
#魔术方法:属性类实例
# __setattr__实例(简单版):
#设置属性时触发
class Hero():
    def __init__(self,name):
        self.name = name        
    def __setattr__(self,key,value):
        print(self)
        print(key)
        object.__setattr__(self,key,value)
        
a = Hero('小白')       
print(a.name)
<__main__.Hero object at 0x00000206D27261D0>
name
小白
#魔术方法:属性类实例
#__delattr__+(if..else..)拦截实例:class Person():
    def __init__(self,name):
        self.name = name
    def __delattr__(self,key):  #若对成员属性进行时自动触发,且此种的key就是 字符串'name',而不是变量name
        print('绝不拦截:{}'.format(self.name))
        if key == 'name':   #如果成员属性名为小白,就会被拦截
            pass
        else:
            super().__delattr__(key)  #删除'小白'外的其他属性都可以
a = Person('小白')
setattr(a,'height',180)  #添加成员属性,第二个参数是字符串
delattr(a,'name')  #删除类中的属性
print(a.__dict__)
delattr(a,'height')
print(a.__dict__)
绝不拦截:小白
{'name': '小白', 'height': 180}
绝不拦截:小白
{'name': '小白'}
#魔术方法:运算类操作
#__gt__操作实例:
class Person():
    def __init__(self,name):
        self.name = name
    def __gt__(self,obj):  #self代表对象a,obj代表对象b
        print('{} 比 {} 大吗?'.format(self.name,obj.name))
        return self.name > self.name
a = Person('abc')
b = Person('cde')
print(a>b)
abc 比 cde 大吗?
False
help(setattr)
Help on built-in function setattr in module builtins:

setattr(obj, name, value, /)
    Sets the named attribute on the given object to the specified value.
    
    setattr(x, 'y', v) is equivalent to ``x.y = v''

类和对象

  • 类和对象三种方法:
    • 实例化方法:
      • 函数中用参数,且第一个参数必须是self
      • 实例化时才可运用
    • 静态方法:
      • 函数中不用参数
      • 不需要实例化,通过类直接访问
    • 类方法:
      • 函数中用参数,第一个参数必须是cls
      • 不用实例化
#类和对象的三种方法
class Person():
    #实例化方法
    def __init__(self):
        print('I am 实例化')
    #静态方法
    @staticmethod
    def sleep():
        print('sleeping ...')
        
    #类方法
    @classmethod
    def play(cls):
        print('playing ...')
        
fact = Person() #实例化
​
Person.sleep() #静态方法
fact.sleep()   #静态方法
​
Person.play() #类方法
fact.play()   #类方法
I am 实例化
sleeping ...
sleeping ...
playing ...
playing ...

抽象方法

  • 含义:没有具体实现内容的方法
  • 作用:规范子类的行为和接口
#抽象方法含义解释
class Animal():
    
    def sayhello(self):  #此处就是运用抽象方法,子类各有表现得差异,填补父类该有的方法即可
        pass
class Person(Animal):
    
    def sayhello(self):
        print('speak hello')
class Dog(Animal):
    
    def sayhello(self):
        print('wow wow!')
person = Person()
dog = Dog()
​
person.sayhello()
dog.sayhello()
speak hello
wow wow!

抽象类

  • 抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
  • 抽象类使用需要借助 abc模块
  • 抽象类作用:设定类的标准,以便开发的时候具有同意统一的规范
  • 抽象类的使用
    • 可以包含抽象方法,也可以包含具体方法
    • 可以有方法,也可以有属性
    • 不允许直接 实例化
    • 必须继承才可使用
    • 继承的子类必须实现所有继承来的抽象方法
    • 假设子类没有实现所有继承的抽象方法,则子类也不能实例化
#抽象类abc模块的运用
import abc
​
#声明一个类并指明当前类的元类
class Human(metaclass=abc.ABCMeta):
    
    #定义一个抽象方法
    @abc.abstractmethod
    def drink(self):
        print('I can drink')
    #定义一个类的抽象方法
    @abc.abstractclassmethod
    def smoking():
        print('I want ban smoking')
    #定义一个静态的抽象方法
    @abc.abstractstaticmethod
    def say():
        print('i can speech ')

自定义类

  • 类其实是一个类定义和各种方法的自由组合
  • 组装类
#组装类实例1
#绑定类(将一个自定义函数绑定到一个类中)
class Person1():
    pass#定义一个函数
def thinking(self):
    print('i have thoughts')
    
class Person2():def thinking(self):
        print('i have thoughts')#此时的函数不属于Person中的方法
#先绑定类操作
​
Person.thinking = thinking 
​
#然后实例化Person1
a = Person()
a.thinking()
thinking(2)   #普通运用函数#实例化Person2
b = Person2()
b.thinking()
i have thoughts
i have thoughts
i have thoughts
#组装类实例2
#绑定实例化(需要特殊方法) MethodType
from types  import MethodType
​
class SuperMan():
    pass
def fly(self):
    print('I can fly')#先实例化类
a = SuperMan()
a.fly = MethodType(fly,SuperMan)  #运用MethodType方法将函数fly绑定至类中
a.fly()
​
I can fly
#利用type创造一个类def swimming(self):
    print('i am swimming')
    
def spitbubbles(self):
    print('i am spitbubbles')#利用type造一个类
​
A = type('Firsh',(object,),{'class_swim':swimming,'calss_spit':spitbubbles})  #key是变量名称
setattr(A,'name','小白')  #添加一个类的属性
#然后实例化刚刚造好的类
a = A()
a.class_swim()  #实例化类中的方法
print(A.__dict__)
i am swimming
{'class_swim': <function swimming at 0x00000204449CEBF8>, 'calss_spit': <function spitbubbles at 0x0000020440D2A620>, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'Firsh' objects>, '__weakref__': <attribute '__weakref__' of 'Firsh' objects>, '__doc__': None, 'name': '小白'}

元类- MetaClass

  • 自身是类
  • 作用:备用创造别的类
  • 必须继承自type,即父类为type,括号内填(type)
  • 命名一般以MetaClass结尾
#元类实例#元类的定义
class YingXiongMetaClass(type):  #父类必须是type
    def __new__(cls,name,sit,t):
        print('我是元类')
        t['name'] = 'HHH'
        t['sit'] = 'BeiJing'
        return type.__new__(cls,name,sit,t)#元类的使用
class Person(object,metaclass=YingXiongMetaClass):
    pass
a = Person()
a.name
​
我是元类
'HHH'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值