函数

函数基础

函数 又叫 方法 功能
函数名规范:字母a-z A-Z数字0-9下划线 _ 不能由数字开头 严格区分大小写 不能用关键字 取名字要有意义 同一个文件中的函数名不能重复
1.自定义函数
def 函数名(形参):
你的代码
2.系统提供的函数 叫做内置函数

先把形参传递给实参 返回值 行不行 相当于break
自定义函数写完不调用 函数不发挥他的作用
调用过程中( )小括号代表执行

函数的参数

###形式参数
def sums(num1,num2):  #""""""自动补全函数注释
    """
    求两个数字的和
    :param num1:int/flost  #写类型
    :param num2: int/float  #写类型
    :return: int/float   #写类型
    """
    print(num1+num2)
###实际参数
sums(11,22)
def xinagsheng(p1,p2,p3):
    """
    :param p1:str
    :param p2: str
    :param p3: str
    :return: str
    """
    print(p1+'唱了一首'+p2)
    print(p3+'也唱了一首'+p2)
xinagsheng('张云雷','探清水河','孟鹤堂')
xinagsheng('郭麒麟','探清水河','张鹤伦')
结果:
张云雷唱了一首探清水河
孟鹤堂也唱了一首探清水河
郭麒麟唱了一首探清水河
张鹤伦也唱了一首探清水河

默认参数

def test(age=10):
    print('你的年龄:%d'%age)
test()  #有了默认值  可以直接调用 不传这个参数
test(age=20) #优先传赋的值

#默认值参数 一定要在 非默认值参数的后面
#前面写法是age = 17 后边就不能只写黄冈 必须city='hg' 但是前面sunf  age=17这种是支持的
def say_hi(name,age,city='wuhan'):  
    # print('大家好,我是{},今年{},来自{}'.format(name,age,city))
    print(f'大家好,我是{name},今年{age},来自{city}')
    return
say_hi('sunf',17)
say_hi('sunf',17,'hg')
say_hi(name='sunf',age=17,city='hg')
say_hi('sunf',age=17,city='hg')

# print(self, *args, sep=' ', end='\n', file=None)
#print方法中的  sep=   end=  缺省参数   也叫默认参数

自定义参数

# 相加
def add_many(nums):
    """
    :param num:列表 元组 集合 字典 range() 字符串
    :return:
    """
    if isinstance(nums,dict):   #isinstance(x,数据类型) 判断是否为这个类型
        nums = nums.values()
    x=0  #存放最终的和
    for i in nums:
        if type(i)==int:
            x+=i
        else:
            x+=int(i)
    return  x
print(add_many([11,2,43,56,74])) #186
print(add_many((11,2,43,56,74))) #186
print(add_many({'name':78,'age':23})) #101
print(add_many('356878')) #37
print(add_many(range(1,9))) #36

def test(*num):  #代表多个参数
    print('num:{}'.format(num)) #num:(1, 2, 3, 4, 5, 6, 7, 8) 是元组
    x=0 #存放总和
    for i in num: #遍历上面元祖
        x+=1
    return x
print(test(1,2,3,4,5,6,7,8))

#万能参数 *args接收单个元素 放到元组中
#**kwargs 接收键值 放到字典中
def wanneng(*args,**kwargs):
    print('args{}'.format(args)) #args(2, 3, 4, (33, 34), '343dfs', [23, 44])
    print('kwargs{}'.format(kwargs)) #kwargs{'sa': 'duyuan', 'han': 'gga'}
#遍历参数
    for x in args:
        print(x)
    for y in kwargs.keys():
        print(y)
wanneng(2,3,4,(33,34),'343dfs',[23,44],sa='duyuan',han='gga')

可变类型与不可变类型的传参

#内存地址 16进制表示  0X  0x   %X  %x  16进制格式化字符
#整形不可变  改变之后地址变化
def test(x):
    print('修改之前的内存的地址:0x%x'%id(x)) #id()用来查看变量内存地址  修改之前的内存的地址:0x7ffab9b57110
    x = 666 # 修改
    print('修改之后的内存的地址:0x%x'%id(x)) #id()用来查看变量内存地址  修改之后的内存的地址:0x19a79798710
test(1)

#列表可变数据   改变之后地址不变
def test(y):
    print('修改之前的内存的地址:0x%x'%id(y)) #id()用来查看变量内存地址 修改之后的内存的地址:0x19a79798710
    y[0] = 'haha' # 修改
    print('修改之后的内存的地址:0x%x'%id(y)) #id()用来查看变量内存地址  修改之后的内存的地址:0x19a79798710
test([1,2,3,4,5,6,7])

函数的返回值

返回值 函数执行的结果
并不是所有的函数都有返回值
如果一个函数没有返回值 那么它的返回值就是None

def adds(x,y):
    """
    求两个数字的和
    :param x: int/float
    :param y: int/float
    :return: int/float
    """
    print(x+y)
    return x+y  #return 表示给到你函数执行结果 打印实参加print
print(adds(3,4)) #7
x = print('hello world')   #直接打印没有返回值
print(x) #None

多个返回值

一般情况下 函数只执行一个return语句
但是有一个列外 finally 语句下 一个函数可能会执行多个return
return 可以返回元组 字典 列表 默认元祖

def test(x,y):
    num1 = x+y
    num2 = x*y
    num3 = x-y
    return num1,num2,num3
    # return [num1,num2,num3]
    # return {'num1':num1,'num2':num2,'num3':num3}
    # return (num1,num2,num3)
print(test(10,15))
a,b,c=test(10,15)  #取出对应的元祖
print(a,b,c)
for x in test(10,5): #遍历
    print(x)
result = test(10,5)
print('商{},商{},余数{}'.format(result[0],result[1],result[2]))  #商15,商50,余数5
a,b,c = test(10,15)
print('数字{},数字{},数字{}'.format(a,b,c)) #数字25,数字150,数字-5

函数调用函数

##三位数相加
def test1(num1,num2):     #实际参数传给形式参数
    """
    求两个数字的和
    :param num1: int/float
    :param num2: int/float
    :return: int/float
    """
	return num1+num2
def test2(x,y,z)   
	print('开始调用test1')
	return test1(y,z)+x       #调用test1
print(test2(10,20,30)    #60
#求[n,m)之间的和
def sums(n,m):
	x=0  #存放最终结果
	    """
    :param num1: int
    :param num2: int
    :return: int
    """
    for i in range(n,m):
    	x+=i
    return x
 print(sums(10,20)  
 #求n的阶乘 
 def factorial(n):
 	x=1
 	for i in range(1,n+1):
 		x*=i
 	return x
 print(factorial(6))
 #求 1! +2!+3!+4!+5!  n的阶乘
 def factorial_sum(n):
 	x=0
 	for i in range(1,n+1):
 		x+=factorial(i)
 	return x
 def factorial(i):
 	y=1
 	for j in range(1,i+1):
 		y*=j
 	return y
print(factorial_sun(6))

函数的全局变量和局部变量

整个.py文件 都可以访问的变量 叫做全局变量
局部变量 这个变量是在函数内部定义的变量 如果函数执行完毕 会从内存中释放空间
globals()#内置函数 用来查看全局变量
locals() #内置函数 用来查看局部变量
对全局变量做修改 用global对局部变量进行声明
局部变量可以调用全局 全局不能调用局部变量
if for while 不存在作用域 也就是他们里边不存在局部变量 全局可以直接调用

a=100 #全局变量
test = 'hello world'
def say_hi():
    num=666 #局部变量 这个变量是在函数内部定义的变量
    # a=1000 #这个a是新定义的局部变量 不会修改全局变量
    global a #声明 我这不是一个新的局部变量  我想对全局变量a做修改
    a=1000
    # return test+str(num)
    print(num+a) #局部变量可以调用全局
# print(say_hi())
say_hi()
print(a)
# print(num) #全局不能调用局部变量 报错
word = '英雄武汉人民' #全局变量
# word = 'haha' 都是全局变量 如果重名 后面将覆盖前面
def test():
    x='hello wuhan' #局部变量
    print('x={}'.format(x))
    # word = '你好湖北' #在函数内容  跟全局变量名重名  不影响
    #表示创建一个新的局部变量
    global word
    word = '你好武汉'
    print('函数内部的变量word={}'.format(word))
    print('全局变量{},局部变量{}'.format(globals(),locals()))  #输出所以全局变量
test()
# print(x)# 这是在全局调用局部变量 报错 不能调用
print('全局变量word={}'.format(word))

递归函数

#用递归实现1-n之间的和
def get(n):
    if n==0:
        return 0
    return n+get(n-1)
print(get(5))
"""
1  get(5) =5+get(4)    10+5=15
2  get(4) =4+get(3)    4+6=10
3  get(3) =3+get(2)    3+3=6
4  get(2) =2+get(1)    2+1=3
5  get(1) =1+get(0)    1+0=1
6  get(0)   return 0    0
"""

# n!
def get_factorial(n):
    if n==0:
        return  1
    return n*get_factorial(n-1)
print(get_factorial(5))
"""
1  get(5) =5*get(4)    5*24=120
2  get(4) =4*get(3)    4*6=24
3  get(3) =3*get(2)    3*2=6
4  get(2) =2*get(1)    2*1=2
5  get(1) =1*get(0)    1*1=1
6  get(0) return 1     1
"""

#斐波那契数列
#0 1 1 2 3 5 8 13 21 34 55 89 144
def Fibnacci(n):
    if n==0 :
        return 0
    elif n==1:
        return 1
    return Fibnacci(n-2)+Fibnacci(n-1)
print(Fibnacci(12))
"""
1 F(12)=F(10)+F(11)         55+89=144
2 F(11)=F(9)+F(10)         34+55=89
3 F(10)=F(8)+F(9)          21+34=55
4 F(9)=F(7)+F(8)           13+21=34
5 F(8)=F(6)+F(7)           8+13=21
6 F(7)=F(5)+F(6)           5+8=13
7 F(6)=F(4)+F(5)           3+5=8
8 F(5)=F(3)+F(4)           2+3=5   
9 F(4)=F(2)+F(3)           1  2    =3
10 F(3)=F(1)+F(2)          1  1    =2
11 F(2)=F(0)+F(1)  return 0  1  = 1
"""

匿名函数lambda

#换新函数名  地址不变
def add(num1,num2):
    return num1+num2
print('函数内存地址:0x%x'%id(add)) #函数内存地址:0x20071bd79d8
x=add(1,3)
print(x)
#给add起了一个别名  地址一样
fn = add
print('新函数名内存地址:0x%x'%id(fn)) #新函数名内存地址:0x20071bd79d8
y =fn(5,6)
print(y)

#匿名  没有名字
#一次性的函数   一般我们就创建一个匿名函数   功能  肯定不会复杂
#调用匿名函数
# 1.给他定义一个名字  这个很少用
test = lambda  x,y: x*y
print(test(1,3)) #3
# 2.把他当作参数传给另一个函数
def test(x,y,fn):
    """
    :param x: int
    :param y: int
    :param fn: 方法 函数
    :return: int
    """
    z=fn(x,y)
    return z
def add(a,b):  # add也叫回调函数
    return a+b
print(test(12,21,add)) #add函数名  不加() 告诉 test 调用函数add   ( )代表执行

print(test(10,20,lambda x,y:x+y))
print(test(10,20,lambda x,y:x*y))
print(test(10,20,lambda x,y:x-y))
print(test10,20,lambda x,y:x/y))

应用匿名函数的内置函数和内置类

排序 sort def sort(self,key=None,reverse=False)

key 是用来指定比较规则 是一个方法函数
reverse 是判断正序倒序

studens = [{'name':'zhangsan ','age':16,'score':83},
            {'name':'lisi','age':17,'score':89},
            {'name':'ergou','age':14,'score':67},
            {'name':'baifa','age':13,'score':89},
            {'name':'wuyu ','age':17,'score':80},
            {'name':'zhah ','age':13,'score':67},
            {'name':'zlala ','age':16,'score':87},
            {'name':'aipig','age':15,'score':78}
           ]
def foo(ele):  #定义函数
    return ele['age']
studens.sort(key=foo) #告诉 sort 按照字典中的 age 进行排序
print(studens)

studens.sort(key=lambda ele:ele['age'],reverse=True)  
print(studens)
排序 sorted

sorted 在python2是个方法 在python3 变成内置类

studens = [{'name':'zhangsan ','age':16,'score':83},
            {'name':'lisi','age':17,'score':89},
            {'name':'ergou','age':14,'score':67},
            {'name':'baifa','age':13,'score':89},
            {'name':'wuyu ','age':17,'score':80},
            {'name':'zhah ','age':13,'score':67},
            {'name':'zlala ','age':16,'score':87},
            {'name':'aipig','age':15,'score':78}
           ]
res = sorted(studens,key=lambda  ele:ele['age'],reverse=True)
print(studens)
过滤 filter 类 def_init_(self,function_or_None,iterable)

unction_or_None 是一个方法
iterable 是一个可迭代对象
对可迭代对象进行过滤 返回的是一个filter对象 可以对对象转成列表 元组等
filter 在python2是个方法 在python3 变成内置类

studens = [{'name':'zhangsan ','age':16,'score':83},
            {'name':'lisi','age':17,'score':89},
            {'name':'ergou','age':14,'score':67},
            {'name':'baifa','age':13,'score':89},
            {'name':'wuyu ','age':17,'score':80},
            {'name':'zhah ','age':13,'score':67},
            {'name':'zlala ','age':16,'score':87},
            {'name':'aipig','age':15,'score':78}
           ]
print(list(filter(lambda x:x['age']>15,studens)))  #list转换为列表形式
#[{'name': 'zhangsan ', 'age': 16, 'score': 83},
# {'name': 'lisi', 'age': 17, 'score': 89},
# {'name': 'wuyu ', 'age': 17, 'score': 80}, 
# {'name': 'zlala ', 'age': 16, 'score': 87}]
叠加 map def init(self, func, *iterables)

func 是一个函数,方法
iterables 是一个可迭代对象
对列表中的每一项数据执行相同的操作 返回的是一个新的迭代器

studens = [{'name':'zhangsan ','age':16,'score':83},
            {'name':'lisi','age':17,'score':89},
            {'name':'ergou','age':14,'score':67},
            {'name':'baifa','age':13,'score':89},
            {'name':'wuyu ','age':17,'score':80},
            {'name':'zhah ','age':13,'score':67},
            {'name':'zlala ','age':16,'score':87},
            {'name':'aipig','age':15,'score':78}
           ]
res= map(lambda x:x['age']+1,studens)
print(res) #<map object at 0x00000185314863C8>
print(list(res)) #[17, 18, 15, 14, 18, 14, 17, 16]
合并 reduce def reduce(function,sequence,initial=None )

第一个参数是个方法
第二个参数是个列表
第三个参数 initial 表示从几开始
如果不加第三个参数 会抛出类型错误
python3整合到了functools 模块
pip install 模块名 先下载
再导入 from functools import reduce

studens = [{'name':'zhangsan ','age':16,'score':83},
            {'name':'lisi','age':17,'score':89},
            {'name':'ergou','age':14,'score':67},
            {'name':'baifa','age':13,'score':89},
            {'name':'wuyu ','age':17,'score':80},
            {'name':'zhah ','age':13,'score':67},
            {'name':'zlala ','age':16,'score':87},
            {'name':'aipig','age':15,'score':78}
           ]
def add(x,y):
    x = 0
    y = {'name':'lisi','age':17,'score':89}
    return x+y['age']
print(reduce(add,studens,0))

print(reduce(lambda x,y:x+y['age'],studens,0)) #x,y为形参  #0+10+17+...+15
print(reduce(lambda x,y:x+y['age'],studens,1))#1+10+17+...+15
print(reduce(lambda x,y:x+y['age'],studens,-10))#-10+17+...+15           

内置函数 any dir help

#any 参数是可迭代对象  判断可迭代参数是否全为假
print(any(['zhangsan',1,[1,2,3]])) #有一个是True 结果返回True
print(any(['',0,[]])) #全为False 结果返回False

#返回参数 范围内的 方法 属性 变量 等
print(dir([]))#['append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
print(dir({}))#['clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
print(dir(()))#['count', 'index']
print(dir(""))#['capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

#help  查看注释
help(input)
help(print)
num = [1,23,3]
help(num.sort)
def test(x,y,age=10):
    """

    :param x: int
    :param y: float
    :param age: int
    :return:
    """
    return x+y+age
help(test)

高阶函数

函数数据类型:int float list dict tuple str set bool function
高阶函数
函数作为另外一个函数的参数
函数作为另外一个函数的返回值
函数内部在定义一个函数 if

#type 查看数据类型
def test(x,y):
    return x+y
print(type(test))#<class 'function'>

def test():
    print('我是test函数')
    return 'hello'
def demo():
    print('我是demo函数')
    return test
def haha():
    print('我是haha函数')
    return test()
#返回一个函数      不加()
#返回一个函数的返回值 加()
str2 = test()
print(str2)
print(type(str2)) #<class 'str'>
print(type(demo()))#<class 'function'>
print(demo()())#demo()()=test()
结果:我是demo函数
		   我是test函数
		    hello

闭包

#嵌套函数,产生闭包问题
#函数嵌套,函数里面还可以定义函数,执行需要被调用
def outer():
    print('outer     hello')
    def inner():   #inner是函数outer内部定义的
        print('inner     hello')
    inner() #inner函数只在outer函数内部可见
outer()

#闭包 = 函数块 + 引用环境       demo(函数块)(引用环境)
# 如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包
def outer(n):
    num = n
    def inner():
        return num+1
    return inner
print(outer(3)()) #4
print(outer(5)()) #6

# 修改外部变量的值  闭包里默认不能修改外部变量。
#使用 nonlocal 关键字 进行声明

def outer():
    x = 10 #在外部函数里边定义一个变量  局部变量
    def inner():
        nonlocal x  #声明x不再是新增的局部变量  而是外部的局部变量x
        x = 5
        print(f'inner里边的x的值{x}')
    return  inner
outer()() #像这样 函数块+引用环境  组成闭包

def outer(num):
    m=100#局部变量
    print(m)
    print('这是outer函数')
    def inner():
        print('我是inner函数代码')
    if num>18:
        inner()
    return 'hello'
print(outer(19))
# print(m)报错 全局变量不能调用局部变量
# print(inner())报错

代码运行时间

# 时间戳
# 1970-01-01 00:00:00 开始  一直到现在的秒数   注意不是北京时间 UTC
#获取代码开始时间
#start = time.time()
#获取代码结束时间
#end  = time.time()
#结束时间-开始时间 = 代码运行的时间
#start-end
import time
start  = time.time() #获取的是时间戳
x=0
for i in range(10000000):
    x+=i
end = time.time()
print('1到10000000求和用了%.2f秒'%(end-start)) #1到10000000求和用了1.02秒
print(f'1到10000000求和用了{(end-start):.2f}秒') #1到10000000求和用了1.02秒
print(start) #1617029572.8805504

函数优化计算代码运行时间

import time
def cal_time(fn):
    start = time.time()
    fn()
    end = time.time()
    # return '1到10000000求和用了%.2f秒'%(end-start)
    return f'1到10000000求和用了{(end-start):.2f}秒'
def demo():
    x=0
    for i in range(10000000):
        x+=i
    print(x)  #求和 49999995000000
def foo():
    print('hello')
    time.sleep(1) #代表程序睡一秒
    print('world')
print(cal_time(demo)) #1到10000000求和用了0.49秒  fn()=demo()调用
print(cal_time(foo))#1到10000000求和用了1.00秒  

装饰器的使用

第一步 调用cal_time
第二步 将demo 传给 cal_time
第三步 获取 start 然后执行fn() 也就是demo() demo需要有参数
第四步 这个参数给到inner 游inner 给到 demo()

import time
def cal_time(fn):
    print('我是外部函数我被调用了')
    print(f'fn={fn}')    #fn=<function demo at 0x000001E525D74798>   fn=<function foo at 0x000002AD522C48B8>
    def inner():
        start = time.time()
        fn()
        end = time.time()
        print(f'1到100000求和用了{(end-start):.2f}秒')   #1到100000求和用了0.47秒  1到100000求和用了1.00秒
    return inner
@cal_time #在执行demo之前  先调用cal_time 第二件事 把demo当作参数传给cal_time
def demo():
    x=0
    for i in range(10000000):
        x+=i
    print(x)  #求和 49999995000000
@cal_time
def foo():
    print('hello')
    time.sleep(1) #代表程序睡一秒
    print('world')
demo()
foo()
含参
import time
def cal_time(fn):
    print('我是外部函数我被调用了')
    print(f'fn={fn}')
    def inner(x,*args,**kwargs):
        start = time.time()
        s = fn(x)
        end = time.time()
        # print(f'1到100000求和用了{(end-start):.2f}秒')
        print('1到100000求和用了%.2f秒'%(end-start))
        for i in args: #遍历
            print(i)
        for j,h in kwargs.items():  遍历字典
            print(j,':',h)
        return s ,end-start
    return inner
@cal_time #在执行demo之前  先调用cal_time 第二件事 把demo当作参数传给cal_time
def demo(n):
    x=0
    for i in range(1,n):
        x+=i
    return x
demo(1000000)
print(demo(5000000,'haha','kangbazi',name='666',age=18))

装饰器的应用

def can_play(fn):
    def inner(x,y,*args,**kwargs):
        ck = kwargs.get('clock',13)  #get获取字典  如果不传clock 默认值就是13
        if ck<=22:
            fn(x,y)
        else:
            print('gosleep')
    return inner
@can_play
def play_game(name,game):
    print(f'{name}play{game}')   #GDplayWTF
play_game('GD','WTF',clock = 13)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值