第七章节 面向对象-
7.1 面向对象基本格式
```python
定义类
class 类名: def 方法名(self,name): print(name) def 方法名(self,name): print(name) def 方法名(self,name): print(name)
调用类中的方法
1.创建该类的对象
obj = 类名()
2.通过对象调用方法
result = obj.方法名("alex") print(resutl) ```
应用场景:遇到很多函数,需要给函数进行归类和划分。
练习题:
```python class Db: def db_read(self): pass
def db_write(self): pass def db_delete(self): pass def db_update(self): pass
class File: def file_read(self): pass
def file_write(self): pass def file_delete(self): pass def file_update(self): pass
class Redis: def redis_read(self): pass
def redis_write(self): pass def redis_delete(self): pass def redis_update(self): pass
```
7.2 对象的作业
储存一些值,以后方便自己使用。
```python class File: def read(self): with open(self.xxxxx, mode='r', encoding='utf-8') as f: data = f.read() return data
def write(self, content): with open(self.xxxxx, mode='a', encoding='utf-8') as f: f.write(content)
# 实例化了一个File类的对象
obj1 = File()
# 在对象中写了一个xxxxx = 'test.log'
obj1.xxxxx = "test.log"
# 通过对象调用类中的read方法,read方法中的self就是obj。
# obj1.read()
obj1.write('alex')
实例化了一个File类的对象
obj2 = File()
在对象中写了一个xxxxx = 'test.log'
obj2.xxxxx = "info.txt"
通过对象调用类中的read方法,read方法中的self就是obj。
obj2.read()
obj2.write('alex') ```
```python class Person: def show(self): temp = "我是%s,年龄:%s,性别:%s " %(self.name,self.age,self.gender,) print(temp)
p1 = Person() p1.name = '李邵奇' p1.age = 19 p1.gender = '男' p1.show()
p2 = Person() p2.name = '利奇航' p2.age = 19 p2.gender = '男' p2.show() ```
```python class Person: def init(self,n,a,g): # 初始化方法(构造方法),给对象的内部做初始化。 self.name = n self.age = a self.gender = g
def show(self): temp = "我是%s,年龄:%s,性别:%s " % (self.name, self.age, self.gender,) print(temp)
类() 实例化对象,自动执行此类中的 init方法。
p1 = Person('李兆琪',19,'男') p1.show()
p2 = Person('利奇航',19,'男') p2.show() ```
总结:将数据封装到对象,方便使用。
总结
```python 如果写代码时,函数比较多比较乱。 1. 可以将函数归类并放到同一个类中。 2. 函数如果有一个反复使用的公共值,则可以放到对象中。 """
class File: def init(self,path): self.file_path = path
def read(self): print(self.file_path) def write(self,content): print(self.file_path) def delete(self): print(self.file_path) def update(self): print(self.file_path)
p1 = File('log.txt') p1.read()
p2 = File('xxxxxx.txt') p2.read() ```
```python class Person: def init(self,user,pwd,email): self.username = user self.password = pwd self.email = email
USERLIST = [对象(用户/密码/邮箱),对象(用户/密码/邮箱),对象(用户/密码/邮箱)] while True: user = input('请输入用户名:') pwd = input('请输入密码:') email = input('请输入邮箱:') p = Person(user,pwd,email) USERLIST.append(p)
for item in USER_LIST: temp = "我的名字:%s,密码:%s,邮箱%s" %(item.username,item.password,item.email,) print(temp)
########## 面向对象写法
class Person: def init(self,user,pwd,email): self.username = user self.password = pwd self.email = email
def info(self): return "我的名字:%s,密码:%s,邮箱%s" %(item.username,item.password,item.email,)
USERLIST = [对象(用户/密码/邮箱),对象(用户/密码/邮箱),对象(用户/密码/邮箱)] while True: user = input('请输入用户名:') pwd = input('请输入密码:') email = input('请输入邮箱:') p = Person(user,pwd,email) USERLIST.append(p)
for item in USER_LIST: msg = item.info() print(msg) ```
7.3游戏开发
```python class Police: def init(self,name) self.name = name self.hp = 10000
def tax(self): msg = "%s收了个税。" %(self.name,) print(msg) def fight(self): msg = "%s去战了个斗。" %(self.name,)
lsq = Police('李邵奇') zzh = Police('渣渣会') tyg = Police('堂有光')
class Bandit: def init(self,nickname) self.nickname = nickname self.hp = 1000
def murder(self,name): msg = "%s去谋杀了%s" %(self.nickname, name,)
lcj = Bandit('二蛋') lp = Bandit('二狗') zsd = Bandit('狗蛋')
1. 二狗去谋杀渣渣会,二狗生命值-100; 渣渣会生命值减5000
lp.murder(zzh.name) lp.hp = lp.hp - 100 zzh.hp = zzh.hp - 5000 ```
```python class Police: def init(self,name) self.name = name self.hp = 10000
def dao(self,other): msg = "%s个了%s一刀。" %(self.name,other.nickname) self.hp = self.hp - 10 other.hp = other.hp - 50 print(msg) def qiang(self): msg = "%s去战了个斗。" %(self.name,) def quan(self,other): msg = "%s个了%s一全。" %(self.name,other.nickname) self.hp = self.hp - 2 other.hp = other.hp - 10 print(msg)
class Bandit: def init(self,nickname) self.nickname = nickname self.hp = 1000
def qiang(self,other): msg = "%s个了%s一全。" %(self.nickname,other.name) self.hp -= 20 other.hp -= 500
lcj = Bandit('二蛋')
lsq = Police('李邵奇') lsq.dao(lcj) lsq.quan(lcj) lcj.qiang(lsq) ```
7.4 继承
```python
父类(基类)
class Base: def f1(self): pass
子类(派生类)
class Foo(Base): def f2(self): pass
创建了一个字类的对象
obj = Foo()
执行对象.方法时,优先在自己的类中找,如果没有就是父类中找。
obj.f2() obj.f1()
创建了一个父类的对象
obj = Base() obj.f1() ```
问题:什么时候才能用继承?多个类中如果有公共的方法,可以放到基类,避免重复编写
```python class Base: def f1(self): pass
class Foo(Base): def f2(self): pass
class Bar(Base): def f3(self): pass
obj1 = Foo()
obj2 = Bar() ```
继承关系中的查找方法的顺序:
```python
示例一
class Base: def f1(self): print('base.f1')
class Foo(Base): def f2(self): print('foo.f2')
obj = Foo() obj.f1() obj.f2()
示例二
class Base: def f1(self): print('base.f1')
class Foo(Base): def f2(self): self.f1() print('foo.f2')
obj = Foo() obj.f2()
示例三
class Base: def f1(self): print('base.f1')
class Foo(Base): def f2(self): self.f1() print('foo.f2') def f1(self): print('foo.f1')
obj = Foo() obj.f2()
示例四
class Base: def f1(self): self.f2() print('base.f1') def f2(self): print('base.f2') class Foo(Base): def f2(self): print('foo.f2')
obj = Foo() obj.f1()
示例五
class TCPServer: pass class ThreadingMixIn: pass class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass
示例六
class BaseServer: def serveforever(self, pollinterval=0.5): self.handlerequestnoblock() defhandlerequestnoblock(self): self.processrequest(request, clientaddress)
def process_request(self, request, client_address): pass
class TCPServer(BaseServer): pass
class ThreadingMixIn: def processrequest(self, request, clientaddress): pass
class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass
obj = ThreadingTCPServer() obj.serve_forever()
```
注意事项:
- self 到底是谁?
- self 是哪个类创建的,就从此类开始找,自己没有就在基类。
7.5 多态(多种形态/多种类型)鸭子模型
```python
def func(arg): v = arg[-1] # arg.append(9) print(v)
java
def func(str arg): v = arg[-1] print(v) ```
总结
-
面向对象的三大特性:封装/继续/多态
- 封装
python class File: def read(self): pass def write(self): pass
python class Person: def __init__(sef,name,age): self.name = name self.age = age p = Person('alex',19)
-
继承
python class Base: pass class Foo(Base): pass
-
多继承
- self 到底是谁?
- self 是有那个类创建,则找方法时候就从他开始找。
多态
python def func(arg): # 多种类型,很多事物 arg.send() # 必须具有send方法,呱呱叫
- 格式和关键字
```python class 类: def init(self,x): self.x = x
def 方法(self,name): print(self.x, name)
# 实例化一个类的对象 v1 = 类(666) v2.方法('alex') ```
三个词:
- 类
- 对象
-
方法
-
什么时候用面向对象?
-
函数(业务功能)比较多,可以使用面向对象进行归类。
- 想要做数据封装(创建字典存储数据时,用面向对象)。
- 游戏示例:创建角色并且根据角色需要再创建人物。
7.6 成员
- 类
- 类变量
- 绑定方法
- 静态方法
- 类方法
- 属性
- 实例(对象)
- 实例变量
1.1 实例变量
```python class Foo:
def --init--(self ,name) self.name = name def info(self): pass
```
1.2 类变量
-
定义:写在类的下一级和方法同级。
-
访问:
类.类变量名称 对象.类变量名称
- 面试题
```python class Base: x = 1
obj = Base()
print(obj.x) # 先去对象中找,没有再去类中找。 obj.y = 123 # 在对象中添加了一个y=123的变量。 print(obj.y) obj.x = 123 print(obj.x) print(Base.x) ############### class Parent: x = 1
class Child1(Parent): pass
class Child2(Parent): pass
print(Parent.x,Child1.x,Child2.x) # 1 1 1 Child1.x = 2 print(Parent.x,Child1.x,Child2.x) # 1 2 1 Child2.x = 3 print(Parent.x,Child1.x,Child2.x) # 1 2 3 ```
总结:找变量优先找自己,自己没有找类 或 基类。修改或赋值只能在自己内部。
1.3 方法(绑定方法/普通方法)
- 定义:至少有一个self 参数
- 执行:先创建对象,由对象方法。
```python class Foo: def func(self,a,b): print(a,b)
obj = Foo() obj.func(1,2)
class Foo: def init(self): self.name = 123
def func(self, a, b): print(self.name, a, b)
obj = Foo() obj.func(1, 2) ```
1.4 静态方法:
-
定义:
- @staticomethod装饰器
- 参数无限制
-
执行:
- 类.静态方法名
- 对象.静态方法(不推荐)
```python class Foo: def init(self): self.name = 123
def func(self, a, b): print(self.name, a, b) @staticmethod def f1(): print(123)
obj = Foo() obj.func(1, 2)
Foo.f1() obj.f1() # 不推荐 ```
1.5 类方法:
-
定义
- @classcomethod装饰器
- 至少有一个参数cls(当前类)
-
执行:
- 类.类方法
- 对象.类方法(不推荐)
```python class Foo: def init(self): self.name = 123
def func(self, a, b): print(self.name, a, b) @staticmethod def f1(): print(123) @classmethod def f2(cls,a,b): print('cls是当前类',cls) print(a,b)
obj = Foo() obj.func(1, 2)
Foo.f1() Foo.f2(1,2) ```
面试题:
python # 问题: @classmethod和@staticmethod的区别? """ 一个是类方法一个静态方法。 定义: 类方法:用@classmethod做装饰器且至少有一个cls参数。 静态方法:用staticmethod做装饰器且参数无限制。 调用: 类.方法直接调用。 对象.方法也可以调用。 """
###### 1.6 属性
- 定义:
- @property装饰器
- 只有一个self 参数
- 执行
- 对象.方法 不用加()
```python class Foo:
@property def func(self): print(123) return 666
obj = Foo() result = obj.func print(result) ```
属性的应用(分页)
```python
属性的应用
class Page: def init(self, totalcount, currentpage, perpagecount=10): self.totalcount = totalcount self.perpagecount = perpagecount self.currentpage = currentpage @property def startindex(self): return (self.currentpage - 1) * self.perpagecount @property def endindex(self): return self.currentpage * self.perpagecount
USERLIST = [] for i in range(321): USERLIST.append('alex-%s' % (i,))
请实现分页展示:
currentpage = int(input('请输入要查看的页码:')) p = Page(321, currentpage) datalist = USERLIST[p.startindex:p.endindex] for item in data_list: print(item) ```
7. 7成员修饰器
- 公有,所有地方都能访问到。
- 私有,只有自己可以访问到。[-Foo 强制访问私有成员]
```python class Foo: def init(self, name): self.__name = name
def func(self): print(self.__name)
obj = Foo('alex')
print(obj.__name)
obj.func() ```
```python class Foo: __x = 1
@staticmethod def func(): print(Foo.__x)
print(Foo.__x)
Foo.func() ```
```python class Foo:
def __fun(self): print('msg') def show(self): self.__fun()
obj = Foo()
obj.__fun()
obj.show() ```
补充
```python class Foo: def init(self,num): self.num = num
clslist = [] for i in range(10): clslist.append(Foo)
for i in range(len(clslist)): obj = clslisti# Foo(0) print(obj.num) ```
```python class Foo: def init(self,num): self.num = num
B = Foo obj = B('alex') ```
```python class Foo: def f1(self): print('f1')
def f2(self): print('f2') def f3(self): v = [self.f1 , self.f2 ] for item in v: item()
obj = Foo() obj.f3() ```
```python class Account:
def login(self): pass def register(self): pass def run(self): info = {'1':self.register, '2':self.login } choice = input('请选择:') method = info.get(choice) method()
```
```python class Foo: pass
class Foo(object): pass
在python3中这俩的写法是一样,因为所有的类默认都会继承object类,全部都是新式类。
如果在python2中这样定义,则称其为:经典类
class Foo: pass
如果在python2中这样定义,则称其为:新式类
class Foo(object): pass
class Base(object): pass class Bar(Base): pass ```
```python 赠送
强制访问私有成员
class Foo: def init(self,name): self.__x = name
obj = Foo('alex')
print(obj.Foo_x) # 强制访问私有实例变量 ```
总结
- 数据封装
- 继承关系的查找
- 成员
- 嵌套
```python class School(object): def init(self,title,addr): self.title = title self.address = addr
class ClassRoom(object):
def __init__(self,name,school_object): self.name = name self.school = school_object
s1 = School('北京','沙河') s2 = School('上海','浦东') s3 = School('深圳','南山')
c1 = ClassRoom('全栈21期',s1) c1.name c1.school.title c1.school.address
v = [11,22,33,{'name':'山海','addr':'浦东'}]
v[0] v[3]['name'] ```
7.8 .嵌套
-
函数:参数可以是任意类型。
-
字典:对象和类都可以做字典的key和values
-
继承的查找关系
```python
class StarkConfig(object): pass
class AdminSite(object): def init(self): self.data_list = []
def register(self,arg): self.data_list.append(arg)
site = AdminSite()
obj = StarkConfig() site.register(obj) ```
```python class StarkConfig(object): def init(self,name,age): self.name = name self.age = age
class AdminSite(object): def init(self): self.data_list = [] self.sk = None
def set_sk(self,arg): self.sk = arg
site = AdminSite() # datalist = [] sk = StarkConfig site.setsk(StarkConfig) site.sk('alex',19) ```
```python class StackConfig(object): pass
class Foo(object): pass
class Base(object): pass
class AdminSite(object): def init(self): self._register = {}
def registry(self,key,arg): self._register[key] = arg
site = AdminSite() site.registry(1,StackConfig) site.registry(2,StackConfig) site.registry(3,StackConfig) site.registry(4,Foo) site.registry(5,Base)
for k,v in site._register.items(): print(k,v() ) ```
```python class StackConfig(object): pass
class UserConfig(StackConfig): pass
class AdminSite(object): def init(self): self._register = {}
def registry(self,key,arg=StackConfig): self._register[key] = arg def run(self): for key,value in self._register.items(): obj = value() print(key,obj)
site = AdminSite() site.registry(1) site.registry(2,StackConfig) site.registry(3,UserConfig) site.run() ```
```python class StackConfig(object): list_display = '李邵奇'
class UserConfig(StackConfig): list_display = '利奇航'
class AdminSite(object): def init(self): self._register = {}
def registry(self,key,arg=StackConfig): self._register[key] = arg def run(self): for key,value in self._register.items(): obj = value() print(key,obj.list_display)
site = AdminSite() site.registry(1) site.registry(2,StackConfig) site.registry(3,UserConfig) site.run() ```
```python class StackConfig(object): list_display = '李邵奇'
def changelist_view(self): print(self.list_display)
class UserConfig(StackConfig): list_display = '利奇航'
class AdminSite(object): def init(self): self._register = {}
def registry(self,key,arg=StackConfig): self._register[key] = arg def run(self): for key,value in self._register.items(): obj = value() obj.changelist_view()
site = AdminSite() site.registry(1) site.registry(2,StackConfig) site.registry(3,UserConfig) site.run() ```
7.9 特殊成员
- --init--
```python --init--初始化方法 给对象中进行赋值(初始化) class Foo: """ 类是干啥的。。。。 """ definit(self,a1): """ 初始化方法 :param a1: """ self.a1 = a1
obj = Foo('alex') ```
- --nwe--
```python 先执行--new--创建空对象【构造方法】 然后在执行--init--进行初始化 class Foo(object): def init(self): """ 用于给对象中赋值,初始化方法 """ self.x = 123 def new(cls, *args, **kwargs): """ 用于创建空对象,构造方法 :param args: :param kwargs: :return: """ return object.new(cls)
obj = Foo() ```
- --call--
```python 对象加() 执行--call-- 类()() 先执行--new--再执行--init--再执行--call-- class Foo(object): def call(self, *args, **kwargs): print('执行call方法')
obj = Foo()
obj()
Foo()() ```
```python from wsgiref.simpleserver import makeserver
def func(environ,startresponse): startresponse("200 OK", [('Content-Type', 'text/plain; charset=utf-8')]) return ['你好'.encode("utf-8") ]
class Foo(object):
def __call__(self, environ,start_response): start_response("200 OK", [('Content-Type', 'text/html; charset=utf-8')]) return ['你<h1 style="color:red;">不好</h1>'.encode("utf-8")]
作用:写一个网站,用户只要来方法,就自动找到第三个参数并执行。
server = makeserver('127.0.0.1', 8000, Foo()) server.serveforever() ```
- --getitem--/--setitem--/--delitem--
```python
--getitem-- 取值
--selitem-- 赋值
--delitem-- 删除
class Foo(object):
def __setitem__(self, key, value): pass def __getitem__(self, item): return item + 'uuu' def __delitem__(self, key): pass
obj1 = Foo() obj1['k1'] = 123 # 内部会自动调用 setitem方法 val = obj1['xxx'] # 内部会自动调用getitem方法 print(val) del obj1['ttt'] # 内部会自动调用 delitem 方法 ```
- --str--
```python
打印一个对象时,会自动调用--str--# 方法,并将其返回值在页面显示出来。
class Foo(object): def --str--(self): ''' 只有在打印对象时,会自动调用此方法,并将其返回值在页面显示出来 :return: ''' return "asfkjkfjdf" obj = Foo() print(obj) ```
python class User(object): def __init__(self,name,email): self.name = name self.email = email def __str__(self): return "%s %s" %(self.name,self.email,) user_list = [User('二狗','2g@qq.com'),User('二蛋','2d@qq.com'),User('狗蛋','xx@qq.com')] for item in user_list: print(item)
- --dict--
```python
取对象中找到所有
class Foo(object): def init(self,name,age,email): self.name = name self.age = age self.email = email
obj = Foo('alex',19,'xxxx@qq.com') print(obj) print(obj.name) print(obj.age) print(obj.email) val = obj.dict # 去对象中找到所有变量并将其转换为字典 print(val) ```
- 上下文管理
```python
--enter--上
--exit--下
class Foo(object): def enter(self): self.x = open('a.txt',mode='a',encoding='utf-8') return self.x def _exit(self, exctype, excval, exctb): self.x.close()
with Foo() as ff: ff.write('alex') ff.write('alex') ff.write('alex') ff.write('alex') ```
```python
class Context:
def enter(self):
print('进入')
return self
def exit(self, exc_type, excval, exctb):
print('推出')
def do_something(self):
print('内部执行')
with Context() as ctx:
print('内部执行')
ctx.do_something()
class Foo(object): def do_something(self) : print('内部执行')
class Context: def enter(self): print('进入') return Foo()
def __exit__(self, exc_type, exc_val, exc_tb): print('推出')
with Context() as ctx: print('内部执行') ctx.do_something() ```
- 两个对象相加
```python
--add--
val = 5 + 8 print(val)
val = "alex" + "sb" print(val)
class Foo(object): def add(self, other): return 123
obj1 = Foo() obj2 = Foo() val = obj1 + obj2 print(val) ```
特殊成员:就是为了能够快速实现执行某些方法而生
7.10 异常处理
- 基本格式
python try: pass except Exception as e: pass
python try: v = [] v[11111] # IndexError except ValueError as e: pass except IndexError as e: pass except Exception as e: print(e) # e是Exception类的对象,中有一个错误信息。
```python try: int('asdf') except Exception as e: print(e) # e是Exception类的对象,中有一个错误信息。 finally: print('最后无论对错都会执行')
# #################### 特殊情况 ######################### def func(): try: # v = 1 # return 123 int('asdf') except Exception as e: print(e) # e是Exception类的对象,中有一个错误信息。 return 123 finally: print('最后')
func() ```
- 主动触发异常
python # raice 加对 Exception # 代码中主动抛出异常 try: int('123') raise Exception('阿萨大大是阿斯蒂') # 代码中主动抛出异常 except Exception as e: print(e)
python def func(): result = True try: with open('x.log',mode='r',encoding='utf-8') as f: data = f.read() if 'alex' not in data: raise Exception() except Exception as e: result = False return result
- 自定义异类
```python class MyException(Exception): pass
try: raise MyException('asdf') except MyException as e: print(e) ```
```python class MyException(Exception): def init(self,message): super().init() self.message = message
try: raise MyException('asdf') except MyException as e: print(e.message) ```
7.11约束
```python
约束字类中必须写send方法,如果不写,则调用时候就报抛出 NotImplementedError
class Interface(object): def send(self): raise NotImplementedError()
class Message(Interface): def send(self): print('发送短信')z
class Email(Interface): def send(self): print('发送邮件') ```
```python class Message(object):
def msg(self): print('发短信') def email(self): print('邮件') def wechat(self): print('微信')
obj = Message() obj.msg() obj.email() obj.wechat() ```
```python class BaseMessage(object): def send(self,a1): raise NotImplementedError('字类中必须有send方法')
class Msg(BaseMessage): def send(self): pass
class Email(BaseMessage): def send(self): pass
class Wechat(BaseMessage): def send(self): pass
class DingDing(BaseMessage): def send(self): print('钉钉')
obj = Email() obj.send() ```
7.12反射
根据字符串的形式去某个对象中操作他的成员
- getattr(对象,“字符串”) 根据字符串的形式去某个对象中获取对象的成员
```python # getattr 内置函数 # setattr 内置函数 赋值 class Foo(object): def init(self,name): self.name = name obj = Foo('alex')
# 获取变量 v1 = getattr(obj,'name') # 获取方法 methodname = getattr(obj,'login') methodname() ```
- hasattr(对象,"字符串") 根据字符串的形式去某个对象中判断是否有该成员
```python from wsgiref.simpleserver import makeserver
class View(object): def login(self): return '登陆'
def logout(self): return '等处' def index(self): return '首页'
def func(environ,startresponse): startresponse("200 OK", [('Content-Type', 'text/plain; charset=utf-8')]) # obj = View() # 获取用户输入的URL methodname = environ.get('PATHINFO').strip('/') if not hasattr(obj,methodname): return ["sdf".encode("utf-8"),] response = getattr(obj,methodname)() return [response.encode("utf-8") ]
# 作用:写一个网站,用户只要来方法,就自动找到第三个参数并执行。 server = makeserver('192.168.12.87', 8000, func) server.serveforever() ```
- setattr(对象,"变量","值") 根据字符串的形式去某个对象中设置成员。
```python class Foo: pass
obj = Foo() obj.k1 = 999 setattr(obj,'k1',123) # obj.k1 = 123
print(obj.k1) ```
- delattr(对象,"变量") 根据字符串的形式去某个对象中删除成员。
```python class Foo: pass
obj = Foo() obj.k1 = 999 delattr(obj,'k1') print(obj.k1) ```
python一切皆对象,所以以后想要通过字符串的形式操作其内部成员都可以通过反射的机制实现。
- py文件
- 包
- 类
- 对象
7.13栈
- 特性:后进先出
- push 入栈
- pop 出栈
```python class Stack(object): """ 后进先出 """ def init(self): self.data_list = []
def push(self, val): """ 向栈中压入一个数据(入栈) :param val: :return: """ self.data_list.append(val) def pop(self): """ 从栈中拿走一个数据(出栈) :return: """ return self.data_list.pop()
来源:https://www.cnblogs.com/wudongmin/p/12259262.html