这里写自定义目录标题
- 一、学习内容概述
- (一)函数式和面向对象的区别
- 1、函数式
- 2、面向对象
- (二)网络编程
- (三)并发编程
- 二、面向对象
- (一)初识面向对象
- 1、对象和self
- 2、应用示例
- (1)示例一
- (2)示例二
- (3)示例三
- 3、常见成员
- (二)三大特性
- 1、封装
- 2、继承
- 3、多态
一、学习内容概述
python支持两种编程方式,函数式和面向对象。
(一)函数式和面向对象的区别
1、函数式
#定义函数,在函数中实现功能
def func():
print('一个New bee的功能')
2、面向对象
#面向对象的编程
#定义类
class Foo(object):
#在类中定义方法
def func(self):
print('一个New bee的功能')
#实例化类的对象
obj = Foo()
#执行类中的方法
obj.func()
函数式推荐初学者使用,上手快且逻辑清晰。面向对象推荐又一些代码经验后使用。
(二)网络编程
允许我们的程序通过网络来进行数据交互和传输
(三)并发编程
一个程序想要执行的速度更快必须掌握并发编程的相关知识。
二、面向对象
(一)初识面向对象
定义类注意:1、类名称首字母大写&驼峰式命名(每个单词的首字母都需要大写);2、在类中有缩进的函数,定义为方法(方法中第一个默认为self),如果需要执行方法,首先需要实例化对象,然后在类中实现具体的方法。
class Message():
def send_email(self, email, content):
data = '给{}发邮件,内容是:{}'.format(email, content)
print(data)
msg_object = Message() #实例化对象,相当于是创建了一块区域
msg_object.send_email("gao.yuxing@outlook.com", "注册成功") #实现了方法
一共四个步骤:1、创建类;2、创建方法;3、创建对象(实例化);4、通过对象调用方法。
在同一个类中,可以插入多个方法,有点归类的意思,将相似功能的函数放在一个类别中。
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("gao.yuxing@outlook.com", "注册成功") #实现了方法
msg_object.send_wechat("高宇星", "注册成功")
1、对象和self
在每个类中,都可以定义一个特殊的初始化方法,在实例化类创建对象时自动执行,即“对象=类()”。创建对象的目的是:1、帮助我们存储数据;2、对象可以帮助我们调用类中的方法,并将自己当作参数传递过去。
同一个类中可以有多个对象。
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("注册成功")
#实例化对象,相当于是创建了一块区域;
#根据__init__方法,模块会将创建的那块区域的内存地址当成self参数传递进去
msg_object.send_email("gao.yuxing@outlook.com") #实现了方法
msg_object.send_wechat("高宇星")
login_object = Message("登陆成功")
login_object.send_email("gao.yuxing@outlook.com")
login_object.send_wechat("高宇星")
self:本质上就是一个参数,这个参数是python内部提供的,其实本质上就是调用当前方法的那个对象。对象:是基于类实例化出来的“一块区域”,默认里面是没有数据的。经过类的init方法可以在内存中初始化一些数据。
2、应用示例
(1)示例一
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("注册成功")
#实例化对象,相当于是创建了一块区域;
#根据__init__方法,模块会将创建的那块区域的内存地址当成self参数传递进去
msg_object.send_email("gao.yuxing@outlook.com") #实现了方法
msg_object.send_wechat("高宇星")
login_object = Message("登陆成功")
login_object.send_email("gao.yuxing@outlook.com")
login_object.send_wechat("高宇星")
class UserInfo():
def __init__(self, name, pwd):
self.name = name
self.password = pwd
def run():
user_object_list = []
#用户注册
while True:
user = input('用户名:')
if user.upper() == "Q":
break
pwd = input("密码")
user_object = UserInfo(user, pwd)
user_object_list.append(user_object)
for obj in user_object_list:
print(obj.name, obj.password)
#run()
'''
用户名:liyuxing
密码151265mylove
用户名:gaogaogao
密码8529
用户名:dididi
密码123456
用户名:qqq
密码123
用户名:q
liyuxing 151265mylove
gaogaogao 8529
dididi 123456
qqq 123
'''
总结:将数据封装到对象以后再获取;规范数据(约束)
(2)示例二
分页显示数据案例:
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 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 = int(input("请输入页码:"))
print(type(page))
page_object = Pagination(page, 20)
page_object_list = user_list[page_object.start():page_object.end()]
for item in page_object_list:
print(item)
(3)示例三
#游戏
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):
'''查看警察的状态'''
messgae = "警察{}的生命值为:{}".format(self.name, self.hit_points)
print(messgae)
def bomb(self, terrorist_list):
'''投炸弹,炸掉恐怖分子'''
for terrorist in terrorist_list:
terrorist = Terrorist(terrorist)
terrorist.blood -= 200
terrorist.show_status()
'''
p1 = Police("高宇星", "队员")
p1.show_status()
p2 = Police("闫雯", "队员")
p2.show_status()
#p2.bomb(["alex", "李杰"])
'''
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()
def strafe(self, police_object_list):
'''扫射某些警察'''
for police_object in police_object_list:
#police_object = Police()
police_object.hit_points -= 8
police_object.show_status()
def show_status(self):
'''查看恐怖分子状态'''
message = '恐怖分子{}的血量值为:{}'.format(self.name, self.blood)
print(message)
#t1 = Terrorist('alex')
#print(t1.blood)
#terrorist_list = ['alex', '李杰']
'''
for i in terrorist_list:
t = Terrorist(i)
t.blood -= 200
t.show_status()
'''
'''
t2 = Terrorist('李杰', 200)
t2.show_status()
p1.bomb(terrorist_list)
'''
def run():
#1、创建3个警察
p1 = Police("高宇星", "队员")
p2 = Police("闫雯", "队员")
p3 = Police("丁凯乐", "队员")
#2、创建2个匪徒
t1 = Terrorist('alex')
t2 = Terrorist('李杰')
#3、alex扫射
t1.strafe([p1, p2, p3])
t2.shoot(p2)
p1.bomb([t1, t2])
if __name__ == '__main__':
run()
'''
警察高宇星的生命值为:192
警察闫雯的生命值为:192
警察丁凯乐的生命值为:192
警察闫雯的生命值为:187
恐怖分子<__main__.Terrorist object at 0x7f8ea7ff1bb0>的血量值为:100
恐怖分子<__main__.Terrorist object at 0x7f8ea7ff1c10>的血量值为:100
'''
总结:在什么时候使用面向对象?
1、仅仅需要做数据封装;
2、封装数据+方法 再对数据进行处理;
3、创建同一类的数据且同类数据可以具有相同的功能。
3、常见成员
绑定方法和实例对象的区别
class Person():
def __init__(self, n1, n2):
#实例变量,实例化了一个Person类的对象,属于对象,不属于类,只能通过对象来调用
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('高宇星', 18)
p1.show() #通过对象来触发
#执行绑定方法
Person.show(p1) #通过类直接来触发,self通过自己手动进行传递,方法较为非主流
(二)三大特性
面向对象的编程在很多语言中都存在,这种编程方式有三大特性:封装、继承、多态。
1、封装
封装主要体现在两个方面:1、将同一类方法封装到同一个类中,例如示例三,将经常所有的功能封装在一起,将匪徒所有的功能也封装在一起;2、将数据封装到对象,在实例化一个对象的基础上,可以通过__init__()初始化方法在对象中封装一些对象,便于后续使用。
2、继承
传统理念之中:儿子可以继承父亲的财产。同样的,在面向对象的编程中也有同样的概念:子类可以继承父类中的方法和变量。父类———子类,基类——派生类。
class Base():
def func(self):
print("Base.func")
class Son(Base):
def show(self):
print("Son.show")
s1 = Son()
s1.show() #Son.show
s1.func() #不是直接在父类Base中调用,而是优先在自己类中调用,自己的类中没有才会去父类里找
s2 = Base()
s2.func()
是哪个类的对象,就优先调用哪个类的方法,为了说明这个问题,举了下面这个例子。
class Base():
def f1(self):
print("before")
self.f2()
print("base.f1")
def f2(self):
print("base.f2")
class Foo(Base):
def f2(self):
print("foo.f2")
obj = Foo()
obj.f1()
'''
before
foo.f2 #obj是Foo类下的,本身是没有f1的,所以会去父类Base中找f1,f1中有self.f2(),这里的self仍然是Foo类中的对象,所以调用的是Foo类中的f2方法
base.f1
'''
obj = Base()
obj.f1()
'''
before
base.f2
base.f1
'''
多继承问题:同样是优先在自己类中找方法,当自己的类中没有时,从父类中找,优先从第一个父类中找起!左边的父类优先于右边的父类!当左边的类中没有方法时,才去右边的类中寻找。
class TCPServer:
def f1(self):
print("TCPServer")
class ThreadingMixIn:
def f1(self):
print("ThreadingMixIn")
class ThreadingMixInTCPServer(ThreadingMixIn, TCPServer):
def run(self):
print('before')
self.f1()
print('after')
obj = ThreadingMixInTCPServer()
obj.run()
'''
before
ThreadingMixIn
after
'''
class BaseServer():
def server_forever(self, requests, client_adress, poll_interval=0.5):
self._handle_request_noblock(requests, client_adress)
def _handle_request_noblock(self, requests, client_adress):
self.process_request(requests, client_adress)
def process_request(self, requests, client_adress):
pass
class TCPServer(BaseServer):
pass
class ThreadingMixIn():
def process_request(self, requests, client_adress):
pass
class ThreadingMixInTCPServer(ThreadingMixIn, TCPServer):
pass
requests='abc'
client_adress = "12345"
obj = ThreadingMixInTCPServer()
#子类中没有,ThreadingMixIn中没有,TCPServer没有,但是TCPServer的父类BaseServer中有server_forever,
#在执行这个方法的时候,还是要从子类开始寻找_handle_request_noblock方法,但是找来找去也只有BaseServer中有
#继而要执行process_request函数,但是也要先从子类ThreadingMixInTCPServer中开始寻找,其第一优先父类ThreadingMixIn()中有该方法
#因此最终执行的是ThreadingMixIn()中的process_request方法。
obj.server_forever(requests, client_adress)
总结:
- 执行对象.方法时,优先去当前对象所关联的类中找,没有的话才去父类中查找;
- python支持多继承:先继承左边,再支持右边;
- self到底是谁?这是关键的问题,优先去self对应的类中获取成员,没有就按照继承关系向上查找。
3、多态
python对数据类型没有任何限制,所以它天生支持多态,参数可以是多种类型,只要符合函数的调用类型即可。
在程序设计中,鸭子类型(duck typing)是动态类型的一种风格。在鸭子类型中,关注点在于对戏那个的行为,能做什么,而不关注对象所属的类型,例如:鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟也可以被称为鸭子。
def func(arg):
v1 = arg.copy()
print(v1)
#func(123)
func([11, 22, 33, 44])