python生成html标签(定位参数和关键字参数、多个参数传入的解封装)

fluent_python的例子

今天在书上看到了一个生成html标签的例子,刚好复习了一下定位参数和关键字参数的定义。

定位参数:
顾名思义,就是按照定义的位置来确定参数,所以参数的传递一定要按照参数的顺序。
关键字参数:
通过func(a=10,b=‘xybb’)这样的方式来指定形参内容的方式,叫做关键字参数。这种情况下可以不按照顺序传入。

同时我们也可以进行混用传入,但此时定位参数是需要在前面的,将所有的关键字参数丢到后面。(不清楚如果两者交叉会怎么样,这样的细节可能会被问道,但在实际的应用中还是稳妥一点好)

另外,我们可能不知道传入的参数的个数,这时我们可以使用’*’ 和’**'来进行处理。(没错,就是一个星号和两个)

直接上代码吧:

def tag(name, *content, cls=None, **attrs):
    """生成一个或多个html标签"""
    if cls:
        attrs['class'] = cls
    if attrs:
        # 制作class="abc"这样的标签部分
        attr_str = ''.join(' %s="%s"' % (attr, value)for attr, value in sorted(attrs.items()))
    else:
        attr_str = ''
    
    if content:
        return '\n'.join('<%s%s>%s</%s>'%(name, attr_str, c, name) for c in content)
    else:
        # </br>这种的单面标识
        return '<%s%s />' % (name, attr_str)

规则
首先一个星号是针对定位输入的情况。我们调用函数的时候,可以理解成将函数打包成一个元组(和一个字典,这个后面再说),然后对应传入参数。
比如我们的这个tag函数,先看到有一个name,将第一个参数给过去,然后剩下的一堆,看到了*content,直接丢进去,星号的作用就是元组的解封装,这样我们就将所有的参数都传入进去了。

那我们说的字典又是怎么回事?
比如我们传入一个tag(‘p’, ‘hello’, ‘world’, cls=‘sidebar’, a=‘a’, b=‘b’, c=‘c’)
如果把关键字参数也搞成元组丢进去,很明显是不准确的,所以我们是一个元组一个字典,按照这样,我们的双星号就是将字典进行解封装。
上面的例子中,p、hello、world打包成元组,cls、a、b、c打包成字典,然后看到name,丢一个p进去,剩下的都给content,他会实现将参数单个传入。字典同理,cls对应还上给cls参数,剩下的attrs实现解封装传入。

我们的形参中,先是一个定位参数,然后是元组解封装,同理字典也是这样,防止我们需要的参数也被解封装导致不能传入。

在正常的读入过程中,先是看定位参数,然后是关键字参数,剩下的才会考虑丢到元组和字典中。(有关键字的在字典,没有的是元组)

如果揪着细节的话,函数有一些特有方法:
'__default __‘有所有的默认值,是一个元组;
’ __ kwdefaults __‘属性中仅保存有关键字的参数;
‘ __code __.co_varnames’ 中有函数的参数名称和函数内部变量的名称;
’ __code __.co_argcount’ 中有参数的个数。

所以我们是可以通过从后往前的方式来将参数和默认值对应起来。

一个小细节:
如果我们不想要一些传入的参数,我们可以直接写一个*上去,就能将定位参数吃掉,后面想要的参数处理成关键字参数就行。

举个例子

我们的标题是html标签啊,不能当标题党。

输入:

print(tag('br'))
print(tag('p', 'hello'))
print(tag('p', 'hello', 'world'))
print(tag('p', 'hello', id=33))
print(tag('p', 'hello', 'world', cls='sidebar'))
print(tag(content='testing', name='img'))
my_tag = {
    'name' : 'img',
    'title': 'Sunset',
    'src'  : 'sunset.jpg',
    'cls'  : 'framed'
}
print(tag(**my_tag))

结果:
在这里插入图片描述

第一个案例中,只有一个name参数为br,attr_str=’’,我们走的是最后一个else,输出’《br /》’。(如果是尖角括号会被markdown解释为html元素)。

第二个案例,name=‘p’,同时定位参数有一个hello,attrs=None,我们走第二组分支的if,显示《p>hello</p》
第三个同理,但是content中多了一个world,所以我们的join传入两个,中间有’\n’,分行显示hello和world。

第四个案例中,content=‘hello’,同时有一个id=33,因为和cls对不上,传入到attrs中。
所以此时的attr_str为"id=“33"”
所以就是《p id=“33”>hello</p》

第五个案例基本上差不多,就是要分两行输出cls=sidebar+hello/world

第六个中,看着像attr有两个键值对,但实际上name是被匹配到了,所以字典中只有一个元素,那一定会问为什么content没有被赋值为testing,因为我们的content其实就是一个口袋,而不是一个形参的名字,所以是没法匹配的。
【书上把这种参数叫做变长参数】

最后一个可谓是最离谱的一个,先将所有的参数打包成一个字典。
这种情况下,其实是先进行一个解封装,所有的参数都是关键字参数,name和cls被匹配上,attr中有剩下的两个。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值