zoukankan      html  css  js  c++  java
  • Python(11):Python函数基础(定义函数、函数参数、匿名函数)

    函数先定义函数,后调用

    一、定义函数:

    1、简单的规则:

    • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()
    • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
    • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
    • 函数内容以冒号起始,并且缩进。
    • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。

    2、语法

    Python 定义函数使用 def 关键字

    默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配起来的。

    def 函数名(param1,param2……):
    """
    函数功能的描述信息
    :param1:描述
    :param2:描述
    :return:返回值
    """
    code
    ...
    return 返回值

    3、无参函数

    def register():
        """注册功能"""
        username = input('username: ').strip()
        pwd = input('password: ').strip()
    
        with open('32.txt', 'a', encoding='utf8') as fa:
            fa.write(f"{username}:{pwd}
    ")
            fa.flush()

    4、有参函数

    def sum_self(x, y):
        """求和"""
        res = x+y
        print(res)
    
    sum_self(1,2)  # 3

    5、空函数

    你只知道你需要实现某个功能,但不知道该如何用代码实现时,你可以暂时写个空函数

    def func():
        pass

    二、调用函数及返回值

    定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。

    这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行。

    函数名(param1、param2……)

    如:

    register()

    1、函数运行完毕所有代码,如果函数体不写return,则会返回None。

    def foo():
        pass
    
    print(foo()) #None

    2、函数可以返回一个或多个值(元组类型)

    def func():
        name = 'nick'
        age = 19
        hobby_list = ['read', 'run']
        return name, age, hobby_list
    
    
    name, age, hobby_list = func()
    print(name,age,hobby_list) #('nick', 19, ['read', 'run'])

    三、函数的参数

    1、普通参数,位置必需参数

    在函数定义阶段,按照从左到右的顺序依次定义的形参,称之为位置形参。

    特点:按照位置定义的形参,都必须被传值,多一个不行,少一个也不行。

    def func(x, y):
        print(x)
        print(y)

    在函数调用阶段,按照从左到右的顺序依次定义的实参,称之为位置实参。

    特点:按照位置为对应的形参依次传值。

    func(1, 2)

    2、关键字参数

    在调用函数时,按照key=value的形式为指定的参数传值,称为关键字实参。

    特点:可以打破位置的限制,但仍能为指定的形参赋值。

    func(y=2, x=1)
    1. 可以混用位置实参和关键字实参,但是位置实参必须在关键字实参的左边。
    2. 可以混用位置实参和关键字实参,但不能对一个形参重复赋值。
    func(x, y=2)
    func(y=2, x)  # SyntaxError: positional argument follows keyword argument
    func(x, x=1)  # NameError: name 'x' is not defined

    3、默认参数

    在定义阶段,就已经被赋值。意味着在调用时可以不用为其赋值。位置形参必须放在默认形参的左边。

    def func(x, y=10):
        print(x)
        print(y)
        
    func(2)

    默认形参的值只在定义阶段赋值一次,也就是说默认参数的值在函数定义阶段就已经固定了。

    m = 10
    
    def foo(x=m):
        print(x)
    
    m = 111
    foo()  # 10

    默认参数的值通常应该是不可变类型。

    def register(name, hobby, hobby_list=None):
        hobby_list = [hobby]
        print(f"{name} prefer {hobby_list}")
    
    
    register('nick', 'read')  # ['read']
    register('tank', 'zuipao')  # [ 'zuipao']
    register('jason', 'piao')  # ['piao']
    
    # 演示形参是可变类型,(列表是可变类型)
    def register(name, hobby, hobby_list=None):
        hobby_list = [hobby]
        print(f"{name} prefer {hobby_list}")
    
    
    register('nick', 'read')  # nick prefer ['read']
    register('tank', 'zuipao')  # tank prefer ['zuipao']
    register('jason', 'piao')  # jason prefer ['piao']o']

    4、不定长参数之*

    形参中的*会将溢出的位置实参全部接收,然后存储元组的形式,然后把元组赋值给*后的参数。需要注意的是:*后的参数名约定俗成为args。

    def sum_self( *args):
        res = 0
        for num in args:
            res += num
        return res
    
    
    res = sum_self(1, 2, 3, 4)
    print(res)  # 10

    注意:实参之*

    实参中的*,*会将*后参数的值循环取出,打散成位置实参。以后但凡碰到实参中带*的,它就是位置实参,应该马上打散成位置实参去看。

    def func(x, y, z, *args):
        print(x, y, z, args)
    
    
    func(1, *(1, 2) , 3, 4)  # 1 1 2 (3, 4)

    5、不定长参数之**

    形参中的**会将溢出的关键字实参全部接收,然后存储字典的形式,然后把字典赋值给**后的参数。需要注意的是:**后的参数名约定俗成为kwargs。

    def func( **kwargw):
        print(kwargw)
    
    
    func(a=5,b=3)  # {'a': 5, 'b': 3}

    注意:实参之**

    实参中的**,**会将**后参数的值循环取出,打散成关键字实参。以后但凡碰到实参中带**的,它就是关键字实参,应该马上打散成关键字实参去看。

    def func(x, y, z, **kwargs):
        print(x, y, z, kwargs)
    
    
    func(1, 3, 4, **{'a': 1, 'b': 2} )  # 1 3 4 {'a': 1, 'b': 2}

    可变长参数应用

    def index(name, age, sex):
        print(f"name: {name}, age: {age}, sex: {sex}")  # name: nick, age: 19, sex: male
    
    
    def wrapper(*args, **kwargs):
        print(f"args: {args}")  # args: ()
        print(f"kwargs: {kwargs}")  # kwargs: {'name': 'nick', 'sex': 'male', 'age': 19}
        index( *args, **kwargs)
    
    
    wrapper(name='nick', sex='male', age=19)

    6、命名关键字参数

    命名关键字则是在「位置参数」和「命名关键字参数」中使用,*,隔开,后面的即为命名关键字。* 后的参数必须用关键字传入。

    def student(name, age, *, city, gender):
        print(name, age, city, gender)
    
    
    student('xiaoming', 6, city='beijing', gender='male')  # xiaoming 6 beijing male
    student('xiaoming', 6, 'beijing', 'male') #TypeError: student() takes 2 positional arguments but 4 were given

    特点:在传值时,必须按照key=value的方式传值,并且key必须命名关键字参数的指定的参数名。

    def register(x, y, *, name, gender='male', age):
        print(x)
        print(name)
        print(age)
    
    
    register(1, 2, name1='nick', age=19)  # TypeError: register() got an unexpected keyword argument 'name1'

    Python3.8 新增了一个函数形参语法, “/” 用来指明函数形参必须使用指定位置参数,不能使用关键字参数的形式。

    在以下的例子中,形参 a 和 b 必须使用指定位置参数,c 或 d 可以是位置形参或关键字形参,而 e 或 f 要求为关键字形参:

    def f(a, b, /, c, d, *, e, f):
        print(a, b, c, d, e, f)

    以下使用方法是正确的:

    f(10, 20, 30, d=40, e=50, f=60)

    四、函数对象

    函数是第一类对象,即函数可以被当做数据处理。

    def func():
        print('from func')
    
    
    print(func)  # <function func at 0x00000000026A9040>

    1、函数当作参数传给一个另一函数

    def func():
        print('from func')
    
    
    def foo(m):
        m()
    
    
    foo(func)  # from func

    2、函数当作另一函数的返回值

    def func():
        print('from func')
    
    
    def foo(x):
        return x
    
    
    res = foo(func)
    print(res)  # <function func at 0x000000000268B040>

    3、函数可以当作容器类型的元素

    def func():
        print('from func')
    
    
    function_list = [func]
    function_list[0]()  # from func

    五、函数递归

    递归的精髓在于通过不断地重复逼近一个最终的结果。

    age(1)=26,age(n)=age(n-1)+2 ,求age(5)的值:

    '''
    ...
    age(5) = age(4) + 2
    age(4) = age(3) + 2
    age(3) = age(2) + 2
    age(2) = age(1) + 2
    age(1) = 26
    
    
    age(n) = age(n-1) +2 
    age(1) = 26  # n=1
    '''
    
    
    def age(n):
        if n == 1:
            return 26
        res = age(n-1) + 2
        return res
    
    
    print(f"age(5): {age(5)}")

    递归的本质就是干重复的活。

    lis = [1, [2, [3, [4, [5, [6, ]]]]]]
    
    
    def tell(lis):
        for i in lis:
            if type(i) is list:
                tell(i)
            else:
                print(i)
    
    
    tell(lis)

    二分法的思想实现查找数字。

    from random import randint
    
    nums = [randint(1, 100) for i in range(100)]
    nums = sorted(nums)
    
    
    def search(search_num, nums):
        print(nums)
        mid_index = len(nums) // 2
        if not nums:
            print('not exists')
            return
        if search_num > nums[mid_index]:
            # in the right
            nums = nums[mid_index + 1:]
            search(search_num, nums)
        elif search_num < nums[mid_index]:
            # in the left
            nums = nums[:mid_index]
            search(search_num, nums)
        else:
            print('find it')
    
    
    search(7, nums)

    六、匿名函数:

    python 使用 lambda 来创建匿名函数。

    所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。

    • lambda 只是一个表达式,函数体比 def 简单很多。
    • lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
    • lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
    • 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。

    1、语法

    lamdbda 参数 : 逻辑代码

    # 可写函数说明
    sum = lambda arg1, arg2: arg1 + arg2
     
    # 调用sum函数
    print ("相加后的值为 : ", sum( 10, 20 ))
    print ("相加后的值为 : ", sum( 20, 20 ))

    匿名函数,他没有绑定名字,使用一次即被收回,加括号既可以运行。

    print(lambda x, y: x + y )  # <function __main__.<lambda>(x, y)>
    res = (lambda x, y: x + y)(1, 2)
    print(res)  # 3

    lambda 匿名函数也是可以使用"关键字参数"进行参数传递,也可以设定默认值。

    g = lambda x=0, y=0: x ** 2 + y ** 2
    print(g(2, 3))
    # 13
    print(g(2))
    # 4
    print(g(y=3))
    # 9

    2、与内置函数联用

    匿名函数通常与max()、sorted()、filter()、sorted()方法联用。

    1.max()

    如果我们想从上述字典中取出薪资最高的人,我们可以使用max()方法,但是max()默认比较的是字典的key。

    1. 首先将可迭代对象变成迭代器对象
    2. res=next(迭代器对象),将res当做参数传给key指定的函数,然后将该函数的返回值当做判断依据
    salary_dict = {
        'nick': 3000,
        'jason': 100000,
        'tank': 5000,
        'sean': 2000
    }
    
    print(max(salary_dict))  # tank
    
    
    def func(k):
        return salary_dict[k]
    
    
    print(max(salary_dict, key=func))  # jason
    print(max(salary_dict, key=lambda name: salary_dict[name] ) )  # jason  匿名函数

    2.sorted()

    如果我们想对上述字典中的人,按照薪资从大到小排序,可以使用sorted()方法。

    1. 首先将可迭代对象变成迭代器对象
    2. res=next(迭代器对象),将res当做参数传给第一个参数指定的函数,然后将该函数的返回值当做判断依据。
    lis = [1, 3, 2, 5, 8, 6]
    sorted(lis)
    print(lis)  # [1, 3, 2, 5, 8, 6]
    print(sorted(lis, reverse=True))  # [8, 6, 5, 3, 2, 1]
    
    salary_dict = {
        'nick': 3000,
        'jason': 100000,
        'tank': 5000,
        'sean': 2000
    }
    
    print(sorted(salary_dict, key=lambda name: salary_dict[name] ))  # ['sean', 'nick', 'tank', 'jason']

    3.map()

    如果我们想对一个列表中的某个人名做处理,可以使用map()方法。

    1. 首先将可迭代对象变成迭代器对象
    2. res=next(迭代器对象),将res当做参数传给第一个参数指定的函数,然后将该函数的返回值作为map()方法的结果之一。
    name_list = ['jason', 'tank', 'sean']
    
    res = map(lambda name: f"{name} sb", name_list)
    print(list(res))  # ['jason sb', 'tank sb', 'sean sb']

    4.filter()

    如果我们想筛选除名字中含有'sb'的名字,我们可以使用filter()方法。

    1. 首先将可迭代对象变成迭代器对象
    2. res=next(迭代器对象),将res当做参数传给第一个参数指定的函数,然后filter会判断函数的返回值的真假,如果为真则留下。
    name_list = ['nick', 'jason sb', 'tank sb', 'sean sb']
    
    filter_res = filter(lambda name: name.endswith('sb'), name_list)
    print(list(filter_res))  # ['jason sb', 'tank sb', 'sean sb']

    七、内置函数

    共68个:

    abs()、  all()、  any()、  ascii()、  bin()、  bool()、  bytearray()、  bytes()、  callable()、  chr()、  classmethod()、  compile()、  complex()、  delattr()、 
    dict()、  dir()、  divmod()、  enumerate()、  eval()、  exec()、  filter()、  float()、  format()、  frozenset()、  getattr()、  globals()、  hasattr()、  hash()、 
    help()、  hex()、  id()、  input()、  int()、  isinstance()、  issubclass()、  iter()、  len()、  list()、  locals()、  map()、  max()、  memoryview()、 
    min()、  next()、  object()、  oct()、  open()、  ord()、  pow()、  print()、  property()、  range()、  repr()、  reversed()、  round()、  set()、 
    setattr()、  slice()、  sorted()、  staticmethod()、  str()、  sum()、  super()、  tuple()、  type()、  vars()、  zip()、  __import__()、  

    1.bytes():解码字符。

    res = '你好'.encode('utf8')
    print(res)  # b'xe4xbdxa0xe5xa5xbd'
    res = bytes('你好', encoding='utf8')
    print(res)  # b'xe4xbdxa0xe5xa5xbd'

    2.chr()/ord():chr()参考ASCII码表将数字转成对应字符;ord()将字符转换成对应的数字。

    print(chr(65)) #A
    print(ord('A')) #65

    3.divmod():分栏。

    print(divmod(10, 3)) #(3, 1)

    4.enumerate():带有索引的迭代。

    l = ['a', 'b', 'c']
    for i in enumerate(l):
        print(i)
    
    # (0, 'a')
    # (1, 'b')
    # (2, 'c')

    5.eval():把字符串翻译成数据类型。

    lis = '[1,2,3]'
    lis_eval = eval(lis)
    print(lis_eval) #[1, 2, 3]

    6.hash():是否可哈希。

    print(hash(1)) #1

    7.abs():求绝对值。

    print(abs(-13))  # 13

    8.all():可迭代对象内元素全为真,则返回真。

    print(all([1, 2, 3, 0])) #False
    print(all([])) #True

    9.any():可迭代对象中有一元素为真,则为真。

    print(any([1, 2, 3, 0])) #True
    print(any([])) #False

    10.bin()/oct()/hex():二进制、八进制、十六进制转换。

    print(bin(17)) #0b10001
    print(oct(17)) #0o21
    print(hex(17)) #0x11

    11.dir():列举出所有time的功能。

    import time
    print(dir(time))
    # ['_STRUCT_TM_ITEMS', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'altzone', 'asctime', 'clock', 'ctime', 'daylight', 'get_clock_info', 'gmtime', 'localtime', 'mktime', 'monotonic', 'perf_counter', 'process_time', 'sleep', 'strftime', 'strptime', 'struct_time', 'time', 'timezone', 'tzname', 'tzset']

    12.frozenset():不可变集合。

    s = frozenset({1, 2, 3})
    print(s) #({1, 2, 3})

    13.globals()/loacals():查看全局名字;查看局部名字。

    # print(globals())
    def func():
        a = 1
        #     print(globals())
        print(locals())
    
    
    func()  # {'a': 1}

    14.pow():

    print(pow(3, 2, 3))  # (3**2)%3 =0

    15.round():

    print(round(3.5)) #4

    16.slice():

    lis = ['a', 'b', 'c']
    s = slice(1, 4, 1)
    print(lis[s]) #['b', 'c']
    # print(lis[1:4:1])

    17.sum():

    print(sum(range(100))) #4950

    18.__import__():通过字符串导入模块。

    m = __import__('time')
    print(m.time()) #1556607502.334777

    19. 面向对象知识点

    1. classmethod
    2. staticmethod
    3. property
    4. delattr
    5. hasattr
    6. getattr
    7. setattr
    8. isinstance()
    9. issubclass()
    10. object()
    11. super()
  • 相关阅读:
    建立十字链表
    KMP算法
    魔术师发牌问题(循环链表)
    约瑟夫问题(循环链表)
    中缀表达式 转 (逆)波兰表达式
    中缀表达式求值
    迷宫问题(回溯法)
    范数
    AUC
    概率论
  • 原文地址:https://www.cnblogs.com/springsnow/p/11912755.html
Copyright © 2011-2022 走看看