python深入了解函数

一、偏函数【了解】

默认参数:可以降低函数调用的难度

偏函数:对函数参数做一些控制的函数

注意:偏函数不需要自定义,直接使用【系统函数】

代码演示:

# int() 默认将其他数据类型转换为整型(10进制)
print(int("123"))  # 123

# int()  函数还提供了第二个参数 base控制转换为几进制
print(int("123",base = 8))   # 83 (8进制数)
print(int("110",base = 2))   # 6

import functools  # 引入functools模块
# 系统提供了 functools.partial 可以创建一个偏函数
int2 = functools.partial(int,base = 8)
print(int2("123"))    # 83

'''
偏函数主要用于内置函数,当内置函数不能满足我们的一些需求的时候,我们可以在这个内置函数的基础上生成一个新的函数(偏函数),两个函数可以实现不同的需求.
'''

二、闭包【掌握】

如果在一个函数的内部定义另外一个函数,外部的函数叫做外函数,内部的函数叫做内函数

如果在一个外部函数中定义一个内部函数,并且外部函数的返回值是内部函数,就构成了一个闭包,则这个内部函数就被称为闭包【closure】

实现函数闭包的条件:

1.必须是函数嵌套函数

2.内部函数必须引用一个定义在闭合范围内的外部函数的变量,----内部函数引用外部变量

3.外部函数必须返回内部的函数

代码演示:

# 闭包: 如果在一个外部函数中定义一个内部函数,并且外部函数的返回值是内部函数,就构成了一个闭包,则这个内部函数就被称为闭包【closure】

# 最简单的闭包
# 外部函数
def outer():
    # 内部函数
    def inner():
        print("lala")
    return inner  # 将内部函数返回
fn = outer()    # fn =====> inner函数
fn()    # 相当于调用了inner函数   输出 lala


# 内部函数使用外部函数的变量
def outer1(b):
    a = 10
    def inner1():
        # 内部函数可以使用外部函数的变量
        print(a + b)
    return inner1
fun1 = outer1(12)
fun1()

'''
注意:
    1.当闭包执行完毕后,仍然能够保存住当前的运行环境
    2.闭包可以根据外部作用域的局部变量得到不同的效果,类似于配置功能,类似于我们可以通过修改外部变量,闭包根据变量的改变实现不同的功能.
    应用场景: 装饰器
'''

三、变量的作用域

1.出现的原因

变量的作用域:变量可以被使用【被访问】的范围

程序中的变量并不是在任意的语句中都可以被访问,访问权限取决于这个变量被定义在哪个位置

在python中 分支语句 if..else if.. 和 循环for 等 是不存在变量作用域问题的.

if 5 > 4:
    a = 11
print(a)

for i in range(10):
    b = 32
print(b)
# 在 分支结构中if.. if..esle  和 循环中for in 不存在作用域的问题.在他们的外面可以直接访问里面定义的变量.

def fn():
    c = 99
# print(c)  # name 'c' is not defined

2.作用范围划分

局部作用域:L【Local】

函数作用域:E【Enclosing】 将变量定义在闭包外的函数中

全局作用域:G【Global】

內建作用域:B【Built-in】

代码演示:

def fn():
    c = 99
# print(c)  # name 'c' is not defined
1.函数内部定义的变量在函数外部不能访问.

# 全局作用域:
num1 = 12    # 全局作用域,在函数内部和外部可以直接访问
def test():
    num2 = 87  # 函数作用域
    print(num1)
    # print(num3)   # name 'num3' is not defined
    def inner():
        num3 = 55   # 局部作用域
        # 在内部函数中,可以访问全局作用域\函数作用域\局部作用域的变量
        print(num1,num2,num3)
    return inner
test()
print(num1)
# print(num2)

fn = test()
fn()

n = int("28")   # builins 内置函数在调用的时候的作用域,这是python解释器自己定义的.

总结:
    1. 在 分支结构中if.. if..esle  和 循环中for in 不存在作用域的问题.在他们的外面可以直接访问里面定义的变量.
    2.作用域主要体现在函数中, 函数内部定义的变量在函数外部不能访问.
    3.函数内部可以访问函数外部的变量.

3.全局变量和局部变量【掌握】

全局变量:将变量定义在函数的外面

局部变量:将变量定义在函数的内部

注意:局部变量只能在其被声明的当前函数中使用,而全局变量可以在整个程序中使用

5.global和nonlocal关键字的使用【掌握】

使用场景:当内部作用域【局部作用域,函数作用域】想要修改全局变量的作用域的时候

1.global

代码演示:

num = 11
def test():
    num = 78
    print(num)
test()    # 78
print(num)  # 11

# 若想在函数的内部,对全局变量进行修改,需要使用global关键字
num1 = 11
def test1():
    # 通过global关键字将函数内部声明变量变为了全局变量
    global num1
    num1 = 75
    print(num1)
test1()   # 75
print(num1)  # 75

2.nonlocal

代码演示:

# nolocal 关键字主要用于闭包函数中  

# nolocal关键字用于闭包函数中
x = 15  # 全局变量
def outer():
    x = 19
    def inner():
        # x = 23
        # global x   # 使用的是 x = 15
        nonlocal x  # 这时候使用的变量是 x = 19
        x += 1
        print("inner:",x)
    return inner

# 闭包会保存住当前的运行环境
test = outer()
test()   # 20
test()   # 21
test()   # 22

num = 11
def demo():
    print(num)
demo()   # 11
demo()   # 11
demo()   # 11

四、列表生成式和生成器【掌握】

1.列表生成式/列表推导式

list comprehension

系统内置的用于创建list的方式

range(start,end,step)缺点:生成的列表一般情况下都是等差数列

代码演示:

# 最基本的列表
# 1.生成1-10之间所有的数字
list1 = list(range(1,11))
print(list1)

# 需求:通过程序的方式生成列表 [1,4,9,16,25]
#第一种方法:使用原始的方式生成
list2 = []
for i in range(1,6):
    list2.append(i ** 2)
print(list2)

# 第二种方法:使用列表生成式
list3 = [i**2 for i in range(1,6)]
print(list3)   # [1, 4, 9, 16, 25]

# 使用列表生成式 生成1-10之间所有的奇数
list4 = [i for i in range(1,11) if i % 2 == 1]
print(list4)

# 使用列表生成式 生成1-10之间所有的奇数并且能被3整除的数字
list5 = [i for i in range(1,11) if i % 2 == 1 and i % 3 == 0]
print(list5)

# 列表生成式中使用双重循环
list6 = [i + j for i in "xyz" for j in "987"]
print(list6)

# 字典生成式:(了解)
dict1 = {i:i*i for i in range(1,6)}
print(dict1)

# 集合生成式:(了解)
set1 = {i*i for i in range(1,6)}
print(set1)

2.生成器

generator

next()

代码演示:

定义生成器: 只需要把列表生成式的[] 换成() 即可
g = (i ** 2 for i in range(1,10))
print(g)
print(type(g))  #<class 'generator'>
# 生成器得到的数据不能直接输出,要想访问里面的数据,必须使用next() 进行遍历,每调用一次next() 就会输出一个数据
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
# 当通过next() 将生成器中的数据遍历完毕以后,接着调用next(),就会出现StopIteration
# print(next(g))   # StopIteration

# 生成器的应用场景:
'''
当需要生成无穷多的数据时,一般使用生成器.   若使用列表生成无穷多的数,会占用大量的空间,不合适.
'''

# 生成器相关的函数 yield
'''
1.yield存在于函数中,当普通函数中有了yield关键词,该普通函数变为了生成器函数.
2.调用生成器函数不会执行代码,需要使用next
3.可以在函数的内部不断地返回值,但是不会终止函数的执行(与return不同)
4.每次调用next以后,程序会在yield处暂停
'''

def test(m):
    print("m=",m)
    yield m * 2
    print("m+1=",m+1)
    yield (m + 1) * 2
    print("m+2",m+2)

g = test(23) # 在普通函数test中加入了关键字yield,那该函数变成了生成器函数,直接调用不会执行.
print(type(g))   # <class 'generator'>
print(next(g))    # 函数执行到第一个yiled处暂停
print(next(g))    # 函数执行到第二个yiled处暂停

五、迭代器【掌握】

1.可迭代对象

可迭代对象【实体】:可以直接作用于for循环的实体【Iterable】

可以直接作用于for循环的数据类型:

​ a.list,tuple,dict,set,string

​ b.generator【() 和yield】

isinstance:判断一个实体是否是可迭代的对象

代码演示:

导入模块的方式:
    第一种: import 模块名
    第二种:from 模块名 import 函数
from fib import fibonacci   表示导入fib模块中的fibonacci 函数

# 使用可迭代对象   需要导入collections.abc
from collections.abc import Iterable

# 通过 isinstance:判断一个实体是否是可迭代的对象	   返回值是bool类型,True或者False

from collections.abc import Iterable
# 可迭代对象:能够被for 循环遍历的实体就是可迭代对象

print(isinstance([],Iterable))   # True
print(isinstance((),Iterable))   # True
print(isinstance({},Iterable))   # True
print(isinstance("loha",Iterable)) # True
# 生成器
print(isinstance((i for i in range(1,10)),Iterable))  # True

# 列表\元组\字典\字符串\生成器  都是可迭代对象

print(isinstance(11,Iterable))  # False
print(isinstance(True,Iterable))  # False

# 整型\浮点型\布尔类型 都不是可迭代对象

2.迭代器

迭代器: 不但可以作用于for循环,还可以被next函数遍历【不断调用并返回一个元素,直到最后一个元素被遍历完成,则出现StopIteration】

目前为止,只有生成器才是迭代器【Iterator】

结论:迭代器肯定是可迭代对象,但是,可迭代对象不一定是迭代器

isinstance:判断一个实体是否是迭代器

代码演示:

from collections.abc import Iterator

# 迭代器:既能够通过 for循环遍历,也能next函数遍历的实体叫做迭代器.
# 目前只有生成器是迭代器

# 使用 isinstance() 判断某个实体是否是迭代器

print(isinstance([],Iterator))  #False
print(isinstance((),Iterator))  #False
print(isinstance({},Iterator))  #False
print(isinstance("loha",Iterator))  #False
print(isinstance(11,Iterator))  #False
print(isinstance(False,Iterator))   #False

# 只有生成器是迭代器
print(isinstance((i for i in range(1,10)),Iterator))  # True

3.可迭代对象和迭代器之间的转换

可以将 可迭代对象转换为迭代器:iter()

代码演示:

虽然list tuple str dict set 这些可迭代对象不能使用next() 函数遍历,但是可以通过iter() 函数将可迭代对象转换为迭代器.
# 可迭代对象转换为迭代器: iter()
list = [12,4,5,78]
# print(next(list))   # 'list' object is not an iterator
list1 = iter(list)   # 将列表转换为 迭代器
print(next(list1))   # 12
print(next(list1))   # 4
print(next(list1))   # 5
print(next(list1))   # 78

总结:

​ a.凡是可以作用于for循环的对象都是Iterable类型

​ b.凡是可以作用于next函数的对象都是Iterator类型

​ c.list/tuple/dict/set/string都不是Iterator,可以通过iter()获得一个Iterator对象

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值