Python_10:高级编程_零碎知识点

一、包和模块

1.1 什么是包(package)

  • 在Python中,包就是用来包裹模块的文件夹。文件夹是可以当成包来使用,但是包并不是文件夹。

  • Python中包的标准:如果一个文件夹中存在__init__.py模块文件的话,这个文件夹就是包。__init__.py一般用来初始化文件。

1.2 什么是模块(module)

xx.py文件, 保存是要执行或者使用代码

1.3 常见导包方式

  • import package.module

  • import package.module as alias

  • from package import module

  • from package import module as alias

  • from package.package… import module as alias

  • from package import * # 通配所有

    • 使用第三方包有时会出现,from package import *无法导入该包下的所有模块。原因在于该包并没有对所拥有的模块进行声明。声明方式如下:__init__.py

      #__init__.py文件中
      #声明该包下的所属模块,只有在__all__属性声明过的模块,才支持*通配导入
      __all__ = ["a.py", "b.py",]	#此处使用列表,也可使用元组
      

二 、is 和 ==

  • is判断的是两个变量的内存地址
  • == 判断是两个变量的值

但是在python中,有小整形常量池(-5~256)和字符串常量池(不包含特殊符号)。

这个标准是pyhthon官方的,各IDE可能会进行修改或者拓展

>>> a = -6
>>> b = -6
>>> a is b
False

>>> c = 12
>>> d = 12
>>> c is d
True

>>> e = 'abc'
>>> f = 'abc'
>>> e is f
True

三、深浅拷贝(对象)

3.1 赋值(基本数据类型)

将一个变量赋值给另一个变量,这个过程叫做赋值。赋值会导致多个变量同时指向同一块内存(栈内存的复制),所以此时不管是==或者is都会返回Ture。

3.2 浅拷贝

  • 如列表的 copy() 方法和 copy.copy()

浅拷贝对象,并不是把对象完整的拷贝,而是仅仅拷贝了第一层对象,如果对象中存储子对象,那么子对象还是藕断丝连。

通俗的理解是:拷贝了引用,并没有拷贝内容。

>>> import copy
>>> a = [1,2,3,[4,5]]

>>> b = copy.copy(a)
>>> b
[1, 2, 3, [4, 5]]

#修改第一层对象
>>> a.append(6)
>>> a
[1, 2, 3, [4, 5], 6]
>>> b
[1, 2, 3, [4, 5]]

#修改第二层对象
>>> b[3].append(7)
>>> b
[1, 2, 3, [4, 5, 7]]
>>> a
[1, 2, 3, [4, 5, 7], 6]	#此时a[3]也发生了改变,这里b[3]引用拷贝了a[3]

3.3 深拷贝

  • copy.deepcopy()

深拷贝是对一个对象所有层次的拷贝,使用了递归的方式。这样,两个对象之间将没有任何关系

缺点:效率低下,占用内存

>>> a = [1,2,3,[4,5]]
>>> b = copy.deepcopy(a)
>>> b
[1, 2, 3, [4, 5]]

>>> b[3].append(6)
>>> b
[1, 2, 3, [4, 5, 6]]
>>> a
[1, 2, 3, [4, 5]]

3.4 最佳实践

  1. 需要将当前对象拷贝的时候,一般建议拷贝为浅拷贝,(效率高,内存占有少)
  2. 如果说,就是需要完全分离,请使用深拷贝

3.5 特殊情况

元组、字符串、数值这些不可变类型,所有深浅拷贝后,永远只有一份内存。

>>> a = (1,2,3)
>>> b = copy.copy(a)
>>> c = copy.deepcopy(a)
>>> b is c
True

但是!如果元组中存在可变类型的元素,深拷贝还是会开辟新内存进行拷贝区分

>>> a = (1,2,3,[4,5])
>>> b = copy.copy(a)
>>> c = copy.deepcopy(a)
>>> b is c
False

四、函数:闭包

能够在函数内部调用其他函数变量的现象就闭包——函数包裹函数的现象,就叫做闭包、闭包是弱数据类型编程语言所特有的现象。(JavaScript高度应用闭包)

作用:让外层函数常驻内存,有可能垃圾无法回收,让局部变量全局化、

def outer():

    print("这是一个闭包")
    a = 10

    def inner():
        print("这是内部函数")
        b = 20
        print(a + b)

    return inner


res = outer()
print(res)

"""
结果:

这是一个闭包
.inner at 0x000002C735088550>
"""

执行outer()函数时。其中的inner()函数并没有执行,因为没有被调用。而return inner返回了inner()函数的内存地址。此时 res 指向了inner()函数

def outer():

    print("这是一个闭包")
    a = 10

    def inner():
        print("这是内部函数")
        b = 20
        print(a + b)

    return inner


res = outer()		#此时res指向inner()函数地址
print(res)
res()				#执行inner()函数

"""
结果:

这是一个闭包
.inner at 0x00000221F7D58550>
这是内部函数
30
"""

在没有闭包的情况下,res = outer() 代码执行完毕后,outer() 函数的内存将会被回收。在闭包的存在下,外层函数 outer() 常驻内存。让局部变量 a 全局化。

五、动态语言特性

python动态语言允许动态添加或者删除属性和方法

  • 动态增加属性
class User(object):
    # __slots__ = ("name", "age")
    def __init__(self):
        self.name = "王"
        self.age = 16


if __name__ == '__main__':
    u1 = User()
    print(u1.name)
    print(u1.age)
    # 动态语言的特性
    u1.gender = "男"
    print(u1.gender)
    
"""
结果:
王
16
男
"""
  • 删除属性
class User(object):
    # __slots__ = ("name", "age")
    def __init__(self):
        self.name = "王"
        self.age = 16


if __name__ == '__main__':
    u1 = User()
    print(u1.name)
    print(u1.age)
    # 动态语言的特性
    u1.gender = "男"
    print(u1.gender)

    del u1.name

    print(u1.name)
    
"""
结果:
王
16
男
Traceback (most recent call last):
  File "D:/OpenLab/Python/4.9/day14/动态语言的特性.py", line 19, in 
    print(u1.name)
AttributeError: 'User' object has no attribute 'name'
"""

可以通过__solits__方法,规定类的固有属性。这样子User类只有这两个属性,无法添加或者删除。

class User(object):
    __slots__ = ("name", "age")
    def __init__(self):
        self.name = "王"
        self.age = 16

六、垃圾回收机制

Python的垃圾回收机制:

以引用计数为主,以分代收集和标记清楚为辅

你可能感兴趣的:(Python的学习,python)