Python基础知识-pycharm版 第6节
Python基础知识-pycharm版 第6节
以下是对原文内容按照给定规则进行的同义改写
070.函数也是对象_内存分析
- 函数同样是对象
在Python中,“一切都是对象”的核心理念同样适用于函数这一类数据结构。当我们在定义一个函数时,在内存中会立即生成相应的函数实例供后续操作使用。

当在定义函数时, 系统会生成一个函数对象, 并通过print_star这个关键字进行引用

运行命令“c=print_star”后

明显看出变量c及print_star 均指向同一函数对象因而,在运行c(3)与运行 print_star(3)时效果完全一致在Python语言中使用圆括号表示调用相应函数若无圆括号则该语言会将该名称视为普通对象与此基本原理相似同样可以采取以下方式:
例如:
zhengshu = int
显见地将内置函数int()赋值给变量zhengshu,则该变量及int都将指向同一内置功能请注意此处仅为理论阐述实际开发中无需此类操作
071.变量的作用域_全局变量_局部变量_栈帧内存分析讲解
称作变量的作用域;各作用域中的同名变数互不干扰;根据其作用范围分为全局和局部两类变数。
- 全局变量:
(1) 在函数或类之外的地方声明变量,则该变量的作用域为当前模块,并从声明位置持续到模块结束。
(2) 使用全局变量会降低函数的一般性和易懂性。因此建议尽可能避免使用全局变量。
(3) 全局变量通常被视为常量来处理。
(4) 如果要在函数内部修改全局变量,则需预先声明"global"关键字。
(1) 在函数体内(包括形参)声明为局部的变量。
(2) 被引用时比全局变量更快,在必要时应优先使用。
(3) 当局部变量与全局变量具有相同名称时,在函数体内隐藏其对应的全局变量,并仅使用与之同名的局部变量。



072.局部变量和全局变量_效率测试
在涉及大量数据处理的循环中,在特别关注效率的地方或者需要频繁处理大量数据的循环中,
局部变量的获取和调用速度比全局变量快,
因此优先采用局部变量,
特别是在需要提升运行速度的情况下。

073.参数的传递_传递可变对象_内存分析
函数参数传递的本质是从实参向形参执行赋值操作。在Python编程语言中,'一切皆为对象' 在这种编程范式下, 所有的赋值操作均属于引用赋值, 因此, Python中的参数传递机制本质上是基于引用而非直接复制数据结构的行为特征。这种机制将导致两种不同的处理方式:第一种是针对可变类型变量的操作, 第二种则是针对固定类型变量的操作
传递参数是可变对象(如列表、字典等常见类型),实际传递的是该对象的引用。在函数体内无需创建新副本即可直接修改所传递的对象。
传递参数是可变对象(如列表、字典等常见类型),实际传递的是该对象的引用。在函数体内无需创建新副本即可直接修改所传递的对象。

074.参数的传递_传递不可变对象_内存分析
接收参数通常是不可变类型(如 int, float, string, tuple, bool 类型中)。这些类型中的实例只能作为引用被接受。在赋值操作中,则由于它们无法被修改,系统会生成一个新的实例。

从id值可以看出, n和a最初是同一个对象.对n进行赋值后, 此时n成为一个新的对象.
075.浅拷贝和深拷贝_内存分析
想要深入了解参数传递的基本机制?有必要解释清楚"浅复制与深复制"的概念。你可以选择调用内置库中的复制函数: shallow_copy() 和 deep_copy() 方法。 shallow_copy() 的作用是仅复制目标对象本身及其直接引用的对象;而 deep_copy() 则会完整地复制所有嵌套对象及其内存空间。这样做的好处是,在源代码中对子对象进行修改时不会影响到主对象的内容。


浅拷贝:只拷贝自己,不拷贝“子孙”

深拷贝:拷贝自己和“子孙”

当传递不可变对象时采用的是浅拷贝策略:
其中参数通常为不可变类型(如整数、浮点数、字符串等)。实际传递的是原始数据的引用,在进行'写操作'时会生成新的对象副本。这种副本采用的是浅复制而非深复制。
076.参数的传递_不可变对象含可变子对象_内存分析


077.参数的类型_位置参数_默认值参数_命名参数
函数调用时,默认情况下自变量会按照其在调用时的顺序自动填充,并确保数量与形参一致。这些作为位置参数使用并按顺序传递的自变量被称为:“位置参数”。

允许对某些特定的参数设定预设值。
这种做法使得在传递时这些特定的参数成为可选项。
它们也被称作"默认值"。
这种安排有助于将这些"默认值"置于位置参数之后。

命名参数
可以按照形参的名称传递参数,称为“命名参数”,也称“关键字参数”。

078.参数的类型_可变参数_强制命名参数
可变参数 即为数量多寡不一的参数 其实就是指多个输入项 这种机制在编程中非常实用 它允许我们灵活地接收不同数量的输入 参数的数量由调用者决定 可以通过这种方式实现模块化的代码设计
其中 *param 用于将多个输入项整合为一个有序数据结构 而 **param 则用于整合这些输入项到一个无序数据结构 这种区分有助于我们更好地理解不同场景下的应用场景

在带星号的"可变参数"之后新增参数,在函数调用时必须指定这些新增的变参名称。

079.lambda表达式和匿名函数
lambda表达式可以用来声明匿名函数。lambda 函数是一种简单的、在同一行中定义函数 的方法。lambda函数实际生成了一个函数对象。
lambda表达式只允许包含一个表达式,不能包含复杂语句,该表达式的计算结果就是函数 的返回值。
lambda表达式的基本语法如下:
lambda arg1,arg2,arg3… : <表达式>
arg1/arg2/arg3为函数的参数。<表达式>相当于函数体。运算结果是:表达式的运算结果。

080.eval()函数用法
功能:将字符串str视为有效的表达式进行求值,并返回计算结果。语法:Python的eval函数采用以下形式进行操作:eval(source, globals, locals),并返回计算结果。参数包括三个部分:
(1) source是Python中的一个表达式或函数对象;该对象通常由compile()生成。
(2) globals是一个可选参数,默认为空字典。
(3) locals是一个可选参数,默认为空映射对象。

在程序中调用eval函数时会将输入的字符串作为可执行代码进行评估,在某些情况下可能会引入潜在的安全隐患。例如,在某些情况下提供的字符串可能会包含具有破坏性的指令。这可能会带来严重后果,并提醒我们在实际应用中必须谨慎处理相关的安全风险。
081.递归函数_函数调用内存分析_栈帧的创建 + 082.递归函数_阶乘计算案例
递归函数被称为:一种能够自我执行并返回结果的程序结构,在其定义中会直接或间接地调用自身实现功能。它与我们在中学时期学习过的"数学归纳法"有着相似之处,在这样的结构下,我们需要关注的是如何将问题分解为更小的子问题,并通过这些子问题逐步求解最终目标。每一个子任务都能够独立完成自身的工作并传递所需结果给下一层级的任务。每个递归程序都应具备两个主要组成部分:
-
终止条件
表示递归什么时候结束。一般用于返回值,不再调用自己。 -
递归步骤
把第 n步的值和第 n-1步相关联。
递归函数因其会产生众多的函数实例而可能造成内存泄漏及计算资源耗尽,在处理大量数据时应避免其使用。


