• Python开发【第五篇】:函数


    1. 函数

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

      函数分为 Python 程序内置函数,用户自定义的函数。将代码定义为函数,有如下好处:

    • 代码重用(某个特定功能复用)
    • 保持代码一致性,易维护
    • 可拓展

    1.1 定义和调用函数

      使用 def 关键字定义一个函数,后面紧跟函数名,小括号也必不可少,语法如下:

    def func():
    	函数体
    

      函数在执行时,首先将函数体加载到解释器中,但是不会运行,只有当调用函数后才会执行,函数名+小括号即可调用函数:

    def func():
    	函数体
    func()		# 调用函数	
    

    1.2 返回值

      有时我们需要函数返回一些数据来报告执行的结果,所有就需要有返回值,只需要在函数中添加 return 关键字,后面跟着返回值即可。

    def func():
    	return 1
    

      return 将返回值传递给函数本身,我们只要调用函数,再将函数赋值给变量即可获得返回值:

    def func():
    	return 1
    res = func()		# 获得返回值,并赋值给变量 res
    print(res)
    
    1
    

      返回值可以是 0 个,也可以是 1 个 或多个:

    • 没有返回值,返回 None
    • 一个返回值,返回 返回值
    • 多个返回值,返回一个元组
    def func():
        # return
        # return 1
        return 1, 2
    res = func()
    print(res)
    
    None
    1
    (1, 2)
    

    1.3 函数参数

      函数的参数可以用函数实现个性化,大致分为两类:

    • 形参:函数在定义时定义的参数
    • 实参:函数在调用时传入的参数

      形参只有在调用时才分配内存单元,调用结束,就释放。仅在函数内部有效,不能在函数外部使用。

      实参可以是常量、变量、表达式、函数,占用内存空间。

    1.3.1 默认参数

      形参又分为:默认参数、位置参数、关键字参数以及可变长参数,而默认参数即在函数定义时默认赋予某个形参一个值。若函数调用时,不传入实参,函数使用默认值,否则使用实参。

    def func(x=2):		# x 默认为 2
        return x + 2
    res = func()		# 即使不传入实参函数也能正常运行
    print(res)
    

    1.3.2 位置参数和关键字参数

      普通的参数即为位置参数,在调用时实参必须与形参一一对应。而关键字参数,可以不用考虑位置的关系,只需要名字相同即可。

    def func(name, words):
        print(name: words)
    func('Hello', words='world')	# 第一个为位置参数,第二个为关键字参数
    func(words='World', name='Hello')	# 不用考虑位置
    

    Tips:位置参数必须在关键字参数后面

    1.3.3 可变长参数

      可变长参数是一种参数组,它可以是多个参数,只需要在参数前加上星号(*)即可。它可以增加函数可拓展性,当你不知道定义的函数需要定义几个参数时,使用它很方便。

      可变长参数分为:*args 和 **kwargs两类:

    • *agrs:将参数们收集起来,打包成一个元组,再一一传递给函数使用
    • **kwargs:将参数们收集并打包成一个字典

    *args

      *args 、**kwargs 是 Python 官方定义的参数名,也可以是其他名字,但是最好使用它,以便于辨认。

    def func(*args):
        print(args)
        print('有 %d 个参数' % len(args))
        print('第三个参数是:', args[2])
    func('P', 'y', 't', 'h', 'o', 'n')
    func('Python', 123, '爬虫')
    
    ('P', 'y', 't', 'h', 'o', 'n')
    有 6 个参数
    第三个参数是: t
    ('Python', 123, '爬虫')
    有 3 个参数
    第三个参数是: 爬虫
    

    Tips:如果可变长参数后面还有参数,要将其定义为关键字参数,否则会被收集成可变长参数里面。建议在使用可变长参数时,可将其他参数设置为默认参数,或关键字参数,这样不易混淆。

    def func(*args, extra=16):
    # def func(*args, extra):
        print(args)
        print(extra)
    func(1,2,3)
    #func(5,6, extra=18)
    
    (1, 2, 3)
    16
    
    (5, 6)
    18
    

      星号(*)既可用来收集打包参数,也可以用来“解包”参数。当传入的参数时列表、元组、字典以及集合时,可变长参数将会将其整个打包成只有一个元组的参数,而在其前面添加一个星号( *),就可以将里面的元素一个个都解出来。

    def func(*args):
        print(args)
    
    l = [1, 2, 3]
    t = (4, 5, 6)
    d = {'name':'rose', 'age': 18}
    func(l)
    func(*l)
    func(t)
    func(*t)
    func(d)
    func(*d)
    
    ([1, 2, 3],)
    (1, 2, 3)
    ((4, 5, 6),)
    (4, 5, 6)
    ({'name': 'rose', 'age': 18},)
    ('name', 'age')
    

    **kwargs

      另一种可变长参数就是 **kwargs,它将传入的实参打包成一个字典,同样地也支持 “解包”。

    def func(x, **kwargs):
        print(x)
        print(kwargs)
        print('总共有 %d 个参数' % len(kwargs))
        print('这些参数分别为:', kwargs)
    
    func(20, name='rose', age=18)
    
    20
    {'name': 'rose', 'age': 18}
    总共有 2 个参数
    这些参数分别为: {'name': 'rose', 'age': 18}
    

      解包,当传入的参数是字典时:

    def func(gender, **kwargs):
        print(gender)
        print(kwargs)
        print('总共有 %d 个参数' % len(kwargs))
        print('这些参数分别为:', kwargs)
    
    t = {'name': 'rose', 'age': 18}
    func('female', **t)
    
    female
    {'name': 'rose', 'age': 18}
    总共有 2 个参数
    这些参数分别为: {'name': 'rose', 'age': 18}
    

      当既有 *args,又有 **kwargs,以及位置参数和位置参数时:

    def func(gender, country='China', *args, **kwargs):
        print(gender, country)
        print(args)
        print(kwargs)
    func('male', 'America', 20, 30, name='rose', age=19)
    
    male America
    (20, 30)
    {'name': 'rose', 'age': 19}
    

    1.4 函数文档

      函数文档即用来描述函数功能的文档,可以让别人更好地理解你的函数,定义函数文档是个好的习惯。

    def func(x):
        """
        计算一个数加一
        :param x: 
        :return: 
        """
        x += 1
        return x
    res = func()
    

    1.5 函数变量

    1.5.1 函数和过程

      在 Python 中函数和过程是分开的,函数(function)与过程(procedure)的区别:

    • 函数:有返回值
    • 过程:简单、特殊且无返回值

      严格来说 Python 没有过程,只有函数,因为即使没有返回值,也会默认返回一个 None。

    def func():
        print('Hi')
    res = func()
    print(res)
    
    Hi
    None
    

    1.5.2 函数变量的作用域

      变量的作用域即变量可见性,也就是可用范围,一般编程语言分为:全局变量(global variable)和局部变量(local variable)。

    • 全局变量:程序开始定义时定义的变量,在函数外部,无缩进,作用域为整个程序
    • 局部变量:在子程序中(一般为函数)定义的变量,函数内部,有缩进,作用域是整个子程序

    当全局变量与局部变量同名是,在子程序中局部变量起作用,在外面全局变量起作用。

    # 首先加载整个函数(不执行),调用函数执行函数内部,打印 tom,最后打印 rose
    name = 'rose'	# 全局
    def test():
        name = 'tom'	# 局部
        print(name)
    test()
    print(name)
    
    tom
    rose	
    

      1. global 关键字

      全局变量的作用域是整个程序,函数内部亦可访问。但是不要在函数内部试图修改全局变量,这是因为 Python 使用了屏蔽(shadowing)的方式去 保护全局变量。一旦在函数内部修改,则会在函数内部创建一个一模一样的局部变量。

    name = 'rose'
    def test():
        name = 'tom'	
        print(name)
    test()
    print(name)
    
    tom
    rose
    

      从上面例子可以看出,全局变量的值没有改变。但是 Python 是支持在函数内部修改全局变量的,只需要在变量前面加上一个 global 关键字即可:

    name = 'rose'
    def test():
        global name
        name = 'tom'
        print(name)
    test()
    print(name)
    
    tom
    tom
    

    总结:当全局与局部变量名字相同时,函数内部优先读取局部变量。为了更好地区分全局与局部变量,一般地全局变量名尽量使用大小,局部变量名使用小写。

      2. 内嵌函数

      函数支持嵌套,即一个函数中嵌套另外一个函数,这种函数叫内嵌函数或内部函数。

    name = 'rose'		# (1)
    def fun1():			# (2)
        name = 'tom'	# (5)
        def fun2():		# (6)
            name = 'lila'		# (8)
        fun2()			# (7)
        print(name)		# (9)
        
    print(name)			# (3)
    fun1()				# (4)
    print(name)			# (10)
    
    rose
    tom
    rose
    

    Tips:内部函数只能在内部调用,外部调用会报 NameError

    1.5.3 闭包

      闭包(closure)是函数式编程中的一个重要数据结构,Python 中认为如果在一个内部函数里,对在外部作用域(但不是全局作用域)的变量进行引用,那么这个内部函数就是闭包(closure)。

    def fun1(x):
        def fun2(y):
            return x * y
        return fun2
    a = fun1(6)			# a 接收的是 fun2() 的内存地址
    print(a)
    b = a(5)			# a(5) 相当于调用 fun2()
    print(b)
    
    # 上述可以简写
    # res = fun1(6)(5)
    # print(res)
    
    <function fun1.<locals>.fun2 at 0x00000000026F48C8>
    30
    

      从上面的例子可以看出,内部函数 fun2()对外部函数 fun1()的变量 x (不是全局变量)进行了引用,那么 fun2()即是闭包。

      nonlocal 关键字

      但需要注意的是不能在外部函数外面调用内部函数,对外部函数的局部变量只能进行访问,不能修改。

    def fun1():
        name = 'rose'
        def fun2():
            name = 'tom'
            return name
        print(name)
        return fun2
    fun1()()
    
    rose		# 外部函数局部变量 name = ‘rose' 并没有被修改
    

      如果在内部函数中想修改外部函数的局部变量可以用 nonlocal 关键字,但是需要注意的是它不能修改全局变量。

    def fun1():
        name = 'rose'
        def fun2():
            nonlocal name		# 添加 nonlocal 关键字
            name = 'tom'
            return name
        print(name)
        return fun2
    fun1()()
    
    tom		# 外部函数局部变量 name = ‘rose' 已经被修改
    

    1.6 函数即变量

      Python 程序按程序执行,遇到函数,先加载到到内存,只有当调用函数时,才会运行函数体。因此一个函数可以作为 变量在另一个函数内部调用执行,前提是第一个函数需要先加载。

      首先加载 f1()、f2(),再调用 f1(),执行 f1()里的函数体,最后调用 f2(),执行 f2()里的函数体:

    def f1():			# (1)
        print('from f1')	# (4)
        f2()			# (5)
    def f2():			# (2)
        print('from f2')	# (6)
    f1()				# (3)
    
    from f1
    from f2
    

      另一种情况:

    def f2():
        print('from f2')
    def f1():
        print('from f1')
        f2()
    f1()
    
    from f1
    from f2
    

      第三种情况,调用 f2()时,因为 函数 f2()还未加载,导致出错(NameError: name 'f2' is not defined):

    def f1():
        print('from f1')
    f2()
    def f2():
        print('from f2')
    f1()
    

    1.7 递归函数

      在函数内部,可以调用其他函数,如果在调用过程中直接或间接调用自身,那么这个函数就是递归函数。

      递归函数特征:

    • 必须有明确的结束条件(否则死循环)
    • 每次进入更深一次递归时,问题规模比上一次都应有所减少
    • 递归效率不高,层次过多容易导致 栈溢出

    函数调用是通过栈(stack)实现,每调用一次,栈就会增加一层栈帧,函数返回,则减少一层。由于栈的大小有限,所有递归过多,就会导致栈溢出。

    def func(n):
        print(n)
        if int(n/2) == 0:		# 结束条件
            return n
        res = func(int/2)	# 调用自身
        return res
    func(10)
    
    10,5,2,1
    

    1.7.1 示例

      递归问路

      使用递归函数,实现一次递归问路操作。

    import time
    person_list = ['rose', 'tom', 'lila', 'json', 'john']
    def ask_way(person_list):
        """
        问路操作
        :param person_list: 被问的人
        :return:
        """
        print('-'*60)
        if len(person_list) == 0:
            return '没人知道'
        person = person_list.pop()
        if person == 'json':
            return '%s 我知道 xxx 怎么走,它在 xxx' % person
        print('你好,%s,请问 xxx 在哪里?' % person)
        print('%s 回答道:我也不知道,我帮你去问问 %s' % (person, person_list))
        time.sleep(2)
        res = ask_way(person_list)
        return res
    res = ask_way(person_list)
    print(res)
    
    ------------------------------------------------------------
    你好,john,请问 xxx 在哪里?
    john 回答道:我也不知道,我帮你去问问 ['rose', 'tom', 'lila', 'json']
    ------------------------------------------------------------
    json 我知道 xxx 怎么走,它在 xxx
    

      二分查找

    data = [1,3,6,7,9,12,14,16,17,18,20,21,22,23,30,32,33,35]
    def find_num(data, num):
        """
        使用二分查找法,查找出一个数字的位置
        """
        print(data)
        if len(data) > 1:
            mid = int(len(data)/2)
            if data[mid] == num:
                print('找到数字', data[mid])
            elif data[mid] > num:
                print('要找的数字在 %s 右边' % data[mid])
                return find_num(data[0:mid], num)
            else:
                print('要找的数字在 %s 左边' % data[mid])
                return find_num(data[mid+1:], num)
        else:
            if data[0] == num:
                print('找到数字', data[0])
            else:
                print('要找的数字不在列表中')
    find_num(data, 66)
    
    [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35]
    要找的数字在 18 左边
    [20, 21, 22, 23, 30, 32, 33, 35]
    要找的数字在 30 左边
    [32, 33, 35]
    要找的数字在 33 左边
    [35]
    要找的数字不在列表中
    

    1.7.2 尾调用

      尾调用又称为为递归,指的是函数在最后一步调用另一个函数的过程(最后一行不一定是最后一步)。

    # bar 在 foo 内为尾调用
    def bar(n):
        return n
    def foo(m):
        return bar(m)
    
    # bar 在 foo 内不是尾调用,最后一步为 return y
    def bar(n):
        return n
    def foo(m):
        y = bar(m)
        return y
    
    # bar1、bar2 在 foo 内都是尾调用
    def bar1(n):
        return n
    def bar2(n):
        return n+1
    def foo(x):
        if type(x) is str:
            return bar1(x)
        elif type(x) is int:
            return bar2(x)
    

      尾调用优化

      定义 a 函数,a 内调用 b,b 调用 c,在内存中形成一个调用记录,又称为调用帧(call frame)。用于存储调用位置和内部变量等信息,即(a——b——c),直至 c 返回结果给 b,c 的调用记录消失。b 返回给 a,b 的调用记录消失,a 返回结果,a 的调用记录消失,所有记录都是先进后出,形成一个调用栈(call stack)

    1.8 匿名函数

      匿名函数即不需要显示地指定函数名的函数,Python 允许使用 lambda 关键字来创建一个匿名函数,匿名函数也被称为 lambda 表达式。

    lambda x:x+2
    lambda x,y,z:(x+1, y+1, z+1)	# 多个参数
    

      冒号左边是原函数参数,可以有多个参数,逗号分隔即可,冒号右边为返回值。对于有些结构比较简单的函数,可以直接定义为匿名函数:

    def func(x):
    	return x+2
    s = func(3)
    print(s)
    

      上述函数可直接定义一个匿名函数:

    f = lambda x:x+2
    f(3)		# 调用
    

      匿名函数常与其他函数搭配使用:

    # 将 匿名函数当做参数传入 calc 中
    def calc(func, li):
        ret = []
        for i in li:
            res = func(i)
            ret.append(res)
        return ret
    li = [2, 3, 4, 6, 8]
    calc(lambda x:x+1, li)
    
    [3, 4, 5, 7, 9]
    

      lambda 表达式的作用:

    • 执行一些脚本时,省略定义函数过程
    • 对于整个程序只需要执行一两次的函数,不用考虑命名问题
    • 简化代码步骤

    2. 函数式编程

    2.1 编程论

      当今编程的三种方法论:

    • 面向过程:
    • 函数式编程:特征(无变量、函数即变量)
    • 面向对象:

      函数式编程(函数+数学函数),更贴近数学,是一种抽象成都很高的编程范式,不允许函数有变量。但 Python 不是严格意义上的函数式编程,因为它允许有变量。

      函数式编程特点:

    • 函数即变量(一个函数作为参数传入另一个函数)
    • 返回值是函数(可以函数本身,也可以是别的函数)

      函数即变量

    def foo(n):
        print(n)
    def bar(name):
        print(name)
    foo(bar('rose'))
    
    rose
    None   
    

      上面例子中,bar('rose') 打印 rose,没有返回值,因此 foo(bar('rose'))相当于 foo(None)

      返回值是函数

      返回函数本身:

    def handle():
        print('from handle')
        return handle		# 返回函数本身内存地址
    h = handle()		# 使用变量 h 接收
    h()			# 再调用函数本身
    
    from handle
    from handle
    

      返回别的函数:

    def test():
        print('from test')
    def test1():
        print('from test1')
        return test		# 返回 test 函数的内存地址
    n = test1()		# 接收
    n() 	 # 相当于调用 test()
    

    2.2 高阶函数

      函数式编程的两个特征:函数即变量,返回值是函数,只需满足其中一个条件,即可成为高阶函数。

    def add(x, y, f):
        return f(x)+f(y)
    print(add(-5, 6, abs))
    
    11
    

      上面例子中,内置函数 abs 作为参数传入函数 add。

    2.2.1 map 函数

      map(function, sequence) 函数是高阶函数的一种,它有两个参数:第一个为函数,另一个接收一个序列。

      其作用是将序列中每个元素(for 循环),作为函数参数传入第一个参数中,直至序列中每个元素都被循环,返回一个迭代器对象,用 list 可获得结果。

    # 对列表 l 中每个元素加 1
    li = [2, 3, 4, 5, 6]
    def add_one(x):
        return x+1
    res = map(add_one, li)
    print(res)
    print(list(res))
    
    <map object at 0x0000000002C5C0B8>
    [3, 4, 5, 6, 7]
    

      上面例子中 map 函数将列表 li 的每个中每个元素取出,再传入 add_one 中。

      同样地也可以使用 lambda 表达式与 map 函数简写:

    res = map(lambda x:x+1, li)
    

      传入两个列表:

    res = map(lambda x, y: x+y, [1, 3, 5], [2, 4, 6])
    print(list(res))
    
    

    2.2.2 filter 函数

      filter(function or None, iterable)函数有两个参数:第一个可以是函数也可以是 None,第二个为可迭代对象。

    • 第一个参数为函数:将序列中每个元素取出作为参数,传入第一个参数中,判断,并把为 True 的值返回
    • 第一个参数为 None:将序列中为 True 的元素返回

      第一个参数为函数:

    # 过滤掉以 123 结尾的名字
    names = ['rose_123', 'lila_123', 'john']
    def filter_123(x):
        return not x.endswith('123')		# 返回没有以 123 结尾的名字
    res = filter(filter_123, names)
    list(res)
    
    john
    

      使用 lambda 表达式简写:

    res = filter(lambda x: not x.endswith('123'), names)
    list(res)
    

      第一个参数为 None:

    res = filter(None, [1, 2, 0, True, False])
    list(res)
    
    [1, 2, True]
    

    2.2.3 reduce 函数

      reduce(function, sequence[, initial])函数三个参数:第一个为函数,第二个为序列,第三个可选为初始值。

      Python3 把 reduce 函数集成到 functools 模块中,因此每次使用时,需要from functools import reduce。它可以把一个函数作用在一个序列上,这个函数必须接收两个参数。首先将序列中的前两个元素取出,传入函数中,返回值再与序列中接下来的元素做累积计算,直至序列中的每个元素都被循环。

      求列表中所有元素的乘积:

      常规:

    nums = [1, 2, 3, 100]
    def reduce_test(func, array):
        res = array.pop(0)
        for i in array:
            res = func(res, i)
        return res
    s = reduce_test(lambda x,y: x*y, nums)
    print(s)
    
    600
    

      reduce:

    from functools import reduce
    
    nums = [1, 2, 3, 100]
    res = reduce(lambda x,y : x*y, nums)
    print(res)
    
    600
    

      首先将 nums 前两个元素,即 1、2 传入lambda x,y: x*y中,返回 x*y。再将 3 传入,最后将 100 传入,相当于(((1*2)*3)*100)

    指定初始值:

    from functools import reduce
    
    nums = [1, 2, 3, 100]
    res = reduce(lambda x,y : x*y, nums, 6)		# 相当于 (((6*1)*2)*3)*100
    print(res)
    
    3600
    

      累加计算:

    from functools import reduce
    
    reduce(lambda x,y: x+y, [1, 2, 3, 4, 5])
    
    15
    

    2.2.4 sorted 函数

      排序算法在程序中是经常用到的算法,无论是冒泡还是快排,其核心都是比较两个元素的大小。

    • 数字:直接比较
    • 字符串/字典:需要用函数抽象出来比较

      sorted(iterable, key, reverse)函数也是一个高阶函数,在列表内置方法中我们就已经接触到了,它可以对一个列表进行排序,默认从小到大。

    sorted([1, -3, 2])
    
    [-3, 1, 2]
    

      此外,它还接收一个 key 函数来自定义排序,key 函数作用在列表中的每个元素上,再进行比较,如按绝对值排序:

    sorted([1, -3, 2], key=abs)
    
    [1, 2, -3]
    
    

      第三个参数 reverse,可以反向排序:

    sorted([1, -3, 2], key=abs, reverse=True)
    
    [-3, 2, 1]
    
    

      上面都是针对数字的排序,直接比较其大小即可。但是对于字符串来说,一般地都是比较其首字母在 ASCII 中的大小:

    sorted(['b', 'a', 'Z'])		# 因为在 ASCII中 Z<a
    
    ['Z', 'a', 'b']
    

      现在我们不想按照 ASCII 来排序,而是按照字母表排序,那么我们可以通过指定 key 函数,将所有字符串转换为大写或小写即可实现:

    sorted(['b', 'a', 'Z'], key=str.upper)
    
    ['a', 'b', 'Z']
    
    

    2.2.5 偏函数

      functools 模块提供了很多功能,其中一个就是偏函数(partial )。

      当函数的参数个数太多,需要简化时,使用 functools.partial 创建一个偏函数,这个新的函数可以固定住原函数的部分参数,从而调用更简单。

    语法结构:

    from functools import partial
    
    func2 = partial(func, *args, **kwargs)	# 第一个参数:要固定的函数,第二个:原函数的位置参数,第三个:关键字参数
    

      第一个参数可以是自定义的函数,也可以是内置函数。

      int() 函数可以把字符串转换为整型,默认按照十进制转换:

    >>> int('123')
    123
    

      int() 函数还额外提供一个 base 参数,如果传入 base,就可以做 N 进制转换:

    >>> int('123', base=8)		# 按照八进制转换
    83
    

    内置函数

      假如要转换大量的二进制字符串,每次都要传入 base,就会很繁琐。我们可以利用偏函数(partial)将 base=2 固定住,定义一个新的函数,每次只需要传入要转换的字符串即可:

    >>> from functools import partial
    
    >>> int2 = partial(int, base=2)		# 将 base = 2 固定住
    >>> int2('100')		# 相当于 kw={'base': 2}  int('100', **kw)
    4
    

    自定义函数

      当我们调用某个函数,已知某个参数的值时,可以将其固定住(相当于设定默认值):

    from functools import partial
    
    def add(x, y):
        return x % y
    add2 = partial(add, 5)	# 自动将 5 作为 *args 的一部分放在最左边,也就是 5 % 100
    print(add2(100))
    
    # 101
    

    2.2.6 练习

      将列表中年龄小于等于 18 岁的人过滤出来。

    people = [
        {'name': 'rose', 'age': 18},
        {'name': 'lila', 'age': 30},
        {'name': 'tom', 'age': 60}
    ]
    
    res = filter(lambda p: p.get('age') <= 18, people)
    print(list(res))
    
    [{'name': 'rose', 'age': 18}]
    

    3. 内置函数

      函数分为 Python 内置函数和自定义函数,内置函数有很多,但是真正能用到的也比较少。

    # abs():求一个数字的绝对值
    >>> abs(-5)
    5
    
    # all(iterable):判断序列中所有元素是否为 True,如果序列为空,也返回 True,返回布尔值
    >>> all([1, 2, 0])
    False
    
    # any(iterable):序列中元素 bool(x),只要有一个为 True,则返回 True,如果序列为空,返回 False
    >>> any([])
    False
    >>> any(['', 0, 1])
    True
    
    # bin(number):十进制转二进制
    >>> bin(10)
    '0b1010'
    
    # hex(number):十进制转十六进制
    >>> hex(10)
    '0xa'
    
    # bool():转换为布尔类型
    >>> bool(0)
    False
    >>> bool(None)
    False
    >>> bool('')
    False
    
    # bytes(obj,encoding=None):将对象编码(二进制)
    # bytes(obj,encoding=None).decode(None):解码,用什么编码就应用什么解码
    >>> name = '你好'
    >>> bytes(name, encoding='utf-8')
    b'xe4xbdxa0xe5xa5xbd'
    >>> bytes(name, encoding='utf-8').decode('utf-8')
    '你好'
    
    # chr(i):返回一个数字在 ASCII 中对应的值
    >>> chr(90)
    'Z'
    
    # ord(obj):查询一个字符咋 ASCII 中的对应的数字
    >>> ord('Z')
    90
    
    # dict():创建一个字典
    >>> d = dict()
    >>> type(d)
    <class 'dict'>
    
    # dir(obj):返回一个对象的所有方法名字
    >>> dir(str)
    
    # help(obj):查看帮助文档
    >>> help(list.append)
    Help on method_descriptor:
    
    append(...)
        L.append(object) -> None -- append object to end
        
    # dirmod(x,y):返回一个元组,结果为 x/有的商和余数,一般用作网页分页
    >>> divmod(10, 3)
    (3, 1)
    
    # id(obj):查看一个对象的内存地址
    >>> id(10)
    1750035808
    
    # globals():查看全局变量
    # locals():查看局部变量
    
    # pow(x,y[,z]):幂运算,z 可选, pow(x,y,z)相当于 (x**y)%z
    >>> pow(10, 3)
    1000
    >>> pow(10, 3, 4)
    0
    
    # reversed(iterable):反转一个序列
    >>> list(reversed('abc'))
    ['c', 'b', 'a']
    >>> list(reversed([1, 2, 3]))
    [3, 2, 1]
    
    # round(number,ndigits):四舍五入,保留几位有效小数
    >>> round(4.5)
    4
    >>> round(4.564, 2)
    4.56
    
    # set(iterable):转换成集合、创建一个集合
    >>> set('123')
    {'2', '3', '1'}
    >>> s = set()
    >>> type(s)
    <class 'set'>
    
    # slice(statr,stop[,step]):序列切片/分片
    >>> l = 'hello'
    >>> s = slice(2, 3)
    >>> l[s]
    'l'
    
    # str():转换为字符串
    >>> str(123)
    '123'
    
    # sum(iterable, start=0):求序列中所有元素的和,还可指定
    >>> l = [1, 2, 3, 4]
    >>> sum(l)
    10
    >>> sum(l, 1)
    11
    
    # tuple():转换为元组
    >>> tuple(['a', 1])
    ('a', 1)
    
    # vars(obj):返回对象的属性和属性值的字典对象。
    >>> vars()
    {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'name': '你好', 'd': "{'name:': '
    rose'}", 's': slice(2, 3, None), 'p': {'name': 'rose', 'age': 18, 'gender': 'male'}, 't': <zip object at 0x0000000002D9FF08>, 'i': ('c', 3), 'age': {'rose': 18, 'tom': 19}, 'li': 'hello', 'l': [1, 2, 3, 4]}
     >>> vars(str)
     ....
     
     # __import__():当模块名是字符串是,可以使用。
     >>> module_name = 'test'
    >>> __import__(module_name)
    <module 'test' from 'C:\Users\HJ\Anaconda3\lib\test\__init__.py'>
    >>> import module_name
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ModuleNotFoundError: No module named 'module_name'
    

      1. eval()

      eval(expression,[globals[,locals]),用于执行一个字符串表达式,并返回表达式值,可以去掉字符串的引号

    >>> d = "{'name:': 'rose'}"
    >>> type(d)
    <class 'str'>
    >>> s = eval(d)
    >>> type(s)
    <class 'dict'>
    

      字符串中表达式的值,也可以计算:

    >>> express = '1*2+3'
    >>> eval(express)
    5
    
    

      2. hash()

      hash(obj)做哈希运算,不管对象有多长,经过哈希运算后的值长度都相同,也不能根据 hash 值反推出原始对象。

      可用于校对软件/文件是否被别人篡改,还可用于判断软件或文件是否下载完整(检验官方给出的 hash 值与自己下载完毕 hash 的值是否相同)

    • 可哈希数据类型:即不可变数据类型,如:字符串、元组
    • 不可哈希数据类型:即可变数据类型,如:列表、字典、集合
    >>> hash('abc')
    5994226220732616244
    >>> hash('123')
    -3466646395452377901
    

      3. isinstance()、type()

      两个都是用于判断数据类型,官方建议使用 isinstance。

    >>> type(123)
    <class 'int'>
    nums = '123'
    if type(nums) is str:
        res = int(nums) + 1
    

      isinstance(x,A_tuple)有两个参数:第一个是待确定类型的数据,第二个是指定一个数据类型,判断两者是否一致,返回一个布尔值。

    >>> isinstance(123, int)
    True
    

      4. zip()

      zip(ite1[,iter2[...]])函数接收两个序列,要求它们元素数据相等,返回两个序列元素一一对应的元组(返回的是 zip 对象的内存地址)。

    >>> p = {'name': 'rose', 'age': 18, 'gender': 'male'}
    >>> t = zip(p.keys(), p.values())
    >>> list(t)
    [('name', 'rose'), ('age', 18), ('gender', 'male')]
    >>> list(zip(['a', 'b', 'c'], [1, 2, 3]))
    [('a', 1), ('b', 2), ('c', 3)]
    
    >>> for i in zip(['a', 'b', 'c'], [1, 2, 3]):
    ...     print(i)
    ...
    ('a', 1)
    ('b', 2)
    ('c', 3)
    

      5. max()、min()

      max(iterable, key, default)、min()返回一个序列中的最大、小元素。

      特性:

    • 原理是将序列中每个元素都循环遍历出来比较
    • 首先比较第一个字符,分出大小则停止比较,若分出,钻继续比较。不同数据类型不能比较
    • 字典比较,默认比较 key
    >>> max([1, 2, 3])                                       
    3                                                        
    >>> max(['a', 'b'])                                      
    'b'                                                      
    >>> max(['a12', 'a2'])                 # a 相同,2>1               
    'a2'                                   # b>a                   
    >>> max(['a12', 'b10'])                                  
    'b10'                                                    
             
    >>> age = {'rose': 18, 'tom': 19}      # 字典比较默认比较 key                  
    >>> max(age)                                             
    'tom'                                          
    
    >>> max(zip(age.values(), age.keys()))        #  既比较大小,又把名字也打印出来                                        
    (19, 'tom')                                              
    

      max()还可以指定比较方法:

    # 取出 age 比较
    >>> people = [
        {'name': 'rose', 'age': 18},
        {'name': 'lila', 'age': 30},
        {'name': 'tom', 'age': 60}
    ]
    
    >>> max(people, key=lambda dic:dic.get('age'))
    {'name': 'tom', 'age': 60}
    
  • 相关阅读:
    1058 A+B in Hogwarts (20)
    1046 Shortest Distance (20)
    1061 Dating (20)
    1041 Be Unique (20)
    1015 Reversible Primes (20)(20 分)
    pat 1027 Colors in Mars (20)
    PAT 1008 Elevator (20)
    操作系统 死锁
    Ajax的get方式传值 避免& 与= 号
    让IE浏览器支持CSS3表现
  • 原文地址:https://www.cnblogs.com/midworld/p/10268355.html
Copyright © 2020-2023  润新知