java 斐波那契数列 重载方法_Python学习笔记(2)

本文详细介绍了Python中的抽象类、接口、多态概念,以及如何使用abc模块实现抽象类。同时,讨论了多态在程序设计中的重要性。此外,还讲解了生成器的使用,包括自定义异常、迭代器、列表生成器和函数生成器,以及生成器的应用场景。最后,提到了如何判断一个函数是否为生成器函数的方法。
摘要由CSDN通过智能技术生成

抽象类:

抽象类是包含抽象方法的类,该类不能被实例化,而抽象方法不包含任何可实现的代码(常用pass语句),只能在其子类中实现抽象函数的代码(一般被子类继承,通过子类实例化后重写方法。

子类一定要实现重写抽象类的所有抽象方法,否则这个子类就是一个抽象类,不能被实例化。

python 本身中不存在抽象类、接口的概念,要实现这种功能需要abc.py这个类库。具体方式:在定义抽象类前需要从类库abc 导入 ABCmeta类(即Metaclass for defining ABstract BaseClasses, 抽象基类的元类)和abstractmethod类。

定义抽象类的步骤:

1、在定义抽象类时需要在类定义中加入如下代码: metaclass=abc.ABCMeta ,  即指定该类的元类是 ABCmeta , 所谓元类就是创建类的类。

2、在定义抽象方法时需要在前面加入如下代码:  @abstractmethod   ;  因为抽象方法不包含任何可实现的代码,因此函数体通常使用 pass 。

48304ba5e6f9fe08f3fa1abda7d326ab.png

import abc

from abc import abstractmethod

class Test(metaclass=abc.ABCMeta):

def __init__(self):

print('做点什么')

@abstractmethod

def do(self):

pass

48304ba5e6f9fe08f3fa1abda7d326ab.png

接口:

接口是一种特殊的类。当抽象类中所有的方法都是抽象方法时,或者一个普通类所有的方法都没有实现逻辑,我们可以把这个类当成一个接口 Interface。

Python中并没有 Interface 这个关键字来定义一个接口,其实就是定义一个抽象类,个人可理解为 是为了规范子类中的所有方法一致性。

接口有两点要注意:

1、接口的实现类(子类)必须要有接口中所有的方法

2、接口的实现类(子类)实现的方法必须跟接口中所有的方法的名字一样

接口有两种实现方式:

48304ba5e6f9fe08f3fa1abda7d326ab.png

import abc

from abc import abstractmethod

#使用抽象类实现,该类里面全是抽象方法

class Interface1(metaclass=abc.ABCMeta):

@abstractmethod

def show(self):

pass

# 使用普通类实现,该类里面全是没有实现逻辑的方法

class Interface2:

def show(self):

pass

class Test(Interface1):

def show(self):

print('重写每一个方法,赋予逻辑')

class Test2(Interface2):

def show(self):

print('重写每一个方法,赋予逻辑')

48304ba5e6f9fe08f3fa1abda7d326ab.png

多态:

所谓多态指的是程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在程序运行期间才决定。

简单理解: 一个函数的参数,通过传入参数的不同具备不同的意义;或者 + 号在不同的地方使用具备不同的意义,这就是多态。

多态的好处: OOP的开闭合原则,对添加代码开放,对修改代码闭合。

实现多态的方法: 1、使用继承;  2、使用接口

重载:

重新定义print输出的内容,使用__str__() 方法,该方法 return 回一个 输出的值。 在类里面定义该方法,直接输出实例对象,会输出 __str__() 方法返回的值

48304ba5e6f9fe08f3fa1abda7d326ab.png

class Test:

def __str__(self):

return '这是重新定义输出的内容'

test = Test()

print(test) # 这是重新定义输出的内容

48304ba5e6f9fe08f3fa1abda7d326ab.png

运算符重载,就是对已有的运算符重新进行定义,赋予其另一种新的功能,以适应不同的数据类型。在一个类中具备了对运算符进行重载的多个方法,该方法可以重新定义两个实例对象相加或相减等运算的结果。

48304ba5e6f9fe08f3fa1abda7d326ab.png

# encoding=utf-8

class Vector:

def __init__(self, x, y):

self.X = x

self.Y = y

# 重载print()方法

def __str__(self):

return "[{0}, {1}]".format(self.X, self.Y)

# 重载 + 运算符

def __add__(self,other):

return Vector(self.X + other.X, self.Y + other.Y)

# 重载 - 运算符

def __sub__(self,other):

return Vector(self.X - other.X, self.Y - other.Y)

# 重载 * 运算符

def __mul__(self,other):

return Vector(self.X * other.X, self.Y * other.Y)

# 重载 % 运算符

def __mod__(self,other):

return Vector(self.X % other.X, self.Y % other.Y)

v1 = Vector(5, 6)

print(v1) # [5, 6]

v2 = Vector(5, 6)

v3 = Vector(3, 3)

print(v2 + v3) # [8, 9]

v4 = Vector(5, 6)

v5 = Vector(3, 3)

print(v4 - v5) # [2, 3]

v6 = Vector(5, 6)

v7 = Vector(3, 3)

print(v6 * v7) # [15, 18]

v8 = Vector(5, 6)

v9 = Vector(3, 3)

print(v8 % v9) # [2, 0]

48304ba5e6f9fe08f3fa1abda7d326ab.png

自定义异常: 除了默认的异常类型,还可以使用 repr() 方法 在类里面自定义异常:

48304ba5e6f9fe08f3fa1abda7d326ab.png

#encoding=utf-8

class MyException(Exception):

def __init__(self, value):

self.value = value

def __str__(self):

return repr(self.value) # 自定义抛出异常信息

try:

test = int(input('请输入年龄'))

if test > 130:

raise MyException('年龄不能大于130') # 自定义抛出异常

if test < 1:

raise MyException('年龄不能小于1') # 自定义抛出异常

except ValueError as e:

print('请输入数字')

except MyException as a: # 使用自定义的异常类型

print(a.value)

48304ba5e6f9fe08f3fa1abda7d326ab.png

迭代器: 使用 iter()  方法, 使某个集合转换为迭代对象, 使用next() 依次输出里面的值。通常跟for 循环配合使用;

48304ba5e6f9fe08f3fa1abda7d326ab.png

list1 = [1,2,3,4,5,6,7,8]

iter1 = iter(list1)

print(next(iter1)) # 1

print(next(iter1)) # 2

for t in iter1:

print(t)

48304ba5e6f9fe08f3fa1abda7d326ab.png

列表生成器: 通过列表生成式,我们可以直接创建一个列表。但是受到内存限制,列表容量肯定是有限的。而且当创建的列表包含100万个数据时,会占用很大的内存,如果我们仅仅使用到前几个数据,那么后面元素占用的空间就浪费了。所以,将列表元素按照某种算法推算出来,不必创建完整的list, 从而节省大量的空间,这种一边循环一边计算的机制,称为生成器(Generator) 。

创建生成器的方法: 把一个列表生成式的 []  改为 ()

list1 = [x for x in range(1,1000)] # 列表生成式

list2 = (x for x in range(1,1000)) # 列表生成器

print(list2)

创建函数生成器的方法:在一个函数内定一个 yield 语句,那个这个函数就变成了 Generator 。 函数生成器和函数的执行流程不一样,函数是顺序执行,遇到return或者执行完毕就返回。而变成generator的函数,在每次调用next() 的时候执行,遇到 yield 语句返回,再次执行时从上次返回的yield语句处继续执行。   如果在 yield 语句前先遇到return ,会直接停止迭代并抛出异常。

48304ba5e6f9fe08f3fa1abda7d326ab.png

def sum():

print('one')

yield 1

print('two')

yield 2

print('three')

yield 3

print('end')

test = sum()

next(test) # one

next(test) # two

next(test) # three

next(test) # end 超过迭代长度,报错

48304ba5e6f9fe08f3fa1abda7d326ab.png

斐波那契数列的各种实现方法:

48304ba5e6f9fe08f3fa1abda7d326ab.png

def fibo(n):

a, b, n1 = 0, 1, 0

while n1 < n:

a, b = b, a + b

print(a)

n1 = n1 + 1

fibo(5) # 1 1 2 3 5

48304ba5e6f9fe08f3fa1abda7d326ab.png

48304ba5e6f9fe08f3fa1abda7d326ab.png

import sys

class Fibo:

def __init__(self, max):

self.max = max

self.a, self.b, self.n = 0,1,0

def __iter__(self): #迭代器,返回自己

return self

def __next__(self):

if self.n < self.max:

r = self.b

self.a, self.b = self.b, self.a + self.b

self.n = self.n + 1

return r

else:

sys.exit(0)

for t in Fibo(5):

print(t) # 1 1 2 3 5

48304ba5e6f9fe08f3fa1abda7d326ab.png

48304ba5e6f9fe08f3fa1abda7d326ab.png

def fibo(n):

a, b, n1 = 0, 1, 0

while n1 < n:

a, b = b, a + b

yield a

n1 = n1 + 1

for t in fibo(5):

print(t) # 1 1 2 3 5

48304ba5e6f9fe08f3fa1abda7d326ab.png

如何判断一个函数是否一个generator函数,使用 isgeneratorfunction 模块:

48304ba5e6f9fe08f3fa1abda7d326ab.png

from inspect import isgeneratorfunction

def fibo(n):

a, b, n1 = 0, 1, 0

while n1 < n:

a, b = b, a + b

yield a

n1 = n1 + 1

print(isgeneratorfunction(fibo)) # True

48304ba5e6f9fe08f3fa1abda7d326ab.png

生成器的应用场景:

1、遍历输出多维列表(扁平化列表)

48304ba5e6f9fe08f3fa1abda7d326ab.png

list1 = [1,[2,3,4],5,6,[7,[8,9]]]

def flatten(list2):

if type(list2) == list:

for t in range(len(list2)):

for e in flatten(list2[t]):

yield e

else:

yield list2

for t in flatten(list1):

print(t)

48304ba5e6f9fe08f3fa1abda7d326ab.png

2、切割读取文件。直接对文件对象调用read() 方法,会导致不可预测的内存占用。好的方法是利用固定长度的缓冲区来不断读取文件内容:

48304ba5e6f9fe08f3fa1abda7d326ab.png

def readFile(paths):

block_size = 4096 * 2

with open(paths, mode='r+') as f:

while True:

block = f.read(block_size)

if block:

yield block

else:

return

for t in readFile('test.txt'):

with open('new.txt', mode='a+') as f2:

f2.write(t)

48304ba5e6f9fe08f3fa1abda7d326ab.png

生成器支持的方法:

close() 方法: 手动关闭生成器,关闭后再次调用迭代会报异常

48304ba5e6f9fe08f3fa1abda7d326ab.png

def test():

yield 1

yield 2

yield 3

yield 4

t = test()

print(next(t)) # 1

print(next(t)) # 2

t.close()

print(next(t)) # 报停止迭代异常

48304ba5e6f9fe08f3fa1abda7d326ab.png

send() 方法: 用于向生成器传入某个参数,yield会根据参数返回特定的值,使用该方法第一次调用的时候必须传 None

48304ba5e6f9fe08f3fa1abda7d326ab.png

def test():

value = 0

while True:

r = yield value

if r == 'stop':

break

value = '得到某个值进行操作并返回:%s'%r

t = test()

print(t.send(None)) # 0 第一次调用必须传 None

print(t.send('a')) # 得到某个值进行操作并返回:a

print(t.send('b')) # 得到某个值进行操作并返回:b

print(t.send('stop')) # 停止迭代报异常

48304ba5e6f9fe08f3fa1abda7d326ab.png

throw()  方法: 用于使生成器抛出指定的异常类型,或自定义异常类型。调用该方法的时候,会消耗下一次迭代。

48304ba5e6f9fe08f3fa1abda7d326ab.png

def test():

while True:

try:

yield '正常输出1'

yield '正常输出2'

print('迭代结束')

except ValueError:

print('值异常')

except TypeError:

break

t = test()

print(next(t)) # 正常输出1

print(next(t)) #正常输出2

t.throw(ValueError) # 值异常

print(next(t)) #正常输出2

标签:__,Python,self,笔记,学习,yield,print,方法,def

来源: https://www.cnblogs.com/xuezhimin-esage-2020/p/14283426.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值