函数

一、目录

1、函数嵌套
2、名称空间和作用域
3、迭代器
4、生成器
5、三元表达式,列表解析,生成器表达式
6、声明,此博文不是为小白而生,所以特别基础的就不入博客里面

二、函数嵌套

函数对象:函数是第一类对象,即函数可以当作数据传递
1 可以被引用
2 可以当作参数传递
3 返回值可以是函数
3 可以当作容器类型的元素
def bar():
    print("from nbar")
def foo():
    print("from foo")
    bar()
foo()

 

函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数

函数的嵌套定义:在一个函数的内部,又定义了另外一个函数

函数调用的三种形式
  1 语句形式:foo()
  2 表达式形式:3*len('hello')
  3 当中另外一个函数的参数:range(len('hello'))

 

函数参数省略,*args和××kwargs不解释

  ××× 阶段性练习

1、写函数,,用户传入修改的文件名,与要修改的内容,执行函数,完成批了修改操作
2、写函数,计算传入字符串中【数字】、【字母】、【空格] 以及 【其他】的个数

3、写函数,判断用户传入的对象(字符串、列表、元组)长度是否大于5。

4、写函数,检查传入列表的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。

5、写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者。

6、写函数,检查字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。
dic = {"k1": "v1v1", "k2": [11,22,33,44]}
PS:字典中的value只能是字符串或列表

#题目一
def modify_file(filename,old,new):
    import os
    with open(filename,'r',encoding='utf-8') as read_f,\
        open('.bak.swap','w',encoding='utf-8') as write_f:
        for line in read_f:
            if old in line:
                line=line.replace(old,new)
            write_f.write(line)
    os.remove(filename)
    os.rename('.bak.swap',filename)

modify_file('/Users/jieli/PycharmProjects/爬虫/a.txt','alex','SB')

#题目二
def check_str(msg):
    res={
        'num':0,
        'string':0,
        'space':0,
        'other':0,
    }
    for s in msg:
        if s.isdigit():
            res['num']+=1
        elif s.isalpha():
            res['string']+=1
        elif s.isspace():
            res['space']+=1
        else:
            res['other']+=1
    return res

res=check_str('hello name:aSB passowrd:alex3714')
print(res)


#题目三:略

#题目四
def func1(seq):
    if len(seq) > 2:
        seq=seq[0:2]
    return seq
print(func1([1,2,3,4]))


#题目五
def func2(seq):
    return seq[::2]
print(func2([1,2,3,4,5,6,7]))


#题目六
def func3(dic):
    d={}
    for k,v in dic.items():
        if len(v) > 2:
            d[k]=v[0:2]
    return d
print(func3({'k1':'abcdef','k2':[1,2,3,4],'k3':('a','b','c')}))
View Code

三、名称空间和作用域

 名称空间:存放名字的地方,准确的说名称空间是存放名字和变量绑定关系,分为以下三种

内置名称空间:在python解释器启动的时候产生,存放一些python内置的名字

全局名称空间:在执行文件的时候产生,存放文件级别定义的名字

局部名称空间:在执行文件的过程中,如果调用了函数,则会产生该函数的局部名称空间,用来存放该函数内定义的名字,该函数在调用的时候生效,在函数调用结束后失效(或者调用了del)

注意:三个名称空间的加载顺序:首先内置--》全局--》局部

  查找名字的顺序  首先局部--》然后全局--》然后内置

如:

  # max=1
        def f1():
            # max=2
            def f2():
                # max=3
                print(max)
            f2()
        f1()
        print(max)

 

补充:

locals() 是函数内的名字空间,包括局部变量和形参
globals() 全局变量,函数定义所在模块的名字空间
dir() 查看内置方法
nonlocal 所声明的变量必须已经存在,否则会报错,修改外层函数的变量
global global---将变量定义为全局变量。可以通过定义为全局变量,实现在函数内部改变变量值
eval() 将字符串str当成有效的表达式来求值并返回计算结果

enclosing 外部嵌套函数的名字空间(闭包中常见)

builtins 内置模块的名字空间

 

作用域关系: 在函数定义的时候都已经固定好了,和调用位置没有关系

作用域即范围

--全局范围:全局存活,全局有效

---局部范围:临时存活,局部有效

 x=1
      def f1():
          def f2():
              print(x)
          return f2

      def f3(func):
          x=2
          func()

      f3(f1())    #x=1
      

        查看作用域:globals(),locals()

        global
        nonlocal


        LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__

 

如果还不懂?  点击看关于作用域详细

四、迭代器

迭代器:重复的过程称之为迭代器,每次重复即一次迭代,每次迭代的结果是下一次迭代的初始值

可迭代对象iterator:凡是对象有.__iter__方法,就是迭代器对象

什么是迭代器对象?

1、有__iter__方法(执行得到的仍然是迭代本身)

2、有__next__方法   (迭代器对象中还有__iter__方法,这是为for循环做准备)

            l={'a':1,'b':2,'c':3,'d':4,'e':5}
            i=l.__iter__() #等于i=iter(l)

            print(next(i))
            print(next(i))
            print(next(i))
如果继续执行next方法,超过最大限制会爆出:
        StopIteration 异常

迭代器对象的优点:

1、提供一种统一的(不依赖索引)的迭代方式

2、迭代器本身,比其他数据类型更加节省内存

迭代器的缺点

1、一次性的,只能我那个后奏,不能回退,不如索引取值灵活

2、无法预知什么时候取值结束,无法预知长度

其中for循环原理:遵守迭代器协议

for循环开始时,会通过迭代协议传递给iter()内置函数,从而能够从可迭代对象中获得一个迭代器,返回的对象含有需要的next()方法

迭代器对象有

   (1)序列类型,如 str,list,tuple,set
   (2)非序列类型,如 dict, file
   (3)用户自定义的一些包含了__iter__()或__getitem__()方法的类

五、生成器

生成器:

  在函数内部包含yeild关键字,那么该函数执行的结果就是生成器

  生成器就是迭代器(可以用isinstance判断)

 yield功能:

  1、把函数的结果做成迭代器(以一种优雅的方式封装好__iter__ __next__方法)

  2、函数暂停与再继续运行的状态是由yield完成

def func():
    print("first")
    yield 1111
    print("second")
    yield 222
    print("third")
    yield 333
g=func()
print(next(g))
next(g)
print(next(g))
# first
# 1111
# second
# third
# 333
# next(g)   #StopIteration

 

 可以把上面的做成for循环遍历

for i in g:
    print(i)
first
1111
second
222
third
333

 

 还没明白?好吧继续往下看

如何产生一个无穷无尽的序列?

是否会想到如下?

def func(n):
    l=[]
    while True:
        l.append(n)
        n+=1
func(1000000000000)

 

想到这里确实不错,可是我可不敢运行啊.。。。

优化:

def func(n):
    print("===")
    while True:
        yield n
        n+=1
g=func(0)


for i in g:
    print(i)

 

 这样就好了,优化后的代码,在电脑中跑一天一夜也没有问题,撑爆不了内存的,因为同一时间内存中只有一个值

 

 range功能:

首先看代码:

for i in range(100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000):
    print(i)

 

 你敢拿这个在服务器上跑吗?为什么不敢!

这里首先for循换执行__iter__方法变成迭代器,所以内存中根本就没有那么大。

注意:

在python2中就不能这样用,因为python2中range是转换变成了列表

再看生成器:

def my_range(start,stop):
    while True:
        if start == stop:
            raise StopIteration
        yield start
        start+=1
g=my_range(1,3)
for i in my_range(1,3):
    print(i)

 

是否看懂?

其实就是创建一个开始和结束的值,如果开始等于结束,那么就结束,这里用了抛出异常来终止运行

模拟tail -f 文件路径|grep "error"

import time
def tail(fileppath):
    with open(fileppath,"r") as f:
        f.seek(0,2)
        while True:
            line=f.readline()
            if line:
                yield line
            else:
                time.sleep(0.2)
def grep(pattern,lines):
    for line in lines:
        if pattern in line:
            print(line,end="")

grep("error",tail("文件路径"))

 

六、三元表达式,列表解析,生成器表达式

 1、三元表达式

 表达式:

def foo(x):
    if x>3:
        return "ok"
    else:
        return "no"
g=foo(4)
print(g)

 

 使用三元表达式

x=10
res="ok" if x>3 else "no"
print(res)

 

从我工作中发现性能上来说,三元表达式要好点

2、列表解析

 往列表中添加元素

l=[]
for i in range(10):
    l.append(i)
print(l)

 

 还可以用列表解析

l=[i for i in range(10)]
print(l)

 

小思考下面的运行方式是什么样子的:

l=[i for i in range(10) if i>=5]
print(l)

 

 

3、生成器表达式

 生成器:应用于数据量很大的场景

l=(i for i in range(10))
print(l.__next__())
print(l.__next__())

 

语法:
(expr for iter_var in iterable)
(expr for iter_var in iterable if condition_expr) 

生成器表达式优点:

生内存,一次只产生一个值在内存中

示例:

#一
with open('a.txt') as f:
    print(max(len(line) for line in f))
    print(sum(len(line) for line in f)) #求包换换行符在内的文件所有的字节数,为何得到的值为0?

#二
print(max(len(line) for line in open('a.txt')))
print(sum(len(line) for line in open('a.txt')))

#三
with open('a.txt') as f:
    g=(len(line) for line in f)
print(sum(g)) #为何报错?

 

posted @ 2017-07-28 11:07  pi-pi-miao-miao  阅读(197)  评论(0)    收藏  举报