阅读文本大概需要 6 分钟
写在前面
这段时间通过公号写文章结交了许多志同道合的朋友,他们中有和我一样的大学生、研究生、以及已经工作的前辈。虽然处于不同的人生阶段,但彼此聊得很 High ,每个人的成长历程中总有相似的地方,遇到的困惑迷茫也大致相同。通过相互间的交流沟通,可能困扰自己很久的问题于前辈而言只是一个小 Case ,所以说要勤于沟通,去找寻属于自己的圈子,这样你才能提升得更快。
分享给大家一个观点,提升认知优先于积累知识。我的微信个签是「努力固然重要,但请记得选择比努力更重要」因为你做出选择的前提是你必须具备一定的认知,方向都错了,努力又有什么用呢,不过是南辕北辙,希望给大家带来一些思考。
Python
01
代码块与笔记
函数
参数传递1
"""
参数传递包含:可更改(mutable)与不可更改(immutable)对象
在 Python 中,string tuple number 是不可更改的对象,而 list dict 等则是可以修改的对象
Python 中一切都是对象,严格意义上,我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象
"""
s = "Mark"
l = [1, 2, 3]
"""
在 Python 中,类型属于对象,变量是没有类型的:
以上代码中: " Mark " 是 String 类型,[1,2,3] 是 list 类型,而变量 l 与 s 是没有类型的,
仅仅是一个对象的引用(一个指针),可以是指向 list 类型对象,也可以是指向 string 类型对象
"""
“值”传递2
# 值传递:传递不可变类型 string tuple number 是不可变的
num = 20
num = 10
print(num) # 10
"""
不可变类型:变量赋值 num = 20 后再赋值 num = 10,这里实际上是生成
一个新的 int 值对象 10,再让 num 指向它,而 旧对象 20 被当成垃圾处理了
类似 C++ 的值传递,如整数、字符串、元组。fun(num),传递的只是 num 的值,没有影响
num 对象本身。在 fun(num)内部修改 num 的值,只是修改另一个复制的对象,并不会影响 num 本身
"""
def f1(num):
num = 10
print(num) # 10
num = 20
f1(num)
print(num) # 20
“引用”传递3
# 引用传递:传递可变类型 list,dict 是可变的
"""
可变类型:变量赋值 l = [1, 2, 3] 后再赋值 l[2] = 4 则是将 l 的
第三个元素值更改,本身 l 没有动,只是其内部的一部分值被修改了
类似 C++ 的引用传递,如 列表,字典。fun(l)是
将 l 真正的传过去,修改后 fun 外部的 l也会受影响
"""
def f2(l):
l[0] = 0
print(l) # [0, 2, 3, 4, 5]
l = [1, 2, 3, 4, 5]
f2(l)
print(l) # [0, 2, 3, 4, 5]
匿名函数4
"""
Python 使用 lambda 来创建匿名函数
1.lambda 只是一个表达式,函数体比 def 简单很多
2.lambda 的主体是一个表达式,而不是一个代码块。仅仅能在 lambda 表达式中封装有限的逻辑进去
3.lambda 函数拥有自己的命名空间,且不能访问作用域外的其他变量
"""
_sum = lambda num1, num2: num1 + num2
print(_sum(1, 2)) # 3
递归函数5
"""
递归调用:一个函数,调用了自身,称为递归调用
递归函数:一个会调用自身的函数称为递归函数
递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰
凡是循环能干的,递归都能干
"""
def _sum(n):
if n == 1:
return 1
return n + _sum(n-1)
_sum = _sum(4) # 10
print(_sum)
"""
递归函数的缺点是使用递归函数需要注意防止栈溢出
在计算机中,函数调用是通过栈(stack)这种数据结构实现的
每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧
由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出
如果不信的话大家可以把上面的 n 改得大一点
"""
迭代6.1
"""
如果给定一个 list 或 tuple ,我们可以通过 for 循环来遍历这个 list 或tuple ,
这种遍历我们称为迭代(Iteration)
在 Python 中,迭代是通过 for ... in 来完成的
可迭代对象(Iterable):可以直接作用于 for 循环的对象,无论有无下标
可以直接作用于 for 的数据类型一般分为两种:
1.集合数据类型:如list tuple dict set string
2.是 generator,包括生成器和带 yield 的 generator function
"""
l = [1, 2, 3]
for i in l:
print(i)
d = {"Iu": 26, "Mark": 18}
for k, v in d.items():
print(k, v)
迭代6.2
# 从 collections 模块导入
from collections import Iterable
"""
如何判断一个对象是可迭代对象呢?方法是通过 collections 模块中的
Iterable 类型判断:isinstance()去判断一个对象是否是Iterable对象
"""
print(isinstance([], Iterable)) # T
print(isinstance((), Iterable)) # T
print(isinstance({}, Iterable)) # T
print(isinstance("", Iterable)) # T
# 生成器 generator
print(isinstance((x for x in range(10)), Iterable)) # T
print(isinstance(1, Iterable)) # F
"""
如果要对 list 实现下标循环(同时输出索引与值)怎么办?
Python 内置的 enumerate 枚举函数可以把一个 list 变成索引-元素对,
这样就可以在for循环中同时迭代索引和元素本身
"""
# 同时引用两个变量
l = [(1, 2), (3, 4), (4, 5)]
for x, y in l:
print(x, y)
l = [1, 2, 3]
for i, v in enumerate(l):
print(i, v)
列表生成式7
# 导入 os 模块
import os
# 列表生成式是 Python 内置的非常简单强大的用来创建 list 的
l = [x * x for x in range(1, 5)]
print(l) # [1, 4, 9, 16]
# 加上if判断,筛选出偶数的平方
l = [x * x for x in range(1, 5) if x % 2 == 0]
print(l) # [4, 16]
# 还可以使用两层循环,可以生成全排列:
c = [m + n for m in 'AB' for n in 'XY']
print(c) # ['AX', 'AY', 'BX', 'BY']
# os.listdir可以列出文件和目录
l = [d for d in os.listdir('.')]
print(l)
生成器 generator8.1
"""
通过列表生成式一次性直接创建的列表既受到内存的限制,也会造成资源的浪费
为节省空间,不必创建完整的list,采用一边循环一边计算的机制,称为生成器:generator
"""
# 1.列表生成式改成generator
# 创建 l 和 g 的区别仅在于最外层的[]和()
g = (x * x for x in range(4))
# <generator object <genexpr> at 0x000002077826CFC0>
print(g)
# 遍历 g 元素
for i in g:
print(i)
生成器 generator8.2
# 2.函数定义中包含 yield 关键字,这个函数就不再是一个普通函数,而是一个generator
"""
斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
1, 1, 2, 3, 5, 8, 13, 21, 34, ...
"""
def fib(x):
n, a, b = 0, 0, 1
while n < x:
# 1 1 2 3 5
print(b, end="\t")
a, b = b, a + b
n += 1
print("")
fib(5)
"""
fib 函数中斐波拉契数列的推算规则,从第一个元素开始,推算出后续元素,逻辑类似于generator
要把fib函数变成 generator,只需把 print(b)改为yield b 即可:
"""
def fib(x):
n, a, b = 0, 0, 1
while n < x:
yield b
a, b = b, a + b
n += 1
f = fib(5)
# 注意普通函数返回结果,generator 函数返回一个 generator 对象
# <generator object fib at 0x000002C1944C7EB8>
print(f)
"""
generator和函数的执行流程不同。函数是顺序执行,遇到return语句
或者最后一行函数语句返回;而变成 generator 的函数,在每次调用next()的时候执行,
遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行
"""
def f():
print('step 1')
yield 1
print('step 2')
yield(2)
# 调用该generator时,先生成一个generator对象,再用next()函数不断获得下一个返回值
f = f()
# 注意:越界会出现 StopIteration 错误
next(f) # step 1
02
练习
如果您是刚开始学习 Python 不久,个人感觉今天的分享还是有难度的,大家多花点时间消化一下。函数的知识还有一些,怕大家一次性消化不了,所以今天就分享到这。后天我们继续函数与模块的学习,大家一起加油!
写在最后
最后给大家推送波福利!!!如果你打算入手或着正在学习Python,欢迎加入我们一起学习。后台回复「Python」,获取到你想要的资源。同时我们组建了一个Python技术学习群,里面大佬与小白都有,有很好的学习氛围。想要进群学习的,加 Mark 微信「IMark950831」,备注「加群」,期待你的到来!
好了,今天的分享就到这了,觉得写得不错的,点赞转发支持下。
推荐阅读:
原创不易,感谢分享