python提高

python提高

GIL(全局解释器锁)

  • 首先,Python 和 GIL 没有半毛钱关系,仅仅只是Cpython(解释器)中难以移除GIL。
  • GIL 只对线程有影响,每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码,所以一个程序是多线程,一定是假的多任务。
  • Python使用多进程是可以利用多核的CPU资源的

计算密集型:进程(因为不需要等待,线程的话效率不高)

io密集型:线程、协程(有等待,在等待时可做其它事)

  • 解决GIL的问题

①是可以换一个解释器,因为GIL是cpython解释器所存在的问题

②可以换一种语言写多线程,Python作为胶水语言,可调用多门语言来用


拷贝(浅和深)

浅拷贝
  • copy模块中的copy()方法可完成浅拷贝
  • 如果把 a = b算入拷贝的话,它就是浅拷贝,只是把 b 标签指向 指向 a的数据空间,并不是拷贝了a里面的数据
  • 如果数据有多层,就只会复制 最顶层 的那个列表,即指定拷贝哪一层就只拷贝那一层,里面的数据不会拷贝

  • 浅拷贝无法拷贝不可变数据类型,仅仅是指向(不可变类型无法修改,拷贝无意义)
深拷贝
  • copy 模块中的 deepcopy() 方法可完成深拷贝
  • 会拷贝所有层次

import导入模块

  • 在一存储全局变量的模块,在主程序导入时,要用

    import 模块名
    

    不要用

    from 模块名 import 变量名
    

    前者导入后,可以用 模块名.变量名 修改全局变量,后者导入后,用变量名=**修改时,实则是定义的一个新的局部变量,无法修改更新全局变量

  • 模块被导入后,重新导入模块不能用 import 模块名 需用 reload重新导入

from imp import reload
reload(模块名)

多继承及MRO顺序

  • 在Python中,所有的 函数名方法名 实际都只是 变量名
在多继承中调用父类被重写的方法:
  • 父类名.方法名(self, name)

    • 注:需传递参数 self

    问题:

    如图:有四个类,其中继承关系如图,四类中都有同一个方法,即各自重写了父类的方法,并在各自里面用 ① 方式调用各自父类的被重写的方法,而最后的 结果Parent 类里的方法被调用了两次,这就多余了,如果该方法是启动线程之类的,这就非常的浪费资源

  • super.方法名(name, *args, **kwargs)

    • 注:super 不需要传递 self

    • super 不只是简单的调用父类的方法,它的调用顺序是由 C3算法 来决定的,如若想查看其顺序,可用 __mro__ 来查看

      print(Grandson.__mro__)
      
      # ####查看结果#####
      (<class '__main__.Grandson'>, <class '__main__.Son1'>, <class '__main__.Son2'>, <class '__main__.Parent'>, <class 'object'>)
      

      这就是 C3算法 算出来的调用顺序

  • ③ super(类名, self).方法名(xxx, xxx)

    • 这中方式是指定要调用的类名,实则它是拿着这个类名去上面的 MRO 顺序表中去找
小试牛刀:
class Parent(object):
    x = 1

class Child1(Parent):
    pass

class Child2(Parent):
    pass

print(Parent.x, Child1.x, Child2.x)
Child1.x = 2
print(Parent.x, Child1.x, Child2.x)
Parent.x = 3
print(Parent.x, Child1.x, Child2.x)

结果

1 1 1
1 2 1
3 2 3

使你困惑或是惊奇的是关于最后一行的输出是 3 2 3 而不是 3 2 1。为什么改变了 Parent.x 的值还会改变 Child2.x 的值,但是同时 Child1.x 值却没有改变?

这个答案的关键是,在 Python 中,类变量在内部是作为字典处理的。如果一个变量的名字没有在当前类的字典中发现,将搜索祖先类(比如父类)直到被引用的变量名被找到(如果这个被引用的变量名既没有在自己所在的类又没有在祖先类中找到,会引发一个 AttributeError 异常 )。

因此,在父类中设置 x = 1 会使得类变量 x 在引用该类和其任何子类中的值为 1。这就是因为第一个 print 语句的输出是 1 1 1。

随后,如果任何它的子类重写了该值(例如,我们执行语句 Child1.x = 2),然后,该值仅仅在子类中被改变。这就是为什么第二个 print 语句的输出是 1 2 1。

最后,如果该值在父类中被改变(例如,我们执行语句 Parent.x = 3),这个改变会影响到任何未重写该值的子类当中的值(在这个示例中被影响的子类是 Child2)。这就是为什么第三个 print 输出是 3 2 3。

不定长参数
  • 为避免多继承报错,使用不定长参数,接受参数
  • *args =====> 元组
  • **kwargs =====> 字典
  • 不定长参数不仅可当作形参,也可以当作当作实参进行传递,当然传递时要加上 * 号,不然,传递时只填 (a, args, kwargs) 的话,args 和 kwargs 会被当作一个元组传递

类里面的方法

  • 方法包括:实例方法静态方法类方法,三种方法在内存中都归属于类,区别在于调用方式不同。

  • 实例方法:由对象调用,至少一个 self 参数

    def test1(self):
        pass
    
  • 类方法:由类调用,至少一个 cls 参数

    @classmethod
    def test2(cls):
        pass
    
  • 静态方法:由类调用,无需参数

    @staticmethod
    def test3():
        pass
    
    

property属性

  • 一种用起来像是使用的实例属性一样的特殊属性,可以对应于某个方法

    # ############### 定义 ###############
    class Foo:
        def func(self):
            pass
    
        # 定义property属性
        @property
        def prop(self):
            pass
    
    # ############### 调用 ###############
    foo_obj = Foo()
    foo_obj.func()  # 调用实例方法
    foo_obj.prop  # 调用property属性
    
    

    注:调用不需要用 ()

  • Python的property属性的功能是:property属性内部进行一系列的逻辑计算,最终将计算结果返回。

  • python2 经典类 只有上面这一种 property属性,而 python3 新式类 除了上面这种还有其它的两种 property 属性

    # ############### 定义 ###############
    class Goods:
        """python3中默认继承object类
            以python2、3执行此程序的结果不同,因为只有在python3中才有@xxx.setter  @xxx.deleter
        """
        @property
        def price(self):
            print('@property')
    
        @price.setter    # 修改
        def price(self, value):
            print('@price.setter')
    
        @price.deleter  # 删除
        def price(self):
            print('@price.deleter')
    
    # ############### 调用 ###############
    obj = Goods()
    obj.price          # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
    obj.price = 123    # 自动执行 @price.setter 修饰的 price 方法,并将  123 赋值给方法的参数
    del obj.price      # 自动执行 @price.deleter 修饰的 price 方法
    
    
类属性方式,创建值为property对象的类属性
  • 当使用 类属性 的方式创建 property 属性时,经典类新式类 无区别,即 Python2Python3 都可以这样创建

    class Foo:
        def get_bar(self):
            return 'laowang'
    
        BAR = property(get_bar)  # 看这里!!
    
    obj = Foo()
    reuslt = obj.BAR  # 自动调用get_bar方法,并获取方法的返回值
    print(reuslt)
    
    
  • property 方法中有个四个参数 (一般第一二个参数用得多)

    • 第一个参数是方法名,调用 对象.属性 时自动触发执行方法
    • 第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法
    • 第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法
    • 第四个参数是字符串,调用 对象.属性.doc ,此参数是该属性的描述信息
    class Foo(object):
        def get_bar(self):
            print("getter...")
            return 'laowang'
    
        def set_bar(self, value): 
            """必须两个参数"""
            print("setter...")
            return 'set value' + value
    
        def del_bar(self):
            print("deleter...")
            return 'laowang'
    
        BAR = property(get_bar, set_bar, del_bar, "description...")  # #####
    
    obj = Foo()
    
    obj.BAR  # 自动调用第一个参数中定义的方法:get_bar
    obj.BAR = "alex"  # 自动调用第二个参数中定义的方法:set_bar方法,并将“alex”当作参数传入
    desc = Foo.BAR.__doc__  # 自动获取第四个参数中设置的值:description...
    print(desc)
    del obj.BAR  # 自动调用第三个参数中定义的方法:del_bar方法
    
    
    property 属性例题
    class Goods(object):
    
        def __init__(self):
            # 原价
            self.original_price = 100
            # 折扣
            self.discount = 0.8
    
        def get_price(self):
            # 实际价格 = 原价 * 折扣
            new_price = self.original_price * self.discount
            return new_price
    
        def set_price(self, value):
            self.original_price = value
    
        def del_price(self):
            del self.original_price
    
        PRICE = property(get_price, set_price, del_price, '价格属性描述...')
    
    obj = Goods()
    obj.PRICE         # 获取商品价格
    obj.PRICE = 200   # 修改商品原价
    del obj.PRICE     # 删除商品原价
    
    

with 打开文件

def m1():
    f = open("output.txt", "w")
    f.write("python之禅")
    f.close()

这样写有一个潜在的问题,如果在调用 write 的过程中,出现了异常进而导致后续代码无法继续执行,close 方法无法被正常调用,因此资源就会一直被该程序占用者释放

  • with 打开文件

    def m3():
        with open("output.txt", "r") as f:
            f.write("Python之禅")
    
    

这种方式是不是更加的简洁

open 方法的返回值赋值给变量 f,当离开 with 代码块的时候,系统会自动调用 f.close() 方法, with 的作用和使用 try / finally 语句是一样的

END…

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值