参数
*args表示填入多个参数,函数体内args代表的是输入参数组成的元祖
**kwargs表示填入多个参数对,函数体kwargs代表的是输入参数对组成的字典
def A(a,*args):
print(args)
A(1,2,3,4)
def B(**args):
print(args)
B(x=1,b=2)
def C(a,*par1,**par2):
print(a,par1,par2)
C(1,2,3,4,x=1,y=2,d=3)
(2, 3, 4)
{'x': 1, 'b': 2}
1 (2, 3, 4) {'x': 1, 'y': 2, 'd': 3}
lambda用法:
1 作为函数:
def sum(a,b):
return a+b
sum = lambda x,y:x+y
sum(a,b)#same result
面试题:
使用lambda将[‘1’,‘2’,‘3’]转化为int
transfer = lambda arr: [int(i) for i in arr]
transfer(arr)
2 初始化时赋值其他函数
屏蔽time的sleep功能。
time.sleep = lambda x:None
time.sleep(3)#nothing will happen
3 lambda作为其他函数的参数
排序中
res = filter(lambda x: x%2 == 0,[1,2,3,4,5])#py3.0 return object
print(list(res))
res = map(lambda x,y:x+y,[1,2,3,4],[2,3,4])
print(list(res))
dic = {3:'b',1:'c',2:'a'}
res = sorted(dic.items(),key = lambda x:x[1])#print all in the order of values
print(res)
res = sorted(dic.items(),key = lambda x:x[0])
print(res)
res = sorted(dic.keys(),key = lambda x:x)#print keys in their order
print(res)
res = sorted(dic.values(),key = lambda x:x)
print(res)
res=reduce(lambda x,y,:'{},{}'.format(x,y),[1,2,3,4,5,6,7])#connect x and y with ,. the operation will be excuted after first two then iterate on three.
print(res)
生成器,迭代器,装饰器
迭代器,用以生成可以迭代的对象。然后再调用next方法进行迭代
a = [2,4,1,4,5,6]
new_a = iter(a)#let a be object of iteration then use next to print
print(new_a)
print(next(new_a))
print(new_a)
print(next(new_a))
print(new_a)
print(next(new_a))
print(range(6))
for i in a:
print(i)
a = [2,4,1,4,5,6]
new_a = iter(a)#let a be object of iteration then use next to print
while True:
try:
print(next(new_a))
except StopIteration:
print('end')
break
如果长度不够时调用next方法将抛出 StopIteration 的error。
重构iter与next方法。事实上所有类都是 继承 Object类,然后重构内部的方法。
重构:
class Myitr:
def __iter__(self):#iter return self
self.val = 1
return self
def __next__(self):# next return its new value for one iteration
if self.val <=10:
self.val+=1
return self.val
else:
raise StopIteration
my = Myitr()
new = iter(my)
'''print(new.val)###
print(next(new))
print(next(new))
print(next(new))'''
print('########')
#for i in range(100):
# print(next(new))
for i in new:
print(i)#first start from 2 because next return +1 first!!
itration对象有点类似 range()产生的对象,可以通过循环进行调用。
再看生成器,其实就是利用yield建立一个可以暂停的 迭代器对象。在循环中保存当时的信息。(只要使用了yield,就会有这种效果,内部变量在迭代时进行暂停的操作)
def fabonacci(x):
count = 0
a = 0
b = 1
while count<x:
yield b
b,a = a+b,b
count+=1
test = fabonacci(10)
print(test)
for i in test:
print(i)
print('########')
import sys
while True:
try:
print(next(test))#if there is no val in the next, StopIteration error will raise
except:
sys.exit()
test本质就是一个迭代器对象,使用next或者for循环可以进行迭代。
装饰器,装饰器通常是一个命名的对象(不允许使用lambda表达式),在被(装饰函数)调用时接受单一参数,并返回另一个可调用对象。任何含有__ call __ 的对象都可以用作装饰器
@A
def B
A(B)
这两个是相等的
@a
@b
@c
def f ():
pass
f = a(b(c(f)))
作为一个方法的装饰器
def A(cls):
def B(*args,**kwargs):
result = func(*args,**kwargs)
return result
return B
@A
class C:
pass
这里注意的是,方法A下的return B不能直接初始化,需要在call的时候初始化并传递参数
作为一个类的装饰器:
class A:
def __init__(self,func):
self.func = func
def __call__(self,*args,**kwargs):
res = self.func(*args,**kwargs)
return res
参数化装饰器:
def A(num):
def B(func):
def C(**args,**kwargs):
res = None
for _ in range(num):
res = func(*args,**kwargs)
return res
return C
return B
调用时传递循环参数,可以得到连续的func输出。第一层传递迭代次数,第二层传递func,第三层传递参数
保存内省的装饰器:
使用装饰器的常见错误是在使用装饰器时不保存函数元数据(主要是文档字符串和原始函数名)。前面所有示例都存在这个问题。装饰器组合创建了一个新函数,并返回一个新对象,但却完全没有考虑原始函数的标识
解决方案:
在第二层添加 wraps(dunc)
注意:
使用自定义装饰器时,会导致 原函数 A.__ name __返回装饰器的方法名。在装饰器函数中使用 @wraps(func)可以保留函数名
常用领域:插入日志,性能测试,事务处理,缓存,权限校验等
本质是传递初始化函数或方法到 装饰器 (甚至可以携带参数)
引申:普通方法,静态方法,类方法
在这里插入代码片class A:
expl = 'this is test1'
def __init__(self):
pass
def normal_method(self):
print(self.expl)
@classmethod
def cls_method(cls):
print(cls.expl)
@staticmethod
def static_method():
x=1
print('nothing is happening,and x={}'.format(x))
A.static_method()
A.cls_method()
a = A()
a.expl = 'this is new test2'
a.normal_method()
a.cls_method() #not change
a.static_method() #no matter whther it is initialization, it will run normally
nothing is happening,and x=1
this is test1
this is new test2
this is test1
nothing is happening,and x=1
普通方法必须初始化以后才可以调用。
静态方法可以不用初始化就调用,输出自带的属性值。
类方法同样可以不用初始化调用,它会返回类属性的本身值,不会随着初始化以后的内容变化。
引申:单例模式
class B(object):
x='test'
def singleton(cls):
_instance = {}
def check(*args,**kwargs):
if cls not in _instance:
print('init 1')
_instance[cls] = cls(*args,**kwargs)
return _instance[cls]
return check
@singleton
class A():
x='test'
a1 = A()
a2 = A()
b1 = B()
b2 = B()
print(a1,a2)
print(b1,b2)
init 1
<__main__.A object at 0x000001A3CAB79E48> <__main__.A object at 0x000001A3CAB79E48>
<__main__.B object at 0x000001A3CAB8E208> <__main__.B object at 0x000001A3CAB8E240>
可以看到单例模式下,两次初始化的内存位置是一样的