zoukankan      html  css  js  c++  java
  • 函数

    定义:

    对功能进行定义和封装,在需要时候,随时拿过来直接调用,定义和封装的就是函数.

    函数:对代码块的封装和定义

    调用函数:

    定义函数的语法:

    def   函数名():

          函数体(代码块)

    函数名的命名规则和变量的命名规则一样.

    函数的调用:

    函数名()  使用函数名去调用,函数就会被调用.

    例:

    def fan():
    print("先找到电饭煲,")
    print("将适量的米洗好,")
    print("将洗好的米放入电饭煲中,")
    print("插上电源,")
    print("将到合适的时间.")
    fan()
    结果:
    先找到电饭煲,
    将适量的米洗好,
    将洗好的米放入电饭煲中,
    插上电源,
    将到合适的时间.

    函数的返回值  return

    当函数结束的时候,该调用方一个结果.

    return作用:遇到return,函数就会停止不会再继续执行.

    return的几种情况:

    1.return后面什么内容都不写后者不写return.那么返回的就是None.

    例:

    def fan():
    print("先找到电饭煲,")
    print("将适量的米洗好,")
    print("将洗好的米放入电饭煲中,")
    print("插上电源,")
    print("将到合适的时间.")
    return
    ret=fan()
    print(ret)
    结果:
    先找到电饭煲,
    将适量的米洗好,
    将洗好的米放入电饭煲中,
    插上电源,
    将到合适的时间.
    None

    2.如果return后面写一个返回值,则调用者可以接收一个结果.

    例:

    def fan():
    print("先找到电饭煲,")
    print("将适量的米洗好,")
    print("将洗好的米放入电饭煲中,")
    print("插上电源,")
    print("将到合适的时间.")
    return "做米饭步骤"
    ret=fan()
    print(ret)
    结果:
    先找到电饭煲,
    将适量的米洗好,
    将洗好的米放入电饭煲中,
    插上电源,
    将到合适的时间.
    做米饭步骤

    3.如果return后面写了多个结果,则调用者可以接收一个元组(tuple),调用者可以直接解构成多个变量.

    例:

    def yue():
    print("约会")
    return "送花","吃饭","看电影"
    a,b,c=yue()
    print(a,b,c)
    结果:
    约会
    送花 吃饭 看电影

    函数的参数:

    在函数执行的时候,给函数传递信息

    参数分为:形参和实参.

    例:

    def yue(song,fangshi):
    print("%s,吃饭,%s" % (song,fangshi))
    yue("送花","看电影")
    yue("不送","逛街")
    结果:
    送花,吃饭,看电影
    不送,吃饭,逛街

    函数的参数个数是没有要求的,但是,在运行的时候形参和实参要匹配,按照位置把实参赋值给形参.

    实参:在函数调用的位置,实际是给函数传递的值

    实参的分类:

    (1)位置参数

    (2)关键值参数.  在实参调用的时候可以指定参数的值是多少.

    (3)混合参数.  先写位置参数在写关键字参数,否则会报错.

    例:

    def xinxi(name,age,sex,hobby,salary):
    print("%s\t%s\t%s\t%s\t%s\t" % (name,age,sex,hobby,salary))
    xinxi("abc",21,"女","听歌",'10000')
    xinxi(age=20,name="abc",hobby="听歌",salary=10000,sex="女")
    xinxi("abc",21,"女",salary=10000,hobby="听歌")
    结果:
    abc 21 女 听歌 10000 
    abc 20 女 听歌 10000 
    abc 21 女 听歌 10000

    形参:在函数声明的位置,声明出来的变量

    形参的分类:

    (1)位置参数

    (2)默认值参数

    (3)默认值和位置参数混合使用

    例:

    def xinxi(id,name,sex="男"):
    print("id:%s,名字:%s,性别:%s" % (id,name,sex))
    xinxi(2,"b","女")
    xinxi(1,"a",)
    结果:
    id:2,名字:b,性别:女
    id:1,名字:a,性别:男

    函数语法:

    def 函数名(形参)

          函数体(代码块)

         (return  "   ")

    函数名(实参) 

    例:1+2+3+4+...+n=?

    def num(n):
    sum = 0
    count=1
    while count<=n:
    sum+=count
    count+=1
    return sum
    ret=num(100)
    print(ret) ==<5050>

    例:判断n是奇数还是偶数?

    def fn(n):
    if n%2==0:
    return "偶数"
    return "奇数"
    ret=fn(425)
    print(ret) ==<奇数> 

    动态参数(形参):

    动态接收位置参数 *args  [def 函数名(*参数名(可以传入任意位置的参数))]

    动态参数接收的是元组(tuple)类型的数据

    例:

    def fn(*food):
    print("我要吃:",food)
    fn("米饭","馒头","面条","菜")
    ==<我要吃: ('米饭', '馒头', '面条', '菜')>

    动态接收参数的时候要注意:动态参数必须在位置参数后面

    动态接收关键字参数  **kwargs 接收到是一个字典(dict)

    例:

    def fn(**drink):
    print(drink)
    fn(drink1="北冰洋",drink2="芬达",drink3="雪碧")
    ==<{'drink1': '北冰洋', 'drink2': '芬达', 'drink3': '雪碧'}>

    传参的顺序:位置参数->*args->默认值参数->**kwargs

    例:

    def fn(a,b,*c,d=4):
    print(a,b,c,d)
    fn(1,2,3,4,5,6,7,8,9)
    ==<1 2 (3, 4, 5, 6, 7, 8, 9) 4>

    *args 和**kwargs可以接收所有参数

    例:

    def fn(*args,**kwargs):
    print(args,kwargs)
    fn(1,5,6,7,name="a",age=12,sex="女")
    ==<(1, 5, 6, 7) {'name': 'a', 'age': 12, 'sex': '女'}>

    动态传参的另一种传参方式:

    在实参位置上给一个序列,列表,在可迭代对象前面加一个*表示把这个序列按照顺序打散.

    在形参位置上加*表示把接收的参数组合成一个元组

    字典也可以打散,需要两个*

    例:

    def fn(*args):
    print(args)
    li=["麻花","月季","紫金花","玫瑰花"]
    fn(*li)
    ==<('麻花', '月季', '紫金花', '玫瑰花')>

    例:

    def fn(**kwargs):
    print(kwargs)
    dic={"a":1,"b":2}
    fn(**dic)
    ==<{'a': 1, 'b': 2}>

    注释:

    例:

    def fn(a,b):
    """
    函数fn是计算a+b的和
    :param a: 第一个数
    :param b: 第二个数
    :return: 返回a+b的和
    """
    print(a,b)
    return a+b

    命名空间:

    1.内置命名空间:python解释器内部运行时的变量函数list,tuple,str,int这些都是内置命名空间

    2.全局命名空间:直接在py文件中,函数外声明的变量都属于全局命名空间.

    3.局部命名空间:在函数中声明的变量会放到局部命名空间.

    加载顺序:内置命名空间>全局命名空间>局部命名空间(函数被执行的时候)

    取值顺序:局部命名空间>全局命名空间>内置命名空间

    作用域:

    1.全局作用域:全局命名空间+内置命名空间  通过globals()函数查看全局作用域中的内容

    2.局部作用域:局部命名函数 通过locals()函数查看局部作用域中的变量和函数信息

    例:

    a=10
    def fn():
    a=40
    b=20
    def abc():
    print("haha")
    print(a,b)
    print(globals())
    print(locals())
    fn()

    函数嵌套:

    1.只要遇见()就是函数的调用.如果没有()就不是函数的调用

    2.函数的执行顺序

    例:

    def fn1():               #1
    print("haha") #3
    def fn2(): #4
    print("keke") #6
    fn2() #5
    print("hoho") #7
    fn1() #2
    ==<haha
    keke
    hoho>

    关键字global和nonlocal:

    global表示.不在使用局部变量作用域中的内容.而改用全局作用域中的变量

    例:

    a=10
    def fun():
    global a #表示不再局部创建这个变量,而是直接使用全局的a
    a=20
    print(a)
    fun()
    print(a) ==<20 20>

    nonlocal 表示在局域作用域中1,调用父级命名空间中的变量

    例:

    a=10
    def fn1():
    a=20
    def fn2():
    nonlocal a
    a=30
    print(a)
    fn2()
    print(a)
    fn1() ==<30 30>

    函数名的运用:

    函数名是一个变量,但它是一个特殊的变量,与括号配合可以执行函数的变量.

    1.函数名可以赋值给其他变量

    例:

    def fn():
    print("abc")
    print(fn) #函数的内存地址
    a = fn #将函数赋值给a
    a() #调用函数
    ==> <function fn at 0x00000229C37C2AE8>
    abc

    2.函数可以作为函数的参数

    例:

    def func(fn):
    fn()
    def gn():
    print("abc")
    func(gn) ==>abc

    3.函数名可以当做容器类的元素

    例:

    def fn1():
    print("呵呵")
    def fn2():
    print("嘿嘿")
    def fn3():
    print("吼吼")
    lis = [fn1,fn2,fn3]
    for i in lis:
    i()
    ==>呵呵
    嘿嘿
    吼吼

    4.函数名可以作为函数的返回值

    例:

    def gn():
    def inner():
    print("aaa")
    return inner #返回inner函数
    ret = gn()
    ret() ==>aaa

    闭包:

    1.闭包定义:内层函数对外层(非全局)的变量的引用.

    变量写在全局是不安全.

    例:

    def fn():
    name = "alex"
    def inner():
    print(name)
    return inner
    ret = fn()
    ret() ==>alex #访问inner函数

    2.闭包的特点:

    (1)安全(防止其它程序改变这个变量)

    (2)常驻内存,提高效率.

    3.查看闭包

    __closure__()函数可以查看闭包.

    如果不是闭包返回None 是闭包会返回cell

    例:

    def fn():
    name = "alex"
    def inner():
    print(name)
    inner()
    print(inner.__closure__)
    fn()
    ==> alex
    (<cell at 0x00000204D86B9468: str object at 0x00000204D867D0D8>,)

    迭代器:

    1.可迭代对象和迭代器

    str.list.tuple.set.range.文件句柄都是可迭代的数据类型

    可迭代的数据类型中都有__iter__()函数.用dir()函数来查看一个数据类型中是否包含了那些函数.

    例:

    s = 'abc'
    print("__iter__"in dir(s)) ==>True

    所有包含了__iter__函数的数据类型都是可迭代的数据类型

    Iterable表示可迭代的

    __iter__作用返回一个迭代器  

    __next__和__iter__两个函数都是迭代器的内部函数

    例:

    lst = ["abc","def","ghi"]
    it = lst.__iter__()
    print(it.__next__()) ==>abc
    print(it.__next__()) ==>def
    print(it.__next__()) ==>ghi
    print(it.__next__()) ==>Error 迭代到最后一个之后,再迭代会报错

    例:

    lis = ["abc","def","ghi"]
    it = lis.__iter__()
    while 1:
    try:
    name = it.__next__()
    print(name)
    except StopIteration:
    break
    ==>abc \n def \n ghi

    try...except固定搭配

    例:

    lst = [1,2,3]
    print("__iter__"in dir(lst)) ==>True
    print("__next__"in dir(lst)) ==>False

    例:

    lst = [1,2,3]
    from collections import Iterable
    from collections import Iterator
    print(isinstance(lst,Iterable)) ==>True
    print(isinstance(lst,Iterator)) ==>False

    isinstance(对象,类型)判断对象是不是...类型

    迭代器一定是可迭代的

    文件句柄是迭代器

    2.迭代器的特点

    (1)节省内存

    (2)惰性机制

    (3)不能反复,只能向下执行

    生成器:

    在python中有三种方式来获取生成器.

    1.通过生成器函数

    2.通过生成器表达式创建生成器

    3.通过数据的转换也可以获取生成器

    例:yield就是生成器函数

    def fn():
    print("ABC")
    yield 123
    print(fn()) ==><generator object fn at 0x000001924E88A938>
    获取生成器内存地址

    例:生成器实质就是迭代器.

    def fn():
    print("ABC")
    yield 123
    ret = fn()
    print(ret.__next__())
    ==>ABC
    123

    yield是分段执行一个函数.  return直接停止函数

    在程序运行完最后一个yield.那么后面继续进行__next__()程序会报错

    生成器的优点:节省内存 

    例:

    def fn():
    i = 1
    while i<100001:
    yield "衣服%s" % i
    i = i + 1
    g = fn()
    g1 = fn() g和g1是两个生成器
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())
    结果:
    衣服1
    衣服2
    衣服3
    衣服4

    生成器是一个一个的指向下一个,不会回去,__next__()到哪,指针就指到那下一次继续获取指针指向的值

    生成器函数被执行,获取的是生成器,而不是函数的执行

    生成器的for循环

    例:

    def fn():
    yield "aa"
    yield "bb"
    yield "cc"
    g = fn()
    for i in g: 本质执行的是__next__()
    print(i)
    结果:
    aa
    bb
    cc

    例:生成器加到列表里面

    def fn():
    yield 11
    yield 22
    yield 33
    g = fn()
    lst = list(g)
    print(lst)
    结果:[11, 22, 33]

    send()方法和__next__()函数一样都可以让生成器执行到下一个yield

    例:

    def eat():
    print("你吃什么啊")
    a = yield "馒头"
    print("a = ",a)
    b = yield "大饼"
    print("b =",b)
    c = yield "韭菜盒子"
    print("c =",c)
    yield "GAME OVER"
    gen = eat()
    ret1 = gen.__next__()
    print(ret1)
    ret2 = gen.send("胡辣汤")
    print(ret2)
    ret3 = gen.send("狗粮")
    print(ret3)
    ret4 = gen.send("猫粮")
    print(ret4)
    结果:
    你吃什么啊
    馒头
    a =  胡辣汤
    大饼
    b = 狗粮
    韭菜盒子
    c = 猫粮
    GAME OVER

    send和next的区别:

    (1)send和next都是让生成器走向下一次

    (2)send可以给上一个yield的位置传递值,不能给最后yield传值.在第一次执行生成器代码不能用send()

    推导式来实现生成器:

    列表推导式:

    语法:[最终结果(变量) for 变量 in 可迭代对象 条件]

    例:for循环

    lst = []
    for i in range(1,15):
    lst.append("python%d" % i)
    print(lst)
    结果:['python1', 'python2', 'python3', 'python4', 'python5', 'python6', 'python7', 'python8', 'python9', 'python10', 'python11', 'python12', 'python13', 'python14']

    例:推导式

    lst = ["prthon%d" % i for i in range(1,15)]
    print(lst)
    结果:['prthon1', 'prthon2', 'prthon3', 'prthon4', 'prthon5', 'prthon6', 'prthon7', 'prthon8', 'prthon9', 'prthon10', 'prthon11', 'prthon12', 'prthon13', 'prthon14']

    例:求100以内的偶数

    lst = [i for i in  range(1,101) if i % 2 == 0]
    print(lst)
    结果:[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100]

    生成器推导式:

    语法:(结果 for 变量 in 可迭代对象 if条件)

    例:

    g = (i for i in range(10))
    print(g) ==><generator object <genexpr> at 0x000002875BB1A938>
    print(list(g)) ==>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    生成器推导式特点:几乎不占内存;惰性机制,不到最后不会拿值

    例:

    def fn():
    print(111)
    yield 222
    g = fn()
    g1 = (i for i in g)
    g2 = (i for i in g1)
    print(list(g))
    print(list(g1))
    print(list(g2))
    结果:
    111
    [222]
    []
    []

    字典推导式:

    语法:{结果 for 变量 in 可迭代对象 条件}结果==>key:value

    例:

    dic = {"a":1,"b":2,"c":3}
    new_dic = {dic[key]:key for key in dic}
    print(new_dic) ==>1: 'a', 2: 'b', 3: 'c'}

    例:

    lst1 = ["A","B","C"]
    lst2 = ["a","b","c"]
    dic = {lst1[i]:lst2[i] for i in range(len(lst1))}
    print(dic) ==>{'A': 'a', 'B': 'b', 'C': 'c'}

    集合推导式 :  特点: 无序 去重

    语法:{结果 for 变量 in 可迭代对象 条件}

    例:

    lst = [1,-1,2,3,1,5,7,3]
    s = {i for i in lst}
    print(s) ==>{1, 2, 3, 5, 7, -1}

    例题:

    1.

    user_list = [{"name":"alex","hobby":"抽烟"},
    {"name":"alex","hobby":"喝酒"},
    {"name":"alex","hobby":"烫头"},
    {"name":"wusir","hobby":"喊麦"},
    {"name":"wusir","hobby":"街舞"}]
    ==>[{'name': 'alex', 'hobby_list': ['抽烟', '喝酒', '烫头']},
    {'name': 'wusir', 'hobby_list': ['喊麦', '街舞']}]

    解题思路: 判断是否在result里面存在这个人的信息,如果不存在则新建一个字典,把hobby_list对应的value值放到一个列表中; 如果存在把hobby_list对应的列表加入一个hobby.

     解题步骤:

    user_list = [{"name":"alex","hobby":"抽烟"},
    {"name":"alex","hobby":"喝酒"},
    {"name":"alex","hobby":"烫头"},
    {"name":"wusir","hobby":"喊麦"},
    {"name":"wusir","hobby":"街舞"}]
    result = []
    for user in user_list:
    for new_user in result:
    if new_user["name"] == user["name"]:
    new_user.setdefault("hobby_list",[]).append(user["hobby"])
    break
    else:
    dic = {}
    dic["name"] = user["name"]
    dic["hobby_list"] = [user["hobby"]]
    result.append(dic)
    print(result)

    如果默认值参数是一个可变的数据类型,在调用的时候改变了.在其他位置看到的也跟着改变.

    例:

    def extendList(val, list=[]):
    list.append(val)
    return list
    list1 = extendList(10)
    list2 = extendList(123, [])
    list3 = extendList('a')
    print('list1=%s' % list1)
    print('list2=%s' % list2)
    print('list3=%s' % list3)
    ==>list1=[10, 'a']
    list2=[123]
    list3=[10, 'a']

    2. 二分查找:查找的必须是有序序列

    例:lst = [11,22,33,44,55,66,77,88,99]

    第一种:
    lst = [11,22,33,44,55,66,77,88,99]
    n = 66
    count = 1
    left = 0
    right = len(lst)-1
    while left <= right:
    middle = (left + right)//2
    if n > lst[middle]:
    left = middle + 1
    elif n < lst[middle]:
    right = middle - 1
    else:
    print(count)
    print(middle)
    break
    count += 1
    else:
    print("不存在")
    结果:3 5

    第二种:
    lst = [11,22,33,44,55,66,77,88,99]
    def fn(left,right,n):

    if left > right:
    return -1
    else:
    middle = (left + right) // 2
    if n > lst[middle]:
    left = middle+1
    elif n < lst[middle]:
    right = middle - 1
    else:
    return middle
    return fn(left,right,n)
    print(fn(0,len(lst)-1,66)) ==>5


    第三种:
    lst = [11,22,33,44,55,66,77,88,99]
    def fn(lst,n):
    left = 0
    right = len(lst) - 1
    middle = (right + left)//2
    if right < left :
    print("不存在")
    return
    if n > lst[middle]:
    lst = lst[middle+1:]
    elif n < lst[middle]:
    lst = lst[:middle]
    else:
    print("存在")
    return
    fn(lst,n)
    fn(lst,66) ==>存在

    3.

    def add(a,b):
    return a+b
    def test():
    for r in range(4):
    yield r
    g = test()
    for n in [2,10]:
    g = (add(n ,i) for i in g )
    print(list(g)) ==>[20, 21, 22, 23]
    解题思路:for n in [2,10] g = (add(n ,i) for i in g)=====g = (add(10,i) for i in (add(10,i) for i in text()))
  • 相关阅读:
    TRAC-IK机器人运动学求解器
    机器人关节空间轨迹规划--S型速度规划
    机械臂运动学逆解(Analytical solution)
    Windows中读写ini文件
    glog日志库使用笔记
    V-rep学习笔记:切削
    机器人单关节力矩控制
    机器人中的轨迹规划(Trajectory Planning )
    DDD Example
    clearing & settlement
  • 原文地址:https://www.cnblogs.com/gxj742/p/9299717.html
Copyright © 2011-2022 走看看