代码改变世界

第十九章 函数的高级话题

2017-04-09 10:55  szn好色仙人  阅读(402)  评论(0编辑  收藏  举报
'''
void Fun0(CRITICAL_SECTION* p)
{
	LeaveCriticalSection(p);
}
	auto Fun1 = [](CRITICAL_SECTION* p){LeaveCriticalSection(p);};
	CRITICAL_SECTION Cs;
	shared_ptr<CRITICAL_SECTION> pShareCs(&Cs, [](CRITICAL_SECTION* p){LeaveCriticalSection(p);});
	unique_ptr<CRITICAL_SECTION, decltype(Fun0)*> pUniqueCs0(&Cs, Fun0);
	unique_ptr<CRITICAL_SECTION, decltype(Fun1)> pUniqueCs1(&Cs, Fun1);
	//unique_ptr<CRITICAL_SECTION, decltype([](CRITICAL_SECTION* p){LeaveCriticalSection(p);})> pUniqueCs2(&Cs, [](CRITICAL_SECTION* p){LeaveCriticalSection(p);});
	//error C3477: lambda 不能出现在未计算的上下文中
	//unique_ptr<CRITICAL_SECTION> pUniqueCs3(&Cs, Fun1);
	//error C2664: “std::unique_ptr<_Ty>::unique_ptr(_RTL_CRITICAL_SECTION *,const std::default_delete<_Ty> &)”: 不能将参数 2 从“`anonymous-namespace'::<lambda0>”转换为“const std::default_delete<_Ty> &”
'''



#1.
#A:设计函数的时候,最好考虑下代码的重用性
#B:一般需让函数独立于外部的东西,少用全局变量,因为后者容易引发依赖关系,导致程序调试和修改的困难
#C:不要改变可变类型参数,除非调用者希望这样做
#D:每一个函数都应该有一个单一的、统一的目标,否则是无法重用在一个函数中把所有步骤都混合在一起的代码的
#E:每一个函数应该相对较小,一个过长或者有着过深嵌套的函数往往就成为设计缺陷的征兆,保持简单,保持简短
#F:通常来讲,我们应该竭力使函数和其他编程组件中的外部依赖性最小化。函数的自包含性越好,它越容易被理解、复用和修改

#2.
#A:向函数添加任意属性
def fun():pass
value = dir(fun)            #value = ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', ...]
nLen = len(value)           #nLen = 34
fun.count = 0
nLen = len(dir(fun))        #nLen = 35
funCopy = fun
value = funCopy.count       #value = 0

#3.
#A:可以给函数附加注解信息,是与函数的参数合结果相关的任意的用户定义的数据,注解是可选的,并且出现的时候只是附加到函数对象的__annotations__属性以供使用  (annotations 即注释)
#B:如果对参数使用默认值--注解(及其:字符)出现在默认值(及其=字符)之前
#C:注解只对def语句有效,在lambda中无效
def fun(a = 10, b = 20): return a,b
dir0 = fun.__annotations__  #dir0 = {}

def fun(a : int, b : 'B', c : list = [1, 2]) : pass
dir1 = fun.__annotations__  #dir1 = {'a': <class 'int'>, 'b': 'B', 'c': <type>}

def fun(a : int, b : 'B', c : list = [1, 2])-> tuple : return a, b, c
value = fun(1, 2)           #value = (1, 2, [1, 2])
dir2 = fun.__annotations__  #dir2 = {'a': <class 'int'>, 'b': 'B', 'c': <type>, 'return': <type>}

#4.
#A:就像def一样,lambda表达式创建了一个之后能调用的函数,但是它返回一个函数而不是将这个函数赋值给一个变量名
#B:lambda是一个表达式而不是一个语句,所以lambda能出现在Python不允许def出现的地方
#C:lambda的主体是一个单个的表达式而不是一个代码块,只能封装有限的逻辑
#D:在lambda主体中的代码像在def内的代码一样都遵守相同的作用域查找规则
lam0 = lambda x, y, z : x + y + z
value = lam0(1, 2, 3)       #value = 6

lam1 = lambda x, y, z : (y + z if x else y - z)
value = lam1(0, 1, 2)       #value = -1
value = lam1(1, 1, 2)       #value = 3

L0 = [1, 2]
lam2 = lambda : [x ** 2 for x in L0]
value = lam2()              #value = [1, 4]

#lam3 = lambda x : if x: print(x) #无法通过编译

#5.
import sys
from tkinter import Button, mainloop
x = Button(
    text = "press me",
    command = (lambda : print('Hello World')))
x.pack()
mainloop()
#上面这段代码将会创建一个界面,界面上有一个按钮名字为 press me 每次点击都会在控制台输出 Hello World

#6.
#A:map函数会对一个序列对象中的每一个元素应用被传入的函数,返回一个可迭代的对象,包含所有序列元素应用函数调用后的结果
#B:对于多个序列,map期待一个N参数的函数用于N序列
#C:filter根据传入值是否为真来进行筛选,返回为真的值
#D:reduce可以按照给定的方法把输入参数中的序列缩减为单个值,提供第三个参数,当传入序列为空时候的一个默认结果
L0 = [1, 2, 3]
L1 = list(map(lambda x : x + 10, L0))               #L1 = [11, 12, 13]
L2 = list(map(lambda x, y : x + y, L0, L1))         #L2 = [12, 14, 16]
L3 = list(filter(lambda x : x > 0, range(-5, 5)))   #L3 = [1, 2, 3, 4]

from functools import reduce
list0 = [1, 2, 3, 4]
value = reduce(lambda x, y : x + y, list0)          #value = 10
value = reduce(lambda x, y : x * y, list0)          #value = 24

try:
    value = reduce(lambda x, y : x * y, [])
except:
    pass                                            #运行至此
value = reduce(lambda x, y : x * y, [], 'a')        #value = 'a'