多态 鸭子类型 反射 内置方法(__str__,__del__) 异常处理

'''
1什么是多态
多态指的是同一种/类事物的不同形态 2 为何要有多态
多态性:在多态的背景下,可以在不用考虑对象具体类型的前提下而直接使用对象
多态性的精髓:统一
多态性的好处:
1增加了程序的灵活性:
以不变应万变,不论对象千变万化,使用者都是同一种形式去调用
2增加了程序可扩展性
继承一个Animal类创建一个新的类,使用者无需更改自己的代码,还是用原来的方式调用
3 如何用多态 '''
'''
class Animal:
def speak(self):
pass class People(Animal):
def speak(self):
print('say hello') class Dog(Animal):
def speak(self):
print('wang wang wang') class Pig(Animal):
def speak(self):
print('哼哼哼') obj1=People()
obj2=Dog()
obj3=Pig() # obj1.speak()
# obj2.speak()
# obj3.speak() def speak(animal):
animal.speak() speak(obj1)
speak(obj2)
speak(obj3)
# say hello
# wang wang wang
# 哼哼哼 多态性带来的好处,比如python的系列类型有多种形态:字符串,列表,元组,多态性提现下 s1='hello'
l1=[1,2,3]
t1=(1,2) 我们可以在不考虑三者类型的前提下使用是 s l t
print(len(s1)) #s1.__len__()
print(len(l1)) #l1.__len__()
print(len(t1)) #t1.__len__() '''
# import abc
#
#
# class Animal(metaclass=abc.ABCMeta):
# @abc.abstractmethod
# def speak(self):
# pass
#
# @abc.abstractmethod
# def run(self):
# pass # Animal() 父类只是用来建立规范的,不能用来实例化的,更无须实现内部的方法
# 只是规定有这些方法或者属性 具体属性或者方法在子类中具体实现
# class People(Animal):
# def speak(self):
# print('say hello')
#
# def run(self):
# pass
#
#
# class Dog(Animal):
# def speak(self):
# print('汪汪汪')
#
# def run(self):
# pass
#
#
# class Pig(Animal):
# def speak(self):
# print("哼哼哼")
#
# def run(self):
# pass
#
#
# obj = People()
# obj2 = Dog()
# obj3 = Pig() # 上面是强制性的,父类有的方法,子类必须有 # obj.speak()
# obj2.speak()
# obj3.speak()
# say hello
# 汪汪汪
# 哼哼哼 # python 崇尚鸭子类型
# 利用标准库中定义的各种‘与文件类似’的对象,尽管这些对象的工作方式像文件,但他们没有继承内置文件对象的方法
# class Disk:
# def read(self):
# print('Disk read')
#
# def write(self):
# print('Disk write')
#
#
# class Memory:
# def read(self):
# print('Mem write')
#
# def write(self):
# print('Mem write')
#
#
# class Cpu:
# def read(self):
# print('Cpu read')
#
# def write(self):
# print('Cpu write') # obj=Disk()
# obj2=Memory()
# obj3=Cpu()
#
# obj.read()
# obj2.read()
# obj3.read() # Disk read
# Mem write
# Cpu read # 反射: 通过字符串来反射/映射到对象/类的属性上
# (之前是 xx.属性来映射或反射到类或对象的属性上)
# class People:
# def __init__(self,name,age):
# self.name=name
# self.age=age
# def run(self):
# print('%s is running' %self.name)
#
#
# obj=People('egon',18) # print(obj.__dict__) #{'name': 'egon', 'age': 18}
# print(obj.name) #obj.__dict__['name'] #egon
# obj.name="EGON" #obj.__dict__['name']="EGON"
# del obj.name #del obj.__dict__['name']
# print(obj.__dict__) #{'age': 18}
# obj.sex='male' #obj.__dict__['sex']='male' # print(hasattr(obj, 'name')) #True 'name' in obj.__dict__ # print(getattr(obj, 'name')) #拿到值egon obj.__dict__['name']
# print(getattr(obj, 'xx', None)) #拿值 没有则返回None obj.__dict__['xx'] # setattr(obj, 'name', 'EGON') #obj.__dict__['name']='EGON' #EGON 有name就改值
# setattr(obj,'xxx','2222') #{'name': 'egon', 'age': 18, 'xxx': '2222'} 没有就创建
# print(obj.name)
# print(obj.__dict__) # delattr(obj,'name')
# print(obj.__dict__) #{'age': 18} # import os
# os.remove
# print(hasattr(os,'remove')) #True # class Ftp:
# def get(self):
# print('get')
# def put(self):
# print('put')
#
# def login(self):
# print('login')
#
# def run(self):
# while True:
# cmd=input(">>>: ").strip() #cmd='get'
# if hasattr(self,cmd): #cmd in self.__dict
# method=getattr(self,cmd) #self.__dict__['cmd']
# method()
#
# else:
# print('输入方法不存在')
#
#
# obj=Ftp()
# obj.run() # 内置方法:
# __str__:在对象被打印时自动触发,可以用来定义对象被打印时的输出信息
# 注意:必须返回一个字符串类型的值
# class People:
# def __init__(self,name,age):
# self.name=name
# self.age=age
#
# def __str__(self):
# # print('run.....')
# return 'name: %s age:%s'%(self.name,self.age)
# obx=People('egon',18)
# print(obx) #print(obx.__str__())
# name: egon age:18 # obj1=list([1,2,3])
# print(obj1) #[1, 2, 3] # __del__:在对象被删除时先自动触发该方法,可以用来回收对象以外其他相关资源,比如系统资源
# class Foo:
# def __init__(self,x,filepath,encoding='utf-8'):
# self.x=x
# self.f=open(filepath,'rt',encoding=encoding)
#
# def __del__(self):
# print('run.....')
# #回收对象关联的其他资源
# self.f.close() # obj=Foo(1,'a.txt')
# print('========》') 1程序结束了会把占用的内存空间回收掉 删除对象 最后执行__del__回收对象关联的其他资源
# ========》
# run..... # obj=Foo(1,'a.txt') #程序没结束提前删除 会先执行__del__ 回收对象关联的其他资源
# del obj
# print('========》')
# run.....
# ========》 '''
1 什么是异常处理
异常是错误发生的信号,一旦程序出错就会产生一个异常,如果该异常
没有被应用程序处理,那么该异常就会被抛出来,程序的执行也随之终止 异常包含三个部分:
1 traceback异常的追踪信息
2 异常的类型
3 异常的信息 错误分为两大类:
1 语法上的错误:在程序运行前就应该立即修正
2 逻辑上的错误 2 为和要有异常处理
避免程序因为异常而崩溃,所以在应用程序中应该对异常进行处理,从而增强程序的健壮性 3 如何异常处理
try:
代码1
代码2 #抛出一种异常 #!!!!下面代码块不会执行
代码3
。。。
except NameError: #捕获异常也只会捕获一种异常下面的except分支不会执行(像if 。。elif...一样)
当抛出的异常是NameError时执行的子代码块
except....:
pass
except...:
pass
else:
pass #else的子代码块会在被检测的代码块没有异常的情况下执行
finally:
pass #无论被检测的代码有没有异常都会执行 '''
# 语法错误
# print('asdjfkj'
# 1 常见的逻辑错误导致的异常
# age=input('>>: ').strip()
# print(age>10) #TypeError # for i in 10: #TypeError
# pass
# import os #AttributeError
# os.xxx
# 1/0 #ZeroDivisionError # print('====1')
# print('====2')
# print('====3')
# # l=[1,2,3]
# # l[100] #IndexError
# print('====4')
# # d={'x':1,'y':2}
# # d['z'] #KeyError
# print('====5') # 2.异常处理
# 异常处理的单分支
# try:
# print('=====1')
# print('=====2')
# print('=====3')
# d = {'x': 1, 'y': 2}
# d['z'] # KeyError
# print('=====4')
# l = [1, 2, 3]
# l[1000] # IndexError
# print('=====5')
# except IndexError:
# print('IndexError')
# print('other code') # 异常处理的多分支
# try:
# print('=====1')
# print('=====2')
# print('=====3')
# d = {'x': 1, 'y': 2}
# d['z'] # KeyError
# print('=====4')
# l = [1, 2, 3]
# l[1000] # IndexError
# print('=====5')
# except KeyError as e:
# print('KeyError',e)
# except IndexError as e:
# print('IndexError',e)
#
# print('other code') # try:
# print('=====1')
# print('=====2')
# print('=====3')
# d = {'x': 1, 'y': 2}
# # d['z'] # KeyError
# print('=====4')
# l = [1, 2, 3]
# l[1000] # IndexError
# print('=====5')
# except (KeyError,IndexError) as e: #except(里面多个错误捕获类型)
# print(e)
# print('other code') # 万能异常类型Exception:可以匹配任意类型的异常
# try:
# print('=====1')
# print('=====2')
# print('=====3')
# d = {'x': 1, 'y': 2}
# # d['z'] # KeyError
# # xxx
# print('=====4')
# l = [1, 2, 3]
# l[1000] # IndexError
# print('=====5')
# except IndexError as e:
# print('IndexError:', e)
# except KeyError as e:
# print('KeyError:', e)
# except Exception as e:
# print('Exception:',e)
#
# print('other code') # 主动触发异常
# print('===>1')
# print('===>2')
# raise TypeError('类型错误') #运行到这里就报错
# print('===>3') # class People:
# def __init__(self,name,age):
# self.__name=name
# self.__age=age
#
# def tell_info(self):
# print(self.__name,self.__age)
#
# def set_info(self,name,age):
# if not isinstance(name,str):
# raise TypeError('名字必须是str类型')
# if not isinstance(age,int):
# raise TypeError('年龄必须是int类型')
# self.__name=name
# self.__age=age # obj=People('egon',18)
# print(obj.__dict__) # {'_People__name': 'egon', '_People__age': 18}
# obj.tell_info() #egon 18 # obj.set_info('alex',123)
# obj.tell_info() #alex 123 # 自定义异常类型(了解)
# class MyException(BaseException):
# def __init__(self,msg):
# super().__init__()
# self.msg=msg
#
# def __str__(self): #在对象被打印时自动触发,可以用来定义对象被打印时的输出信息
# return '<%s>'%self.msg
#
# raise MyException('我自定义的异常')
# # __main__.MyException: <我自定义的异常> # 断言
print('上半部分,生产数据')
l=[1,2,3,4,5] # if len(l)!=5: #满足条件执行里面的 主动触发异常 下面代码不执行
# raise TypeError('类表长度必须为5')
assert len(l)==5 #相当于门槛,满足条件才执行下面的代码
#AssertionError print('下半部分,处理数据')

封装:封装的真谛在于明确地区分内外,封装的属性可以直接在内部使用,而不能被外部直接使用,然而定义属性的目的终归是要用,外部想要类隐藏的属性,需要我们为其开辟接口,让外部能够间接地用到我们隐藏起来的属性,意义:

  1封装数据:将数据隐藏起来这不是目的。隐藏起来然后对外提供操作该数据的接口,然后我们可以在接口附加对数据的操作限制,以此完成对数据属性操作的严格控制。

class Teacher:
def __init__(self,name,age):
# self.__name=name
# self.__age=age
self.set_info(name,age) def tell_info(self):
print('姓名:%s,年龄:%s' %(self.__name,self.__age))
def set_info(self,name,age):
if not isinstance(name,str):
raise TypeError('姓名必须是字符串类型')
if not isinstance(age,int):
raise TypeError('年龄必须是整型')
self.__name=name
self.__age=age t=Teacher('egon',18)
t.tell_info() t.set_info('egon',19)
t.tell_info()

  2封装方法:目的是隔离复杂度

    在编程语言里,对外提供的接口(接口可理解为一个入口),可以是函数,称为接口函数,这与接口的概念还不一样,接口代表一组接口函数的集合体。

#取款是功能,而这个功能有很多功能组成:插卡、密码认证、输入金额、打印账单、取钱
#对使用者来说,只需要知道取款这个功能即可,其余功能我们都可以隐藏起来,很明显这么做
#隔离了复杂度,同时也提升了安全性 class ATM:
def __card(self):
print('插卡')
def __auth(self):
print('用户认证')
def __input(self):
print('输入取款金额')
def __print_bill(self):
print('打印账单')
def __take_money(self):
print('取款') def withdraw(self):
self.__card()
self.__auth()
self.__input()
self.__print_bill()
self.__take_money() a=ATM()
a.withdraw() 隔离复杂度的例子

  3在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的

#正常情况
>>> class A:
... def fa(self):
... print('from A')
... def test(self):
... self.fa()
...
>>> class B(A):
... def fa(self):
... print('from B')
...
>>> b=B()
>>> b.test()
from B #把fa定义成私有的,即__fa
>>> class A:
... def __fa(self): #在定义时就变形为_A__fa
... print('from A')
... def test(self):
... self.__fa() #只会与自己所在的类为准,即调用_A__fa
...
>>> class B(A):
... def __fa(self):
... print('from B')
...
>>> b=B()
>>> b.test()
from A

隐藏:在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)

  这仅仅只是一种变形操作且仅仅只在类定义阶段发生变形

  类中所有双下划线开头的名称如__x都会在类定义时自动变形成:_类名__x的形式。

__delattr__() 删除属性前进行的操作需要继承super().__delattr__(属性)否则删除不了

__del__() 删除对象前进行的操作 释放和对象相关的其他资源

__delete__()删除对象的属性(属性是组合类型的 一个类的对象作为另外一个类的属性)

上一篇:K2路由器刷机教程


下一篇:svn查看日志(show log)显示时间为1970的解决方法