精华内容
下载资源
问答
  • 关键字参数:**others,便于函数功能的扩展 任意的参数列表 *others 解包参数列表 解包参数列表 函数函数式编程 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。 函数能提高应用的...

    目录

    函数与函数式编程

    函数的定义

    函数与过程

    返回值与返回值类型

    前向引用

    内部/内嵌函数

    函数装饰器

    传递函数

    参数的种类

    位置参数

    参数默认值

    命名关键字参数

    关键字参数:**others,便于函数功能的扩展

    任意的参数列表 *others

    解包参数列表  

    解包参数列表  


    函数与函数式编程

    函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

    函数能提高应用的模块性,和代码的重复利用率。Python提供了许多内建函数,比如print()。我们也可以自己创建函数,这被叫做用户自定义函数。

    函数的定义

    我们可以定义一个由自己想要功能的函数,以下是简单的规则:

    函数代码块以def关键词开头,后接函数标识符名称和圆括号()。

    任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。

    函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。

    函数内容以冒号起始,并且缩进。

    return[表达式]结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回None。

    以创建一个输出任意范围内 Fibonacci 数列的函数为例:

    def fib(n):
        a,b=0,1
        while a<n:
            print(a,end=" ")
            a,b=b,a+b
        print()
    fib(2000)

    关键字def引入一个函数定义。它必须后跟函数名称和带括号的形式参数列表。构成函数体的语句从下一行开始,并且必须缩进。

    函数体的第一个语句可以(可选的)是字符串文字;这个字符串文字是函数的文档字符串或docstring。

    函数的执行会引入一个用于函数局部变量的新符号表。更确切地说,函数中所有的变量赋值都将存储在局部符号表中;而变量引用会首先在局部符号表中查找,然后是外层函数的局部符号表,再然后是全局符号表,最后是内置名称的符号表(变量作用域问题,之后会详细介绍)。因此,全局变量和外层函数的变量不能在函数内部直接赋值(除非是在global语句中定义的全局变量,或者是在nonlocal语句中定义的外层函数的变量),尽管它们可以被引用。

    在函数被调用时,实际参数(实参)会被引入被调用函数的本地符号表中;因此,实参是通过按值调用传递的(其中值始终是对象引用而不是对象的值)。当一个函数调用另外一个函数时,将会为该调用创建一个新的本地符号表。

    函数定义会把函数名引入当前的符号表中。函数名称的值具有解释器将其识别为用户定义函数的类型。这个值可以分配给另一个名称,该名称也可以作为一个函数使用。这用作一般的重命名机制:

    print(fib)
    f=fib
    f(
    100)

    上面这个函数是无返回值的函数,即没有return语句,默认返回None。一般来说解释器不会打印出单独的返回值None,如果真想看到它,可以使用print()

    print(fib(0))

    print(fib(1))

    写一个返回斐波那契数列的列表(而不是把它打印出来)的函数,非常简单:

    def fib2(n):
        result=[]
        a,b=0,1;
        while a<n:
            result.append(a)
            a,b=b,a+b
        return result
    f100=fib2(100)
    print(f100)

    函数与过程

    函数与过程都是可以被调用的实体,一般来说,函数有一定的返回值,过程是简单、特殊、没有返回值的函数。

    返回值与返回值类型

    当没有返回值时,Python的实际返回对象是None。

    当返回对象的数目为1时,Python的返回值类型是该对象的类型。

    当返回对象的数目大于1时,Python的返回值类型是元组。

    def fun1():
        pass
    print(fun1())
    def fun2():
        return '123'
    print(fun2())
    def fun_list():
        return ['123','xyz',456]
    print(fun_list())
    def fun_tuple1():
        return 1,2,3
    print(fun_tuple1())
    def fun_tuple2():
        return (1,2,3)
    print(fun_tuple2())

    运行结果:

    None

    123

    ['123', 'xyz', 456]

    (1, 2, 3)

    (1, 2, 3)

    fun1()返回None,fun2()的返回值类型是字符串,fun_list()、fun_tuple1()、fun_tuple2()的返回值大于1个,fun_list()返回的是一个列表,fun_tuple1()、fun_tuple2()等价,都是一个元组。

    所以在我们看来。返回一个容器对象时,好像是返回了多个对象(元组在语法上不需要带括号),事实上,他们仍返回的是一个,一个容器罢了。

    保存元组返回值的三种方法:

    def fun_tuple():
        return 'abc',5,['k','p']
    aTuple=fun_tuple()
    x,y,z=fun_tuple()
    (a,b,c)=fun_tuple()
    print(aTuple)
    print(x,y,z)
    print((a,b,c))

    运行结果:

    ('abc', 5, ['k', 'p'])

    abc 5 ['k', 'p']

    ('abc', 5, ['k', 'p'])

    在对x、y、z和a、b、c的赋值中,根据返回值的顺序,每个变量会接收到与之对应的返回值。而aTuple直接获得函数隐式返回的整个元组。

    前向引用

    def foo():
        print(
    '1')
        bar()

    def bar():
        print(
    '2')
    foo()

    运行结果:

    1

    2

    可见上例中foo()先调用的bar(),然后bar()才声明,系统不会报错。但是不推荐这么写,从感觉上来说,有悖常识,自己尽量让需要用的放在前面吧。

    内部/内嵌函数

    在函数体内部创建另外一个函数是完全合法的,这种函数叫内嵌函数。

    如:

    def foo():
        print('1')
        def bar():
            print('2')
        bar()
    foo()

    运行结果:

    1

    2

    内部函数的整个函数体都在外部函数的作用域里。如果没有任何对bar()的外部引用,那么除了在外部函数体foo()内,任何其他地方都不能对其进行调用。

    另外一个函数体内创建函数对象的方式是使用lambda语句。这个之后的学习会涉及。

    函数装饰器

    暂时看不懂,先不写。

    传递函数

    传递函数的方式大致有三种:

    1. 被引用(访问或者以其他变量作为其别名)
    2. 作为参数传入函数
    3. 作为字典、列表等容器对象的元素

    下面详细介绍一下用其他的变量作为函数的别名。

    def foo():
        print('1')
    bar=foo
    bar()

    运行结果:

    1

    当我们把foo赋给bar时,bar和foo引用了同一个函数对象,所以能以调用foo()相同的方式调用bar()。

    故:foo是函数对象的引用;foo()是函数对象的调用。

    再如:

    def foo():
        print('1')
    def bar(argfunc):
        argfunc()
    bar(foo)

    运行结果:

    1

    参数的种类

    位置参数

    位置参数必须以在被调用函数中的定义的准确顺序来传递。若没有任何默认参数的话,传入函数的参数的精确的数目必须和声明中的数字一致。

    当然,我们也可以不按位置地将关键字参数传入函数,给出关键字来匹配其在参数列表中的合适位置,但是位置参数的数字一定要对。

    def info(name,sex,grades,school='abc'):
        print(name)
        print(sex)
        print(grades)
        print(school)
    info('Jennifer','female','3')
    print()
    info(sex='female',name='Jennifer',school='lalala',grades='1')
    print()
    info(grades='1',sex='male',name='frank')

    运行结果:

    Jennifer

    female

    3

    abc

     

    Jennifer

    female

    1

    lalala

     

    frank

    male

    1

    abc

    参数默认值

    最有用的形式是对一个或多个参数指定一个默认值。这样创建的函数,可以用比定义时允许的更少的参数调用,设置默认参数,必选参数在前,默认参数在后。比如:

    def ask_ok(prompt,retries=4,reminder='Please try again!'):
        while True:
            ok=input(prompt)
            if ok in ('y','ye','yes'):
                return True
            if ok in ('n','no','nop','nope'):
                return False
            retries=retries-1
            if retries<0:
                raise ValueError('invalid user response')
            print(reminder)

    这个函数可以通过几种方式调用:

        只给出必需的参数:ask_ok('Do you really want to quit?')

        给出一个可选的参数:ask_ok('OK to overwrite the file?', 2)

    或者给出所有的参数:ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')

    这个示例还介绍了 in 关键字。它可以测试一个序列是否包含某个值。

    默认值是在定义过程中在函数定义处计算的,所以下例会打印5。

    i=5
    def f(arg=i):
        print(arg)
    i=6
    f()

    重要警告: 默认值只会执行一次这条规则在默认值为可变对象(列表、字典以及大多数类实例)时很重要。比如,下面的函数会存储在后续调用中传递给它的参数:

    def f(a,L=[]):
        L.append(a)
        return L
    print(f(1))
    print(f(2))
    print(f(3))

    打印结果如下:

    如果你不想要在后续调用之间共享默认值,你可以这样写这个函数:

    def f(a,L=None):
        if L is None:
            L=[]
        L.append(a)
        return L
    print(f(1))
    print(f(2))
    print(f(3))

    命名关键字参数

    函数调用时,指定参数名称,称为关键字参数(别和默认参数混淆,这里是函数调用)

    def temp(a,b,c):
    
        print(a)
    
        print(b)
    
        print(c)
    
    temp(1,3,c=99)
    
    temp(a=1,b=2,c=3)
    
    temp(1,b=2,c=100)

    顺序要求:函数调用时,关键字参数必须在普通参数(位置参数)的后面

    temp(100,b=200,c=300)

    temp(a=100,32,100) #错误语法,关键字参数不能在普通参数的前面

    使用字典解包方式传入关键字参数(后面小节中会详细讲到)

    hi = {"a":100,"b":99,"c":1000}

    temp(**hi) #等同于下面#

    temp(a=100,b=99,c=1000)

    函数调用时,当剩余的参数全部为关键字参数时,可随意定义顺序

    当全部为关键字参数时,调用函数时的参数顺序可随意书写,因为你指定了参数名,但是参数的数量不能少于函数定义时要求的位置参数的数量

    temp(c=100,b=38,a=10)

    也可以使用形如kwarg=value的关键字参数来调用函数。例如下面的函数:

    def parrot(voltage,state='a stiff',action='voom',type='Norwegian Blue'):
        print("--This parrot wouldn't",action,end=' ')
        print("if you put",voltage,"volts though it.")
        print("-- Lovely plumage, the", type)
        print("-- It's", state, "!")

    接受一个必需的参数(voltage)和三个可选的参数(state, action,和 type)。这个函数可以通过下面的任何一种方式调用:

    • 一个位置参数:parrot(1000)
    • 一个关键字参数:parrot(voltage=1000)
    • 两个关键字参数;parrot(voltage=1000000, action='VOOOOOM')
    • 两个关键字参数;parrot(action='VOOOOOM', voltage=1000000)
    • 三个位置参数:parrot('a million', 'bereft of life', 'jump')
    • 一个位置参数,一个关键字参数:parrot('a thousand', state='pushing up the daisies')

    但下面的函数调用都是无效的:

    • 丢失必要参数:parrot()
    • 在关键字参数之后的非关键字参数 :parrot(voltage=5.0, 'dead')
    • 同一参数的重复值 :parrot(110, voltage=220)
    • 未知的关键字参数:parrot(actor='John Cleese')

    在函数调用中,关键字参数必须跟随在位置参数的后面。传递的所有关键字参数必须与函数接受的其中一个参数匹配(比如 actor 不是函数 parrot 的有效参数),它们的顺序并不重要。这也包括非可选参数,(比如 parrot(voltage=1000) 也是有效的)。不能对同一个参数多次赋值。下面是一个因为此限制而失败的例子:

    def function(a):
        pass
    function(0,a=0)

    关键字参数:**others,便于函数功能的扩展

    当存在一个形式为**name最后一个形参时,它会接收一个字典其中包含除了与已有形参相对应的关键字参数以外的所有关键字参数。这可以与一个形式为*name接收一个包含除了已有形参列表以外的位置参数的元组的形参组合使用(*name必须出现在**name之前,下一小节会讲到)。例如,如果我们这样定义一个函数:

    def cheeseshop(kind, *arguments, **keywords):
        print("-- Do you have any", kind, "?")
        print("-- I'm sorry, we're all out of", kind)
        for arg in arguments:
            print(arg)
        print("-" * 40)
        for kw in keywords:
            print(kw, ":", keywords[kw])

    它可以像这样调用:

    cheeseshop("Limburger", "It's very runny, sir.",
               "It's really very, VERY runny, sir.",
               shopkeeper="Michael Palin",
               client="John Cleese",
               sketch="Cheese Shop Sketch")

    注意打印时关键字参数的顺序保证与调用函数时提供它们的顺序是相匹配的。

    任意的参数列表 *others

    最后,最不常用的选项是可以使用任意数量的参数调用函数。这些参数会被包含在一个元组里。在可变数量的参数之前,可能会出现零个或多个普通参数。:

    def write_multiple_items(file, separator, *args):
        file.write(separator.join(args))

    一般来说,这些可变参数将在形式参数列表的末尾,因为它们收集传递给函数的所有剩余输入参数。出现在*args参数之后的任何形式参数都是‘仅关键字参数’,也就是说它们只能作为关键字参数而不能是位置参数。

    def concat(*args, sep="/"):
       
    return sep.join(args)
    print(concat("earth", "mars", "venus"))
    print(concat("earth", "mars", "venus", sep="."))

    解包参数列表  

    当参数已经在列表或元组中但需要为需要单独位置参数的函数调用解包时,会发生相反的情况。例如,内置的 range() 函数需要单独的 start 和 stop 参数。如果它们不能单独使用,请使用 * 运算符编写函数调用以从列表或元组中解包参数,*args输出结果是3 6:

    list(range(3,6))
    print(list(range(3,6)))
    args=[3,6]
    print(list(range(*args)))

    以同样的方式,字典可以使用 ** 运算符来提供关键字参数:

    def parrot(voltage, state='a stiff', action='voom'):
        print("-- This parrot wouldn't", action, end=' ')
        print("if you put", voltage, "volts through it.", end=' ')
        print("E's", state, "!")
    d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
    parrot(**d)

    更多Python框架梳理,请参考: 【Python学习】Python最全总结

     有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。

    展开全文
  • 但是我知道你要用哪个函数来处理这个命令, 我也知道你的主模块是什么.cpp或者.h, 或者说, 我根本不用关心你在主模块里怎么处理它, 也应该关心用什么函数处理它...... 怎么办? 使用回调! —— lone wolf...

    转载于:http://blog.csdn.net/vlily/article/details/7244682

    转载于:http://blog.csdn.net/shengnan_wu/article/details/8116935

    转载于:http://blog.csdn.net/callmeback/article/details/4242260/

    转载于:https://blog.csdn.net/initiallysunny/article/details/53708466 

    C++中一个函数作为作为另一个函数的参数:
     把函数名作为参数就是函数的地址了.
    要将函数名作为参数,需要使用函数指针。

    函数指针的定义格式为

    ret_type (*var_name)(arg_list);

    表示返回值为ret_type,参数列表为arg_list的函数指针var_name.

    int (*p)(int,int);

    表示返回值为int,参数为两个int型的函数指针p。

    以函数指针作为形参,即可实现函数名作为参数,由另一个函数调用。
     

    一、 定义某一函数的指针类型:
    就像自定义数据类型一样,我们也可以先定义一个函数指针类型,然后再用这个类型来申明函数指针变量。
    我先给你一个自定义数据类型的例子。
    typedef int* PINT;    //为int* 类型定义了一个PINT的别名
    int main()
    {
      int x;
      PINT px=&x;   //与int * px=&x;是等价的。PINT类型其实就是int * 类型
      *px=10;       //px就是int*类型的变量  
      return 0;
    }
    根据注释,应该不难看懂吧!(虽然你可能很少这样定义使用,但以后学习Win32编程时会经常见到的。)
    下面我们来看一下函数指针类型的定义及使用:(请与上对照!)
    //自行包含头文件
    void MyFun(int x);    //此处的申明也可写成:void MyFun( int );
    typedef void (*FunType)(int );   //这样只是定义一个函数指针类型
    FunType FunP;              //然后用FunType类型来申明全局FunP变量

    int main(int argc, char* argv[])
    {
    //FunType FunP;    //函数指针变量当然也是可以是局部的 ,那就请在这里申明了。 
       MyFun(10);     
       FunP=&MyFun;  
       (*FunP)(20);    

          return 0;
    }

    void MyFun(int x)  
    {
       printf(“%d\n”,x);
    }

    看黑体部分:
    首先,在void (*FunType)(int ); 前加了一个typedef 。这样只是定义一个名为FunType函数指针类型,而不是一个FunType变量。
    然后,FunType FunP;  这句就如PINT px;一样地申明一个FunP变量。
    其它相同。整个程序完成了相同的事。
    这样做法的好处是:
    有了FunType类型后,我们就可以同样地、很方便地用FunType类型来申明多个同类型的函数指针变量了。如下:
    FunType FunP2;
    FunType FunP3;
    //……
     
    二、 函数指针作为某个函数的参数
    既然函数指针变量是一个变量,当然也可以作为某个函数的参数来使用的。所以,你还应知道函数指针是如何作为某个函数的参数来传递使用的。
    给你一个实例:
    要求:我要设计一个CallMyFun函数,这个函数可以通过参数中的函数指针值不同来分别调用MyFun1、MyFun2、MyFun3这三个函数(注:这三个函数的定义格式应相同)。
    实现:代码如下:
    //自行包含头文件 
    void MyFun1(int x);  
    void MyFun2(int x);  
    void MyFun3(int x);  
    typedef void (*FunType)(int ); //②. 定义一个函数指针类型FunType,与①函数类型一至
    void CallMyFun(FunType fp,int x);

    int main(int argc, char* argv[])
    {
       CallMyFun(MyFun1,10);   //⑤. 通过CallMyFun函数分别调用三个不同的函数
       CallMyFun(MyFun2,20);   
       CallMyFun(MyFun3,30);   
    }
    void CallMyFun(FunType fp,int x) //③. 参数fp的类型是FunType。
    {
      fp(x);//④. 通过fp的指针执行传递进来的函数,注意fp所指的函数是有一个参数的
    }
    void MyFun1(int x) // ①. 这是个有一个参数的函数,以下两个函数也相同
    {
       printf(“函数MyFun1中输出:%d\n”,x);
    }
    void MyFun2(int x)  
    {
       printf(“函数MyFun2中输出:%d\n”,x);
    }
    void MyFun3(int x)  
    {
       printf(“函数MyFun3中输出:%d\n”,x);
    }
    输出结果:略
     

     

     

    1. 函数指针是指向函数的指针变量。c在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针指向的地址处。有了指向函数的指针变量后。可以通过该指针变量调用函数,函数指针有两个用途:调用函数、做函数的参数:

      1. 调用函数,如下所示:

     

    输出结果如下:

    由以上可以说明成功调用。

     

       b.无参函数指针做参数的实现,如下(标准写法)所示:

     

    输出结果如下:

     

    还有以下写法也能成功,因为c语言标准规定可以这样用:

     

    也能成功输出

     

    c.带参有返回值的函数指针做参数的

     

     

    输出结果如下:

     

    而不能写成如下所示:

     

    也可写成以下形式,其中涉及到函数指针类型的转换:

     

    2.函数指针数组的实用之处:当我们需要判断大量条件的时候,并且在每一个条件都有相应的处理函数,这时实用switch...case..的代码量会很大,并且效率会比较低,这个时候就可以使用函数指针数组来解决这个问题了,可以使用每个条件为数组下表:如下所示:

    结果如下

     

     

    回调函数

     

    1、基础知识

    所谓回调,就是模块A要通过模块B的某个函数b()完成一定的功能,但是函数b()自己无法实现全部功能,需要反过头来调用模块A中的某个函数a()来完成,这个a()就是回调函数。如下图

    ①约定接口规范。在模块B必须约定接口规范,也就是定义回调函数a()的函数原型

     

    一开始是不好理解,用下面这个例子可能会有帮助:

    诸葛亮(A)给赵子龙(B)一个锦囊(a()),吩咐他在干活时(b())若遇到危急时打开按锦囊(a())指示办, 锦囊里的命令就是回调函数,危急时刻就是回调的时机。 

    不同的锦囊里可以有不同的命令。

     

    在看LWIP时,见到用回调函数,再看某老外公司OPC源代码时,见到用回调函数。看我国内某些代码(我公司软件等)时没用到。于是,我对回调函数产生了很大的好奇。以前,我写VC程序时用到过回调函数,但是没有用C语言来使用。最近,看到国外大量的经典代码中广泛使用了回调函数(LWIP、某两个公司的OPC程序等),都是C语言来实现的,而不是VC windows程序中别人实现自己使用的那种。

    为了弄明白这种函数的奥妙,首先提出三个问题:

    1.        回调函数是什么东西?

    2.        回调函数怎么开发,怎么使用?

    3.        回调函数的作用,应该在什么情况下使用?

     

    带着问题来学习,有目的!呵呵,个人经验。

    打开baidu.com、google.cn搜索了好多资料,如下:

    顺便提一下,某君的一个签名很让我佩服:1好好活着,因为我们会死很久。2五千年的文明 两百年的无奈

     

    第一个问题:

    *******************************************************************************

    其实回调就是一种利用函数指针进行函数调用的过程.  

    为什么要用回调呢?比如我要写一个子模块给你用,   来接收远程socket发来的命令.当我接收到命令后,   需要调用你的主模块的函数,   来进行相应的处理.但是我不知道你要用哪个函数来处理这个命令,     我也不知道你的主模块是什么.cpp或者.h,   或者说,   我根本不用关心你在主模块里怎么处理它,   也不应该关心用什么函数处理它......   怎么办?

    使用回调!

    —— lone wolf

     

    使用回调函数实际上就是在调用某个函数(通常是API函数)时,将自己的一个函数(这个函数为回调函数)的地址作为参数传递给那个函数。而那个函数在需要的时候,利用传递的地址调用回调函数,这时你可以利用这个机会在回调函数中处理消息或完成一定的操作。

    —— 某专家

     

    回调函数,就是由你自己写的。你需要调用另外一个函数,而这个函数的其中一个参数,就是你的这个回调函数名。这样,系统在必要的时候,就会调用你写的回调函数,这样你就可以在回调函数里完成你要做的事。

    —— 绿叶

     

    http://hi.baidu.com/zhuyipeng/blog/item/863fefdb7c736c63d1164eec.html 是一篇比较好的文章。

     

    什么是回调函数?
      回调函数是应用程序提供给Windows系统DLL或其它DLL调用的函数,一般用于截获消息、获取系统信息或处理异步事件。应用程序把回调函数的地址指针告诉DLL,而DLL在适当的时候会调用该函数。回调函数必须遵守事先规定好的参数格式和传递方式,否则DLL一调用它就会引起程序或系统的崩溃。通常情况下,回调函数采用标准WindowsAPI的调用方式,即__stdcall,当然,DLL编制者可以自己定义调用方式,但客户程序也必须遵守相同的规定。在__stdcall方式下,函数的参数按从右到左的顺序压入堆栈,除了明确指明是指针或引用外,参数都按值传递,函数返回之前自己负责把参数从堆栈中弹出。
      理解回调函数!

    —— jufengfeng

     

    Function Pointers provide the concept of callback functions.

    —— newty.de

    *******************************************************************************

    看了这么多的资料,我只将每位的定义总结一下就一句话:回调函数就是函数指针的一种用法。

    在部分资料上,大量讨论了回调函数怎么被调用,到底被谁调用,还有好多的图形,我认为都没有看到问题的本质。

     

     

    第二个问题:

    *********************************************************************

    我实现了一个很简单的回调函数。

    #include <stdio.h>

     

    void printWelcome(int len)

    {

           printf("欢迎欢迎 -- %d/n", len);

    }

     

    void printGoodbye(int len)

    {

           printf("送客送客 -- %d/n", len);

    }

     

    void callback(int times, void (* print)(int))

    {

           int i;

           for (i = 0; i < times; ++i)

           {

                  print(i);

           }

           printf("/n我不知道你是迎客还是送客!/n/n");

    }

    void main(void)

    {

           callback(10, printWelcome);

           callback(10, printGoodbye);

           printWelcome(5);

    }

    *******************************************************************************

    上面的代码没有被任何系统函数调用,说明那些东西只是撒撒土迷迷路人眼而已。还有面相对象编程时,用class给封装起来也是掩人耳目,不要被外表所迷惑。

     

     

    第三个问题:

    *********************************************************************

    用过STL的人都知道,在STL中众多算法和程序都用到回调函数,这实现了一种策略。只要任何符合我的标准的函数和计算都可以用我这个公式。你可以实现各种各样的回调函数,只要符合我的格式就能用。

    就上面的程序来说,你只要函数格式符合cllback第二个参数的格式不论你给别人做饭、铺床叠被都可以正常工作。这就是回调的作用,把回调实现留给别人。

    这是一个用法。

     

    有一位朋友用分层的概念来解释了回调机制:callback函数为B层,main函数和print*函数为A层,A层调用了B层的回调函数callmeback,而B层的回调函数调用了A层的实现函数print*。说白了B层就是一个接口。

     

     

    这是我的理解。Over!

    展开全文
  • golang函数实现默认参数

    千次阅读 2019-10-16 23:21:37
    golang本身并支持像C++那样的函数默认参数,不过可以自己实现相关方法达到默认参数的目的; 以下用创建人的个人信息为例,名字必须输入,而邮箱地址和年龄可以不用输入,输入时使用默认值,示例代码如下: ...

    golang函数实现默认参数

    golang本身并不支持像C++那样的函数默认参数,不过可以自己实现相关方法达到默认参数的目的;

     

    以下用创建人的个人信息为例,名字必须输入,而邮箱地址和年龄可以不用输入,不输入时使用默认值,示例代码如下:

    package main
    
    import (
    	"fmt"
    )
    
    type DetailInfo struct {
    	Email string
    	Age   int
    }
    
    type Handler interface {
    	parse(detail *DetailInfo)
    }
    
    type HandleFunc func(*DetailInfo)
    
    func (f HandleFunc) parse(detail *DetailInfo) {
    	f(detail)
    }
    
    // 针对不同默认参数设置闭包函数, 这里比较关键,闭包函数=函数+运行环境(可以引用外部函数的变量)
    func WithEmail(email string) HandleFunc {
    	return func(detail *DetailInfo) {
    		detail.Email = email
    	}
    }
    
    func WithAge(age int) HandleFunc {
    	return func(detail *DetailInfo) {
    		detail.Age = age
    	}
    }
    
    type Persion struct {
    	Name string
    	DetailInfo
    }
    
    // 这里的接口类Handler并不是必须的,换成闭包函数HandleFunc类型一样可以
    func newPersion(name string, infos ...Handler) Persion {
    	detail := &DetailInfo{
    		Email: "unkown",
    		Age:   -1}
    	for _, info := range infos {
    		// 接口函数调用闭包函数
    		info.parse(detail)
    	}
    
    	return Persion{Name: name, DetailInfo: DetailInfo{Email: detail.Email, Age: detail.Age}}
    }
    
    func main() {
    	persion1 := newPersion("小明")
    	fmt.Println("persion1:", persion1)
    	persion2 := newPersion("小红", WithEmail("xiaohong@qq.com"))
    	fmt.Println("persion2:", persion2)
    	persion3 := newPersion("张三", WithAge(18))
    	fmt.Println("persion3:", persion3)
    	persion4 := newPersion("李四", WithEmail("lisi@qq.com"), WithAge(28))
    	fmt.Println("persion3:", persion4)
    }
    

    输出结果:

    persion1: {小明 {unkown -1}}
    persion2: {小红 {xiaohong@qq.com -1}}
    persion3: {张三 {unkown 18}}
    persion3: {李四 {lisi@qq.com 28}}

    分析:

    1. 关键点是用到了可变参数和闭包函数;

    2. 通过可变参数循环调用闭包函数,给参数赋值;

    3. 通过闭包函数特性(可以引用外部函数的变量),给需要设置的参数赋值;

    展开全文
  • js匿名函数作为函数参数 (返回值作为另一个函数的参数)

    NodeJS 以事件响应的形式返回结果大家都知道的,所以有时候不能直接返回值给函数调用,那就需要在事件响应后把结果返回,于是就用到了匿名函数作为函数参数 (也可以理解为返回值作为另一个函数的参数)。

    代码,以前一般做法:

    function a()
    	{
    		var result = b();
    		document.write(result);
    	}
    	function b()
    	{
    		var a=123; return a;
    	}

    但是如果本身 function b() 里面就嵌套一个事件响应,想把响应的结果返回就不行了。如代码:

    connection.query("select * from table1",function selectCb(err, results, fields) 
    	{
    		if (err) 
    		{
    			console.log("=== query err: sql=["+sql+"], "+err+"===");
    			fun(-1);
    		}
    		return results;//这样在调用函数里面是不会收到返回值的
    	});

    原因:因为Nodejs 非阻塞的问题,以上函数调用后就已经马上返回了,根本等不到数据查询出来。

    相当于调用以下函数aa(),你是不会等得到返回result的,因为调用aa(),执行query()后,接着执行下面的代码,也就是函数已经返回,但其他数据库可能还没有查询出来结果。

    function aa()
    {
    connection.query()
    { 
        var result;
        ....;//数据库查询
        return result;
    }
    return null;
    }
    


    于是就有了这篇文章说的内容,直接上代码原型:

        <!DOCTYPE html>  
        <html lang="en">  
          <head>  
          </head>  
          
          <body>  
            <script>  
            function test( a, b ){  
                a+=1;  
                b(a);  
            }  
          
          test(3, function(result){  
                console.log(result);  
            });  
          
            </script>  
          </body>  
        </html>  

    一个使用例子:Node JS查询数据线信息

    //Nodejs mysql交互的类定义
    function dbHelper(username,password,database,hostname)
    {
        this.username = username;
    	this.password = password;
    	this.database = database;
    	this.hostname = hostname;
    	this.connection = require('mysql').createConnection({
            host:this.hostname,
            user:this.username,
            password:this.password,
            database: this.database
    		});
    	this.query = function(sql,fun)
    	{
    		this.connection.query(sql,function selectCb(err, results, fields) 
    		{
    			if (err) 
    			{
    				console.log("=== query err: sql=["+sql+"], "+err+"===");
    				fun(-1);
    			}
    			fun(results);
    		});
    	}
    }
    
    	var db = new dbHelper('root','123456','nodejs_mysql_test',"localhost");
    	db.query('SELECT * FROM test',function(result){
            console.log("out putting result...");
            //console.log(result);
            for(var i=0;i<result.length;i++)
            {
                console.log(result[i].id);
                console.log(result[i].title);
                console.log(result[i].text);
            }
        });
    
    

    PS,以上dbHelper 的写法,一般在Node js要用module.exports = dbHelper;


    匿名函数参考内容:http://blog.csdn.net/pingfengafei/article/details/44096155

    展开全文
  • python函数除了带参数,带固定参数之外,还有另外三类函数参数有重要使用价值,是提升python水平需要强化的内容。它们是默认参数、元组参数和字典参数。下面举例子说明。 1.默认参数 即在函数定义时赋值的参数。...
  • Python自定义函数及函数参数

    千次阅读 2015-12-08 23:46:56
    Python函数的定义实例如下: def funA(a,b): "函数描述性文字" s=a+b ...可以给函数参数设置默认值,如果需要函数参数设置默认值,则采用如下定义: def funB(a,b=0): "函数描述性文字
  • Scala 函数 - 默认参数函数

    千次阅读 2018-09-15 00:38:20
    Scala允许您指定函数参数的默认值。 这样一个参数可以从函数调用中选择性地省略,在这种情况下,相应的参数值将使用默认值。如果指定其中一个参数,则使用该参数将传递第一个参数,第二个参数将从默认值中获取。 ...
  • 本文学习Python函数,包括:函数调用 定义函数 函数参数 递归函数我们知道圆的面积计算公式为:S = π r*r当我们知道半径r的值时,就可以根据公式计算出面积。假设我们需要计算3个不同大小的圆的面积:r1 = 12.34 ...
  • 函数参数函数调用

    千次阅读 2015-03-14 16:07:06
    1 函数参数 在调用函数时,大多数情况下主调函数和被调函数之间存在着数据传递关系。于是就用到了形式参数和实际参数,简称形参和实参。在定义函数函数名后面括号中的变量称为“形参”,在主调函数(一般为...
  • findContours函数参数详解

    万次阅读 多人点赞 2016-08-19 21:54:17
    注: 这篇文章用的OpenCV版本是2.4.10, 3以上的OpenCV版本相关函数可能有改动Opencv中通过使用findContours函数,简单几个的步骤就可以检测出物体的轮廓,很方便。这些准备继续探讨一下findContours方法中各参数的...
  • python函数参数以及顺序

    千次阅读 2019-02-25 16:25:08
    必选参数(位置参数) 默认参数 可变参数 关键字参数 参数组合 在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都...函数参数 函数的参数-廖雪峰python3 ...
  • 函数指针作为某个函数参数

    千次阅读 2017-01-07 17:31:00
    转载;... 分类: C/C++ ... 函数指针变量是一个变量,可以作为某个函数的... 一个实例: 设计一个 CallMyFun 函数,这个函数可以通过参数中的函数指针值不同来分别调用 MyFun1、MyFun2、MyFun3 这三个函数(注:这
  • python函数的4种参数类型

    万次阅读 多人点赞 2019-06-29 16:18:16
    总结 python 函数中的不同参数类型的使用方法。 在调用函数时,通常会传递参数函数内部的代码保持不变,针对 不同的参数 处理 不同的数据。 有位置传参、关键字传参、默认值参数、多值参数等。 1、参数传递 形参...
  • 我们在C语言编程中会遇到一些参数个数可变的函数,例如printf()  这个函数,它的定义是这样的:  int printf( const char* format, ...);  它除了有一个参数format固定以外,后面跟的参数的个数和类型是  可变的...
  • python中函数参数

    千次阅读 2018-10-25 19:40:29
    1、为什么使用函数? 因为没有函数的编程只是在单纯的写代码逻辑,如果想重用...2、函数参数 (1)、必备参数(位置参数):实参和形参的数量上必须要保持一致。 如: def sum(a,b): c = a+b print(c) sum(1,2) (...
  • C++(笔记)容器(vector)作为函数参数如何传参

    万次阅读 多人点赞 2017-05-17 17:51:54
    一、大致以下类型 void 函数名( vector< int> obj ); void 函数名( vector* pobj );... // 在函数能改变 pobj 指向的对象 ,//调用时不会调用拷贝构造函数 void 函数名( vector< int>& obj ); void
  • C++函数的默认参数详解

    万次阅读 2020-12-01 00:18:09
    规则1: C++规定,默认参数只能放在形参列表的最后,而且一旦为某个形参指定了默认值,那么它后面的所有形参都必须有默认值。...但这样写可以: void func(int a, int b=10, int c=20, int d) { } void fu
  • 函数的参数JS和其他大多数语言一个较为明显的区别就在于函数参数的处理上。因为在JS中调用函数的时候,传入的参数数据类型是可以固定的,个数也无所谓多少个。听起来很奇怪,实际上,JS中的参数在内部是用一个数组...
  • 一、内联函数背景:函数调用是有时间开销的。如果函数本身只有几条语句,执行非常快,而且函数被反复执行很多次,相比之下调用函数所产生的这个开销就会显得比较大。目的:为了减少函数调用的开销,引入了内联函数...
  • python学习——函数参数

    千次阅读 2016-07-09 17:03:00
    对于函数的调用者来说,只需要知道如何传递正确的参数,以及函数将返回什么样的值就够了,函数内部的复杂逻辑被封装起来,调用者无需了解。 Python的函数定义非常简单,但灵活度却非常大。除了正常定义的必选参数外...
  • fopen函数mode参数详解

    万次阅读 2016-12-04 23:23:19
    函数简介: 函数功能:fopen能打开磁盘内的文件,使程序能对文件进行读写。 函数原型:FILE *fopen(const char *path, const char * mode); 传入参数说明: *path——所要打开的文件和路径 *mode——打开文件...
  • 函数指针是指向函数的指针变量。c在编译时,每一个函数都有一个入口地址,该...可以通过该指针变量调用函数函数指针有两个用途:调用函数、做函数参数: 调用函数,如下所示: 输出结果如下: ...
  • 【c语言】函数的默认参数

    千次阅读 2018-11-30 20:19:37
    在c语言中是没有函数...设置函数默认值需要注意有以下几点 1.函数默认值一般写在声明中2.函数的默认值必须设置为自右向左依次赋值 3.默认值只能赋一次 4.函数的默认值能设置为局部变量 第一点: 先写一段简...
  • 就像自定义数据类型一样,我们也可以先定义一个函数指针类型,然后再用这个类型来申明函数指针变量。 我先给你一个自定义数据类型的例子。 typedef int* PINT; //为int* 类型定义了一个PINT的别名 int main() {  ...
  • 我们可以赋予函数参数默认值。所谓默认值就是在调用时,可以写某些参数的值,编译器会自动把默认值传递给调用语句中。默认值可以在声明或定义中设置;但在声明和定义都设置时,会出现重定义默认参数的错误。 ...
  • 就像自定义数据类型一样,我们也可以先定义一个函数指针类型,然后再用这个类型来申明函数指针变量。 我先给你一个自定义数据类型的例子。 typedef int* PINT; //为int* 类型定义了一个PINT的别名 int main
  • http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001374738449338c8a122a7f2e047899fc162f4a7205ea3000########################################################函数参数:...
  • c语言中函数参数处理顺序 下面我们来看2个案例,分析下c语言中函数参数处理顺序。 第一个: #include "stdio.h" void fn(int a,int b,int c) { printf("%d,%d,%d", a, b, c); } void main() { int a = 3; ....
  • 函数声明和定义一般都有参数,C语言中函数声明关注的是函数返回值类型、函数名称、函数参数类型,其中函数参数名称并关注,因此参数名称可以在声明时省略,在定义时取任意名称。 注意:声明和定义是有区别的,具体...
  • 所谓函数,就是把具有独立功能的代码块组织成为一个小模块,在需要的时候调用 函数的使用包含两个步骤 1.定义函数–封装独立的功能 2.调用函数–享受封装的成果 函数的作用:在开发时,使用函数可以提高编写的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,240,556
精华内容 496,222
关键字:

以下哪个函数不需要参数