python奇遇记:深入的了解函数

很久没更新了,抱歉。最近一段时间忙着对付各种考试,现在总算是考完了,继续来聊聊Python。Python中的函数使用def关键字定义,这个大家都知道,而且Python中函数的定义很灵活,什么位置参数、关键字参数、默认参数、可变参数等等一大堆,而且经常听到的匿名函数又是什么,还有个装饰器、闭包,这些又是什么,我们来详细的讲一讲函数。

函数是一等对象

在Python中,函数就是对象,你可以直接把一个函数赋值给变量,作为参数,或者在函数中返回(这样的函数叫做高阶函数),像下面这样:

# 计算斐波那契

deffactorial(n):'''returns n!'''return1ifn

# 把函数赋值给一个变量

fac = factorialprint(fac(5))

# 作为列表推导式的参数

d = [fac(n)forninrange(6)]print(d)

a = ['sd','sdsd','sdsdssd','s']

# len是python内置的函数

# 直接作为参数

# 对a中的数据按长度大小排序

print(sorted(a, key=len))

120[1, 1, 2, 6, 24, 120]['s', 'sd', 'sdsd', 'sdsdssd']

python中也有匿名函数,不过功能很受限制。python中匿名函数除了作为参数传给高阶函数之外,很少使用到。高阶函数是指那些参数是函数或者返回结果是函数的函数。来看个匿名函数的例子:

a =lambdaa, b: a+b

# 传入参数

a(1,2)

3

可调用对象

可调用对象说的是一个对象可以使用调用,像这样:

# min是内置函数,函数是对象

min([2,34,])

fromdatetimeimportdatetimedatetime.now()

datetime.datetime(2018, 1, 3, 20, 39, 12, 160257)

在Python中,方法、函数、类都是可调用对象,如何让那些不可调用的对象(比如类的实例)变成可调用的?方法是实现call内置方法。我们之前写过一类计算向量的类vector,原来的代码中没有定义call方法:

classVector:

def__init__(self, x=, y=): self.x = x self.y = y

# 真假值,如果向量模为0,返回falsedef__bool__(self):

returnbool(abs(self))

# 实现向量加法def__add__(self, other): x = self.x + other.x y = self.y + other.y

returnVector(x, y)

# 实现向量乘法,例如r*3def__mul__(self, scalar):

returnVector(self.x*scalar, self.y*scalar)

# 返回向量的模# hypot()返回欧几里德范数 sqrt(x*x + y*y)def__abs__(self):

returnhypot(self.x, self.y)

# 实现__repr__方法,在控制台打印向量时会输出Vector(1, 2)# 实现__str__,使用str()返回字符串def__repr__(self):

return'Vector(%r, %r)'% (self.x, self.y)

v = Vector(2,3)

# 我们希望v像Vector一样可以传入参数

# 会报错

v(2,3)

TypeError: 'Vector' object is not callable

出错的原因是因为变量v是不可调用的,它只是Vector类的实例而已。实现call方法之后再来试试:

# 只列出__call__部分的代码

'''def __call__(self, x, y): return Vector(x, y)'''

v = Vector(2,3)

# 现在就可以调用啦

print(v(3,4))v2 = v(3,4)v3 = v(5,4)print(v2+v3)

Vector(3, 4)Vector(8, 8)

就先说这些,装饰器和闭包的内容过于繁琐,下篇文章再讲。

本文来自企鹅号 - 码上就来媒体

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏五分钟学算法

五分钟学会一个有意思的排序:计数排序

由于LeetCode上的算法题很多涉及到一些基础的数据结构,为了更好的理解后续更新的一些复杂题目的动画,推出一个新系列 -----《图解数据结构》,主要使用动画...

786
来自专栏小白客

一文读懂正则表达式的基本用法

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过...

791
来自专栏蓝天

彻底理解C/C++指针

彻底理解C++指针.pdf 推荐阅读pdf版本,原因是从WPS复制粘贴到ChinaUnix后格式有些丢了。

641
来自专栏Java Edge

Java中类型参数“<T>”和无界通配符“<?>”的区别

List<T>最应该出现的地方,应该是定义一个泛型List容器 但List是库里自带的容器,看看ArrayList的源码头一行:

851
来自专栏java学习

面试题35(关于局部变量与全局变量的理解?)

下面代码的运行结果是? public class Demon { public static void main(String[] args) { St...

2405
来自专栏Jed的技术阶梯

普通树简介以及Java代码实现

1571
来自专栏desperate633

[编程题] 奇怪的表达式求值代码

常规的表达式求值,我们都会根据计算的优先级来计算。比如*/的优先级就高于+-。但是小易所生活的世界的表达式规则很简单,从左往右依次计算即可,而且小易所在的世界没...

511
来自专栏从流域到海域

C++对象的赋值和复制

本文属于上篇博文《C++区别于其他语言的知识点总结》第13小节。 13.对象的赋值和复制 对象的赋值:C++中对象可以使用”=”进行赋值,通过重载”=”号...

1789
来自专栏坚毅的PHP

list comprehensions

2011-10-07 列表解析 python很优雅的东西,今天从cookbook稍微深的理解下它,举例: >>> multi = [[0] * 5] * 3 ...

3353
来自专栏Golang语言社区

Go 语言的基本数据类型

0)变量声明 var 变量名字 类型 = 表达式 例: var num int = 10 复制代码 其中“类型”或“= 表达式”两个部分可以省略其中的一个。 1...

36511

扫码关注云+社区