首页 > 编程语言 > 详细

Python语法进阶

时间:2021-09-13 18:52:45      阅读:27      评论:0      收藏:0      [点我收藏+]

Python进阶

一、装饰器

1. 包的概念及基本使用

  • 闭包的概念:在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
  • 闭包构成的条件:
    • 存在函数的嵌套关系
    • 内层函数引用了外层函数的临时变量
    • 外层函数返回内层函数的引用(地址)

2. 闭包中变量问题

  • 内层定义了和外层同名的变量

    内层优先使用内层定义的变量,即是定义的变量的代码在内层的最后面

  • 解决办法:当内层存在和外层同名变量,而且内层需要使用外层定义的变量,此时应该使用

    nonlocal 关键字进行约束

3. 装饰器入门

  • 装饰器的作用:不修改源代码的基础上,给函数增加新的功能

  • 装饰器使用:

    1. 存在闭包

    2)需要装饰的函数

  • 写法:

    @闭包的外层函数名

    def 待装饰的函数():

4. 【应用】装饰有参数的函数

  • 普通参数

    待装饰

    @functioin_out

    def login(num):

    注意:

    1)function_in(参数)

    2)func(参数)

  • 可变参数

    待装饰

    @functioin_out

    def login(*args, **kwargs):

    注意:

    1)function_in(*args, **kwargs)

    2)func(*args, **kwargs)

    错误用法:

    func(args,kwargs)

5. 【应用】装饰有返回值的函数

  • 步骤
    • 待装饰的函数必须有返回值(return)
    • 闭包的内层函数 func(*args,**kwargs) 改为 return func(*args,**kwargs)

6. 在原装饰器上设置外部变量

  • 作用:向装饰器内部传递参数

  • 格式:

    def test(path):
       def function_out(func):
       	  def function_in():
       	     ....
       	  return function_in
       return function_out
    
  • 使用:

    @test("login.py")

    1. test(login.py) ---> function_out

    2. @ 第一步的结果 ——> @ founction_out

7. 多重装饰器

  • 多重装饰器:给一个函数进行多次装饰
  • 装饰原则:就近原则(靠近待装饰函数的先装饰,随后一层一层装饰)

8. 类装饰器

  • 作用:使用一个类为一个函数装饰

  • 类的书写:

    必须有两个方法

    1. init 方法,必须接收 装饰器传递的参数 func

    2)call方法, self.func()

    # 装饰器类
    class Test(object):
    
        def __init__(self,func):
            print("----init----方法")
            print("---func--", func)
            # func 是login函数的引用
            self.func = func
    
        def run(self):
            print("---正在疯跑---")
    
        def __call__(self, *args, **kwargs):
            print("----开始验证----")
            # 调用原来login的内容
            self.func()
    
  • 格式:@类名

          待装饰的函数
    

    @Test

    def login():

    login = Test(login)

    login() ---> 调用类的 __call__方法

  • 对象名() 调用对象的 __call__()

二、GIL

1. GIL锁引入

  • 监控资源的竞争情况 htop
  • 资源的消耗的情况
    • 单进程 1核
    • 多进程 多核
    • 多线程 多核但是很低 gil锁的问题

2. GIL概念及影响

  • Gil 全局解释器锁
  • GIL跟python语言没有关系,Python底层解释器Cpython的问题
  • GIL释放的情况
    • 线程执行完毕释放
    • I/O 阻塞的时候释放
    • Python 3.x使用计时器(执行时间达到阈值后,当前线程释放GIL)

3. GIL解决方案

  • 解决方案:
    • 更换解释器 Jpython pypy
    • 用进程替换线程(进程会占用更多的系统资源)
    • 子线程用C语言实现(test.c-->libtest.so-->python加载)

三、浅拷贝与深拷贝

1. python中可变和不可变

  • 可变类型(mutable),创建后可以继续修改对象的内容(值)

    字典、列表

  • 不可变类型(unmutable) ,一旦创建就不可修改的对象(值)

    数字, 字符串,元组

    当内容发生修改,计算机重新分配一块内存空间

2. 简单可变类型拷贝

  • 深拷贝:

    • 会产生新的空间
    • 能够保持各自的独立性
    • 如果拷贝的对象,子对象也会拷贝(产生新的空间)
  • 浅拷贝

    • 不会产生新的空间
    • 源对象和副本对象指向同一个空间
    • 如果拷贝的对象,子对象不会拷贝(不会产生新的空间)
  • 简单可变类型的拷贝总结:

    简单可变类型的数据不管深拷贝还是浅拷贝,都会产生新的空间,而且保持各自的独立性

3. 复杂可变类型拷贝

  • 复杂可变类型的深浅拷贝问题
    • 浅拷贝,拷贝的是顶层对象的值,子对象不会拷贝(只是引用子对象)
    • 深拷贝,拷贝的顶层对象和对象的子对象,子对象会产生新的内存空间

4. 简单不可变类型拷贝

  • 简单不可变类型
    • copy() 浅拷贝,副本和源指向同一个空间
    • deepcopy() 浅拷贝,副本和源指向同一个空间

5. 复杂不可变类型拷贝

  • 复杂不可变类型的拷贝问题
    • 浅拷贝, 直接引用
    • 深拷贝,看数据具体是可变还是不可变的,如果数据是可变的,会产生新的空间,保持数据的独立性

6. 切片拷贝、字典拷贝

  • 切片拷贝: 浅拷贝(如果是简单可变类型,底层会产生新的空间)
  • 字典拷贝: 浅拷贝

四、Import问题

1. import导入模块路径问题

  • 存在的问题:当我们把模块文件放到工程文件夹的外部的文件,发现无法正常引入模块

  • 原因: 外部的文件夹的路径,没有放到环境变量中

  • 查看环境变量

    1. 导入 sys模块
    2. sys.path 查看环境变量 返回值是列表
  • 把自己写的模块的路径加入到环境变量中

    • sys.path.append("自己的路径") # 加入环境变量的末位
    • sys.path.insert(0, "自己的路径") # 加入到环境变量的开头位置

2. import的reload加载问题

  • import 导入模块后,如果模块被修改,此时再次 import 不起作用

    import 自动防止重复包含

  • 强制重新加载一次模块

    reload() 函数

    1. from imp import reload
    2. reload(要重新加载的模块)

3. from...import的私有化问题

  • 私有化: 模块中的一些变量不希望被其他模块导入,可以使用私有化解决

  • 私有化使用的前提:必须使用 “ from xxx import * “

  • 用法: 在模块中,把变量前增加一个下划线 _变量名

  • 注意:如果使用其他的方式导入模块,私有化将无效

    from xxx import _私有变量

    print(_私有变量) 不会报错

4. import和from...import的区别

  • 区别
    • 写法:
      • import 模块名.变量/函数/类
      • from ... import * 变量名/函数/类
    • 底层的区别:
      • import 直接引用了源模块的 变量/函数/类
      • from ... import *  拷贝源模块的 变量/函数/类 到当前自己类

五、多继承的顺序

1. 可变参数的拆包问题

  • 可变参数 *args **kwargs 默认会封包过程
  • 如果想要这种单数继续传递到下一个函数,传递的时候 func(*args,**kwargs)

2. 单继承中super()

  • super() 使用的时候,传递参数的时候,self 不用传递

  • super() 调用顺序,按照 mro顺序来完成

    Grandson.__mro__ 是一个元组

    当在类中使用 super() 在 mro列表中找到当前类的下一个元素,调用该元素的方法

3. 多继承和MRO顺序

  • 多继承中 super() 执行顺序,严格执行 MRO顺序表

  • MRO顺序表:

    • 类名.mro()
    • 类名.__mro__
  • 注意:

    当在类中使用 super() 在 mro列表中找到当前类的下一个元素,调用该元素的方法

    多继承中,不建议使用类名 直接调用父类的方法

六、Property

1. property基本使用

  • @property 的特点: 让我们通过对象.方法名的方式可以调用方法

  • 语法格式:

    @proerty

    def xxx(self):

    ? pass

  • 注意:

    @property 装饰的方法,只能有一个参数self

2. property其他使用方式

  • 经典类: @property 一种方式

  • 新式类:

    • @property

      goods.price 获取价格的方法

    • @xxx.setter

      goods.price = xxx

    • @xxx.deleter

      del goods.price ---> @xxx.delete 装饰的方法

3. property作为类属性

  • 定义 property 对象的类属性

    xxx =property(参数1,参数2,参数3,参数4)

      第一个参数,当我们 foo.BAR 自动调用第一个参数的方法
      第二个参数,当我们 foo.BAR = 100,自动调用第二个参数的方法
      第三个参数,当我们 del foo.BAR ,自动调用第三个参数的方法
      第四个参数,当我们 Foo.BAR.__doc__,自动获取第四个参数的内容 
    
  • 使用

    • 对象.xxx 获取值
    • 对象.xxx = 100 设置值
    • del 对象.xxx 调用第三个参数方法
    • 类.xxx.__doc__ 获取第四个参数的内容

七、魔法属性和方法-1

  • 魔术属性

    • __doc__ 获取描述信息
      • 获取类的 类名.__doc__
      • 获取方法的描述 对象.方法名.__doc__
    • __module__ 获取所属的模块(对象名.__module__) 直接改文件 获取的__main__
    • __class__ 获取对象所属的类 对象名.__class__
  • 魔术方法

    • __init__ 初始化方法 类名() 自动调用
    • __del__ 删除对象的时候,会调用 del 对象
  • 魔术属性__dict__ 获取对象或者类的信息

    • 获取对象信息 对象名.__dict__对象的实例属性信息
    • 获取类的信息类名.__dict__ 模块、类描述、对象方法...
  • 魔术方法

    • __call__() 当使用 对象名() 会调用该方法
    • __str__() 打印对象的会调用 print(obj) str方法一定要return,而且return 一定字符串内容
    • 用字典的书写格式操作对象的方法
      • __getitem__ 对象[‘xxx‘]
      • __setitem__ 对象[‘xx‘] = xxx
      • __delitem__ del 对象[‘xx‘]

八、with管理上下文方式一

1. 上下文管理器

  • 上下文:以 with open 来说,打开文件在上文 关闭文件在下文

  • 上下文管理器:

    • __enter__ 上文方法
    • __exit__ 下文方法
  • 自定义一个满足满足上下文管理器的 类

    """
    类:  MyFile()
    类方法:
        1. __enter__()  上文方法
        2. __exit__()   下文方法
        3. __init__()   方法,接收参数并且初始化
    
    
    with MyFile(‘hello.txt‘, ‘r‘) as file:
        file.read()
    
    """
    
    
    class MyFile(object):
    
        # 1. __enter__()  上文方法
        def __enter__(self):
            print("进入上文....")
            # 1,打开文件
            self.file = open(self.file_name, self.file_model)
            # 2,返回打开的文件资源
            return self.file
    
        # 2. __exit__()   下文方法
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("进入下文....")
            # 关闭文件资源
            self.file.close()
    
        # 3. __init__()   方法,接收参数并且初始化
        def __init__(self, file_name, file_model):
            # 保存文件名和文件打开模式,到实例属性中
            self.file_name = file_name
            self.file_model = file_model
    
    
    if __name__ == ‘__main__‘:
    
        with MyFile("hello.txt", "r") as file:
            # 开始读取文件
            file_data = file.read()
            print(file_data)
    

2. 通过装饰器 @ contextmanager 实现上下文管理

  • 装饰器

  • 待装饰的函数

    myopen() 分拆成上文和下文,使用yield 分拆

    def myopen(file_name,file_model):
    
        print("进入上文")
        # 1.打开文件
        file = open(file_name,file_model)
        # 2.返回资源
        yield file
        print("进入下文")
        # 下文
        # 3. 关闭资源
        file.close()
    
  • 装饰的过程:

    • 导入模块 from contextlib import contextmanager

    • 第二步:

      @contextmanager
      def myopen(file_name,file_model):

      ...

Python语法进阶

原文:https://www.cnblogs.com/yangxuezhi/p/15260690.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!