1 前言
函数非常重要,并且我们在数学中早就接触过函数了。
比如,明明y=2x+5
这样简单的函数,为什么数学书上常常会出现下面这样的写法呢?
y=f(x)
f(x)=2x+5
我相信很多人以前其实是根本没有细想过的,甚至觉得这明显就是多此一举。
但待你深入学习数学、乃至其它学科,逐渐你会发现,这样写是有其原因的。
任何领域想要长足的发展,都需要有一定的体系结构,而这些体系结构中会有大量重复、低层次的内容,如果不将其压缩,就会造成后续升级繁琐。
比如,乘法就是对加法的压缩,当你想要计算100*100
时,你不会想到用100个100去相加,因为那样太繁琐。
同样的,专业领域一般都有属于自己的专有名词,比如计算机领域就有硬盘、内存等,它们的作用同样是压缩信息,这样你就不用每次交流都说出一大堆描述性的词来描述这个东西。
也许例子不太恰当,但想来你应该能理解我的意思。
函数对于编程的意义很大程度上也在于此:压缩低层次、相对固定不变的内容,日后直接通过函数名使用即可。
2 深入理解
虽然不同语言中对于函数的实现方法并不相同,但大体可以将函数分为三个部分:
- 参数
- 内部执行语句
- 返回值
也就是说,只要有了上面这三个部分,其实就可以定义一个函数了,比如C/C++中的函数:
返回值 name(参数){
执行语句
}
比如rust中的函数:
fn funname(参数)-> 返回值{
执行语句
}
函数名只是函数的一个标识,是用来寻找这个函数位置的,比如很多语言中都存在匿名函数,就是只使用一次的函数,那就没必要使用函数名,因为它并不是必要的。
更进一步抽象的说,函数其实你也可以理解为一个对象,而函数名,实际上就是这个对象的名称,就和普通的变量没什么区别。
这一点在js代码中就非常常见:
let a=10;
let f=()=>{}
上面这句话就是让f
变量等于一个函数,()
中存放函数参数,{}
中存放执行语句,至于返回值则不需要写,因为js中是在运行时推断的。
上面介绍的都是声明函数,也就是告诉程序我写了这个函数,而想要执行它,基本都是通过下面这种代码形式:
ret=funName(参数);
也就是通过函数名+参数的形式来执行函数,然后将执行的结果交给最前面的变量。
对于函数来说,很多语言还存在函数重载,典型的代表就是C++
,它可以允许你用一个函数名定义多个函数。
但事实上,这多个函数依旧是不同的函数,并且函数名也不会相同,因为C++编译器在编译的时候会根据你函数的参数来修改你的函数名。
这也是为什么C++中重载函数的参数个数、类型、顺序不能完全相同的原因。
至于类函数,其实也是一个普通的函数,只不过它指定了第一个参数为this
指针,也就是当前变量的实例,且不需要我们填。
比如一个类:
class Test{
public:
void fun(int a){}
}
如果能拿到fun函数的地址,那么下面两种写法其实是等价的:
Test t;
t.fun(100);
pfun=&fun; //假设拿到了fun函数的地址
pfun(&t,100);//与上面写法实际上是等价的。
这在rust、go等现代化语言中就可以很好的看出来,它们不再支持类,但允许你使用结构体绑定函数。
3 函数名规则
不同编程语言的函数名命名规则基本都是相同的,只是推荐命名规则不同。
其通用的规则如下:
- 只能包含特定字符:函数名通常只能由字母(大小写英文字母)、数字和下划线组成。例如,
calculate_sum
、get_user_info
等都是符合规则的函数名。 - 不能以数字开头:函数名必须以字母或下划线开头,不能以数字开头。像
123function
就是不合法的,而function123
则是可以的。 - 不区分大小写:大多数编程语言对函数名的大小写是不敏感的。也就是说,
myFunction
和myfunction
会被视为同一个函数,这取决于语言规范,但无论什么语言一般都不推荐用大小写来区分函数的作用。 - 具有描述性:函数名应该能够清晰地表达该函数的功能。例如,一个用于计算两个数之和的函数可以命名为
add_numbers
,这样其他人在阅读代码时就能很容易理解函数的用途。 - 避免使用保留字:不能使用编程语言中的保留字(如
if
、else
、for
等)作为函数名,因为这些保留字在语言中有特定的语法含义。
具体到各个语言内时,虽然上面的规则都是通用的,但也存在一些习惯性的写法:
- Python:推荐使用小写字母,多个单词之间用下划线分隔,这种命名方式被称为蛇形命名法(snake_case),如
calculate_average
。 - Java:遵循驼峰命名法(camelCase),即第一个单词首字母小写,后续单词首字母大写,例如
calculateSum
。 - JavaScript:和 Java 类似,也常用驼峰命名法,如
getUserItem
。 - C++:既可以使用蛇形命名法,也可以使用驼峰命名法,不过在一些大型项目中会有统一的代码风格规范要求。
- Rust:推荐蛇形命名法
但这也仅仅只是推荐,如果你习惯了某个写法,无论什么语言都可以继续使用,这并不会被视作错误,最多只是警告,比如rust使用驼峰式命名、编译器就会警告。