函数

作者: 马梦里 | 来源:发表于2018-01-24 16:51 被阅读0次

转:https://foofish.net/function-is-first-class-object.html

在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。

python 的函数是第一对象

正确理解 python 函数,能够帮我们更好地理解 装饰器(@)、匿名函数(lambda)与函数式编程等高阶技术。

一、函数是对象

在 Python 中万物皆为对象,函数也不例外,函数作为对象可以赋值给一个变量、可以作为元素添加到集合对象中、可作为参数值传递给其它函数,还可以当做函数的返回值,这些特性就是第一类对象所特有的。
简单的函数:

>>> def foo(text):
...     return len(text)
... 
>>> foo('zen of python')
13

函数 foo() 作为一个对象,拥有对象模型的三个通用属性:id、类型、值:

>>> id(foo)
34515536
>>> type(foo)
<class 'function'>
>>> foo
<function foo at 0x020EAA50>

函数作为对象,可以赋值给另外一个变量:

>>> bar = foo
>>> bar
<function foo at 0x020EAA50>
>>> bar("zen of python")
13
>>> bar == foo
True

bar = foo 是因为他们指向一样

图片.png

赋值给另外一个变量时,函数并不会被调用,仅仅是在函数对象上绑定一个新的名字而已(或新名字指向该函数),单纯的起一个新名字不需要加括号和参数;

二、函数可以存储在容器

容器对象(list、dict、set等)中可以放任何对象,包括证书、字符串。函数也可以放在容器对象中:

>>> funcs = [foo, str, len]
>>> funcs
[<function foo at 0x103f45e18>, <class 'str'>, <built-in function len>]
>>> for f in funcs:
...     print(f("hello"))
...
5
hello
5
>>>

foo 是我们自定义的函数,str 和 len 是两个内置函数。可以通过索引或列表遍历来调用函数:

[<function foo at 0x020EAA50>, <class 'str'>, <built-in function len>]
>>> funcs[0]('zen of python')
13

三、函数可以作为参数

函数还可以作为参数传递给另外一个函数:

>>> def show(func):
...     size = func("zen of python")
...     print('length of string is : {}'.format(size))
...     
>>> show(foo)
length of string is : 13

四、函数还可以作为返回值:

>>> def nick():
...     return foo
... 
>>> nick
<function nick at 0x020EA078>
>>> a = nick
>>> a
<function nick at 0x020EA078>
>>> a("python")
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: nick() takes 0 positional arguments but 1 was given
>>> a = nick()
>>> a
<function foo at 0x020EAA50>
>>> a("python")
6

这里有个错误,见最后

还可以简写为:

>>> nick()("python")
6

函数接收一个或多个函数作为输入或者函数输出(返回)的值是函数时,我们称这样的函数为高阶函数,show 和 nick 都属于高阶函数。
python 内置函数中,典型的高阶函数是 map,map 接收一个函数和一个迭代对象作为参数,调用 map 时,依次把迭代对象的元素作为参数调用该函数:

>>> map(foo, ['the', 'zen', 'of', 'python'])
<map object at 0x020D0250>
>>> lens = map(foo, ['the', 'zen', 'of', 'python'])
>>> list(lens)
[3, 3, 2, 6]

map 函数的作用相当于:

>>> [foo(i) for i in ['the', 'zen', 'of', 'python'] ]
[3, 3, 2, 6]

只不过 map 函数的效率更高一点

五、函数可以嵌套

python 还允许函数中定义函数,这种函数叫做嵌套函数:

>>> def get_length(text):
...     def clean(t):                          # 2
...         return t[1:]
...     new_text = clean(text)          # 1
...     return len(new_text)
... 
>>> get_length('python')
5

这个函数的目的是取出字符串的第一个字符后再计算它的长度。get_length 调用时,先执行 1 处的代码,发现有调用 clean 函数,接着执行 2 的代码,把返回值赋值给 new_text,再执行后续代码。

>>> clean("python")
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'clean' is not defined

函数中里面的嵌套函数不能在函数外面被调用,只有局部使用域。

六、实现了 call的类也可以作为函数

对于一个自定义的类,如果实现了 call 方法,那么该类的实例对象的行为就是一个函数,可以被调用:

>>> class ADD:
...     def __init__(self, n):
...         self.n = n
...     def __call__(self, x):
...         return self.n + x
...     
>>> add = ADD(1)
>>> add(4)
5
>>> ADD(1)(4)
5

执行 add(4) 相当于调用 ADD.call(add, 4),self 就是实例对象 add,self
.n 等于 1,所以返回值是:1 + 4:

add(4)
  ||
Add(1)(4)
  ||
Add.__call__(add, 4)

确定对象是否可以调用,可以用内置函数 callable 来判断。

>>> callable(foo)
True
>>> callable(1)
False
>>> callable(int)
True

总结

python 中包含函数在内的一切皆为对象,函数作为第一类对象,支持赋值给变量,支持作为参数传递给其他函数,支持作为其他函数的返回值,支持函数的嵌套,实现了 call 方法的类实例对象也可以当做函数被调用。




有点不明白,调用函数和类,什么时候需要写 (),什么时候不需要写:

函数:

>>> def foo(text):
...     return len(text)
...
>>> def nick():
...     return foo

a = nick 调用的 是 nick 函数本身,有没有参数都可以这样写,相当于给函数起个别名;
b = nick() 调用的是 nick 函数的返回值(foo),nick(var) 函数必须写完整,不然无法返回值;
nick()(var)nick()foo 函数,nick()(var) 是函数 foo 的返回值,等同于 b(var)

类:

>>> class test(object):
...     y = "me"
...     def __init__(self):
...         self.y = 'you'
...         
>>> a = test
>>> a
<class 'test'>
>>> print(a.y)
me
>>> a.y
'me'
>>> b = test()
>>> b
<test object at 0x020D0E50>
>>> b.y
'you'
>>> print(b.y)
you

不带括号,调用的是类本身,没有执行 __init__ 函数;带括号的实例化方法调用了 __init__() 函数,此时必须传入需要的参数;

函数带不带括号,决定了是调用当前函数,还是调用返回值
类带不带括号,决定了掉不掉用 __init__ 方法

相关文章

  • Excel(三)

    AND函数 OR函数 NOT函数 IF函数 频率分析函数FREQUENCY

  • if、else if、for、while、repeat函数

    ①if函数 ②else if函数 ③for函数 ④while函数 ⑤repeat函数

  • strsplit、mapply、paste、match函数

    strsplit函数 mapply函数 strsplit函数 mapply函数 paste函数 match函数 第...

  • Oracle中常用函数(SQL)

    Oracle函授有以下几个分类:数字函数、字符函数、日期函数、转换函数、集合函数、分析函数 数字函数: 字符函数:...

  • MySQL函数

    字符函数 数字运算函数 比较运算符和函数 日期时间函数 信息函数 聚合函数 加密函数 流程函数

  • BI-SQL丨AND & OR & IN

    AND函数 & OR函数 & IN函数 AND函数、OR函数和IN函数都可以理解是WHERE函数的补充,当然也可以...

  • Python之函数

    课程大纲 函数定义 函数的参数 函数的返回值 高阶函数 函数作用域 递归函数 匿名函数 内置函数 函数式编程 将函...

  • 函数基本知识

    函数 函数的定义: def 函数名() 函数的调用:函数名() #不能将函数调用放在函数定义上方 函数的文档注...

  • 积分表——不定期更新

    基本初等函数包括: 常函数: 幂函数 指数函数 对数函数 三角函数 反三角函数 I、反函数Ⅱ、复合函数:初等函数(...

  • MySQL基本使用

    函数 常用函数 数学函数 字符串函数 日期函数

网友评论

      本文标题:函数

      本文链接:https://www.haomeiwen.com/subject/refuaxtx.html