def bef_aft(func):   #定义一个名为bef_aft的函数名 ,()里的是函数的参数,设置为func, 函数的参数分为实参和形参,有个参数传递的概念 ,下面有很多的解释
def PRint(*arg,**kwarg): #再度定义一个PRint函数,里面的参数列表()是*arg 和**kwarg;关于*arg **kwarg。下面有详细的解释
print("before".center(50,"-")) # 输出内容()字符串before ,center 是内置函数,居中对齐的意思,()50,"-" ??什么意思?50个——?
res=func(*arg,**kwarg) #res 等于什么? res是定义的变量吗? 又出现了kwarg ,kw是key word arg呢?最常见的是出现在参数列表里面,实际上这个符号没有任何意义只是一个名称,它指向传递给这个方法来使用的参数,就像你的名字一样,比如你叫张三,可能你同事都习惯叫你小张,你弟弟妹妹都叫你哥,实际上都是
print(res) #输出:res
print("after".center(50,"-")) #好吧,这是和上上一行一起配合夹着res显示的。
return res #请问:print 和return 有什么区别??
return PRint #又见return 返回输出定义的PRint的内容。 @bef_aft #嵌入语法糖
def f1(arg): #函数定义 f1 参数(arg)
return arg + 1 #返回 arg+1 @bef_aft #一样嵌入语法糖
def f2(arg1, arg2): #函数定义f2 ()参数列表arg1,arg2
return arg1 + arg2 #返回值 arg1+arg2 f1(2) #问题来了,这是什么意思? 函数f1 参数2??位置2
f2(5,2) #同上,5,2
def f1(arg):
return arg + 1
def f2(arg1, arg2):
return arg1 + arg2

这要用装饰器来实现。

先说说函数定义,我们都知道,下面的代码定义了一个函数funcA

def funcA():
  pass
    
显然,函数funcA没有参数(同时啥也不干:D)。

ps因为()里的是空的,没有参数。。。

下面这个函数funcB就有两个参数了,  ps 分别是a 和 b ,括号里是参数列表。
def funcB(a, b):
  print a
  print b
调用的时候,我们需要使用函数名,加上圆括号扩起来的参数列表,比如 funcB(100, 99),执行结果是:
100
99

看下面一行

很明显,参数的顺序和个数要和函数定义ps funcB中一致,如果执行funcB(100),Python会报错的:
TypeError: funcB() takes exactly 2 arguments (1 given)

我们可以在函数定义中使用参数默认值,比如
def funcC(a, b=0):
  print a
  print b
在函数funcC的定义中,参数b有默认值,是一个可选参数,如果我们调用funcC(100),b会自动赋值为0。

OK,目前为止,我们要定义一个函数的时候,必须要预先定义这个函数需要多少个参数(或者说可以接受多少个参数)。一般情况下这是没问题的,但是也有在定义函数的时候,不能知道参数个数的情况(想一想C语言里的printf函数),在Python里,带*的参数就是用来接受可变数量参数的。看一个例子:

ps,简单的例子如下:

def funcD(a, b, *c):
  print a
  print b
  print "length of c is: %d " % len(c)    # ps :注意,这里我不是很懂,output是 4 ……哦,明白了!! 就是除了 1,2 之外的所有数字。
  print c     #同样不懂,返回了一个小括号的元组(3,4,5,6)

调用funcD(1, 2, 3, 4, 5, 6)结果是
1
2
length of c is: 4
(3, 4, 5, 6)
我们看到,前面两个参数被a、b接受了,剩下的4个参数,全部被c接受了,c在这里是一个tuple。我们在调用funcD的时候,至少要传递2个参数,2个以上的参数,都放到c里了,如果只有两个参数,那么c就是一个empty tuple

好了,一颗星我们弄清楚了,下面轮到两颗星。

上面的例子里,调用函数的时候,传递的参数都是根据位置来跟函数定义里的参数表匹配的,比如funcB(100, 99)和funcB(99, 100)的执行结果是不一样的。在Python里,还支持一种用关键字参数(keyword argument)调用函数的办法,也就是在调用函数的时候,明确指定参数值付给那个形参。比如还是上面的funcB(a, b),我们通过这两种方式调用
funcB(a=100, b=99)

funcB(b=99, a=100)
结果跟funcB(100, 99)都是一样的,因为我们在使用关键字参数调用的时候,指定了把100赋值给a,99赋值给b。也就是说,关键字参数可以让我们在调用函数的时候打乱参数传递的顺序!

另外,在函数调用中,可以混合使用基于位置匹配的参数和关键字参数,前题是先给出固定位置的参数,比如
def funcE(a, b, c):
  print a
  print b
  print c

调用funcE(100, 99, 98)和调用funcE(100, c=98, b=99)的结果是一样的。

好了,经过以上铺垫,两颗星总算可以出场了:

如果一个函数定义中的最后一个形参有 ** (双星号)def funcF(a, **b):前缀,

所有正常形参之外的其他的关键字参数都将被放置在一个字典中传递给函数,比如:
def funcF(a, **b):   #定义一个函数 funcF ,参数列表是()里的 a 和 **b
  print a    #输出 a
  for x in b:   #生成器 for in ,用一个x来遍历b里面的数据。
    print x + ": " + str(b[x])   #输出 ,x 然后 拼接 :号 再拼接 字符串类型的 列表。 这里有点不懂 + str(b[x])     b【x】??
调用funcF(100, c='你好', b=200),执行结果
100
c: 你好
b: 200
大家可以看到,b是一个dict对象实例,它接受了关键字参数b和c。

常规参数,*参数及**参数可以同时使用,具体怎么用?看看Python Reference Manual吧,关于Function definitions的那些章节。其实,笨想也能猜出来啊,o(∩_∩)o...

  1. 关于*arg和**kwarg

首先我们可以定一个简单的函数, 函数内部只考虑required_arg这一个形参(位置参数)

def exmaple(required_arg):
print required_arg exmaple("Hello, World!") >> Hello, World!

那么,如果我们调用函数式传入了不止一个位置参数会出现什么情况?当然是会报错!

exmaple("Hello, World!", "another string")

>> TypeError: exmaple() takes exactly 1 argument (2 given)

def exmaple2(required_arg, *arg, **kwarg):
if arg:
print "arg: ", arg if kwarg:
print "kwarg: ", kwarg exmaple2("Hi", 1, 2, 3, keyword1 = "bar", keyword2 = "foo") >> arg: (1, 2, 3)
>> kwarg: {'keyword2': 'foo', 'keyword1': 'bar'}

从上面的例子可以看到,当我传入了更多实参的时候

  • *arg会把多出来的位置参数转化为tuple
  • **kwarg会把关键字参数转化为dict

再举个例子,一个不设定参数个数的加法函数

def sum(*arg):
res = 0
for e in arg:
res += e
return res print sum(1, 2, 3, 4)
print sum(1, 1)
>> 10
>> 2

当然,如果想控制关键字参数,可以单独使用一个*,作为特殊分隔符号。限于Python 3,下面例子中限定了只能有两个关键字参数,而且参数名为keyword1keyword2

def person(required_arg, *, keyword1, keyword2):
print(required_arg, keyword1, keyword2) person("Hi", keyword1="bar", keyword2="foo")
>> Hi bar foo

如果不传入参数名keyword1keyword2会报错,因为都会看做位置参数

person("Hi", "bar", "foo")

>> TypeError: person() takes 1 positional argument but 3 were given

调用函数时使用*arg和**kwarg

直接上例子,跟上面的情况十分类似。反向思维。

def sum(a, b, c):
return a + b + c a = [1, 2, 3] # the * unpack list a
print sum(*a)
>> 6
def sum(a, b, c):
return a + b + c a = {'a': 1, 'b': 2, 'c': 3} # the ** unpack dict a
print sum(**a)
>> 6
*arg是非关键字参数,用于元组,
**kwarg是关键字参数,用于字典
其中的 KW 代表关键字 可以看到,这两个是python中的可变参数。
*args表示任何多个无名参数,它是一个tuple;
**kwargs表示关键字参数,它是一个dict。并且同时使用*args和**kwargs时,必须*args参数列要在**kwargs前

												

180114 用装饰器实现在不改变函数调用者的代码基础上,实现在函数执行前后分别打印"before" 和 "after"的更多相关文章

  1. 谈谈Python中的decorator装饰器,如何更优雅的重用代码

    众所周知,Python本身有很多优雅的语法,让你能用一行代码写出其他语言很多行代码才能做的事情,比如: 最常用的迭代(eg: for i in range(1,10)), 列表生成式(eg: [ x* ...

  2. python描述符(descriptor)、属性(property)、函数(类)装饰器(decorator )原理实例详解

     1.前言 Python的描述符是接触到Python核心编程中一个比较难以理解的内容,自己在学习的过程中也遇到过很多的疑惑,通过google和阅读源码,现将自己的理解和心得记录下来,也为正在为了该问题 ...

  3. python 内置函数和函数装饰器

    python内置函数 1.数学相关 abs(x) 取x绝对值 divmode(x,y) 取x除以y的商和余数,常用做分页,返回商和余数组成一个元组 pow(x,y[,z]) 取x的y次方 ,等同于x ...

  4. python函数(3):装饰器

    昨天学了很多函数方面的概念和知识其中有一个闭包的函数.很多人都对闭包的作用不是很清楚,今天我们就来认识一个新的知识点装饰器.它就是闭包函数的一个经典应用. 预习: 编写装饰器,为多个函数加上认证的功能 ...

  5. python装饰器小计

    1.装饰器:本质是函数,是用来给其他函数添加附加扩展功能的函数,其返回值是一个函数(函数指针) 2.装饰器作用:不改变函数源代码和函数调用方式的前提下添加函数的附加功能. 3.装饰器储备知识点: A. ...

  6. Python全栈开发之---装饰器

    1.装饰器的形成过程 import time def func1(): print('in func1') def timer(func): def inner(): start = time.tim ...

  7. python之装饰器函数

    本章内容 引入 装饰器的形成过程 开放封闭原则 谈装饰器主要功能和装饰器固定结构 带参数的装饰器 多个装饰器装饰一个函数 引入 作为一个会写函数的python开发,我们从今天开始要去公司上班了.写了一 ...

  8. Python小白学习之路(二十四)—【装饰器】

    装饰器 一.装饰器的本质 装饰器的本质就是函数,功能就是为其他函数添加附加功能. 利用装饰器给其他函数添加附加功能时的原则: 1.不能修改被修饰函数的源代码        2.不能修改被修饰函数的调用 ...

  9. python三大神器之装饰器

    装饰器的形成过程 假如你要写一个计算函数执行时间的函数,代码如下: import time def func1(): print('in func1') def timer(func): def in ...

随机推荐

  1. springboot+多数据源配置

    作者:纯洁的微笑 出处:http://www.ityouknow.com/ 起多数据源,一般都来解决那些问题呢,主从模式或者业务比较复杂需要连接不同的分库来支持业务.我们项目是后者的模式,网上找了很多 ...

  2. 使用MyBatis缓存

    (1).为什么需要使用缓存:: MyBatis是一个持久层(数据库层)映射框架,在所有访问数据库的操作中,无疑数据查询是最耗费数据库资源的操作了,因为你一次可能需要查询成千上百万条记录(如果你不加限制 ...

  3. 中文颜色名称与RGB颜色对照表

    中文颜色名称颜色对照表 鸨色 #f7acbc 赤白橡 #deab8a 油色 #817936 绀桔梗 #444693 踯躅色 #ef5b9c 肌色 #fedcbd 伽罗色 #7f7522 花色 #2b4 ...

  4. 转:Siri之父:语音交互或将主导未来十年发展

    http://zhinengjiaohu.juhangye.com/201709/weixin_5664458.html Siri之父Adam Cheyer认为,语音交互很可能是未来十年内计算技术的一 ...

  5. Who Will Win?

    Gautam and Subhash are two brothers. They are similar to each other in all respects except one. They ...

  6. mysql case when group by实例

    mysql 中类似php switch case 的语句. select xx字段, case 字段 when 条件1 then 值1 when 条件2 then 值2 else 其他值 END 别名 ...

  7. scrapy框架第一章

    操作环境:python2.7+scrapy 安装比较简单,网上教程也超多,就不在此赘述. 示例网站:https://www.cnblogs.com/cate/python/ (爬去关于博客园所有pyt ...

  8. 移动端IOS第三方输入法遮挡底部Input及android键盘回落留白问题

    var interval; //消息框获取焦点 $('#J_text').focus(function(){ interval = setInterval(function() { scrollToE ...

  9. css3特效样式库

    直接调用样式类即可: /* animation */ .a-bounce,.a-flip,.a-flash,.a-shake,.a-swing,.a-wobble,.a-ring{-webkit-an ...

  10. ValueError: too many values to unpack (expected 2)

    记录下总是码错的地方 for key,value in final_table:#final_table is a dict 然后报错 File "./count_co_Mty_read_n ...