知识点小结
该处仅用于快速复习,详细知识及代码如何编写点请跳过。
Python中支持两种编程方式来写代码,分别是:函数式编程、面向对象式编程。
声明一个类:class Ok: 或class Ok() 或 class Ok(object) ,py3默认继承object,新式类,py2,经典类。
1.根据类型创建一个对象,内存的一块区域 。
2.执行__init__方法,模块会将创建的那块区域的内存地址当self参数传递进去。
self是什么?
self是一个参数,在通过 对象.方法 的方式去执行方法时,这个参数会被python自动传递(值为调用当前方法的对象)
即使第一个参数不写self,如改写成qqqq,此时qqqq即为self。
什么是对象?
对象,基于类实例化出来”一块内存“,默认里面没有数据;经过类的 __init__方法,可以在内存中初始化一些数据。
什么时候用面向对象编程好一些?
仅做数据封装。
封装数据 + 方法再对数据进行加工处理。
创建同一类的数据且同类数据可以具有相同的功能(方法)。
三大特性:封装 继承 多态
- 封装,将方法封装到类中 或 将数据封装到对象中,便于以后使用。
- 继承,将类中的公共的方法提取到基类中去实现。
- 多态,Python默认支持多态(这种方式称之为鸭子类型),最简单的基础下面的这段代码即可。
def func(arg):
v1 = arg.copy() # 浅拷贝 即要能执行这种方法,不然会报错。
print(v1)
成员: 实例变量 类变量,绑定方法 类方法 静态方法,属性。
class Ok: country = 'china' def __init__(self,name): self.name = name def fuc1(self): print('这是绑定方法') @classmethod def fuc2(cls): print('这是类方法') @staticmethod def fuc3(): print('这是静态方法') @property def fuc4(self): print('这是属性')
分清楚每一步修改或者增加的是那里的对象
class People: country = 'china' def __init__(self, name='未输入', age=18): self.name = name self.age = age def fuc1(self): print(self.name, self.age) person1 = People('卢本伟', 18) print(person1.country) # china 对象中没有 会向类变量中寻找 person1.name = 'lbw' #将对象中的name变量修改 person1.country = '中国' #对象中没有country 会创建一个country对其进行赋值 print(person1.name, person1.age, person1.country, People.country) #lbw 18 中国 china
class People: country = 'china' def __init__(self, name='未输入', age=18): self.name = name self.age = age def fuc1(self): print(self.name, self.age, self.country) class Ok(People): name = 'nihao' def fuc2(self): print(self.name, self.age, self.country) @classmethod def fuc3(cls): print(cls.name) person = Ok('周润发', 19) # 相当于自己的类在有一个init person.fuc1() # 周润发 19 china self是自己的优先在Ok里找 person.fuc2() # 周润发 19 china person.fuc3() # 你好 Ok.country = '韩国' #添加类变量 优先找实例变量->自己的类变量->父类类变量 Ok.name = '不知道' person.fuc1() # 周润发 19 韩国 person.fuc2() # 周润发 19 韩国 person.name = '卢本伟' person.country = '日本' # 对象中添加了实例变量country print(People.country, Ok.country) # china 韩国 person.fuc1() # 卢本伟 19 日本 person.fuc2() # 卢本伟 19 日本
编写属性的方式有哪些?
(点击目录 属性 跳转)
成员修饰符(公有/私有)
对于私有成员,在成员名字前加两道下划线__,即为私有。
class Ok: def __init__(self, name='未输入', age=18): self.__name = name self.age = age def __fuc1(self): pass def fuc2(self): self.__name = 'lbw' print(self.__name) class Yes(Ok): def fuc3(self): print(self.__name) #这样不执行不会报错 k = Ok('周润发') k.fuc2() #lbw print(k.age) #18 kk = Yes() kk.fuc3() #在这里会报错 子类也无法调用父类的自私有变量/方法
注意:要看self写在哪个类里
class Base(object): def __data(self): print("base.__data") def num(self): print("base.num") self.__data() class Foo(Base): def func(self): self.num() obj = Foo() obj.func() ''' base.num base.__data 虽然self一直都是Foo实例化的对象的,但其在调用__data时,是在Base类内部调用的 '''
写在最后,按理说私有成员是无法被外部调用,但如果用一些特殊的语法也可以(Flask源码中有这种写法,大家写代码不推荐这样写)。
class Foo(object): def __init__(self): self.__num = 123 self.age = 19 def __msg(self): print(1234) obj = Foo() print(obj.age) print(obj._Foo__num) obj._Foo__msg()
特殊成员
new init call str dict add getitem setitem delitem enter exit iter
要明白每个的作用 去目录跳转查看 迭代器 生成器 可迭代对象 等的内容
class IT(object): def __init__(self): self.counter = 0 def __iter__(self): return self def __next__(self): self.counter += 1 if self.counter == 3: raise StopIteration() return self.counter class Foo(object): def __iter__(self): return IT() obj = Foo() # 可迭代对象 for item in obj: # 循环可迭代对象时,内部先执行obj.__iter__并获取迭代器对象;不断地执行迭代器对象的next方法。 print(item)
mro和c3算法
继承关系 :从左到右,深度优先,大小钻石,留住顶端
内置函数补充:classmethod、staticmethod、property、callable、super 、type 、isinstance 、issubclass
异常处理写法和细分
面向对象基础
目标:了解面向对象并可以根据面向对象知识进行编写代码。
概要:
- 初识面向对象
- 三大特性(面向对象)
- 封装
- 继承
- 多态
- 再看数据类型
1. 初识面向对象
想要通过面向对象去实现某个或某些功能时需要2步:
- 定义类,在类中定义方法,在方法中去实现具体的功能。
- 实例化类并的个一个对象,通过对象去调用并执行方法。
class Message: def send_email(self, email, content): data = "给{}发邮件,内容是:{}".format(email,content) print(data) msg_object = Message() # 实例化一个对象 msg_object,创建了一个一块区域。 msg_object.send_email("xxxx@live.com","注册成功")
注意:1.类名称首字母大写&驼峰式命名;2.py3之后默认类都继承object;3.在类种编写的函数称为方法;4.每个方法的第一个参数是self。
类中可以定义多个方法,例如:
class Message: def send_email(self, email, content): data = "给{}发邮件,内容是:{}".format(email, content) print(data) def send_wechat(self, vid, content): data = "给{}发微信,内容是:{}".format(vid, content) print(data) msg_object = Message() msg_object.send_email("xxxxx@live.com", "注册成功") msg_object.send_wechat("lbw", "注册成功")
你会发现,用面向对象编程写的类有点像归类的意思:将某些相似的函数划分到一个类中。
但,这种编写方式让人感觉有些鸡肋,直接用 函数 写多好呀。对吧?
别着急,记者往下看。
1.1 对象和self
在每个类中都可以定义个特殊的:__init__ 初始化方法,在实例化类创建对象时自动执行,即:对象=类()。
class Message: def __init__(self, content): self.data = content def send_email(self, email): data = "给{}发邮件,内容是:{}".format(email, self.data) print(data) def send_wechat(self, vid): data = "给{}发微信,内容是:{}".format(vid, self.data) print(data) # 对象 = 类名() # 自动执行类中的 __init__ 方法。 # 1. 根据类型创建一个对象,内存的一块 区域 。 # 2. 执行__init__方法,模块会将创建的那块区域的内存地址当self参数传递进去。 往区域中(data="注册成功") msg_object = Message("注册成功") msg_object.send_email("xxxxx@live.com") # 给xxxxx@live.com发邮件,内容是:注册成功 msg_object.send_wechat("lbw") # 给lbw发微信,内容是:注册成功
通过上述的示例,你会发现:
对象,让我们可以在它的内部先封装一部分数据,以后想要使用时,再去里面获取。
self,类中的方法需要由这个类的对象来触发并执行( 对象.方法名 ),且在执行时会自动将对象当做参数传递给self,以供方法中获取对象中已封装的值。
注意:除了self默认参数以外,方法中的参数的定义和执行与函数是相同。
当然,根据类也可以创建多个对象并执行其中的方法,例如:
class Message: def __init__(self, content): self.data = content def send_email(self, email): data = "给{}发邮件,内容是:{}".format(email, self.data) print(data) def send_wechat(self, vid): data = "给{}发微信,内容是:{}".format(vid, self.data) print(data) msg_object = Message("注册成功") msg_object.send_email("lbw@live.com") # 给lbw@live.com发邮件,内容是:注册成功 msg_object.send_wechat("xxx") login_object = Message("登录成功") login_object.send_email("lbw@live.com") # 给lbw@live.com发邮件,内容是:登录成功 login_object.send_wechat("xxx")
面向对象的思想:将一些数据封装到对象中,在执行方法时,再去对象中获取。
函数式的思想:函数内部需要的数据均通过参数的形式传递。
self,本质上就是一个参数。这个参数是Python内部会提供,其实本质上就是调用当前方法的那个对象。
对象,基于类实例化出来”一块内存“,默认里面没有数据;经过类的 __init__方法,可以在内存中初始化一些数据。
1.2 常见成员
在编写面向对象相关代码时,最常见成员有:
- 实例变量,属于对象,只能通过对象调用。
- 绑定方法,属于类,通过对象调用 或 通过类调用。
注意:还有很多其他的成员,后续再来介绍。
class Person: def __init__(self, n1, n2): # 实例变量 self.name = n1 self.age = n2 # 绑定方法 def show(self): msg = "我叫{},今年{}岁。".format(self.name, self.age) print(msg) def all_message(self): msg = "我是{}人,我叫{},今年{}岁。".format(Person.country, self.name, self.age) print(msg) def total_message(self): msg = "我是{}人,我叫{},今年{}岁。".format(self.country, self.name, self.age) print(msg) # 执行绑定方法 p1 = Person("lbw",20) p1.show() # 或 # p1 = Person("lbw",20) # Person.show(p1) # 初始化,实例化了Person类的对象叫p1 p1 = Person("lbw",20)
1.3 应用示例
将数据封装到一个对象,便于以后使用。
class UserInfo: def __init__(self, name, pwd,age): self.name = name self.password = pwd self.age = age def run(): user_object_list = [] # 用户注册 while True: user = input("用户名:") if user.upper() == "Q": break pwd = input("密码") # user_object对象中有:name/password user_object = UserInfo(user, pwd,19) # user_dict = {"name":user,"password":pwd} user_object_list.append(user_object) # user_object_list.append(user_dict) # 展示用户信息 for obj in user_object_list: print(obj.name, obj.password) 总结: - 数据封装到对象,以后再去获取。 - 规范数据(约束)
- 注意:用字典也可以实现做封装,只不过字典在操作值时还需要自己写key,面向对象只需要
.即可获取对象中封装的数据。 - 将数据分装到对象中,在方法中对原始数据进行加工处理。
user_list = ["用户-{}".format(i) for i in range(1,3000)] # 分页显示,每页显示10条 while True: page = int(input("请输入页码:")) start_index = (page - 1) * 10 end_index = page * 10 page_data_list = user_list[start_index:end_index] for item in page_data_list: print(item) class Pagination: def __init__(self, current_page, per_page_num=10): self.per_page_num = per_page_num if not current_page.isdecimal(): self.current_page = 1 return current_page = int(current_page) if current_page < 1: self.current_page = 1 return self.current_page = current_page def start(self): return (self.current_page - 1) * self.per_page_num def end(self): return self.current_page * self.per_page_num user_list = ["用户-{}".format(i) for i in range(1, 3000)] # 分页显示,每页显示10条 while True: page = input("请输入页码:") # page,当前访问的页码 # 10,每页显示10条数据 # 内部执行Pagination类的init方法。 pg_object = Pagination(page, 20) page_data_list = user_list[ pg_object.start() : pg_object.end() ] for item in page_data_list: print(item)
还有这个示例:将数据封装到一个对象中,然后再方法中对已封装的数据进行操作。
import os import requests class DouYin: def __init__(self, folder_path): self.folder_path = folder_path if not os.path.exists(folder_path): os.makedirs(folder_path) def download(self, file_name, url): res = requests.get( url=url, headers={ "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 FS" } ) file_path = os.path.join(self.folder_path, file_name) with open(file_path, mode='wb') as f: f.write(res.content) f.flush() def multi_download(self, video_list): for item in video_list: self.download(item[0], item[1]) if __name__ == '__main__': douyin_object = DouYin("videos") douyin_object.download( "罗斯.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg" ) video_list = [ ("a1.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300fc20000bvi413nedtlt5abaa8tg"), ("a2.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0d00fb60000bvi0ba63vni5gqts0uag"), ("a3.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg") ] douyin_object.multi_download(video_list)
根据类创建多个对象,在方法中对对象中的数据进行修改。
class Police: """警察""" def __init__(self, name, role): self.name = name self.role = role if role == "队员": self.hit_points = 200 else: self.hit_points = 500 def show_status(self): """ 查看警察状态 """ message = "警察{}的生命值为:{}".format(self.name, self.hit_points) print(message) def bomb(self, terrorist_list): """ 投炸弹,炸掉恐怖分子 """ for terrorist in terrorist_list: terrorist.blood -= 200 terrorist.show_status() class Terrorist: """ 恐怖分子 """ def __init__(self, name, blood=300): self.name = name self.blood = blood def shoot(self, police_object): """ 开枪射击某个警察 """ police_object.hit_points -= 5 police_object.show_status() self.blood -= 2 def strafe(self, police_object_list): """ 扫射某些警察 """ for police_object in police_object_list: police_object.hit_points -= 8 police_object.show_status() def show_status(self): """ 查看恐怖分子状态 """ message = "恐怖分子{}的血量值为:{}".format(self.name, self.blood) print(message) def run(): # 1.创建3个警察 p1 = Police("lbw", "队员") p2 = Police("uzi", "队员") p3 = Police("mlxg", "队长") # 2.创建2个匪徒 t1 = Terrorist("alex") t2 = Terrorist("eric") # alex匪徒射击mlxg警察 t1.shoot(p3) # alex扫射 t1.strafe([p1, p2, p3]) # eric射击uzi t2.shoot(p2) # lbw炸了那群匪徒王八蛋 p1.bomb([t1, t2]) # lbw又炸了一次alex p1.bomb([t1]) if __name__ == '__main__': run()
总结:
- 仅做数据封装。
- 封装数据 + 方法再对数据进行加工处理。
- 创建同一类的数据且同类数据可以具有相同的功能(方法)。