当前位置: 首页 > news >正文

Python基础09_类和对象(下)迭代器和生成器函数式编程

一、类和对象(下)

1、封装

封装是指隐藏类的实现细节,让使用者不用关心这些细节;

封装的目的是让使用者通过尽可能少的方法(或属性)操作对象

Python的封装是假的(模拟的)封装

私有属性和方法

  • python类中以双下划线(__)开头,不以双下划线结尾的标识符为私有成员,私有成员只能使用方法来进行访问和修改

    • __开头的属性为类的私有属性,在子类和类外部无法直接使用

    • __开头的方法为私有方法,在子类和类外部无法直接调用

class A:def __init__(self):self.__a = 100  # 私有属性self.b = 200  # 实例属性# 私有方法def __m1(self):print("私有方法")a = A()
print(a.b)  # 200
print(a.a)  # AttributeError: 'A' object has no attribute 'a'
a.__m1()  # AttributeError: 'A' object has no attribute '__m1'
# 强行访问(不推荐)
print(a._A__a)  # 100
class B(A):def __init__(self):A.__init__(self)def m2(self):# 子类也无法访问self.__m1()print(f"{self.__a}")b_z = B()
b_z.m2()  # AttributeError: 'B' object has no attribute '_B__m1'

2、多态

定义

  • 字面意思"多种状态"

  • 多态是指在有继承/派生关系的类中,调用基类对象的方法,实际能调用子类的覆盖方法的现象叫多态

状态

  • 静态(编译时状态)

  • 动态(运行时状态)

说明

  • 多态调用的方法与对象相关,不与类型相关

  • Python的全部对象都只有"运行时状态(动态)", 没有"C++语言"里的"编译时状态(静态)"

class Shape:def draw(self):print("Shape的draw()被调用")class Point(Shape):def draw(self):print("正在画一个点!")class Circle(Point):def draw(self):print("正在画一个圆!")def my_draw(s):s.draw()  # 此处显示出多态shapes1 = Circle()
shapes2 = Point()
# 调用Circle 类中的draw
my_draw(shapes1)  # 正在画一个圆!
# 调用Point 类中的draw
my_draw(shapes2)  # 正在画一个点!

3、方法重写

果父类方法的功能不能满足需求,可以在子类重写父类的方法

函数重写

在自定义类内添加相应的方法,让自定义类创建的实例像内建对象一样进行内建函数操作

对象转字符串函数重写

str() 函数的重载方法:

  • def __str__(self)
  • 如果没有 __str__(self) 方法,则返回repr(obj)函数结果代替
class MyNumber:"此类用于定义一个自定义的类,用于演示str/repr函数重写"def __init__(self, value):"构造函数,初始化MyNumber对象"self.value = valuedef __str__(self):"转换为普通字符串"return f"{self.value}"n1 = MyNumber("一只猫")
n2 = MyNumber("一只狗")
print(n2)  # 一只狗

内建函数重写

  • __abs__ abs(obj) 函数调用

  • __len__ len(obj) 函数调用

  • __reversed__ reversed(obj) 函数调用

  • __round__ round(obj) 函数调用

算术运算符重载

方法名运算符和表达式说明
__add__(self, rhs)self + rhs加法
__sub__(self, rhs)self - rhs减法
__mul__(self, rhs)self * rhs乘法
__truediv__(self, rhs)self / rhs除法
__floordiv__(self, rhs)self // rhs地板除
__mod__(self, rhs)self % rhs取模(求余)
__pow__(self, rhs)self ** rhs

4、super函数

super() 函数是用于调用父类(超类)的一个方法。

super() 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。

super() 方法的语法:

在子类方法中可以使用super().add()调用父类中已被覆盖的方法

可以使用super(Child, obj).myMethod()用子类对象调用父类已被覆盖的方法

"""
钻石继承问题
D B A C
"""
class A:def process(self):print("A process")class B(A):def process(self):print("B process")# 防止子类同名覆盖# A.process(self)  # 手动调用A的process方法super().process()  # 调用super()方法class C(A):def process(self):print("C process")# 防止子类同名覆盖# A.process(self)  # 手动调用A的process方法super().process()  # 调用super()方法class D(B,C):def process(self):print("D process")# 防止子类同名覆盖# B.process(self)  # 手动调用B的process方法# C.process(self)super().process()  # 调用super()方法d = D()
# d.process()  # D B A C A
d.process()  # D B A C
# 在类的属性中使用super()
class Parent:def __init__(self, name):self.name = nameclass Child(Parent):def __init__(self, name, age):super().__init__(name)  # 调用super()方法 则不用写父类名self.age = agedef print_info(self):print(self.name, self.age)child01 = Child("小明",10)
child01.print_info()  # 小明 10

二、迭代器和生成器

1、迭代器

  • 迭代器是访问可迭代对象的工具

  • 迭代器是指用 iter(obj) 函数返回的对象(实例)

  • 迭代器可以用next(it)函数获取可迭代对象的数据

迭代器函数iter和next

函数说明
iter(iterable)从可迭代对象中返回一个迭代器,iterable必须是能提供一个迭代器的对象
next(iterator)从迭代器iterator中获取下一个记录,如果无法获取一下条记录,则触发 StopIteration 异常

说明

  • 迭代器只能往前取值,不会后退

  • 用iter函数可以返回一个可迭代对象的迭代器

# 可迭代的对象
L = list(range(10))
it = iter(L)
print(next(it))  # 0# try-except 处理异常
while True:try:print(next(it))except:print("迭代结束")break
# 0 1 2 3 4 5 6 7 8 9 迭代结束

2、生成器

生成器和迭代器一样可以配套for循环语句使用。

yield 是一个关键字,用于定义生成器函数,生成器函数是一种特殊的函数,可以在迭代过程中逐步产生值,而不是一次性返回所有结果。

  • yield 语句返回的是可迭代对象
  • return 返回的为不可迭代对象

生成器函数

含有yield 语句的函数是生成器函数,此函数调用回返回一个生成器对象,生成器也是可迭代对象

语法:

yield 表达式
def myrange(stop):i = 0while i < stop:yield ii += 1for x in myrange(10):print(x)# 0 1 2 3 4 5 6 7 8 9

生成器表达式

语法

( 表达式 for 变量 in 可迭代对象 [if 真值表达式])
# [] 内容代表可以省略

三、函数式编程

定义:用一系列函数解决问题。

  • 函数可以赋值给变量,赋值后变量绑定函数。

  • 允许将函数作为参数传入另一个函数。

  • 允许函数返回一个函数。

1、函数作为参数

将核心逻辑传入方法体,使该方法的适用性更广。

def fun01():print("fun01函数执行")# a = fun01()  # fun01函数执行def fun02(func):print("fun02函数执行")func()fun02(fun01)  # fun02函数执行 fun01函数执行

总结

1、使用场合

很多的逻辑或者说核心点是不变的,大多数就是一致的,这个时候就可以使用函数式编程思想,可以很好的去定位这个逻辑【函数式编程思想相对于面向对象编程思想,它更接近于算法】。

2、函数式编程&面向对象思想

如果需求中存在多个逻辑变化点时,可以使用类来进行,因为面向对象中存在继承、重写。而函数式编程思想则是将变化点提取到函数中,实现简单的逻辑。

1.1 lambda表达式
# 定义:
变量 = lambda 形参: 方法体# 调用:
变量(实参)

说明

  • 形参没有可以不填
  • 方法体只能有一条语句,且不支持赋值语句
1.2 内置高阶函数

定义:将函数作为参数或返回值的函数。

常用:

(1)map(函数,可迭代对象)

  • 使用可迭代对象中的每个元素调用函数,将返回值作为新可迭代对象元素;返回值为新可迭代对象。

(2)filter(函数,可迭代对象)

  • 根据条件筛选可迭代对象中的元素,返回值为新可迭代对象。

(3)sorted(可迭代对象, key=函数, reverse=True)

  • 排序,返回值为排序后的列表结果。

(4)max(可迭代对象, key = 函数)

  • 根据函数获取可迭代对象的最大值。

(5)min(可迭代对象,key = 函数)

  • 根据函数获取可迭代对象的最小值。

class Gril:list_girl = []  # 类属性 存放信息def __init__(self,name,score,age,height):self.name = nameself.score = scoreself.age = ageself.height = height# print(self)Gril.list_girl.append(self)def __str__(self):return f"{self.name}-{self.score}-{self.age}-{self.height}"girl01 = Gril("阿珂", 100, 23, 168)
girl02 = Gril("苏荃", 92, 32, 170)
girl03 = Gril("双儿", 90, 25, 159)
girl04 = Gril("小郡主", 79, 22, 160)
girl05 = Gril("方怡", 75, 27, 165)
girl06 = Gril("建宁", 86, 25, 163)
girl07 = Gril("曾柔", 67, 24, 158)# print(girl01)
"""
lambda表达式
变量 = lambda 形参: 方法体
"""# 01 打印所有对象的名称
"""
map(函数,可迭代对象)使用可迭代对象中的每个元素调用函数,将返回值作为新可迭代对象元素;返回值为新可迭代对象
"""
for element in map(lambda item: item.name, Gril.list_girl):print(element)
print("---------------")# 02 获取所有颜值大于80的对象
"""
filter(函数,可迭代对象)根据条件筛选可迭代对象中的元素,返回值为新可迭代对象
"""
for element in filter(lambda item: item.score > 80, Gril.list_girl):print(element)
print("---------------")# 03 获取年龄最大的对象
"""
max(可迭代对象, key = 函数)根据函数获取可迭代对象的最大值
"""
print(max(Gril.list_girl, key=lambda item:item.age))
print("---------------")# 04 排序
"""
sorted(可迭代对象, key=函数, reverse=True)排序,返回值为排序后的列表结果
"""
for element in sorted(Gril.list_girl, key=lambda item:item.score, reverse=False):print(element)"""
阿珂
苏荃
双儿
小郡主
方怡
建宁
曾柔
---------------
阿珂-100-23-168
苏荃-92-32-170
双儿-90-25-159
建宁-86-25-163
---------------
苏荃-92-32-170
---------------
曾柔-67-24-158
方怡-75-27-165
小郡主-79-22-160
建宁-86-25-163
双儿-90-25-159
苏荃-92-32-170
阿珂-100-23-168
"""

2、函数作为返回值

2.1 闭包

定义

  • 定义在一个函数内部的函数,同时这个函数又引用了外部的变量。

  • 在本质上,闭包是将内部嵌套函数和函数外部的执行环境绑定在一起的对象。

满足条件:

  • 必须有一个内嵌函数

  • 内嵌函数必须引用外部函数中变量

  • 外部函数返回值必须是内嵌函数。

def func01():a = 1def func02():print(a)return func02re = func01()
re()  # 1
2.2 装饰器

定义

  • 装饰器是一个函数,主要作用是来用包装另一个函数或类

作用

  • 在不修改被装饰的函数的源代码,不改变被装饰的函数的调用方式的情况下添加或改变原函数的功能。

语法

def 装饰器函数名(fn):语句块return 函数对象@装饰器函数名 <换行>
def 被装饰函数名(形参列表):语句块
def print_func_name(func):def wrapper():# 新功能# __name__ 获取函数名 内置属性print(func.__name__)# 旧功能return func()return wrapper# 被装饰器函数
@print_func_name
def func01():print("func01已执行")return "motto"
@print_func_name
def func02():print("func02已执行")func02()  # func02 func02已执行
func01()  # func01 func01已执行

分类

基本装饰器 带参数的装饰器 装饰器链 类装饰器

"""
旧函数 统计值
新函数 功能是打印总执行时间
"""
import time
# 新函数
def all_time(func):def wrapper(*args, **kwargs):# time.time()方法可以获取当前时间start_time = time.time()# 调用旧函数result = func(*args, **kwargs)# 获得结束时间end_time = time.time()print("执行时间:", end_time - start_time)return result# 闭包 返回内部函数return wrapper# 旧函数
@all_time
def func01():sum_value = 0for i in range(100000000):sum_value += ireturn sum_valuefunc01()  # 4.061215400695801# 输入参数的形式
@all_time
def func02(n):sum_value = 0for i in range(n):sum_value += ireturn sum_valuefunc02(1000000000)  # 41.46981358528137


http://www.mrgr.cn/news/54262.html

相关文章:

  • 微服务的一些基本概念
  • MySQL | Explain的是使用详解
  • 05,hive
  • Synopsys工具中命令中filter选项
  • Vue前端开发2.2 数据绑定
  • nextjs中集成富文本编辑器wangEditor
  • UEFI 基础教程 (四十八.2) — UEFI code style
  • org.apache.http.impl.client.CloseableHttpClient的时候如果发生异常
  • 《使用Gin框架构建分布式应用》阅读笔记:p88-p100
  • 群控系统服务端开发模式-功能整理
  • 【移动安全】OWASP MASTG 移动应用程序安全测试指南
  • 大模型~合集14
  • 理解 React 中的 ReactElement、children 和 ReactNode
  • Java 线程池获取池中所有线程列表的方法
  • 优化方法之随机梯度下降SGD优化器收敛性证明
  • 代码随想录day04
  • mysql connect -- C api编译链接问题,接口介绍(初始化和销毁,连接,执行sql语句,获取结果集的元数据和数据,设置编码格式)
  • Python Logging 模块
  • Unexpected error: java.security.InvalidAlgorithmParameterException
  • 关于office中的word文档图片替换问题
  • MySQL程序介绍<二>
  • freeswitch-esl 进行强拆控制
  • 【代码随想录Day46】单调栈Part01
  • 探索计算机技术的无限可能:从基础到前沿的深度之旅
  • PCL 点云配准 非线性加权最小二乘优化的点到面ICP算法(精配准)
  • 使用 NVBit 进行内存访问跟踪指南