# 一等对象/一等函数
'''
1.在运行时创建
2.能赋值给变量或数据结构中的元素
3.能作为函数的参数传给函数
4.能作为函数的返回值返回结果
'''
# 函数对象本身时function对象的实例
def factorial(n):
'''return n!'''
return 1 if n < 2 else n*factorial(n-1)
"""
print(factorial(42))
print(factorial.__doc__) # 打印函数说明
print(type(factorial))
fact = factorial # 把函数赋值给变量
print(fact)
print(fact(5))
res = list(map(factorial,range(11)))
print(res)
"""
# 高阶函数 : 接受函数为参数,或者把函数作为返回的结果
# map,reduce,filter,sorted
# map,reduce,filter的现代替代者
# map和filter和列表推导式比较
"""
print(list(map(factorial,range(6))))
print([factorial(n) for n in range(6)])
print(list(map(factorial,filter(lambda n:n%2,range(6)))))
print([factorial(n) for n in range(6) if n%2])
"""
# 使用reduce和sum计算0-99的和
"""
from functools import reduce
from operator import add
print(reduce(add,range(100)))
print(sum(range(100)))
"""
# 其他内置归约函数 all any
"""
print(all([1,1,1,1]))
print(all([]))
print(any([1,0,0,0]))
print(any([]))
"""
# 使用lambda表达式反转拼写
"""
fruits = ['strawberry','fig','apple','cherry','raspberry','banana']
res = sorted(fruits,key=lambda word:word[::-1])
print(res)
"""
# 如果lambda表达式难以理解,重构的方法
# 编写注释,说明lambda表达式的作用
# 研究一会儿注释,并找出一个名称来概括注释
# 把lambda表达式转换成def语句,使用那个名称来定义函数
# 删除注释
# 可调用对象
"""
1.用户定义的函数
2.使用def或者lambda表达式创建
3.内置函数
4.使用C语言(cpython)实现的函数,如len或者time.strftime
5.内置方法
6.使用c语言实现的方法,如dict.get
7.方法
8.在类的定义中定义的函数
9.类
调用类的过程:
运行__new__创建一个实例
运行__init__初始化实例
把实例返回给调用方
10.类的实例
如果类定义了__call__方法,那么它的实例可以作为函数调用
11.生成器函数 使用yield关键字的函数或者方法,调用生成器函数返回的是生成器对象
判断是否可调用,可以实用内置函数callable()
"""
"""
print(abs)
print(str)
print([callable(n) for n in (abs,str,int,13.0)])
"""
# 用户定义的可调用类型
"""
import random
class BingoCage:
'''定义一个类,完成了__call__方法
让这个类的实例表现得像一个函数
这个类的实例由任何可迭代对象创建,
调用实例会取出一个元素'''
def __init__(self,items):
self._items = list(items)
random.shuffle(self._items)
def pick(self):
try:
return self._items.pop()
except IndexError:
raise LookupError('pick from empty BingoCage')
def __call__(self):
return self.pick()
if __name__ == '__main__':
bingo = BingoCage(range(3))
print(bingo.pick())
print(bingo())
print(callable(bingo))
"""
# 函数内省
# print(dir(factorial))
# __dict__ : 函数用来存储赋予它的用户属性
# 常规对象没有而函数有的属性
"""
class C:pass
c = C()
def func():pass
print(sorted(set(dir(func)) - set(dir(c))))
# ['__annotations__',:参数和返回值的注解
# '__call__', :实现()运算符,即可调用对象协议
# '__closure__', :函数闭包,即自由变量的绑定,通常为None
# '__code__',:编译成字节码的函数元数据和函数定义体
# '__defaults__',:形式参数的默认值
# '__get__', :实现只读描述符协议
# '__globals__', :函数所在模块中的全局变量
# '__kwdefaults__',: 仅限关键字形式参数的默认值
# '__name__',:函数名称
# '__qualname__':函数的限定名称,如random.choice]
"""
# 从定位参数到仅限关键字参数
# tag函数用于生成html标签,使用名为cls的关键字传入"class"属性,这是一种变通的方法,
# 因为class是python的关键字
def tag(name,*content,cls = None,**attrs): # cls是一个仅限关键字参数
'''生成一个html标签'''
if cls is not None:
attrs['calss'] = cls
if attrs:
attr_str = ''.join(' %s="%s"'%(attr,value)
for attr,value in sorted(attrs.items()))
else:attr_str = ''
if content:
return 'n'.join('<%s %s>%s%s>'%(name,attr_str,c,name) for c in content)
else:
return '<%s %s />'%(name,attr_str)
"""print(tag('br')) # 传入单个位置参数
print(tag('p', 'hello')) # 第一个参数后面的任意个参数会被*content捕获,存入一个元组
print(tag('p', 'hello','world'))
print(tag('p', 'hello',id = 33)) # 没有明确指定名称的参数会被**attrs捕获,存入一个字典
print(tag('p', 'hello','world',cls='sidebar')) # cls参数只能作为关键字参数传入
print(tag(content = 'testing',name='img')) # 第一个位置参数也能作为关键字参数传入
my_tag = {'name':'img','title':'Sunset Boulevard',
'src':'sunset.jpg','cls':'framed'}
print(tag(**my_tag)) # 拆包 同名的键会被绑定到具名的参数上,余下的则被**attrs捕获
"""
# 如果不想支持数量不定的位置参数,但是想支持仅限关键字参数,在签名中放一个*
"""def f(a,*,b): # b必须强制传入关键字参数
return a,b
print(f(1, b=2)) # (1,2)
# print(f(1, 2)) # 报错
print(f(1)) # 报错 必须传入b的关键字参数
"""
# 获取关于参数的信息
"""import bobo
@bobo.query('/')
def hello(person):
return 'hello %s!'%person
print(hello('丁小马'))
"""
# 在指定长度截取字符串的函数
"""def clip(text,max_len = 80):
'''在manx_len的前面或者跟后面的第一个空格处截断文本'''
end = None
if len(text) > max_len:
space_before = text.rfind(' ',0,max_len)
if space_before >= 0 :
end = space_before
else:
space_after = text.rfind(' ',max_len)
if space_after >= 0:
end = space_after
if end is None: # 没找到空格
end = len(text)
return text[:end].rstrip()
print(clip.__defaults__) # >>>(80,)
print(clip.__code__) # >>>