# 一等对象/一等函数
'''
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 addprint(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.用户定义的函数使用def或者lambda表达式创建2.内置函数使用C语言(cpython)实现的函数,如len或者time.strftime3.内置方法使用c语言实现的方法,如dict.get4.方法在类的定义中定义的函数5.类调用类的过程:运行__new__创建一个实例运行__init__初始化实例把实例返回给调用方6.类的实例如果类定义了__call__方法,那么它的实例可以作为函数调用7.生成器函数 使用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():passprint(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'] = clsif 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,bprint(f(1, b=2)) # (1,2)
# print(f(1, 2)) # 报错
print(f(1)) # 报错  必须传入b的关键字参数
"""# 获取关于参数的信息"""import bobo
@bobo.query('/')
def hello(person):return 'hello %s!'%personprint(hello('丁小马'))
"""# 在指定长度截取字符串的函数"""def clip(text,max_len = 80):'''在manx_len的前面或者跟后面的第一个空格处截断文本'''end = Noneif len(text) > max_len:space_before = text.rfind(' ',0,max_len)if space_before >= 0 :end = space_beforeelse:space_after = text.rfind(' ',max_len)if space_after >= 0:end = space_afterif end is None: # 没找到空格end = len(text)return text[:end].rstrip()print(clip.__defaults__) # >>>(80,)
print(clip.__code__) # >>><code object clip at 0x00000281885292F0, file "E:\pythonProjects\pythonProject\读书笔记\流畅的Python\04第五章一等函数\__init__.py", line 205>
print(clip.__code__.co_varnames) # >>>('text', 'max_len', 'end', 'space_before', 'space_after')
print(clip.__code__.co_argcount) # >>>2
"""# 提取函数的签名"""from inspect import signature
sig = signature(clip)
print(sig)for name,param in sig.parameters.items():print(param.kind,':',name,'=',param.default)
# POSITIONAL_OR_KEYWORD : text = <class 'inspect._empty'> 表示没有默认值
# POSITIONAL_OR_KEYWORD : max_len = 80
# .kind属性的值
#     POSITIONAL_OR_KEYWORD:可以通过位置参数和关键字参数传入的形参
#     VAR_POSITIONAL : 定位参数元组
#     VAR_KEYWORD : 关键字参数字典
#     KEYWORD_ONLY : 仅限关键字参数
#     POSITIONAL_ONLY : 仅限位置参数
"""#  把tag函数的签名绑定到一个参数字典上"""import inspect
sig = inspect.signature(tag) # 获取函数签名
my_tag = {'name':'img','title':'Sunset Boulevard','src':'sunset.jpg','cls':'framed'}
bound_args = sig.bind(**my_tag) # 将实参绑定给函数调用中的形参
print(bound_args)
for name,value in bound_args.arguments.items():print(name,'=',value)
del my_tag['name']
bound_args = sig.bind(**my_tag) # 报错缺少了 name参数
"""#函数注解def clip(text:str,max_len:'int > 0' = 80)->str: # 有注解的函数声明'''在manx_len的前面或者跟后面的第一个空格处截断文本'''end = Noneif len(text) > max_len:space_before = text.rfind(' ',0,max_len)if space_before >= 0 :end = space_beforeelse:space_after = text.rfind(' ',max_len)if space_after >= 0:end = space_afterif end is None: # 没找到空格end = len(text)return text[:end].rstrip()print(clip.__annotations__) # 注解存放在这个属性里#从函数签名中提取注解
from inspect import signature
sig = signature(clip)
print(sig.return_annotation)for param in sig.parameters.values():note = repr(param.annotation).ljust(13)print(note,':',param.name,'=',param.default)

operator 和 functools模块介绍


# 计算阶乘
# operator包提供兼用运算符的函数形式"""from functools import  reduce
from operator import muldef fact(n):return reduce(mul,range(1,n+1))print(fact(5))# itemgetter(): 构建一个函数,返回序列的某个位置上的值
# itemgetter(1) 作用等同于 lambda fields:fields[1]
# 使用itemgetter排序一个元组列表
metro_data= [('Tokyo','JP',36.933,(35.689722,139.691667)),('New Yory','US',20.104,(40.808611,-74.020386)),('Delhi NCR','IN',21.935,(28.613889,77.208889)),('Mexico City','MX',20.124,(19.43333,-99.113333)),('Sao Paulo','BR',19.649,(-23.547778,-46.638533))]from operator import itemgetter
for city in sorted(metro_data,key=itemgetter(1)):print(city)# 如果把多个参数传给itemsgetter,它构建的函数会返回提取的值构成的元组cc_name = itemgetter(1,0)
for city in metro_data:print(cc_name(city))# attrgetter:创建的函数根据名称提取对象的属性# 定义一个namedtuple,演示使用attrgetter处理它from collections import namedtuple
LatLong = namedtuple('LatLong','lat long')
Metropolis = namedtuple('Metropolis','name cc pop coord')
metro_areas = [Metropolis(name,cc,pop,LatLong(lat,long))for name,cc,pop,(lat,long) in metro_data]
print(metro_areas[0])
print(metro_areas[0].coord.lat)from operator import attrgettername_lat = attrgetter('name','coord.lat')
for city in sorted(metro_areas,key=attrgetter('coord.lat')):print(name_lat(city))
""""""import operator
# operator中的函数
print([name for name in dir(operator) if not name.startswith('_')])
#['abs', 'add', 'and_', 'attrgetter', 'concat', 'contains', 'countOf',
# 'delitem', 'eq', 'floordiv', 'ge', 'getitem', 'gt', 'iadd', 'iand',
# 'iconcat', 'ifloordiv', 'ilshift', 'imatmul', 'imod', 'imul', 'index',
# 'indexOf', 'inv', 'invert', 'ior', 'ipow', 'irshift', 'is_', 'is_not',
# 'isub', 'itemgetter', 'itruediv', 'ixor', 'le', 'length_hint', 'lshift',
# 'lt', 'matmul', 'methodcaller', 'mod', 'mul', 'ne', 'neg', 'not_', 'or_',
# 'pos', 'pow', 'rshift', 'setitem', 'sub', 'truediv', 'truth', 'xor']
"""# methodcaller"""from operator import methodcaller
s = 'The time has come'
upcase = methodcaller('upper')
print(upcase(s))
hiphenate = methodcaller('replace',' ','_')
print(hiphenate(s))
"""# 使用functools.partial冻结参数
# functools提供了一些列高阶函数
# functools.partial用于部分应用一个函数:
#     基于一个函数创建一个新的可调用对象,把原函数的某些参数固定
#     使用和这个函数可以把接受一个或者多个参数的函数改编成需要会回调的API,这样参数更少
# functools.partial的第一个参数是一个可调用对象,后面是任意个要绑定的位置参数和关键字参数
# 使用partial把一个两个参数的函数改编成需要单参数的可调用对象from functools import partial
from operator import multriple = partial(mul,3) # 固定住做乘法的其中一个数为3
print(triple(7))print(list(map(triple, range(1, 10))))def tag(name,*content,cls = None,**attrs): # cls是一个仅限关键字参数'''生成一个html标签'''if cls is not None:attrs['calss'] = clsif 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)picture = partial(tag,'img',cls = 'pic-frame')
print(picture(src='wupus.jpeg'))
print(picture)
print(picture.func)
print(picture.args)
print(picture.keywords)

读书笔记:《流畅的Python》第五章 一等函数相关推荐

  1. 读书笔记-流畅的python(1-6章)

    前言:这正是本书的主要目的:着重讲解这门语言的基本惯用法,让你的代码简洁.高效且可读,把你打造成熟练的 Python 程序员. 自己总结学习作为输出,很多为了节省时间只是复制粘贴,不具有广泛意义 第一 ...

  2. 《Real-Time Rendering 4th Edition》读书笔记--简单粗糙翻译 第五章 着色基础 Shading Basics

    写在前面的话:因为英语不好,所以看得慢,所以还不如索性按自己的理解简单粗糙翻译一遍,就当是自己的读书笔记了.不对之处甚多,以后理解深刻了,英语好了再回来修改.相信花在本书上的时间和精力是值得的. -- ...

  3. 读书笔记_CLR.via.c#第五章_基元类型_引用类型_值类型

    基元类型 1.不管在什么操作系统上c#的int始终代表32位整数. 2.c#中long代表64位. 类型转换 安全转换时,才允许隐式转型. 不安全转换时,为显式转型. 溢出检测方法 控制溢出的一个办法 ...

  4. C语言基础教程读书笔记5.2.(第五章函数和存储类2)

    4.作用域规则 标示符只能在说明或对他定义它的函数体或分程序内饰可见的,而在该函数体或分程序外则是不可见的. 举个例子: # include <stdio.h> int main() { ...

  5. 《java编程思想》读书笔记(二)第五章(2)

    成员初始化 Java尽力保证:所有变量在使用前都能得到恰当的初始化. 对于方法的局部变量,Java会以编译时报错的形式贯彻这种保证,比如: 1 void f() 2 { 3 int i; //这里编译 ...

  6. 【读书笔记】.NET本质论第四章-Programming with Type(Part Two)

    欢迎阅读本系列其他文章: [读书笔记].NET本质论第一章 The CLR as a Better COM [读书笔记].NET本质论第二章-Components(Part One) [读书笔记].N ...

  7. 【python第五章——函数】

    python第五章--函数 第五章--函数 5.1函数概述 5.2 函数进阶 下面部分之后再写 5.3函数习题(一些小例子) 第五章--函数 5.1函数概述 快速入门: #定义函数 def func( ...

  8. python 第五章 字典

    python 第五章 # # !/usr/bin/python # # -*- coding: utf-8 -*- # # @File : 总结.py # # @time : 2019-07-1010 ...

  9. 【爆肝更新】Python基础教程:第五章_Python函数

    原创:公众号 数据说话 [爆肝更新]Python基础教程:第五章_Python函数 函数介绍 学习目标: 快速体验一下函数的使用 了解函数的作用. 函数:是组织好的,可重复使用的,用来实现特定功能的代 ...

最新文章

  1. awk 内置变量与自定义变量
  2. python requests.packages.urllib3问题记录
  3. docker run -it 如何退出_Docker学习笔记(4)容器的基本命令 1 - 你个小秃头
  4. 设计模式在项目中的应用案例_设计模式在项目中的应用(初学者版)
  5. std::map用法总结
  6. JS 中去除空格和换行的正则表达式写法
  7. python3 协程 写法_理解Python的协程(Coroutine)
  8. 深入分析AsyncTask
  9. centos7配置ntp服务器
  10. [HDCTF2019]Maze
  11. java 快速判断对象是否为null的快捷方法
  12. 互联网监控直播-LiveGBS分发出RTMP、HLS、FLV、RTSP视频流说明介绍
  13. 信息技术基础2(课程笔记)
  14. 直击本质:聊聊小程序的前世今生
  15. kindlenbsp;3nbsp;开箱、注册、装多…
  16. 2017年年终总结 韩俊强的博客
  17. 阿里云国际版如何使用NGINX作为HTTPS转发代理服务器
  18. 2021.9月win10补丁造成共享打印机问题报错0X0000011b
  19. MySQL下载安装运行
  20. 1002: 简单多项式求值 ZZULIOJ

热门文章

  1. python建立分析模型_《利用Python进行数据分析》13.2 使用Patsy创建模型描述
  2. 电磁波波长越短能量越强_5G信号为什么穿墙能力弱?电磁波不是波长越短穿透力越强吗?...
  3. 爬虫练习-爬取《斗破苍穹》全文小说
  4. 联想台式计算机配置单,联想台式电脑报价 联想电脑配置参数
  5. 使用Medusa美杜莎暴力破解SSH密码
  6. web后台管理系统框架
  7. VS2015 注释英文
  8. linux批量修改文件名字
  9. 从中医角度体检健身标准
  10. [重装系统] windows 10 重装系统记录