类和对象(接上篇)
封装
私有属性和方法:
python类中以双下划线(__
)开头,不以双下划线结尾的标识符为私有成员,私有成员只能使用方法来进行访问和修改
-
以
__
开头的属性为类的私有属性,在子类和类外部无法直接使用 -
以
__
开头的方法为私有方法,在子类和类外部无法直接调用
魔术方法:
常用的Python魔术方法
-
__init__(self, ...)
: 初始化对象,通常用于设置对象的属性。 -
__str__(self)
: 定义对象的字符串表示形式,可通过str(object)
或print(object)
调用。例如,您可以返回一个字符串,描述对象的属性。 -
__repr__(self)
: 定义对象的“官方”字符串表示形式,通常用于调试。可通过repr(object)
调用。 -
__len__(self)
: 定义对象的长度,可通过len(object)
调用。通常在自定义容器类中使用。
多态 polymorphic
-
多态调用的方法与对象相关,不与类型相关
-
Python的全部对象都只有"运行时状态(动态)", 没有"C++语言"里的"编译时状态(静态)"
方法重写
如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法
函数重写
在自定义类内添加相应的方法,让自定义类创建的实例像内建对象一样进行内建函数操作
str/函数重写示例:
内建函数重写
-
__abs__
abs(obj) 函数调用 -
__len__
len(obj) 函数调用 -
__reversed__
reversed(obj) 函数调用 -
__round__
round(obj) 函数调用
运算符重载
运算符重载的作用:
让自定义类的实例像内建对象一样进行运算符操作
让程序简洁易读
对自定义对象将运算符赋予新的运算规则
运算符重载说明:
运算符重载方法的参数已经有固定的含义,不建议改变原有的意义
super函数
super() 函数是用于调用父类(超类)的一个方法。
super() 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
super() 方法的语法:
在子类方法中可以使用super().add()调用父类中已被覆盖的方法
可以使用super(Child, obj).myMethod()用子类对象调用父类已被覆盖的方法
super().init()
super().__init__()
是 Python 中用于调用父类(基类)构造函数的一种方式。它通常用于子类的构造函数中,以确保父类的构造函数被正确调用和初始化。这在继承(inheritance)中尤为重要,因为父类的初始化代码可能包含设置实例变量或执行其他重要的初始化任务。
super().init()的作用
-
代码重用:避免在子类中重复父类的初始化代码。
-
正确初始化:确保父类的初始化逻辑(如设置属性、分配资源等)被执行。
-
支持多重继承:在多重继承情况下,
super()
可以确保所有基类的构造函数都被正确调用。
Python迭代器与生成器
-
迭代器是访问可迭代对象的工具
-
迭代器是指用 iter(obj) 函数返回的对象(实例)
-
迭代器可以用next(it)函数获取可迭代对象的数据
迭代器函数iter和next
-
迭代器只能往前取值,不会后退
-
用iter函数可以返回一个可迭代对象的迭代器
-
迭代器对象能用next函数获取下一个元素
生成器
生成器是在程序运行时生成数据,与容器不同,它通常不会在内存中保留大量的数据,而是现用现生成。
-
yield 是一个关键字,用于定义生成器函数,生成器函数是一种特殊的函数,可以在迭代过程中逐步产生值,而不是一次性返回所有结果。
-
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
-
每次使用 yield 语句生产一个值后,函数都将暂停执行,等待被重新唤醒。
-
yield 语句相比于 return 语句,差别就在于 yield 语句返回的是可迭代对象,而 return 返回的为不可迭代对象。
-
然后,每次调用生成器的 next() 方法或使用 for 循环进行迭代时,函数会从上次暂停的地方继续执行,直到再次遇到 yield 语句。
生成器函数
含有yield 语句的函数是生成器函数,此函数调用回返回一个生成器对象,生成器也是可迭代对象
yield 语句的语法
生成器表达式
( 表达式 for 变量 in 可迭代对象 [if 真值表达式])
python 函数式编程
-
函数可以赋值给变量,赋值后变量绑定函数。
-
允许将函数作为参数传入另一个函数。
-
允许函数返回一个函数。
函数作为参数
将核心逻辑传入方法体,使该方法的适用性更广。
lambda 表达式
作用:
-- 作为参数传递时语法简洁,优雅,代码可读性强。
-- 随时创建和销毁,减少程序耦合度。
语法
内置高阶函数
常用:
(1)map(函数,可迭代对象)
-
使用可迭代对象中的每个元素调用函数,将返回值作为新可迭代对象元素;返回值为新可迭代对象。
(2)filter(函数,可迭代对象)
-
根据条件筛选可迭代对象中的元素,返回值为新可迭代对象。
(3)sorted(可迭代对象, key=函数, reverse=True)
-
排序,返回值为排序后的列表结果。
(4)max(可迭代对象, key = 函数)
-
根据函数获取可迭代对象的最大值。
(5)min(可迭代对象,key = 函数)
-
根据函数获取可迭代对象的最小值。
函数作为返回值
闭包 closure
闭包必须满足以下三个条件:
-
必须有一个内嵌函数
-
内嵌函数必须引用外部函数中变量
-
外部函数返回值必须是内嵌函数。
示例:
装饰器 decorators(专业提高篇)
装饰器是一个函数,主要作用是来用包装另一个函数或类
装饰器的作用:
在不修改被装饰的函数的源代码,不改变被装饰的函数的调用方式的情况下添加或改变原函数的功能。
函数装饰器的语法:
基本装饰器
用函数装饰器替换原函数myfun
当使用@mydeco
语法装饰myfun
函数时,实际上发生的是:
-
myfun
函数作为参数传递给了mydeco
装饰器。 -
在
mydeco
内部,首先调用了fn()
,即此时调用了myfun
函数,产生了输出:"函数myfun被调用"。 -
接着,打印了"装饰器函数被调用了,并返回了fx"。
-
然后,
mydeco
装饰器返回了新的函数fx
。 -
第二次调用时,调用的实际是第一次调用后返回的fx函数。因此,此刻
myfun
实际上被替换成了新的函数fx
。这样的行为正是Python装饰器的特性之一:装饰器可以修改函数的行为,甚至完全替换被装饰的函数。
有参数的函数装饰器(在myfunc外加了一层)
mydeco
是一个装饰器函数,它接受一个函数fn
作为参数。- 在
mydeco
内部,我们定义了一个新的函数fx
。这个新函数会:- 打印一条消息 "====这是myfunc被调用之前===="。
- 调用原始的函数
fn()
并保存返回值到变量ret
。 - 打印另一条消息 "----这是myfunc被调用之后===="。
- 返回
fn
的返回值(在这个例子中是None
,因为myfunc
没有显式地返回任何东西)。
mydeco
函数最后返回了这个新的函数fx
。@mydeco
是 Python 中的一种语法糖,它将myfunc
函数作为参数传递给mydeco
装饰器,并将mydeco
的返回值(也就是fx
函数)重新赋值给myfunc
。- 因此,在使用装饰器后,当我们调用
myfunc
时,实际上是在调用fx
函数。 - 当
myfunc
第一次被调用时,实际上是fx
被调用。 fx
首先打印 "====这是myfunc被调用之前===="。- 然后
fx
调用原来的myfunc
函数,这会导致打印 "myfunc被调用."。 - 接着
fx
打印 "----这是myfunc被调用之后===="。 fx
完成执行并返回(在这个情况下没有实际返回值,因为myfunc
没有返回任何内容)。- 这个过程在每次调用
myfunc
时都会重复。
输出结果
当你运行上面的代码三次,你会得到如下输出:
装饰器链
具体的执行过程如下:
-
装饰器是从内到外依次应用的。在你的代码中,首先应用的是
@uppercase
,然后是@exclamation
。 -
@uppercase
装饰器会先包裹say_hello
函数,然后@exclamation
装饰器再包裹已经被@uppercase
包裹过的函数。
步骤详细如下:
-
首先
@uppercase
包装say_hello
函数:-
调用
say_hello("Bob")
返回"Hello, Bob"
。 -
@uppercase
装饰器的wrapper
函数将结果转换为大写,变为"HELLO, BOB"
。
-
-
然后
@exclamation
包装已经被@uppercase
包装过的say_hello
函数:-
调用
wrapper
(即@uppercase
装饰器的wrapper
函数)返回"HELLO, BOB"
。 -
@exclamation
装饰器的wrapper
函数将结果加上一个感叹号,变为"HELLO, BOB!"
。
-
类装饰器
-
MyDecorator
是一个类装饰器,它接受一个函数func
作为参数并在__call__
方法中执行额外操作。 -
使用
@MyDecorator
应用类装饰器,它将包装say_hello
方法,使其在调用前后执行额外操作。 -
与基本装饰器类似