在Python中,包就是用来包裹模块的文件夹。文件夹是可以当成包来使用,但是包并不是文件夹。
Python中包的标准:如果一个文件夹中存在__init__.py模块文件的话,这个文件夹就是包。__init__.py一般用来初始化文件。
xx.py文件, 保存是要执行或者使用代码
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", …] #此处使用列表,也可使用元组
但是在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
将一个变量赋值给另一个变量,这个过程叫做赋值。赋值会导致多个变量同时指向同一块内存(栈内存的复制),所以此时不管是==或者is都会返回Ture。
浅拷贝对象,并不是把对象完整的拷贝,而是仅仅拷贝了第一层对象,如果对象中存储子对象,那么子对象还是藕断丝连。
通俗的理解是:拷贝了引用,并没有拷贝内容。
>>> 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]
深拷贝是对一个对象所有层次的拷贝,使用了递归的方式。这样,两个对象之间将没有任何关系
缺点:效率低下,占用内存
>>> 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]]
元组、字符串、数值这些不可变类型,所有深浅拷贝后,永远只有一份内存。
>>> 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的垃圾回收机制:
以引用计数为主,以分代收集和标记清楚为辅