精华内容
下载资源
问答
  • 在使用python来编写代码时,会经常使用python调用函数、自带函数或模块,一些不常用的函数或是模块的用途不是很清楚,这时候就需要用到help函数来查看帮助。 这里要注意下,help()函数是查看函数或模块用途的详细...
  • 调用chm文件,HtmlHelp函数 最近在改的defects, 有一个调用chm的。被迫看了看网上的文档,发现不太全,决定自己写一个。 一般的人都喜欢用ShellExecute来调用chm文件。ShellExecute函数可以启动各种类型的文件,...
      
    

    调用chm文件,HtmlHelp函数

          最近在改的defects, 有一个调用chm的。被迫看了看网上的文档,发现不太全,决定自己写一个。

          一般的人都喜欢用ShellExecute来调用chm文件。ShellExecute函数可以启动各种类型的文件,如果chm 文件比较详细,topic比较多,需要在不同的地方打开不同的topic,那么ShellExecute就达不到要求了。

          HtmlHelp函数的使用:

    第一步:安装htmlhelp.exe,你可以从微软的网站上下载:http://www.microsoft.com/downloads/details.aspx?FamilyID=00535334-c8a6-452f-9aa0-d597d16580cc&displaylang=en

    第二步:把htmlhelp.lib引入进来,并且 #include<htmlhelp.h>

    第三步:现在可以用了。

    HtmlHelp(NULL, cstr1, HH_DISPLAY_TOPIC, (DWORD)cstr2.GetBuffer());

    第一个参数:是父窗口句柄。

    第二个参数cstr1: 是你chm的名字,比如C:/sample.chm,

    第三个参数HH_DISPLAY_TOPIC:是你显示的方式,目前的传入的HH_DISPLAY_TOPIC是说cstr2是topic。

    第四个参数cstr2: 是根据第3个参数不同传入不同的类型的。

    具体可以参考MSDN,我会在文章最后附上MSDN上面的解释

     

    目前就有一个问题了,你说你也不知道这个chm里面的topic是什么。

    把chm的文件后缀改成 .zip。 解压以后发现一个ContextId*.h 文件。自己进去找。

    介绍一个例子,在下面的网址,这个不但是一个例子,还是一个小工具可以查看chm文件里面的Context id 和 topic。 值得一看,但是他的输入路径有点问题,自己改一下就能用了。

    http://www.codeproject.com/KB/winhelp/htmlhelp.aspx

     

     

    About the HTML Help API Function

    The HTML Help API has one function that displays a help window. Using the API commands, you can specify which topic to display in the help window, whether the help window is a three-pane Help Viewer or a pop-up window, and whether the HTML topic file should be accessed via a context ID, an HTML Help URL, or a Keyword link (KLink) lookup.

    HTML Help API syntax

    HWND HtmlHelp(
                  HWND    hwndCaller,
                  LPCSTR  pszFile,
                  UINT    uCommand,
                  DWORD   dwData) ;

    Parameters

    hwndCaller
    Specifies the handle ( hwnd) of the window calling HtmlHelp(). The help window is owned by this window.

    When the help window is closed, HtmlHelp() will return focus to the owner unless the owner is the desktop. If hwndCaller is the desktop, then the operating system determines where focus is returned.

    In addition, if HtmlHelp() sends any notification messages from the help window, they are sent to hwndCaller as long as you have enabled notification message tracking in the help window definition.

    pszFile
    Depending on the uCommand value, specifies the file path to either a compiled help (.chm) file, or a topic file within a specified help file.

    A window type name can also be specified, preceded with a greater-than (>) character.

    If the specified command does not require a file, this value may be NULL.

    uCommand
    Specifies the command to complete.
    dwData
    Specifies any data that may be required, based on the value of the uCommand parameter.

    Return Value

    Depending on the specified uCommand and the result, HtmlHelp() returns one or both of the following:

    • The handle (hwnd) of the help window.
    • NULL. In some cases, NULL indicates failure; in other cases, NULL indicates that the help window has not yet been created.

    Example

    The following example calls the HH_DISPLAY_TOPIC command to open the help file named Help.chm and display its default topic in the help window named Mainwin. Generally, the help window specified in this command is a standard HTML Help Viewer.

    HWND hwnd =
       HtmlHelp(
                GetDesktopWindow(),
                "c://Help.chm::/Intro.htm>Mainwin",
                HH_DISPLAY_TOPIC,
                NULL) ;
    Note   When using the HTML Help API, set the stack size of the hosting executable to at least 100k. If the defined stack size is too small, then the thread created to run HTML Help will also be created with this stack size, and failure could result. Optionally, you can remove /STACK from the link command line, and remove any STACK setting in the executable's DEF file (default stack size is 1MB in this case). You can also you can set the stack size using the /Fnumber compiler command (the compiler will pass this to the linker as /STACK).

    See Also

    展开全文
  • 本文学习Python函数,包括:函数调用 定义函数 函数的参数 递归函数我们知道圆的面积计算公式为:S = π r*r当我们知道半径r的值时,就可以根据公式计算出面积。假设我们需要计算3个不同大小的圆的面积:r1 = 12.34 ...

    本文学习Python函数,包括:函数调用 定义函数 函数的参数 递归函数

    我们知道圆的面积计算公式为:S = π r*r

    当我们知道半径r的值时,就可以根据公式计算出面积。假设我们需要计算3个不同大小的圆的面积:

    r1 = 12.34
    r2 = 9.08
    r3 = 73.1
    s1 = 3.14 * r1 *r1
    s2 = 3.14 * r2 *r2
    s3 = 3.14 * r3 *r3

    当代码出现有规律的重复的时候,我们需要注意,每次写3.14 * x*x不仅麻烦,而且,如果要把3.14改成3.14159265359的时候,得全部替换。

    有了函数,我们就不再每次写s = 3.14 * x * x,而是写成更有意义的函数调用s = area_of_circle(x),而函数area_of_circle()本身只需要写一次,就可以多次调用。

    基本上所有的高级语言都支持函数,Python也不例外。Python不但能非常灵活的定义函数,而且本身内置了很多有用的函数,可以直接调用。

    抽象

    抽象是数学中非常常见的概念。例如:
    计算数列的和,比如:1+2+3+4+…+100,写起来十分不方便,于是数学家发明了求和符号∑,可以把1+2+3+4+…+100记作:
    100
    ∑n
    n=1
    这种抽象记法非常强大,因为我们看到∑就可以理解成求和,而不是还原成低级的加法运算。

    而且,这种抽象记法是可以扩展的,比如:
    100
    ∑(n*n+1)
    n=1
    还原成加法运算就变成了:
    (1*1+1)+(2*2+1)+(3×3+1)+…+(100*100+1)
    可见,借助抽象,我们才能不关心底层的具体计算过程,而直接在更高的层次上思考问题。

    我们写计算机程序也是一样的,函数就是最基本的一种代码抽象的方式。

    使用函数

    Python内置了很多有用的函数,我们可以直接调用。

    要调用一个函数,需要知道函数名称和参数,比如求绝对值的函数abs,只有一个参数。可以直接从Python的官方网站查看文档:

    https://docs.python.org/3/library/functions.html#abs

    这里写图片描述
    也可以在交互式命令行里面通过help(abs)查看abs函数的帮助信息:

    Help on built-in function abs in module builtins:
    
    abs(x, /)
        Return the absolute value of the argument.

    调用abs函数:

    >>> abs(100)
    100
    >>> abs(-20)
    20
    >>> abs(-12.34)
    12.34

    调用函数的时候,如果传入的参数数量不对,就会报错:TypeError,并且Python会明确的告诉你:abs()有且仅有1个参数,但是给出了两个:

    >>> abs(1,2)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: abs() takes exactly one argument (2 given)

    如果传入的参数数量是对的,但参数类型不能被函数所接受,也会报TypeError的错误,并且给出错误信息:str是错误的参数类型:

    >>> abs('a')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: bad operand type for abs(): 'str'

    而max()函数可以接受任意多个参数,并返回最大的那个:

    >>> max(1,2,3)
    3
    >>> max(2,3,-4,0,2,9)
    9

    数据类型转换
    Python内置的常用函数还包括数据类型转换函数,比如 int()函数可以把其他数据类型转换为整数:

    >>> int('123')
    123
    >>> int(12.34)
    12
    >>> str(1.23)
    '1.23'
    >>> str(100)
    '100'
    >>> bool(1)
    True
    >>> bool('')
    False

    函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”:

    >>> a = abs  # 变量a指向abs函数
    >>> a(-1)    # 所以也可以通过a调用abs函数
    1

    小练习

    请利用Python内置的hex()函数把一个整数转换成十六进制表示的字符串:

    >>> n1 = 255
    >>> n2 = 1000
    
    >>> print(hex(n1))
    0xff
    
    >>> print(hex(n2))
    0x3e8
    这也行:
    >>> hex(n1)
    '0xff'
    >>> hex(n2)
    '0x3e8'

    定义函数

    在Python中,定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。

    我们以自定义一个求绝对值的my_abs函数为例:

    def my_abs(x):
        if x >= 0:
            return x
        else:
            return -x

    请自行测试并调用my_abs看看返回结果是否正确。

    请注意,函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑。

    如果没有return语句,函数执行完毕后也会返回结果,只是结果为None。

    return None可以简写为 return。

    在Python交互环境中定义函数时,注意Python会出现…的提示。函数定义结束后需要按两次回车重新回到>>>提示符下:

    如果你已经把my_abs()的函数定义保存为abstest.py文件了,那么,可以在该文件的当前目录下启动Python解释器,用from abstest import my_abs来导入my_abs()函数,注意abstest是文件名(不含.py扩展名):

    空函数

    如果想定义一个什么事也不做的空函数,可以用pass语句:

    def nop():
        pass

    pass语句什么都不做,那有什么用?实际上pass可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass,让代码能运行起来。

    pass还可以用在其他语句里,比如:

    if age >= 18:
        pass

    缺少了pass,代码运行就会有语法错误。

    参数检查

    调用函数时,如果参数个数不对,Python解释器会自动检查出来,并抛出TypeError:

    >>> my_abs(1, 2)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: my_abs() takes 1 positional argument but 2 were given

    但是如果参数类型不对,Python解释器就无法帮我们检查。

    试试my_abs和内置函数abs的差别:

    >>> my_abs('A')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 2, in my_abs
    TypeError: unorderable types: str() >= int()
    
    >>> abs('A')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: bad operand type for abs(): 'str'

    当传入了不恰当的参数时,内置函数abs会检查出参数错误,
    而我们定义的my_abs没有参数检查,会导致if语句出错,出错信息和abs不一样。所以,这个函数定义不够完善。

    我们来修改一下my_abs的定义,对参数类型做检查,只允许整数和浮点数类型的参数。数据类型检查可以用内置函数isinstance()实现:

    def my_abs(x):
        if not isinstance(x, (int, float)):
            raise TypeError('bad operand type')
        if x >= 0:
            return x
        else:
            return -x

    添加了参数检查后,如果传入错误的参数类型,函数就可以抛出一个错误:

    >>> my_abs('A')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 3, in my_abs
    TypeError: bad operand type

    返回多个值

    函数也是可以返回多个值的。
    比如,在游戏中经常需要从一个点移动到另一个点,给出坐标/位移和角度,就可以计算出新的坐标:

    import math
    
    
    def move(x, y, step, angle=0):
            nx = x + step * math.cos(angle)
            ny = y - step * math.sin(angle)
            return nx, nydef move(x, y, step, angle=0):
        nx = x + step * math.cos(angle)
        ny = y - step * math.sin(angle)
        return nx, ny
    
    
    x, y = move(100, 100, 60, math.pi / 6)
    
    print(x, y)

    import math语句表示导入math包,并允许后续代码引用math包里面的sin/cos等函数。

    然后,我们就可以同时获得返回值:
    这里写图片描述
    但,其实这只是一种假象,Python函数返回的任然是单一值:

    r = move(100, 100, 60, math.pi / 6)
    print(r)

    这里写图片描述
    原来返回值是一个tuple!但是,在语法上,返回一个tuple可以省略括号,而多个变量可以同时接受一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实际是返回一个tuple,但写起来更方便。

    小结:

    定义函数时,需要确定函数名和参数个数;

    如果有必要,可以先对参数的数据类型做检查;

    函数体内部可以用return随时返回函数结果;

    函数执行完毕也没有return语句时,自动return None。

    函数可以同时返回多个值,但其实就是一个tuple。

    小练习:
    请定义一个函数quadratic(a, b, c),接收3个参数,返回一元二次方程:

    ax*x + bx + c = 0的两个解。

    提示:计算平方根可以调用math.sqrt()函数:

    # 定义一个函数quadratic(a, b, c),
    # 接收3个参数,返回一元二次方程:
    # ax*x + bx + c = 0的两个解
    
    # ax²+bx+c=0(a≠0)
    # Δ=b²-4ac
    # ①若Δ=b²-4ac<0
    # 则无实数根
    # ②若Δ=b²-4ac=0
    # 则有两个相等的实数根(即就一个)
    # x=-b/2a
    # ③若Δ=b²-4ac>0
    # 则有两个不相等的实数根
    # x1=[-b-√(b²-4ac)]/2a
    # x2=[-b+√(b²-4ac)]/2a
    
    import math
    
    
    def quadratic(a, b, c):
        if a != 0:
            delta = b * b - 4 * a * c
            if delta < 0:
                print('no result !')
            elif delta == 0:
                print('two equal result !')
                x = -b/2*a
                return print('x1=x2=', x)
            elif delta > 0:
                # x1=[-b - √(b*b-4*a*c)] / 2*a
                # x2=[-b + √(b*b-4*a*c)] / 2*a
                x1 = (-b + math.sqrt(delta))/(2*a)
                x2 = (-b - math.sqrt(delta))/(2*a)
                print('two result !')
                return x1, x2
        else:
            x = -c / b
            return x
    
    
    print(quadratic(2, 3, 1))
    print(quadratic(1, 3, -4))

    这里写图片描述

    函数的参数

    函数的参数

    定义函数的时候,我们把多参数的名字和位置确定下来,函数的接口定义就完成了。对于函数的调用者来说,只需要知道如何传递正确的参数,以及函数将返回什么样的值就够了,函数内部的复杂逻辑被封装起来,调用者无需了解。

    Python的函数定义非常简单,但灵活度非常大。除了正常定义的必选参数外,还可以使用默认参数/可变参数和关键字参数,使得函数定义出来的接口,不但能处理复杂参数,还可以简化调用者的代码。

    位置参数

    我们首先来写一个计算x*x的函数:

    >>> def power(x):
    ...     return x*x
    ... 

    对于power(x)函数,参数x就是一个位置参数。

    当我们调用power函数时,必须传入有且仅有的一个参数x:

    >>> power(5)
    25
    >>> power(15)
    225

    现在,如果我们要计算x*x*x怎么办?可以再定义一个power3函数,但是如果要计算x*x*x*x / x*x*x*x怎么办?我们不可能定义无限多个函数。

    这个时候,我们可以把power(x)修改为power(x,n),用来计算x的n次方:

    def power(x, n):
        s = 1
        while n > 0:
            n = n-1
            # n -= 1
            s = s * x
        return print(s)
    
    power(5, 2)
    
    power(5, 3)

    这里写图片描述
    修改后的power(x,n)函数有两个参数:x和n,这两个参数都是位置参数,调用函数时,传入的两个值按照位置顺序依次赋值给参数x和n。

    默认参数

    新的power(x,n)函数定义没有问题,但是,旧的调用代码失败了,原因是我们增加了一个参数,导致旧的代码因为缺少一个参数而无法正常调用:
    这里写图片描述
    Python的错误信息很明确:调用函数power()缺少了一个位置参数n。

    这个时候,默认参数就派上用场了。由于我们经常计算x*x,所以,完全可以把第二个参数n的默认值设定为2:

    def power(x, n=2):
        s = 1
        while n > 0:
            n = n-1
            # n -= 1
            s = s * x
        return print(s)
    
    power(5)
    
    power(5, 2)

    这样,当我们调用power(5)时,相当于调用power(5,2)
    这里写图片描述
    对于n > 2的其他情况,就必须明确的传入n,比如power(5,3).

    从上面的例子中可以看出,默认参数可以简化函数的调用。设置默认参数时,有以下几点需要注意:

    1)必选参数在前,默认参数在后,否则Python的解释器会报错
    2)如何设置默认参数

    当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。

    使用默认参数有什么好处呢?最大的好处就是能降低调用函数的难度。

    举个例子,我们写一个一年级小学生注册的函数,需要传入name和gender两个参数:

    def enroll(name, gender):
        print('name:', name)
        print('gender:', gender)
    
    
    enroll('Frank', 'F')

    这样,调用enroll()函数只需要传入两个参数:
    这里写图片描述
    如果继续传入年龄/城市等信息怎么办?这样会使得调用函数的复杂度大大增加。

    我们可以把年龄和城市设为默认参数:

    def enroll(name, gender, age=6, city='Kunming'):
        print('name:', name)
        print('gender:', gender)
        print('age:', age)
        print('city:', city)
    
    enroll('Frank', 'F')

    这样,大多数学生注册时不需要提供年龄和城市,只提供必须的两个参数:
    这里写图片描述
    只有与默认参数不符的学生才需要提供而外的信息:

    enroll('Bob', 'M', 7)
    
    enroll('Adam', 'M', city='Tianjin')

    可见,默认参数降低了函数调用的难度,而一旦需要更复杂的调用时,又可以传递更多的参数来实现。
    无论是简单调用还是复杂调用,函数只需要定义一个。

    有多个默认参数时,调用的时候,既可以按顺序提供默认参数,比如调用enroll(‘Bob’,’M’,7),意思就是,除了name,gender这两个参数外,最后一个参数应用在参数age上,city参数由于没有提供,任然使用默认值。

    我们也可以不按照顺序提供部分默认参数。当不按顺序提供部分默认呢参数时,需要把参数名写上。
    比如调用enroll(‘Adam’,’M’,city=’Tianjin’),意思是,city参数用传进去的值,其他默认参数继续使用默认值。

    默认参数很有用,但使用不当,也会掉坑里。
    默认参数有个最大的坑,如下:

    def add_end(L=[]):
        L.append('END')
        return L
    
    print(add_end([1,2,3]))
    
    print(add_end(['x','y','z']))
    
    print(add_end())
    
    print(add_end())
    
    print(add_end())

    当我们正常调用时,结果似乎没错,但是当我们使用默认参数时,一开始结果也是对的:

    但是再次调用add_end()时,结果就不对了:
    这里写图片描述
    有点醉了,默认参数是[]呀,但是函数似乎每次都记住了上次添加的‘END’后的list。

    原因解释如下:

    Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。

    所以,定义默认参数要牢记一点:默认参数必须指向不变对象!

    修改上面的例子,我们可以用None这个不变对象来实现:

    def add_end(L=None):
        if L is None:
            L = []
        L.append('END')
        return L
    
    print(add_end())
    
    print(add_end())

    现在,无论调用多少次,都不会有问题:
    这里写图片描述

    为什么要设计str None这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。

    可变参数

    在Python函数中,还可以定义可变参数。
    顾名思义,可变参数就是传入的参数个数是可变的,可以是1个 2个到任意个,还可以是0个。

    我们以数学题为例,给定一组数字a,b,c,…,计算a*a+b*b+c*c+…。

    要定义出这个函数,我们必须确定输入的参数。由于参数个数不确定,我们首先想到可以把a,b,c…作为一个list或者tuple传进来,这样,函数可以定义如下:

    def calc(numbers):
        sum = 0
        for n in numbers:
            sum = sum + n * n
    
        return sum
    
    
    print(calc([1, 2, 3]))
    
    print(calc((1, 3, 5, 7)))

    但是,调用的时候,需要先组装出一个list或tuple:
    这里写图片描述

    如果利用可变参数,调用函数的方式就可以简化成这样:

    print(calc(1, 2, 3))
    
    print(calc(1, 3, 5, 7))

    所以,我们把函数的参数改为可变参数:

    def calc(*numbers):
        sum = 0
        for n in numbers:
            sum = sum + n*n
    
        return sum
    
    print(calc(1, 2, 3))
    
    print(calc(1, 3, 5, 7))

    这里写图片描述

    定义可变参数和定义一个list或tuple参数相比,仅仅在参数前面加了个*号。在函数内部,参数numbers接收到的是一个tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数:

    >>>calc(1, 2)
    5
    >>>calc()
    0

    如果已经有一个list或者tuple,要掉用一个可变参数怎么办?我们可以这样做:

    >>>nums = [1, 2, 3]
    >>>calc(nums[0], nums[1], nums[2])
    14

    这种写法当然是可行的,问题太繁琐,所以,Python允许我们在list或者tuple前面加一个*号,把list或者tuple的元素变成可变参数传进去:

    >>>nums = [1, 2, 3]
    >>>calc(*nums)
    14

    *nums表示把nums这个list的所有元素作为可变参数传进去。
    这种写法相当有用,而且很常见。

    关键字参数
    可变参数允许你传入0个或任意个参数,这些可变参数就在函数调用时自动组装成为一个tuple。

    而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。如下例:

    def person(name, age, **kw):
        print('name:', name, 'age', age, 'other:', kw)
    
    print(person('Michael', 30))
    
    print(person('Bob', 35, city='Beijing'))
    
    print(person('Adam', 45, gender='M', job='Engineer'))

    函数person除了必选参数name和age外,还接受关键字参数kw。

    在调用函数时,可以只传入必选参数

    当然,也可以传入任意个数的关键字参数:
    这里写图片描述

    关键字参数有什么用呢?它可以扩展函数的功能。比如,在person函数里,我们保证能接收到name和age这两个参数,但是,如果调用者愿意提供更多的参数,我们也能收到。

    试想我们正在做一个用户注册的功能,除了用户名和年龄是必填项外,其他都是可选项,利用关键字参数来定义这个函数就能满足注册的需求。

    和可变参数类似,也可以先组装出一个dict,然后,把该dict转换为关键字参数传进去:

    extra0 = {'city': 'Beijing', 'job': 'Engineer'}
    
    print(person('Jack', 25, city=extra0['city'], job=extra0['job']))
    name: Jack age 25 other: {'job': 'Engineer', 'city': 'Beijing'}

    当然,上面复杂的调用可以用简化的写法:

    extra1 = {'city': 'Beijing', 'job': 'Enginer'}
    print(person('Jack', 24, **extra1))
    name: Jack age 24 other: {'job': 'Enginer', 'city': 'Beijing'}

    **extra表示把extra这个dict的所有key-valye用关键字参数传入到函数的**kw参数,kw将获得一个dict,注意:kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra。

    命名关键字参数

    对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。至于到底传入了哪些,就需要在函数内部通过kw检查。

    def person(name, age, **kw):
        if 'city' in kw:
            pass
        if 'job' in kw:
            pass
        print('name', name, 'age', age, 'other', kw)
    
    
    print(person('Jack', 24, city='Kunming', adr='Chenggong', zipcode=547688))

    这里写图片描述

    如果限制关键字参数的名字,就可以使用命名关键字参数,例如,只接受city和job作为关键字参数。这种方式定义的函数如下:

    def person(name, age, *, city, job):
        print(name, age, city, job)
    
    # 调用方式如下:
    
    person('Jack', 26, city='Kunming', job='Engineer')

    这里写图片描述

    命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错:

    Traceback (most recent call last):
      File "/usr/local/developTools/pycharmProjects/python3Learning/function/personFun*.py", line 7, in <module>
        person('Jack', 26, 'Kunming', 'Engineer')
    TypeError: person() takes 2 positional arguments but 4 were given

    这里写图片描述
    由于调用时缺少参数名city和job,Python解释器把这4个参数均视为位置参数,但person()函数接收2个位置参数。

    命名关键字参数可以有缺省值,从而简化调用:

    def person(name, age, *, city='Kunming', job):
        print(name, age, city, job)
    
    
    person('Jack', 26, job='Engineer')

    这里写图片描述
    由于命名关键字参数city具有默认值,调用时,可以不传入city参数。

    使用命名关键字参数时,要特别注意,不是参数,而是特殊分隔符。如果缺少,Python解释器将无法识别位置参数和命名关键字参数:

    def person(name, age, city, job):
        # 缺少 * ,city和job将被视为位置参数
        pass

    参数组合

    在Python中定义函数,可以用必选参数 默认参数 可变参数 关键字参数 命名关键字参数,这5中参数都可以组合使用,除了可变参数无法和命名关键字参数混合。

    但是,请注意,参数定义的顺序必须是:
    必选参数 默认参数 可变参数/命名关键字参数和关键字参数。

    例如,定义一个函数,包含上述若干中参数:

    def f1(a, b, c=0, *args, **kw):
        print('a=', a, 'b=', b, 'c=', c, 'args=', args, 'kw =', kw)
    
    
    def f2(a, b, c=0, *, d, **kw):
        print('a=', a, 'b=', b, 'c=', c, 'd=', d, 'kw=', kw)
    
    
    f1(1, 2)
    
    f1(1, 2, c=3)
    
    f1(1, 2, 3, 'a', 'b')
    
    f1(1, 2, 3, 'a', 'b', x=99)
    
    f2(1, 2, d=99, ext=None)

    在函数调用的时候,Python解释器会自动按照位置参数和参数名把对应的参数传递进去:
    这里写图片描述

    最神奇的是通过一个tuple和dict,我们也可以调用上述函数:

    args = (1, 2, 3, 4)
    kw = {'d': 99, 'x': '#'}
    
    f1(*args, **kw)
    
    args = (1, 2, 3)
    kw = {'d': 88, 'x': '#'}
    
    f2(*args, **kw)

    这里写图片描述

    所以,对于任意函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参数时如何定义的。

    小结:

    Python的函数具有非常的灵活的参数形态,既可以实现简单的调用,又可以传入非常复杂的参数。

    默认参数一定要用不可变对象,如果是可变对象,程序运行时会含有逻辑错误!

    要注意定义可变参数和关键字参数的语法:

    *args是可变参数,args接收的是一个tuple;
    **kw是关键字参数,kw接收的是一个dict。

    以及调用函数时如何传入可变参数和关键字参数的语法:

    可变参数既可以直接传入:func(1, 2, 3),又可以先组装list或tuple,在通过args传入:func((1, 2, 3));

    关键在参数既可以直接传入:func(a=1, b=2),又可以先组装dict,在通过kw传入:func({‘a’: 1,’b’: 2})。

    使用*args和**kw是Python的习惯写法,当然也可以用其他参数名,但是最好使用习惯用法。

    命名关键字参数就是为了显示调用者可以传入的参数名,同时可以提供默认值。

    定义命名关键字参数时不要忘了写分隔符*,否则定义的将是位置参数。

    递归函数

    在函数内部,可以调用其他函数。
    如果一个函数在内部调用自身本身,这个函数就是递归函数。

    例如,我们来计算阶乘n! = 1×2×3×…×n,用函数fact(n)表示,可以看出:

    fact(n) = n!=1×2×3×…×(n-1)×n = (n-1)!×n = fact(n-1)×n

    所以,fact(n)可以表示为n×fact(n-1),只有n=1时需要特殊处理。

    于是,fact(n)用递归的方式写出来就是:

    def fact(n):
        if n == 1:
            return 1
        return n * fact(n - 1)
    
    
    print(fact(1))
    
    print(fact(5))
    
    print(fact(100))

    这里写图片描述

    如果我们计算fact(5),可以根据函数定义看到计算过程如下:

    >>>fact(5)
    >>>5 * fact(4)
    >>>5 * (4 * fact(3))
    >>>5 * (4 * (3 * fact(2)))
    >>>5 * (4 * (3 * (2 * fact(1))))
    >>>5 * (4 * (3 * (2 * 1)))
    >>>5 * (4 * (3 * 2))
    >>>5 * (4 * 6)
    >>>5 * 24
    >>>120

    递归函数的有点是定义简单,逻辑清晰。
    理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。

    使用递归函数需要注意防止栈溢出

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

    fact(1000)
    /usr/bin/python3.5 /usr/local/developTools/pycharmProjects/python3Learning/function/factFun.py
    Traceback (most recent call last):
      File "/usr/local/developTools/pycharmProjects/python3Learning/function/factFun.py", line 24, in <module>
        print(fact(1000))
      File "/usr/local/developTools/pycharmProjects/python3Learning/function/factFun.py", line 4, in fact
        return n * fact(n - 1)
    
      .............................
    
      File "/usr/local/developTools/pycharmProjects/python3Learning/function/factFun.py", line 4, in fact
        return n * fact(n - 1)
      File "/usr/local/developTools/pycharmProjects/python3Learning/function/factFun.py", line 2, in fact
        if n == 1:
    RecursionError: maximum recursion depth exceeded in comparison
    
    Process finished with exit code 1

    解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。

    尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。

    这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

    上面的fact(n)函数由于return n*fact(n - 1)引入了乘法表达式,所以就不是尾递归了。
    要改成尾递归方式,需要多一点代码,主要是把每一步的乘积传入到递归函数中:

    def fact(n):
        return fact_iter(n, 1)
    
    
    def fact_iter(num, product):
        if num == 1:
            return product
        return fact_iter(num - 1, num * product)

    可以看到,return fact_iter(num - 1,num * product)仅返回递归函数本身,num - 1和num * product在函数调用前就会被计算,不影响函数调用。

    fact_iter(5, 1)
    fact_iter(4, 5)
    fact_iter(3, 20)
    fact_iter(2, 60)
    fact_iter(1, 120)
    120

    尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。

    遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改写成尾递归方式,也会导致栈溢出。

    小结:

    使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。

    针对尾递归优化的语言可以通过尾递归防止栈溢出。
    尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。

    Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。

    小练习:

    汉诺塔的移动可以用递归函数非常简单地实现。

    请编写move(n, a, b, c)函数,它接收参数n,表示3个柱子A、B、C中第1个柱子A的盘子数量,然后打印出把所有盘子从A借助B移动到C的方法,例如:

    展开全文
  • MATLAB中调用C语言函数

    千次阅读 2019-07-07 16:12:28
    文章目录1....MATLAB官网调用C函数:https://ww2.mathworks.cn/help/matlab/matlab_external/install-mingw-support-package.html?searchHighlight=MinGW-w64 Compiler&s_tid=doc_srchtitle ...

    1.测试效果

    第一个例子

    MATLAB官网调用C函数:https://ww2.mathworks.cn/help/matlab/matlab_external/install-mingw-support-package.html?searchHighlight=MinGW-w64 Compiler&s_tid=doc_srchtitle
    1您可以通过编译 yprime.c 示例来测试 MinGW® 编译器。将源文件复制到可写文件夹。 copyfile(fullfile(matlabroot,‘extern’,‘examples’,‘mex’,‘yprime.c’),’.’,‘f’)
    2 如果您在系统中仅安装了 MinGW 编译器,则 mex 命令会自动选择 MinGW。继续下一步。但如果您有多个 C 或 C++ 编译器,请使用 mex -setup 选择 MinGW。
    mex -setup
    3 编译该 MEX 文件。
    mex yprime.c
    4 MATLAB 将显示“编译工具”消息,其中显示了用于编译 MEX 文件的编译器。
    运行函数。
    yprime(1,1:4)
    在这里插入图片描述
    第二个例子
    参考MATLAB学习(五)MATLAB中调用C语言函数
    1 在matlab中新建文件

    #include "mex.h"    //头文件必须包含mex.h
    double mexSimpleDemo(double *y,double a,double b);           //C语言算法程序声明,在最后调用时,第一
                    //                 个参数是返回结果
    //c语言到matlab变换,以mexFunction命名
    void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
    {
        double *y;
        double m,n;
        
        //获取输入变量的数值大小
        m=mxGetScalar(prhs[0]);
        n=mxGetScalar(prhs[1]);
        //获取输出变量的指针
        plhs[0]=mxCreateDoubleMatrix(1,1,mxREAL);
        y=mxGetPr(plhs[0]);
         
        //调用子函数
        mexSimpleDemo(y,m,n);
    
    }
    
    //C语言函数  
    double mexSimpleDemo(double *y,double a,double b)
    {
        return *y=(a>b)?a:b;
    
    }
    

    保存为mexSimpleDemo.c的文件
    2 在matlab中输入
    mex mexSimpleDemo.c
    3 测试调用结果在matlab输入
    a=mexSimpleDemo(5,3)
    在这里插入图片描述

    2.matlab调用c函数资料

    下载资料:https://download.csdn.net/download/weixin_39249915/11293038

    展开全文
  • help函数是python的一个内置函数(python的内置函数可以直接调用,无需import),它是python自带的函数,任何时候都可以被使用。help函数能作什么、怎么使用help函数查看python模块中函数的用法,和使用help函数时...
       
    

    help函数是python的一个内置函数(python的内置函数可以直接调用,无需import),它是python自带的函数,任何时候都可以被使用。


    使用help函数查看帮助实例

    1、查看一个模块的帮助

    复制代码 代码如下:
    >>>help('sys')

    之后它回打开这个模块的帮助文档
    2、查看一个数据类型的帮助(直接通过类型名)
    复制代码 代码如下:
    >>>help(str)
    >>>help(list)

    >>>help(list)


    3、查看一个数据类型的帮助(通过一个实例)
    >>>L = [1,2,3]
    >>>help(L)
    >>>help(L.sort)
    展开全文
  • Python学习笔记基础三_函数函数定义函数调用 函数定义 定义:函数表示一个功能代码块 作用:代码可以重复使用,降低代码重复率 语法格式: def 函数名( 形式参数[可选] ): &amp;amp;amp;amp;amp;amp;amp;...
  • help函数是python的一个内置函数(python的内置函数可以直接调用,无需import),它是python自带的函数,任何时候都可以被使用。help函数能作什么、怎么使用help函数查看python模块中函数的用法,和使用help函数时...
  • 》》调用help函数 help(函数对象) 》》如何给自己的函数加文档说明 文档字符串(doc str)在定义函数时,可以在函数内部编写文档字符串,文档字符串就是函数的说明 实直接在函数的第一行写一个字符串就是文档字...
  • help函数是python的一个内置函数(python的内置函数可以直接调用,无需import),它是python自带的函数,任何时候都可以被使用。help函数能作什么、怎么使用help函数查看python模块中函数的用法,和使用help函数时...
  • 使用Doxygen+Graphviz+HtmlHelp 生成函数调用关系图 在写这篇博客之前,首先感谢一下另外一篇博主的文章,Windows平台下Doxygen+GraphViz+HtmlHelp自动生成函数调用关系图。 附上原文链接:...
  • python 调用函数

    千次阅读 2017-10-13 19:58:18
    Python内置了很多有用的函数,我们可以直接调用。 要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数abs,只有一个...也可以在交互式命令行通过help(abs)查看abs函数的帮助信息。 调用abs函数: >
  • 这篇文档介绍怎样使用Doxygen+Graphviz+HtmlHelp 生成函数调用关系图
  • 安装了MATLAB2018b版本后,一开始使用没有发现有什么问题,后来使用help函数时候才报错,代码是下面这一堆:Exception in thread “AWT-EventQueue-0” java.lang.NoClassDefFoundError: **Could not initialize ...
  • python学习——调用函数

    千次阅读 2016-07-09 16:37:37
    Python内置了很多有用的函数,我们可以直接调用。 要调用一个函数,需要知道函数的名称和参数,比如求绝对值的...也可以在交互式命令行通过help(abs)查看abs函数的帮助信息。 调用abs函数: &gt;&gt;...
  • 起初在VS中手动查看OpenCV源码,发现简单的函数能够很快整理出该函数的层次调用关系,但是遇到一些复杂的函数时,一层一层的往下查看一会儿脑袋就大了。并且,在查看源码的过程中,发现很多底层的函数都会被重复调用...
  • 但是,有时,您只需在单个 m 文件中编写一些函数, 尽管只能调用顶部以外的函数在 m 文件中。 这完全没问题,因为您通常期望这些函数永远不会被其他 m 文件使用。 然后,稍后,您发现自己想要访问那些小功能来自...
  • 关于在C++中调用system函数

    千次阅读 2015-09-08 08:16:15
    关于在C++中调用system函数 - heirenheiren的专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/heirenheiren/article/details/7367187 先看看下面的这一段程序: #include #include int ...
  • 只要调用strcpy()函数在程序运行时,总是出现错误: error C4996: ‘strcpy’: This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS....
  • 在Matlab中调用OpenCV函数

    千次阅读 2013-12-15 22:09:35
    matlab调用opencv的函数  由于最近学习的需要, 所以需要將別人写好的mex funtion重编一次;但是使用到了opencv的lib, 所以在编译mex的時候, 需要将opencv的lib也一起加到matlab的环境中. 系统环境: win XP matalb...
  • MATLAB函数调用

    千次阅读 2021-01-07 20:57:42
    数学建模 matlab自定义函数 时间 2020年5月10日 ...2.两个文件运行函数函数定义文件和函数调用文件(函数可在脚本文件或命令窗口直接调用),两文件必须放在同一目录下,函数文件名必须与函数名相...
  • 将 mustache 模板编译成一个可调用的、可调用函数。 安装 $ npm install -g mustache-cache 用法 Usage: mustache-cache <template> [options] Options: -h, --help output usage information -V, --version ...
  • 在VC++中调用matlab函数

    千次阅读 2016-07-17 19:38:28
    以DLL方式调用M文件中的函数,就是重要的手段。 首先要按帖子Matlab6.1与VC6混合编程小结 (1)中所说的设置编程环境  下面不废话,给出一段例子, :假设有M文件:mfile.m   其中有...
  • Python中调用help()报错:Not enough Memory

    千次阅读 2017-06-22 16:59:29
    最近在ipython中调用help()函数,提示:Not enough Memory[In1]: help(help) Not enough Memory记得以前使用时没有问题的,然后再网上查了一下, http://bugs.python.org/issue19914 For posterity for anyone ...
  • 我在main 函数里面调用这个递归函数,没有报错,用printf()也没有输出结果, 改了倒数第二行代码: 改成 ret=num*recursion_factorials(--num); 结果就出来了。。 那么问题来了,为什么会产生这样的差异?如果...
  • 可以给自己的程序都加上这个东西,便于快速的找到错误吧,看到别人都是这么用的 ...//signal 函数用法参考http://www.kernel.org/doc/man-pages/online/pages/man2/signal.2.html //backtrace ,backtrace_symbo
  • 只需要使用函数名,即可调用某个函数:$ fname ; #执行函数 可以传递参数给函数,并由脚本进行访问:fname arg1 arg2; # 传递参数 以下是函数fname的定义。在函数fname中,包含了各种访问函数参数的方法。 代码如下:...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 137,989
精华内容 55,195
关键字:

怎么调用help函数