Python参数之self,可变参数*args ,**kwargs

  • Post author:
  • Post category:python

众所周知,定义一个函数需要传进去参数,那,假如参数个数不固定,意思就是定义时候,根本不知道要传递几个参数进去,该怎么办呢?这个时候,可变参数就派上用场了。
我们可以使用*args与**kwargs来作为形参,定义函数。假如我们把一个普通函数封装到类里面,那么,会有什么本质的区别么?答案是肯定的,函数的第一个参数默认必须是self,因为只有这样,这个函数才被标识为属于哪个类,而且,更是为了方便访问类里面的其他实例方法跟属性变量。

*arg的使用

def func_1(*kk):
    print(kk, type(kk))


if __name__ == "__main__":
    func_1(1, 5, 'ops')
'''
打印结果如下:
(1, 5, 'ops') <class 'tuple'>
'''

可以看到,我们传递进去的多个参数,居然被合成为一个tuple的类型数据了。
然后,我们更改函数,让函数既可以接收指定的参数,又可以接受不固定个数的参数


def func_1(p1, p2, *kk):
    print(p1, p2, kk, type(kk))


if __name__ == "__main__":
    func_1(1, 5, 'ops', 6)
'''
打印结果如下:
1 5 ('ops', 6) <class 'tuple'>
'''

这个时候会发现,居然按照顺寻把前两个指定的参数填充了,最后剩下来的,封装成了一个tuple类型的元组,这里一定要注意,arg后面,不可以再跟参数了,因为这样,我们不知道arg到底 取几个数字。然而*arg后面是可以跟**kwargs的。因为键值对中间有等号,很容易区分开来了。

**kwargs

接下来我们再次修改一下函数,这次再函数的结尾添加**kwargs

def func_1(p1, p2, *kk, **gg):
    print(p1, p2, kk, type(kk), gg, type(gg))


if __name__ == "__main__":
    func_1(1, 5, 'ops', 6, a=3, b=4)
'''
打印结果如下:
1 5 ('ops', 6) <class 'tuple'> {'a': 3, 'b': 4} <class 'dict'>
'''

然后可以看到,这个函数不但有了可变单个参数,还有了可变键值对参数(dict)。键值对不管有几个,都被封装到了一个dict类型的参数里面了。
最后注意一下参数顺序,必须按照有名字参数,*args,**kwargs这样的顺序。例如下面都是反例

def func_1(p1, p2, *kk, p3, **gg):  #这一句在使用的时候,一定要把p3=5明确写出来p3等于多少,否则调用也报错。
def func_1(p1, p2, *kk, p3, **gg,p4):  #这一句通不过编译

self参数

上面所展示的函数都是普通的函数,为了引入self参数,我们必须引入面向对象的概念,面向对象,指向对象自己本身的数据类型,需要一个指针(或者是句柄(对指针的进一步封装,里面封装了对象自身数据的指针与对象所属类型的指针)),代码如下


class Creature:
    def creature_speak(self, name):  # 这个参数self是必须的,没有这个参数编译不通过
        print(name)

    def creature_do_math(self, num):
        num = num ** 2
        print(num)


if __name__ == "__main__":
    creature = Creature()
    creature.creature_do_math(5)  # 这一句相当于调用了self.creature_do_math(self,5)

可见,如果一个函数被封装到了类里面,那么,self作为函数第一个参数是必须的,因为只有这样,才能确定调用这个函数的是那个对象实例。这就是被封装到类里面的函数与普通的函数的本质区别。


版权声明:本文为aLLLiyyy原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。