转:https://www.tuicool.com/wx/vEVrqeR
06 python开发之函数
博客园精华区12-12 20:56
目录
* 6.2 调用函数与函数返回值
* 6.2.1 调用函数三种形式
* 6.2.2 函数的返回值return(函数的产品)
函数就是用来盛放代码的容器
具备某一功能的工具-->工具
实现准备好工具的过程-->函数的定义
遇到应用场景,拿来就用
使用函数可以解决代码可读性差以及拓展性差的问题
先定义后引用
def 函数名(参数1,参数2,…):
"""文档描述"""
函数体
return 值
def say_hello(): # say_hello=函数的内存地址
print("======")
print("hello world")
print("======")
print(say_hello) #
say_hello()
x = 10 # x=10的内存地址
print(x)
# 函数定义阶段:只检测语法,不执行代码
def foo():
xxx
print('from foo')
foo()
示例1
def bar():
print('from bar')
def foo():
print('from foo')
bar()
foo() # from foo | from bar
示例二
def bar():
print('from bar')
foo()
def foo():
print('from foo')
bar() # from bar | from foo
示例三
def bar():
print('from bar')
foo()
bar() # 报错,要先定义后引用
def foo():
print('from foo')
定义函数的三种形式
# 无参函数
def f1():
print("hello")
print("你好")
print("Hi")
f1() # hello | 你好 | Hi
def login():
name = input('username>>>:').strip()
pwd = input('password>>>:').strip()
if name == "ccc" and pwd == '111':
print('ok')
else:
print('error')
login() # username>>>:
def login(name,pwd):
if name == "ccc" and pwd == "123":
print('ok')
else:
print('error')
login("ccc","123") # ok
login("ccc","1234") # error
def f2(x, y):
print(x)
print(y)
f2(111, 222) # 111 | 222
def add(x, y):
print(x+y)
add(10, 20) # 30
add(30, 40) # 70
def login():
pass
def transfer():
pass
def withdraw():
pass
def check_balance():
pass
len("hello")
res = len("hello") + 10
print(res) # 15
def add(x, y):
z = x + y
return z
print(add(5, 5)) # 10
res = add(add(1, 2), 3)
print(res) # 6
Ⅰ 没有return-->默认返回就是None
def func():
print(111)
res = func() # 111
print(res) # None
Ⅱ return 值-->返回就是那一个值
def max2(x, y):
if x > y:
return x
else:
return y
res = max2(100, 200) * 5
print(res) # 1000
Ⅲ return 值1,值2,值3--->返回的是一个元组
def func():
return [11, 22], 2, 3
res = func()
print(res, type(res)) # ([11, 22], 2, 3)
def func():
print(111)
return 2201202
print(2222)
return 11112222
print(3333)
res = func()
print(res) # 111 2201202
return就是函数的处理结果
函数内没有return关键字,或者说return后面没有值-->None
return 值
return 值1,值2,值3--->(值1,值2,值3)
可以有多个return,但只要执行一次整个函数就会立即结束,并且返回值
def f1():
x = 10
def f2():
print('from f2')
return f2
res = f1() # 即res=f2的内存地址
print(res) #
res() # from f2
python3新增类型提示功能,例如我们可以为函数增加类型提示信息,而不影响函数本身的执行:
注释的一般规则是参数名后跟一个冒号(:),然后再跟一个expression,这个expression可以是任何形式。
# Type hinting
def add(x: int, y: int) -> int:
res = x + y
return res
print(add.__annotations__)
形参
在定义函数时,在括号内指定参数/变量名,称之为形式参数,简称形参
形参的本质就是变量名
实参
在调用函数时,括号内传入的值,称之为实际参数,简称实参
实参的本质就是变量值
实参与形参的关系
在调用函数时,实参的值会绑定给形参,该绑定关系可以在函数内使用
在函数调用结束后,会解除绑定关系
在定义函数时,按照从左往右的顺序依次定义的变量名,称之为位置形参
特点:必须被传值,多一个少一个都不行
def func(x, y):
print(x, y)
func(1, 2)
func(1, 2, 3) # 报错
func(1) # 报错
在调用函数时,按照从左往右的顺序依次传入的值,称之为位置实参
特点:按照位置与形参一一对应
def func(x, y):
print(x, y)
func(1, 2)
func(2, 1)
在定义函数时就已经为某个形参赋值了,该形参就称为默认参数
特点:在调用阶段可以不用为默认形参传值
def func(x, y=111):
print(x, y)
func(1, 2) # 1 2
func(1) # 1 111
def register(name, age, gender="male"):
print(name, age, gender)
register("egon", 18)
register("lxx", 38)
register("hxx", 32, "female")
register("李建国", 30)
register("alex", 31)
register("xxx", 18)
在调用函数时,按照key=value的形式指定的实参,称之为关键字实参
特点:可以打乱顺序,仍能指名道姓为指定的形参赋值
def func(x, y=2222):
print(x, y)
func(y=222, x=1212) # 1212 222
func(x=111) # 111 2222
位置实参和关键字实参可以混用,注意点:
Ⅰ 位置实参必须放在关键字实参前面
Ⅱ 不能为同一个形参重复赋值
def func(x, y=2222):
print(x, y)
func(1, y=2) # 1 2
func(y=2, 1) # 报错
func(1, y=2, x=3) # 报错
位置形参和默认形参可以混用,注意点:
位置形参必须放在默认形参前面
def func(x, y=111):
print(x, y)
def func(y=111, x): # 报错
print(x, y)
m = 222
def func(x, y=m):
print(x, y)
m = 666
func(111) # 得到111 222
def register(name,hobby,hobbies=[]):
hobbies.append(hobby)
print('%s 的爱好是 %s' %(name, hobbies))
def register(name, hobby, hobbies=None):
if hobbies is None:
hobbies=[]
hobbies.append(hobby)
print('%s 的爱好是 %s' %(name, hobbies))
register("egon", "smoke")
register("lxx", "dance")
register("hxx", "drink")
可变长函数是指在调用函数时,传入参数个数不固定,而实参是为形参赋值的
因此必须有对应格式的形参来接受溢出的实参
def func(x, y, *z):
print(x, y, z)
func(1, 2, 3, 4, 5) # 1 2 (3, 4, 5)
func(1, 2) # 1 2 ()
func(1) # 报错
def my_sum(*args):
res = 0
for i in args:
res += i
print(res)
my_sum(1) # 1
my_sum(1, 2) # 3
my_sum(1, 2, 3) # 6
def func(x, y, **kwargs):
print(x, y, kwargs)
func(1, y=2, a=1, b=2, c=3) # 1 2 {'a': 1, 'b': 2, 'c': 3}
def func(a, b, c, d):
print(a, b, c, d)
func(*"hello") # 报错,不对应
func(*"hell") # h e l l
func(*[11, 22, 33, 44]) # 11 22 33 44
func(11, 22, *[33, 44]) # 11 22 33 44
func(11, 22, *{"k1": 111, "k2": 222}) # 11 22 k1 k2
在实参中带**😗*会将紧跟其后的实参打散成关键字实参
注意**后面跟的必须是一个字典
def func(a, b, c, d):
print(a, b, c, d)
func(**{"k1": 333, "k2": 444}) # 报错
func(**{"d": 333, "b": 444, "a": 111, "c": 222}) # 111 444 222 333
func(**[("d", 333), ("b", 444), ("a", 111), ("c", 222)]) # 报错
在形参中,*必须在**前
在实参中,*必须在**前
def index(x, y, z):
print('index------>', x, y, z)
def wrapper(*arges, **kwargs):
index(*arges, **kwargs)
wrapper(1, 2, 3) # index------> 1 2 3
wrapper(z=3, y=2, x=1) # index------> 1 2 3
def wrapper(*arges,**kwargs):
print(arges)
print(kwargs)
wrapper(1, 2, a=1,b=2,c=3) # (1, 2) {'a': 1, 'b': 2, 'c': 3}
在*与**之间定义的形参称为关键字形参
特点:必须按照key=value的形式传值
def func(x, y=1, *args, a=666, b, **kwargs):
print(x)
print(y)
print(args)
print(a)
print(b)
print(kwargs)
func(1, 2, 3, 4, 5, 6, 7, a=111, b=222, c=333) # 1 2 (3, 4, 5, 6, 7) 111 222 {'c': 333}
func(1, 2, 3, 4, 5, 6, 7, b=222, c=333) # 1 2 (3, 4, 5, 6, 7) 666 222 {'c': 333}
func(1, 2, 3, 4, 5, 6, 7, b=222, 333) # 报错
def func():
print('from func')
def func():
print('from func')
f = func
f() # from func
def func():
print('from func')
def bar(x):
print(x)
mmm = 11111
bar(mmm) # 11111
bar(func) #
def add(x): # x=函数func的内存地址
return x # return 函数func的内存地址
res = add(func) # res=add(func的内存地址)
print(res) #
x = 10
l = [x, func]
print(l) # [10,
l[-1]() # from func
# 新的功能只需要在字典中加入即可,无需动循环
def login():
print('login')
def register():
print('register')
def transfer():
print('transfer')
def withdraw():
print('withdraw')
func_dic = {
"1": [login, "登录"],
"2": [register, "注册"],
"3": [transfer, "转账"],
"4": [withdraw, "提现"]
}
while True:
print("0 退出")
for k in func_dic:
print(k, func_dic[k][-1])
choice = input("请输入操作编号:").strip()
if choice == "0":
break
if choice in func_dic:
func_dic[choice][0]()
else:
print("输入的操作不存在")
def f1():
print('from f1')
def f2():
print('from f2')
print(f2)
f2()
x=1111
f1()
from math import pi
def circle(radius, mode=0):
def perimiter(radius):
return 2 * pi *radius
def area(radius):
return pi * (radius ** 2)
if mode == 0:
return perimiter(radius)
elif mode == 1:
return area(radius)
res1 = circle(10, mode=0)
print(res1) # 62.83185307179586
res2 = circle(10, mode=1)
print(res2) # 314.1592653589793
def max2(x, y):
if x > y:
return x
else:
return y
def max4(a, b, c, d):
res1 = max2(a, b)
res2 = max2(res1, c)
res3 = max2(res2, d)
return res3
res = max4(1, 2, 3, 4)
print(res) # 4
名称空间namespace
名称空间就是存放名字的地方
三类名称空间(内置名称空间、全局名称空间、局部名称空间)
Ⅰ 内置名称空间:存放内置的名字
随着解释器启动就产生,解释器关闭就销毁
print
input
len
Ⅱ 全局名称空间:存放的是顶级的名字
运行顶级代码前产生,文件运行完毕则销毁
Ⅲ 局部名称空间:在函数内定义的名字
调用函数则产生一个函数的局部名称空间,该函数调用结束则立即销毁
名称空间示例
x = 10 # 全局名称空间
def f1(): # f1本身是全局名称空间
y = 2 # 局部名称空间
if 1 > 0:
z = 3 # 全局名称空间
if 3 > 1:
m = 333 # 全局名称空间
局部名称空间-->全局名称空间-->内置名称空间
Tips:在全局无法查看局部的,在局部可以看全局的
优先级示例
x = 111
def f1():
print(x)
x = 222
f1() # 报错
x = 111
def f1():
x = 222
print(x)
f1() # 222
名称空间的嵌套关系是在函数定义阶段,即检测语法时确定的
与调用函数的位置无关,与函数定义位置有关
global 局部对全局变量修改
x = 111
def f1():
global x
x = 222
f1()
print(x) # 222
x = 111
def f1():
x = 222
def f2():
nonlocal x
x = 333
f2()
print(x)
f1() # 333
作用域即范围
全局范围(内置、全局名称空间属该范围):全局存活,全局有效
局部范围(局部名称空间属该范围):临时存活,局部有效
作用域关系是在函数定义阶段固定的,与函数调用位置无关
查看作用域
LEGB代表名字查找顺序:locals -> enclosing function -> globals -> _builtings _
locals 是函数内的名字空间,包括局部变量和形参
enclosing 外部嵌套函数的名字空间(闭包中常见)
globals 全局变量,函数定义所在模块的名字空间
builtings 内置模块的名字空间
闭函数
该函数就是定义在一个函数内部的函数
def outter():
def wrapper():
pass
包函数
闭函数引用了一个来源于外层函数的变量
def outter():
x = 111
def wrapper():
print(x)
wrapper()
x = 222 # 不妨碍
outter() # 111
意义:
返回的函数对象外部还包了一层作用域
该函数无论在何处调用都优先使用自己外层包裹的作用域
应用:
延迟计算
from urllib.request import urlopen
def index(url):
def get():
return urlopen(url).read()
return get
baidu=index('http://www.baidu.com')
print(baidu().decode('utf-8'))
什么是装饰器
器---->工具
装饰-->添加新功能
装饰器就是定义个函数,用该函数去为其他函数添加新功能
为什么用装饰器
开放封闭原则:针对上线的功能对拓展是开放的,但是对修改源代码以及调用方式是封闭的
需求:为index加上新功能-->统计其运算时间
import time
def index():
time.sleep(1)
print('from index')
index()
# 1、首先考虑直接在运行的代码体上下方加入时间模块
import time
def index():
start = time.time()
time.sleep(1)
print('from index')
stop = time.time()
print('run time is %s' % (stop - start))
index()
# 2、不修改源代码
import time
def index():
time.sleep(1)
print('from index')
start = time.time()
index()
stop = time.time()
print('run time is %s' % (stop - start))
# 3、把调用放进函数
import time
def index():
time.sleep(1)
print('from index')
def wrapper():
start = time.time()
index()
stop = time.time()
print('run time is %s' % (stop - start))
wrapper()
# 3.1改进一
import time
def index():
time.sleep(1)
print('from index')
def wrapper(f):
start = time.time()
f()
stop = time.time()
print('run time is %s' % (stop -start))
wrapper(index)
# 3.2改进二
import time
def index():
time.sleep(1)
print('from index')
def outter(f):
def wrapper():
start = time.time()
f()
stop = time.time()
print('run time is %s' % (stop - start))
return wrapper
index = outter(index)
index()
# 添加新功能home
import time
def index():
time.sleep(1)
print('from index')
def home(name):
time.sleep(1)
print('homepage welcome %s' % name)
def outter(f):
def wrapper(*args, **kwargs):
start = time.time()
f(*args, **kwargs)
stop = time.time()
print('run time is %s' % (stop - start))
return wrapper
index = outter(index)
index()
home = outter(home)
home('ccc')
# 最终版
import time
def index():
time.sleep(1)
print('from index')
def home(name):
time.sleep(1)
print('homepage welcome %s' % name)
return 123
def outter(f):
def wrapper(*args, **kwargs):
start = time.time()
res = f(*args, **kwargs)
stop = time.time()
print('run time is %s' % (stop - start))
return res
return wrapper
index = outter(index)
home = outter(home)
res = index()
print(res) # None
res = home('ccc')
print(res) # 123
在被装饰对象的正上方单独一行添加@timer,当解释器解释到@timer时就会调用timer函数,且把它正下方的函数名当做实参传入,然后将返回的结果重新赋值给原函数名
原函数
import time
def index():
time.sleep(1)
print('from index')
def home(name):
time.sleep(1)
print('homepage welcome %s' % name)
return 123
def outter(f):
def wrapper(*args, **kwargs):
start = time.time()
res = f(*args, **kwargs)
stop = time.time()
print('run time is %s' % (stop - start))
return res
return wrapper
index = outter(index)
home = outter(home)
res = index()
print(res) # None
res = home('ccc')
print(res) # 123
import time
def timmer(f):
def wrapper(*args, **kwargs):
start = time.time()
res = f(*args, **kwargs)
stop = time.time()
print('run time is %s' % (stop - start))
return res
return wrapper
@timmer # index = timmer(index)
def index():
time.sleep(1)
print('from index')
@timmer # home = time(home)
def home(name):
time.sleep(2)
print('welcome to %s' % name)
return 123
index()
res = home("ccc")
print(res)
def auth(driver):
def func(x):
…
return func
@auth(driver='file')
def index():
pass
@auth(driver='mysql')
def home():
pass
import time
def login(x, engine='file'):
def auth(func):
def wrapper(*args, **kwargs):
print("========>", x)
inp_user = input("username>>>>:").strip()
inp_pwd = input("password>>>:").strip()
if engine == "file":
print("基于file认证")
if inp\_user == "egon" and inp\_pwd == "123":
print('login successful')
res = func(\*args, \*\*kwargs)
return res
else:
print('username or password error')
elif engine == 'mysql':
print("基于mysql认证")
elif engine == "ldap":
print("基于ldap认证")
else:
print("未知认证来源")
return wrapper
return auth
@login(11, engine='file') # @auth # index = auth(index) # index=wrapper
def index():
time.sleep(1)
print('from index')
@login(22, engine='file') # @auth # home=auth(home) # home=wrapper
def home(name):
time.sleep(2)
print('home page,welcome %s' % name)
return 123
index()
home('egon')
加载顺序(outter函数的调用顺序):自下而上
执行顺序(wrapper函数的执行顺序):自上而下
def foo():
pass
相当于
foo=deco1(deco2(deco3(foo)))
def outter1(func1): # func1 = wrapper2的内存地址
print('============>outter1')
def wrapper1(*args, **kwargs):
print('=============wrapper1')
res1 = func1(*args, **kwargs)
return res1
return wrapper1
def outter2(func2): # func2 = wrapper3的内存地址
print('============>outter2')
def wrapper2(*args, **kwargs):
print('=============wrapper2')
res2 = func2(*args, **kwargs)
return res2
return wrapper2
def outter3(func3): # func3 = index的内存地址
print('============>outter3')
def wrapper3(*args, **kwargs):
print('=============wrapper3')
res3 = func3(*args, **kwargs)
return res3
return wrapper3
# index = wrapper1的内存地址
@outter1 # outter1(wrapper2的内存地址)-->wrapper1的内存地址
@outter2 # outter2(wrapper3的内存地址)-->wrapper2的内存地址
@outter3 # outter3(index的内存地址)-->wrapper3的内存地址
def index():
print('from index')
print('*'*25)
index()
import time
def timmer(func):
def wrapper1(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
stop = time.time()
print('run time is:%s' % (stop - start))
return res
return wrapper1
def login(x, engine='file'):
def auth(func):
def wrapper2(*args, **kwargs):
print("========>", x)
inp_user = input("username>>>>:").strip()
inp_pwd = input("password>>>:").strip()
if engine == "file":
print("基于file认证")
if inp\_user == "egon" and inp\_pwd == "123":
print('login successful')
res = func(\*args, \*\*kwargs)
return res
else:
print('username or password error')
elif engine == 'mysql':
print("基于mysql认证")
elif engine == "ldap":
print("基于ldap认证")
else:
print("未知认证来源")
return wrapper2
return auth
@timmer
@login(11, engine='file')
def index():
time.sleep(1)
print('from index')
index()
@login(11, engine='file')
@timmer
def index():
time.sleep(1)
print('from index')
index()
import time
from functools import wraps
def timmer(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
stop = time.time()
print('run time is:%s' % (stop - start))
return res
return wrapper
@ timmer
def index():
"""index函数"""
time.sleep(1)
print('from index')
help(index)
def func(x, y): # func=函数的内存地址
return x+y
匿名函数:没有名字的函数
应用场景:临时用一次,通常用于与其他函数配合使用
# 无用调用方式
f = lambda x, y: x+y
print(f)
res = f(1, 2)
print(res)
res = (lambda x, y: x+y)(1, 2)
print(res)
salaries = {
"egon": 1000,
"alex": 2000,
"jack": 3000,
"rose": 4000
}
def get_salary(name):
return salaries[name]
print(max(salaries, key = get_salary)) # rose
print(max(salaries, key=lambda name: salaries[name])) # rose
print(min(salaries, key=lambda name: salaries[name])) # egon
print(sorted(salaries)) # ['alex', 'egon', 'jack', 'rose']
print(sorted(salaries, key=lambda name: salaries[name])) # ['egon', 'alex', 'jack', 'rose']
print(sorted(salaries, key=lambda name: salaries[name], reverse=True)) # ['rose', 'jack', 'alex', 'egon']
# abs 返回绝对值
print(abs(-11)) # 11
print(abs(0)) # 0
print(abs(11)) # 11
print(all('')) # True
print(all([])) # True
print(all([11, 22, 333, 0])) # False
print(any('')) # False
print(any([])) # False
print(any([0, None, '', 1])) # True
print(any([0, None, ''])) # False
print(chr(65)) # 数字->字母A
print(ord('A')) # 字母->数字65
print(chr(90)) # Z
print(bin(11)) # 十进制->二进制 0b1011
print(oct(11)) # 十进制->八进制 0o13
print(hex(11)) # 十进制->十六进制 0xb
int
float
str
list
tuple
dict
set
bool
bytes
print(callable(len)) # True
classmethod
staticmethod
setattr
getattr
delattr
hasattr
dir
exec
l = eval("[1, 2, 3]")
print(l[0]) # 1
with open('user1.txt', mode='wt', encoding='utf-8') as f:
dic = {"ccc": "123", "zzz": "456", "yyy": "789"}
f.write(str(dic))
with open('user1.txt', mode='rt', encoding='utf-8') as f:
data = f.read()
print(data, type(data)) # {'ccc': '123', 'zzz': '456', 'yyy': '789'}
dic = eval(data)
print(dic["ccc"]) # 123
# 1、map 映射
names = ["egon", "lxx", "hxx"]
res = (name if name == "egon" else name+"_sb" for name in names)
print(list(res)) # ['egon', 'lxx_sb', 'hxx_sb']
用map实现
names = ["egon", "lxx", "hxx"]
res = map(lambda name:name if name == "egon" else name+"_sb", names)
print(res) #
names = ['egon', 'lxx_sb', 'hxx_sb']
res = (name for name in names if name.endswith("sb"))
print(list(res)) # ['lxx_sb', 'hxx_sb']
用filter实现
names = ['egon', 'lxx_sb', 'hxx_sb']
res = filter(lambda name:name.endswith("sb"), names)
print(list(res)) # ['lxx_sb', 'hxx_sb']
from functools import reduce
res = reduce(lambda x,y:x+y, "hello", "xxx")
print(res) # xxxhello
from functools import reduce
res = reduce(lambda x,y:x+y, [1, 2, 3], 100)
print(res) # 106
s = frozenset({1, 2, 3}) # 不可变
s1 = set({1, 2, 3}) # 可变
s1.add(4)
print(s1) # {1, 2, 3, 4}
x = 3333
def func():
x = 1
y = 2
print(locals())
print(globals())
func() # {'x': 1, 'y': 2}
# {'__name__': '__main__', …}
a = 1111
print(locals()) # {'__name__': '__main__', …}
print(globals()) # {'__name__': '__main__', …}
print(locals() is globals()) # True
print(hash("asaasdf")) # -9196404338305892359
res = pow(10, 3, 3) # 10 ** 3 % 3
print(res) # 1
res = reversed([11, 333, 222, 77])
print(list(res)) # [77, 222, 333, 11]没有排序,直接反序
print(round(3.5)) # 4
l = [11, 22, 33, 44, 55, 66, 77, 88, 99]
res = l[0: 7: 2]
print(res) # [11, 33, 55, 77]
用slice实现
l = [11, 22, 33, 44, 55, 66, 77, 88, 99]
s = slice(0, 7, 2)
res = l[s]
print(res) # [11, 33, 55, 77]
s1 = "hello"
l = [11, 22, 33, 44, 55, 66]
res1 = zip(s1, l)
print(list(res1)) # [('h', 11), ('e', 22), ('l', 33), ('l', 44), ('o', 55)]
res2 = zip(l, s1)
print(list(res2)) # [(11, 'h'), (22, 'e'), (33, 'l'), (44, 'l'), (55, 'o')]
zip多的元素会直接丢掉
迭代器指的是迭代取值的工具
迭代是一个重复的过程(不是单纯重复),每次重复都是基于上一次的结果进行的
count = 1
while count < 5:
print(count)
count += 1
使用迭代器的目的
Ⅰ 为了找到一种通用的迭代取值的方案
Ⅱ 节省内存
可迭代对象
内置有__iter__方法的类型都称之为可迭代对象
但凡调用了__iter__方法,就会将该类型转换成迭代对象
res = 值.__iter__() 或 res = iter(值)
迭代器对象
Ⅰ 内置有__next__方法
Ⅱ 内置有__iter__方法(为了方便for循环)
迭代器对象一定是可迭代对象
可迭代对象不一定是迭代器对象
优点:
Ⅰ 提供了一种不依赖索引的迭代取值方案
Ⅱ 惰性计算,节省内存
缺点:
Ⅰ 取值麻烦
Ⅱ 无法预测值的长度
Ⅲ 是一次性的
"hello".__iter__() # 字符串
[].__iter__() # 列表
(11,).__iter__() # 元组
{"k1": 12, }.__iter__() # 字典
{11, 22}.__iter__() # 集合
f = open("a.txt", mode="wt") # 文件
f.__iter__()
l = [11, 22, 33]
iter_l = l.__iter__()
print(iter_l.__next__()) # 11
print(iter_l.__next__()) # 22
print(iter_l.__next__()) # 33
info = {'name': "ccc", "age": 18, "gender": 'male'}
iter_info = info.__iter__()
print(iter_info.__next__()) # name
print(iter_info.__next__()) # age
print(iter_info.__next__()) # gender
print(iter_info.__next__()) # 抛出异常StopIteration
迭代器的iter与本身
print(iter_info.__iter__().__iter__().__iter__() is iter_info) # True
l = [11, 222, 333, 444, 555]
iter_l = iter(l) # l.__iter__
while True:
try:
print(next(iter_l))
except StopIteration:
break
l = {'name': "ccc", "age": 18, "gender": 'male'}
iter_l = iter(l)
while True:
try:
print(next(iter_l))
except StopIteration:
break
print('--------------------')
while True:
try:
print(next(iter_l))
except StopIteration:
break
l = {'name': "ccc", "age": 18, "gender": 'male'}
iter_l = iter(l)
while True:
try:
print(next(iter_l))
except StopIteration:
break
print('--------------------')
iter_l = iter(l)
while True:
try:
print(next(iter_l))
except StopIteration:
break
l = [11, 222, 333, 444, 555]
iter_l = iter(l)
for item in iter_l:
print(item)
print('====================')
for item in iter_l:
print(item)
l = [11, 222, 333, 444, 555]
iter_l = iter(l)
for item in iter_l:
print(item)
print('====================')
iter_l = iter(l)
for item in iter_l:
print(item)
for循环原理:
1、调用可迭代对象.__iter__(),拿到一个迭代器对象
2、调用next(迭代对象),将返回值赋值变量item
3、循环往复,直到抛出异常Stopiteration,for会检测异常然后结束循环
f = open('a.txt', mode='rt', encoding='utf-8')
for line in f:
print(line)
print('=======')
for line in f:
print(line)
f.close()
生成器:生成器就是一种自定义迭代器(生成器内置iter和next方法)
使用生成器是为了省内存
使用生成器的方式:
函数体内但凡出现yield关键字,调用函数不会触发函数体代码的运行,而是会返回一个生成器对象
yield与return
相同点:在返回值角度的用法一致
不同点:Ⅰ yield可以返回多次值,return只能返回一次
Ⅱ yield可以暂停函数,然后可以用next方法触发函数体代码的运行->协程(或用list)
def func():
print("111")
yield 1
print("222")
yield 2
print("333")
yield 3
print("444")
g = func() # 生成器本质就是一个迭代器
print(g) #
res = next(g) # 111
print(res) # 1
res = next(g) # 222
print(res) # 2
res = next(g) # 333
print(res) # 3
next(g) # 444 检测异常StopIteration
g = func()
print(g)
for i in g:
print(i)
def my_range(start, stop, step=1):
while start < stop:
yield start
start += step
for i in my_range(0, 5, 2):
print(i)
res = "条件成立时返回的值" if "条件" else "条件不成立时返回的值"
def max2(x, y):
if x > y:
return x
else:
return y
res = max2(1, 2)
# 可用三元表达式一行解决
x = 1
y = 2
res = x if x > y else y
[表达式 for i in 可迭代对象 if 条件]
{k:v for i in 可迭代对象 if 条件}
{k for i in 可迭代对象 if 条件}
l = []
for i in range(8):
l.append(i)
print(l) # [0, 1, 2, 3, 4, 5, 6, 7]
l = [i for i in range(10)]
print(l) # [0, 1, 2, 3, 4, 5, 6, 7]
names = ["egon", "lxx_sb", "hxx_sb"]
name = []
for item in names:
if item.endswith('sb'):
name.append(item)
print(name) # ['lxx_sb', 'hxx_sb']
names = ["egon", "lxx_sb", "hxx_sb"]
name = [name for name in names if name.endswith('sb')]
print(name) # ['lxx_sb', 'hxx_sb']
res = {i: i for i in range(5) if i > 2}
print(res) # {3: 3, 4: 4}
res = {i for i in range(5) if i > 2}
print(res, type(res)) # {3, 4}
调用带yield的函数
生成器表达式,将列表生成式的[]换成()即可
(expression for item in iterable if condition)
列表生成式返回的是一个列表,生成器表达式返回的是一个生成器对象
生成器表达式更加节省内存(一次只产生一个值在内存中)
如果要读取一个大文件的字节数应该是基于生成器表达式的方式完成的
res = (i for i in range(5))
print(res) #
print(next(res)) # 0
print(next(res)) # 1
print(next(res)) # 2
print(next(res)) # 3
print(next(res)) # 4
print(next(res)) # 抛出异常StopIteration
with open(r'a.txt', mode='rt', encoding='utf-8') as f:
res = 0
for line in f:
res += len(line)
print(res) # 15
with open(r'a.txt', mode='rt',encoding='uyf-8') as f:
res = sum(len(line) for line in f)
print(res) # 15 依次执行next(res),然后累加到一起得到结果
核心是 过程
二字
过程指的是解决问题的步骤,即先干什么后干什么再干什么
基于面向过程开发程序好比是在设计一条条流水线,是一种机械式的思维方式,正好契合计算机的运行原理
计算机运行原理:任何程序的执行最终都要转换成cpu的指令流水按过程调度执行
即无论采用什么语言、何种编程范式设计出的程序,最终的执行都是过程式的
优点:将复杂的问题流程化,进而简单化
缺点:程序的可扩展性差
面向过程的程序设计一般用于那些功能一旦实现之后就很少需要改变的场景,
如果你只是写一些简单的脚本,去做一些一次性任务,用面向过程去实现是极好的,
但如果你要处理的任务是复杂的,且需要不断迭代和维护,那还是用面向对象最为方便。
函数递归调用:在调用一个函数的过程中又调用了自己
本质:循环的过程-->用函数来实现的循环
递归调用必须在满足某种条件下结束,不能无限递归调用下去
python不是函数式编程语言,无法对递归进行尾递归优化
递归的两个阶段:
Ⅰ 回溯-->一层层往下爬
Ⅱ 递推-->一层层往上爬
def f1():
print("from f1")
f1()
f1() # 先递归执行,超过最大限制后报错RecursionError
# 可用getrecursionlimit修改限制
import sys
print(sys.getrecursionlimit()) # 默认限制是1000
sys.setrecursionlimit(2000) # 可修改,但一般不修改(受主机操作系统栈大小限制)
print(sys.getrecursionlimit(2000)) # 此时修改为2000
# 问题
某公司四个员工坐在一起,问第四个人薪水,他说比第三个人多1000,问第三个人薪水,第他说比第二个人多1000,问第二个人薪水,他说比第一个人多1000,最后第一人说自己每月5000,请问第四个人的薪水是多少?
要知道第四个人的月薪,就必须知道第三个人的,第三个人的又取决于第二个人的,第二个人的又取决于第一个人的,而且每一个员工都比前一个多一千,数学表达式即
salary(4)=salary(3)+1000
salary(3)=salary(2)+1000
salary(2)=salary(1)+1000
salary(1)=5000
总结为:
salary(n)=salary(n-1)+1000 (n>1)
salary(1)=5000 (n=1)
要求第n个员工的薪水,需要回溯得到(n-1)个员工的薪水,以此类推,直到得到第一个员工的薪水,此时,salary(1)已知,因而不必再向前回溯了。然后进入递推阶段:从第一个员工的薪水可以推算出第二个员工的薪水(6000),从第二个员工的薪水可以推算出第三个员工的薪水(7000),以此类推,一直推算出第第四个员工的薪水(8000)为止,递归结束。需要注意的一点是,递归一定要有一个结束条件,这里n=1就是结束条件。
def salary(n):
if n == 1:
return 5000
return salary(n-1)+1000
s=salary(4)
print(s) # 8000
在未满足n==1的条件时,一直进行递归调用,即一直回溯。而在满足n==1的条件时,终止递归调用,即结束回溯,从而进入递推阶段,依次推导直到得到最终的结果。
items=[[1, 2], 3, [4, [5, [6, 7]]]]
def foo(items):
for i in items:
if isinstance(i, list): #满足未遍历完items以及if判断成立的条件时,一直进行递归调用
foo(i)
else:
print(i, end=' ')
foo(items) #打印结果1 2 3 4 5 6 7
使用递归,我们只需要分析出要重复执行的代码逻辑,然后提取进入下一次递归调用的条件或者说递归结束的条件即可,代码实现起来简洁清晰
手机扫一扫
移动阅读更方便
你可能感兴趣的文章