zoukankan      html  css  js  c++  java
  • python学习7

    一、动态传参

    动态传参用到 *args 和 **kwargs ,*号表示接收位置参数,args是参数名;**表示接收关键字参数,kwargs是参数名

    复制代码
     1 def chi(*food):
     2     print(food)    #('胡辣汤', '油条', "豆浆")
     3     print(*food)   #'胡辣汤', '油条', "豆浆
     4 chi("胡辣汤","油条","豆浆")
     5 
     6 
     7 def chi(**food):
     8     print(food)   
     9 
    10 chi(food1="胡辣汤",food2 = "油条",food3="豆浆")
    11 #结果  {'food1': '胡辣汤', 'food2': '油条', 'food3': '豆浆'}
    复制代码

    参数顺序: 位置参数,*args, 默认值参数,**kwargs

    无敌传参:可以接收任何参数

    1 #无敌传参示例
    2 def func(*args, **kwargs):   #可以是任何参数
    3        pass
    4 
    5 func("位置参数",kw ="关键字参数")

    注意:*号在形参位置表示聚合,在实参位置表示打散  ,字典打散用两个**

    复制代码
    def func(*args): #形参位置  聚合
        print(args)
    lst = [1,2,3]
    t = (22,33)
    func(*lst,*t)  #实参位置 将列表和元组打散了
    #结果  (1, 2, 3, 22, 33)
    
    def fun(**kwargs):  #形参位置,聚合
         print(kwargs)
    
    dic1 = {"name":"alex","gender":"男"}
    dic2 = {"age":"1000"}
    fun(**dic1,**dic2)    #实参位置, 字典打散
    # 结果 {'name': 'alex', 'gender': '男', 'age': '1000'}
    
    dic1 = {"name":"alex","age":"30"}
    dic2 = {"age":"1000"}
    fun(**dic1,**dic2)  #这是会报错,因为两个字典中有重复的key,一个key对应多个值
    复制代码

    二、命名空间和作用域

    在python解释器开始执行之后, 就会在内存中开辟一个空间, 每当遇到一个变量的时候, 就把变量名和值之间的关系记录下来,

    我们给存放名字和值的关系的空间起了个名字叫:命名空间。我们的变量在存储的时候就 是存储在这片空间中的。

    分为内置命名空间、全局命名空间、局部命名空间

    内置空间存储python解释器内置的东西,全局空间放py文件中函数外声明的变量,局部空间放函数内声明的变量

    顺序:

    文件加载时

      先加载内置空间,再全局,最后局部(函数调用时才用到)

    在取值的时

    先从局部空间找,然后是全局空间,最后是内置空间

    作用域

    作用域就是作用范围, 按照生效范围来看分为 全局作用域和局部作用域

    全局作用域: 内置空间+全局空间的变量

    局部作用域:局部空间的变量

    查看作用域:

      globals()  查看全局作用域中的变量名字

      locals() 查看当前作用域中的变量名字  (可以用在全局也可以用在局部)

    三、函数的嵌套

    1. 注意函数的执行顺序

    2. 只要遇到了()就是函数的调用. 如果没有()就不是函数的调用

    四、golbal和nonlocal关键字

    golbal关键字  表示引入全局变量 arg,如果全局变量中没有arg就在局部声明这个变量为全局变量

    nonlocal关键字  表示在局部 引入上一层空间的变量,如果上一层没有继续找上一层,都没有时报错。

    a = 100
    def func():
    print(a) # 取值时可以取全局变量,逐层往上找
    func()

    def func():
    a = 28 # 想要修改时会报错,局部空间不能直接修改全局变量
    print(a)
    func()
    --------------
    a = 100
    def func():
    global a # 加了个global表示不在局部创建这个变量了. 而是直接使用全局的a
    print(a) #100
    a = 28 #这时就能在局部空间修改全局变量了
    print(a) #28
    func()
    print(a) #28

    golbal

    a = 10
    def func1():
    a = 20
    def func2():
    nonlocal a #找上一层的a a = 20
    a = 30 #将a =20 修改为 a =30
    print(a) #30
    func2()
    print(a) #10
    func1()

    nonlocal

    函数默认参数的初始化问题

    函数的默认参数使得函数的调用变得简单。实际上,默认参数的值只在定义时计算一次,因此每次使用默认参数调用函数时,得到的默认参数值是相同的。我们看一个例子。

    复制代码
    import datetime as dt
    from time import sleep
    
    def log_time(msg,time = dt.datetime.now()):
        sleep(1)
        print("%s:%s"%(time.isoformat(),msg))
    
    log_time("msg 1")
    log_time("msg 2")
    log_time("msg 3")
    复制代码

    结果:

    三次调用函数得到的默认值是一模一样,而且中间让程序睡眠了1秒,可以排除是程序运行太快的因素,因此这足以说明函数的默认值只在定义的时候计算了一次,以后每次调用用到默认值时都是用的定义时计算的值。

    可变参数与不可变参数

    当默认参数是可变参数时:

    复制代码
    1 def bad_append(new_item,a_list =[]):   #列表是可变数据类型
    2     print("address of a_list:",id(a_list))
    3     a_list.append(new_item)
    4     return a_list
    5 
    6 print(bad_append("1"))  # ["1"]
    7 print(bad_append("2"))   # ["1","2"]
    复制代码

    我们期待结果是["1"] 和 ["2"],但实际是["1"]和["1","2"],这是因为,函数参数只在定义的时候计算一次,在定义时参数a_list的内存你地址已经分配好了,由于列表是可变数据类型,改变数据不会重新创建对象,也就没有内存地址的重新分配,所以在以后调用时,只要不给默认参数重新赋值,它的内存地址都不会改变。两次调用用的是同一个内存地址,操作的是同一个列表。

    当参数时不可变数据类型时:

    复制代码
    def immutable_test(i =1):
        print("befor,adress of i",id(i))  
        i += 1
        print("after,address of i",id(i))  
        return i
    
    print(immutable_test())  
    print(immutable_test())
    复制代码

    结果:

    很明显第二次调用没有受第一次调用的影响,因为 i 是不可变数据类型,对它的操作会使内存重新分配,重新创建一个对象。那么函数中i += 1之后名字i指向了另外的地址;根据默认参数的规则,下次调用时,i指向的地址还是函数定义时赋予的地址,这个地址的值1并没有被改变。

    结论:

    默认参数为不可变数据类型时,多次调用不会造成任何影响;为可变数据类型时,多次调用的结果不符合预期。

    因此,在将可变数据类型作为默认参数时,就不能只在函数定义时初始化一次,而应该在每次调用时初始化。

    最佳实践是定义函数时指定可变默认参数的值为None,在函数体内部重新绑定默认参数的值。以下是对上面的两个可变默认参数示例最佳实践的应用:

    def good_append(new_item,a_list = None):
    if a_list is None:
    a_list = []
    a_list.append(new_item)
    return a_list

    print(good_append("1")) #['1']
    print(good_append("2")) #['2']
    print(good_append("c",["a","b"])) #['a', 'b', 'c']

    def log_time(msg,time = None):
    if time is None:
    time = dt.datetime.now()
    sleep(1)
    print("%s:%s"%(time.isoformat(),msg))

    log_time("msg1") #2018-10-31T19:44:34.117109:msg1
    log_time("msg2") #2018-10-31T19:44:35.117166:msg2

    最佳实践

  • 相关阅读:
    494 Target Sum 目标和
    493 Reverse Pairs 翻转对
    492 Construct the Rectangle 构建矩形
    491 Increasing Subsequences 递增子序列
    488 Zuma Game 祖玛游戏
    486 Predict the Winner 预测赢家
    485 Max Consecutive Ones 最大连续1的个数
    483 Smallest Good Base
    Django Form组件
    Django Auth组件
  • 原文地址:https://www.cnblogs.com/wuyufeng-9-14/p/10172625.html
Copyright © 2011-2022 走看看