*args与**kwarsg及闭包和装饰器

过程

先理解闭包,再理解装饰器,不要忘了不定长参数

def func():
    msg = '111'
    def func1():
        print(msg)
    return func1
 
"""
1-理解闭包
闭包即内部函数调用外部函数作用域里面的变量
比如func1就是一个闭包函数
"""
func()()# 这里实际上是func1()
"""
2-装饰器
fn是被装饰的目标函数
2.1-仅仅只是传递函数名的装饰器[基本不会用到]
2.2-装饰带有参数的函数
2.3-装饰带有返回值的函数
2.4-装饰参数不确定的函数[可归类到装饰带有参数的函数里面]
2.5-装饰器本身携带参数
"""
def decorator(fn):
    def wrapper():
        print("添加的功能,装饰不带有参数的函数")
        return fn()
    return wrapper
 
@decorator
def test():
    print("原有功能")
 
 
test()# 实际上是decorator(test)
 
def decorator1(fn):
    def wrapper(n1,n2):
        print("添加的功能,装饰带有参数的函数")
        return fn(n1,n2)
    return wrapper
 
@decorator1
def test1(a,b):
    print("a b=%s"%(a b))
    print("原有功能")
 
 
test1(1,2)# 实际上是decorator1(test1(1,2))
 
def decoretor2(fn):
    def wrapper():
        print("添加的功能,装饰带有返回值的函数")
        res = fn()
        return res
    return wrapper
 
@decoretor2
def test2():
    print("原有功能")
    return "返回值001"
 
a = test2() # 实际是decorator2(test2)
print(a)
 
 
def decorator3(fn):
    def warpper(*args,**kwargs):
        print("添加的功能,装饰不定长参数的函数")
        return fn(*args,**kwargs)
    return warpper
 
@decorator3
def test3(n1,n2,n3):
    print("原有功能")
    print(n1 n2 n3)
 
 
test3(1,2,3)# 实际上是decorator1(test1(1,2,3))
 
def decorator4(home):
    def func_1(fn):
        def wrapper(*args,**kwargs):
            print("装饰器本身携带参数")
            print("目前家在%s"%(home))
            return fn(*args,**kwargs)
        return wrapper
    return func_1
 
@decorator4(home='wuhan')
def test4(n1,n2,n3):
    print("原有功能")
    print(n1 n2 n3)
 
# test3(1,2,3)=decorator3(home="武汉")(test(1,2,3))()
"""
1-先调用decorator3(home="wuhan")
2-执行func_1(test(1,2,3)) # 到这里其实就和前面的装饰器一样
3-执行wrapper
4-执行test(1,2,3)
"""
test4(1,2,3)

Python fun(*args,**kwargs)中*args,**kwargs参数含义及用法

1. Python函数中的两种参数

我们知道,在Python中有两种参数

  • 位置参数(positional argument): 位置参数只能由参数位置决定
  • 关键词参数(keyword argument): 关键词参数只需要用 keyword = somekey 的方法即可传参

位置参数只能由参数位置决定。这也就决定了位置参数一定要在前面,否则关键词参数数量的变化都会使得位置无法判断。

2. 理解函数调用中的*

*的作用是将tuple或者list中的元素进行unpack,分开传入,作为多个参数。

def func(a,b,c)
    print(a,b,c)
alist = [1,2,3] # 这里alist的长度必须和函数中参数的个数相同,否则会报错
func(*alist)     # 等同于 func(1, 2, 3)
1 2 3

2.1 * 做了什么

它拆开数列alist的数值作为位置参数,并把这些位置参数传给函数func来调用。

因此拆数列、传位置参数意味着func(*alist)与func(1,2,3)是等效的,因为 alist= [1,2,3]。

3. 理解函数调用中的**

**的作用是unpack字典,并将字典中的数据项作为键值参数传给函数。

为了更好的理解举几个例子:

def func(a, b, c):
    print(a, b, c)
    
if __name__ == "__main__":
    dic = {'b': 2, 'c': 3}
    func(1, b=2, c=3)
    func(1, **dic)
1 2 3
1 2 3

4. 理解函数调用中的*args和**kwargs

kwargs是keyword argument的缩写,args就是argument。常见的是*args 在 **kwargs 前面。

这两个的用途和效果如下:

def this_fun(a,b,*args,**kwargs):
    """
    在这个函数定义中,参数”a, b”代表”常规参数列表”。
    args 接收元组作为位置参数,而非是常见的参数列表
    
    """
    print(a,b)
    print(args)
    print(kwargs)
if __name__ = '__main__'
    this_fun(0,1,2,3,index1=11,index2=22)
    
0,1
(2, 3)
{'index2': 22, 'index1': 11}

也就是说,第一中不定的参数形式把剩下的没有关键字的参数收起来形成一个tuple,而第二种把有关键字的收起来做成一个字典。

5. 实例说明args, kwargs的应用场景

5.1 子类传参给父类方法

在任何时候继承类和重写方法的,我们应当用到args, kwargs将接收到的位置参数和键值参数给父类方法。通过实例我们更好的理解

class Model(object):
    def __init__(self, name):
        self.name = name
    def save(self, force_update=False, force_insert=False):
        if force_update and force_insert:
            raise ValueError("Cannot perform both operations")
        if force_update:
            print("Updated an existing record")
        if force_insert:
            print("Created a new record")

定义一个类,我们可以创建类的对象,类的对象有一个方法save().假设类的对象可以通过save()方法保存到数据库中。通过函数save()参数来决定是否在数据库中创建一条记录或者更新现存的记录。

构造一个新类,类有Model的行为,但只有符合某些条件才会保存这个类的对象。这个新类继承Model,重写Model的save()

class ChildModel(Model):
    def save(self, *args, **kwargs):
        if self.name == 'abcd':
            super(ChildModel, self).save(*args, **kwargs)
        else:
            return None

实际上对应的保存动作发生在’Model’的save方法中。所以我们调用子类的的save()方法而非’Model’的方法.子类ChildModel的save()接收任何父类save()需要的参数,并传给父类方法。因此,子类save()方法参数列表中有*args和**kwargs,它们可以接收任意位置参数或键值参数,常规参数列表除外。

下面创建ChildModel实体并调用save方法:

c=ChildModel('abcd')
c.save(force_insert=True)
c.save(force_update=True)
# 结果
Created a new record
Updated an existing record

这里传参数给对象的save()方法。调用的是子类的save(), 它接收一个包含关键字参数kwargs的字典。然后,它使用**将字典作为关键字参数unpack,然后将其传递给超类save()。因此,超类save()获得关键字参数force_insert并执行相应的操作。

5.2 *args 实现sum

def my_sum(*args):
    res = 0
    for val in args:
        res  = val
    return res
    
l1 = [4, 8]
l2 = [1,2,3]
print(my_sum(*l1))         # 12
print(my_sum(*l2))         # 6
print(my_sum(4,5,6))     # 15

以上为个人经验,希望能给大家一个参考,也希望大家多多支持Devmax。

python中*args与**kwarsg及闭包和装饰器的用法的更多相关文章

  1. ios – Swift中的UIView动画不起作用,错误的参数错误

    我正在尝试制作动画并使用下面的代码.我得到“无法使用类型’的参数列表调用’animateWithDuration'(FloatLiteralConvertible,延迟:FloatLiteralConvertible,选项:UIViewAnimationoptions,动画:()–>()–>$T4,完成:(Bool)–>(Bool)–>$T5)’“错误.这意味着我使用了错误的参数.我错了.请

  2. ios – 使用捕获列表中的无主内容导致崩溃,即使块本身也不会执行

    欣赏有关如何调试此内容的任何提示或有关导致崩溃的原因的解释……

  3. XCode 3.2 Ruby和Python模板

    在xcode3.2下,我的ObjectiveCPython/Ruby项目仍然可以打开更新和编译,但是你无法创建新项目.鉴于xcode3.2中缺少ruby和python的所有痕迹(即创建项目并添加新的ruby/python文件),是否有一种简单的方法可以再次安装模板?我发现了一些关于将它们复制到某个文件夹的信息,但我似乎无法让它工作,我怀疑文件夹的位置已经改变为3.2.解决方法3.2中的应用程序模板

  4. ios – Swift传递封闭与Params

    目前我传递一个闭包作为一个对象的属性,该对象不接受参数并且没有返回值,如下所示:到目前为止,这工作得很好.我希望能够在设置此闭包时传入一个参数,以便在MyClass的实例中使用.我正在寻找下面的SOMETHING,虽然我确定语法不正确:我如何将参数传递给可以在MyClass中使用的闭包–即可以在属性本身的didSet部分内使用的值,如第二个示例中所示?

  5. ios – 来自UIAlertController的self.navigationController?.popViewControllerAnimated

    我是新手,但我想我已经掌握了它.这让我的进步很难过.我想要做的是当我们无法找到他的查询的相关数据时向用户抛出错误消息,然后继续将他带回到之前的ViewController.但是,我在这方面遇到了麻烦.在我添加操作的行上,我收到以下错误:’UIViewController?’不是Void的子类型我该怎么做呢?

  6. ios – 如何添加@noescape注释到可选闭包

    我的功能有这个签名:而现在我想让自己在给定的关闭中逃脱自我.但是当我尝试这个:编译器抱怨:是否可以在可选参数中使用它?

  7. ios – Swift闭包为AnyObject

    如何将()–>()转换为AnyObject?我试图将它转换为:处理程序为AnyObject,但它给我一个错误说:()–>()不符合协议’AnyObject’解决方法HowcanIcast()->()intoAnyObject?

  8. ios – 在swift中将捕获列表正确放置在嵌套闭包中

    在Swift中为哪些嵌套闭包定义捕获的引用?如果[weakself]被捕获在只有内部最后面的闭包,GCD将保留ExampleDataSource,直到块完成执行,这就解释了为什么调试看起来像这样:同样的事情会发生,如果没有捕获列表被包括,我们从来没有可选地解开自己,尽管编译器,确实试图警告你!

  9. ios – 两个类,回调和单元测试

    而且,我不觉得这样的行为会很容易测试?

  10. 寒城攻略:Listo 教你 25 天学会 Swift 语言 - 18 Automatic Reference Counting

    //每个Person类的实例拥有一个被初始化为nil的apartment可选属性,因为一个人并不一定拥有一座公寓)}}classApartment{letnumber:Intinit{number=number}tenant:Person1?//声明Apartment2类中的tenant属性为弱引用varPin:Person2?鉴于这种关系,Customer类有一个可选类型属性card,而CreditCard类的customer属性则是非可选类型的classCustomer{varcard:CreditC

随机推荐

  1. 10 个Python中Pip的使用技巧分享

    众所周知,pip 可以安装、更新、卸载 Python 的第三方库,非常方便。本文小编为大家总结了Python中Pip的使用技巧,需要的可以参考一下

  2. python数学建模之三大模型与十大常用算法详情

    这篇文章主要介绍了python数学建模之三大模型与十大常用算法详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感想取得小伙伴可以参考一下

  3. Python爬取奶茶店数据分析哪家最好喝以及性价比

    这篇文章主要介绍了用Python告诉你奶茶哪家最好喝性价比最高,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

  4. 使用pyinstaller打包.exe文件的详细教程

    PyInstaller是一个跨平台的Python应用打包工具,能够把 Python 脚本及其所在的 Python 解释器打包成可执行文件,下面这篇文章主要给大家介绍了关于使用pyinstaller打包.exe文件的相关资料,需要的朋友可以参考下

  5. 基于Python实现射击小游戏的制作

    这篇文章主要介绍了如何利用Python制作一个自己专属的第一人称射击小游戏,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起动手试一试

  6. Python list append方法之给列表追加元素

    这篇文章主要介绍了Python list append方法如何给列表追加元素,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  7. Pytest+Request+Allure+Jenkins实现接口自动化

    这篇文章介绍了Pytest+Request+Allure+Jenkins实现接口自动化的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  8. 利用python实现简单的情感分析实例教程

    商品评论挖掘、电影推荐、股市预测……情感分析大有用武之地,下面这篇文章主要给大家介绍了关于利用python实现简单的情感分析的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下

  9. 利用Python上传日志并监控告警的方法详解

    这篇文章将详细为大家介绍如何通过阿里云日志服务搭建一套通过Python上传日志、配置日志告警的监控服务,感兴趣的小伙伴可以了解一下

  10. Pycharm中运行程序在Python console中执行,不是直接Run问题

    这篇文章主要介绍了Pycharm中运行程序在Python console中执行,不是直接Run问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

返回
顶部