s14 第4天 关于python3.0编码 函数式编程 装饰器 列表生成式 生成器 内置方法
python3 编码默认为unicode,unicode和utf-8都是默认支持中文的。
如果要python3的编码改为utf-8,则或者在一开始就声明全局使用utf-8
#_*_coding:utf-8_*_
或者将字符串单独声明:
a = "中文".encode("utf-8")
函数式编程
函数式编程中的函数指代的是数学中的函数。
函数式编程输入如果确定,则输出一定是确定的。函数中并没有很多逻辑运算
python是一个面向对象的语言,只是一部分支持函数式编程。
装饰器:
定义:本质是一个函数,装饰其他函数,为其他函数增加附加功能
原则:
1、不能修改被装饰的函数的源代码
2、不能修改被装饰的函数的调用方式
实现装饰器的知识准备:
1、函数即"变量"
定义函数的过程实际是将函数体以字符串的形式保存进内存的过程,当函数()时才是调用执行函数。
因此函数的定义:
def 函数名():
函数体
实际等价于
函数名= “函数体”
因此函数名就是一个变量名。
可以作为一个参数传递给另一个函数
2、高阶函数
a:把一个函数名当做实际参数传递给另一个函数
可以在不修改函数的源代码的情况下实现新功能
def bar():
print("in the bar")
def new_func(func):
print("new_func")
func()
print("after")
原来调用:bar()
新功能调用为:new_func(bar) ,就增加新功能了,但是改变了原函数的调用方法
b:返回值中包含函数名
不修改原函数的调用方式情况下实现新功能
def bar():
print("in the bar")
def new_func(func):
print("new_func")
func()
print("after")
return func
bar = new_func(bar)
bar() # 为改变原函数的调用方式
返回结果
new_func # new_func功能
in the bar # new_func功能
after # new_func功能
in the bar # bar功能
3、嵌套函数
在一个函数的函数体内用def去定义一个新函数
高阶函数+嵌套函数 => 装饰器
装饰器的写法:
1、普通装饰器
def bar():
print("in the bar")
def test(func):
def new_func():
print("new_func")
func()
print("after")
return new_func
@test
bar()
2、装饰器传递参数:
def bar():
print("in the bar")
def test(func)
def new_func(*args,**kwargs):
print("new_func")
func(*args,**kwargs)
print("after")
return new_func
@test
bar("liubo",30)
3、装饰器带参数,即可以在装饰器内做一些判断:
import time
def decorator(type):
def outer(func):
if type=="1":
definner(*args,**kwargs):
start_time=time.time()
ret=func(*args,**kwargs)
stop_time=time.time()
print("func running time is %s" % (stop_time-start_time))
return ret
return inner
else:
def inner(*args,**kwargs):
print("your input is wrong")
return inner
return outer
print("请输入type:")
type=input(">>>")
@decorator(type)
def f1(name,age):
time.sleep(3)
print("your name is{},age is{}".format(name,age))
f1("liubo",30)
列表生成式
a = [i*2 for i in range(10)]
生成的a为
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
改列表生成器等价于
a = []
for i in range(10):
a.append(i*2)
print(a)
列表生成器可以使代码很简洁,任何针对i的for循环都可以写为[i的处理 for循环]的格式
当连续调用2次列表生成器对同一个列表时,结果并不会叠加2次的数据,而是第二次的数据会覆盖第一次的数据
a = [i*2 for i in range(10)]
a = [i*3 for i in range(10)]
print(a)
结果
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
生成器:
如果执行一个循环的结果非常巨大,而我们只用其中一部分内容,那么多余的数据就是无用的。因此我们需要一种工具在执行循环时,每次循环生成一个数据,而之前的数据会释放,而后面的数据并没有生成,不会占地方。这种工具就是生成器。
上面提到的列表生成式,实际就是在生成时就将列表里的元素全部加载进内存的。
如果:(i*2 for i in range(10)),这样就变成了一个生成器,当输入这个命令时,内存中并没有生成任何元素,只是增加了一个生成器
因此获取生成器中的元素就不能用类似列表的切片的方式获取。
生成器只有在调用时才会生成相应的数据,调用可以使用for循环来生成,也可以使用__next__()方法获取下一个元素。而生成器只有调用时保留当前值,因此生成器无法取上一个值。实际for循环就是在for内部反复的调用next方法
如何生成一个生成器?
一个裴波那契数列的生成器:
def fib(max):
n,a,b = 0,0,1
while n < max:
yield b
a,b = b,a+b
n+=1
return "---done----"
f = fib(10) # 创建生成器
此时f就是一个生成器,那么我要应用这个函数中元素就需要使用next的方式调用。
print(f.__next__())
print(f.__next__())
print(f.__next__())
从上面的例子我们可以看到,生成器就是在函数中出现了yield关键字的函数,当函数运行时,遇到yield函数会暂停,并且返回yield后面的值,这样每次我们调用__next__()方法时,程序都会返回当前运行的结果。而return的内容就是异常时产生的消息
生成器的好处
1、节约内存外
2、可以中断数据的生成去做其他的事,然后再返回到生成器中
print(f.__next__())
print("....") # 中断生成器
print(f.__next__()) # 再次进入生成器
print("xxx") #再次中断生成器
print(f.__next__())
通过__next__()方法,当超过了生成器的元素数量时,就会以异常结束,异常的提示就是程序最后返回的值
StopIteration: ----done---- # 异常
那么如果需要避免这个异常,则需要将异常抓出
g = fib(6)
while True:
try: # 如果正常,则尝试循环
x = next(g)
print("g:",x)
except StopIteration as e: # 如果出现了StopIteration ,则按下面执行
print("Generator retrun value:",e.value) # e.value就是出错的返回值,此处为"---done----"
break
调用一个生成器
def f1():
x = 0
while x < 10:
yield x # 第一次调用next会生成0
x += 1 # 第二次next会先加1 然后输出1
f2 = f1() # 首先定义f2,调用f1函数。此时相当于从f2进入了f1函数
print(f2.__next__()) # 之后的每次调用都是从f2 = f1()这里进入的,因此会依次输出0-4
print(f2.__next__())
print(f2.__next__())
print(f2.__next__())
print(f2.__next__())
如果如下
print(f1().__next__()) # 这样相当于每次都是从f1从新进入,因此每次输出都是0。因为每次都是重新调用函数
print(f1().__next__())
print(f1().__next__())
print(f1().__next__())
print(f1().__next__())
在调用生成器的函数中,除了next方法,还有一个send方法。
next方法仅仅是唤醒生成器的yield,让他开始生成元素,但是如果yield没有返回值,则返回值为None。
send方法唤醒yield,同时给yield传递值。
例如
在生成器函数中
baozi = yield
上面这个函数,取一个变量等于yield,程序 运行到此会暂停,但是yield为空,因此如果我用next方法下面调用baozi这个变量,值为空。
但是如果我在调用send方法,则这个值就会被send发送进来。
def cus(name)
print("%s 开始吃包子" % name)
baozi = yield # 包子赋值给yield,但是并没有返回值,这里的作用是停下来同时接收send的值给baozi
print("%s 的包子已经被我吃了" % baozi) # 此处却需要调用baozi这个变量。
那么如果我需要baozi这个变量有值,就需要这样调用:
c = cus("liubo") # 创建生成器并命名为c
c.__next__() # 首先要让生成器运行到yield。
c.send("韭菜馅") # 调用send方法,将"韭菜馅"这个字符串传递给yield,并向下执行
生成器单线程的并行效果 执行案例
import time
def cus(name):
print("%s 开始吃包子" % name)
while True:
baozi = yield # 包子赋值给yield,但是并没有返回值
print("{}:{} 个包子已经被我吃了".format(name,baozi)) # 此处却需要调用baozi这个变量。
def producer(name):
c1 = cus("c1") # 创建生成器
c2 = cus("c2")
c1.__next__() # 让生成器执行到yield,同时也打印cus函数的第一句话,代表c1已准备好
c2.__next__()
for i in range(1,4):
time.sleep(1)
print("{}:我做了2个包子".format(name))
time.sleep(1)
c1.send(i) # 将i传递给c1,i将会被传递给baozi变量以便打印
time.sleep(1)
c2.send(i)
producer("liubo")
上述程序,将使一个厨师和两个食客三个程序同时运行(但实际是串行的)
迭代器
可直接作用于for循环的数据类型:
1、集合数据类型,例如list,tuple,dict,set,str等
2、生成器,包括带yield的生成器
可以直接作用于for循环的对象统称为可迭代对象,Iterable
可以被__next__()函数调用并不断返回下一个值的对象统称为迭代器 Iterator
可以使用isinstance(),判断一个对象是否为Iterable对象
form collections import Iterator
isinstance((x for x in range(10)),Iterator) # isinstance(对象,类型) 判断对象是否为特定类型
可迭代对象不一定是迭代器(list,tuple,dict),但是可以使用iter()函数将其变为迭代器
a = [11,22,33] # 可迭代对象 不是迭代器
b = iter(a) # 就是一个迭代器了,可以用b.__next__()调用下一个元素
迭代器在python代表一个数据流,是一个惰性运算,即只有当用到这个值时才生成这个值,因此迭代器可以代表一个无穷大的序列。
可迭代对象在创建之初即需要创建所有的元素,迭代器的长度是未知的,但是可迭代对象的长度却是已知的。因此可迭代对象不能是迭代器,只能通过iter()函数转换。
内置方法
内置方法 |
功能 |
案例 |
|
abs(x) |
取一个数的绝对值 |
||
all(iterable) |
如果可迭代对象中的所有元素都是True,则返回镇;否则返回False |
print(all([0,1,-3])) |
|
any(iterable) |
如果可迭代对象中有一个元素为真,则返回真。与all相对 |
||
ascii(object) |
将一个对象在acsii中的对应打印出来 |
不常用 |
|
bin(x) |
将一个十进制转换为二进制 |
bin(255) 输出0b11111111 |
|
bool(x) |
返回一个值的真假,空和0都为假 |
||
bytearray(str,encoding) |
默认情况下,字符串和二进制类型都是不允许修改的,但是bytearray是可以修改的 |
b = bytearray("abcde",encoding ="utf-8") print(b) 输出:a2cde,在这里第二个元素b就被替换为acsii表中第50个元素了。在这种情况下我使用b[1]的方式获取的并非b,而是b在ascii中对应的序号。 但是如果直接用b = byte("abcde",encoding ="utf-8"),则针对某个元素的修改实际都是新建这个列表或字符串,而不是在原来的基础上修改 |
不常用 |
callable() |
判断一个对象是否可以调用,即对象是否可以在最后加() |
def test:pass print(callable(test)) 输出 True |
|
chr(i) |
输入一个数字,返回acsii表中对应的元素 |
char(97) 输出"a" |
|
ord() |
输入一个元素,返回ascii表中对应的序号 |
ord("a") 输出97 |
|
classmethod(func) |
|||
compile (code,"文件名",执行方式) |
将一个字符串编译为可以被python执行的语句(此时仍未执行)。 其中code是被编译的字符串,文件名是当出错时日志输出的位置,执行方式是希望被那个命令执行 |
code = "for i in range(10)" c = complie(code,"","exec") exec(c) 输出,执行code的代码。此处使用的exec执行命令 |
|
dict() |
生成一个字典 |
||
dir() |
可以查询对象的内部方法 |
dir([]) 输出列表的方法 ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__' , '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__' , '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__' , '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_e x__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__s izeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'ex tend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] 其中__的是内部方法不可用 |
|
divmod(a,b) |
a和b相除与商和余数 |
x,y = divmod(5,2) print("x=",x) print("y=",y) 输出: x=2 y=1 2为商,1为余数 |
|
enumerate(iterable,start=0) |
将一个可迭代对象序列化,开始的序列为start=中定义的。将可迭代对象中每个元素与其序号单独形成一个新的元组。每个元组就可以分片获取。start如果不写,默认从0开始 |
li = [11,22,33] for i in enumerate(li,start=1): print(i) 输出: (1, 11) (2, 22) (3, 33) |
|
eval(表达式,globals=None,locals=None) |
eval()用来将字符串编译为表达式,例如 s = "8*8" r = eval(s) , print(r)的时候会返回为64,eval只能执行表达式,eval有返回值,如果用eval(“7+8+9”),是能返回结果的,这点比exec强,对比exec。 |
x=1 eveal("x+1") 输出 2 |
|
exec(object) |
exec() 用来执行编译后的代码,和complie何用,先用complie编译,然后用exec执行。exec可以执行所有的python的命令,exec只是执行没有返回值,因此用exec运行一个表达式,是拿不到结果的,例如exec(“7+8+9”),只是执行但是结果是拿不到的。在执行代码的时候exec可以接受代码或者字符串。 |
||
filter(func,iterable) |
将可迭代对象的每个函数带入func中,生成一个迭代器,迭代的元素时func中返回为真的值 |
def func1(a): if a>22: retrun True b = filter(func1,[11,22,33,44]) for i in b: print(i) 返回 33 44 此处也可以直接跟lambda函数 for i in filter(lambda x : x>22,[11,22,33,44]): print(i) 返回 33 44 |
|
map(func,iterable) |
和filter对比,filter方法将返回为真的值生成新的迭代器。 而map方法则将返回值迭代。 |
for i in map(lambda x:x>22,[11,22,33,44]) print(i) 返回 False False True True 当然就是说map会将func的结果直接返回,如果 for i in map(lambda n : n*2,[11,22,33]): print(i) 返回 22 44 66 |
|
import functools |
是一个二元操作函数,他用来将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给reduce中的函数 func()(必须是一个二元操作函数)先对集合中的第1,2个数据进行操作,得到的结果再与第三个数据用func()函数运算,最后得到一个结果。 |
import functools res = functools.reduce(lambda x,y:x*y,range(1,10)) print(res) 上面的函数的结果就是1*2*3*4.....*9。 如描述里面的func必须是一个二元操作的,那么这里的两个变量就会首先从后面的可迭代对象中取前两个,然后按照要求返回,之后会将返回值与下一个对象操作,知道可迭代对象中所有的元素都被处理。 |
|
frozenset() |
将一个集合变成不可修改的集合。 |
a = set([]) 此时的a可以有pop,clear等方法可以修改这个集合 但是如果用 a = frozenset() a就不在有这些方法了 |
|
globals() |
以字典的形式当前整个代码中的所有变量 |
||
hash() |
将一个特定对象进行哈希算法 |
||
hex() |
将数字转为十六进制 |
||
locals() |
以字典形式打印当前代码中的全部的局部变量 |
||
max() |
返回可迭代对象中的最大值 |
||
min() |
返回最小值 |
||
next() |
从迭代器中返回下一个item |
||
oct() |
将一个数字转为八进制 |
||
pow(x,y) |
打印x的y次方的结果 |
||
round(x,y) |
x是一个浮点数,y则为保留小数点后多少位,默认y为0即不显示小数,结果会四舍五入 |
round(1.2323,2) 输出 1.23 |
|
sorted(排序内容,key="排序依据8") |
排序,只能排序int类型的数字。如果排序字典则字典的key必须是int类型 |
可以将字典排序 a = {1:11,2:22,5:55,3:33,4:44} print(sorted(a)) 输出会将key排序输出 [1, 2, 3, 4, 5] print(sorted(a.items())) 字典.items()这个方法本身会将字典转为元组 输出结果为 按照字典key排序,并将字典的键值对变为元组 [(1, 11), (2, 22), (3, 33), (4, 44), (5, 55)] 如果要按照字典的值排序 print(sort(a.items(),key=lambda x:x[1])) 其中,a.items()会将字典的键值对变为元组,每个元组的[0]是键,[1]是值 lambda x:x[1] 是将这个元组带入函数,并返回[1]角标即字典的值, key = lambda x : x[1]代表以字典的值为排序依据 返回结果 [(1, 11), (2, 22), (3, 33), (4, 44), (5, 55)] 以值排序,key可以不是int类型 a = {"zhangsan":11,"lisi":22,5:55,3:33,4:44} print(sorted(a.items(),key=lambdax:x[1])) 返回结果 [('zhangsan', 11), ('lisi', 22), (3, 33), (4, 44), (5, 55)] |
|
sum() |
输入列表,将列表求和 |
||
zip(列表a,列表b) |
将两个列表的元素一一对应,取列表中元素最少的拼接 |
||
__import__() |
正常的import导入模块时后面模块名是一个变量。但是如果模块名是一个字符串,就不能用import。因此需要__import__() |
__import__("decorator") |
匿名函数
函数的目的是为了重复调用,为此建立函数在内存中占用空间,但是如果这个函数仅调用一次这个占用的空间就被浪费了。因此引出了匿名函数。
lambda函数即匿名函数,因为这个函数并未像其他函数一样通过def func()的方式创建了一个func的函数,他并没有创建函数名,因此当还行一次后就没有对应的变量与之关联,其占用的内存空间也就会被回收。
def func(n):
print(n)
这个函数的lambda写法为
lambda n:print(n)
执行时可以
(lambda n:print(n))(5)
a = lambda n : print(n)
a(5)
A = lambda n:print(n) # 这里的A是一个函数
A = (lambda n : print(n))(5) # 这里的A是匿名函数的结果,传递了n = 5给匿名函数后的return
但是lambda只能执行简单的操作,比如三元运算
a = lambda n : print("n<3") if n<3 else print("n>3") # 相当于return 返回了一个三目运算
a(5)
软件目录开发规范
os.path.dirname() |
获取当前目录的上级目录名 |
os.path.abspath(__file__) |
获取当前文件的绝对路径 |
sys.path.append() |
追加环境变量的路径 |
因此如果一个文件的绝对路径为:E:\Atm\bin\atm.py,我需要将E:\Atm路径追加到python模块调用的环境变量中,那么需要这样写
base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(base)
s14 第4天 关于python3.0编码 函数式编程 装饰器 列表生成式 生成器 内置方法的更多相关文章
- [Python3] 037 函数式编程 装饰器
目录 函数式编程 之 装饰器 Decrator 1. 引子 2. 简介 3. 使用 函数式编程 之 装饰器 Decrator 1. 引子 >>> def func(): ... pr ...
- Python基础部分:10、数据类型的内置方法和字符编码
目录 一.数据类型内置方法 1.字典dict内置方法 1.1.类型转换 2.字典必须要掌握的方法 2.1.取值方式 2.2.修改内部数据值 2.3.删除数据 2.4.统计字典中键值对个数 2.5.字典 ...
- python3.x Day4 内置方法,装饰器,生成器,迭代器
内置方法,就是python3提供的各种函数,可以认为是关键字,帮助进行一些列的牛x运算. abs()#取绝对值 all([])#可迭代对象中的所有元素都为True 则为True,只要至少一个为Fals ...
- [Python3] 009 字符串:给你们看看我的内置方法 第一弹
目录 前言 如何查看 python3 中和 str 有关的方法 字符串方法 1. capitalize() 2. casefold() 3. center(width) 4. count(sub[, ...
- [Python3] 015 冰冻集合的内置方法
目录 0. 前言 英文名 元素要求 使用限制 返回 方法数量 1. 如何查看 frozenset() 的内置方法 2. 少废话,上例子 2.1 copy() 2.2 difference() 2.3 ...
- [Python3] 014 集合的内置方法
目录 1. Python3 中如何查看 set() 的内置方法 2. 少废话,上例子 (1) add() (2) 又见清理大师 clear() (3) 又见拷贝君 copy() (4) 找茬君 dif ...
- [Python3] 017 字典的内置方法
目录 1. Python3 中如何查看 dict() 的内置方法 2. 少废话,上例子 (1) 清理大师 clear() (2) 拷贝君 copy() (3) get(key, default=Non ...
- python3.x 基础三:装饰器
装饰器:本质是函数,用于装饰其他函数,在不改变其他函数的调用和代码的前提下,增加新功能 原则: 1.不能修改被装饰函数的源代码 2.不能修改被装饰函数的调用方式 3.装饰函数对于被装饰函数透明 参考如 ...
- 【Flask】 python学习第一章 - 4.0 钩子函数和装饰器路由实现 session-cookie 请求上下文
钩子函数和装饰器路由实现 before_request 每次请求都会触发 before_first_requrest 第一次请求前触发 after_request 请求后触发 并返回参数 tear ...
随机推荐
- All about Performing User-Managed Database Recovery
Automatic Recovery with SET AUTORECOVERY ======================================== Issuing SET AUTORE ...
- 怎样清除SWAP里的文件
在vim 编辑一个文件时断了网,文件就留在SWAP里,但我再vim这个文件保存后,再打开时又提示SWAP里有这文件了,此时swapoff -a后再ls -al查看,把文件所在目录里*.swp结尾的文件 ...
- CSS3样式linear-gradient的使用
linear-gradient linear-gradient是CSS3中新增的样式,主要用于颜色的渐变效果.MDN地址 linear-gradient在不同内核下使用方式不同,详细内容可参考w3cp ...
- C#简单验证并限制登录次数小示例
描述:提示用户输入用户名,密码,与数据库中的数据匹配,如果正确则提示登陆成功,否则,提示登陆失败 错误次数超过三次,提示登陆次数过多,禁止登陆 数据表示例: //数据库中ErrorTimes的次数增加 ...
- EF框架操作postgresql,实现WKT类型坐标的插入,查询,以及判断是否相交
1.组件配置 首先,要下载.NET for Postgresql的驱动,npgsql,EF6,以及EntityFramework6.Npgsql,版本号 3.1.1.0. 由于是mvc项目,所以,把相 ...
- Android Studio报错 Error: A library uses the same package as this project
今天在导入一个项目的时候,as报错 Error: A library uses the same package as this project 经过百度Google 发现解决办法:在modules的 ...
- Josephus问题的不同实现方法与总结
/************************************************************************/ /* Josephus问题--数组实现 */ /* ...
- 网络叠加模式VLAN、VxLAN、GRE
什么是叠加网络 1.一个数据包(或帧)封装在另一个数据包内;被封装的包转发到隧道端点后再被拆装. 2.叠加网络就是使用这种所谓"包内之包"的技术安全地将一个网络隐藏在另一个 网络中 ...
- Angularjs通过$http与服务器通信
angular是一个前端框架,实现了可交互式的页面,但是对于一个web应用,页面上进行展示的数据从哪里来,肯定需要服务端进行支持,那么angular是如何同服务端进行交互的呢? $http angul ...
- POJ 半平面交 模板题 三枚
给出三个半平面交的裸题. 不会的上百度上谷(gu)歌(gou)一下. 毕竟学长的语文是体育老师教的.(卡格玩笑,别当真.) 这种东西明白就好,代码可以当模板. //poj1474 Video Surv ...