社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

【Python】大神教你五分钟搞清楚Python函数的参数!

机器学习初学者 • 5 年前 • 1026 次点击  

灵活的参数

Python函数的形参种类多,且具有很高的灵活性。我们经常遇到:位置参数、关键词参数、仅限关键字参数、仅限位置参数等等。如果概念没彻底搞清楚,使用起来就不那么顺手。

“

提要:参数有 位置参数 和 关键字参数 两大类,分别都可以设置 默认值 ,也都可以设置 可变参数收集器 来分别收集两者。Python3新增了 仅限关键字参数 ,Python3.8新增了 仅限位置参数 。

”

上图概括了Python中的参数及其位置,这样在写程序的时候,我们能做到心中有数了。

本文以实际函数进化为例,逐个分析以上参数类型,最后囊括所有参数类型,以检验和加深理解。

现在,我们要编写一个HTML标签的生成函数。其调用形式:html = tag('p','Hello')

可得html内容为:

Hello

。

仅使用位置参数就能实现这个功能。

位置参数

位置参数有普通位置参数、带默认值位置参数和可变参数收集器。如下用到前两者:

def tag(name,content='Nothing...'):
    template = '%s%s>'%(name,content,name)
    return template

以上函数使用简单格式化字符串实现功能。其中name和content都是位置参数,实际调用的时候,可以灵活传入实参:

  • 忽略带默认值的参数 tag('p')
  • 顺序传入 tag('p','Hello')
  • 以命名方式乱序传入 tag(content='Hello',name='p')
  • 元组拆包传入参数 tag(*('p','Hello'))
  • 字典展开传入参数 tag(**{'name':'p','content':'Hello'})

可变参数收集

继续,我们需要根据多个内容,生成相同标签名的多个标签。例如html = tag('li','Line1','Line2','Line3')要得到html内容为:

  • Line1
  • Line2
  • Line3
  • 。

    位置参数固定数目,而内容数目多变。为了实现收集多出来的'Line2'和'Line3',我们需要在位置参数列表的末尾,使用*args这种形式,定义可变参数收集,来收集剩余位置参数。所谓剩余元素,即实参传递给普通位置参数,覆盖默认值参数后的剩余参数。

    def tag(name,content='Nothing...',*args):
        template = '%s%s>'%(name,content,name)
        if args:
            for arg in args: 
                template += '%s%s>'%(name,arg,name)
        return template

    可变参数*args,收集name和content之外的剩余位置参数。

    关键字参数

    HTML标签可能需要许多属性,比如X website中的alt和href属性。这些属性需要明确指明变量名和具体值,关键字参数非常合用。

    在位置参数列表的最后,使用**kwargs来收集关键字参数。

    def tag(name,content='Nothing...',*args,**kwargs):
        attrs = {}
        if kwargs:
            attrs.update(kwargs)
        attrs = ' '.join(['%s=\'%s\''%(k,v) for k,v in attrs.items()])

        template = '%s%s>'%(name,attrs,content,name)
        if args:
            for arg in args: 
                template += '%s%s>'%(name,attrs,arg,name)
        return template

    其调用形式为:html = tag('a','Hello',alt='test',href='http://www.baidu.com')',得html内容为:Hello`

    仅限关键字参数

    新的需求:HTML标签需要定义style、class属性。而且是强制要求定义,在生成函数调用时,必须指出这两个属性,否则报错。这样的强制关键字参数的要求,用仅限关键字参数(keyword-only),非常符合要求。

    仅限关键字参数定义在位置参数列表的末尾,关键字参数收集器之前。可以有默认值。主要特性是强制要求调用者以关键字形式传入参数。

    其调用形式header = tag('p','Welcome to my website.',class_='p1',style='font-size:30'),调用中,明确指出了仅限关键字参数class_和style。函数定义如下,其使用attrs字典整合了两个仅限关键字参数和关键字参数收集器的内容:

    def tag(name,content='Nothing...',*args,class_,style='color:000000',**kwargs):
        attrs = {}
        attrs['class'] = class_ 
        attrs['style'] = style 
        if kwargs:
            attrs.update(kwargs)
        attrs = ' ' .join(['%s=\'%s\''%(k,v) for k,v in attrs.items()])

        template = '%s%s>'%(name,attrs,content,name)
        if args:
            for arg in args: 
                template += '%s%s>'%(name,attrs,arg,name)
        return template

    仅限位置参数

    tag标签生成HTML中的前两个参数:name表示标签名,content表示标签内容。我们不希望这个参数乱用,或者各种拆包、展开字典赋值。只希望它变成pow(2,3),divmod(14,3),这样意义非常明确的用法。以使调用tag时,明确第一个就是标签名,紧跟着标签内容。

    实现这个功能,Python3.8新增的仅限位置参数(positional_only)非常适合。在仅限位置参数后加上一个/就实现了之前的参数是仅限位置参数的功能。

    如下:

    def
    tag(name,content='Nothing...',/,*args,class_,style='color:
    000000'
    ,**kwargs)
    :
     

    调用的时候,必须指出前两项,而且只能是按照位置传入,不能命名传入、元组拆包,字典展开等。这样的强制要求简化和规范了调用。

    如下调用中,只有第一种符合仅限位置参数调用规范。

    tag('p','content','content2',class_='flo')            #可行
    tag(name='p',content = 'content','content2',class_='flo')    
    #失败

    测试

    使用如上述函数,我们实现了生成HTML标签内容的功能,整体测试如下:新建p,ul,li和a标签,封装进div,最后嵌入html中,生成index.html文件。

    header = tag('p','Welcome to my website.',class_='p1',style='font-size:30')
    intro = tag('p','gongqingkui M',class_='p1')

    li = tag('li','Python Intro.','DIY CPU',class_='li1') 
    ul1 = tag('ul','Projects',li,class_='ul1')

    homeURL = tag('a','X website',alt='Test URL',class_='a1',href='www.X.com',style='color:red')

    main = tag('div',header,intro,ul1,homeURL,class_='main')
    html = tag('html',tag('head','',class_=''),tag('body',main,class_=''),class_='')

    with open('index.html','w',encoding='utf-8')as f:
    f.write(html) 

    源代码戳:https://gist.github.com/gongqingkui/5e4d1d8967a5eb47a1caee4eee3fc617

    总结

    • 参数有 位置参数 和 关键字参数 两大类

      分别都可以设置 默认值

      也都可以设置 可变参数收集器 来分别收集两者

    • Python3新增了 仅限关键字参数

    • Python3.8新增了 仅限位置参数

    • 参数形式总结如下,函数def fun(a,b=2,/,c,d=4,*args,e,f=6,**kwargs)中:

      a 仅限位置参数

      b 带默认值的仅限位置参数

      c 位置参数

      d 带默认值的位置参数

      *args 位置参数收集器

      e 仅限关键字参数

      f 带默认值的仅限关键字参数

      **kwargs 关键字参数收集器


    往期精彩回顾





    本站qq群851320808,加入微信群请扫码:

    Python社区是高质量的Python/Django开发社区
    本文地址:http://www.python88.com/topic/113853