一、函数的定义(函数一定是先定义,后引用)

函数是完成特定功能的代码块。

def:声明函数的关键字

fun:函数变量名

():参数列表,参数可以是0-n个,但是()不能丢

函数体:实现功能的具体代码

return:函数的返回值

代码示例:

def fn():
    print("In the function1")
    return 'good'
print(fn())

def fn1(money):
    print('你付了%s元钱' % money)
    print('函数的一行代码')
    print('函数的二行代码')
    return '冰红茶'
# 直接打印fn1,只能看到函数存放代码的地址
print(fn1,id(fn1)) #<function fn1 at 0x00000098D1DF9BF8> 656356121592
#使用函数名调用
fn1(10)
# 函数的返回值也称之为函数值,就是函数执行结束后的结果
# 可以用变量接收;可以直接打印;可以直接使用
print('---------------------')
msg = fn1(10)
print(msg)
print('>>>>',fn1(10)+'好喝')

案例:函数实现文件复制

# 源文件和复制的文件都自由指定
def copy_file(source,target):
    '''
    :param source: 源文件
    :param target: 复制后的文件
    :return:
    '''
    with open(source, 'rb') as r, open(target, 'wb') as w:
        for line in r:
            w.write(line)

二、函数的分类

1、按函数体分为空函数和非空函数

空函数:项目之初,明确项目有哪些功能,但是不清楚具体的功能体,可以先用pass填充

def calculate():
    pass

非空函数,用函数体

def add_num(n1, n2):
    ''' 函数的注释
    :param n1: 第一个数
    :param n2: 第二个数
    :return: 两个数之和
    '''
    return n1 + n2
res = add_num(10,20)
print(res)

2、按参数列表分为有参和无参函数

无参函数:

def test1():
    print("in the test1")

def test2():
    print("in the test2")
    return 0

def test3():
    print("in the test3")
    return 1,'hello',['shj','xxn'],{'name':'shj'}

x = test1()
y = test2()
z = test3()
print(x)  #None
print(y)  #0
print(z)  #元组(1, 'hello', ['shj', 'xxn'], {'name': 'shj'})

有参函数:

def test4(x,y):
    print(x)
    print(y)
test4(2,1)  位置参数调用,与形参一一对应,等价于test4(y=1,x=2)
test4(y=1,x=2) 关键字调用,不需要按形参定义的顺序给值
位置参数一定不能放在关键字参数的后面

参数详解:

# 默认参数:调用函数的时候,默认参数非必须传递
# 用途:
#     1、默认安装与自定义安装
#     2、给数据库默认端口等
def test5(x,y=2):
    print(x)
    print(y)
test5(1)
test5(1,5)  #定义了默认参数,如果不给值就按默认,给值就打印所给的值

# 参数组:针对实参不固定,需要多个形参的情况
# 第一种
def test6(*args):   #args相当于形参名
    print(args)
test6(1,2,3,4,5)
test6(*[1,2,3,4,5]) #args=tuple([1,2,3,4,5]),元组相当于只读列表

# 第二种
# *args:接收n个位置参数,转换成元组的形式
def test7(x,*args):
    print(x)
    print(args)
test7(1,2,3,4,5,6,7)

# 第三种,接收字典
# **kwargs:接收n个关键字参数,转换成字典的形式
def test8(**kwargs):
    print(kwargs)
    print(kwargs['name'])
    print(kwargs['age'])
    print(kwargs['sex'])
test8(name='shj',age=23,sex='男') #关键字参数转为字典:{'age': 23, 'sex': '男', 'name': 'shj'}
test8(**{'name':"shj",'age':23,'sex':'男'})

# 跟位置参数结合
def test9(name,**kwargs):
    print(name)
    print(kwargs)
#test9('shj','aaa')  报错,必须加关键字参数才行
test9('shj',age=22,sex='man')   #正确写法

# 跟默认参数结合(定义时,参数组一定放最后)
def test9(name,age=23,**kwargs):
    print(name)
    print(age)
    print(kwargs)
test9('shj',sex='man',hobby='街舞',age=18)  #关键字参数赋值
test9('shj',18,sex='man',hobby='街舞')  #跟上面等价,这里是位置参数赋值

def test10(name,age=23,*args,**kwargs):
    print(name)
    print(age)
    print(args)
    print(kwargs)
test10('shj',age=18,sex='man',hobby='街舞')

3、按返回值分类:

'''
1. 没有return的函数
2. 空return
# 空返回

3. return一个值
4. return多个值
# 值返回
'''
# 空返回
def fun():
    print('in the fun')
res = fun()
print('没有return关键字的返回值:%s'% res) #None

def fun2():
    print('fun2 run!!!')
    return
res = fun2()
print('空return关键字的返回值:%s' % res)  # None

# 无return和空return函数的区别
# 空return:可以根据具体情况主动退出函数(像break结束循环一样)
def fn3(msg):
    print('fn3 第一行逻辑')
    # msg信息不正常:'' | None
    if msg == '' or msg is None:
        # 结束函数
        return
    print('msg信息正常: %s' % msg)
msg = input('msg: ')
fn3(msg)

# 值返回
# 一个值的返回
def add_num(n1,n2):
    return n1 + n2
print(add_num(1,2))

def computed(n1, n2):
    # 返回四则运算的结果
    r1 = n1 + n2
    r2 = n1 - n2
    r3 = n1 / n2
    r4 = n1 * n2
    return [r1, r2, r3, r4]

a, b, c, d = computed(50, 25)
print(a, b, c, d)

# 多个值的返回: 本质就是返回装有多个值的元组
def computed_sup(n1, n2):
    # 返回四则运算的结果
    r1 = n1 + n2
    r2 = n1 - n2
    r3 = n1 // n2
    r4 = n1 ** n2
    return r1, r2, r3, r4

a, b, c, d = computed_sup(50, 25)
print(a, b, c, d)

res = computed_sup(50, 25)  # 得到的是装有所有结果的元组
print(res)

三、函数的嵌套调用:在一个函数体调用另一个函数

# 在解释过程中,不执行函数体,在函数被调用时,函数体才被执行

def fn1():
    print('fn1 run')
    fn2()

def fn2():
    print('fn2 run')
    fn3()

def fn3():
    print('fn3 run')

# 注:在fn1中调用了fn2,所以调用fn1的逻辑应该在fn2定义之后
fn1()

嵌套函数案例:实现比较数字的最大值

# 两个数
def max_2(n1,n2):
    if n1 > n2:
        return n1
    return n2
print(max_2(2,3))
# 三个数
def max_3(n1,n2,n3):
    m = max_2(n1,n2)
    return max_2(m,n3)
print(max_3(1,2,3))
# 四个数
def max_4(n1,n2,n3,n4):
    m2 = max_3(n1,n2,n3)
    return max_2(m2,n4)
print(max_4(1,2,3,4))

四、函数对象

def fn():
    num = 10
    print("fun function run")
print(fn)  # <function fn at 0x000000E0B324C1E0>

函数名存放的就是函数的地址,所以函数名也是对象,称之为函数对象

函数的用法:

1、可以直接被引用

def fn():
    num = 10
    print("fun function run")
print(fn)  # <function fn at 0x000000E0B324C1E0>

func = fn
print(func)  # <function fn at 0x000000E0B324C1E0>
fn()    # fun function run
func()  # fun function run

2、可以当作函数参数传递

def add(a,b):
    return a + b

def subtract(a,b):
    return a-b

def multiply(a,b):
    return a*b

def divide(a,b):
    return a/b

#计算:通过该函数可以完成任意两个数的四则运算
def computed(fn,n1,n2):
    # fn代表四则运算的任一种
    # res为运算结果
    res = fn(n1,n2)
    print(res)

# 完成两个数的某一运算,拿到结果
while True:
    cmd = ("cmd:")
    if cmd == 'add':
        result = computed(add,100,20)
    elif cmd == 'substract':
        result = computed(substract,100,20)
    else:
        print("Invalid input")
        break
    print(result)

3、可以作为容器类型的元素

def add(a, b):
    return a + b
def low(a, b):
    return a - b
def jump(a, b):
    return a * b
def full(a, b):
    return a / b
def quyu(a, b):
    return a % b
def computed(fn, n1, n2):
    res = fn(n1, n2)
    return res
method_map = {
    'add': add,
    'low': low,
    'jump': jump,
    'full': full,
    'quyu': quyu,
}
while True:
    cmd = ("cmd:")
    # 用户输入的指令只要有对应关系,就会自动去走对应的计算方法
    # 这样外界就不用去关心到底有哪些计算方法
    if cmd in method_map:
        cp_fn = method[cmd]  #拿到计算方法
        result = computed(cp_fn,100,20)  #通过计算得到结果
        print(result)
    else:
        print("输入有误,退出")
        break

4、可以作为函数的返回值

def add(a, b):
    return a + b
def low(a, b):
    return a - b
def jump(a, b):
    return a * b
def full(a, b):
    return a / b
def quyu(a, b):
    return a % b
def computed(fn, n1, n2):
    res = fn(n1, n2)
    return res
method_map = {
    'add': add,
    'low': low,
    'jump': jump,
    'full': full,
    'quyu': quyu,
}
# 根据指令获取计算方法
def get_cp_fn(cmd):
    if cmd in method_map:
        return method_map[cmd]
    return add  # 输入有误用默认方法处理

while True:
    cmd = input('cmd: ')
    if cmd == 'quit':
        break
    cp_fn = get_cp_fn(cmd)
    result = computed(cp_fn, 100, 20)
    print(result)

五、名称空间,作用域

名称空间:存放名字与内存空间地址对应关系的容器

作用:解决由于名字有限,导致名字重复发送冲突的问题

三种名称空间:

1、Built-in:内置名称空间;系统级,一个;随解释器执行而产生,解释器停止而销毁

2、Global:全局名称空间;文件级,多个;随所属文件加载而产生,文件运行完毕而销毁

3、Local:局部名称空间;函数级,多个;随所属函数执行而产生,函数执行完毕而销毁

注:

del  函数名:可以移除查找最近的名字与内存空间地址的对应关系

加载顺序:Built-in > Global > Local

print(len('abc'))

len = len('abcdef')
print(len)

del len

# del len

print(len('000111222'))
'''
[
    # ['len': 100001]  # 保存长度的变量
    ['len': 200001]  # 计算长度的函数
]
'''

def fn1():
    len = 10
    print(len)

def fn2():
    len = 20
    print(len)

fn1()
fn2()

global关键字:

global关键字可以将local的名字提升为global的名字

一个文件中的global名字就是一个,所以函数内部外部使用的名字都是一个

def fn():
    global num
    num = 20
    print(num)
fn()    注:一定要调用函数,才能产生名字,并提升为全局变量
print(num)

作用域:名字起作用的范围

作用:解决同名共存问题

# 四种作用域
# Built-in:内置作用域,所有文件所有函数
# Global:全局作用域,当前文件所有函数
# Enclosing:嵌套作用域,当前函数与当前函数的内部函数
# Local:局部作用域,当前函数
len = 10
def outer():
    len = 20  # 外层函数的局部变量:Enclosing - 嵌套作用域
    def inner():
        len = 30
        print('1:', len)  # inner -> outer -> global -> built-in
    inner()
    print('2:', len)  # outer -> global -> built-in
outer()
print('3:', len)  # global -> built-in

del len
print('4:', len)  # built-in

LEGB

不同作用域之间名字不冲突,以达到名字的重用

查找顺序:Local -> Enclosing -> Global -> Built-in -> 抛异常

六、闭包

闭包就是嵌套函数(格式稍作改良)

inner可以使用outer的局部变量:可以将inner定义在outer中

inner的调用还是在外部,inner函数对象能被outer返回

# 将内部函数对象作为外部函数的返回值:

1、可以使用局部变量

2、不改变函数的调用位置

def outer():
    num = 10
    def inner():  # 闭包:定义在函数内部的函数称之为闭包
        print(num)
    return inner
fn = outer()   # fn = inner
fn()

闭包案例:

# 案例一:外部函数可以为闭包传递参数 (了解)
"""
import time
def download():
    print('开始下载')
    time.sleep(2)
    print('下载完成')
    data = "下载得到的数据"
    outer(data)
# 为闭包传参
def outer(data):
    def inner():
        # 保存,播放,删除等操作
        print("闭包打印:", data)
    inner()
download()
"""

# 案例二:延迟执行
import requests

'''
# get_html一执行就获取页面
def get_html(url):
    html = requests.get(url)
    print(html.text)
get_html('https://www.baidu.com')
get_html('https://www.python.org')
get_html('https://www.sina.com.cn')
get_html('https://www.baidu.com')
'''

def outer(url):
    def get_html():
        html = requests.get(url)
        print(html.text)
    return get_html
# 先预定义多个爬虫方法,爬页面操作并未执行
baidu = outer('https://www.baidu.com')
python = outer('https://www.python.org')
sina = outer('https://www.sina.com.cn')
# 什么时候想爬什么页面就调用指定页面的爬虫方法
baidu()
sina()
baidu()

python基础——7(函数)的更多相关文章

  1. python基础——匿名函数

    python基础——匿名函数 当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便.  在Python中,对匿名函数提供了有限支持.还是以map()函数为例,计算f(x)=x2时 ...

  2. python基础——返回函数

    python基础——返回函数 函数作为返回值 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回.  我们来实现一个可变参数的求和.通常情况下,求和的函数是这样定义的: def calc_ ...

  3. python基础——sorted()函数

    python基础——sorted()函数 排序算法 排序也是在程序中经常用到的算法.无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小.如果是数字,我们可以直接比较,但如果是字符串或者两个d ...

  4. python基础——filter函数

    python基础——filter函数 Python内建的filter()函数用于过滤序列. 和map()类似,filter()也接收一个函数和一个序列.和map()不同的是,filter()把传入的函 ...

  5. python基础——匿名函数及递归函数

    python基础--匿名函数及递归函数 1 匿名函数语法 匿名函数lambda x: x * x实际上就是: def f(x): return x * x 关键字lambda表示匿名函数,冒号前面的x ...

  6. 八. Python基础(8)--函数

    八. Python基础(8)--函数 1 ● 函数返回布尔值 注意, 自定义的函数也可以是用来作逻辑判断的, 例如内置的startswith()等函数. def check_len(x):     ' ...

  7. python基础之函数详解

    Python基础之函数详解 目录 Python基础之函数详解 一.函数的定义 二.函数的调用 三.函数返回值 四.函数的参数 4.1 位置参数 4.2 关键字参数 实参:位置实参和关键字参数的混合使用 ...

  8. Python学习笔记(一)python基础与函数

    1.python基础 1.1输入与输出 输出 用print加上字符串,就可以打印指定的文字或数字 >>> print 'hello, world' hello, world > ...

  9. Day3 - Python基础3 函数、递归、内置函数

    Python之路,Day3 - Python基础3   本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8. ...

  10. Python基础__函数

    本节将进入函数的介绍,函数是Python基础中最精彩的部分之一,接下来将对函数做详细介绍.函数 函数就是对代码进行一个封装.把实现某一功能的代码进行封装到一起.下次需要使用时不需要进行编写代码直接调用 ...

随机推荐

  1. Hexo - 修改永久链接的默认格式

    Hexo的永久链接的默认格式是 :year/:month/:day/:title/,比如访问站点下某一篇文章时,其路径是 2018/04/12/xxxx/,如果我们的文章标题是中文的,那么该路径就会出 ...

  2. C/C++ 动态库so的生成与调用

    1. Linux-(C/C++)动态链接库生成以及使用(libxxx.so) 2. C++文件如何在linux下生成动态库So,以及如何使用这个动态库 3. c++ 发布动态.so 简记1. 编译生成 ...

  3. 如何从GAC中拷贝文件出来 C:\Windows\assembly

    方法一:命令行拷贝. 开始--运行--cmd--"cd C:\WINDOWS\assembly".一般自己开发的dll都在GAC_MSIL这个文件夹下面,按照我如下的截图就可以拷贝 ...

  4. JVM线程与Linux内核线程的映射[转]

    Linux从内核2.6开始使用NPTL (Native POSIX Thread Library)支持,但这时线程本质上还轻量级进程. Java里的线程是由JVM来管理的,它如何对应到操作系统的线程是 ...

  5. UVa OJ 458

     The Decoder  Write a complete program that will correctly decode a set of characters into a valid m ...

  6. flex和box兼容性写法

    display: -webkit-box; /* Chrome 4+, Safari 3.1, iOS Safari 3.2+ */ display: -moz-box; /* Firefox 17- ...

  7. String 截取字符串#中间的文本

    通过正则实现: String regex = "#([^#]+)#"; @Test public void test() { String text = "#中俄建交七十 ...

  8. mysql use index() 优化查询

    mysql use index() 优化查询 FORCE INDEX/IGNORE INDEX 的语法: SELECT *** FROM TABLE [{USE|IGNORE|FORCE} INDEX ...

  9. (转)@Autowire注解与自动装配

    http://blog.csdn.net/yerenyuan_pku/article/details/52860713 前面我们已经学会使用@Resource注解注入属性,并且我们还编码剖析了@Res ...

  10. swfit:运算符重载 Operator Methods

    Operator Methods Classes and structures can provide their own implementations of existing operators. ...