Python入门到逆袭7(进阶篇1)

1. 函数

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段,简单来讲,函数就是一段可重复执行的代码逻辑。

1.1 函数示例

def test_func():
    '''
    这是一个测试函数
    :return:
    '''
    print('这是一个测试函数')
    return

解释 :

def 函数定义的关键词,函数必须以为def开头来定义。

test_func 函数名,可自行定义,一般约定为(简短、见名知意)

() 括号中用于定义参数,没有参数的时候,则为空

‘’’ ‘’’  函数的描述(好的函数先描述函数的功能,然后每个参数的格式和代表的意义和返回值)

接下来就是函数功能逻辑,自行编写对应的代码实现

return用户返回函数执行后返回的参数,没有返回值可以不带参数。

 

1.2 函数调用

函数调用处处见,低头不见抬头见。例如我们在之前基础篇中使用的系统库函数,print、os.system等函数,都是函数的调用,现在的区别只在于我们调用的是我们自己实现的函数,调用方法还是一样的。

下面,我们自定义一个函数和调用这个函数:

def save_cur_time():
    '''
    保存当前时间
    :return:
    '''
    localtime = time.localtime()
    str_time = time.strftime("%Y-%m-%d %H:%M:%S", localtime)

    fp = open('cur_time.txt', 'a+')
    fp.write(str_time)
    fp.write('\r\n')
    fp.close()

def main():
    '''
    主函数
    :return:
    '''
    save_cur_time()

if __name__ == '__main__':
   main()

解释:

main()   这里是第一个函数调用,跳转到main函数中执行代码

save_cur_time() 是第二个函数调用,跳转到save_cur_time函数中执行代码逻辑,保存当前的时间到文本中。

 

执行结果:

 

1.3 函数参数

  • 不可变类型参数

在 python 中,strings, tuples, 和 numbers 是不可更改的对象。

即使在函数中临时改变了参数的值,在函数执行结束后,参数的值还是原来的值。

例如:

def immutable_param(param):
    '''
    不可变类型参数函数
    :param param: 参数值 (int)
    :return:
    '''
    print('immutable_param param传入值为 : {}'.format(param))
    param = 10
    print('immutable_param param修改后的值为 : {}'.format(param))

param = 1
	immutable_param(param)
	print('函数结束后,param的值为: {}'.format(param))

结果:

immutable_param param传入值为 : 1

immutable_param param修改后的值为 : 10

函数结束后,param的值为: 1

 

  • 可变类型参数

在 python 中,list,dict 等则是可以修改的对象,如果在函数中临时改变了参数的值,在函数执行结束后,参数的值就被永久的改变了。

例如:

def mutable_param(param):
    '''
    可变类型参数函数

    :param param: 参数值 (dict)
    :return:
    '''

    print('mutable_param param传入值为 : {}'.format(param))
    del param['1key']
    param['10key'] = '10value'
    print('mutable_param param修改后的值为 : {}'.format(param))


param = {'1key': '1value', '2key': '2value'}
mutable_param(param)
print('函数结束后,param的值为: {}'.format(param))

结果:

mutable_param param传入值为 : {'1key': '1value', '2key': '2value'}

mutable_param param修改后的值为 : {'2key': '2value', '10key': '10value'}

函数结束后,param的值为: {'2key': '2value', '10key': '10value'}

 

  • 默认参数

默认参数将会在函数的参数中设置一个默认值,当调用函数并且没有传递该参数的时候,则会默认给该参数设置默认值,并在函数的范围内生效。

例如:

def default_param(param1, param2 = 10):
    '''
    默认参数函数
    :param param1: 参数1
    :param param2: 默认参数,默认值为10
    :return:
    '''

    print('default_param param1:{}  param2:{}'.format(param1, param2))


default_param(1, 2)
default_param(1)

 

结果:

default_param param1:1  param2:2

default_param param1:1  param2:10

 

  • 不定长参数

不定长参数函数,在我们一开始的时候就遇到了,例如神奇的main,再例如,神奇的print函数,例如print后面可以有一个参数,两个参数.....N个参数,这里我们就类似实现一个看一下,就容易理解了。

例如:

def variable_param(param1, *kwarg):
    '''
    可变参数函数
    :param param1: 参数1
    :param kwarg:  可变参数
    :return:
    '''

    print('variable_param param1:{}'.format(param1))
    for var in kwarg:
        print('variable_param kwarg:{}'.format(var))


variable_param(10, 20,  30)
variable_param(10, 20, 30, 40, 50)

 

结果:

variable_param param1:10

variable_param kwarg:20

variable_param kwarg:30

 

variable_param param1:10

variable_param kwarg:20

variable_param kwarg:30

variable_param kwarg:40

variable_param kwarg:50

 

  • 参数题外话 : (一般项目团队都会做的一些约束)
  1. 参数默认不超过5个(超过5个会进行压栈)
  2. 所有外部输入参数,都需要做参数类型、有效值校验

 

2. 装饰器

装饰器,理解起来,有点费力, 需要层层深入,如果看完之后没看懂,那就,在看一遍,还是不懂,多动手练习几次,其义自见。

 

2.1 万物皆对象

对象这个概念,是变相对象编程语言中的概念,如果对这个概念不太熟悉,可以先看下一章”类”这一块。

在编程语言中,除了int、string、dict等这项变量申明出来的是对象外,函数也是一个对象,函数名对应的就是一个函数地址。

例如:

def func_obj():
    '''
    函数对象测试函数
    :return:
    '''

    print('这是一个函数')

print('func_obj函数对象: {}'.format(func_obj))

结果:

func_obj函数对象: <function func_obj at 0x7f9b6143f578>

 

解释:

func_obj函数本身也是一个对象,存储在内存中的地址为0x7f9b6143f578。

 

接上面示例:

func_obj()
func_test = func_obj
func_test()

 

结果:

这是一个函数

这是一个函数

 

解释:

func_obj() :正常的函数调用

func_test = func_obj : 将函数地址复制给func_test,这个和C里面的函数指针是一样的

func_test() : 执行函数func_obj

 

参考代码 :

https://github.com/minlixia/python (advanced/01_func.py)

 

2. 装饰器

装饰器,理解起来,有点费力, 需要层层深入,如果看完之后没看懂,那就,在看一遍,还是不懂,多动手练习几次,其义自见。

可能下面前几个章节关联性并不是那么强,可以单独来理解,但是每个小章节优势必须要了解的,因为最后完整的理解装饰器的时候,需要这些小章节知识的结合汇总理解。

2.1 万物皆对象

对象这个概念,是变相对象编程语言中的概念,如果对这个概念不太熟悉,可以先看下一章”类”这一块。

在编程语言中,除了int、string、dict等这项变量申明出来的是对象外,函数也是一个对象,函数名对应的就是一个函数地址。

例如:

def func_obj():
    '''
    函数对象测试函数
    :return:
    '''

    print('这是一个函数')

print('func_obj函数对象: {}'.format(func_obj))

结果:

func_obj函数对象: <function func_obj at 0x7f9b6143f578>

解释:

func_obj函数本身也是一个对象,存储在内存中的地址为0x7f9b6143f578。

 

接上面示例:

func_obj()
func_test = func_obj
func_test()

 

结果:

这是一个函数

这是一个函数

 

解释:

func_obj() :正常的函数调用

func_test = func_obj : 将函数地址复制给func_test,这个和C里面的函数指针是一样的

func_test() : 执行函数func_obj

 

2.2 函数中的函数(子函数)

顾名思义,函数的中的函数,即使在函数中再定义一个子函数,子函数的有效范围只在当前函数内。

例如:

def internal_func():
    '''
    子函数示例函数
    :return:
    '''

    print('子函数示例')

    def hello():
        print('this is hello function')

    def test():
        print('this is test funcion')

    hello()


internal_func()

结果:

子函数示例

this is hello function

 

解释:

def hello(): 在函数internal_func中定义一个子函数, 只能在internal_func 函数内部中被调用。

虽然还定义了test函数,但是没有调用,就不会执行test函数中的代码。

 

2.3 将函数作为参数传递给另外一个函数

既然万物接对象,那函数对象也可以作为参数传递给另外一个函数。

例如:

def func_param_func(func_param):
    '''
    执行func_param对应的参数
    :param func_param: 函数对象
    :return:
    '''

    print('执行{}函数'.format(func_param))
    func_param()

func_param_func(func_obj)

结果:

执行<function func_obj at 0x7f9d1c527578>函数

这是一个函数

 

解释:

func_param() : 其实这行代码和上面”万物皆对象”里面的示例代码一样

func_obj()
func_test = func_obj
func_test()

 

2.4 装饰器函数

有了上面的知识储备后,我们可以开始写一个装饰器了,装饰器其实和”将函数作为参数传递给另外一个函数”原理是一样的。

示例:

def func_trace(func):
    '''
    装饰器函数,用于func函数名
    :param func: 函数对象
    :return:
    '''

    def wrapper(*args, **kwargs):
        print('[func_trace]: enter {}()'.format(func.__name__))
        return func(*args, **kwargs)

    return wrapper

@func_trace
def add_func(a, b):
    '''
    整数相加
    :param a:
    :param b:
    :return:
    '''
    sum = a + b
    return sum



sum = add_func(1, 2)
print('add_func(1, 2) = {}'.format(sum))

 

结果:

[func_trace]: enter add_func()

add_func(1, 2) = 3

 

解释:

def func_trace(func) : 定义一个装饰器函数, func为函数对象

def wrapper(*args, **kwargs): 包装器,args、kwargs是func函数的参数。

接下来时装饰器函数自己的逻辑代码

return func(*args, **kwargs) : 执行func函数。

 

@func_trace

def add_func(a, b):

定义了一个add_func函数,@func_trace为装饰器,@func_trace相当于:

func_trace(add_func)

wrapper中的args = (1,2)

所以,return func(*args, **kwargs)就变成了:

return add(1,2)

 

2.5 装饰器类

装饰器类和装饰器函数实现的效果差不多是一样的,但是类相对于函数来说能够更加内聚,在类的内部能够实现对应的成员函数和成员变量。

为了将装饰器定义成一个实例,你需要确保它实现了 __call__() 和 __get__() 方法。 例如,下面的代码定义了一个类,它在其他函数上放置一个简单的记录层。

例如:

class Decorate(object):
    '''

    '''

    def __init__(self):
        '''
        初始化
        '''
        print('Decorate init')


    def __call__(self,  func):
        '''
        :param func:
        :return:
        '''

        def wrapper(*args, **kwargs):
            print('[Decorate]: enter {}()'.format(func.__name__))
            return func(*args, **kwargs)

        return wrapper


@Decorate()
def sub_func(a, b):
    '''
    a - b
    :param a:
    :param b:
    :return:
    '''
    return a - b



sum = sub_func(10, 2)
print('sub_func(10, 2) = {}'.format(sum))

 

结果:

[Decorate]: enter sub_func()

sub_func(10, 2) = 8

 

参考代码 :

https://github.com/minlixia/python (advanced/02_decorator.py)

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaxiadeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值