Python高阶技巧全解

1、闭包

1.1、为什么要使用闭包

一下代码是模拟ATM机器存取款的代码,咱们看下有什么问题

# 账户总余款
account_amount = 0


def atm(num, deposit=True):
    """
    ATM机器
    :param num: 存取款金额
    :param deposit: 是否是存款,默认true
    :return:
    """

    global account_amount
    if deposit:
        account_amount += num
        print(f"存款:{num},账户余额:{account_amount}")
    else:
        account_amount -= num
        print(f"取款:{num},账户余额:{account_amount}")


if __name__ == '__main__':
    # 存款
    atm(300)
    # 存款
    atm(300)
    # 取款款
    atm(100, False)

总结:

通过全局变量account_amount记录账户余款,尽管功能实现没有问题,但是存在一下问题

①、代码在命名空间上不够干净(变量定义)、整洁

②、全局变量有被修改的风险

由于存在以上两个问题,我们需要使用到闭包

1.2、使用闭包

我们将1.1代码改造如下:

def account_create(init_amount=0):
    def atm(num, deposit=True):
        # 注意:需要使用nonlocal 关键字修饰外部函数的变量,才可以在内部函数中修改它
        nonlocal init_amount
        """
        ATM机器
        :param num: 存取款金额
        :param deposit: 是否是存款,默认true
        :return:
        """

        if deposit:
            init_amount += num
            print(f"存款:{num},账户余额:{init_amount}")
        else:
            init_amount -= num
            print(f"取款:{num},账户余额:{init_amount}")

    return atm


if __name__ == '__main__':
    fn = account_create(0)
    fn(300)
    fn(200)
    fn(100, False)

在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包。

1.3、简单闭包

def outer(logo):
    def inner(msg):
        print(f"{logo}:{msg}")

    return inner


if __name__ == '__main__':
    fn1 = outer("张三")
    fn1("大家好")

    fn2 = outer("李四")
    fn2("hello,大家好")

1.4、闭包的注意点

  • 优点:

无需定义全局变量即可实现通过函数,持续的访问、修改某个值

闭包使用的变量的所用于在函数内,难以被错误的调用修改

  • 缺点:

由于内部函数持续引用外部函数的值,所以会导致这一部分内存空间不被释放,一直占用内存

2、装饰器

装饰器其实也是一种闭包, 其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。

def outer(func):
    def inner():
        print("我要睡觉了")
        func()
        print("我起床了")

    return inner


"""
    这里要增加 @外部的方法名
"""


@outer
def sleep():
    import random
    import time
    print("睡眠中....")
    time.sleep(random.randint(1, 3))


if __name__ == '__main__':
    sleep()

3、单例模式

单例模式需要通过两个文件实现

定义test_10.py 文件,内容如下

class StrTools:
    pass


str_tools = StrTools()

定义test_11.py文件,内容如下

from test_10 import str_tools

if __name__ == '__main__':
    s1 = str_tools
    s2 = str_tools
    # 如果打印的s1和s2内存地址一致,则说明单例成功
    print(s1)
    print(s2)

4、工厂模式

"""
定义人类
"""


class Person:

    def introduce(self):
        """
        自我介绍
        :return:
        """
        pass


"""
定义工人,继承至Person
"""


class Worker(Person):
    def introduce(self):
        """
        自我介绍
        :return:
        """
        print("我是工人")


"""
定义学生
"""


class Student(Person):
    def introduce(self):
        """
        自我介绍
        :return:
        """
        print("我是学生")


"""
定义教师
"""


class Teacher(Person):
    def introduce(self):
        """
        自我介绍
        :return:
        """
        print("我是教师")


"""
定义工厂类
"""


class Factory:
    def create_person(self, p_type) -> Person:
        """
        创建人类
        :param p_type: 类型
        :return:
        """
        if p_type == 'w':
            return Worker()
        elif p_type == 's':
            return Student()
        else:
            return Teacher()
        return None


if __name__ == '__main__':
    f = Factory()
    w = f.create_person("w")
    s = f.create_person("s")
    t = f.create_person("t")
    w.introduce()
    s.introduce()
    t.introduce()

5、多线程编程

绝大多数编程语言,都允许多线程编程,Pyhton也不例外。

Python的多线程可以通过threading模块来实现。

5.1、实例

import threading
import time


def sing(arg):
    """
    定义唱歌方法,无限循环
    :return:
    """
    while True:
        print(arg)
        time.sleep(1)


def dance(arg):
    """
    跳舞,无限循环
    :return:
    """
    while True:
        print(arg)
        time.sleep(1)


if __name__ == '__main__':
    # 注意这里,target=函数名称,不能加小括号,否则线程无效 
    sing_thread = threading.Thread(target=sing, args=("我在唱歌",))
    dance_thread = threading.Thread(target=dance, args=("我在跳舞",))
    sing_thread.start()
    dance_thread.start()

猜你喜欢

转载自blog.csdn.net/u011837804/article/details/129627743