文章目录
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) #可运用父类的属性name
print(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(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 语句,进行删除拦截
- _getattr_
-
运算类操作
- _gt_
- 进行大小判断的时候触发函数
- 填入参数:
- self:获取当前对象
- 第二个参数是第二个对象
- 返回任意值,推荐布尔值.
- _gt_
-
#魔术方法:操作类实例
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'