存在的问题:当我们把模块文件放到工程文件夹的外部的文件,发现无法正常引入模块
原因: 外部的文件夹的路径,没有放到环境变量中
查看环境变量
1.导入 sys模块
2.sys.path 查看环境变量 返回值是列表
把自己写的模块的路径加入到环境变量中
1.sys.path.append(“自己的路径”) # 加入环境变量的末位
2.sys.path.insert(0, “自己的路径”) # 加入到环境变量的开头位置
import 导入模块后,如果模块被修改,此时再次 import 不起作用
import 自动防止重复包含
强制重新加载一次模块
reload() 函数
1.from imp import reload
2.reload(要重新加载的模块)
私有化: 模块中的一些变量不希望被其他模块导入,可以使用私有化解决
私有化使用的前提:必须使用 “ from xxx import * “
用法: 在模块中,把变量前增加一个下划线 _变量名
注意:如果使用其他的方式导入模块,私有化将无效
import和from…import的区别from xxx import _私有变量
print(_私有变量) 不会报错
区别
o写法:
import 模块名.变量/函数/类
from … import * 变量名/函数/类
o底层的区别:
import 直接引用了源模块的 变量/函数/类
from … import * 拷贝源模块的 变量/函数/类 到当前自己类
可变参数 *args **kwargs 默认会封包过程
如果想要这种单数继续传递到下一个函数,传递的时候 func(*args,**kwargs)
# 定义两个函数 func02 func01
# func02 调用func01
# func02 有可变参数
def func01(*args, **kwargs):
print("--------- func01 ---------")
print(args)
print(kwargs)
def func02(*args, **kwargs):
print("args = ", args)
print("kwargs = ", kwargs)
# 调用func01
# 此处没有进行拆包,导致参数传递过去不不和要求
# func01(args,kwargs)
## func01(*args,**kwargs)
if __name__ == '__main__':
func02(10,20,30,40,50,a=10,b=20)
单继承中super()
super() 使用的时候,传递参数的时候,self 不用传递
super() 调用顺序,按照 mro顺序来完成
Grandson.mro 是一个元组当在类中使用 super() 在 mro列表中找到当前类的下一个元素,调用该元素的方法
多继承中 super() 执行顺序,严格执行 MRO顺序表
MRO顺序表:
o类名.mro()
o类名.mro
注意:
当在类中使用 super() 在 mro列表中找到当前类的下一个元素,调用该元素的方法多继承中,不建议使用类名 直接调用父类的方法
# 定义父类Parent
class Parent(object):
def __init__(self, name,*args, **kwargs):
self.name = name
print('parent的init结束被调用')
# 定义子类 Son1 --继承--> Parent
class Son1(Parent):
def __init__(self, name,age, *args, **kwargs):
self.age = age
super().__init__( name,*args, **kwargs)
print('Son1的init结束被调用')
# 定义子类 Son2 --继承--> Parent
class Son2(Parent):
def __init__(self, name, gender,*args, **kwargs):
self.gender = gender
super().__init__(name,*args, **kwargs)
print('Son2的init结束被调用')
# 定义子类 Grandson --继承--> Son1 Son2
class Grandson(Son1, Son2):
def __init__(self, name, age, gender):
# parent 调用2次
# Son2.__init__(self, name, age)
# Son2.__init__(self, name, gender)
super().__init__(name, age,gender) # 单独调用父类的初始化方法
print('Grandson的init结束被调用')
# 创建对象
gs = Grandson('grandson', 12, '男')
print(Grandson.mro())
多继承和MRO顺序-2
properties装饰器方法
property基本使用
@property 的特点: 让我们通过对象.方法名的方式可以调用方法
语法格式:
@proerty
def xxx(self):
? pass
注意:
@property 装饰的方法,只能有一个参数self
class Foo(object):
# 初始化方法
def __init__(self, num):
self.num = num
# 获取值的方法
@property
def prop(self):
return self.num
# 创建对象
foo = Foo(100)
# 调用对象方法
# print(foo.prop())
# foo.prop 之后,---> foo.prop()
# @property 像使用属性一样去使用方法,获取值
print(foo.prop)
@property实现分页类
"""
类名: Page
方法:
1.初始化方法
2.获取开始的位置
3.获取结束的位置
"""
class Page(object):
# 1.初始化方法
def __init__(self,num):
# 当前页
self.current_page = num
# 每页大小
self.page_size = 10
# 2.获取开始的位置
@property
def start(self):
# limit (当前页-1)* 每页大小, 每页大小
# 1,10
# 11,20
return (self.current_page-1)*10+1
# 3.获取结束的位置
@property
def end(self):
return self.current_page*self.page_size
# 创建类的对象
page = Page(2)
# 获取开始位置
# print(page.start())
print(page.start)
# 获取结束位置
print(page.end)
# print(page.end())
@property其它方法使用
经典类: @property 一种方式
新式类:
o@property
goods.price 获取价格的方法
o@xxx.setter
goods.price = xxx
o@xxx.deleter
del goods.price —> @xxx.delete 装饰的方法
"""
类: Goods
方法:
1.初始化方法
2.获取价格的方法
3.设置价格的方法
4.删除价格的方法
"""
class Goods(object):
# 1.初始化方法
def __init__(self):
# 初始化一个原价
self.org_price = 1000
# 初始化折扣
self.discount = 0.7
# 2.获取价格的方法
@property
def price(self):
return self.org_price * self.discount
# 3.设置价格的方法
@price.setter
def price(self,val):
if val > 0:
self.org_price = val
# 4.删除价格的方法
@price.deleter
def price(self):
print("执行了 deleter 方法")
# del self.org_price
# 创建对象
goods = Goods()
# goods.price == goods.price()
print(goods.price)
# goods.price == goods.price(500)
goods.price = 500
print(goods.price)
# del goods.price == @price.deleter 装饰的方法
del goods.price
property作为类属性
定义 property 对象的类属性
xxx =property(参数1,参数2,参数3,参数4)
# 第一个参数,当我们 foo.BAR 自动调用第一个参数的方法
使用
o对象.xxx 获取值
o对象.xxx = 100 设置值
odel 对象.xxx 调用第三个参数方法
o类.xxx.doc 获取第四个参数的内容
class Goods(object):
# 1.初始化方法
def __init__(self):
# 初始化一个原价
self.org_price = 1000
# 初始化折扣
self.discount = 0.7
# 2.获取价格的方法
def get_price(self):
return self.org_price * self.discount
# 3.设置价格的方法
def set_price(self,val):
if val > 0:
self.org_price = val
# 4.删除价格的方法
def del_price(self):
print("执行了 deleter 方法")
# del self.org_price
# property(第一个参数,第二个参数,第三个参数,第四个参数)
# 第一个参数,当我们 foo.BAR 自动调用第一个参数的方法
# 第二个参数,当我们 foo.BAR = 100,自动调用第二个参数的方法
# 第三个参数,当我们 del foo.BAR ,自动调用第三个参数的方法
# 第四个参数,当我们 Foo.BAR.__doc__,自动获取第四个参数的内容
BAR = property(get_price,set_price,del_price,"BAR 是一个property对象")
if __name__ == '__main__':
# 创建对象
goods = Goods()
# goods.BAR == goods.get_price()
print(goods.BAR)
# 设置价格
# goods.BAR = 500, ===== goods.set_price(500)
goods.BAR = 500
print(goods.BAR)
# 删除价格
# del goods.BAR ===== @del_price.delter
del goods.BAR
# 获取对象描述
# Goods.BAR.__doc__ === Goods.__doc__
print(Goods.BAR.__doc__)
魔术属性与方法
魔术属性
o__doc__ 获取描述信息
获取类的 类名.doc
获取方法的描述 对象.方法名.doc
o__module__ 获取所属的模块(对象名.module) 直接改文件 获取的__main__
o__class__ 获取对象所属的类 对象名.class
魔术方法
o__init__ 初始化方法 类名() 自动调用
o__del__ 删除对象的时候,会调用 del 对象
class Goods(object):
"""这是一个商品的类 Goods"""
def set_price(self):
"""这是Goods类中定义的设置价格方法"""
pass
def __del__(self):
print("__del__ 正在执行")
# 1、类的描述信息
# 类名.__doc__
print(Goods.__doc__)
goods = Goods()
# g2 = goods
# 2、对象方法的描述
# 对象名.方法名.__doc__
print(goods.set_price.__doc__)
# 3、获取当前模块
print(goods.__module__)
# 4、获取对象所属的类
print(goods.__class__)
# 5、删除对象会执行 对象的 __del__()
del goods
print("xxxxx")
魔术属性__dict__ 获取对象或者类的信息
o获取对象信息 对象名.dict__对象的实例属性信息
o获取类的信息类名.dict 模块、类描述、对象方法…
魔术方法
o__call() 当使用 对象名() 会调用该方法
o__str__() 打印对象的会调用 print(obj) str方法一定要return,而且return 一定字符串内容
o用字典的书写格式操作对象的方法
__getitem__ 对象[‘xxx’]
__setitem__ 对象[‘xx’] = xxx
__delitem__ del 对象[‘xx’]
class Goods(object):
"""这是一个商品的类 Goods"""
# 类属性
goods_color = "白色"
def __init__(self):
# 实例属性
self.org_price = 100
self.discount = 0.7
def set_price(self):
"""这是Goods类中定义的设置价格方法"""
pass
def __call__(self, *args, **kwargs):
print("__call__ 方法被调用")
def __str__(self):
return "我是一个寂寞的对象"
def __del__(self):
print("__del__ 正在执行")
def __getitem__(self, item):
print("key = ", item)
def __setitem__(self, key, value):
print("key = %s, value = %s" % (key,value))
def __delitem__(self, key):
print("要删除 key = ",key)
goods = Goods()
# 对象名() 会去调用对象的 __call__() 方法
# goods()
# print 打印对象的时候,默认输出<__main__.Goods object at 0x7efe5e9e0a20>
# print(goods)
# 通过__dict__ 获取对象信息,对象.__dict__返回字典
# print(goods.__dict__)
# 通过__dict__ 获取类的信息 类名.__dict__ 返回值是一个字典
# print(Goods.__dict__)
# dict1 = {}
# dict1['a'] = 10
# goods['a'] 调用 __getitem__方法
# goods['a']
# goods['a'] = 10 调用 __setitem__ key,value
# goods['a'] = 10
# del goods['a'] 调用 __delitem__ key
del goods['a']
with管理上下文
上下文:以 with open 来说,打开文件在上文 关闭文件在下文
上下文管理器:
o__enter__ 上文方法
o__exit__ 下文方法
"""
类: MyFile()
类方法:
1. __enter__() 上文方法
2. __exit__() 下文方法
3. __init__() 方法,接收参数并且初始化
with MyFile('hello.txt', 'r') as file:
file.read()
"""
class MyFile(object):
# 1. __enter__() 上文方法
def __enter__(self):
print("进入上文....")
# 1,打开文件
self.file = open(self.file_name, self.file_model)
# 2,返回打开的文件资源
return self.file
# 2. __exit__() 下文方法
def __exit__(self, exc_type, exc_val, exc_tb):
print("进入下文....")
# 关闭文件资源
self.file.close()
# 3. __init__() 方法,接收参数并且初始化
def __init__(self, file_name, file_model):
# 保存文件名和文件打开模式,到实例属性中
self.file_name = file_name
self.file_model = file_model
if __name__ == '__main__':
with MyFile("hello.txt", "r") as file:
# 开始读取文件
file_data = file.read()
print(file_data)
装饰器实现上下文
通过装饰器 @ contextmanager 实现上下文管理
o装饰器
o待装饰的函数
omyopen() 分拆成上文和下文,使用yield 分拆
"""
思路:
def myopen(file_name,file_model)
上文(打开资源)
yield
下文(关闭资源)
装饰器装饰函数的步骤:
1. 导入模块 from contextlib import contextmanager
2. 开始装饰 @contextmanager
"""
from contextlib import contextmanager
@contextmanager
def myopen(file_name,file_model):
print("进入上文")
# 1.打开文件
file = open(file_name,file_model)
# 2.返回资源
yield file
print("进入下文")
# 下文
# 3. 关闭资源
file.close()
with myopen("hello.txt", "r") as file:
file_data = file.read()
print(file_data)



