python 基础(四) 函数

函数

一、什么是函数?

函数是可以实现一些特定功能的 小方法 或者是小程序

优点:

  1. 提高 了代码的后期维护

  2. 增加了代码的重复使用率

  3. 减少了代码量 提高了代码可读性

二、函数的定义

使用 def关键+函数名([参数]):

​ 函数体

函数的命名规则:

遵循变量的命名规则

三、函数名

(1) 函数的调用

函数名([参数])

(2) 函数名区分大小写

(3) 只能在函数定义的下方来调用

(4) 函数不能重名 会被覆盖

四、函数的参数问题

(1) 形参(形式上的参数)

​ 在函数定义处的括号里的变量 称之为 形参

注意:

  1. 函数在定义的时候 存在形参 且没有默认值 则在调用时 必须传实参

    a(1,2) #此刻1和2称之为实参

  2. 函数在定义时 如果没有 形参 则不能传实参

  3. 传入的实参个数 不能大于形参个数

  4. 实参和形参对应

  5. 实参的参数 和 形参一一对应 从左倒右依次赋值

(2) 形参默认值

在函数定义处 给当前形参赋一个默认值 则在调用时 当前有默认值的形参 可传可不传

如果传实参 则当前形参的值为实参的值 否则值为默认值

实例:

def defaultArg(a,b=2):
    print(a,b)
defaultArg(1) #1,2  
defaultArg(1,3) #1 3
 

错误写法(没有遵循默认值的规则)

def defaultArg(a=1,b): 
    print(a,b)
defaultArg(1,2)
 

在给形参默认值的时候 有默认值放在最后面

(3) 关键字参数

可以做到给指定的形参赋值

def demo(a,b,c):
# def demo(a,b,c):
    print(a,b,c)
# demo(1,2,3)
# demo(c=1,b=2,a=3) #关键字参数 关键字为 形参名
# demo(1,b=2,c=3) #关键字参数  第一个值默认传递给a 从左到右
# demo(a=1,2,c=3) #follows keyword argument
# demo(1,b=2,a=3) #关键字参数 当前参数a 赋值2次
 

五、函数的返回值

(1) 没有返回值的情况

实例:

a = 1
def func():
    a = 1+2
print(func())#打印函数调用处   None
 

(2) 有返回值的情况

使用关键字 return

使用 return 可以方便我们对函数值的操作(你能够拿到这个值 并对他操作)

实例:

a = 1
def func():
    a = 1+2
    return a
print(func())#将值返回给函数调用处   3
 

注意事项:

在函数体内使用return时 return下面的代码将不会在执行

(3) 函数返回多个值得情况

实例:

def mySum(a=0,b=0):
    Sum = a + b
    return Sum,a,b  #将a,b,Sum全部返回     以元组的方式
    return (Sum,a,b)  #将a,b,Sum全部返回   以元组的方式
    return [Sum,a,b]  #将a,b,Sum全部返回   以列表的方式
 

六、不定长参数

概念:也就是传入得参数得个数 不确定

(1) *args 以元组接收不确定实参得值

def demo(*args): #以元组得形式 接受不确定参数得个数
    print(args)
demo(1,2,3)  #(1,2,3)
demo() #空元组 ()
 

*args和普通形参的搭配使用

A: *args,a
def demo(a,b,*args):
    print(args,a)
 
demo(1,2) #1 2 ()
demo(1,2,3,4,5) #1 2 (3, 4, 5)
demo('x') #('x',) 1
demo('x','y') #('x', 'y') 1
 
B: a,*args
def demo(*args,a=1):
    print(args,a)
demo('x','y',a=2) #('x', 'y') 2
 

(2) **kwargs 以字典得形式接收不确定参数

其中关键字为 字典得键 值为字典得值

def func(**kwargs):
    print(kwargs)
func(a=1,b=2,c=3)
func(a=1,a=2) #SyntaxError: keyword argument repeated
 

注意:

关键字 不能重复

SyntaxError: keyword argument repeated

(3) 在调用处的 **的使用

def func(**kwargs):
    print(kwargs) #{'a':'a','b':'b'}
myDict = {'a':'a','b':'b'}
func(**myDict) #在调用处    将字典 转换为关键字参数
 

(4) 组合使用

普通参数,*args,**kwargs

def demo(x,*args,**kwargs):
    print('x',x,'*args',args,'**kwargs',kwargs)
demo(1,2,3,4,a=1,y=2)
#demo(x=1,2,3,4,a=1,y=2) #x 1 *args (2, 3, 4) **kwargs {'a': 1, 'y': 2}
 

七、递归

概念:自己调用自己

实现累加得普通操作

def mySum(num):
    Sum = 0
    for i in range(1,num+1):
        # print(i)
        Sum += i
    print(Sum)
mySum(5)
 

使用递归实现一个数得累加

def mySum(num):
    if num == 0:
        return False
        # return #int' and 'NoneType'
    return num + mySum(num-1)
 

运行过程

 
mySum(5)
5+mySum(4)
5+(4+mySum(3))
5+(4+(3+mySum(2)))
5+(4+(3+(2+mySum(1))))
5+(4+(3+(2+(1+mySum(0)))))
5+(4+(3+(2+(1+False))))
5+(4+(3+(2+1))))
5+(4+(3+3)))
5+(4+6)
5+10
15
 

证明递归原路返回

def demo(n):
    print(n)
    if n>=0:
        demo(n-1)
    print(n)
demo(3)
 

上面代码得分解

def a(n):
    print(n) #4
    b(n-1) #3
    print(n) #4
def b(n): #3
    print(n) #3
    c(n-1) #2
    print(n) #3
def c(n): #2
    print(n) #2
    d(n-1)
    print(n) #2
def d(n): #1
    print(n) #1
    print(n) #1
a(4)
 

1.定义一个函数 模仿pop

传入一个列表 将最后得值弹出并返回

def myPop(List):
    val = List[-1]
    del List[-1]
    return val
myList = [1,2,3,4]
print(myPop(myList))
 

2.自定义一个函数 实现 字典得键值交换

def dictChange(Dict):
    newDict = {}
    for i in Dict:
        # print(i)
        newDict[Dict[i]] = i
    return newDict
myDict = {'name':'zs','age':'18'}
print(dictChange(myDict))
 

3.实现一个 类似 popitem()的操作

def myPopitem(Dict):
    keys = list(Dict.keys())[-1]
    val = Dict[keys]
    del Dict[keys]
    return keys,val
myDict = {'a':'1','b':'2'}
print(myPopitem(myDict))
print(myDict)
 

八、可变类型与不可变类型

不可变类型:如整数,字符串,元组...

可变类型: 字典,列表...

不可变类型实例:

def change(var):
    # print(var)
    # print(id(var))
    var = 2
Int = 1
change(Int)
# print(id(Int))
print(Int)
 

有值2 Int变量执行了2 在传递给change函数得时候 按照传值得方式赋值了变量Int Int和var都执行了 2(int对象)

在 var = 2 得时候 创建了一个新的变量

可变类型实例:

def change(List):
    List.append('a')
myList = [1,2,3]
change(myList)
print(myList)
 

理解的代码

a = [1,2,3]
b = a
b = 2
# print(a)
# print(b)
# b.append('a')
print(b)
print(a)s
 

九、变量得作用域

在python中 程序得变量 并不是在哪个位置都可以访问得倒 访问权限 取决于变量得定义位置

  • L 局部作用域

  • E 闭包函数外得函数中

  • G 全局作用域

  • B 内建作用域

(1) 在函数外部声明得变量 称之为 全局变量 函数内外都能够获取
num = 1
def func():
    print(num)
  
func()
 

函数内可以获取到全局变量 但是不能进行修改

(2) 在函数内部声明得变量称之为局部变量 只能在函数内部使用 函数外部获取不到
def func():
    num = 2
    print(num)
func()
print(num)
 

在函数内部想用某个变量 那么会先在函数内部查找 如果内部不存在 则取外部查找

(3) global 声明函数内外使用同一个变量
num = 1
def func():
    global num
    num = 2
func()
print(num)
 
(4) 将局部变量 声明为全局变量(函数内外都可以获取到)
def func():
    global x #将局部变量 声明为全局变量
    x = 1
func()
print(x)
 
(5) nonlocal 当函数发生嵌套时(将上层的变量于当前声明内外使用同一个)
num = 1
Str = 'string'
#1 当函数放生嵌套的时候  在使用变量时 去上一层查找
def a():
    # nonlocal num
    # num = 2
    Str = '新的字符串'
    def b():
        # nonlocal num #将外层和当的变量声明统一使用同一个
        # num = 3
        def c():
            # global num
            nonlocal num
            num = 'num'
            print(num)
            # print(Str)
        c()
        print(num)
    b()
    print(num)
a()
 

如果函数上层没有要查找的变量 则去上上层... 直到查到为止

在函数嵌套时 里层函数使用global时 会将全局变量声明使用

是否会引入新的作用域

  1. 在python中 只有模块(module),类(class),函数 会引入新的作用域

  2. if/else try/except for/while 是不会引入新的作用域 也就是说 这些语句内定义的变量 外部也能够访问

十、lambda表达式(匿名函数)

定义: lambda

变量名 = lambda [参数]:函数体

注意:

  1. lambda 只是一个表达式 函数体比def简单很多

  2. lambda 是表达式 不是代码块 只能在lambda中封装有限的逻辑

  3. 调用和函数一样 变量名([参数])

实例:

#第一种方式
func = lambda a,b:a+b  #将值进行返回
func = lambda a,b:print(a+b)  #将值进行输出
#第二种方式 定义并调用
print((lambda a,b:a+b)(1,2))
#第三种 给默认值
func = lambda a=1,b=1:a+b
print(func())
#第四种 没有形参的情况
a = 1
func = lambda :a
print(func())
#第五种 嵌套
func = lambda :(lambda :print('我是嵌套的表达式'))()
 

十一、装饰器

概念: 在代码运行期间 动态的添加功能 称之为装饰器

步骤1

def demo(arg):
    print('我是demo函数')
    # print(arg)
    # func()
    arg()
def func():
    print('我是func函数')
# demo('abc')
demo(func)
 

步骤2

def demo(arg):
    def inner():
        print('当前时间为')
        return arg()
    return inner
def func():
    print('2018/4/5')
def func2():
    print('2018-4-5')
func2 = demo(func2)
func2()
func = demo(func)
func()
 

步骤3

#demo函数 是一个 实现主体功能的函数
def demo(arg):
    def inner(age): #根据 age判断年龄段
        Str = ''
        if age<=10:
            Str = '儿童'
        elif age<=20:
            Str = '少年'
        elif age<=30:
            Str = '青年'
        elif age<=50:
            Str = '中年'
        else:
            Str = '老年'
        return arg(Str)
    return inner
#自己有需求 要添加实现的函数
def func(person):
    print('你已经步入了{}'.format(person))
func = demo(func)
func(60)
 

步骤4

import functools
#demo函数 是一个 实现主体功能的函数
def demo(arg):
    @functools.wraps(arg) #将inner复制给func
    def inner(age): #根据 age判断年龄段
        pass
    ...
#自己有需求 要添加实现的函数
@demo #==  func = demo(func)
def func(person):
    print('你已经步入了{}'.format(person))
 
给装饰器传参数
import functools
def demo(text):
    def inner(arg):
        @functools.wraps(arg)
        def decorator(*args,**kwargs):
            print(text)
            return arg(*args,**kwargs)
        return decorator
    return inner
@demo('现在的时间为') #demo('现在的时间为')(time)
def time(*args,**kwargs):
    print('2018/4/25',args)
 

十二、包和模块

模块(Module): 就是python中的一个 py文件 其中定义的所有 的变量和函数 都属于当前的py文件 Module对于所有函数而言 相当于一个 全局的命名空间(namespace) 而每一个函数又有自己的局部命名空间

包(Package): 所谓的包 就是 一堆module的集合 也就是一堆py文件 包文件总 必须有一个__init__.py文件 作为当前包的初始化

__name__

判断当前文件 是在主文件执行 还是在其他文件导入执行的

在主文件name的值为 main 被其它文件导入 name的值为他自己模块的名称

Module:

里面就是一堆的类,函数,变量

a.py

 
age = 10
def demo():
    return '你调用a.py中的demo函数了'
if __name__ == '__main__':
    print(demo())
 

Package:

目录结构:

package

----> __init__.py

----> func.py 包含某些功能的py文件

-----> ...py

包或者模块的导入

from 包名.模块名 import 属性或者函数

from package.a import demo 导入一个 
from package.a import demo,age 导入多个
from package.a import * 导入所有
使用
print(demo())
print(age)
 

from 包名 import 模块名

from package import a   package导入a模块
 

import 包.模块名/模块名

import 包.模块名/模块名 as 别名

import package.a
print(package.a.age)
import package.a as t
print(t.age)
 

包中的初始化操作

__init__.py 通常做一个包被导入时 进行初始化的操作 可以将其他模块module 中的变量,函数 进行导入 在外部导入当前包的时候 不需要指定包下的模块名 而是直接 from 包名 import 函数/变量

实例

package->__init__.py

from package.a import demo
from package.a import *
from package.b import func
from .a import *
def abc():
    print('走我了')
 

在外部的test.py中进行导入使用

from package import demo,func,abc
from package import *  #导入所有
print(demo())
print(func())
abc()
 
原文地址:https://www.cnblogs.com/gugubeng/p/9715173.html