共计 10398 个字符,预计需要花费 26 分钟才能阅读完成。
原创:叫我詹躲躲
起源:思否
链接:python 面型对象编程进阶(继承、多态、私有化、异样捕捉、类属性和类办法)
致谢:感激求知教育提供的视频教程
1. 单继承
## 封装,继承和多态
## 1. 封装
1、满足把内容封装到某个中央,另一个中央去调用封装的内容
2、应用初始化构造方法, 或者应用 self 获取封装的内容
## 2. 继承
子类继承父类的属性和内容
1.1 单继承示例
class Animal:
def eat(self):
print('吃饭了')
pass
def drink(self):
print('喝水了')
pass
class Dog(Animal):
def wwj(self):
## 子类独有的实现
print('小狗汪汪叫')
pass
class Cat(Animal):
def mmj(self):
## 子类独有的实现
print('小猫喵喵叫')
pass
d1 = Dog()
d1.eat()
d2 = Cat()
d2.eat()
## 总结:所以对于面向对象的继承来说,能够极大的晋升效率,缩小反复代码
2. 多继承
class Shenxian:
def fly(self):
print('神仙会飞')
pass
class Monkey:
def chitao(self):
print('猴子喜爱吃桃')
pass
class Sunwukong(Shenxian,Monkey):
pass
swk = Sunwukong()
swk.fly()
swk.chitao()
2.1 留神办法重名:
## 多个父类存在雷同的办法,该调用哪一个
class D(object):
def eat(self):
print('D.eat')
pass
class C(object):
def eat(self):
print('C.eat')
pass
class B(D):
pass
class A(B,C):
pass
a = A()
a.eat
print(A.__mro__) ## 显示类的继承程序
<class '__main__.A'>,
<class '__main__.B'>,
<class '__main__.D'>,
<class '__main__.C'>,
<class 'object'>
## 执行程序应该是 去 A 外面查找,找第一个父类,A 中没有的话,去 B 中查找,,B 类中没有,C 类中没有,去 D 类中查找;
2.2 案例 简洁继承
class Grandfather():
def eat(self):
print('吃的办法')
pass
pass
class Father(Grandfather):
pass
class Son(Father):
pass
son = Son()
print(Son.__mro__)
## <class '__main__.Son'>,
## <class '__main__.Father'>,
## <class '__main__.Grandfather'>,
## <class 'object'>
2.3 重写父类办法
class Grandfather():
def eat(self):
print('吃的办法')
pass
pass
class Father(Grandfather):
## 笼罩了父类的办法
def eat(self):
print('爸爸常常吃海鲜')
pass
class Son(Father):
pass
son = Son()
print(Son.__mro__)
## 定义跟父类雷同的办法,能够实现笼罩和重写父类的办法
2.4 重写初始化办法
class Grandfather():
def __init__(self,name):
self.name = name
pass
def eat(self):
print('吃的办法')
pass
pass
class Father(Grandfather):
def __init__(self):
pass
## 笼罩了父类的办法
def eat(self):
print('爸爸常常吃海鲜')
pass
class Son(Father):
pass
son = Son()
print(Son.__mro__)
2.5 调用父类初始化办法
class Father:
def __init__(self,name):
self.name = name
pass
## 笼罩了父类的办法
def eat(self):
print('爸爸常常吃海鲜')
pass
class Son(Father):
def __init__(self,name):
Father.__init__(self,name) ## 调用父类的办法,能够具备 name 属性
## 或者
## super.__init__(name) ## 也能够这样写
self.age = 90 ## 增加新的实例办法
self.sex = '男'
pass
pass
son = Son('hello')
2.6 调用父类的办法
class Father:
def __init__(self,name):
self.name = name
pass
## 笼罩了父类的办法
def eat(self):
print('父类的吃办法')
pass
class Son(Father):
def __init__(self,name):
Father.__init__(self,name) ## 调用父类的办法,能够具备 name 属性
## 或者
## super.__init__(name) ## 也能够这样写
self.age = 90 ## 增加新的实例办法
self.sex = '男'
pass
pass
def __str__(self):
print('{}'.format(self.name))
pass
def eat(self):
super().eat() ## 调用父类的办法
print('子类的吃办法')
pass
son = Son('詹躲躲')
son.eat()
## 父类的吃办法
## 子类的吃办法
3 多态
同一种行为,对于不同子类【对象】有不同的实现形式
3.1 要想实现多态,必须有两个前提
1. 继承:产生在父类和子类之间
2. 重写:子类重写父类的办法
3.1 案例演示
class Animal:
## 根本类
def say(self):
print('动物类')
pass
pass
class Duck(Animal):
## 子类 派生类
def say(self):
print('鸭子类')
pass
pass
class Dog(Animal):
## 子类 派生类
def say(self):
print('小狗类')
pass
pass
## duck1 = Duck()
## duck1.say()
## dog = Dog()
## dog.say()
def commonIvoke(obj):
## 对立调用
obj.say()
## 循环对立调用
listObj = [Duck(),Dog()]
for item in listObj:
commonIvoke(item)
## 在定义时的类型跟调用时不一样的时候,称为多态。
3.2 多态的益处
1. 减少程序的灵活性
2. 减少程序的扩展性
4. 类属性和实例属性
## 类属性:就是类对象领有的属性,它被所有类对象的实例对象所共有,类对象和实例对象能够拜访。## 实例属性:实例对象所领有的属性,只能通过实例对象拜访。class Student:
## 类属性
name = '叫我詹躲躲'
def __init__(self,age):
self.age = age
pass
pass
lm = Student(18)
## 通过实例对象去拜访类属性
print(lm.name)
print(lm.age)
## 通过类对象去拜访
print(Student.name)
print(Student.age)
## 总结
## 类属性:类对象和实例对象都能够拜访
## 实例属性:只能由实例属性拜访
## 所有的实例对象指向同一类对象
## 实例对象去批改类属性 不能批改
## 类对象能够批改类属性 能够批改
5. 类属性和静态方法
## 装璜器 @classmethod
class Person:
country = 'china'
## 类办法 用 classmethod 润饰
@classmethod
def get_country(cls):
return cls.country ## 拜访类属性
pass
@classmethod
def change_country(cls):
cls.country = 'America'
pass
## 通过类对象去援用
print(Person.get_country())
print(Person.change_country())
print(Person.get_country())
5.1 静态方法
class Person:
country = 'china'
## 类办法 用 classmethod 润饰
@classmethod
def get_country(cls):
return cls.country ## 拜访类属性
pass
@classmethod
def change_country(cls):
cls.country = 'America'
pass
@staticmethod
def get_data():
return Person.country
pass
## 通过类对象去援用
print(Person.get_country())
print(Person.change_country())
print(Person.get_country())
print(Person.get_data())
个别不会通过是实例对象去拜访静态方法
因为静态方法次要寄存逻辑办法,自身与类以及实例没有交互,也就是不会波及类中办法和属性的操作
依据资源可能无效的利用
5.2 求零碎以后的工夫
import time
class sys_time:
def __init__(self,hour,min,second):
self.hour = hour
self.min =min
self.second = second
@staticmethod
## 独立的性能
def show_time():
return time.strftime('%H:%M:%S',time.localtime())
print(sys_time.show_time())
## 15:15:44
5.3 总结
1. 类办法的第一个参数是类对象,cls 进而去援用类对象的属性和办法
2. 实例办法的第一个参数是实例属性,若存在雷同的实例属性或者办法,实例属性优先级最高
3. 静态方法不须要额定的参数,若须要援用属性。,则能够通过类对象或者实例对象去援用即可,必须应用装璜器 @staticmethod 装璜
6. 私有化
6.1 私有化属性
## 公有属性 以__结尾,申明为属性公有,不能在类的内部被应用或者间接拜访。class Person(object):
def __init__(self):
self.__name = '叫我詹躲躲' ## 私有化
self.age = '21'
pass
def __str__(self):
return '{}的年龄是{}'.format(self.__name,self.age)
person = Person()
## print(person.__name) ## 报错
print(person) ## 能够拜访
## 叫我詹躲躲的年龄是 21
## 公有属性,不能被子类继承
6.2 私有化办法
class A(object):
def __eat(self):
print('吃饭')
pass
pass
def run(self):
print('跑步')
pass
pass
b = A()
b.__eat() ## 报错
b.run() ## 跑步
7.property 办法
属性函数
class A(object):
def __init__(self):
self.__name = 18
def __eat(self):
return self.__name
pass
pass
def run(self):
print('跑步')
pass
pass
age = property(__eat, run)
b = A()
print(b.age) ## 报错
b.run() ## 跑步
7.1 @age.setter ## 批改属性
class A(object):
def __init__(self):
self.__name = 18
def __eat(self):
return self.__name
pass
pass
def run(self):
print('跑步')
pass
@property ## 增加属性标识
def age(self):
return self.__name
pass
@age.setter ## 批改属性
def age(self,params):
self.age = params
pass
pass
p1 = A()
print(p1.age) ## 18
p1.age = 16
print(p1.age)
8. __new__办法
作用:创立并返回一个实例对象,如果__new__只调用了一次,就会失去一个对象。继承自 object 的旧式类,才有 new 这一魔术办法。
8.1 注意事项
1.__new__是一个实例化调用的第一个办法
2.__new__至多必须有一个参数 cls, 代表要实例化的类,此参数在实例化时由 python 解释器提供,其余的参数是间接传递给__init__办法
3.__new__决定是否应用该__init__办法,因为__new__能够调用其余的类的构造方法或者返回实例对象作为类的实例,如果__new__没有返回实例,则__init__不会被调用
4. 在__init__办法中,不能调用本人的__new__办法,return cls__new__(cls), 否则会报错。
class A(object):
def __init__(self):
print('__init__执行了')
pass
pass
def __new__(cls,*args,**kwargs):
return super().__new__(cls,*args,**kwargs)
pass
pass
a = A()
print(a)
__init__执行了
<__main__.A object at 0x00000291F97D5160>
## 当__new__返回的时候 __init__才会显示
9. 单例模式
9.1 确保一个类只有一个实例存在, 应用__new__
class DataBaseClass(object):
def __new__(cls,*args,**kwargs):
## cls._instance = cls.__new__(cls) ## 不能应用本人的 new 办法
if not hasattr(cls,'_instance'):
cls._instance = super().__new__(cls,*args,**kwargs)
return cls._instance
pass
pass
db1 = DataBaseClass()
db2 = DataBaseClass()
db3 = DataBaseClass()
print(id(db1))
print(id(db2))
print(id(db3))
## 三个指向的内存地址都一样的
## 1852298514784
## 1852298514784
## 1852298514784
10 谬误和异样解决
try:
## 可能呈现谬误的代码块
except:
## 出错之后执行的代码块
else:
## 没有出错的代码块
finally:
## 不论有没有出错,都会执行
10.1 谬误和异样解决示例
try:
## 可能呈现谬误的代码块
li = [1,2,3]
## print(li[10])
print(1/0)
except IndexError as msg:
## 出错之后执行的代码块
print(msg)
except ZeroDivisionError as msg:
## 出错之后执行的代码块
print(msg)
else:
## 没有出错的代码块
print('没有出错了')
finally:
## 不论有没有出错,都会执行
print('出错了')
## 用一个 try 能够捕捉多个不同类型的异样
10.2 应用 Exception 解决所有谬误
try:
print(b)
except Exception as result:
print(result)
else:
print('出错了')
finally:
print('出错了')
10.3 在适合的档次去捕捉
def A(s):
return s/int(s)
pass
def B(s):
return A(s)/2
pass
def main():
try:
B(0)
except Exception as result:
print(result)
main()
在适合的地位进行谬误捕捉
division by zero
10.4 异样运行机制
1、解释器会查找相应的异样捕捉类型
2、一直传递给下层,没有找到异样解决,会退出
11. 自定义异样类型
class ToolongException(Exception):
def __init__(self, len):
self.len = len
def __str__(self):
return '输出的长度是'+str(self.len)+'长度, 超出长度了'
def name_test():
name = input('输出名字')
try:
if len(name)>5:
raise ToolongException(len(name))
else:
print(name)
except ToolongException as result:
print(result)
else:
print('没有出错了')
name_test()
## 输出的长度是 13 长度, 超出长度了
12 动静增加属性和办法
import types
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
pass
pass
def __str__(self):
return '{}明天 {} 岁了'.format(self.name, self.age)
pass
pass
zhz = Student('詹躲躲', 25)
zhz.wight = 60
def dymicMethod(self):
print('{}体重是{}'.format(self.name,self.wight))
pass
## 动静增加属性
print(zhz.wight)
## 类增加属性
Student.pro = '计算机科学'
## 实例能够拜访
print(zhz.pro)
## 动静增加实例办法
## import types
zhz.printInfo = types.MethodType(dymicMethod,zhz)
zhz.printInfo()
## 詹躲躲体重是 60
13 动静绑定类办法
import types
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
pass
pass
def __str__(self):
return '{}明天 {} 岁了'.format(self.name, self.age)
pass
pass
zhz = Student('詹躲躲', 25)
zhz.wight = 60
def dymicMethod(self):
print('{}体重是{}'.format(self.name,self.wight))
pass
## 动静绑定类办法
@classmethod
def classTest(cls):
print('类办法')
pass
## 动静绑定静态方法
@staticmethod
def staticTest():
print('静态方法')
pass
13.1. 动静增加属性
print(zhz.wight)
13.2. 类增加属性
Student.pro = '计算机科学'
## 实例能够拜访
print(zhz.pro)
13.3. 动静增加实例办法
## import types
zhz.printInfo = types.MethodType(dymicMethod,zhz)
zhz.printInfo()
13.4. 动静绑定类办法
Student.testMethod = classTest
Student.testMethod()
13.5. 动静绑定类办法 实例调用
zhz.testMethod()
13.6. 动静绑定静态方法
Student.statictest = staticTest
Student.statictest()
13.7. 动静绑定静态方法 实例调用
zhz.statictest()
14._slots_属性
class Student(object):
__slots__ = ('name', 'age', 'score')
def __str__(self):
return "{},{}".format(self.name, self.age)
xw = Student()
xw.name = '叫我詹躲躲'
xw.age = 25
## print(xw.__dict__)
## {'name': '叫我詹躲躲', 'age': 25}
xw.s11 = '1212'
#### 报错
print(xw)
子类未声明 __slots__,不会继承父类的__slots__,此时子类能够随便的属性赋值
子类申明了,范畴为 子类 + 父类的范畴
15. 题目练习 一
15.1 python new 的办法和作用是什么?
用来创立实例对象,只有继承了 object 的话,才有这个办法。
15.2 什么是单例模式,实用于什么场景?
要求一个类有且只有一个实例,并且提供了全局的拜访点。日志插入 logger, 网站计数器,权限验证模块,window 资源管理器,零碎回收站,数据库连接池
15.3 私有化办法和私有化属性在子类中是否继承?
不能的
15.4 在 python 中什么是异样?
程序在执行中呈现的异样。
15.5 python 中如何解决异样?
别离依据异样的类型去解决
15.6 python 中异样解决的个别格局,能够应用伪代码形容?
## try:
## 失常操作
## except:
## ##....
## else:
## ##....
## finally:
## ##...
15.7 __slots__的作用
限度属性的随便输出,节俭内存空间
15.8 私有化的属性的作用?
爱护数据,封装性的体现
15.9 在类外是否批改公有属性?
不能够间接批改,通过办法去实现,能够借助 property
15.10 如果一个类,只有指定的属性或者办法能被内部批改,该如何限度?
对属性进行私有化
16 题目练习二
16.1 定义一个 person 类,类中要有初始化办法,办法中要有人名,年龄两个公有属性
提供获取用户信息的函数, 提供设置公有属性的办法, 设置年龄在 0 -120 岁两头,如果不在这个范畴,不能设置胜利
class Person:
def __init__(self,name,age):
self.__name = name
self.__age = age
pass
pass
def GetUserInfo(self):
return "{}的年龄为{}".format(self.__name,self.__age)
pass
pass
def __str__(self):
return "{}的年龄为{}".format(self.__name,self.__age)
def setAge(self,age):
if age>0 and age<120:
self.__age = age
else:
pass
person = Person('詹躲躲',19)
print(person.GetUserInfo())
## 詹躲躲的年龄为 19
print(person.setAge(30))
print(person.GetUserInfo())
## 詹躲躲的年龄为 30
16.2 请写一个单例模式
class DataBaseClass(object):
def __new__(cls,*args,**kwargs):
## cls._instance = cls.__new__(cls) ## 不能应用本人的 new 办法
if not hasattr(cls,'_instance'):
cls._instance = super().__new__(cls,*args,**kwargs)
return cls._instance
pass
pass
db1 = DataBaseClass()
db2 = DataBaseClass()
db3 = DataBaseClass()
print(id(db1))
print(id(db2))
print(id(db3))
16.3 创立一个类,并定义两个私有化属性,提供一个获取属性的办法。利用 property 属性给调用者提供调用
class Student:
def __init__(self, name, score):
self.__name = name
self.___score = score
@property
def name(self):
return self.__name
@name.setter
def name(self, name):
self.__name = name
def __str__(self):
return self
def __call__(self, *args, **kwargs):
print(self.name)
pass
pass
xm = Student('詹躲躲',98)
xm.__call__()
xm.name()
16.4 创立一个 Animal 类。实例一个 cat 对象,给 cat 绑定一个 run 办法,给类绑定一个类属性 color
import types
class Animal:
pass
def run(self):
print('小猫')
cat = Animal()
cat.run = types.MethodType(run,cat)
cat.run()
Animal.color = 'red'
print(cat.color)
def info():
print('ok')
Animal.info = info
Animal.info()
原创:叫我詹躲躲
起源:思否
链接:python 面型对象编程进阶(继承、多态、私有化、异样捕捉、类属性和类办法)
致谢:感激求知教育提供的视频教程