day4 函数对象 函数嵌套 名称空间与作用域 闭包函数 装饰器 迭代器 生成器 内置函数

一、函数对象

1 可以被引用
2 可以当作参数传递
3 返回值可以是函数
3 可以当作容器类型的元素

def foo():
    print('from foo')

func=foo

print(foo)
print(func)
func()

输出结果如下:

<function foo at 0x00000000026220D0>
<function foo at 0x00000000026220D0>
from foo

  

二、函数嵌套

python允许在定义函数的时候,其函数体内又包含另外一个函数的完整定义,这就是我们通常所说的嵌套定义。为什么?因为函数是用def语句定义的,凡是其他语句可以出现的地方,def语句同样可以出现。
像这样定义在其他函数内的函数叫做内部函数,内部函数所在的函数叫做外部函数。当然,我们可以多层嵌套,这样的话,除了最外层和最内层的函数之外,其它函数既是外部函数又是内部函数。#函数的嵌套定义

def f1():

    def f2():
        print('from f2')
        def f3():
            print('from f3')
        f3()
    f2()


f1()
输出结果如下:

from f2
from f3


三、名称空间与作用域

三种名称空间:

内置名称空间:随着python解释器的启动而产生。
print(sum)
print(max)
print(min)

输出结果如下:
<built-in function sum>
<built-in function max>
<built-in function min>
dir()函数接受模块名作为参数,返回一个排好序的字符串列表,内容是一个模块里定义过的名字。便获得了内建模块里定义的名字:
import builtins
for i in dir(builtins): 
    print(i)
输出结果:
ArithmeticError
AssertionError
AttributeError
BaseException
BlockingIOError
BrokenPipeError
BufferError
BytesWarning
ChildProcessError
ConnectionAbortedError
ConnectionError
ConnectionRefusedError
ConnectionResetError
DeprecationWarning
EOFError
Ellipsis
EnvironmentError
Exception
False
FileExistsError
FileNotFoundError
FloatingPointError
FutureWarning
GeneratorExit
IOError
ImportError
ImportWarning
IndentationError
IndexError
InterruptedError
IsADirectoryError
KeyError
KeyboardInterrupt
LookupError
MemoryError
ModuleNotFoundError
NameError
None
NotADirectoryError
NotImplemented
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
PermissionError
ProcessLookupError
RecursionError
ReferenceError
ResourceWarning
RuntimeError
RuntimeWarning
StopAsyncIteration
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TimeoutError
True
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
WindowsError
ZeroDivisionError
__build_class__
__debug__
__doc__
__import__
__loader__
__name__
__package__
__spec__
abs
all
any
ascii
bin
bool
bytearray
bytes
callable
chr
classmethod
compile
complex
copyright
credits
delattr
dict
dir
divmod
enumerate
eval
exec
exit
filter
float
format
frozenset
getattr
globals
hasattr
hash
help
hex
id
input
int
isinstance
issubclass
iter
len
license
list
locals
map
max
memoryview
min
next
object
oct
open
ord
pow
print
property
quit
range
repr
reversed
round
set
setattr
slice
sorted
staticmethod
str
sum
super
tuple
type
vars
zip

全局名称空间:文件的执行会产生全局名称空间,指的是文件级别定义的名字都会放入该空间

x=1

def func():
    money=2000
    x=2
    print('func')
print(x)
print(func)
func()
print(money)
输出结果如下:
1
<function func at 0x0000000002493E18>
func
Traceback (most recent call last):
  File "D:/py17/day4/名称空间与作用域.py", line 59, in <module>
    print(money)
NameError: name 'money' is not defined
作用域:
1. 全局作用域:内置名称空间,全局名层空间
2. 局部作用:局部名称空间
名字的查找顺序:局部名称空间---》全局名层空间---》内置名称空间
x=1
def func():
    x=2
    print(x)
    sum=123123
    print(sum)
func()
输出结果:
2
123123
查看全局作用域内的名字:gloabls()
查看局局作用域内的名字:locals()
x=1000
def func(y):
    x=2
    print(locals())
    print(globals())

func(1)
输出结果:
{'x': 2, 'y': 1}
{'__name__': '__main__', '__doc__': '\n作用域:\n    1. 全局作用域:内置名称空间,全局名层空间\n    2. 局部作用:局部名称空间\n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000002566828>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/py17/day4/名称空间与作用域.py', '__cached__': None, 'x': 1000, 'func': <function func at 0x0000000002153E18>}
全局作用域:全局有效,在任何位置都能被访问到,除非del删掉,否则会一直存活到文件执行完毕

局部作用域的名字:局部有效,只能在局部范围调用,只在函数调用时才有效,调用结束就失效
x=1

def f1():
    print(x)

def foo():
    print(x)

def f(x):
    # x=4
    def f2():
        # x=3
        def f3():
            # x=2
            print(x)

        f3()
    f2()

f(4)
输出结果:
4  

四、闭包函数

1. 定义在内部函数
2. 包含对外部作用域而非全局作用域的引用,
3.该内部函数就成为闭包函数


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

    return f2
闭包应用:惰性计算
from urllib.request import urlopen

def index(url):
    def get():
        return urlopen(url).read()

    return get

oldboy=index('http://crm.oldboyedu.com')

print(oldboy().decode('utf-8'))
print(oldboy.__closure__[0].cell_contents)


res=urlopen('http://crm.oldboyedu.com').read()

print(res.decode('utf-8'))

五、装饰器

定义:本质是函数,(装饰其他函数),就是为其他函数添加附加功能。

原则:1. 不能修改被装饰的函数的源代码。

         2. 不能修改被装饰的函数的调用方式。

实现装饰器知识储备:

1. 函数即'变量'

2.高阶函数

a. 把一个函数名当做实参传递给另外一个函数(在不修改被装饰函数的源代码的情况下为其添加功能)

b. 返回值中包含函数名

3. 嵌套函数

高阶函数 + 嵌套函数 =》 装饰器

 

import time

def timmer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print('run time is %s' %(stop_time-start_time))
    return wrapper

@timmer
def index():

    time.sleep(3)
    print('welcome to index')

index()

输出结果:
welcome to index
run time is 3.000171422958374 

六、迭代器

 迭代的概念:  重复+上一次迭代的结果为下一次迭代的初始值。

       重复的过程称为迭代,每次重复即一次迭代,
      并且每次迭代的结果是下一次迭代的初始值。
while True: #只满足重复,因而不是迭代
    print('====>')


#下面才为迭代
l = [1, 2, 3]
count = 0
while count < len(l):  # 只满足重复,因而不是迭代
    print('====>', l[count])
    count += 1

l = (1, 2, 3)
count = 0
while count < len(l):  # 只满足重复,因而不是迭代
    print('====>', l[count])
    count += 1

s='hello'
count = 0
while count < len(s):
    print('====>', s[count])
    count += 1

为什么要有迭代器?对于没有索引的数据类型,必须提供一种不依赖索引的迭代方式。

可迭代的对象:内置__iter__方法的,都是可迭代的对象。

# [1,2].__iter__()
# 'hello'.__iter__()
# (1,2).__iter__()
#
# {'a':1,'b':2}.__iter__()
# {1,2,3}.__iter__()

迭代器:执行__iter__方法,得到的结果就是迭代器,迭代器对象有__next__方法。

i=[1,2,3].__iter__()

print(i)
#
print(i.__next__())
print(i.__next__())
print(i.__next__())
print(i.__next__()) #抛出异常:StopIteration

输出结果:
<list_iterator object at 0x000000000261AFD0>
1
2
3
Traceback (most recent call last):
  File "D:/py17/day4/迭代器.py", line 57, in <module>
    print(i.__next__()) #抛出异常:StopIteration
StopIteration
i={'a':1,'b':2,'c':3}.__iter__()
--------------------------------------------------
print(i.__next__())
print(i.__next__())
print(i.__next__())
print(i.__next__())
输出结果:

Traceback (most recent call last):
File "D:/py17/day4/迭代器.py", line 65, in <module>
print(i.__next__())
StopIteration
a
b
c

-----------------------------------------------------------------------

dic={'a':1,'b':2,'c':3}
i=dic.__iter__()
while True:
try:
key=i.__next__()
print(dic[key])
except StopIteration:
break
输出结果:

1
2
3

------------------------------------------------------------------------

s={'a',3,2,4}

s.__iter__() #iter(s)

i=iter(s)
print(next(i))
print(next(i))
print(next(i))
print(next(i))
#print(next(i))
输出结果:

2
a
3
4

 

--------------------------------------------------
print(i.__next__())
print(i.__next__())
print(i.__next__())
print(i.__next__())
输出结果:
Traceback (most recent call last):
File "D:/py17/day4/迭代器.py", line 65, in <module>
print(i.__next__())
StopIteration
a
b
c

-----------------------------------------------------------------------

dic={'a':1,'b':2,'c':3}
i=dic.__iter__()
while True:
    try:
        key=i.__next__()
        print(dic[key])
    except StopIteration:
        break
输出结果:
1
2
3

------------------------------------------------------------------------

s={'a',3,2,4}

s.__iter__() #iter(s)

i=iter(s)
print(next(i))
print(next(i))
print(next(i))
print(next(i))
#print(next(i))
输出结果:
2
a
3
4

  

判断是不是可以迭代,用Iterable

判断是不是迭代器,用Iterator 

在Python中可以使用type()与isinstance()这两个函数判断对象类型,而isinstance()函数的使用上比type更加方便。

from collections import Iterable,Iterator

'abc'.__iter__()
().__iter__()
[].__iter__()
{'a':1}.__iter__()
{1,2}.__iter__()

f=open('a.txt','w')
f.__iter__()


#下列数据类型都是可迭代的对象
print(isinstance('abc',Iterable))
print(isinstance([],Iterable))
print(isinstance((),Iterable))
print(isinstance({'a':1},Iterable))
print(isinstance({1,2},Iterable))
print(isinstance(f,Iterable))
输出结果:

True
True
True
True
True
True

----------------------------------------------------------------------------------

#只有文件是迭代器对象
print(isinstance('abc',Iterator))
print(isinstance([],Iterator))
print(isinstance((),Iterator))
print(isinstance({'a':1},Iterator))
print(isinstance({1,2},Iterator))
print(isinstance(f,Iterator))
输出结果:

False
False
False
False
False
True

生成器   

生成器函数:只要函数体包含yield关键字,该函数就是生成器函数生成器就是迭代器。

生成器就是迭代器

def foo():
    print('first')
    yield 1
    print('second')
    yield 2
    print('third')
    yield 3
    print('fourth')
    yield 4
    print('fifth')
    yield 5
g=foo()

print(next(g)) #触发迭代器g的执行,进而触发函数的执行
print(next(g))
print(next(g))
print(next(g))
print(next(g))

  

yield的功能:
1.相当于为函数封装好__iter__和__next__
2.return只能返回一次值,函数就终止了,
而yield能返回多次值,每次返回都会将函数暂停,下一次next会从
上一次暂停的位置继续执行。

内置函数

内置参数详解 https://docs.python.org/3/library/functions.html?highlight=built#ascii                                                                                                                      

posted @ 2017-01-18 10:58  menglingqian  阅读(169)  评论(0编辑  收藏  举报