1.内置参数
Built-in Functions | ||||
abs() | dict() | help() | min() | setattr() |
all() | dir() | hex() | next() | slice() |
any() | divmod() | id() | object() | sorted() |
ascii() | enumerate() | input() | oct() | staticmethod() |
bin() | eval() | int() | open() | str() |
bool() | exec() | isinstance() | ord() | sum() |
bytrarray() | filter() | issubclass() | pow() | super() |
bytes() | float() | iter() | print() | tuple() |
callable() | format() | len() | property() | type() |
chr() | frozenset() | list() | range() | vars() |
classmethod() | getattr() | locals() | repr() | zip() |
compile() | globals() | map() | reversed() | __import__() |
complex() | hasattr() | max() | round() | |
delattr() | hash() | memoryview() | set() |
内置参数详解 https://docs.python.org/3/library/functions.html?highlight=built#ascii
2.迭代器&生成器
列表生成式,是Python内置的一种极其强大的生成list的表达式。
如果要生成一个list [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9] 可以用 range(1 , 10):
1
2
|
#print(list(range(1,10))) [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] |
如果要生成[1x1, 2x2, 3x3, ..., 10x10]
怎么做?
1
2
3
4
5
6
|
l = [] for i in range ( 1 , 10 ): l.append(i * i) print (l) ####打印输出#### #[1, 4, 9, 16, 25, 36, 49, 64, 81] |
而列表生成式则可以用一行语句代替循环生成上面的list:
1
2
|
>>> print ([x * x for x in range ( 1 , 10 )]) [ 1 , 4 , 9 , 16 , 25 , 36 , 49 , 64 , 81 ] |
for循环后面还可以加上if判断,这样我们就可以筛选出仅偶数的平方:
1
2
|
>>> print ([x * x for x in range ( 1 , 10 ) if x % 2 = = 0 ]) [ 4 , 16 , 36 , 64 ] |
>>>[ i*2 for i in range(10)] [0,1,4,6,8,10,12,14,16,18] 等于 >>>a=[] >>>for i in range(10): . . . a.append(i*2) >>>a [0,1,4,6,8,10,12,14,16,18]
小程序
str1 = "" for i in iter(input,""): # 循环接收 input输入的内容 str1 += i print(str1)
生成器
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]
改成()
,就创建了一个generator:
>>>l = [x*x for x in range(10)] >>>l [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>>g = (x*x for x in range(10)) >>>g <generator object <genexpr> at 0x1022ef630>
创建L
和g
的区别仅在于最外层的[]
和()
,L
是一个list,而g
是一个generator。
我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?
如果要一个一个打印出来,可以通过next()
函数获得generator的下一个返回值:
>>> next(g) 0 >>> next(g) 1 >>> next(g) 4 >>> next(g) 9 >>> next(g) 16 >>> next(g) 25 >>> next(g) 36 >>> next(g) 49 >>> next(g) 64 >>> next(g) 81 >>> next(g) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
所以,我们创建了一个generator后,基本上永远不会调用next()
,而是通过for
循环来迭代它,并且不需要关心StopIteration
的错误。
generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for
循环无法实现的时候,还可以用函数来实现。
比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
1, 1, 2, 3, 5, 8, 13, 21, 34, ...
def fib(max): n,a,b=0,0,1 while n < max: print(b) a,b=b,a+b n = n+1 return 'done'
上面的函数可以输出斐波那契数列的前N个数:
>>>fib(10) 1 1 2 3 5 8 13 21 34 55 done
生成器的特点:
1)生成器只有在调用时才会生成相应的数据;
2)只记录当前位置;
3)只有一个__next__()方法;
还可通过yield实现在单线程的情况下实现并发运算的效果:
import time def consumer(name): print("%s 准备吃包子!" %name) while True: baozi = yield print("包子[%s]来了,被[%s]吃了!" %(baozi,name)) c = consumer("ChenRonghua") c.__next__() def produceer(name): c = consumer("a") c2 = consumer("b") c.__next__() c2.__next__() print("老子开始准备做包子啦!") for i in range(10): time.sleep(1) print("做了1个包子,分两半!") c.send(i) c2.send(i) produceer("alex")
迭代器
我们已经知道,可以直接作用于for
循环的数据类型有以下几种:
一类是集合数据类型,如list
、tuple
、dict
、set
、str
等;
一类是generator
,包括生成器和带yield
的generator function。
这些可以直接作用于for
循环的对象统称为可迭代对象:Iterable
。
可以使用isinstance()
判断一个对象是否是Iterable
对象:
>>>from collections import Iterable >>>isinstance([],Iterable) True >>>isinstance({},Iterable) True >>>isinstance('abc',Iterable) True >>> isinstance((x for x in range(10)), Iterable) True >>> isinstance(100, Iterable) False
凡是可作用于for
循环的对象都是Iterable
类型;
凡是可作用于next()
函数的对象都是Iterator
类型,它们表示一个惰性计算的序列;
集合数据类型如list
、dict
、str
等是Iterable
但不是Iterator
,不过可以通过iter()
函数获得一个Iterator
对象。
Python的for
循环本质上就是通过不断调用next()
函数实现的,例如:
for x in [1,2,3,4,5]: pass
实际上完全等价于:
# 首先获得Iterator对象: it = iter([1, 2, 3, 4, 5]) # 循环: while True: try: # 获得下一个值: x = next(it) except StopIteration: # 遇到StopIteration就退出循环 break
3.装饰器
定义:
本质上是个函数,功能是装饰其他函数—就是为其他函数添加附加功能
装饰器原则:
1) 不能修改被装饰函数的源代码;
2) 不能修改被装饰函数的调用方式;
实现装饰器知识储备:
函数即“变量”
定义一个函数相当于把函数体赋值给了函数名
1.函数调用顺序
其他高级语言类似,python不允许在函数未声明之前,对其进行引用或者调用
错误示范:
1 def foo(): 2 print('in the foo') 3 bar() 4 foo() 5 6 报错: 7 in the foo 8 Traceback (most recent call last): 9 File "<pyshell#13>", line 1, in <module> 10 foo() 11 File "<pyshell#12>", line 3, in foo 12 bar() 13 NameError: global name 'bar' is not defined 14 15 def foo(): 16 print('foo') 17 bar() 18 foo() 19 def bar() 20 print('bar') 21 报错:NameError: global name 'bar' is not defined
正确示范:(注意,python为解释执行,函数foo在调用前已经声明了bar和foo,所以bar和foo无顺序之分)
def foo() print('in the foo') bar() def bar(): print('in the bar') foo() def bar(): print('in the bar') def foo(): print('in the foo') bar() foo()
2.高阶函数
满足下列条件之一就可成函数为高阶函数
1.某一函数当做参数传入另一个函数中
2.函数的返回值包含n个函数,n>0
高阶函数示范:
def bar(): print('in the bar') def foo(func): res=func() return res foo(bar)
高阶函数的牛逼之处:
def foo(func): return func print('function body is %s' %(foo(bar))) print('function name is %s' %(foo(bar).func_name)) foo(bar)() #foo(bar)() 等同于bar=foo(bar)然后bar() bar = foo(bar) bar()
3.内嵌函数和变量作用域
定义:在一个函数体内创建另一个函数,这种函数就叫内嵌函数
嵌套函数:
def foo(): def bar(): print('in the bar') bar() foo()
局部作用域和全局做用域的访问顺序
x = 0 def grandpa(): def dad(): x = 2 def son(): x=3 print(x) son() dad() grandpa()
4.高阶函数+内嵌函数=》装饰器
函数参数固定
def decorartor(func): def wrapper(n): print('starting') func(n) print('stopping') return wrapper def test(n): print('in the test arg is %s' %n) decorartor(test)('alex')
函数参数不固定
def decorartor(func): def wrapper(*args,**kwargs): print('starting') func(*args,**kwargs) print('stopping') return wrapper def test(n,x=1): print('in the test arg is %s' %n) decorartor(test)('alex',x=2222)
1.无参装饰器
import time def decorator(func): def wrapper(*args,**kwargs): start_time=time.time() func(*args,**kwargs) stop_time=time.time() print("%s" %(stop_time-start_time)) return wrapper @decorator def test(list_test): for i in list_test: time.sleep(0.1) print('-'*20,i) #decorator(test)(range(10)) test(range(10))
2.有参装饰器
import time def timer(timeout=0): def decorator(func): def wrapper(*args,**kwargs): start=time.time() func(*args,**kwargs) stop=time.time() print('run time is %s ' %(stop-start)) print(timeout) return wrapper return decorator @timer(2) def test(list_test): for i in list_test: time.sleep(0.1) print ('-'*20,i) #timer(timeout=10)(test)(range(10)) test(range(10))
3.终极装饰器
user,passwd = 'alex','abc123' def auth(auth_type): print('auth func:',auth_type) def outer_wrapper(func): def wrapper(*args,**kwargs): print("wrapper func args:",*args,**kwargs) if auth_type=="local": username = input("Username:").strip() password = input("Password:").strip() if user == username and passwd == password: res = func(*args,**kwargs) print("---after authentication") return res else: exit("