"""
模块
# 一、模块导入
## 1. 定义
Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句。
模块让你能够有逻辑地组织你的 Python 代码段。
把相关的代码分配到一个模块里能让你的代码更好用,更易懂。
模块能定义函数,类和变量,模块里也能包含可执行的代码。
包括:内置模块,自定义模块,第三方模块;
## 2. 作用
- 最大的好处是大大提高了代码的可维护性。其次,编写代码不必从零开始。
当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,
包括Python内置的模块和来自第三方的模块。
- 使用模块还可以避免函数名和变量名冲突。
相同名字的函数和变量完全可以分别存在不同的模块中,
因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。
但是也要注意,尽量不要与内置函数名字冲突。
## 3. 模块导入
### import
import导入模块执行的操作:
- 产生一个新的名称空间;
- 在新建的名称空间俩面执行模块(.py)的内容
- 拿到了一个模块名, 执行模块文件产生的名称空间.
### import .... as ...
对于导入的模块重命名
### from .... import ....
from .... import ..... as ....
从模块里面导入函数, 变量, 装饰器等.....
##4. 解决问题
问题: 导入模块时, 模块里面执行代码结果也会显示
解决方法:
__name__, 所在文件没有当作模块导入是, 结果为__main__;
__name__, 所在文件被当作模块导入是, 结果为模块的名称;
# 判断模块是否被导入, 如果没有被导入, 则执行下面的代码.
if __name__ == "__main__":
print("这是写好的模块里面的显示.......")
print(timeit(hello))
print(__name__)
##5. __all__决定用来控制from xxx import *导入的内容
##6. 模块的分类
- 内置模块(random, string.....)
- 自定义模块(自己写的模块)
- 第三方模块(别人写好的模块)
## 7. 如何安装第三方模块
- pip3 install 模块名
导入模块练习
微信聊天机器人
import itchat
import requests
def get_tuling_reponse(_info):
#print(_info)
api_url = 'http://www.tuling123.com/openapi/api'
data ={
'key':'3526d29a41534231a58f7620dd4cad7c',
'info':_info,
'userid':'图灵机器人'
}
# 发送数据到指定网址,获取网址返回的数据
res = requests.post(api_url,data).json()
#print(res,type(res))
# 给用户返回的内容
print(res['text'])
return res['text']
# get_tuling_reponse('给我讲个笑话~')
# get_tuling_reponse('给我讲个故事')
# get_tuling_reponse('cat')
# 时刻监控好友发送的文本消息,并且给予一个回复
# isGroupChat=True 接收群聊消息
# 注册响应事件,消息类型为itchat.content.TEXT,即文本消息
@itchat.msg_register(itchat.content.TEXT,isFriendChat=True)
def text_reply(msg):
# 获取好友发送的文本消息
# 返回同样的文本消息
content = msg['Content']
# 将好友的消息发送给机器人去处理,处理的结果就是返回给好友的消息
returnContent = get_tuling_reponse(content)
return returnContent
itchat.auto_login()
itchat.run()
import os
import itchat
# 在python中执行shell命令
# 1.第一种方式:可以判断命令是否执行成功;
# 返回值为0,执行成功
# 返回值不为0.执行是失败
# os.system('ls')
# res = os.system('hostnamess')
# print(res)
# 2.第二种方式 用来保存命令的执行结果的
# res = os.popen('hostname').read()
# print(res)
@itchat.msg_register(itchat.content.TEXT,isFriendChat=True)
def text_reply(msg):
"""
需求:当我们的文件助手发送消息的时候,执发送的内容
1.如果执行成功,显示执行结果
2.如果执行失败,显示执行失败
:param msg:
:return:
"""
if msg['ToUserName'] == 'filehelper':
# 获取要执行的命令的内容
command = msg['Content']
# 让电脑执行命令代码
# 如果执行成功,返回值是0
if os.system(command) == 0:
res = os.popen(command).read()
result = '[返回值]-命令执行成功,执行结果:\n' + res
itchat.send(result,'filehelper')
# 如果命令执行失败
else:
result = '[返回值]-命令%s执行失败,请重试' %(command)
itchat.send(result,'filehelper')
itchat.auto_login()
itchat.run()
import itchat
# 给指定好友发送消息
itchat.auto_login(hotReload=True)
# 根据好友昵称查找好友的信息,返回值是一个列表,有多个元素
res = itchat.search_friends('***')
#print(res)
# 通过索引获取该好友的详细信息
ly = res[0]['UserName']
while True:
itchat.send('python',toUserName=ly)
面向过程:1--->2
--->3--->4 怎么做
面向对象:4 谁来做
相对于函数来说是一个更大的封装,根据职责将对象所能实现的功能封装到一起
1.确定对象要做的事情(方法->多个)
2.让对象调用方法
植物大战僵尸
向日葵 豌豆射手 僵尸
生命值 生命值 生命值
生产阳光() 发射子弹() 移动()
摇摇晃晃() 咬()
类:是一群具有相同特征和行为事物的一个统称(抽象的-->不能直接使用)
特征:被称为属性
行为:被称为方法
对象:由类创建出来的一个具体的存在,由哪一个类创建出来的
对象,就拥有哪一个类中定义的方法和属性
先有类-->再有对象
类和对象的关系:
类是模板,对象是根据这个模板创建出来的,先有类再有对象
类只需要有一个,对象可以有很多个
不同对象(由同一类创建出来的对象)之间的属性可以不相同
类中定义了什么属性和方法,使用这个类创建出来的对象就有什么
属性和方法,不可能多也不可能少
类的设计
1.类名:这类事物的名字(大驼峰命名法)
大驼峰命名法
1.每一个单词的首字母大写
2.单词与单词之间没有下划线
2.属性:这个类创建出来的对象有什么样的特征
3.方法:这个类创建出来的对象有什么样的行为
类名的确定
名词提炼法分析整个业务流程,出现的名词,通常就是找到的类
属性和方法的确定
对 对象的特征描述,通常可以定义成属性
对象具有的行为(动词),通常可以定义为方法
提示:需求中没有涉及的属性或方法在设计类时,不需要考虑
例题演示
# 猫爱吃鱼,猫要喝水
# 哪一个对象调用的方法,self就是哪一个对象的引用
# 在类封装方法的内部,self就表示当前调用方法的对象自己
# 在的方法内部 可以通过 self.属性 来访问对象的属性
class Cat:
def eat(self):
print('%s 爱吃鱼' %(self.name))
def drink(self):
print('猫要喝水')
# 创建猫对象
tom = Cat()
# 在类的外部 对象.属性 可以给对象添加属性
# 不推荐使用
# 对象包含哪些方法,应该封装再类中
tom.name = 'Tom'
print(tom)
addr = id(tom)
print(addr)
# %x:打印格式为十六进制
print('%x' %(addr))
# %d:打印格式为十进制
print('%d' %(addr))
tom.eat()
tom.drink()
初始化方法
我们现在已经知道了使用 类名() 就可以创建一个对象
当使用类名()创建对象时,python的解释器会自动执行以下操作:
1.为对象在内存中分配空间--创建对象
2.调用初始化方法为对象的属性设置初始值--初始化方法(__init__)
这个初始化方法就是__init__方法,__init__是对象的内置方法
__init__方法是专门用来定义一个类具有哪些属性的方法
改造初始化方法--初始化的同时设置初始值:
在开发中,如果希望在创建对象的同时,就设置对象的属性,可以对__init__方法进行改造
1.把希望设置的属性值,定义成__init__方法的参数
2.在方法内部使用self.属性名 = 形参 接收外部传递的参数
3.在创建对象时,使用类名(属性1,属性2..)调用
"""
class Cat:
def __init__(self,new_name):
print('这是一个初始化方法')
# self.属性名 = 属性的初始值
#self.name = 'Tom'
self.name = new_name
# 在类中,任何方法都可以使用self.name
def eat(self):
print('%s 爱吃鱼' %(self.name))
# 使用类名()创建对象的时候,会自动调用初始化方法__init__
tom = Cat('tom')
# 定义属性之后,再用Cat创建对象的时候,都会拥有该属性
print(tom.name)
tom.eat()
lazy_cat = Cat('miaomiao')
print(lazy_cat.name)
lazy_cat.eat()
"""
__del__:对象被从内存中销毁前,会被自动调用
在python中
当使用类名()创建对象时,为对象分配完空间后,自动调用__init__方法
当一个对象被从内存中销毁前(把这个对象从内存中删除掉),
会自动调用__del__方法
应用场景
__init__改造初始化方法,可以让创建对象更加灵活
__del__如果希望在对象被销毁前,再做一些事情,可以考虑一下__del__方法
生命周期(出生到死亡)
一个对象从调用类名()创建,生命周期开始
一个对象的__del__方法一但被调用,生命周期结束
在对象的生命周期内,可以访问对象属性,或者让对象调用方法
"""
class Cat:
def __init__(self, new_name):
self.name = new_name
print('%s 来了' % (self.name))
def __del__(self):
print('%s 走了' % (self.name))
cat1 = Cat('tom')
print(cat1.name)
print('*' * 50)
cat2 = Cat('kimmy')
print(cat2.name)
# del关键字可以删除一个对象,del关键字自己调用__del__方法
del cat2
print('$' * 50)
"""
__str__:返回对象的描述信息 print函数输出使用
在python中,使用python输出对象变量,默认情况下,
会输出这个变量引用的对象是由哪>一个类创建的对象,
以及在内存中的地址(十六进制表示)
如果在开发中,希望使用print输出对象变量时,
能够打印自定义的内容,就可以利用__str__这个内置方法了
"""
class Cat:
def __init__(self,new_name):
self.name = new_name
def __str__(self):
# 必须返回一个字符串
return '我是 %s' %(self.name)
cat = Cat('tom')
print(cat)
练习:
"""
栈的方法
入栈 出栈 取栈顶元素
栈的长度 判断栈是否为空
显示栈的元素
"""
class Stack:
def __init__(self):
self.stack=[]
def push(self,value):
self.stack.append(value)
return True
def pop(self):
if self.stack:
# 获取出栈元素,并返回
item = self.stack.pop()
return item
else:
return False
def top(self):
if self.stack:
return self.stack[-1]
else:
return False
def length(self):
return len(self.stack)
def isempty(self):
return self.stack == []
def view(self):
return ','.join(self.stack)
s = Stack()
print(s.push('1'))
s.push('2')
print(s.view())
item = s.pop()
print(item)
print(s.view())
print(s.isempty())
print(s.length())
"""
封装
1.封装是面向对象编程的一大特点
2.面向对象编程的第一步 将属性和方法封装到一个抽象的类中(为什么说是抽象的,因为类不能直接使用)
3.外界使用类创建对象,然后让对象调用方法
4.对象方法的细节都被封装在类的内部
"""
需求1:
1.小明和小美都爱跑步
2.小美体重45.0公斤
3.小明体重75.0公斤
4.每次跑步都会减少0.5公斤
5.每次吃东西都会增加1公斤
class person:
def __init__(self, new_name, new_weight):
self.name = new_name
self.weight = new_weight
print('%s爱跑步,现在%s公斤' % (self.name, self.weight))
# 在对象方法内部,可以直接访问对象的属性
def run(self):
self.weight -= 0.5
print('%s跑了一次步,还剩%s公斤' % (self.name, self.weight))
def eat(self):
self.weight += 1
print('%s吃了一次东西,还剩%s公斤' % (self.name, self.weight))
# 同一个类创建出多个对象之间,属性互补干扰的
a = person('小明', 75)
b = person('小美', 45)
a.eat()
b.run()
a.eat()
a.run()
b.eat()
需求2:摆放家具
1.房子有户型,总面积和家具名称列表
新房子没有任何的家具
2.家具有名字和战地面积,其中
床:占4平米
衣柜:占2平面
餐桌:占1.5平米
3.将以上三件家具添加到房子中
4.打印房子时,要求输出:户型,总面积,剩余面积,家具名称列表
两个类
家具类
房子类
因为房子类要使用家具 被使用的类 应该先开发
class HouseItem:
# 初始化方法
def __init__(self, name, area):
self.name = name
self.area = area
def __str__(self):
return '[%s]占地%.2f平方米' % (self.name, self.area)
class House:
def __init__(self, house_type, house_area):
self.house_type = house_type
self.house_area = house_area
# 剩余面积
self.free_area = house_area
# 家具名称列表
self.Item_list = []
def __str__(self):
return ('户型:%s\n总面积:%.2f平方米[剩余:%.2f平方米]\n家具:%s'
% (self.house_type, self.house_area, self.free_area, str(self.Item_list)))
def add_item(self, item):
# 1.判断家具的面积
if item.area > self.free_area:
print('%s的面积太大了,无法添加' % (item.name))
return
# 2.将家具的名称添加到列表中
self.Item_list.append(item.name)
# 3.计算剩余面积
self.free_area -= item.area
# 1.创建家具
bed = HouseItem('bed', 4)
print(bed)
chest = HouseItem('chest', 2)
table = HouseItem('table', 1.5)
# 2.创建房子对象
my_home = House('一室一厅', 40)
# 将家具添加到房子里
my_home.add_item(bed)
my_home.add_item(chest)
my_home.add_item(table)
print(my_home)
"""
小结:
1.主程序只负责创建房子对象和家具对象
2.让 房子 对象调用add_item 方法 将家具添加到房子中
3.面积计算,剩余面积,家具列表 等处理都被封装到房子类的内部
1.封装是面向对象编程的一大特点
2.面向对象编程的第一步 -- 将 属性 和 方法 封装到一个抽象的类中
3.外界使用 类 创建 对象,然后让对象调用方法
4.对象方法的细节都被封装在类的内部
"""
演练重点:一个对象的属性可以是另外一个类创建的对象
示例:士兵射击
需求:
1.士兵瑞恩有一把AK47
2.士兵可以开火(士兵开火扣动的是扳机)
3.枪 能够 发射子弹(把子弹发射出去)
4.枪 能够 装填子弹 --增加子弹的数量
Soldier Gun
------- -----------
name model
gun bullet_count
-------------------------------------
__init__(self) __init__(self)
fire(self) add_bullet(self,count)
shoot(self)
"""
class Gun:
def __init__(self,name):
# 枪的型号
self.name=name
# 子弹的数量(调用增加子弹的方法来增加子弹数量)
self.bullet_count=0
def add_bullet(self,count):
self.bullet_count+=count
def fire_bullet(self):
# 判断子弹数量
if self.bullet_count==0:
print('[%s] 没有子弹了...' %(self.name))
return
# 发射子弹 子弹数量变化
self.bullet_count -= 1
print('%s 响了,还剩%s颗子弹 ' %(self.name,self.bullet_count))
class Soldier:
def __init__(self,name):
self.name=name
# 枪(新兵没有枪
self.gun=None
def fire(self):
# 1.判断士兵是否有枪
if self.gun==None:
print('[%s]还没有枪..'%self.name)
return
print('go!go!go!!!')
self.gun.add_bullet(10)
print('%s加了10颗子弹'%self.name)
self.gun.fire_bullet()
# 创建枪对象
ak=Gun('ak47')
# 创建士兵对象
tom=Soldier('Tom')
tom.fire()
# 通过主程序的赋值语句,士兵有枪了
tom.gun=ak
tom.fire()
tom.fire()
"""
面向对象三大特性
1.封装:根据职责将属性和方法封装到一个抽象的类中
2.继承:实现代码的重用,相同的代码不需要重复的写
单继承:
子类拥有父类的所有方法和属性(子类只需封装自己特有的方法)
"""
class Animal:
def eat(self):
print('吃')
def drink(self):
print('喝')
def run(self):
print('跑')
def sleep(self):
print('睡')
class Cat(Animal):
def call(self):
print('喵喵~')
class Hellokitty(Cat):
def speak(self):
print('我可以说日语~')
# 创建猫对象
# fentiao = Cat()
# fentiao.eat()
# fentiao.drink()
# fentiao.run()
# fentiao.sleep()
# fentiao.call()
hk = Hellokitty()
hk.speak()
# 子类可以继承父类的所有属性和方法
hk.call()
# 继承的传递性,子类拥有父类的父类的属性和方法
hk.eat()
hk.drink()
hk.run()
hk.sleep()
"""
专业术语:
Cat类是Animal类的子类,Animal类是Cat类的父类,Cat从Animal类继承
Cat类是Animal类的派生类,Animal类是Cat类的基类,Cat类从Animal类派生
"""
class Animal:
def eat(self):
print('吃')
def drink(self):
print('喝')
def run(self):
print('跑')
def sleep(self):
print('睡')
class Cat(Animal):
def call(self):
print('喵喵~')
class Hellokitty(Cat):
def speak(self):
print('我可以说日语~')
def call1(self):
super().call() # 只在python3中支持
print('#@!#@!#@!')
def call2(self):
# 调用原本在父类中封装的方法
Cat.call(self)
print('1433223')
hk = Hellokitty()
hk.speak()
hk.call1()
hk.call2()
"""
多继承
子类拥有一个父类叫做单继承
子类可以拥有多个父类,并且具有所有父类的属性和方法
例如:孩子会继承自己父亲和母亲的特性
"""
class A:
def test(self):
print('test 方法')
class B:
def demo(self):
print('demo 方法')
class D:
def haha(self):
print('!!!!!!!!!!!!')
class C(A,B,D):
"""多继承可以让子类对象,同时具有多个父类的属性和方法"""
pass
c = C()
c.test()
c.demo()
c.haha()
"""
多继承的注意事项:
问题的提出:
如果不同的父类中存在同名的方法,子类对象在调用方法时,会调用哪一个父类中的方法呢?
提示:开发时,应尽量避免这种容易产生混淆的情况
如果父类之间存在同名的属性或方法,因该尽量避免使用多继承
看的是父代排序
"""
class A:
def test(self):
print('A----test 方法')
def demo(self):
print('A----demo 方法')
class B:
def test(self):
print('B----test 方法')
def demo(self):
print('B----demo 方法')
class C(B,A):
pass
class D(A, B):
pass
c = C()
c.test()
c.demo()
d = D()
d.test()
d.demo()
"""
新式类和旧式(经典)类:
object是Python为所有对象提供的基类,提供有一些内置的属性和方法,可以使用dir函数查看
新式类:以object为基类的类,推荐使用
经典类:不以object为基类的类,不推荐使用
在python3.X中定义的类时,如果没有指定父类,会默认使用object作为基类--python3.x中定义的类都是新式类
在python2.x中定义类时,如果没有指定父类,则不会以object作为基类
####推荐使用新式类#############
新式类和旧式类在多继承时---会影响到方法的搜索顺序
为保证编写的代码能够同时在python2.x和python3.x运行
今后在定义类时,如果没有父类,建议统一继承自object
"""
调用过多情况如:
一个grandson调用了很多次parent类
class Parent(object):
def __init__(self,name):
print('parent的init开始被调用')
self.name = name
print('parent的init结束被调用')
class Son1(Parent):
def __init__(self,name,age):
print('Son1的init开始被调用')
self.age = age
Parent.__init__(self,name)
print('Son1的init结束被调用')
class Son2(Parent):
def __init__(self,name,gender):
print('Son2的init开始被调用')
self.gender = gender
Parent.__init__(self,name)
print('Son2的init结束被调用')
class Grandson(Son1,Son2):
def __init__(self,name,age,gender):
print('grandson的init开始被调用')
Son1.__init__(self,name,age)
Son2.__init__(self,name,gender)
print('grandson的init结束被调用')
gs = Grandson('grandson',18,'男')
print('姓名:',gs.name)
print('年龄:',gs.age)
print('性别:',gs.gender)
新式类:调用的顺序为广度优先
旧式类:调用顺顺序为深度优先
super()类:不重复的调用父类,解决了钻石继承(多继承)的难题
优化方法就是运用super,如:
class Person(object):
def __init__(self):
print('我要好好学习')
def study(self):
print('我要好好学习语言')
class Man(Person):
def __init__(self):
print('我是男的我要好好学习')
def study(self):
print('我要学好数学')
#super().study()
class Womam(Person):
def __init__(self):
print('我是女的我要好好学习')
def study(self):
print('我要学好英语')
super().study()
class Son(Man,Womam):
def __init__(self):
print('我是儿子我要好好学习')
def study(self):
print('我要学好化学和物理')
#Womam.study(self)
#Man.study(self)
super().study()
print(Son.mro())
son1 = Son()
son1.study()
"""
super实现原理:通过c3算法,生成mro(method resolution order)列表,根据列表中元素顺序查询调用
super()不是指父类 而是指以实例化对象为起点的mro序列中的下一个
简洁点的三个原则就是:
子类在父类前,所有类不重复调用,从左到右
"""
在下面可以测试:
class A():
def go(self):
print ("go A go!")
def stop(self):
print ("stop A stop!")
def pause(self):
raise Exception("Not Implemented")
class B(A):
def go(self):
super(B, self).go()
print ("go B go!")
class C(A):
def go(self):
super(C, self).go()
print ("go C go!")
def stop(self):
super(C, self).stop()
print ("stop C stop!")
class D(B,C):
def go(self):
super(D, self).go()
print ("go D go!")
def stop(self):
super(D, self).stop()
print ("stop D stop!")
def pause(self):
print ("wait D wait!")
class E(B,C):
pass
a = A()
b = B()
c = C()
d = D()
e = E()
"""
私有属性和私有方法
应用场景及定义方式
应用场景
在实际开发中,对象的某些属性或方法可能只希望在对象的内部使用,而不希望在外部被访问到
私有属性 就是 对象 不希望公开的 属性
私有方法 就是 方法 不希望公开的 方法
定义方法
在定义属性或方法时,在属性名或者方法名前增加两个下划线,定义的就是私有属性或方法
"""
class Women(object):
def __init__(self,name):
self.name = name
self.__age = 18
def __secret(self):
print('%s 的年龄是 %d' %(self.name,self.__age))
lily = Women('lily')
#print(lily.__age)
lily.__secret()
静态和实例
class Date(object):
def __init__(self,year,month,day):
self.year = year
self.month = month
self.day = day
# 实例方法(默认情况下会传递对象给echo方法)
def echo(self):
print('%s %s %s' %(self.year,self.month,self.day))
# 默认传递类本身给这个方法
@classmethod
def as_string(cls,s):
#print(cls)
month,day,year = s.split('/')
d = cls(year,month,day) # d = Date(2018,10,10)
return d
# 静态方法:不需要创建对象,直接就可以使用
@staticmethod
def is_vaild(s):
# 批量将年月日转换成整型
# month,day,year = s.split('/')
# month,day,year = [int(i) for i in s.split('/')]
month,day,year = map(int,s.split('/'))
return 0<month<=12 and 0<day<=31 and 1<year< 9999
d = Date(2018,10,10)
d.echo()
s = '10/10/2018'
Date.as_string(s).echo()
print(Date.is_vaild(s))
"""
一切皆对象
类也是一个特殊的对象-->类对象
类属性
类方法
"""
"""
需求:定义一个工具类
每件工具都有自己额名字
需要知道使用这个类,创建了多少个工具对象
"""
class Tool(object):
# 1.使用赋值语句定义类属性,记录所有工具的数量
count = 0
def __init__(self,name):
self.name = name
# 让类属性的值 +1
Tool.count += 1
@classmethod
def show_tool_count(cls):
# cls.count 在类方法内部,访问当前的类属性
print('工具对象的数量 %d' %(cls.count))
# 创建工具对象(对象在创建的时候,会自动调用初始化方法)
#print(Tool.count)
tool1 = Tool('斧头')
#tool2 = Tool('榔头')
tool1.show_tool_count()
# 输出工具对象的属性
# 使用 类名.属性名 的方式来获取属性名
#print(Tool.count)
类是一个特殊的对象
Python中一切皆对象
class AAA: 定义的类属性属于类对象
obj1 =AAA: 属于实例对象
在运行程序时,类 同样会被加载到内存
在python中,类 是一个特殊的对象--类对象
在程序运行时,类对象(模板) 在内存中之有一份,使用一个类(模板)可以创建出很多个对象实例
除了封装 实例 的属性和方法外,类对象还可以有自己的属性和方法
1.类属性
2.类方法
通过 类名. 的方式可以直接访问类的属性或者调用类的方法
类方法需要用修饰器@classmethod来标示,告诉解释器这是一个类方法
类方法的第一个参数应该是cls
由哪一个类调用的方法,方法内的cls就是哪一个类的引用
这个参数和实例方法的第一个参数是self类似(哪一个对象调用的方法,self就是哪一个对象的引用)
通过类名调用类方法,调用方法时,不需要传递cls参数
在方法内部
也可以通过cls.访问类的属性
也可以通过cls.调用其他的类方法