1. 内容
本文旨在介绍Python的学习思维,不必局限于文中将要介绍的函数,装饰器等概念。
文中环境为 python3, ipython中运行
2. 要求
要求已了解Python基本语法,基本数据结构和内置函数,广告
3. 废话
本人技术有限,敬请指教。
喜欢逛影视推荐区,发现权限不够了,故有此文。
坛友给仨热心,就要仨!
4. 函数
函数是什么
函数使用来封装代码的,再通俗点,一个函数就是一个功能。
怎么创建函数
格式
def 函数名([参数1, ...):
"""使用说明
"""
函数体(代码写在这里)
[return 返回值]
来做下解释:
- 方括号表示可选
- 函数名与变量名定义要求一致,字母,数字,下划线,(允许中文,但不建议),需以下划线或字母开头哦
- 使用说明是可选的
- return语句是用来返回函数这个功能的结果,(程序是专门用来计算和处理东西的,所以返回值就是功能的计算结果或处理结果)
好,让我们步入正题
1. 无参函数
我们先来举第一个例子,函数功能为 获取一个有8个0的列表
先来看看不用函数时的实现与使用:生成与打印
lst8_1 = [0, ] * 8 # 第一行有8个0
print(lst5_1)
我们要使用函数了
def create_lst8():
"""生成5个0的列表
"""
lst8_1 = [0, ] * 8
return lst8_1
lst8_1 = create_lst8()
print(lst8_1)
这么一看,使用函数貌似更麻烦了,请耐心看下去
2. 有参函数及默认参数
需求变了,我们想要有10个或更多个的数字0列表怎么办,第一种没有使用函数的实现就会很麻烦,我们来看函数的实现
def create_lst(n):
"""n可指定列数
"""
lst = [0, ] * n # 注意此处列表乘法的限制,n必须为整数,否则会异常的哟,请自行学习异常处理
return lst
lst = create_lst8(8)
print(lst)
可以看到,如果我们不使用函数也是可以的,把函数体内代码拿出来,n改为你想要的列数。
但是,函数的另一个作用就是 复用,也就是这个函数我们可以在任意声明它的位置使用,只要其参数n改变,就可以获取到相应的列表,而不使用函数,你就需要再写一遍。嗯~有点啰嗦了。
参数可以有多个,并且可以有默认参数
def create_lst(tmp, n=8):
"""n可指定个数
"""
print(tmp) # tmp是我用来帮大家理解函数参数格式的,没有作用
lst = [0, ] * n
return lst
lst = create_lst(1000) # 存在默认参数的情况下,我们可以省略有默认值的n参数,而tmp没有默认值,所以必须要传值
print(lst)
有多个参数时定义函数,注意:
- 有默认值的参数需要定义在后面,比如 n=8 要写在 tmp 后
有多个参数时使用函数,注意:
- 不写参数名需要参数位置对应,比如上面的函数 create_lst(1000, 10), 在函数内 tmp就是1000,n就是8
- 写参数名可以任意调整位置,比如上面的函数 create_lst(n=10, tmp=1000)
3. 可变参
大家可能见过这种形式的函数定义
def create_lst(*args, **kwargs):
"""
args 会接收所有没有写参数名的参数,以列表形式呈现
kwargs 会接收所写了参数名的参数,以字典形式呈现
"""
lst = [0, ] * kwargs['n']
return lst
lst = create_lst(1000, n=10) # 注意此时,在函数内部 args 为 [1000, ],kwargs 为 {'n': 10}
print(lst)
这种形式的函数定义要做好参数的判断,因为如果参数n没有作为函数参数,上述调用就会报错了。
多写代码理解哦
4. 拆箱(并非C#对象中的拆箱概念) - 函数调用的黑科技
Python 支持这种语法
a, b = 1, 2 # 赋值 a = 1, b = 2
a, b = [1, 2] # 赋值 a = 1, b = 2
a, *b = [1, 2, 3] # 我擦 a = 1, b = [2, 3],是不是跟3.可变参有点像
我们反过来,现在有个变量 vars_1 = [1000, 10]
就是tmp和n,怎么传给函数呢
create_lst(vars_1[0], vars_1[1]) # 没错,这是传统的写法
create_lst(*vars_1) # create_lst(vars_1[0], vars_1[1])
对于字典 vars_2 = {'tmp': 1000, 'n': 10}
create_lst(**vars_2) # 我擦!!create_lst(tmp=1000, n=10)
貌似有点绕,多写代码看看效果,告诉大家一个用来理解的笨方法,不知道是什么东西的变量就使用print输出一下
5. 返回值
注意:不写return,相当于在函数结束有个 return None
5. 装饰器
装饰器是个什么东东
一句话,Python中一切都是对象,通俗一点,装饰器可以用来扩展函数的功能
既然函数也是对象,那函数也可以作为函数的参数和返回值,如下
def call_func(func):
print('函数%s被调用了' % func.__name__)
return func # 此处原封不动的返回func函数
create_lst = call_func(create_lst) # 然而效果并不好,只是体现了 *函数可以作为参数和返回*
来看装饰器,create_lst函数不是要求n为整数吗,我们使用装饰器给这个函数加上数据验证功能
def arg_check(func):
"""arg_check就是装饰器
"""
def wraper(*args, **kwargs):
"""wraper是参数func函数的替代品
"""
n = kwargs.get('n) # 获取n的值,注意,我们从kwargs中获取n,就需要参数n以命名参数的形式传入
if not isinstance(n, int) or n<3:
print('警告:n取值无效,已设为默认值8')
n = 8 # 如果n不是整数或者n小于3,则将n设为默认8
ret = func(n=n) # 将已验证的参数传入我们的原始函数
return ret
return wraper # 装饰器返回包装函数wraper,大家可以自己理解一下调用时的运行流程
@arg_check # 使用装饰器定义函数
def create_lst(*args, **kwargs):
"""
args 会接收所有没有写参数名的参数,以列表形式呈现
kwargs 会接收所写了参数名的参数,以字典形式呈现
"""
lst = [0, ] * kwargs['n']
return lst
#create_lst = arg_check(create_lst) # 上面的定义相当于此句。理解一下,其实赋值符号左边的函数是包装函数wraper
create_lst(n=None) # 此时函数依然可运行,可以思考一下会返回什么
还会有有参装饰器,上面的装饰器已经将n的默认值固定为8,我们可以通过装饰设置n的默认值
def arg_check(func, n=8):
"""arg_check就是装饰器
"""
def wraper(*args, **kwargs):
"""wraper是参数func函数的替代品
"""
number = kwargs.get('n) # 防止作用域问题
if not isinstance(number, int) or number<3:
print('警告:n取值无效,已设为默认值8')
number = n # 如果n不是整数或者n小于3,则将n设为默认8
ret = func(n=number) # 将已验证的参数传入我们的原始函数
return ret
return wraper # 装饰器返回包装函数wraper,大家可以自己理解一下调用时的运行流程
@arg_check(n=10) # 使用装饰器定义函数,n的默认值为10
def create_lst(*args, **kwargs):
"""
args 会接收所有没有写参数名的参数,以列表形式呈现
kwargs 会接收所写了参数名的参数,以字典形式呈现
"""
lst = [0, ] * kwargs['n']
return lst
装饰器差不多就结束了
ps. 学习Python装饰器的同时,大家也可以了解一下闭包
6. 作用域
上面提到了作用域,函数作用域是指 函数内部定义的变量,在函数外是无效的
def func(n):
a = 0
上述函数,func作用域内有两个变量,n和a
- a在函数外是没有的,所以函数外部获取不到a的值
- n有点麻烦,涉及传入的对象还是值,也就是c语言中的传引用与传值,传值时对n的修改是不影响外部的,而传对象时对n进行修改,外部的传来的这个变量也会随之更改(有点绕)。基本数据类型好像都是传值形式(int, str, float, bool等),对象类型有tuple(不可更改哟),list,set,dict,以及类对象
再来看代码
a = 0
n = [1, 2, 3]
def func(a, n):
a = 1 # 这个是不影响函数外部的那个a的
print(a)
n[0] = 0 # 注意我们给n传递一个列表
print(n)
func(a, n) # 此时将函数外部的a, n传递到函数内部
print(a) # 0 # a是基本类型,使用值传递,不影响外部
print(n) # [0, 2, 3] # n是列表,使用引用传递,对n更改外部的值也改变
7. 内置函数
我们先用ipython来看看python的内置函数,不得不说,这些函数都能用到的
dir(__builtin__)
# ...略...
# 'abs', # 取绝对值
# 'all', # 可迭代对象内部元素是否全为True(不是布尔类型的进行转为bool)
# 'any', # 可迭代对象内部元素是否含有True
# 'ascii', # 返回参数的ascii码 ascii('中国') -> '\\u4e2d\\u56fd'
# ...略...
dir是一个内置函数,用来获取参数对象的属性,而builtin是python环境启动时就会导入的模块,内置函数都是在builtin中的。先理解到此处即可。
我们该如何了解怎么使用这些内置函数呢?是的,help!!!
help(abs) # help也是内置函数,help(abs)就是查看abs函数的帮助文档,篇幅有限,abs就是取绝对值函数,具体帮助请自行查看输出
先写这么多吧。