多态性 鸭子类型 内置方法 反射 异常处理 断言 raise 自定义异常

多态性

多态:同一种事物有多种形态。
多态性:多态性指的是可以在不考虑对象具体类型的情况下直接使用对象。

鸭子类型:强耦合思想,把不是同一种事物的用法统一在一起(归一的思想),使用者使用起来会更加方便
多态:同一种事物有多种形态

class Animal:
	def say(self):
		print('动物是这么叫的',end='')

class People(Animal):
	def say(self):
		super().say()
		print('嘤嘤嘤')

class Dog(Animal):
	def say(self):
		super().say()
		print('汪汪汪')
		
class Cat(Animal):
	def say(self):
		super().say()
		print('喵喵喵')
		
类里面的函数改成同一个名字say()
obj1=People()	# 调用类的接口改成变量名obj1
obj2=Dog()		# 调用类的接口改成变量名obj2
obj3=Cat()		# 调用类的接口改名变量名obj3
obj1.say()-----># '动物是这么叫的嘤嘤嘤'	People().say()
obj2.say()-----># '动物是这么叫的汪汪汪'	People().say()
obj3.say()-----># '动物是这么叫的喵喵喵'	People().say()

# 甚至可以定制统一的接口接受传入的动物对象
def animal_say(animal):		# obj1  obj2  obj3当成参数传入
	animal.say()
	

其实我们之前一直在接触这种多态的思想,不管是字符串,列表,字典,元祖,都可以测量长度。因为这些数据类型都有__len__方法。

len多态原理演示
# "aaa".__len__()
# [].__len__()
# {}.__len__()
def len(obj):
    return obj.__len__()

print(len("aaa"))    

我们可以强制规定子类使用父类的功能(通过定义抽象基类),也可以约定俗成靠程序员自我遵守统一的命名规范,下面我们简单示范一下两种情况。

代码演示
import abc

class Animal(metaclass = abc.ABCMeta):  # 导入adc模块强行统一标准,如果子类的代码不写成talk的函数名调用会直接报错
    @abc.abstractmethod		# 强制约束所有子类都得有这些功能
    def talk(self):		# 定义了抽象基类,给父类的功能添加装饰器后,就规定了子类定义名字相同的这些功能,如果子类没有,就会报错
        pass
注意:导入adc模块后的父类只能作为一个标准去定标准,不能再实例化去使用

class Animal:
    def talk(self):
        pass

class Dog(Animal):
    def talk(self):
        print("汪汪汪")

class Cat(Animal):
    def talk(self):
        print("喵喵喵")

class Pig(Animal):
    def talk(self):
        print("哼哼哼")

obj1 = Dog()
obj2 = Cat()
obj3 = Pig()

# 定制统一的接口接受传入的动物对象
def talk(animal):
	animal.talk()
# 代码示范:靠程序员自觉性实现相同效果
class Dog:
	def say(self):
		print('汪汪汪')
class Cat:
	def say(self):
		print('喵喵喵')
class Pig:
	def say(self):
		print('哼哼哼')

但其实我们完全可以不依赖于继承,只需要制造出外观和行为相同对象,同样可以实现不考虑对象类型而使用对象,这正是Python崇尚的“鸭子类型”(duck typing):“如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子”。比起继承的方式,鸭子类型在某种程度上实现了程序的松耦合度。

# 二者看起来都像文件,因而就可以当文件一样去用,然而它们并没有直接的关系
class Txt: # Txt类有两个与文件类型同名的方法,即read和write
    def read(self):
        pass
    def write(self):
        pass

class Disk: # Disk类也有两个与文件类型同名的方法:read和write
    def read(self):
        pass
    def write(self):
        pass

内置方法

class Foo:
    pass

obj = Foo()  # obj是Foo的一个对象,也可以讲Foo是obj的一个实例
print(isinstance(obj, Foo))  # isinstance 用来判断obj是不是Foo的一个实例
print(isinstance([1, 2, 3], list)) # isinstance 用来判断[1,2,3]是不是Foo的一个实例

print(issubclass(Foo, object))  # 判断Foo是否是object的子类

__开头并且__结尾的属性会在满足某种条件下自动触发
class People:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):  # str用来控制对象显示打印结果的,str没有参数,返回值必须是str类型
        return "%s %s" % (self.name, self.age)

obj = People("nana", 18)
print(obj)  # print(obj._str_())

class People:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.f = open("a.txt", mode="rt", encoding="utf-8")

    def __del__(self):  # 类的对象被删除后,会自动触发del的运行
        self.f.close()

obj = People("nana", 18)
del obj
print("=========end============")

反射

反射在类与对象里面全都通用

hasattr:判断对象是否拥有某个属性
getattr: 获得对象中的某个属性                      (查)
setattr:将对象中某个属性设置为新的属性  (增,改。属性没有就增加,有就覆盖)
delattr:删除对象中的某个属性                    (删)
class People:
    country = "China"

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def tell_info(self):
        print(self.name, self.age)

obj = People("nana", 18)		# 调用类传入参数("nana", 18)实例化到一个对象obj

print(hasattr(obj, "country"))   #  hasattr判断能不能调用到obj.country,会先从对象里面去查看,找不到会从类里面去找

res = getattr(obj, "country")   #  getattr取值obj.country
print(res)

method = getattr(obj, "tell_info")	#  getattr可以拿到obj与tell_info的绑定方法
method()

setattr(obj, "xxx", 111)   #  obj.xxx=111
print(obj.xxx)

delattr(obj, "name")   # 删除obj里面self.name
print(obj.name)

异常处理
什么是异常
异常是错误发生的信号,
程序一旦出错就会产生一个异常
如果该异常没有被处理,该异常就会抛出来,程序的运行也随即终止

错误一般分为两种
1.语法错误
2.逻辑错误

如何处理异常
语法错误->程序运行前就必须改正确
逻辑错误->针对可以控制的逻辑错误,应该直接在代码层面解决
针对不可以控制的逻辑错误,应该采用 try…except…

可控的逻辑错误案例:
age = input("age:").strip()
if age.isdigit():
    age = int(age)
    if age > 19:
        print("too big")
    elif age < 19:
        print("too small")
    else:
        print("you got it")
else:
    print("输入的必须是数字")

try…except… 是一种异常产生之后的补救措施

# try...except...的完整语法
print("start...")
try:
    被监测的代码块1
    被监测的代码块2
    被监测的代码块3
    被监测的代码块4
    被监测的代码块5
except 异常的类型1 as e:
    处理异常的代码
except 异常的类型2 as e:
    处理异常的代码
except 异常的类型3 as e:
    处理异常的代码
except (异常的类型4,异常的类型5,异常的类型6)as e:
    处理异常的代码
except Exception:        # Exception可以处理所有的异常,保证程序的正常运行
    处理异常的代码
else:
    没有发生异常时要执行的代码
finally:
    无论异常与否,都会执行该代码,通常用来进行回收资源的操作
print("end...")

# 注意try可以只跟except,finally联用,但是try不能else联用

try…except…模拟不可控逻辑案例演示

案例1print("start...")
try:
    print(111)
    print(222)
    l = [11, 22, 33]
    l[100]
    print(333)
except IndexError as e:  # 异常处理对上了就显示异常提示信息,抛出异常后继续执行代码
    print(e)

print("end...")

案例2print("start...")
try:
    print(111)
    print(222)
    l = [11, 22, 33]
    l[100]
    print(333)
except KeyError as e:  # 异常对不上会直接报错,不会继续执行代码,程序直接崩掉
    print(e)

print("end...")

案例3print("start...")
try:
    print(111)
    print(222)
    l = [11, 22, 33]
    l[0]
    dic = {"k1": 111}
    dic["kkk"]
    print(333)
except Exception as e:  # except Exception可以抛出异常后,继续执行代码
    print(e)
else:  # 没有发生异常时要执行的代码
    print("else的代码")
finally:  # 无论异常与否,都会执行该代码,通常用来进行回收资源的操作
    print("=====>finally的代码")
    
print("end...")

断言 raise 自定义异常

断言代码呈现
l = [111, 222]
# if len(l) != 3:
#     raise Exception("必须达到三个值")
assert len(l) == 3  # 判断条件是否成立,如果条件不成立抛出异常,不会再执行后续代码,一般适用于测试代码的时候,如果条件成立,assert就会当作不存在
print("后续代码")


raise
raise IndexError("索引错误")   # 主动抛异常,自己指定规则的时候可以用raise制定异常


自定义异常
class Permissio(BaseException):
    def __init__(self, msg):
        self.msg = msg


raise Permissio("权限错误")    # 自己制定异常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值