PHP函数处理 函数(1): call_user_func(_array)、func_get_arg(s)、func_num_args

2024-05-02 13:48

本文主要是介绍PHP函数处理 函数(1): call_user_func(_array)、func_get_arg(s)、func_num_args,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

函数简介

call_user_func_array

mixed call_user_func_array ( callable $callback , array $param_arr )
把第一个参数作为回调函数(callback)调用,把参数数组(param_arr)作为回调函数的的参数传入。param_arr 要被传入回调函数的数组,这个数组得是索引数组。参数可以引用传递。

call_user_func

mixed call_user_func ( callable $callback [, mixed $parameter [, mixed $… ]] )
第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。
parameter 0个或以上的参数,被传入回调函数。传入call_user_func()的参数不能为引用传递。

func_get_args

array func_get_args ( void ) 获取函数参数列表的数组。
返回一个数组,其中每个元素都是目前用户自定义函数的参数列表的相应元素的副本。

func_num_args

int func_num_args ( void )
Gets the number of arguments passed to the function.

func_get_arg

mixed func_get_arg ( int $arg_num )
从用户自定义函数的参数列表中获取某个指定的参数。
arg_num 参数的偏移量。函数的参数是从0开始计数的。当 arg_num 比实际传入的参数的数目大或小于0的时候发出一个警告,返回 FALSE 。

应用

call_user_func_array

场景一:函数名是未知、函数的参数类型及个数也是未知的
场景二:用于函数回调,回调函数可能是一个普通函数(动态调用普通函数,类似可变函数),可能是类方法,也可能是静态方法。如果使用call_user_func_array,你就不用去判断方法的类型

可以调用静态方法

class mrClass {function test() {if (is_object($this)) {// do something for instance method 实例调用echo 'this is an instance call <br />' . "\n";} else {// do something different for procedural methodecho 'this is a procedure call <br />' . "\n";}}static function testStatic() {if (is_object($this)) {// do something for instance method 实例调用echo 'this is an instance call <br />' . "\n";} else {// do something different for procedural methodecho 'this is a procedure call <br />' . "\n";}}
}$inst = new mrClass();
$inst->test();//Strict standards: Non-static method mrClass::test() should not be called statically
mrClass::test();//静态调用,没有生成$this,输出$this为null,并报错。is_object(null)返回false//Strict standards: Non-static method mrClass::test() should not be called statically
mrClass::testStatic();//静态调用,没有生成$this,输出$this为null,并报错echo '<hr>';//Notice: Undefined variable: this, $this报的错,而不是调用报的错
call_user_func_array(array('mrClass','testStatic'),[]);

可以引用

function increment(&$var)
{$var++;
}$a = 0;
//call_user_func('increment', &$a);//Fatal error: Call-time pass-by-reference has been removed in ...
call_user_func('increment', $a);//Warning: Parameter 1 to increment() expected to be a reference, value given in ...echo $a."\n";call_user_func_array('increment', array(&$a)); // You can use this instead before PHP 5.3
echo $a."\n";//以上例程会输出:
//0
//1

func_num_args、func_get_arg

function foo()
{$numargs = func_num_args();echo "Number of arguments: $numargs<br />\n";if ($numargs >= 2) {echo "Second argument is: " . func_get_arg(1) . "<br />\n";//var_dump(func_get_arg(-1)); //Warning: func_get_arg(): The argument number should be >= 0 in 。。。//var_dump(func_get_arg(6)); //Warning: func_get_arg(): Argument 6 not passed to function in 。。。}$arg_list = func_get_args();for ($i = 0; $i < $numargs; $i++) {echo "Argument $i is: " . $arg_list[$i] . "<br />\n";}
}foo(1, 2, 3);/*
以上例程会输出:Number of arguments: 3<br />Second argument is: 2<br />Argument 0 is: 1<br />Argument 1 is: 2<br />Argument 2 is: 3<br />
*/

call_user_func与直接调用速度区别

在php中,使用“变量函数”(variiable function)会比call_user_func()慢,而call_user_func_array()比call_user_func()还要更慢。

相关的benchmark如下:


# Benchmark (2 million iterations)# Operation                    Seconds
# Literal function          1.218
# Variable function         1.305
# call_user_func()          2.734
# call_user_func_array()    3.386

可以看到,变量函数和普通函数调用(literal function)速度差别不大,和call_user_func相差有一倍以上,而call_user_func_array则要更慢。所以你给的代码才会尽量避免使用call_user_func_array而更倾向于使用变量函数。因为只有很少的函数会有5个以上的参数,所以上面代码里才把1到5个函数的调用用变量函数来写,而只留下小部分的函数用call_user_func_array调用,从而最大的加快程序执行速度。

其实,这些函数的效率差异不会有想象的那么大,上面的benchmark是迭代200万次的结果,如果你的程序只会调用’call_user_func_array’几千次或以下,这些差异将会非常小(大概是0.002秒左右)。

参考

php.net
php call_user_func_array函数有什么不好的地方吗?
php问题 call_user_func_array 这个函数什么时候用?最近再看tp框架 很多地方用到了这个函数
使用call_user_func_array()来回调执行函数与直接使用函数的区别是什么?
Benchmarking magic–PHP

这篇关于PHP函数处理 函数(1): call_user_func(_array)、func_get_arg(s)、func_num_args的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/954393

相关文章

Python+FFmpeg实现视频自动化处理的完整指南

《Python+FFmpeg实现视频自动化处理的完整指南》本文总结了一套在Python中使用subprocess.run调用FFmpeg进行视频自动化处理的解决方案,涵盖了跨平台硬件加速、中间素材处理... 目录一、 跨平台硬件加速:统一接口设计1. 核心映射逻辑2. python 实现代码二、 中间素材处

Go异常处理、泛型和文件操作实例代码

《Go异常处理、泛型和文件操作实例代码》Go语言的异常处理机制与传统的面向对象语言(如Java、C#)所使用的try-catch结构有所不同,它采用了自己独特的设计理念和方法,:本文主要介绍Go异... 目录一:异常处理常见的异常处理向上抛中断程序恢复程序二:泛型泛型函数泛型结构体泛型切片泛型 map三:文

SpringSecurity中的跨域问题处理方案

《SpringSecurity中的跨域问题处理方案》本文介绍了跨域资源共享(CORS)技术在JavaEE开发中的应用,详细讲解了CORS的工作原理,包括简单请求和非简单请求的处理方式,本文结合实例代码... 目录1.什么是CORS2.简单请求3.非简单请求4.Spring跨域解决方案4.1.@CrossOr

pandas使用apply函数给表格同时添加多列

《pandas使用apply函数给表格同时添加多列》本文介绍了利用Pandas的apply函数在DataFrame中同时添加多列,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录一、Pandas使用apply函数给表格同时添加多列二、应用示例一、Pandas使用apply函

requests处理token鉴权接口和jsonpath使用方式

《requests处理token鉴权接口和jsonpath使用方式》文章介绍了如何使用requests库进行token鉴权接口的处理,包括登录提取token并保存,还详述了如何使用jsonpath表达... 目录requests处理token鉴权接口和jsonpath使用json数据提取工具总结reques

Python中Namespace()函数详解

《Python中Namespace()函数详解》Namespace是argparse模块提供的一个类,用于创建命名空间对象,它允许通过点操作符访问数据,比字典更易读,在深度学习项目中常用于加载配置、命... 目录1. 为什么使用 Namespace?2. Namespace 的本质是什么?3. Namesp

C# 空值处理运算符??、?. 及其它常用符号

《C#空值处理运算符??、?.及其它常用符号》本文主要介绍了C#空值处理运算符??、?.及其它常用符号,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录一、核心运算符:直接解决空值问题1.??空合并运算符2.?.空条件运算符二、辅助运算符:扩展空值处理

浅析Python中如何处理Socket超时

《浅析Python中如何处理Socket超时》在网络编程中,Socket是实现网络通信的基础,本文将深入探讨Python中如何处理Socket超时,并提供完整的代码示例和最佳实践,希望对大家有所帮助... 目录开篇引言核心要点逐一深入讲解每个要点1. 设置Socket超时2. 处理超时异常3. 使用sele

MySQL中如何求平均值常见实例(AVG函数详解)

《MySQL中如何求平均值常见实例(AVG函数详解)》MySQLavg()是一个聚合函数,用于返回各种记录中表达式的平均值,:本文主要介绍MySQL中用AVG函数如何求平均值的相关资料,文中通过代... 目录前言一、基本语法二、示例讲解1. 计算全表平均分2. 计算某门课程的平均分(例如:Math)三、结合

SpringMVC配置、映射与参数处理​入门案例详解

《SpringMVC配置、映射与参数处理​入门案例详解》文章介绍了SpringMVC框架的基本概念和使用方法,包括如何配置和编写Controller、设置请求映射规则、使用RestFul风格、获取请求... 目录1.SpringMVC概述2.入门案例①导入相关依赖②配置web.XML③配置SpringMVC