Python之---面向对象编程
一、基础类的定义
类:对一系列具有相同特征(属性)和行为(方法)的事物的统称,是一个抽象的概念,不是真实存在的事物。
对象:对象是类创建出来的真实存在的事物。
两者之间的关系:用类去创建或者是实例化一个对象
简单理解就是:把数据和对数据的操作用一种叫做“对象”的东西包裹起来,然后通过对象来调用。这就是面向对象编程。
语法如下:
#1.定义类:注意大小驼峰命名习惯
class Machine():
def washClose(self): #self是指调用函数的对象
print("洗衣服...")
print(self)
#2.创建对象:对象名=类名()
wash01=Machine()
#3.验证成果:实例方法:类名.方法名()
wash01.washClose()
注意: self是指调用该函数的对象
类属性:
类属性是归属于对象的属性,所有对象共有的属性。
类属性可以使用类对象或实例对象访问。
优点:
1.记录的某项数据始终保持一致时,定义类属性
2.实例属性要求每个对象都为其单独开辟一个内存空间来记录数据,而类属性是为全类所共有,仅占用一个内存,相比更加节省内存空间。
类属性的访问方式有两种:1、类名.属性名;2、对象名.属性名
修改类属性:只能通过类.属性名修改
class dog():
tooth=10
print(dog.tooth)
dog1=dog()
print(dog1.tooth)
修改类属性的值:类名.类属性=值 ;
dog.tooth=20
不能通过对象名修改!!!通过实例对象修改的,实际上是创建了一个跟类属性同名的实例属性:对象名.类属性=值
dog1.tooth=200
实例属性
某一个对象所拥有的属性,每一个实例属性都是一个对象的,所以占用空间大。
1.类外添加获取实例属性
实例属性既可以在类的外面添加获取,也可以在类的里面添加获取
语法:
对象名.属性名=值
wash01.hight=31
2.类内添加获取属性
语法:self.属性名
#1.定义类
class Machine():
def washClose(self): #self是指调用函数的对象
print("洗衣服...")
print(self)
#2.创建对象:对象名=类名()
wash01=Machine()
wash01.hight=31
#3.验证成果:实例方法:类名.方法名()
wash01.washClose()
print(wash01.hight)
二、函数
- 静态方法、类方法,可以被类或类的实例对象调用
- 实例方法只能被实例对象调用
- 静态方法,参数没有要求
- 类方法,第一个参数必须要默认传类,一半习惯用cls
- 实例方法,第一个参数必须要默认传实例对象,一般习惯用self
默认函数
init() :初始化数据
class Washer():
#定义初始化方法,添加实例属性
def __init__(self):
self.width=23
self.height=32
def print_info(self):
#类里面调用实例属性
print(f'宽度:{self.width},高度:{self.height}')
washinfo=Washer()
washinfo.print_info()
结果:
宽度:23,高度:32
注意:
1._ _ init _ _()方法,在创建一个对象时,自动被调用
2. _ _ init _ _(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递过去
带参数的init方法
class Washer():
#定义初始化方法,添加实例属性
def __init__(self,width,height):
self.width=width
self.height=height
def print_info(self):
#类里面调用实例属性
print(f'宽度:{self.width},高度:{self.height}')
washinfo=Washer(122,222)
washinfo.print_info()
结果:
宽度:122,高度:222
_ _ str _ _() 一般用return做结束,主要是一些说明的文字。
_ _ del _ _() : 当删除对象时,python解释器会默认调用del方法。
类方法
特点:需要用装饰器@classmethod来标识其为类方法。对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数。
类方法一般和类属性搭配使用
当方法中需要使用类对象(如访问私有属性等)时,定义类方法
class dog(object):
__tooth=10
@classmethod
def get_tooth(cls):
return cls.__tooth
dog1=dog()
print(dog1.get_tooth())
result:
10
静态方法
特点:
需要通过修饰器@staticmethod进行装饰说明,静态方法既不需要传递对象也不需要传递实例对象(参数没有self/cls)
静态方法可以通过实例对象和类对象访问,非静态方法不能通过实例对象访问
使用场景:
当方法中既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象(如类属性,类方法,创建实例等)时,定义静态方法
取消不需要的参数传递,有利于减少不必要的内存占用和性能消耗
class dog(object):
__tooth=10
@staticmethod
def dogmethod():
print('这是一个静态方法')
dog1=dog()
dog.dogmethod()
dog1.dogmethod()
result:
这是一个静态方法
这是一个静态方法
三、闭包
定义:在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包
构成闭包的三大条件:
1.在函数嵌套(函数里面再定义函数)的前提下
2.函数内部使用了外部函数的变量(还包括外部函数的参数)
3.外部函数返回了内部函数
闭包作用:
闭包就是一个内部定义的函数。可以保存外部函数内的变量,不会随着外部函数调用完而销毁
注意:
- 由于闭包引用了外部函数的变量,则外部函数的变量没有及时释放,消耗内存。
举例:
def func():
global a
a=1
def func2(num):
sum=0
for i in range(num):
sum+=i
sum+=a
print(f'综合:{sum}')
return func2
new=func() #调用嵌套的外部函数
x=new(2) #调用嵌套的内部函数
y=func()(2) #简写:一步调用嵌套的内部函数
print(x) #综合:1 综合:3
#print(y) #同x的结果
闭包的使用:
def fun_name(name):
def dialog(msg):
print(name+':'+msg)
return dialog
Tom=fun_name('Tom')
Jerry=fun_name('Jerry')
Tom('小可爱,一起去吃饭吧')
Jerry('谁是你的小可爱,不去,等下要去约会')
Tom('狗子🐕,你变了')
Jerry('不,狗子🐕,一直都是你傻,哈哈哈哈哈')
Tom('我发现可以正常打印狗的标志,不信你看:🐕')
Jerry('傻狗')
result:
Tom:小可爱,一起去吃饭吧
Jerry:谁是你的小可爱,不去,等下要去约会
Tom:狗子🐕,你变了
Jerry:不,狗子🐕,一直都是你傻,哈哈哈哈哈
Tom:我发现可以正常打印狗的标志,不信你看:🐕
Jerry:傻狗
闭包修改外部函数变量:
def func():
a=1
def func2():
nonlocal a -------------这里直接用a=2,或global a /a=2 都无法改变a的变量值,因为此时外部函数定义的a也是一个局部变量,只在func函数内部局部有效。
a=2
b=a+1
print(f'综合:{b}')
print(f'修改前的a值:{a}')
func2()
print(f'修改后的a值:{a}')
return func2
func()
result:
修改前的a值:1
综合:3
修改后的a值:2
四、装饰器
装饰器就是给现有的函数添加装饰功能的函数。简单来说就是:把原来的函数包装起来,在不改变原代码的情况下,给它新增功能。
特点:
1.它的参数传入的是被装饰的函数
2.返回值是新定义的一个包装了原有函数的内部函数
3.新定义的函数如wrapper的参数可以根据实际需要看是否要传,建议传(*args,**kwargs)可以同时兼容不带参数的函数和带参数的函数(其实原理就是*args是形式参数,表示的是0个或多个参数,可带可不带)
4.*args代表所有的位置参数,**kwargs代表所有的关键词参数。
其实Decorator之前学习java的朋友们肯定还有一丢丢印象,比如我们常见的:@classmethod,@staticmethod , @property
是不是很熟悉呀?这些都是装饰器的应用。接下来首先讲下函数装饰器吧。
最典型的使用场景:
老板让你给一个旧的功能添加几个小功能优化一下,但是原功能的核心代码不能改动。
该怎么做最好呢?
答案肯定就是使用装饰器啦,不改变原代码,还能添加新的东西,这东西现在可是炙手可热呀。
(面试贼爱拿出来刺激你,这时候你当场懵。内心os:啥?装饰器?好像有一丢丢印象,但是咋说呀,在你小脑袋里疯狂输出一波后,还没来得及整理讲出来,面试官就会说:那咱们来说说下一个问题吧,emmmmm)-------------不好意思,这就是我经历过的惨痛遭遇…
不说废话啦,咱们这就开始入门:先看看如下模板,大致简单了解下叭~
装饰器代码通用模板:
def decorator(func):
def wrapper(*args,**kwargs):-----------------函数内部定义的新增逻辑函数,参数写了是为了跟内部调用被装饰函数保持一致。
print("这是为被装饰函数添加的新功能逻辑")
res=func(*args,**kwargs) #对于被装饰函数没有参数的可以不写,这里写了是为了兼容有传参的函数
return res
return wrapper-----------这个是装饰器函数,返回值是内部的函数。固定写法。
@decorator-------------------------------------装饰器标志,也叫《语法糖衣》
def test1():
print("这是被装饰函数的内容逻辑")
test1() #调用执行函数
好了,知道你看懂了,接下来输出一波实践:
不带参数的被装饰函数
import time
def Timer(func):
def wrapper():#同样是为了兼容有传参的函数
print('hello,this is a decorator')
time_Start=time.time()
func() #对于被装饰函数没有参数的可以不写,这里写了是为了兼容有传参的函数
time_Stop=time.time()
Total_time=time_Stop-time_Start
print(f'总共花了{Total_time}s')
return wrapper
@Timer #等价于test1=Timer(test1) 最终就是test1=wrapper,被装饰器函数修改成了新定义的装饰函数
def test1():
print("执行被装饰函数逻辑")
sum=0
for i in range(10000):
sum=sum+i
print(f"总和为{sum},被装饰函数执行完毕")
test1()
result:
hello,this is a decorator
执行被装饰函数逻辑
总和为49995000,被装饰函数执行完毕
总共花了0.000997781753540039s
你会了吗?
会了咱们就下一个:
带参数的被装饰函数
wrapper把参数带入即可wrapper(*args,**kwargs)
import time
def Timer(func):
def wrapper(*args,**kwargs):#同样是为了兼容有传参的函数
print('hello,this is a decorator')
time_Start=time.time()
func(*args,**kwargs) #对于被装饰函数没有参数的可以不写,这里写了是为了兼容有传参的函数
time_Stop=time.time()
Total_time=time_Stop-time_Start
print(f'总共花了{Total_time}s')
return wrapper
@Timer
def test1(a,b): ----------------------------带参数的被装饰函数
print("执行被装饰函数逻辑")
sum=0
sum=a+b
print(f"总和为{sum},被装饰函数执行完毕")
test1(1,2)
也会了吧?那咱们继续…
带返回值的被装饰函数
只需要给wrapper添加一个返回值即可,当然这是一个有返回值的函数,那么需要将这个返回值设置为变量才能正常获取打印。
import time
def Timer(func):
def wrapper(*args,**kwargs):#同样是为了兼容有传参的函数
print('hello,this is a decorator')
time_Start=time.time()
res=func(*args,**kwargs) #对于被装饰函数没有参数的可以不写,这里写了是为了兼容有传参的函数
time_Stop=time.time()
Total_time=time_Stop-time_Start
print(f'总共花了{Total_time}s')
return res
return wrapper
@Timer
def test1(a,b):
print("执行被装饰函数逻辑")
sum=0
sum=a+b
return f"总和为{sum},被装饰函数执行完毕"
last=test1(1,2)
print(last)
result:
hello,this is a decorator
执行被装饰函数逻辑
总共花了0.0s
总和为3,被装饰函数执行完毕
啥啥啥,没看懂?那就去手敲亿点点代码实践实践吧~
学到这,对于装饰器已经了解的很多了,甚至可以手撕代码,敲醒面试官。
但是…
以上只是个函数装饰器,也叫类装饰器,还有好多其他的呢,比如:
- 多装饰器串联
- 带参数的装饰器(这个指的是语法糖衣带参数,非被装饰函数带参哈!)
- 带状态的装饰器
- 类装饰器
- 用类封装的装饰器
- 装饰器常用情况举例
多装饰器举例
其实多装饰器实现原理很简单,一个函数一个函数的执行,流程如下:
1,先执行装饰器test2,对于test2来说它的fun就是(@test3+func())
2,运行到test2的内部函数func()中,这时候应该去执行test3装饰器内部函数
3,等test3整个执行完成,这时候才会再去接着执行test2剩余的代码。
整个流程其实有点类似递归函数的感觉!
图示:
import time
def test2(func):
def wrapper():
print('test2')
func()
print('22222222')
return wrapper
def test3(func):
def wrapper3():
print('test3')
func()
print('333333')
return wrapper3
@test2
@test3
def test1():
print("执行被装饰函数逻辑")
test1()
result:
test2
test3
执行被装饰函数逻辑
333333
22222222
被装饰函数传入一个带参语法糖衣,怎么搞??
使用带有参数的装饰器,其实就是在原有的装饰器外层再包裹一个函数来接收装饰器传入的参数,返回是装饰器,因为@符号需要配合装饰器实例使用。
如下代码,其实就是给装饰器增加了缓冲时间而已。
当然如果你只是按照原来装饰器那样写,那会直接调用wrapper函数,但是我传入的函数又没有参数呀,这时候就会报错。怎么解决呢?
这时候,只要给整个装饰器函数外面套一层传参的函数就行啦。注意这个函数的返回值还是要按照装饰器函数写法哦,return的值要是内部定义函数名
import time
def run(seconds):
def decorator(func):
def wrapper(*args,**kwargs):
print('hello,this is a decorator')
time.sleep(seconds)
time_Start=time.time()
func(*args,**kwargs)
time_Stop=time.time()
Total_time=time_Stop-time_Start
print(f'总共花了{Total_time}s')
return wrapper
return decorator
@run(5)
def test1():
print("执行主函数逻辑")
for i in range(10):
print(i,end='')
test1()
执行原理:
1.先执行run(5),接受秒数作为参数
2.run里面创建了decorator函数,这就是原来的那个装饰器函数
3.decorator里面又创建了wrapper,执行跟之前的一毛一样滴。
原因:
1)当python发现run(5)这个装饰器自带了参数时,就不会再传入当前函数作为参数,直接调用run,这是python解释器规定的
2)run返回了一个函数,这时候python会再把当前函数传入进去,这时候就成了一个普通装饰器啦。
类装饰器
类装饰器模板:
class myDecorator(object):
def __init__(self,func): #定义__init__方式是为了讲函数当作一个参数传递到类内部
self.__func=func #定义私有属性,是为了防止通过show.func()来被调用
def __call__(self, *args, **kwargs): #实现__call__方法,是为了让该类变成一个可调用对象,可以向调用函数一样进行调用
#添加装饰功能
print('先来一套拳踢秀')
self.__func()
@myDecorator
def show():
print('表演中国功夫~')
show()
小结:
- @myDecorator 等价于show=myDecorator(show),所以需要实现一个init方法,并加一个func参数
- 要想类的实例对象能够像函数一样被调用,需要在类里面实现call方法,把类实例变成可调用对象(callable),也就是说可以像调用函数一样进行调用。
注意:函数之所以能被调用,是因为函数内部实现了call方法
代码调试装饰器
创建一个装饰器:会打印函数参数,以及返回值--------这个其实就是自动打印日志,程序员们找bug的重要证据呀!
def debug(func):
def wrapper(*args,**kwargs):
print(f'函数名:{func.__name__};\n参数1:{args};\n参数2:{kwargs}')
ret=func(*args,**kwargs)
print(f'return:{ret}')
return ret
return wrapper
@debug
def add(a,b):
return a+b
print(add(1,3))
result:
函数名:add;
参数1:(1, 3);
参数2:{}
return:4
4
上面这道题就是给原来的求和函数增加了打印执行日志的功能,如:函数名,当前传的参数;然后再执行,再打印函数返回值。这就是为了记录一个功能的前因后果,好排查问题!!!
练习:搬家具
class Furniture():
def __init__(self,name,area):
self.name=name
self.area=area
class Hourse():
def __init__(self,address,area):
#地理位置
self.address=address
#房屋面积
self.area=area
#剩余面积
self.free_area=area
self.furniture=[]
def add_furniture(self,item):
if self.free_area>=item.area:
self.furniture.append(item.name)
#剩余面积=剩余面积减去新增的家具面积
self.free_area-=item.area
else:
print("家具太大,房子太拥挤啦,装不下~")
def __str__(self):
return f'该房子地理位置在{self.address},房屋面积{self.area},剩余面积{self.free_area},家具有{self.furniture}'
doublebed=Furniture('双人床',12)
singlebed=Furniture('单身奢华贵族床',50)
house=Hourse('深圳坪洲',12)
# house.add_furniture(doublebed)
house.add_furniture(singlebed)
# print(house)
#house2=Hourse('深圳',1212,doublhouebed)
结果:
五、面向对象三大特征
1.面向对象三大特征:
1)封装
将属性和方法书写到类里面操作。封装可以为属性和方法添加私有权限
2)继承
子类默认继承父类的所有属性和方法;子类可以重写父类的属性和方法
3)多态
同一对象操作可以作用域不同的对象。
传入不同的对象,产生不同的效果
好处:调用灵活,更容易编写出通用的编程,以适应需求的不断变化。
实现步骤:
1)定义父类,提供公共方法
2)定义子类,重写父类方法
3)传递子类对象给调用者,可以看到不同子类的执行效果不同。
class Aminimal():
def work(self):
pass
class Dog(Aminimal):
def work(self):
print('汪汪汪')
class Cat(Aminimal):
def work(self):
print('喵喵喵')
class People():
def play(self,aminimal): #传入不同的对象参数,对应的结果也不同
aminimal.work()
cat=Cat()
dog=Dog()
peo=People()
peo.play(cat)
peo.play(dog)
六、面向对象–继承
python面向对象的继承指的是多个类之间的所属关系。即子类默认继承父类的所有属性和方法。
python不同的解释器,有两种类:经典类和新式类(python3.0支持)
经典类:
class 类名:
代码
新式类:
class 类名(object【父类名称1,父类名称2】):
代码
当一个类有多个父类的时候,并且这两个父类有相同名称的属性或方法时,默认使用的是第一个父类同名的属性和方法
如果子类和父类拥有同名的属性和方法(子类重写父类同名属性和方法),子类对象调用到的属性和方法是子类中的。
想要看清类之间的继承关系,可以通过类名._ mro _方法查看
想要调用父类中的同名方法。通过在子类将子类和父类的同名方法写成一个新的方法,通过调用不同的新的方法实现调用父类还是子类。
class parent_class():
def __init__(self):
self.kongfu='父类武功秘籍'
def makecake(self):
print(f'运用{self.kongfu}方法')
class son_class(parent_class):
def __init__(self):
self.kongfu='独创的武功秘籍'
def makecake(self):
#调用自己初始化原因:如果不加自己的初始化,则kongfu属性值是上一次调用的init内的kongfu属性值
self.__init__()
print(f'运用{self.kongfu}方法')
#需要分别调用子类和父类的方法重定义
def parent_menthod(self):
parent_class.__init__(self)
parent_class.makecake(self)
def son_method(self):
# son_class.__init__(self)
son_class.makecake(self)
new1=son_class()
new1.makecake()
new1.son_method()
new1.parent_menthod()
new1.makecake() #若子类的方法未调用初始化,则会默认使用上一次调用的值,结果:运用父类武功秘籍方法
结果:
运用独创的武功秘籍方法
运用独创的武功秘籍方法
运用父类武功秘籍方法
运用独创的武功秘籍方法
class tusun(son_class):
pass
new2=tusun()
new2.son_method()
new2.parent_menthod()
结果:
运用独创的武功秘籍方法
运用父类武功秘籍方法
super()调用父类方法:
使用方法:
1.super(当前类名,self).函数()
2.super().函数()
使用super()可以自动查找父类,调用顺序遵循_ mro _类属性的顺序。比较适合单继承使用。
class parent_class():
def __init__(self):
self.kongfu='父类武功秘籍'
def makecake(self):
print(f'运用{self.kongfu}方法')
class son_class(parent_class):
def __init__(self):
self.kongfu='独创的武功秘籍'
def makecake(self):
#调用自己初始化原因:如果不加自己的初始化,则kongfu属性值是上一次调用的init内的kongfu属性值
self.__init__()
print(f'运用{self.kongfu}方法')
super().__init__()
super().makecake()
class tusun(son_class):
# 一次性调用父类的方法
def old_two_method(self):
super().__init__()
super().makecake()
new2=tusun()
new2.old_two_method()
result:
运用独创的武功秘籍方法
运用父类武功秘籍方法
私有属性和私有方法的定义用两个下划线即可,如:self._ _ money=100 私有东西不能继承。
class son_class(parent_class):
def __init__(self):
# 私有属性和方法
self.__money = 100
def __info_siyou(self):
print(f'这是son的私有方法')
```php
私有属性可以通过get()方法设置获取
def get_money(self):
return self.__money
类里设置get,set方法,用于在类外获取或修改私有属性值:
class son_class(parent_class):
def __init__(self):
# 私有属性和方法
self.__money = 100
def get_money(self):
return self.__money
def set_money(self,money):
self.__money=money
class tusun(son_class):
pass
new2=tusun()
print(new2.get_money())
new2.set_money(200)
print(new2.get_money())
result:
100
200
六、异常
当检测到一个错误时,解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的异常
'''
语法:
try:
可能发生错误的代码
except:
如果出现异常执行的代码
'''
try:
open('test.txt','r')
except:
open('test.txt','w')
捕获异常处理
'''
语法:
try:
可能发生错误的代码
except 异常类型:
捕获到异常需要做的处理
'''
try:
print(num)
except NameError:
print('未定义')
如果尝试执行的代码异常类型和捕获的异常类型不一致,则无法捕获异常
一般try下只能放一行尝试执行的代码
捕获多个异常类型,并捕获异常描述信息
try:
print(1/0)
except (ZeroDivisionError,NameError) as result: #显示异常结果
print(result)
结果:
division by zero
若要捕获所有的异常,用Exception 捕获,它是所有程序异常类的父类
try:
print(1/0)
except Exception as result:
print(result)
else语句的解释:
try:
print(1)
except Exception as result:
print(result)
else:
print('程序没有异常,也会执行else')
结果:
1
程序没有异常,也会执行else
finally语句,无论是否有异常都要执行的代码
import fileinput
try:
f = open('text.txt','r')
except Exception:
f = open('text.txt','w')
else:
print('程序没有异常')
finally:
f.close()
异常传递
'''
语法:
try:
可能发生错误的代码
except 异常类型:
捕获到异常需要做的处理
'''
import fileinput
import time
try:
f = open('text.txt')
try:
while True:
conf=f.readline()
#判断,如果读取到的行长度为0,说明没有内容了
if len(conf)==0:
break
time.sleep(5)
print(conf)
except:
#在命令提示符中,如果按下ctrl+c则是终止结束程序
print('意外终止')
except Exception:
print('文件不存在')
自定义异常提示
# 1.自定义异常率
# 2.抛出异常
# 3.给出异常提示
class ShortInputError(Exception): #必须要继承Exception类
def __init__(self,shortlen,minlen):
self.shortlen=shortlen
self.minlen=minlen
#设置抛出异常的描述信息-----必写
def __str__(self):
return f'您输入的密码密码长度{self.shortlen}太短,至少需要{self.minlen}位密码'
def main():
try:
con=input('请输入密码:')
#如果密码长度小于3,则抛出异常
if len(con)<3:
raise ShortInputError(len(con),3)
except Exception as result:
print(result)
else:
print("密码输入完成")
main() 函数调用
结果:
请输入密码:1
您输入的密码密码长度1太短,至少需要3位密码
七、模块
导入模块的三种方式:
1.import 模块名,调用的时候要模块名.功能来调用
2.from 模块名 import 功能名 , 调用的时候直接用功能调用就行
3.from 模块名 import * , 功能调用不需要模块名.功能,直接功能名即可
导入模块的别名的形式:
模块别名:import 模块名 as 别名
功能别名:from 模块名 import 功能 as 别名
定义别名之后,只能使用别名,不能使用模块名!!
制作模块
每个python文件都可以作为一个模块,模块的名字就是文件的名字。也就是说自定义模块名必须标志符密码规则。
步骤:
1.定义模块(模块其实就是定义的一个类(py文件)及包含的方法内容,方法在其他地方被调用)
2.测试模块
3.调用模块
def test(a,b):
print(a+b)
#用于测试的作用,__name__是系统变量,是模块的标识符。如果是自身模块是__main__,如果是再其他模块下,则是原始模块名称
if __name__ =='__main__':
test(1,1)
模块定位顺序:
1.当前目录
2.shell变量pythonpath下的每个目录
3.python默认路径。UNIX下,默认路径一般为/usr/local/lib/python/模块搜索路径存储在system模块的sys.path变量中。
注意:
1.文件名不要与已有的模块同名
2.使用from模块名 import 功能的时候,如果功能名重复,调用到的是最后定义或导入的功能。
all列表
如果一个模块文件中有_ all _变量,当使用from xx import * 时,只能导入这 个列表中的函数元素。
例如在一个类中定义了两个函数,但是all列表中只有包含一个函数,此时另外的导入类就只能调用all列表中有的函数,其他的无法调用。
__all__=['testA']
def testA():
print('A')
def testNB():
print('B')
包
包就是放文件的文件夹,新建包后,包内部会自动创建_ init _.py文件,这个文件控制着包的导入行为
导包方法一:
import 包名.模块名
导包方法二:
from 包名 import *
注意:必须在 _ _init_ _.py 文件中添加_ _all_ _ =['调用函数名'],控制允许导入的模块列表