本文主要内容

一等对象

普通函数 & 高阶函数

可调用对象 & 自定义可调用类型

  函数内省

  函数注释

python高级——目录

文中代码均放在github上:https://github.com/ampeeg/cnblogs/tree/master/python高级

一等对象

  1. '''
  2. 在python中,"一等对象"指的是满足下述条件的程序实体:
  3. (1)在运行时创建
  4. (2)能赋值给变量或数据结构中的元素
  5. (3)能作为参数传给函数
  6. (4)能作为函数的返回结果
  7.  
  8. 整数、字符串和字典都是一等对象。在面向对象编程中,函数也是对象,并满足以上条件,所以函数也是一等对象,称为"一等函数"
  9. '''
  10.  
  11. if __name__ == "__main__":
  12. # 函数的一等性质
  13. def foo(n):
  14. '''returns n!'''
  15. return 1 if n < 2 else n * foo(n-1)
  16.  
  17. print(foo(5)) #
  18.  
  19. my_foo = foo
  20. print(my_foo) # <function foo at 0x1010e3f28> 能赋值给变量
  21. print(list(map(my_foo, range(6)))) # [1, 1, 2, 6, 24, 120] 能赋值给函数
  22.  
  23. def foo2():
  24. return foo
  25.  
  26. my_foo2 = foo2()
  27. print(my_foo2(5)) # 120 可作为函数的返回结果

普通函数 & 高阶函数

  1. '''
  2. 我们一般将函数分为"普通函数"和"高阶函数",接受函数为参数的函数为高阶函数,其余为普通函数
  3.  
  4. 普通函数大家再熟悉不过,本文不讲,主要讲一下map、filter、reduce三个高阶函数
  5. '''
  6.  
  7. if __name__ == "__main__":
  8. # map第一个参数接受一个函数,并将这个函数作用于后面可迭代对象的每一个元素中
  9. l = map(lambda x : x ** 2, range(11)) # 返回的是生成器类型
  10. print(list(l)) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
  11.  
  12. w = map(str.upper, 'asfafasfasfaf')
  13. print(list(w)) # ['A', 'S', 'F', 'A', 'F', 'A', 'S', 'F', 'A', 'S', 'F', 'A', 'F']
  14.  
  15. # filter第一个参数也接受函数,并返回所有满足该函数的元素
  16. l = filter(lambda n: n % 2, range(10)) # 返回n % 2为真的数,就是奇数
  17. l2 = filter(lambda n: n % 2 ==0, range(10)) # 返回偶数
  18. print(list(l)) # [1, 3, 5, 7, 9]
  19. print(list(l2)) # [0, 2, 4, 6, 8]
  20.  
  21. # reduce 从python3开始,reduce放在functools中
  22. # reduce将某个操作连续应用到序列元素上,即其会将前一步的结果继续应用到下一个元素上
  23. from functools import reduce
  24. s = reduce(lambda x,y: x + y, range(101))
  25. print(s) # 5050 对1到100求和

可调用对象 & 自定义可调用类型

  1. '''
  2. 我们在使用函数或者实例化对象的时候会用到括号(即()),这个括号实际上是调用运算符,python里面有7中可调用对象:
  3.  
  4. 1、用户定义的函数
  5. def和lambda创建
  6. 2、内置函数
  7. 使用C语言实现的函数,如len或time.strftime
  8. 3、内置方法
  9. 使用C语言实现的方法,如dict.get
  10. 4、方法
  11. 在类的定义体中定义的函数
  12. 5、类
  13. 调用类时其实首先运行的是__new__方法,然后运行__init__方法。这里很有意思,自定义类中其实没有重写__new__方法,
  14. 而是调用的超类的__new__方法,如果查看源代码的实现逻辑,相信你会有新的发现,这里不做讨论。
  15. 6、类的实例
  16. 如果类定义了__call__方法,那么它的实例可以作为函数调用
  17. 7、生长器函数
  18. 使用yield关键字的函数或方法。
  19. '''
  20.  
  21. if __name__ == "__main__":
  22. # 创建一个自定义可调用类
  23. class Foo():
  24. def __init__(self):
  25. self.name = "Foo"
  26. def __call__(self, *args, **kwargs):
  27. print("调用__call__")
  28.  
  29. Foo()() # 输出:调用__call__
  30.  
  31. # 以上使用 Foo()() 这种写法看上去很有意思。首先,Foo()会创建一个Foo实例,调用__init__构造方法,; 然后使用实例(),此时
  32. # 调用__call__方法

函数内省

  1. '''
  2. 函数内省我们通过例子来看
  3. '''
  4.  
  5. if __name__ == "__main__":
  6. # 先创建一个函数
  7. def foo(n):
  8. ''':returns n!'''
  9. return 1 if n<2 else n*foo(n-1)
  10.  
  11. print(foo.__doc__) # :returns n! __doc__里面存储了注释内容
  12.  
  13. # 看看这个函数中有多少属性
  14. print(dir(foo))
  15. '''
  16. ['__annotations__', '__call__', '__class__', '__closure__', '__code__',
  17. '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__',
  18. '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__',
  19. '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__',
  20. '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__',
  21. '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
  22. '''
  23.  
  24. # 下表对一些属性做了说明
名称 类型 说明
__annotations__ dict 参数和返回值的注解
__call__ method-wrapper 实现()运算符
__closure__ tuple 函数闭包
__code__ code 编译成字节码的函数元数据和函数定义体
__defaults__ tuple 形式参数的默认值
__get__ method-wrapper 实现只读描述符协议
__globals__ dict 函数所在模块中的全局变量
__kwdefaults__ dict 仅限关键字形式参数的默认值
__name__ str 函数名称
__qualname__ str 函数的限定名称

函数注释

  1. '''
  2. 函数注解很简单,用下面例子简单讲解即可明了
  3. '''
  4.  
  5. if __name__ == "__main__":
  6. def foo(num: int, step: 'int 间隔(大于0小于num)'=1) -> int:
  7. ''':returns 求num的阶乘,可以设置步长''' # 这里的注释存储在__doc__中
  8. return num if num <= step else num * foo(num-step,step)
  9.  
  10. print(foo(5)) # 120 (5*4*3*2*1)
  11. print(foo(5, 2)) # 15 (5*3)
  12.  
  13. # 函数声明中的各个参数可以在冒号(:)之后增加注释,该注释可以直接写参数类型,也可以写字符串
  14. # -> 符号后面是对函数返回值进行注解
  15.  
  16. # 这些注释内容存储在属性 __annotations__中
  17. print(foo.__annotations__) # {'step': 'int 间隔(大于0小于num)', 'num': <class 'int'>, 'return': <class 'int'>}
  18.  
  19. # 这样注释后,在使用pycharm时会出现自动提示

python高级系列文章目录

python高级——目录

python高级(五)—— python函数(一等对象)的更多相关文章

  1. Python高级编程-Python一切皆对象

    Python高级编程-Python一切皆对象 Python3高级核心技术97讲 笔记 1. Python一切皆对象 1.1 函数和类也是对象,属于Python的一等公民 ""&qu ...

  2. 第三章:Python高级编程-深入类和对象

    第三章:Python高级编程-深入类和对象 Python3高级核心技术97讲 笔记 3.1 鸭子类型和多态 """ 当看到一直鸟走起来像鸭子.游泳起来像鸭子.叫起来像鸭子 ...

  3. 为什么用Python,高级的Python是一种高级编程语言

    Python特性 如果有人问我Python最大的特点是什么,我会毫不犹豫地告诉他:它简单易学,功能强大.作为一个纯自由软件,Python有许多优点: 很简单.基于"优雅".&quo ...

  4. 第九章:Python高级编程-Python socket编程

    第九章:Python高级编程-Python socket编程 Python3高级核心技术97讲 笔记 9.1 弄懂HTTP.Socket.TCP这几个概念 Socket为我们封装好了协议 9.2 cl ...

  5. 【Python】Java程序员学习Python(五)— 函数的定义和使用

    不想做一个待宰的羔羊!!!!要自己变得强大.... 函数的定义和使用放在最前边还是有原因的,现在语言趋于通用,基本类型基本都是那些,重点还是学习对象的使用方法,而最根本的还是方法的使用,因此优先介绍, ...

  6. python基础五(函数、全局变量和局部变量)

    一.全局变量和局部变量 全局变量,即可以在当前文件所有地方都可使用的变量,一次修改,整个文件都影响.如果函数体内部使用全局变量,要先声明global 局部变量,只能在函数体内部使用,除了函数体就不可使 ...

  7. python好用的函数或对象

    1.ljust.rjust "hello".ljust(10,"x") #将字符串hello做对齐,并且用字符'x'补到10个字符 #输出为:helloxxxx ...

  8. python语言(五)匿名函数、读写excel、操作数据库、加密、redis操作

    一.匿名函数 递归:就是调用自己 def func(): num = int(input('num:')) if num % 2 ==0: print('是偶数') return else: func ...

  9. python高级 之(一) --- 函数类型

    函数 模块 模块: 一个py文件就是一个模块, 每个模块之间是可以相互访问的 访问之前需要进行导入 分类: 1.系统提供的模块 math random 2.自己自定义的,自己封装的常用功能的的py文件 ...

  10. python高级内置函数和各种推导式的介绍:一行搞定的代码

    一.知识要点 all 都为真 any 有真的 min 最小的 max 最大的 sum 求和 reversed 反转 sorted 排序 zip 对应合并 [] 列表推倒式 () 生成器 {} 字典推倒 ...

随机推荐

  1. servicestack.redis工具类

    using System;using System.Collections.Generic;using System.Linq;using ServiceStack.Redis;using Servi ...

  2. Qt webkitwidgets模块和webenginewidgets模块

    问题 将Qt开发的程序从Qt5.5或更低的版本迁移到5.6或更高的版本时,会提示webkitwidgets是unknown module. Project ERROR: Unknown module( ...

  3. Redis学习(2)—— 实例与注释说明[转]

    import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import ...

  4. Storm的StreamID使用样例(版本1.0.2)

    随手尝试了一下StreamID的的用法.留个笔记. ==数据样例== { "Address": "小桥镇小桥中学对面", "CityCode" ...

  5. [C#] IEnumerable vs IQueryable

    这篇博客将介绍IEnumerable和IQueryable之间的区别. 1. IQueryable是继承自IEnumerable接口的.所以IEnumerable能做的,IQueryable都能做. ...

  6. functions函数插件的定义和使用

    创建Smarty插件:在插件目录(plugins)里新建文件 类型.插件名.php文件,然后插件方法名字书写规范: smarty_类型_插件名([...]){}在模板(tpl文件)中调用插件时格式{插 ...

  7. C#6.0特性(快来围观)(转)

    出处:http://www.cnblogs.com/HJL-Blog/p/4457632.html 说明一下,很多博友一进来就认为仅仅是语法糖,C#语法的更新,代表着它的进步,语法糖是为了让我们更好的 ...

  8. zrender源码分析2--初始化Storage

    接上次分析到初始化ZRender的源码,这次关注内容仓库Storage的初始化 入口1:new Storage(); // zrender.js /** * ZRender接口类,对外可用的所有接口都 ...

  9. 编写高质量代码改善C#程序的157个建议——建议123:程序集不必与命名空间同名

    建议123:程序集不必与命名空间同名 程序集一般会和命名空间同名,但这并不是必须的.事实上,不同名的命名空间和程序集是很常见的. 程序集表示的是一种物理上的分组,而命名空间是逻辑上的分组,两者没有必然 ...

  10. 编写高质量代码改善C#程序的157个建议——建议102:区分接口和抽象类的应用场合

    建议102:区分接口和抽象类的应用场合 接口和抽象类有一些显而易见的区别: 接口支持多继承,抽象类则不能. 接口可以包含方法.属性.索引器.事件的签名,但不能有实现,抽象类则可以. 接口在增加新方法后 ...