目录

返回函数

偏函数

装饰器

itertools

collections

dir()type()


 

返回函数
'''
高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。
'''
def calc_num(*args):
	ax = 0
	for n in args:
		ax = ax + n
	return ax

print(calc_num(12,23,43))

# 但是,如果不需要立刻求和,而是在后面的代码中,根据需要再计算怎么办?可以不返回求和的结果,而是返回求和的函数:
def lazy_sum(*args):
	def sum():
		ax = 0
		for n in args:
			ax = ax + n
		return ax
	return sum

f = lazy_sum(23,43,545,23)
# 当我们调用lazy_sum()时,返回的并不是求和结果,而是求和函数:
print(f)
# 调用函数f时,才真正计算求和的结果:
print(f())


'''
在这个例子中,我们在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。

返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
'''
def count():
	fs = []
	for i in range(1,4):
		def f():
			return i * i
		fs.append(f)
	return fs
# 返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9。
f1,f2,f3 = count()
print(f1(),f2(),f3())


# 如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:
def count():
	def f(j):
		def g():
			return j * j
		return g
	fs = []
	for i in range(1,4):
		fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()
	return fs

f1,f2,f3 = count()
print(f1(),f2(),f3())
偏函数

 

'''

'''
# int()函数可以把字符串转换为整数,当仅传入字符串时,int()函数默认按十进制转换:
print(int('12'))

# 但int()函数还提供额外的base参数,默认值为10。如果传入base参数,就可以做N进制的转换:
print(int('12345', base = 8))
print(int('12345', base = 16))

# 假设要转换大量的二进制字符串,每次都传入int(x, base=2)非常麻烦,于是,我们想到,可以定义一个int2()的函数,默认把base=2传进去:
def int2(x, base = 2):
	return int(x, base)

print(int2('10000'))
print(int2('10101001'))



# functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2:
import functools

int3 = functools.partial(int, base = 3)
print(int3('102102'))

'''
functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
'''


kw = {'base':5}
print(int('1021234', **kw))

 

装饰器

'''
假设我们要增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
'''
#因为它是一个decorator,所以接受一个函数作为参数,并返回一个函数。
def log(func):
	def wrapper(*args, **kw):
		print('现在在调用 %s():' % func.__name__)
		return func(*args, **kw)
	return wrapper



# 我们要借助Python的@语法,把decorator置于函数的定义处:
@log
def now():
	print('2015-3-25')

f = now
f()

@log
def now2():
	return '2015-43-2'

f = now2
print(f())

# 函数对象有一个__name__属性,可以拿到函数的名字
print(now.__name__)
print(f.__name__)


'''
把@log放到now()函数的定义处,相当于执行了语句:

now = log(now)

由于log()是一个decorator,返回一个函数,所以,原来的now()函数仍然存在,只是现在同名的now变量指向了新的函数,于是调用now()将执行新函数,即在log()函数中返回的wrapper()函数。
'''

'''
wrapper()函数的参数定义是(*args, **kw),因此,wrapper()函数可以接受任意参数的调用。在wrapper()函数内,首先打印日志,再紧接着调用原始函数。

如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数,写出来会更复杂。

比如,要自定义log的文本:
'''
def log(text):
	def decorator(func):
		def wrapper(*args, **kw):
			print('%s %s():' % (text, func.__name__))
			return func(*args, **kw)
		return wrapper
	return decorator

@log('execute')
def now():
	print('balabala')

now()


'''
和两层嵌套的decorator相比,3层嵌套的效果是这样的:

>>> now = log('execute')(now)

我们来剖析上面的语句,首先执行log('execute'),返回的是decorator函数,再调用返回的函数,参数是now函数,返回值最终是wrapper函数。
'''


import functools

def log(func):
	@functools.wraps(func)
	def wrapper(*args, **kw):
		print('call %s():' % func.__name__)
		return func(*args, **kw)
	return wrapper
  itertools
​
'''
itertools

Python的内建模块itertools提供了非常有用的用于操作迭代对象的函数。


itertools模块提供的全部是处理迭代功能的函数,它们的返回值不是list,而是Iterator,只有用for循环迭代的时候才真正计算。
'''

# 我们看看itertools提供的几个“无限”迭代器:
'''
无限序列只有在for迭代时才会无限地迭代下去,如果只是创建了一个迭代对象,它不会事先把无限个元素生成出来,事实上也不可能在内存中创建无限多个元素。
'''
import itertools

# count()会创建一个无限的迭代器,所以上述代码会打印出自然数序列
natuals = itertools.count(1)
for n in natuals: # 执行10000次
    if n == 10000:
        break
    print(n)

# cycle()会把传入的一个序列无限重复下去:
cs = itertools.cycle('ABC')
i = 0
for c in cs:
    i = i + 1
    if i == 1000:
        break
    print(i,c)

# repeat()负责把一个元素无限重复下去,不过如果提供第二个参数就可以限定重复次数:
ns = itertools.repeat('A',5)
for n in ns:
    print(n)



'''
无限序列虽然可以无限迭代下去,但是通常我们会通过takewhile()等函数根据条件判断来截取出一个有限的序列:
'''
natuals = itertools.count(1)
ns = itertools.takewhile(lambda x:x <= 10,natuals)
print(list(ns))



'''
chain()

chain()可以把一组迭代对象串联起来,形成一个更大的迭代器:
'''
for c in itertools.chain('abc','xyz'):
    print(c)

'''
groupby()

groupby()把迭代器中相邻的重复元素挑出来放在一起:
'''
for key,group in itertools.groupby('AAABBBCCCCCAAAAA'):
    print(key,list(group))

for key in itertools.groupby('AAABBBCCCCCAAAAA'):
    print(key)
'''
A ['A', 'A', 'A']
B ['B', 'B', 'B']
C ['C', 'C', 'C', 'C', 'C']
A ['A', 'A', 'A', 'A', 'A']
('A', <itertools._grouper object at 0x00000000020E9198>)
('B', <itertools._grouper object at 0x00000000020E91D0>)
('C', <itertools._grouper object at 0x00000000020E9128>)
('A', <itertools._grouper object at 0x00000000020E9198>)
'''

# 实际上挑选规则是通过函数完成的,只要作用于函数的两个元素返回的值相等,这两个元素就被认为是在一组的,而函数返回值作为组的key。
# 如果我们要忽略大小写分组,就可以让元素'A'和'a'都返回相同的key:
for key,group in itertools.groupby('AaaaaBBBBbbBBBcccCCc',lambda x:x.upper()):
    print(key,list(group))

​
collections
'''
collections

collections是Python内建的一个集合模块,提供了许多有用的集合类。
'''


# namedtuple
# namedtuple是一个函数,它用来创建一个自定义的tuple对象
# 并且规定了tuple元素的个数,并可以用属性而不是索引来引用tuple的某个元素。
# 我们用namedtuple可以很方便地定义一种数据类型,它具备tuple的不变性,又可以根据属性来引用,使用十分方便。
p = (1,2)

from collections import namedtuple

Point = namedtuple('Point',['x','y'])
p = Point(1, 2)
print(p.x, p.y)


# 可以验证创建的Point对象是tuple的一种子类:
print(isinstance(p, Point))
print(isinstance(p, tuple))





'''
deque

使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。

deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:

deque除了实现list的append()和pop()外,还支持appendleft()和popleft(),这样就可以非常高效地往头部添加或删除元素。
'''
from collections import deque

q = deque(['a','b','c'])
q.append('x')
q.appendleft('y')
print(q)





'''
defaultdict

使用dict时,如果引用的Key不存在,就会抛出KeyError。

如果希望key不存在时,返回一个默认值,就可以用defaultdict.

除了在Key不存在时返回默认值,defaultdict的其他行为跟dict是完全一样的。
'''
from collections import defaultdict

dd = defaultdict(lambda:'N/A')
dd['key1'] = 'abc'
print(dd['key1'])
print(dd['key2'])





'''
OrderedDict

使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。

如果要保持Key的顺序,可以用OrderedDict:
'''
from collections import OrderedDict

d = dict([('a',1),('b',2),('c',3)])
print(d)

od = OrderedDict([('a',1),('b',2),('c',3)])
print(od)

# OrderedDict的Key会按照插入的顺序排列,不是Key本身排序:
od = OrderedDict()
od['z'] = 1
od['y'] = 2
od['x'] = 3
print(list(od.keys()))


# OrderedDict可以实现一个FIFO(先进先出)的dict,当容量超出限制时,先删除最早添加的Key:
from collections import OrderedDict

class LastUpdatedOrderedDict(OrderedDict):
    """docstring for LastUpdatedOrderedDict"""
    def __init__(self, capacity):
        super(LastUpdatedOrderedDict, self).__init__()
        self._capacity = capacity
    def __setitem__(self,key,value):
        containsKey = 1 if key in self else 0
        if len(self)-containsKey > self._capacity:
            last = self.popitem(last=False)
            print('remove:',last)
        if containsKey:
            del self[key]
            print('set:',(key,value))
        else:
            print('add:',(key,value))
        OrderedDict.__setitem__(self,key,value)




'''
Counter

Counter是一个简单的计数器,例如,统计字符出现的个数:
'''
from collections import Counter

c = Counter()
for ch in 'programming':
    c[ch] = c[ch] +1

print(c)


python 返回函数,偏函数,装饰器,itertools,collections,dir()type()_默认值

dir()type()
# 判断对象类型,使用type()函数:
print(type(1233))
print(type('str'))
print(type(None))

# 如果一个变量指向函数或者类,也可以用type()判断:
print(type(abs))
print(type(type(1)))

print(type(123)==type(234))
print(type(123)==int)
print(type('abs')==str)
print(type('abc')==type(123))


print('---------------------------------')

# 判断基本数据类型可以直接写int,str等,但如果要判断一个对象是否是函数怎么办?可以使用types模块中定义的常量:
import types

def fn():
	pass

print(type(fn)==types.FunctionType)
print(type(abs)==types.BuiltinFunctionType)
print(type(lambda x : x)==types.LambdaType)
print(type((x for x in range(10)))==types.GeneratorType)


print('---------------------------------')


# 如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list
print(dir('abc'))

print('and'.__len__())
print(len('abcd'))

class MyDog(object):
	"""docstring for MyDog"""
	def __len__(self):
		return 100

dog = MyDog()
print(len(dog))


print('---------------------------------')


class MyObject(object):
	"""docstring for MyObject"""
	def __init__(self):
		self.x = 9
	def power(self):
		return self.x * self.x

obj = MyObject()
print(hasattr(obj, 'x'))  # 有属性'x'吗?
print(obj.x)              # 获取属性'x'
print(hasattr(obj, 'y'))  # 有属性'y'吗?
setattr(obj, 'y', 19)     # 设置一个属性'y'
print(hasattr(obj, 'y'))  # 有属性'y'吗?
print(obj.y)              # 获取属性'y'

# 可以传入一个default参数,如果属性不存在,就返回默认值:
print(getattr(obj, 'z', 404)) # 获取属性'z',如果不存在,返回默认值404

# 也可以获得对象的方法:
print(hasattr(obj, 'power'))
print(getattr(obj, 'power'))
fn = getattr(obj, 'power')
print(fn)
print(fn())


def readImage(fp):
	if hasattr(fp, 'read'):
		return readData(fp)
	return None