Python高级语法

本文介绍了Python的高级特性,包括GIL、深拷贝与浅拷贝的区别、私有化、import导入模块、多继承和MRO顺序、类与实例的区别、property属性的使用、名字重整、魔法属性以及with语句和上下文管理器的作用。对于多线程性能,Python通过GIL在IO密集型任务中有所提升,而在计算密集型任务中推荐使用多进程。同时,文章还探讨了复制行为、私有变量的访问限制以及模块导入的细节。
摘要由CSDN通过智能技术生成

GIL(全局解释器锁)

  • Python语言和GIL没有半毛钱关系。仅仅是由于历史原因在Cpython虚拟机(解释器),难以移除GIL。
  • GIL:全局解释锁。每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码。
  • 线程释放GIL锁的情况:在IO操作等可能会引起阻塞的system call之前。可以暂时释放GIL,但在执行完毕后,必须重新获取GIL Python 3.x使用计时器(执行时间达到阈值后,当前线程释放GIL)或Python 2.x,tickets计数达到100
  • Python哦使用多进程是可以利用多核的CPU资源的。
  • 多线程爬取比单线程性能有提升,因为遇到IO阻塞会自动释放GIL锁

计算密集型:多进程

IO密集型:多线程、协程

想要解决GIL问题:可以换解释器,或者用其他语言来解析


深拷贝、浅拷贝

a = [11,22]
b = a

复制的并不是[11,22]这个列表,而是复制a指向该列表的引用,这仅仅是指向

通过import copy,调用deepcopy函数,如c = copy.deepcopy(a),拷贝的是列表,而不是引用,这是深拷贝

使用copy.copy()复制的是一个新的内容,但里面具体的内容是复制的引用,这就是浅拷贝,复制的内容一成不变,这是浅拷贝;使用copy.deepcopy()是在一个新的空间里复制一遍,而不是引用,这是深拷贝。

如果copy.copy拷贝的是元组,那么它不会进行浅拷贝,仅仅是指向。原因:因为元组是不可变类型,那么意味着数据一定不能修改,因此用copy.copy的时候它会自动判断,如果是元组它就是指向了它

如果用copy.copy、copy.deepcopy对一个全部都是不可变类型的数据进行拷贝,那么它们结果相同,都是引用指向。如果拷贝的是一个拥有可变类型的数据,即使元组为最顶层,那么deepcopy依然是深拷贝而copy.copy还是指向


私有化

  • xx:公有变量
  • _x:单前置下划线,私有化属性或方法,from somemodule import * 禁止导入,类对象和子类可以访问
  • __xx:双前置下划线,避免与子类中的属性命名冲突,无法在外部直接访问(名字重整所以访问不到)
  • __xx__:双前后下划线,用户名字空间的魔法对象或属性。例如:__init__, __不要自己发明这样的名字
  • xx_:单后置下划线,用于避免与Python关键词的冲突

通过name mangling(名字重整(目的就是以防子类意外重写基类的方法或者属性)如:_Class__object)机制就可以访问private了。


import导入模块

from xxx import yyy、
import xxx
from xxx import *
import xxx,zzz
from xxx import yyy,mmm
import xxx as XXX(重命名 )
from imp import reload
reold(xxx)重新加载模块 

多继承以及MRO顺序

多继承时使用super时调用父类方法是按照mro顺序,Grandon.__mro__是一个存有mro数据的元组,而super()也可以指定调用的父类方法

参数 * 和 ** 传参时如果有多余的参数,* 表示多余的一般参数会保存在一个元组里,** 表示带键值对的多余参数将会保存在一个字典里


类对象、实例对象、类方法、实例方法、类属性、实例属性、静态方法

类对象相当于模板,而实例对象相当于类对象实例化

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

  • 实例方法:由对象调用;至少一个self参数;执行实例方法时,自动将调用该方法的对象赋值给self;
  • 静态方法:由类调用;无默认参数;

property属性

property是一种用起来像是使用的实例属性一样的特殊属性,可以对应于某个方法,它在调用时并不是调用函数,而是直接调用返回值

创建property属性的方式

property属性有两种方式

  • 装饰器 即:在方法上应用装饰器
  • 类属性 即:在类中定义值为property对象的类属性

装饰器方式

在类的实例方法上应用@property装饰器

Python中的类有经典类和新式类,新式类的属性比经典类的属性丰富。(如果)类继object,那么该类是新式类

新式类三种使用property装饰器

@property
def price(self, value):
    print("@property")
@price.setter
def price(self, value):
    print("@price.setter")
@price.deleter
def price(self)
    print("@price,deleter")

通过类属性创建property属性

class Foo:
    def get_bar(self):
        return "laowang" 
        
    BAR = property(get_bar)
    
    
obj = Foo()
result = obj.BAR  # 自动调用get_bar方法,并获取方法的返回值
print(result)

名字重整

私有属性的原因,Python中为了找不到私有的属性,把名字改了,造成了这种假象,可以通过调用__dict__来查看重整后的名字,
规律是在私有名字前加上类名加上单下划线

魔法属性

无论人或事物往往都有不按套路出牌的情况,Python的类属性也是如此,存在着一些具有特殊含义的属性,详情如下:

1.__doc__

  • 表示类的描述信息
clas FOO:
    """ 描述类信息,这是用于看片的神器 """
    def func(self):
        pass
        
        
print(Foo.__doc_\_\)
#输出:类的描述信息

2.__module__和__class__

  • __module__ 表示当前操作的对象在那个模块
  • __class__ 表示当前操作的对象的类是什么
test.py
# -*- coding:utf-8 -*-


class Person(object):
    def __init__(self):
        self.name = "laowang"
main.py
from test import Person


obj = Person()
print(obj.__module__)  # 输出 test 即: 输出模块
print(obj.__class__)  # 输出 test.Person 即:输出类

3.__init__

  • 初始化方法,通过类创建对象时,自行触发执行
class Persom:
    def __init__(self,name):
        self.name = name
        self.age = 18
        
        
obj = Person("laowang")  # 自动执行类中的__init__方法

6.__del__

  • 当对象在北村中被释放时,自动触发执行。

注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,__del__的调用是由解释器在进行垃圾回收时自动触发执行的。

class Foo:
    def __del__(self):
        pass

5.__call__

  • 对象后面加括号,触发执行。

注:__init__方法的执行是由创建对象触发的,即:对象 = 类名();而对于__call__方法的执行是由对象后加括号触发的,即:对象()或者类()()

class Foo:
    def __init__(self):
        pass
        
    def __call__(self, *args ,**kwargs):
    print("__call__")

with与上下文管理器

普通版:

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

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

进阶版:

def m2():
    f = oper("output.text", "w")
    try:
        f.write("python之禅")
    except IOError:
        print("oops error")
    finally:
        f.close

上下文管理器

任何实现了__enter__()和__exit__()方法的对象都可以称之为上下文管理器,上下文管理器对象可以使用with关键字,显然,文件(file)对象也实现了上下文管理器。

那么文件对象是如何实现这两个方法的呢?我们可以模拟实现一个自己的文件夹,让该类实现__enter__()和__exit__()方法。

class File():
    
    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode
    
    
    def __enter__(self):
        print("entering")
        self.f = open(self.filename, self.mode)
        return self.f
        
        
    def __exit__(self, *args):
        print("will exit")
        self.f.close()

enter()方法返回资源对象,这里就是你将要打开的那个文件对象,exit()方法处理一些清理工作。因为File类实现了上下文管理器,现在就可以使用with语句了

with File("out.txt", "w") as f:
    print("writing")
    f.write("hello, python")

这样,你就无需显示地调用close方法了,由系统自动去调用,哪怕中间遇到异常close方法也会被调用。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值