07-函数高级&列表生成器&生成器&迭代器

一、函数的特殊用法

1.变量可以指向函数

代码演示:

#abs------>absolute

#abs()是一个系统的内置函数【built-in function】
print(abs(-10))   #10

print(abs)   #<built-in function abs>

#结论一:abs(-10)是函数的调用,而abs是函数本身

x = abs(-20)
print(x)   #20

f = abs
print(f)   #<built-in function abs>

#结论二;函数本身也可以直接赋值给一个变量,也就是说:变量可以指向一个函数   num = 10
#如果一个变量指向了一个函数,则可以通过这个变量去调用这个函数
print(f(-30))

#结论三:f = abs, 则表示f已经指向了abs所表示的函数,调用abs和调用f实现的效果是一样的

def test():
    return  "fjskghs"

print(test())
fun = test
print(fun())

2.函数名是一个变量

代码演示:

#函数的特殊用法之函数名是一个变量

#结论一:函数名其实就是指向函数的变量

#abs():可以将abs看做一个变量,指向了一个可以计算绝对值的函数

#abs更改指向【变量的重新赋值】

num = 10
num = "hello"

#让abs指向一个整型
print(abs)
abs = 10
print(abs)

#print(abs(-100))

3.函数作为参数

代码演示:

#函数的特殊用法之函数作为参数

#变量可以指向函数,函数名是一个变量,而函数的形参本身就是一个变量,可以接收实参,那么一个函数就可以接收另一个函数作为参数
#高阶函数【一个函数就可以接收另一个函数作为参数】

#一个简单的高阶函数【需求:求两个数的绝对值的和】
#参数:x和y就是需要参与运算的数据,fun是一个函数
"""
def add(x,y):
    return abs(x) + abs(y)

"""
def add(x,y,fun):
    return fun(x) + fun(y)    #abs(x) + abs(y)

#将函数名abs作为参数使用
result = add(-5,6,abs)    #x = -5  y = 6   fun = abs  fun()
print(result)


#自定义函数
def show():
    print("abc")

def func(f):
    print("hello")
    f()

func(show)

二、偏函数

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

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

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

代码演示:

import  functools

# 偏函数的使用


#int(x)   可以将字符串或者浮点型转换为整型
#默认:将其中的字符串按照十进制输出
print(int("123"))

#int()还提供了一个额外的参数:base
#print(int("abc123"))
#base;指明前面数据的进制,int()执行完成之后,最终还是以十进制输出
print(int("123",base = 10))   #123
print(int("123",base = 8))    #83


print(int("110",base = 2))
print(int("11010",base = 2))
print(int("110001",base = 2))

#转换大量的二进制,每次传入base = 2麻烦,可以将这个功能提取出来
def customInt(x,base=2):
    return int(x,base)
print(customInt("110"))  #6
print(customInt("11010"))  #26

#上面通过默认参数模仿了偏函数的使用,但是系统提供了功能:functools.partial可以创建一个偏函数【前提;需要导入import  functools】
#参数:需要创建偏函数的原函数名  需要设定的参数
int2 = functools.partial(int,base=2)
print(int2("110"))   #6
print(int2("11010"))  #26

print(int2("110",base=10))   #110

#总结:偏函数
#主要针对的是系统函数,如果系统默认的操作满足不了需求,则可以在这个系统函数的基础上生成一个新的函数【偏函数】,两个函数可以实现不同的需求

三、闭包

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

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

代码演示:

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

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

#1.最简单的闭包
#外函数
def func(str):
    #内函数【闭包】
    def innerFunc():
        print("hello")

    return innerFunc

#f中存储了外函数func的返回值,而func的返回值是innerFunc,j就相当于f = innerFunc
f = func("abc")   #f = innerFunc
#f()就相当于innerFunc()
f()

#2.
#a和b被称为外函数中的临时变量【自由变量】
def outer(a):
    b = 10
    def inner():
        #在内函数中可以直接使用外函数中临时变量
        print(a + b)
    return  inner

f1 = outer(5)
f1()

#3.
def outer1(num1):
    def inner1(num2):
        #在内函数中可以直接使用外函数中临时变量
        print(num1,num2)
    return  inner1

f2 = outer1(10)
f2(20)

#应用场景:装饰器

四、变量的作用域

1.出现的原因

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

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

2.作用范围划分

局部作用域:L【Local】

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

全局作用域:G【Global】

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

代码演示:

#1.不同作用域变量的定义
num4 = int(2.9)    #B;內建作用域
num3 =  3    #G;全局作用域
def outer():
    num1 = 1    #E:函数作用域

    def inner():
        num2 = 2   #L:局部作用域

        #注意:当所有的变量不同名的时候,在闭包中,可以任意访问四种不同作用域对应的变量
        print(num4,num3,num2,num1)

    return  inner

f = outer()
f()

3.变量的查找规则

查找的顺序:L------>E------>G------>B【极端情况:当所有的变量同名的情况下】

代码演示:

#变量的查找规则

#注意:全局作用域和内置作用域,当重名的时候,谁出现在后面,则先匹配到谁
x = 0
x1 = int(3.3)

def outer1():
    j = 1
  
    def inner1():
        i = 2
        #【就近原则】
        print(x)

    return  inner1

f1 = outer1()
f1()
#函数
def show(a):
    num1 = 10
    print(num1,a)
show(20)
#print(num1,a)
#结论一:在函数中定义的变量【形参,在函数体中定义的变量】,作用域仅限于函数内部
# 【变量的生命周随着函数的出现而出现,函数执行完毕则变量随着被销毁】

#if语句
if True:
    msg = "hello"
    print(msg)
print(msg)


 #for循环
for i in range(0,5):
    print(i)
print(i)

#结论二;Python中只有模块【module】、类【class】和函数【def,lambda】才会引入新的作用域
#其他的代码块:if语句,while语句,for语句,try-except语句都不会引入新的作用域

4.全局变量和局部变量

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

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

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

代码演示:

#全局变量
total = 0

def show():
    print(total)
show()

if True:
    total = 20
    print(total)

total = 10
print(total)

def add(arg1,arg2):
    #arg1,arg2,total1都属于局部变量
    total1 = arg1 + arg2
    print(total1)

add(10,20)
#print(total1)

示例:

#1.计算1~某个数范围内奇数的和并返回
def fun1(num):
    sum = 0
    for i in range(1,num + 1):
        if i % 2 == 1:
            sum += 1

    return sum

print(fun1(100))

#2.判断某个数是否是质数,返回结果
def fun2(num):
    is_prime = True

    for x in range(2,num):
        if num % x == 0:
            is_prime = False
            break
    if is_prime and num != 1:
        return "质数"
    else:
        return "不是质数"

fun2(10)

5.global和nonlocal关键字的使用

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

1.global

代码演示:

#global

#全局变量
num = 1
def fun1():

    #此时要使用全局变量中的num,需要给编译器做一个声明,声明此处使用num就是使用的全局变量中的num
    global num
    print(num)
    print(id(num))   #1355785312

    #局部变量
    num = 123
    print(num)
    print(id(num))   #1355789216

fun1()


#练习
a = 10
def test():
    global  a
    a = a + 1
    print(a)

test()

2.nonlocal

代码演示:

#前提:nonlocal关键字是定义在闭包中
x = 0

def outer():
    x = 1

    def inner():
        #使用nonlocal关键字进行声明,相当于将局部作用域范围扩大了
        nonlocal x
        x = 2
        print("inner:",x)
    #return  inner

    inner()

    print("outer:",x)   #2

outer()
print("global:",x)
"""
原本:
inner: 2
outer: 1
global: 0
"""

"""
修改:
inner: 2
outer: 2
global: 0
"""

五、列表生成式和生成器

1.列表生成式

list comprehension

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

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

代码演示:

#列表生成式

list1 = list(range(1,11))
print(list1)   #[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


#需求:[1, 4, 9, 16, 25]
list2 = []
for x in range(1,11):
    list2.append(x ** 2)
print(list2)  #[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

#1
#使用列表生成式完成上面的需求
#列表生成式的格式:[生成的元素 for-in循环]
list3 = [x ** 2 for x in range(1,11)]
print(list3)   #[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

#2.
#[4,16,36,64,100]
list4 = [x ** 2 for x in range(1,11) if x % 2 == 0]
print(list4)


#3.嵌套for循环,第一个循环就相当于外层循环,第二个循环就相当于内层循环
list5 = [m + n for m in "ABC" for n in "XYZ"]
print(list5)

#["AX","AY","AZ"....]

"""
for m in "ABC":
    for n in "XYZ":
        print(m + n)

"""

#4
#for k,v in dict.items)():
d = {"x":"1","y":"2","z":"3"}
for k,v in d.items():
    print(k,v)

list6 = [k + "=" + v for k,v in d.items()]
print(list6)   #['x=1', 'y=2', 'z=3']


#练习:使用列表生成式生成一个新的列表,将一个已知列表中的所有的字符变为小写
l1 = ["Hello","GOOD","ABC","kkH"]
#l2 = ["hello","good","abc","kkh"]

newList1 = []
for element in l1:
    str = element.lower()
    newList1.append(str)
print(newList1)


newList2 = [s.lower() for s in l1]
print(newList2)

2.生成器

generator

next()

代码演示:

#生成器

#方式一:(),将列表生成式中的[]改成()
#列表生成式的类型是list,生成器的类型是generator【当做一种新的数据类型】
r1 = (x ** 2 for x in range(1,6))
print(r1)   #(1,4,9,16,25)
print(type(r1))

"""
for i in r1:
    print(i)
"""

#生成器区别于列表生成式:可以使用next遍历,每调用一次则获取一个元素
#next()
print(next(r1))
print(next(r1))
print(next(r1))
print(next(r1))
print(next(r1))
#注意:当生成器中的元素全部获取完成之后,接着调用next函数的,则会出现StopIteration
#print(next(r1))   #StopIteration异常


#方式二:yield---->让步
#(x for x in range(1,6))----->1,2,3,4,5
def test(n):
    for i in range(1, n + 1):
        #执行到yield的时候,则函数会停止,将yiled后面的变量返回
        yield i ** 2
        #yield后面的代码的执行时机:当调用next函数的时候
        print(i)

t = test(5)
print(t)  #<generator object test at 0x0000019CC432A1A8>
print(next(t))
print(next(t))
print(next(t))
print(next(t))
print(next(t))

六、迭代器

1.可迭代对象

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

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

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

​ b.generator【() 和yield】

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

代码演示:

#一、可迭代对象

#1.导入
from  collections  import  Iterable

#2.使用isinstance(数据,Iterable)
print(isinstance([],Iterable))
print(isinstance((),Iterable))
print(isinstance({},Iterable))
print(isinstance((x for x in range(10)),Iterable))
print(isinstance("hello",Iterable))

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

print("****88")

2.迭代器

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

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

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

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

代码演示:

#二、迭代器
from  collections  import  Iterator

print(isinstance([],Iterator))
print(isinstance((),Iterator))
print(isinstance({},Iterator))
print(isinstance("hello",Iterator))
print(isinstance((x for x in range(10)),Iterator))   #True

print("****88")

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

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

代码演示:

#三、虽然list、tuple、dict、set、string都不是迭代器
#iter():将list、tuple、dict、set、string的  Iterable转换为Iterator
print(isinstance(iter([]),Iterator))
print(isinstance(iter(()),Iterator))
print(isinstance(iter({}),Iterator))
print(isinstance(iter("hello"),Iterator))

总结:

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

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容

  • 一、快捷键 ctr+b 执行ctr+/ 单行注释ctr+c ...
    o_8319阅读 5,779评论 2 16
  • 写在前面的话 代码中的# > 表示的是输出结果 输入 使用input()函数 用法 注意input函数输出的均是字...
    FlyingLittlePG阅读 2,724评论 0 8
  • 一、函数的特殊用法 1.变量可以指向函数 代码演示:#abs------>absolute#abs()是一个系统的...
    hollow_02f9阅读 659评论 0 0
  • 再次回答北京已经不一样了 韩雪她已是陆凯的妻子 但是韩雪还没这个意识 陆凯对他说结婚以后你就和我住在一起吧!神马和...
    零点之后阅读 309评论 0 0
  • 妄谈人生 今天为何要谈人生呢?对一个人来说,或者说对绝大多数人来说,活着是头等重要的大事。那么人活着的意义到底是什...
    清净无量阅读 522评论 0 2