Python 函数定义和使用
- # 函数的概念
- # 概念
- # 写了一段代码实现了某个小功能; 然后把这些代码集中到一块, 起一个名字; 下一次就可以根据这个名字再次使用这个代码块, 这就是函数
- # 作用
- # 方便代码的重用
- # 分解任务, 简化程序逻辑
- # 使代码更加模块化
- # 函数分类
- # 内建函数
- # 三方函数
- # 自定义函数
- # 函数的基本使用
- # 简单定义
- # def 函数名():
- # 函数体
- # 函数的调用
- # 函数名()
- def myFun():
- print(1)
- #函数调用
- myFun()
- # 函数的参数
- # 单个参数
- # 场景
- # 需要动态的调整函数体中某一个处理信息
- # 则可以, 以参数的形式接收到相关数据
- # 定义
- # def 函数名(参数名称):
- # 函数体
- # 函数体中, 可以直接以变量的方式使用该参数
- # 函数的调用
- # 函数名(参数值)
- # 形参和实参的概念
- # 上述函数定义中, "参数名称"即为形参;
- # 在调用函数的时候, 传递的真实数据, 即为实参
- # 多个参数
- # 场景
- # 需要动态的调整函数体中多个处理信息时
- # 则可以以 逗号 做分割, 接收多个参数
- # 定义
- # def 函数名(参数名称1, 参数名称2):
- # 函数体
- # 函数体中, 可以直接以变量的方式使用所有参数
- # 调用
- # 方式1
- # 函数名(参数1, 参数2, 参数3...)
- # 形参和实参一一对应
- # 方式2
- # 函数名(参数名称1=参数1, 参数名称n = 参数n...)
- # 可以指明形参名称
- # 称为"关键字参数"
- # 不需要严格按照顺序
- # 不定长参数
- # 场景
- # 如果函数体中, 需要处理的数据, 不确定长度
- # 则可以以不定长参数的方式接收数据
- # 方式1
- # 定义
- # def 函数名(*args):
- # 元组
- # 函数体
- # 函数体中, 可以直接以元组变量的方式使用该参数
- # 使用
- # 函数名(参数1, 参数2, 参数3...)
- def myFunA(*args):
- print(args,type(args))
- for v in args:
- print(v)
- myFunA(1, 2, 3) #(1, 2, 3) <class 'tuple'>
- # 方式2
- # 定义
- # def 函数名(**dic):
- # 字典
- # 函数体
- # 函数体中, 可以直接以字典变量的方式使用该参数
- # 使用
- # 函数名(参数名称1=参数1, 参数名称2=参数2...)
- def myFunB(**kwargs):
- print(kwargs, type(kwargs))
- myFunB(name = "abc", age = 18) # {'name': 'abc', 'age': 18} <class 'dict'>
- # 参数拆包
- # 装包
- # 把传递的参数, 包装成一个集合, 称之为"装包"
- # 拆包
- # 把集合参数, 再次分解成单独的个体, 称之为"拆包"
- def mySum(a, b):
- print(a + b)
- def myFunC(*args):
- print(args)
- #拆包
- mySum(*args)
- myFunC(1, 2) #(1, 2) 3
- # 缺省参数
- # 场景
- # 当我们使用一个函数的时候, 如果大多数情况下, 使用的某个数据是一个固定值, 或者属于主功能之外的小功能实现;
- # 则可以使用默认值
- # 这种参数, 称为"缺省参数"
- # 定义
- # def 函数名(变量名1=默认值1, 变量名2=默认值2):
- # 函数体
- # 函数体中, 即使外界没有传递指定变量, 也可以使用, 只不过值是给定的默认值
- # 使用
- # 函数名(变量1, 变量2)
- # 此处如果是缺省参数, 则可以不填写
- # 参数注意
- # 值传递和引用传递
- # 值传递
- # 是指传递过来的, 是一个数据的副本;
- # 修改副本, 对原件没有任何影响
- # 引用传递
- # 是指传递过来的, 是一个变量的地址
- # 通过地址, 可以操作同一份原件
- # 但是注意
- # 在Python当中, 你没得选, 只有引用传递(地址传递)
- # 但是
- # 如果数据类型是可变类型, 则可以改变原件
- # 如果数据类型是不可变类型, 则不可以改变原件
- def test(num):
- print(id(num))
- print(num)
- num = 11
- print(id(num)) # 和a地址不一样
- a = 10
- print(id(a))
- test(a) # 打印的id 值一样
- print(id(a))
- print("------------------")
- # 值发生改变,是根据数据类型来说的
- def test1(num):
- print(id(num))
- num.append(666)
- a = [1, 2, 3]
- print(id(a))
- test1(a) # 打印的id 值一样
- print(a) #[1, 2, 3, 666]
- # 函数的返回值
- # 场景
- # 当我们通过某个函数, 处理好数据之后, 想要拿到处理的结果
- # 语法
- # def 函数():
- # 函数体
- # return 数据
- # 注意事项
- # 1. return 后续代码不会被执行
- # 2. 只能返回一次
- # 3. 如果想要返回多个数据, 可先把多个数据包装成一个集合, 整体返回
- # 列表
- # 元组
- # 字典
- # ...
- def myCall(a, b):
- he = a + b
- cha = a - b
- return (he, cha) # 返回元组,就可以返回多个值了
- he, cha = myCall(11, 10)
- print(he, cha) #21 1
- # 函数的使用描述
- # 场景
- # 当我们编写三方函数, 为了方便他人使用, 就需要描述清楚我们所写的函数功能以及使用方式等信息
- # 定义格式
- # 直接在函数体的最上面, 添加三个双引号对注释
- # def 函数():
- # ''' 这里写帮助信息 '''
- # 查看函数使用文档
- # help(函数)
- # 经验
- # 一般函数的描述, 需要说明如下几个信息
- # 函数的功能
- # 参数
- # 含义
- # 类型
- # 是否可以省略
- # 默认值
- # 返回值
- # 含义
- # 类型
- def caculate(a, b = 1):
- """
- 计算2个数的和与差
- :param a: 参数1:数值类型,不可选,没有默认值
- :param b: 参数2:数值类型,可选,默认值:1
- :return:返回的是计算的结果:元组类型,(和,差)
- """
- he = a + b
- cha = a - b
- return (he, cha) # 返回元组,就可以返回多个值了
- help(caculate)
- # 偏函数
- # 概念&场景
- # 当我们写一个参数比较多的函数时, 如果有些参数, 大部分场景下都是某一个固定值, 那么为了简化使用, 就可以创建一个新函数,
- # 指定我们要使用的函数的某个参数, 为某个固定的值; 这个新函数就是"偏函数"
- # 语法
- # 方式1
- # 自己写一个新的
- # 方式2
- # 借助functools模块的partial函数
- # import functools
- # newFunc = functools.partial(函数, 特定参数=偏爱值)
- # 场景
- # int()
- #方式1
- def myFun1(a, b, c, d):
- print(a + b + c + d)
- def myFun2(a, b, c, d = 1):
- myFun1(a, b, c, d)
- myFun2(1, 2, 3) #print 7
- #方式2
- import functools
- newFun = functools.partial(myFun1, d = 2)
- newFun(1, 2, 3) #print 8
- #应用场景
- numStr = ""
- res = int(numStr, base = 2)
- print(res) #print 18
- int2 = functools.partial(int, base = 2)
- print(int2(numStr)) #print 18
- # 高阶函数
- # 概念
- # 当一个函数A的参数, 接收的又是另一个函数时, 则把这个函数A成为是"高阶函数"
- # 例如
- # sorted函数
- # 案例
- # 动态计算两个数据
- l = [{"name": "a1", "age": 18}, {"name": "a2", "age": 20}, {"name": "a3", "age": 19}]
- def getKey(x):
- return x["age"] #按age的值来排序
- result = sorted(l, key = getKey)
- print(result) # [{'name': 'a1', 'age': 18}, {'name': 'a3', 'age': 19}, {'name': 'a2', 'age': 20}]
- #案例
- def caculate_test(num1,num2, newFun):
- return newFun(num1, num2)
- def sum(a, b):
- return a + b
- res = caculate_test(1, 2, sum)
- print(res) #
- # 返回函数
- # 概念
- # 是指一个函数内部, 它返回的数据是另外一个函数; 把这样的操作成为"返回函数"
- # 案例
- # 根据不同参数, 获取不同操作, 做不同计算
- def getFunc(flag):
- def sum(a, b, c):
- return a + b + c
- def jian(a, b, c):
- return a - b - c
- if flag == "+":
- return sum
- elif flag == "-":
- return jian
- newFun = getFunc("+")
- res = newFun(1, 2, 3)
- print(res) #
- # 匿名函数
- # 概念
- # 也称为 "lambda函数"
- # 顾名思义, 就是指没有名字的函数
- # 语法
- # lambda 参数1, 参数2.. : 表达式
- # 限制
- # 只能写一个表达式
- # 不能直接return
- # 表达式的结果就是返回值
- # 所以, 只适用于一些简单的操作处理
- # 测试
- # func = lambda x, y: x + y
- # func(1, 2)
- result = (lambda x, y : x + y)(1, 2)
- print(result, type(result)) #3 <class 'int'>
- newFunc = lambda x, y : x + y
- print(newFunc(4,5)) #
- #应用场景
- l = [{"name": "a1", "age": 18}, {"name": "a2", "age": 20}, {"name": "a3", "age": 19}]
- result = sorted(l, key = lambda x : x["age"])
- print(result) # [{'name': 'a1', 'age': 18}, {'name': 'a3', 'age': 19}, {'name': 'a2', 'age': 20}]
- # 闭包
- # 概念
- # 在函数嵌套的前提下
- # 内层函数引用了外层函数的变量(包括参数)
- # 外层函数, 又把 内层函数 当做返回值进行返回
- # 这个内层函数+所引用的外层变量, 称为 "闭包"
- # 标准格式
- # def test1(a):
- # b = 10
- # 其他函数定义代码
- # def test2():
- # print(a)
- # print(b)
- # return test2
- # 应用场景
- # 外层函数, 根据不同的参数, 来生成不同作用功能的函数
- # 案例
- # 根据配置信息, 生成不同的分割线函数
- # 注意事项
- # 1. 闭包中, 如果要修改引用的外层变量
- # 需要使用 nonlocal 变量 声明
- # 否则当做是闭包内, 新定义的变量
- # 2. 当闭包内, 引用了一个, 后期会发生变化的变量时, 一定要注意
- # 函数, 是被调用时, 才去确定变量标识所对应的值
- #应用场景
- def line_config(content,length):
- print("-" * (length // 2) + content + "-" * (length // 2))
- line_config("闭包",20) #----------闭包----------
- line_config("闭包",20) #----------闭包----------
- #上面的方式调用麻烦,现在改造一下,方便调用
- def line_config(content,length):
- def line():
- print("-" * (length // 2) + content + "-" * (length // 2))
- return line
- line1 = line_config("闭包",20)
- line1() #----------闭包----------
- line1() #----------闭包----------
- line2 = line_config("闭包",40)
- line2() #--------------------闭包--------------------
- # 装饰器
- # 作用
- # 在函数名以及函数体不改变的前提下, 给一个函数附加一些额外代码
- # 语法
- # @装饰器
- # def 被装饰函数():
- # code
- # 案例
- # 发说说, 发图片
- # 附加
- # 身份验证 操作
- # "开放封闭"原则
- # 已经写好的代码, 尽可能不要修改
- # 如果想要新增功能, 在原先代码基础上, 单独进行扩展
- # 单一职责
- # 注意
- # 装饰器的执行时间, 是立即执行
- # 进阶
- # 装饰器叠加
- # 从上到下装饰
- # 从下到上执行
- # 对有参函数进行装饰
- # 无论什么场景, 保证函数调用参数个数一致
- # 为了通用, 可以使用不定长参数, 结合 拆包操作进行处理
- # 对有返回值的函数进行装饰
- # 无论什么场景, 保证函数返回值一致
- # 带有参数的装饰器
- # 通过@装饰器(参数)的方式, 调用这个函数, 并传递参数; 并把返回值, 再次当做装饰器进行使用
- # 先计算 @ 后面的内容, 把这个内容当做是装饰器
- def checkLogin(func):
- print("*" * 10 ) # 只在使用@装饰器运行
- def inner():
- print("登陆认证....")
- func()
- print("-" * 10) # 函数调用后才运行
- return inner
- @checkLogin # fss = checkLogin(fss)
- def fss():
- print("发说说")
- @checkLogin # fpic = checkLogin(fpic)
- def fpic():
- print("发图片")
- #下面为业务的逻辑部分,如果要想在程序中保持业务逻辑和代码不变,就需要上面的装饰符
- indexItem = 1
- if indexItem == 1 :
- fss()
- else:
- fpic()
- # 生成器
- # 生成器
- # 是一个特殊的迭代器(迭代器的抽象层级更高)
- # 所以, 拥有迭代器的特性
- # 惰性计算数据, 节省内存
- # 能够记录状态, 并通过next()函数, 访问下一个状态
- # 具备可迭代特性
- # 但是, 如果打造一个自己的迭代器, 比较复杂
- # 需要实现很多方法
- # 后续在"面向对象"编程中会进行讲解
- # 所以, 就有一个更加优雅的方式 "生成器"
- # 创建方式
- # 生成器表达式
- # 把列表推导式的[] 修改成 ()
- # (i for i in range(1, 10000000) if i % 2 == 0)
- # 生成器函数
- # 函数中包含 yield语句
- # 这个函数的执行结果就是 "生成器"
- # 产生数据的方式
- # 生成器具备可迭代特性
- # next()函数
- # 等价于
- # 生成器.__next__()
- # for in
- # send() 方法
- # send方法有一个参数,指定的是上一次被挂起的yield语句的返回值
- # 相比于.__next__()
- # 可以额外的给yield 语句 传值
- # 注意第一次调用
- # t.send(None)
- # 关闭生成器
- # g.close()
- # 后续如果继续调用, 会抛出StopIteration异常提示
- # 注意
- # 如果碰到return
- # 会直接终止, 抛出StopIteration异常提示
- # 生成器只会遍历一次
- # L = [i for i in range(1,100) if i % 2 == 0] #直接生成列表,range生成比较多的时候,浪费内存
- L = (i for i in range(1, 100) if i % 2 == 0)
- print(L) #<generator object <genexpr> at 0x03A7AC60>
- print(next(L)) #
- print(next(L)) #
- print(L.__next__()) #
- for i in L:
- print(i) # 从 8 开始,因为上面已经移动了指针
- def test():
- print("xxx")
- yield 1
- print("a")
- yield 2
- print("b")
- runing = test() # 不会打印xxx
- for i in runing:
- print(i)
- # 递归函数
- # 体现
- # 函数A内部, 继续调用函数A
- # 概念
- # 传递
- # 回归
- # 注意事项
- # 有传递, 一定要有回归
- # 否则, 就是无限的循环调用
- # 案例
- # 求一个数值的阶乘 5!= 5 * 4 * 3 * 2 * 1
- def jiecheng(n):
- if n == 1:
- return 1
- return n * jiecheng(n - 1)
- print(jiecheng(5)) #
- # 函数作用域
- # 基本概念
- # 变量的作用域
- # 变量的作用范围
- # 可操作范围
- # Python是静态作用域,也就是说在Python中,变量的作用域源于它在代码中的位置;
- # 在不同的位置, 可能有不同的命名空间
- # 命名空间
- # 是作用域的体现形式
- # 不同的具体的操作范围
- # Python-LEGB
- # L-Local
- # 函数内的命名空间
- # 作用范围: 当前整个函数体范围
- # E-Enclosing function locals
- # 外部嵌套函数的命名空间
- # 作用范围: 闭包函数
- # G-Global
- # 全局命名空间
- # 作用范围: 当前模块(文件)
- # B-Builtin
- # 内建模块命名空间
- # 作用范围: 所有模块(文件)
- # 注意
- # Python中没有块级作用域
- # 块级作用域
- # 代码块中, 比如 if while for 后的代码块
- # LEGB规则
- # 按照L -> E -> G -> B 的顺序进行查找
- # 基于命名空间的常见变量类型
- # 局部变量
- # 在一个函数内部定义的变量;
- # 作用域为函数内部
- # 查看局部变量
- # locals()
- # 全局变量
- # 在函数外部, 文件最外层定义的变量
- # 作用域为整个文件内部
- # 查看全局变量
- # globals()
- # 注意点
- # 访问原则
- # 从内到外
- # 结构规范
- # 全局变量
- # 函数定义
- # 使用
- # 修改
- # 后续代码
- # 全局变量和局部变量重名
- # 获取
- # 就近原则
- # 修改
- # global 全局变量
- # 声明
- # l -> e
- # unlocal
- # 命名
- # 全局变量
- # g_xxx
Python 函数定义和使用的更多相关文章
- Python(2)深入Python函数定义
Python学习 Part2:深入Python函数定义 在Python中,可以定义包含若干参数的函数,这里有几种可用的形式,也可以混合使用: 1. 默认参数 最常用的一种形式是为一个或多个参数指定默认 ...
- Python函数定义和使用
函数是一段可以重复多次调用的代码,通过输入的参数值,返回需要的结果.通过使用函数,可以提高代码的重复利用率.本文主要介绍Python函数的定义.调用和函数参数设置方法. 函数的定义 Python函数定 ...
- Python 函数定义以及参数传递
Python 函数定义以及参数传递1.函数定义#形如def func(args...): doSomething123以关键字def 开头,后面是函数名和参数下面是函数处理过程. 举例: def ad ...
- python函数定义
刚学用Python的时候,特别是看一些库的源码时,经常会看到func(*args, **kwargs)这样的函数定义,这个*和**让人有点费解.其实只要把函数参数定义搞清楚了,就不难理解了. 先说说函 ...
- Python学习-10.Python函数定义(二)
在Python中定义函数的时候,可以使用参数默认值的方式定义函数 例子: def welcome(who,state='is',action='talking'): print(who,state,a ...
- 9 - Python函数定义-位置参数-返回值
目录 1 函数介绍 1.1 为什么要使用函数 1.2 Python中的函数 2 函数的基本使用 3 函数的参数 3.1 参数的默认值 3.2 可变参数 3.2.1 可变位置传参 3.2.2 可变关键字 ...
- 初识python 函数(定义,传参,返回值)
python基础(二): 菜鸟教程基础知识讲解的非常全面,内容选择我认为的重点输出一遍 函数: 定义一个函数: 你可以定义一个由自己想要功能的函数,以下是简单的规则: def fun(arg): pa ...
- python 函数定义
我们可以创建一个函数来列出费氏数列 >>> def fib(n): # write Fibonacci series up to n ... """Pr ...
- Python学习 Part2:深入Python函数定义
在Python中,可以定义包含若干参数的函数,这里有几种可用的形式,也可以混合使用: 1. 默认参数 最常用的一种形式是为一个或多个参数指定默认值. >>> def ask_ok(p ...
随机推荐
- 高质量JavaScript代码
才华横溢的Stoyan Stefanov,在他写的由O’Reilly初版的新书<JavaScript Patterns>(JavaScript模式)中,我想要是为我们的读者贡献其摘要,那会 ...
- 在Windows端安装kafka 提示错误: 找不到或无法加载主类 的解决方案
在配置好kafka的server.properties文件后,cmd进入命令窗口输入命令:.\bin\windows\kafka-server-start.bat config\server.prop ...
- Jmeter - 分布式部署负载机
1. 原理图: 2.具体操作 ① 负载机 安装JDK.Jmeter[版本与Controller 调度机一致] ② 配置环境变量 ③ 负载机自定义端口号 a.进入Jmeter的bin目录,找到Jmete ...
- 下载苹果APP历史版本
1.参考教程: iOS 下载旧版本 app 或者已下架 app 方法 - 简书 https://www.jianshu.com/p/33dc8bfd4134 2.步骤总结: 下载旧版带 app 管理的 ...
- PAT 1013 Battle Over Cities(并查集)
1013. Battle Over Cities (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue It ...
- Remoting在多IP多网卡内外网环境下的问题
Remoting服务器端如果服务器有多块网卡,多个IP地址的情况下会出现客户端callback失败的问题,debug以后发现客户端会callback到服务器端另外一个IP地址(例如外网地址,而不是内网 ...
- centos7.3下使用yum 安装pip
centos下安装pip时失败: No package pip available.Error: Nothing to do 解决方法: 需要先安装扩展源EPEL. EPEL(http://fedor ...
- Access导入Sql 2008 R2 错误 0xc020801c
在选择数据源界面: 数据源:Microsoft Access 文件名:选择要导入的文件 用户名:admin 密码:(空的) 猛击”高级“按钮 切到”高级“选项卡,访问权限设为 ReadWrite,去掉 ...
- OC处理.Net Json时间格式
通过服务器收到的json时间格式是/Date(xxxxxxxxxxxxx+xxxx)/,其中前半部分是自1970年的millionSecs,后半部是时区,我们需要对齐进行转换. 解决方式有两种,第一种 ...
- 品友推广的投放原理 RTB:Real Time Bidding(实时竞价) DSP:Demand-Side Platform(需求方平台) 广告交易平台:AD Exchange
总结: 1.实时竞价 0.1秒出价各个广告主出价,投放价高者: RTB(Real Time Bidding)实时竞价,是一种利用第三方技术在数以百万计的网站或移动端针对每一个用户展示行为进行评估以及出 ...