python函数

1,初识函数

# 函数
s = '杭州海博'
# 定义一个函数实现len(s)的功能
# 定义函数 def():
# def my_len():   #  函数名:字母,下划线,数字,不能以数字开头,避免关键字
#     i = 0
#     for k in s:
#         i += 1
#     print(i)
#
# # 调用函数,必须带上()
# my_len()
# leng = my_len()
# print(leng)  # 结果为None,说明没有返回值
# #  函数的特点:定义了之后,可以在任何需要它的地方调用这个函数

# # 加一个函数的返回值
# def my_len():
#     i = 0
#     for k in s:
#         i += 1
#     print(i)
#     return i  # 加返回值
# my_len()
# leng = my_len()
# print(leng)  # 结果为4,有返回值

# 返回值的三种情况
#1,没有返回值--返回None  1.1,函数里面没有写return  .1.2,只写了”return“,return代表结束一个函数。1.3,写return None,这个最不常用的
#2,返回1个值:2.1,可以返回任何数据类型  2.2,只要返回了就可以直接接收 2.3,如果在一个程序里面有多个return,只执行第一次运行的代码
#3,返回多个值:3.1,有多少返回值就用多少变量接受。 3.2,多个返回值,用一个变量接受:得到的是一个元祖
# def func():
#     return 1,2,3
# r = func()
# print(r)  # (1, 2, 3)
View Code

2,函数的参数

# 函数的参数
# def my_len(s): # 接受参数,形式参数
#     i = 0
#     for k in s: # 注意这个s要跟形参s一样
#         i += 1
#     return i
# s = '杭州海博'
# ret = my_len(s) # 调用函数的时候传递参数,实际参数
# ret = my_len([1,2,3])  # 调用函数的时候传递参数,实际参数
# print(ret)

# 参数的几种情况
'''
1,没有参数,定义函数时候括号里面不写内容
2,有一个参数
3,有多个参数
    3.1 位置参数
    3.2,关键字传递参数
    3.3 不能给同一个变量传递多个变量
'''
# 站在实参的角度上:
# def my_sum(a,b):
#     res = a + b
#     return res
# ret = my_sum(1,2)  #位置参数
# ret = my_sum(a = 1,b = 2) # 关键字传递参数
# ret = my_sum( 1, b=2) #混着使用可以,但必须先位置,再关键字
# print(ret)

# 站在形参的角度上
    #位置参数:必须传,有几个参数就传几个值
    #*args:动态参数,可以接受任意多个按位置传入的参数
    #默认参数,可以不传
    #**kwargs,可以接受任意多个按关键字传入的参数

# 定义函数的时候:
'''
1,位置参数:直接定义参数
2,默认参数,关键字参数:参数名= ”默认值“
3,动态参数:可以接受任意多个参数   参数名前加* 参数名习惯用args,
*args:接收的是按照位置传参的值,组织成一个元祖
**kwargs:接收的是按照关键字传参的值,组织成一个字典
4,顺序:必须先定义位置参数,动态参数*args,定义默认参数,**kwargs
'''

# def classmate(name,sex='男'):
#     print('%s:%s'%(name,sex))
# classmate('张三')
# classmate('小美','女')

#动态参数,求多个值得和
# def sum(*args): # *args是一个元祖,args也可以改成别的名字
#     sum = 0
#     for i in args:
#         sum = sum + i
#     return sum
# sum = sum(1,2,3,4)
# print(sum)

# def func(**kwargs):  # **代表字典,形参名习惯用kwargs
#     print(kwargs)
# func(a=1,b=2,c=3)
# func(a=1,b=2)
# func(a=1)

# 动态参数的另一种传参方式
# def func(*args): # 站在形参的角度上,给变量加上*,就是组合所有传来的值
#     print(args)
# func(1,2,3,4,5)
# li = [6,7,8,9]
# func(*li)  # (6, 7, 8, 9) 站在实参的角度上,给一个序列加上*,就是将这个序列按照顺序打散

# def func(**kwargs): # 站在形参的角度上,给变量加上*,就是组合所有传来的值
#     print(kwargs)
# func(a=1,b=2)
# li = {'a':1,'b':2}
# func(**li)  # 站在实参的角度上,给一个字典加上*,就是将这个字典按照顺序打散

# 函数的注释
# def func():
#     '''
#     这个函数实现了什么功能
#     参数1:什么,,
#     参数2:什么,,,
#
#     :return: 是什么东西
#     '''
#     pass

# 关于默认参数的陷阱:
# def qqxing(li = []):
#     li.append(1)
#     print(li)
# qqxing()  #[1]
# qqxing([]) #[1]  # 传了参数,所有列表只有一个1
# qqxing()  # [1, 1] 如果默认参数的值是一个可变数据类型,那么每一次调用这个函数的时候不传值就公用这个数据类型的资源
# qqxing()  # [1, 1, 1]
View Code

3,函数的嵌套和作用域

# 函数的嵌套定义
# 嵌套中,内部函数可以使用外部函数的变量
# a = 1
# def outer():
#     a = 1
#     def inner():
#         b = 2
#         print('第二层:',a)
#         print('inner')
#         def inner2():
#             nonlocal a # 如果第二层没有a,就继续上一层,对全局无效的
#             a += 1
#             print(a,b)
#             print('inner2')
#         inner2()
#
#     inner()
#     print('第一层:',a)
# outer()
# print('全局:',a )
#nonlocal只能用于局部变量,找上层中离当前函数 最近 一层 的局部变量。只会影响一层。

def func():
    print(123)
func2 = func # 函数名可以赋值,函数名本质就是在内存中的储存地址
func2()

li = [func,func2] #函数名可以作为容器类型的元素
for i in li:
    i()

def wahaha(f):  # 函数名可以作为函数的参数
    f()
    return f  # 函数名可以作为函数的返回值
qqxing = wahaha(func)
qqxing()
print(wahaha(func))

4,命名空间和作用域

#函数进阶--命名空间
#全局命名空间:--我们写的代码和函数名
'''
 是程序从上到下被执行的过程中依次被加载进内存的
    放置了我们所设置的变量名和函数名
'''
#局部命名空间--函数
'''
    就是函数内部定义的名字
    当调用函数的时候才会产生这个命名空间,函数结束,命名空间消失
'''
#内置命名空间:--python解释器
'''
    就是python解释器一启动就可以直接使用的名字存储在内置命名空间中,内置的名字在启动解释器的时候被加载进内存里
    比如:print(),input(),list ,tuple
'''

'''
在局部:可以使用全局、内部
在全局:可以使用内部,不能使用局部
在内部:不能使用局部和全局
'''

# print(max(1,2))  # 2
# def max():
#     print('in max func')
# max()
# # 结果:
# # in max func
# print(max())
# #结果:
# #in max func
# #None
#在正常情况下,直接使用内置的名字
#当我们在全局定义了何内置空间中名字同名的名字时,会使用全局的名字
#当我自己有的时候,就不要找我的上级要了
#如果自己没有,就找上一级要,如果找内置空间的名字都没找到就报错


# def func():
#     pass
# print(func)
# #func--->对应的函数的内存地址
# #函数名(),加了()才是函数的调用
# #也等于函数的内存地址()

#作用域:只有两种
'''
# 1,全局作用域
# 作用在全局,内置和全局名字空间中的名字都属于全部作用域
# 2,局部作用域
# 函数
# '''
# a = 1
# def func():
#     global a
#     a += 1  # 如果上面没有global a,会报错
#     print(a)
# func()
#对于不可变数据类型,在局部能查看全局作用域中的变量,但不能直接修改,如果需要修改,需要再函数的开始添加global声明
#如果再一个局部(函数)内声明了一个global变量,那么这个变量在局部的所有操作将对全局的变量有效

a = 1
b = 2
def func():
    x = 'aaa'
    y = 'bbb'
    print(globals())  # 全局的变量名字
    print(locals())  #{'y': 'bbb', 'x': 'aaa'}
func()
print(globals())  # 全局的变量
print(locals())  #还是全局的变量,因为locals翻译过来是本地的意思,跟代码位置有关系。
#globals 永远打印全局的名字
#locals 输出什么,跟位置有关系
View Code

5,闭包

#闭包:函数嵌套,内部函数调用外部函数的变量
# def outer():
#     a  = 1
#     def inner():
#         print(a)
#     print(inner.__closure__)  # (<cell at 0x000001F6319D0B58: int object at 0x0000000064AC22D0>,)
# outer()
# print(outer.__closure__)  #None

# def outer():
#     a  = 1
#     def inner():
#         print(a)
#     return inner  # 把函数名inner作为outer函数的返回值
# b = outer()
# b()  # 可以通过外部直接调用嵌套里面的函数

import urllib  # 模块
from urllib.request import urlopen
def get_url():
    url = 'http://www.baidu.com/index.heml'
    def inner():
        ret = urlopen(url).read()
        print(ret)
    return inner
get = get_url()
get()
View Code

6,函数的作业

# 函数的作业
# 写函数,接受n个参数,求这些参数的数字和
# def sum_func(*args):
#     total = 0
#     for i in args:
#         total = total + i
#     return total
# print(sum_func(12,3,4))

# 读代码,回答:代码中,打印出来的值,a,b,c分别是什么
# a = 10  # 顺序1
# b = 20  # 顺序2
# def test1(a,b):  # 顺序3:定义函数
#     print(a,b)   # 顺序5,执行函数,打印出来20,10
# c = test1(b,a)  # 顺序4:调用函数test1(b,a)就是test1(20,10)  #顺序6,把函数test1的结果赋值为c,但是函数没有返回值,所以c为None
# print(c)
# 结果:# 这道题考的知识1,实参的变量名跟形参的变量名没有关系,2,函数返回值 3,关于赋值的c,要先把函数运行完,再赋值
# 20 10
# None

# 读代码,回答:代码中,打印出来的值,a,b,c分别是什么
# a = 10
# b = 20
# def test2(a,b):
#     a = 3
#     b = 5
#     print(a,b)
# c = test2(b,a)
# print(c)
# #结果
# #3,5
# #None

# 写函数,检查获取传入列表或元祖对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者
# def func(l):
#     return l[1::2]
# print(func([1,2,3,4,5]))  # 这个题考的切片

#写函数,判断用户传入的对象(字符串,列表,元祖)长度是否大于5
# def func(l):
#     return len(l) > 5    # 大于或者小于是一个比较,返回bool值
# print(func((1,2,3,4)))

# 写函数,检车传入列表的长度,如果大于2,仅保留前两个长度的内容,并将新内容返回给调用者
# def func(l):
#     if len(l)>2:
#         return l[0:2] #也可以不要if,如果小于的,返回就是本来的列表
# print(func([1,2,3,4]))

# 写函数,计算传入字符串中【数字】,【字母】,【空格】以及【其他】的这四分类个数,并返回结果
# def func(s):
#     num = 0
#     alpha = 0
#     space = 0
#     other = 0
#     for i in s:
#         if i.isdigit():
#             num += 1
#         elif i.isalpha():
#             alpha += 1
#         elif i.isspace():
#             space += 1
#         else:
#             other += 1
#     return ('数字数量:{}\n字母数量:{}\n空格数量:{}\n其他数量:{}\n'.format(num,alpha,space,other))
# print(func('1a %'))
# 上题方法2
# def func(s):
#     dic = {'num':0,'alpha':0,'space':0,'other':0}
#     for i in s:
#         if i.isdigit():
#             dic['num'] += 1
#         elif i.isalpha():
#             dic['alpha'] += 1
#         elif i.isspace():
#             dic['space'] += 1
#         else:
#             dic['other'] += 1
#     return dic
# print(func('1a %'))

#写函数,检查用户传入的对象(字符串,列表,元祖)的每一个元素是否含有空内容,并返回结果
#'dfdg jkjl' 这个字符串算有一个空内容的,有个空格
#[1,2,3,'',[],(),'dfsaf jlkl'] 列表中字符串作为元素,不算空内容的
# def func(x):
#     if type(x) is str and x:
#         for i in x:
#             if i == ' ':
#                 return True
#     elif type(x) is list or type(x) is tuple and x:
#         for i in x:
#             if not i:
#                 return True
# print(func([]))

#写函数,检查传入字典的每一个value的长度,如果大于2,仅保留前两个长度的内容,并将新内容返回给调用者
#dic = {'k1':'vava','k2':[1,2,3,4]}  value中只有字符串和列表
# def func(dic):
#     for k in dic:
#         if len(dic[k])>2:
#             dic[k] = dic[k][0:2]
#     return dic
# dic = {'k1':'vava','k2':[1,2,3,4]}

# 写函数,接受两个数字参数,返回大的数字
# def func(a,b):
#     if a>b:
#         return a
#     else:
#         return b  # 两个数字一样的,就返回一个值
# print(func(3,3))
#上题方法2,三元运算
#变量 = 条件返回True的结果 if 条件 else 条件返回False的结果
#三元运算的调节:
#必须要有结果,必须有if和else,必须是简单的运算
# def func(a,b):
#     c = a if a>b else b
#     return c
# print(func(1,2))

#写函数,用户传入修改的文件名和要修改的内容,执行函数,批量操作
# def func(filename,old,new):
#     with open(filename,'r',encoding='utf-8') as f, open('%s.bak'%filename,'w',encoding='utf-8') as f2:
#         for line in f:
#             if old in line:
#                 line = line.replace(old,new)
#             f2.write(line) # 可以多次write,不会被清空,只有在打开的一瞬间清空的。
#             f2.write(line)
# filename = '开会主题'
# old = '电'
# new = '气'
# func(filename,old,new)
View Code

7,装饰器

import time
# time.time() # 获取当前时间
# time.sleep(3)  # 让程序在执行这个位置的时候停一会儿
# print('hahaha')

# def func():  #顺序1
#     time.sleep(0.02)  # 顺序10
#     print('大家好')   #顺序11
# def timer(f):  # 顺序2   #装饰器函数
#     def inner(): #顺序4:执行timer函数,定义inner函数
#         start = time.time()  # 顺序8
#         f()  # 顺序9,f就是传入的实参func     # 被包装的函数,不想被修改的
#         end = time.time()  # 顺序12
#         print(end-start)  # 顺序13
#     return inner #顺序5:把inner作为返回值返回给timer函数
# func = timer(func)   #顺序3:执行timer函数,把func值传入  顺序6,赋值func = inner
# func()   # 顺序7,func()就是inner(),执行inner函数

#装饰器的作用:不想修改函数的调用方式,但是还想在原来的函数前后添加功能
#timeer就是一个装饰器函数,只是对一个函数有一些装饰作用

'''
原则:开放封闭原则
开放:对扩展是开放的
封闭:对修改是封闭的

封板:

'''

#语法糖
# def timer(f):
#     def inner():
#         start = time.time()
#         ret = f()
#         end = time.time()
#         print(end-start)
#         return ret
#     return inner
# @timer  # 语法糖 @装饰器函数名,相当于下面的func = timer(func)
# def func():
#     time.sleep(0.02)
#     print('大家好')
#     return '新年好'
# # func = timer(func)
# ret = func()
# print(ret)

#装饰带参数的函数的装饰器
# def timer(f):
#     def inner(*args,**kwargs):
#         start = time.time()
#         ret = f(*args,**kwargs)
#         end = time.time()
#         print(end-start)
#         return ret
#     return inner
# @timer  # 语法糖 @装饰器函数名,相当于下面的func = timer(func)
# def func(a):
#     time.sleep(0.02)
#     print('大家好',a)
#     return '新年好'
# # func = timer(func)
# ret = func(1)
# print(ret)

# def wrapper(f):  #装饰器函数,f是被装饰的函数
#     def inner(*args,**kwargs):
#         '''在被装饰函数之前要做的事'''
#         ret = f(*args,**kwargs)  # 真正被装饰的函数执行
#         '''在被装饰函数之后要做的事'''
#         return ret
#     return inner
# @wrapper  # 语法糖 @装饰器函数名,相当于下面的func = timer(func)
# def func(a):
#     time.sleep(0.02)
#     print('大家好',a)
#     return '新年好'
# # func = timer(func)
# ret = func(1)
# print(ret)

# def wapper(func):
#     def inner(*args,**kwargs):
#         print('在被装饰的函数之前做的事')
#         ret = func(*args,**kwargs)
#         print('在被装饰的函数之后做的事')
#         return ret
#     return inner
#
# @wapper  #holiday = wapper(holidy)
# def holiday(day):
#     print('全体放假%s天'%day)
#     return '好开心'
# print(holiday(3))

#动态参数
# def outer(*args,**kwargs):  #聚合  ,接收的时候组合成元祖
#     print(args)  #(1, 2, 3, 4)
#     print(*args)  # 1 2 3 4  # 打散  ,调用的时候就打散啦
#     def inner(*args):  #聚合
#         print(args)
#         print(*args)  # 打散
#     inner(*args)
# outer(1,2,3,4)  #等价于outer(*(1,2,3,4)),也等于outer(*[1,2,3,4])
View Code

 

posted @ 2020-10-17 14:01  包子789654  阅读(89)  评论(0编辑  收藏  举报