python参数的位置传递优点_Python函数基础知识

目录

函数的基础

形参:

实参:

动态传参:

不容易理解的地方:

return   返回值

命名空间

函数名:

闭包

如何分辨闭包:

闭包的作用:

迭代器:

递归:

装饰器:

作用:

使用情景:

扩展(带参装饰器)

生成器的三种创建办法:

定义:

优点:

使用方式:

推导式

列表推导式 [结果 for 变量 in 可迭代对象 if 筛选]

字典推导式 {键 : 值 for 变量 in 可迭代对象 if 筛选}   结果是

集合推导式 {结果 for 变量 in 可迭代对象 if 筛选}

函数的基础

# 申明方法

def 方法名(形参):

代码块

# 调用方法

方法名(实参)

def demo(name,age):

print(f'(我是{name},我今年{age}岁))

#调用方法

demo('admin',12)

形参:

位置形参:def demo(name,age)

默认值形参:def demo(name,age=12)

二者可以混合使用,但是 位置形参 必须在默认值形参之前

实参:

位置实参:demo('admin',12)

关键字实参: demo('admin',age=12)

二者可以混合使用,但是 位置实参 必须在关键字实参之前

动态传参:

*参数   是位置参数

**参数  是关键字参数 方法接受到的是字典

位置参数>动态位置参数>关键字参数>动态关键字参数

在形参上:*聚合   **聚合

在实参上:*打散   **打散

格式:

*args  接受所有位置参数

lis = [1,2,3,4]

def function(*args): # 聚合 将打散的 内容 再次组成元组形式 (1,2,3,4)

print(args)

print(*args)

function(lis) #

function(*lis) #打散 *lis实际上就是 1,2,3,4

#结果:

([1, 2, 3, 4],)

[1, 2, 3, 4]

(1, 2, 3, 4)

1 2 3 4

**wargs 接受所有关键字参数*******************************************

dir = {'a':1,'b':2,"c":3,"d":4}

def function(**kargs): #这里将其聚合成 {'a':1,'b':2,"c":3,"d":4}

# print(**kargs) #报错 TypeError: 'a' is an invalid keyword argument for this function

# print(*kargs) # a b c d

print(kargs) #{'a': 1, 'b': 2, 'c': 3, 'd': 4}

function(**dir) # 其实这里的是 a=1 b=2 c=3 d=4

# function(*dir) #报错 TypeError: function() takes 0 positional arguments but 4 were given

# function(dir) #报错 TypeError: function() takes 0 positional arguments but 1 was given

#注意 :

dir = {'a':1,'b':2,"c":3,"d":4}

def function(**kwargs):

print(**kwargs) #报错 TypeError: 'a' is an invalid keyword argument for this function

function(**dir)

为什么打印 **kwargs 会报错的原因是:

字典前加 ** 会将字典打散为 a=1,b=2,c=3,d=4。

传入 function(**kwargs)方法后会被 **kwargs 全部接受 聚合成 {'a': 1, 'b': 2, 'c': 3, 'd': 4}

而 print(**字典) 则会将 字典再次打散为关键字参数,

但是print 的方法的参数中是没有 **kwargs(接受所有的关键字参数的) , 因此会报错

但是 print()方法中是有 *args 参数的,也就是为什么print(*args) 并不会报错

不容易理解的地方:

def func(**kwargs):

print(kwargs)

dic = {"1":1}

func(**dic)

#结果: {'1': 1}

#减少写参数量

# dic = {"1":1}

# func(**dic) 等同于 func("1"=1) 虽然后者报错,但是在实际空间中是以这种方式存储

return   返回值

def demo(name,age):

print(f'(我是{name},我今年{age}岁))

return

print("这句话不会执行")

#调用方法

demo('admin',12)

注意:在一个方法体内,return之后的代码都不会执行到

命名空间

内置命名空间(优先级最高)

存放Python解释器为我们提供的名字,其中就包括内置函数,list,dict,tuple,set,str,int等都属于内置空间的。

全局命名空间

局部命名空间:函数内部

取值顺序:就进原则

globals()函数来查看全局作用域中的内容

locals()来查看当前作用域的内容

global 变量名  : 表示使用全局变量

在局部变量中使用,当全局变量中没有该参数时,则会将局部变量升级为 全局变量   (不推荐)

nonlocal  变量名 : 找局部作用域中,离他最近的那层的变量给引用过来,。如果除全局外的局部都不存在改变量则会报错(No find)

函数名:

def func():

pass

函数名可以当作值去赋值给变量

a = func

a() #调用的是func()

函数名可以当作参数传递给函数

def func2(msg):

print(msg)

func2(func) #执行后的结果 打印的是 func方法的内存地址

函数名可以当作函数返回值,注意:返回值不能加括号

def func():

def func_copy():

pass

return func_copy

print(func()) #打印的是 func_copy的内存地址

print(func()()) #打印的是 func_copy的方法内容

函数名可以当作元素存放一个容器里

def func():pass

def func2():pass

def func3():pass

li = [func,func2,func3] #列表中存的其实是 每个方法的内存地址

for i in li:

i() #打印每一个方法

查看函数的内存地址 print(函数名)

print(func)

闭包

如何分辨闭包:

闭包必须是嵌套函数,内部函数在使用外部变量(非全局变量)就是闭包。

可以使用方法名.__closure__   查看该函数是否为闭包   只要返回值不是None,他就是闭包

def func():

n = 1

def func2():

print(n)

return func2 #注意这里的返回值 只是func2的方法名,也就是将其的地址返回。

func()()

闭包的作用:

1.可以读取到其他函数内部的变量

2.可以将变量保存在内存中,使其生命周期增强

3.可以保护其内部变量不受外界影响,不被修改,做到私有化

迭代器:

lst = [1,2,3,4,5]

l = lst.__iter__() # 从一个可迭代对象转换成迭代器

print(l.__next__()) #从迭代器中读取第一个

可迭代对象:具有 __iter__()方法

print(isinstance('列表等',Iterable))        判断是否为可迭代对象

迭代器:拥有 __iter__()方法和__next__() 方法

print(isinstance('列表等',Iterator))        判断是否为迭代器

# for循环机制

li = [1,2,3,4,5,6]

for i in li:

print(i)

# 等价于

li2 = li.__iter__()

while True: # 循环:

try:

print(li2.__next__()) # 获得下一个值:

except StopIteration:

break # 遇到StopIteration就退出循环

递归:

其实就是方法自己本身再调用自己

# 一个简单的递归

def fun(n):

print(n)

n += 1

fun(n)

fun(1)

#结果会报

# RecursionError: maximum recursion depth exceeded while calling a Python object

递归注意事项:有进也有出

递归的最大深度:官方定义是 1000,而实际上测试 只是 998

# 递归求阶乘

def factorial(n):

if n == 1 :

return 1

else:

return n*factorial(n-1)

递归的深度可以修改:

import sys

sys.setrecursionlimit(int num) #调用sys系统模块

装饰器:

装饰器的本质其实就是 闭包

举一个简单的装饰器

import time

def fun(a, b):

print('我是fun',a,b)

def test(fun):

def time_fun(*args,**kwargs):

star = time.time() #时间戳

time.sleep(2) #睡眠两秒钟

fun(*args,**kwargs)

end = time.time() #时间戳

print(end-star)

return time_fun #闭包功能

fun = test(fun) #将 time_fun函数的内存地址赋值给fun

fun(1,2) #虽然看见的是fun函数,但是实际走的却是time_fun函数

# 结果:

# 我是fun 1 2

# 2.000408411026001

可以使用@符 升级为:

@ 后跟 装饰器的名称          整体等同于   被装饰函数名称 = 装饰器名称(被装饰函数名称)

import time

def test(fun):

def time_fun(*args,**kwargs):

star = time.time() #时间戳

time.sleep(2) #睡眠两秒钟

fun(*args,**kwargs)

end = time.time() #时间戳

print(end-star)

return time_fun #闭包功能

@test #fun = test(fun)

def fun(a, b):

print('我是fun',a,b)

fun(1,2) #虽然看见的是fun函数,但是实际走的却是time_fun函数

#结果相同

作用:

在开发阶段要满足 开放封闭 原则   (开放是指:扩展功能开放。  封闭是指:源码封闭,不允许其他人修改)

装饰器可以实现不改变调用函数名的情况下,实现对本来函数的功能实现扩展

使用情景:

测试函数的运行时间

登陆校验

扩展(带参装饰器)

import time

def all(name):

def test(fun):

def time_fun(*args, **kwargs):

star = time.time() #时间戳

time.sleep(2) #睡眠两秒钟

print(name)

fun(*args, **kwargs)

end = time.time() #时间戳

print(end-star)

return time_fun #闭包功能

return test

@all('a') #fun = all('a')(fun) fun(1,2)

def fun(a, b):

print('我是fun', a, b)

fun(1,2) #虽然看见的是fun函数,但是实际走的却是time_fun函数

1.生成器的三种创建办法:

1.通过生成器函数  关键字 yield

def func():

print(1)

yield 1

print(2)

yield 2

l = func()

print(l.__next__())

print(l.__next__())

# print(l.__next__()) #报错,StopIteration

2.通过生成器表达式创建生成器

生成器表达式:

(结果 for  变量 in 可迭代对象 if 筛选)  #重点是小括号

get1 = ( i for i in range(10) if i%2 == 0)

print(get1)

#结果:at 0x0000017DB9320938>

3.通过数据转换

2.生成器函数定义:

函数中包含了yield的就是生成器函数

注意:生成器函数被执行,获取到的是生成器,而不是函数的执行

yield from

def func():

li = [1,2,3,4]

yield from li

f = func()

for i in f:

print(i, end=",")

#结果:1,2,3,4

3.生成器的优点:

li = []

def func():

for i in range(1000):

li.append(i)

print(li)

#比较浪费空间,一次性取完

def func():

for i in range(1000):

yield i

f = func()

for i in range(10):

print(f.__next__())

#需要多少取多少

4.使用方式:

1. __next__()

get1 = ( i for i in range(10) if i%2 == 0) #生成器就是一个自己写的迭代器

#方式一:

for i in get1:

print(i,end=" ")

#方式二:

for i in range(5):

print(get1.__next__(),end=" ")

#结果:0 2 4 6 8

2.send(值)   给上一个yield位置传一个值  #send其实有next方法和传值方法

def func():

for i in range(10):

print(i)

l = yield "你好"

print(l)

f = func()

print(f.__next__()) #第一次执行,会执行完yield,暂留在那里

print(f.send("我不好")) #使用send会将参数赋值给上一次暂留位置,也就是程序中的l ,然后继续执行,知道下一个yield暂停

#结果:

# 0

# 你好

# 我不好

# 1

# 你好

注意点:send在使用时,如果没有先使用 __next__方法,则send()方法中的参数必为None

yield和return的区别:

yield和return的效果是一样的,但是还是有点区别

yield是分段来执行一个函数    yield 后面跟的相当于一个输出语句

return是直接停止这个函数

send和__next__()一样都可以让生成器执行到下一个yield

send和__next__()区别:

send 和 next()都是让生成器向下走一次

send可以给上一个yield的位置传递值,不能给最后一个yield发送值,在第一次执行生成器的时候不能使用send()

第一次调用的时候使用send()也可以但是send的参数必须是None

5.推导式

1.列表推导式 [结果 for 变量 in 可迭代对象 if 筛选]

li = [i for i in range(10) if i%2 == 0]

print(li)

#结果:[0, 2, 4, 6, 8]

2.字典推导式 {键 : 值 for 变量 in 可迭代对象 if 筛选}   结果是

li_1 = [1,2,3,4]

li_2 = [1,2,3,4]

dic = {li_1[i]:li_2[i]for i in range(len(li_1))}

print(dic)

#结果:{1: 1, 2: 2, 3: 3, 4: 4}

3.集合推导式 {结果 for 变量 in 可迭代对象 if 筛选}

set1 = { i for i in range(10) if i%2 == 0}

print(set1)

#结果:{0, 2, 4, 6, 8}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值