码迷,mamicode.com
首页 > 编程语言 > 详细

python 第四天

时间:2017-07-28 22:33:33      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:python   装饰器   迭代器   

第一、

1、函数的嵌套的调用:在调用函数的过程中又调用了其他的函数。代码简洁、可读性较高。

例1:

def foo():

    print(‘from foo‘)


def bar():

    print(‘from bar‘)

    foo()

bar()


#结果:

from bar

from foo


例2:

def max2(x,y):

    if x > y:

        return x

    else:

        return y


def max4(a,b,c,d):

    res1 = max2(a,b)

    res2 = max2(res1,c)

    res4 = max2(res2,d)

    return res4


print(max4(1,4,2,5))


2、函数的嵌套定义:在一个函数的内部、又定义另外一个函数。


第二、

1、名称空间:存放名字的地方、准确的说是存放名字和变量值绑定关系的地方。

python中的名称空间有:

1、内置名称空间:在py启动的时候产生、存放一些python自带的名字。

print(),len(),max()……


2、全局名称空间:在执行文件时、文件级别定义的名字。

x=1、

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


三个名称空间的加载顺序:

内置-->全局-->局部

从上到下。


三个名称空间的查询顺序:

局部-->全局-->内置

从下往上。


2、作用域:作用的应用范围

全局作用域:全局有效、任何位置都能访问得到。

全局包含:globals

1、内置名称

2、全局名称

例:

def f1():

    def f2():

        def f3():

            print(max)


        f3()

    f2()

f1()

<built-in function max>


局部作用域:临时有效、局部有效。

局部包含:locals

1、局部名称

全局作用域的局部依然是全局作用域。


dir 查看对象下有哪些方法。


#global 关键字

global

x=1

def f1():

    global x

    x=2

f1()

print(x)

2


#不加global 也可以修改可变类型的数据

l = []

def f2():

    l.append(‘f2‘)

f2()

print(l)l = []

def f2():

    l.append(‘f2‘)

f2()

print(l)


[‘f2‘]


x=0

def f1():

    x=3

    def f2():

        x=2

        def  f3():

            global x

            x=3

        f3()

    f2()

f1()


print(x)


3


x=0

def f1():

    x=3

    def f2():

        x=2

        def  f3():

            global x

            x=3

        f3()

        print(x)

    f2()

f1()


2


x=0

def f1():

    x=3

    def f2():

        x=2

        def  f3():

            nonlocal x

            x=3

        f3()

        print(x)

    f2()

f1()

3


#优先掌握:作用域关系在函数定义时就已经定义了,与调用的位置无关。需要回到原来定义函数的位置去找作用域关系


x= 1

def f1():

    def f2():

        print(x)

    return f2


def foo(func):

    x=100

    func()


foo(f1())

1


#此处值为1是因为作用域的定义在上面。

3、闭包函数:闭合、包裹。

定义:

1、定义在函数内部的函数

2、包含对外部作用域名字的引用,而不是全局作用域名字得引用,那么该内部函数就称为闭包函数。

def f1():

    x=2

    def f2():

        print(x)

    return f2


res=f1()

res()

2


#此处的f2函数就是闭包函数、此时他不是独立存在的他的外围包一层作用域。

def deco():

    x=123123

    def wrapper():

        print(x)

    return wrapper

    wrapper()


func=deco()

func()


123123


#查看外部变量

import requests

def index(url):

    def get():

        print(requests.get(url).text)

    return get


python_web=index(‘http://www.python.org‘)

baidu_web=index(‘http://www.baidu.com‘)


print(python_web.__closure__)


(<cell at 0x0000007E65EA55E8: str object at 0x0000007E66035DF8>,)


import requests

def index(url):

    def get():

        print(requests.get(url).text)

    return get


python_web=index(‘http://www.python.org‘)

baidu_web=index(‘http://www.baidu.com‘)


print(python_web.__closure__[0].cell_contents)


http://www.python.org


当闭包内部函数没有被作用域包住的时候,他的作用域为None

4、为什么要用装饰器?

1、开发封闭原则:对扩展是开放的、对修改是封闭的。

 装饰器:目的为其他人添加新功能、

 装饰器可以是任意可调用对象、被装饰的对象可以是任意可调用对象。


  2、装饰器需要遵循的原则:

  2.1 不修改装饰对象的源代码

  2.2 不修改被调用对象的功能

  其目的就是满足1和2条件添加新功能


例1:

import time

def index():

    time.sleep(3)

    print(‘welcome to index‘)


def home():

    time.sleep(3)

    print(‘welcome to home‘)


def timmer(func):

    def wrapper():

        start=time.time()

        func()

        stop=time.time()

        print(‘run time is %s‘ %(stop-start))

    return wrapper


index=timmer(index)

home=timmer(home)


index()

home()


简写装饰器:

import time

def timmer(func):

    def wrapper():

        start=time.time()

        func()

        stop=time.time()

        print(‘run time is %s‘ %(stop-start))

    return wrapper


@timmer #装饰器需要在调用的上面

def index():

    time.sleep(3)

    print(‘welcome to index‘)

@timmer #@等价 home=timmer(home)

def home():

    time.sleep(3)

    print(‘welcome to home‘)


index()

home()


#@装饰器名、必须写在被装饰对象的正上方、而且是单独一行


例2:、对被修饰对象加参数

import time

def timmer(func):

    def wrepper(*args,**kwargs):

        start=time.time()

        func(*args,**kwargs)

        stop=time.time()

        print(‘run time is %s‘ %(stop-start))

    return wrepper


@timmer

def index():

    time.sleep(2)

    print(‘welcome to index‘)

@timmer

def home(name):

    time.sleep(2)

    print(‘welcome to %s‘ %name)


index()

home(‘home‘)


例3:返回值

#对被修饰对象加参数

import time

def timmer(func):

    def wrepper(*args,**kwargs):

        start=time.time()

        res=func(*args,**kwargs)

        stop=time.time()

        print(‘run time is %s‘ %(stop-start))

        return res

    return wrepper


@timmer

def index():

    time.sleep(2)

    print(‘welcome to index‘)

    return  123

@timmer

def home(name):

    time.sleep(2)

    print(‘welcome to %s‘ %name)

    return 456


res=index()

print(res)

res1=home(‘home‘)

print(res1)


>>

welcome to index

run time is 2.00014328956604

123

welcome to home

run time is 2.0002007484436035

456


例3:用装饰器实现用户登录认证的功能

cust_dic={‘user‘:None}

def auth(func):

    def auth_toke(*args,**kwargs):

        if cust_dic[‘user‘]:

            return func(*args, **kwargs)

        user_inp = input(‘user>> ‘).strip()

        pass_inp = input(‘pass>> ‘).strip()

        with open(‘db‘,‘r‘,encoding=‘utf-8‘) as use_f:

            use_list=eval(use_f.read())

            if user_inp == use_list[0][‘user‘] and pass_inp == use_list[0][‘password‘]:

                cust_dic[‘user‘] = user_inp

                return func(*args,**kwargs)

            else:

                print(‘log in error‘)

    return auth_toke


@auth

def access():

    print(‘login sessfull‘)


@auth

def error(name):

    print(‘welcome to is %s‘ %name)


access()

error(‘json‘)


>>:

user>> json

pass>> 123123

login sessfull

welcome to is json


#闭包函数只需要用到3层就能满足一切函数的传参。

#装饰器补充

import time

def foo():

    ‘‘‘这是index函数‘‘‘

    time.time()

    print(‘access‘)

    return 123

# print(help(foo))


print(foo.__doc__)


    这是index函数

#多个装饰器

谁在上面谁先生效。

5、迭代器:

迭代:重复的过程、每一次重复都是基于上一次的结果而来。

取出序列类型的元素就是迭代

例1:

l = [‘a‘,‘b‘,‘c‘,‘d‘]

count=0

while  count < len(l):

    print(l[count])

    count+=1


>>

a

b

c

d


5.1、迭代器:取出非序列数据、不按索引。

5.2、可迭代对象:凡是对象有__iter__方法:对象.__iter__,该对象就是可迭代对象。

可迭代对象有:字符串、列表、元组、字典。

例2:

dic={‘name‘:‘egon‘}

res=dic.__iter__()

print(res)  #iterator 迭代器

例3:

dic={‘name‘:‘egon‘,‘age‘:11}

res=dic.__iter__()

print(next(res))

print(next(res)

>>

name

age

#StopIteration 提示迭代器没有值了,应该停止了

迭代器本身也是可迭代的对象。

dic={‘name‘:‘egon‘,‘age‘:11}

# res=dic.__iter__()

res=iter(dic)

print(next(res))

print(next(res))

>>

name

age

#当迭代器遇到stopiteration的时候会停止运行。

s=‘hello‘

l=[‘a‘,‘b‘,‘c‘,‘d‘]

iter_l=iter(l)

while True:

    try:

        print(next(iter_l))

    except StopIteration:

        break

>>

a

b

c

d

6、迭代器对象:

6.1、有__iter__,执行结果仍然是迭代器本身

6.2、有__next__,执行一次取一个值

迭代器对象的优点:

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

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

3、迭代器可以存放无穷无尽个值。


例1、

with open(‘db‘,encoding=‘utf-8‘) as f:

    print(next(f))

    print(next(f))

    print(next(f))

    print(next(f))


>>

111111111111111111111

11111111111111

11111111111

1111111

迭代器缺点:

1、一次性的、只能往后不能回退、不如索引取值更灵活。

占内存大的环境不能用索引方式。

2、无法预知什么时候结束、即无法预知长度。

for循环就是一个迭代器。

for循环的对象就是可迭代对象。


判断一个对象是否是可迭代对象的方法就是?看该对象是否有iter方法。

文件是迭代器。****

7、生成器

生成器:在函数内部包含yield关键字、那么该函数的执行结果是生成器

生成器就是迭代器。

#yield的功能:

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

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

例1、手动实现rang函数。

def my_rang(start,stop):

    while True:

        if start == stop:

            raise StopIteration

        yield start

        start+=1

for i in my_rang(1,3):

    print(i)

7.1、yield 与 return的比较?

相同:都有返回值的功能

不同:return只能返回一次、


例2、taif -f |grep 实现

import time

def tail(filepath):

    with open(filepath,‘r‘) as f:

        f.seek(0,2)

        while True:

            line = f.readline()

            if line:

                yield line

            else:

                time.sleep(0.2)


def grep(patten,lines):

    for line in lines:

        if patten in line:

            print(line,end=‘‘)

grep(‘error‘,tail(‘db‘))

8、三元表达式:

为真时的结果 if 判定条件 else 为假时的结果  

1 if 5>3 else 0

输出为1、如果5大于3、否则输出0

9、列表解析

根据已有列表,高效创建新列表的方式。

列表解析是Python迭代机制的一种应用,它常用于实现创建新的列表,因此用在[]中。


例1:传统方式

l=[]

for n in range(11):

    l.append(n)

print(l)

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


例2:列表解析

l=[ n for n in range(10)]

print(l)

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


例3:取出10内大于4的数字

传统方法:

l=[]

for n in range(10):

    if n >= 4:

        l.append(n)

print(l)

[4, 5, 6, 7, 8, 9]


列表解析:

l=[ n for n in range(10) if n >=4 ]

print(l)

[4, 5, 6, 7, 8, 9]

10、生成器表达式:

生成器表达式并不真正的创建数字列表,而是返回一个生成器对象,此对象在每次计算出一个条目后,把这个条目"产生"(yield)出来。生成器表达式使用了"惰性计算"或称作"延时求值"的机制。

序列过长,并且每次只需要获取一个元素时,应该考虑生成器表达式而不是列表解析。


N=(i**2 for i in range(11))

print(N)

<generator object <genexpr> at 0x000000A5BE8A1D00> #此处返回的是一个生成器的地址


生成器取值通过next方法:


N=(i**2 for i in range(11))

# print(N)

print(next(N))

print(next(N))

print(next(N))

print(next(N))


0

1

4

9


生成器取值到元素遍历完毕之后,抛出StopIteration

N=(i**2 for i in range(11))

# print(N)

while True:

    try:

        print(next(N))

    except StopIteration:

        break


本文出自 “男儿该自强” 博客,请务必保留此出处http://nrgzq.blog.51cto.com/11885040/1951622

python 第四天

标签:python   装饰器   迭代器   

原文地址:http://nrgzq.blog.51cto.com/11885040/1951622

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!