GIL/copy/私有/面向对象

1. GIL

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

2. 深拷贝和浅拷贝

# 1. 引用

# 2. 浅拷贝
    # 浅拷贝是对于一个对象的顶层拷贝

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9,[10, 11, 12]]
print(id(a))  # 2201716937288
print(id(a[10]))  # 2829155127880

b = copy.copy(a)
print(b)
print(id(b))  # 2201716937800
print(id(b[10]))  # 2829155127880  # 只复制了顶层,引用底层,底层改变,浅拷贝得来的值也会跟着改变
                                   # [:]和copy.copy()一样属于浅拷贝
                                   # 若果浅拷贝一个字典,键是拷贝,值是引用

# 3. 深拷贝
    # 深拷贝是对于一个对象所有层次的拷贝(递归)
    # 不只是顶层的id改变,底层的id也改变
    # 源数据发生改变,关我何事

# 4. 注意
    # copy.copy()对于可变类型,会进行浅拷贝
    # copy.copy()对于不可变类型,不会拷贝,仅仅是指向
    # 浅拷贝中有引用,那就引用
    # 深拷贝中有引用,会递归复制

3. 私有化

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

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

class Person(object):
    def __init__(self, name, age, taste):
        self.name = name
        self._age = age 
        self.__taste = taste

    def showperson(self):
        print(self.name)
        print(self._age)
        print(self.__taste)

    def dowork(self):
        self._work()
        self.__away()


    def _work(self):
        print('my _work')

    def __away(self):
        print('my __away')

class Student(Person):
    def construction(self, name, age, taste):
        self.name = name
        self._age = age 
        self.__taste = taste

    def showstudent(self):
        print(self.name)
        print(self._age)
        print(self.__taste)

    @staticmethod
    def testbug():
        _Bug.showbug()

# 模块内可以访问,当from  cur_module import *时,不导入
class _Bug(object):
    @staticmethod
    def showbug():
        print("showbug")

s1 = Student('jack', 25, 'football')
s1.showperson()
print('*'*20)

# 无法访问__taste,导致报错
# s1.showstudent() 
s1.construction('rose', 30, 'basketball')
s1.showperson()
print('*'*20)

s1.showstudent()
print('*'*20)

Student.testbug()

总结:

  • 父类中属性名为__名字的,子类不继承,子类不能访问
  • 如果在子类中向__名字赋值,那么会在子类中定义的一个与父类相同名字的属性
  • _名的变量、函数、类在使用from xxx import *时都不会被导入

4. 封装、继承、多态

为什么要封装

GIL/copy/私有/面向对象_第1张图片

 

 GIL/copy/私有/面向对象_第2张图片

好处:

  1. 在使用面向过程编程时,当需要对数据处理时,需要考虑用哪个模板中哪个函数来进行操作,但是当用面向对象编程时,因为已经将数据存储到了这个独立的空间中,这个独立的空间(即对象)中通过一个特殊的变量(__class__)能够获取到类(模板),而且这个类中的方法是有一定数量的,与此类无关的将不会出现在本类中,因此需要对数据处理时,可以很快速的定位到需要的方法是谁 这样更方便
  2. 全局变量是只能有1份的,多很多个函数需要多个备份时,往往需要利用其它的变量来进行储存;而通过封装 会将用来存储数据的这个变量 变为了对象中的一个“全局”变量,只要对象不一样那么这个变量就可以再有1份,所以这样更方便
  3. 代码划分更清晰

为什么要继承

  1. 能够提升代码的重用率,即开发一个类,可以在多个子功能中直接使用
  2. 继承能够有效的进行代码的管理,当某个类有问题只要修改这个类就行,而其继承这个类的子类往往不需要就修改

怎样理解多态

Python中多态的作用
让具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容(功能)的函数。

Python中多态的特点
1、只关心对象的实例方法是否同名,不关心对象所属的类型;
2、对象所属的类之间,继承关系可有可无;
3、多态的好处可以增加代码的外部调用灵活度,让代码更加通用,兼容性比较强;
4、多态是调用方法的技巧,不会影响到类的内部设计。

多态的应用场景

1. 对象所属的类之间没有继承关系
调用同一个函数fly(), 传入不同的参数(对象),可以达成不同的功能

class Duck(object):                                  # 鸭子类
    def fly(self):
        print("鸭子沿着地面飞起来了")

class Swan(object):                                  # 天鹅类
    def fly(self):
        print("天鹅在空中翱翔")

class Plane(object):                                 # 飞机类
    def fly(self):
        print("飞机隆隆地起飞了")

def fly(obj):                                        # 实现飞的功能函数
    obj.fly()

duck = Duck()
fly(duck)

swan = Swan()
fly(swan)

plane = Plane()
fly(plane)

# 运行结果:

鸭子沿着地面飞起来了
天鹅在空中翱翔
飞机隆隆地起飞了

2. 对象所属的类之间有继承关系(应用更广)

class gradapa(object):
    def __init__(self,money):
        self.money = money
    def p(self):
        print("this is gradapa")
 
class father(gradapa):
    def __init__(self,money,job):
        super().__init__(money)
        self.job = job
    def p(self):
        print("this is father,我重写了父类的方法")
 
class mother(gradapa): 
    def __init__(self, money, job):
        super().__init__(money)
        self.job = job
 
    def p(self):
         print("this is mother,我重写了父类的方法")
         return 100
         
#定义一个函数,函数调用类中的p()方法
def fc(obj): 
    obj.p()
gradapa1 = gradapa(3000) 
father1 = father(2000,"工人")
mother1 = mother(1000,"老师")

fc(gradapa1)            #这里的多态性体现是向同一个函数,传递不同参数后,可以实现不同功能.
fc(father1)
print(fc(mother1))

# 运行结果:

this is gradapa
this is father,我重写了父类的方法
this is mother,我重写了父类的方法
100

你可能感兴趣的:(GIL/copy/私有/面向对象)