第七章 面向对象
7.1.1 面向对象基本格式
class 类名: #类名首字母需要大写 def 方法名(self,name)#self是默认参数不用传参,而其他的需要传参,如name需要传参 print(name) obj = 类名() #创建了一个类名的对象,实例化对象 result = obj.方法名('alex') #通过对象调用了方法 print(result) class Foo: def func(self,name) print(name) obj = Foo() result = obj.name('alex') print(result)
应该场景:遇到很多函数,需要给函数进了归类和划分(封装思想)
例题:
class Db: #Db是数据库 def db_reda(self): pass def db_write(self): pass def db_deleta(self): pass def db_update(self): pass class File:#file是文件 def file_read(self): pass def file_write(self): pass def file_deleta(self): pass
1.1.2.对象的作用
存储一些值,以后方便调用
class File: def read(self): with open(self.xxxx, mode='r', encoding='utf-8') as f: data = f.read() return data def write(self,content): with open(self.xxxx, mode='a', encoding='utf-8') as f: f.write(content) # # 实例化了一个File类的对象 obj1 = File() # # 在对象中写了一个xxxxx = 'test.log' obj1.xxxxx = "test.log" # # 通过对象调用类中的read方法,read方法中的self就是obj。 ##哪个对象调用了方法就是self # # obj1.read() obj1.write('alex') # 实例化了一个File类的对象 obj2 = File() # 在对象中写了一个xxxxx = 'test.log' obj2.xxxxx = "info.txt" # 通过对象调用类中的read方法,read方法中的self就是obj。 # obj2.read() obj2.write('alex')
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()
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()
总结:将数据封装到对象,方便使用。
""" 如果写代码时,函数比较多比较乱。 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()
例题:
# 1. 循环让用户输入:用户名/密码/邮箱。 输入完成后再进行数据打印。 # ########## 以前的写法 USER_LIST = [] while True: user = input('请输入用户名:') pwd = input('请输入密码:') email = input('请输入邮箱:') temp = {'username':user,'password':pwd,'email':email} USER_LIST.append(temp) 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 USER_LIST = [对象(用户/密码/邮箱),对象(用户/密码/邮箱),对象(用户/密码/邮箱)] while True: user = input('请输入用户名:') pwd = input('请输入密码:') email = input('请输入邮箱:') p = Person(user,pwd,email) USER_LIST.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,) USER_LIST = [对象(用户/密码/邮箱),对象(用户/密码/邮箱),对象(用户/密码/邮箱)] while True: user = input('请输入用户名:') pwd = input('请输入密码:') email = input('请输入邮箱:') p = Person(user,pwd,email) USER_LIST.append(p) for item in USER_LIST: msg = item.info() print(msg)
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 # ...
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):#other代指警察 msg = "%s个了%s一全。" %(self.nickname,other.name) self.hp -= 20 other.hp -= 500 lcj = Bandit('二蛋') lsq = Police('李奇') lsq.dao(lcj) #lcj是对象 lsq.quan(lcj) lcj.qiang(lsq)
1.1.4 继承(可以一直往上继承)
注意:创建了一个父类的对象,父类不能继承子类的
# 父类(基类) class Base: def f1(self): pass # 子类(派生类) class Foo(Base): def f2(self): pass # 创建了一个子类的对象 obj = Foo() # 执行对象.方法时,优先在自己的类中找,如果没有就是父类中找。 obj.f2() obj.f1() # 创建了一个父类的对象,父类不能继承子类的 obj = Base() obj.f1() obj.f2()#--->错
问题:什么时候才能用到继承?多个类中如果有公共的方法,可以放到基类中避免重复编写。
class Base: def f1(self): pass class Foo(Base): def f2(self): pass class Bar(Base): def f3(self): pass obj1 = Foo() obj2 = Bar()
继承关系中的查找方法的顺序:
# 示例一 class Base: def f1(self): print('base.f1') class Foo(Base): def f2(self): print('foo.f2') obj = Foo() obj.f1()#base.f1 self是obj obj.f2()#foo.f2 self是obj # 示例二 class Base: def f1(self): #self是obj print('base.f1') class Foo(Base): def f2(self): self.f1() print('foo.f2') obj = Foo() obj.f2()#base.f1 foo.f2 # 示例三 class Base: def f1(self): print('base.f1') class Foo(Base): def f2(self): self.f1() #obj.f1 print('foo.f2') def f1(self): print('foo.f1') obj = Foo() obj.f2() # foo.f1 foo.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()# foo.f2 base.f1 # 示例五 class TCPServer: pass class ThreadingMixIn: pass class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass # 示例六 class BaseServer: def serve_forever(self, poll_interval=0.5): self._handle_request_noblock() def _handle_request_noblock(self): self.process_request(request, client_address) def process_request(self, request, client_address): pass class TCPServer(BaseServer): pass class ThreadingMixIn: def process_request(self, request, client_address): pass class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass obj = ThreadingTCPServer() obj.serve_forever()
注意事项:
-
self 到底是谁?需要先清楚self到底是谁
-
self 是哪个类创建的,就从此类开始找,自己没有就找父类。
-
# Python def func(arg): v = arg[-1] # arg.append(9) print(v) # java def func(str arg): v = arg[-1] print(v)
面试题:什么是鸭子模型。
对于一个函数而言,Python对于参数的类型不会限制,那么传入参数时就可以是各种类型,在函数中如果有例如:arg.send方法,那么就是对于传入类型的一个限制(类型必须有send方法)。
这就是鸭子模型,类似于上述的函数我们认为只要能呱呱叫的就是鸭子(只有有send方法,就是我们要想的类型)
class File: def read(self): pass def write(self): pass
class Person: def __init__(sef,name,age): self.name = name self.age = age p = Person('alex',19)
2 继承
class Base: pass class Foo(Base): pass
3 多态
def func(arg): # 多种类型,很多事物 arg.send() # 必须具有send方法,呱呱叫
三个关键词:类 / 对象/ 方法
class 类: def __init__(self,x): self.x = x def 方法(self,name): print(self.x, name) # 实例化一个类的对象 v1 = 类(666) v2.方法('alex')
- 函数(业务功能)比较多,可以使用面向对象来进行归类。 - 想要做数据封装(创建字典存储数据时,面向对象)。 - 游戏示例:创建一些角色并且根据角色需要再创建人物
7.2面向对象的类成员
7.2.1 成员--类
类.类变量名称
对象.类变量名称
class Foo: city = '北京'--》city是类变量 def __init__(self,name) self.name = name def func(self): pass obj1 = Foo('alex') print(Foo.city) #北京 print(obj2.city ) #北京
面试题
class Base: x = 1 obj = Base() print(obj.x) #1 先去对象中找,没有再去类中找。 obj.y = 123 # 在对象中添加了一个y=123的变量。 print(obj.y) #123 obj.x = 123 print(obj.x) #123 print(Base.x) #1
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
总结:找变量优先找自己,自己没有找父 类 或 基类;修改或赋值只能在自己的内部设置。
-
-
执行:先创建对象,由对象.方法()。
-
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)
-
-
@staticmethod装饰器
-
参数无限制
-
-
执行:
-
类.静态方法名 ()
-
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() # 不推荐
7.2.1.4类方法
-
-
@classmethod装饰器
-
至少有cls参数,当前类。
-
-
执行:
-
类.类方法()
-
对象.类方法() (不推荐)
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): #cls是当前的类就是Foo print('cls是当前类',cls) print(a,b) obj = Foo() obj.func(1, 2) Foo.f1() Foo.f2(1,2) obj.f2(1,2) #不推荐
面试题:
# 问题: @classmethod和@staticmethod的区别? """ 一个是类方法一个静态方法。 定义: 类方法:用@classmethod做装饰器且至少有一个cls参数。 静态方法:用staticmethod做装饰器且参数无限制。 调用: 类.方法直接调用。 对象.方法也可以调用。 """
7.2.1.5 属性
-
定义:
-
@property装饰器
-
-
-
执行:
-
对象.方法 不用加括号。
class Foo: @property def func(self): #只能有self参数不能有其他参数 print(123) return 666 obj = Foo() result = obj.func print(result)
# 属性的应用 class Page: def __init__(self, total_count, current_page, per_page_count=10): self.total_count = total_count self.per_page_count = per_page_count self.current_page = current_page @property def start_index(self): return (self.current_page - 1) * self.per_page_count @property def end_index(self): return self.current_page * self.per_page_count USER_LIST = [] for i in range(321): USER_LIST.append('alex-%s' % (i,)) # 请实现分页展示: current_page = int(input('请输入要查看的页码:')) p = Page(321, current_page) data_list = USER_LIST[p.start_index:p.end_index]#起始和结束位置 for item in data_list: print(item)
7.2.2 成员 --实例(对象)
实例变量(字段)
class Foo: def __init__(self.name): self.name = name def info(self): pass obj1 = Foo('alex') obj2 = Foo('eric')
7.2.3 成员修饰符
-
-
私有(有双下划线),只有自己可以访问到,下一级也不能访问
class Foo: def __init__(self, name): self.__name = name #私用变量 self.name = name #公共变量 外部可以访问 def func(self): print(self.__name) obj = Foo('alex') # print(obj.__name) #外部访问不到 obj.func() #alex 内部可以访问
class Foo: __x = 1 @staticmethod def func(): print(Foo.__x) # print(Foo.__x) Foo.func() #1 NONE
class Foo: def __fun(self): print('msg') def show(self): self.__fun() obj = Foo() # obj.__fun() obj.show()
class Base: def __f1(self): print('Bsae.f1') class Foo(Base): def func(self): self.__f1() obj = Foo() obj.func() #报错,下一级也无法访问私有的
class Foo: def __init__(self,name): self.__x = name obj = Foo('alex') print(obj._Foo__x) #alex 强制访问私有实例变量
练习题:
class Foo: def __init__(self,num): self.num = num cls_list = [] for i in range(10): cls_list.append(Foo) for i in range(len(cls_list)): obj = cls_list[i](i) #对象 print(obj.num) # 0-9
class Foo: def __init__(self,num): self.num = num B = Foo obj = B('alex')
class Foo: def f1(self): print('f1') def f2(self): print('f2') obj = Foo() v = [ obj.f1,obj.f2 ] for item in v: item()
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()
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
-
函数:参数可以是任意类型。
-
字典:对象和类都可以做字典的key和value
-
继承的查找关系
7.2.4.1 函数:参数可以是任意类型。
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']
#学校、老师互相关联 class School(object): def __init__(self,name,address): self.name = name self.address = address self.teacher_list = [] def append_teacher(self,teacher): self.teacher_list.append(teacher) class Teacher(object): def __init__(self,name,comment,school): self.name = name self.comment = comment self.school = school def check_address(self): print('%s在%s办公'%(self.name,self.school.address)) #创建三个校区 beijing = School('老男孩北京校区','沙河') shanghai = School('老男孩上海校区','章江') shenzhen = School('老男孩深圳校区','南山') #创建两个老师 t1 = Teacher('太白','还行',beijing) t2= Teacher('alex','屌丝',shanghai) t1.check_address() #太白在沙河办公 查看老师归属哪个学校 t2.check_address() #alex在章江办公
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()
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() # data_list = [] sk = StarkConfig site.set_sk(StarkConfig) #sk = StarkConfig site.sk('alex',19)
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() )
7.3.1 '_ init _' 初始化方法
class Foo: """ 类是干啥的。。。。 """ def __init__(self,a1): """ 初始化方法 :param a1: """ self.a1 = a1 obj = Foo('alex')
class Foo(object): def __init__(self): """ 用于给对象中赋值,初始化方法 """ self.x = 123 def __new__(cls, *args, **kwargs): """ 用于创建空对象,构造方法 :param args: :param kwargs: :return: """ return object.__new__(cls)#返回什么obj就等于什么 obj = Foo() #先执行new,在执行对象的初始化
class Foo(object): def __call__(self, *args, **kwargs): print('执行call方法') # obj = Foo() # obj()#执行call方法 Foo()()-->先执行new方法在执行init方法在执行call方法,#输出执行call方法
#!/usr/bin/env python # -*- coding:utf-8 -*- from wsgiref.simple_server import make_server def func(environ,start_response): start_response("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 = make_server('127.0.0.1', 8000, Foo()) server.serve_forever()
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)#xxxuuu del obj1['ttt'] #删除 内部会自动调用 __delitem__ 方法
class Foo(object): def __str__(self): """ 只有在打印对象时,会自动化调用此方法,并将其返回值在页面显示出来 :return: """ return 'asdfasudfasdfsad' obj = Foo() print(obj)
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)
7.3.6
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){'name':'alex','age':19,'email':'xxxx@qq.com'}
class Foo(object): def __enter__(self): self.x = open('a.txt',mode='a',encoding='utf-8') return self.x def __exit__(self, exc_type, exc_val, exc_tb): self.x.close() with Foo() as ff: ff.write('alex') ff.write('alex') ff.write('alex') ff.write('alex')
'内部执行') # 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()
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) #123
特殊成员:就是为了能够快速实现执行某些方法而生。
7.4 内置函数补充
判断一个实例对象是否是一个类的实例对象
class Foo: pass obj = Foo() if type(obj) == Foo: print('obj是Foo类的对象')
7.4.2 issubclass 判断某个类是否是某个类的子类
class Base: pass class Base1(Base): pass class Foo(Base1): pass class Bar: pass print(issubclass(Bar,Base)) #False print(issubclass(Foo,Base)) #True
class Base(object): pass class Foo(Base): pass obj = Foo() print(isinstance(obj,Foo)) True # 判断obj是否是Foo类或其基类的实例(对象) print(isinstance(obj,Base)) #True 判断obj是否是Foo类或其基类的实例(对象)
class Base(object): def func(self): print('base.func') return 123 class Foo(Base): def func(self): v1 = super().func()#返回值给v1 print('foo.func',v1) obj = Foo() obj.func() #base.func foo.func 123 # super().func() 去父类中找func方法并执行
class Bar(object): def func(self): print('bar.func') return 123 class Base(Bar): pass class Foo(Base): def func(self): v1 = super().func() print('foo.func',v1) obj = Foo() obj.func() base.func foo.func 123 # super().func() 根据类的继承关系,按照顺序挨个找func方法并执行(找到第一个就不在找了)
class Base(object): # Base -> object def func(self): super().func() print('base.func') class Bar(object): def func(self): print('bar.func') class Foo(Base,Bar): # Foo -> Base -> Bar pass obj = Foo() obj.func() # bar.func base.func # super().func() 根据self对象所属类的继承关系,按照顺序挨个找func方法并执行(找到第一个就不在找了)
7.5.1 基本格式
try: pass except Exception as e: pass
try: v = [] v[11111] # IndexError except ValueError as e: pass except IndexError as e: pass except Exception as e: print(e) # e是Exception类的对象,对象中有一个错误信息。
try: int('asdf') except Exception as e: print(e) # e是Exception类的对象,中有一个错误信息。 finally: print('最后无论对错都会执行') # finally:最后无论对错都会执行 # #################### 特殊情况 ######################### def func(): try: # v = 1 # return 123 int('asdf') except Exception as e: print(e) # e是Exception类的对象,中有一个错误信息。 return 123 finally: print('最后') func() #在python中有try中finally即使遇到return,它也是先执行完在return
try: int('123') raise Exception('阿萨大大是阿斯蒂') # 代码中主动抛出异常 except Exception as e: print(e) #阿萨大大是阿斯蒂
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
class MyException(Exception): pass try: raise MyException('asdf') except MyException as e: print(e)
class MyException(Exception): def __init__(self,message): super().__init__() self.message = message try: raise MyException('asdf') except MyException as e: print(e.message)
class Foo: pass obj = Foo()
class Foo: def __iter__(self): return iter([1,2,3,4])#转换成迭代器 obj = Foo() class Foo: def __iter__(self): yield 1 yield 2 yield 3 obj = Foo() for item in obj: print(obj) #1 2 3
记住:只要能被for循环就是去看他内部的iter方法。
# 约束字类中必须写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('发送邮件')
class Message(object): def msg(self): print('发短信') def email(self): print('邮件') def wechat(self): print('微信') obj = Message() obj.msg() obj.email() obj.wechat()
class BaseMessage(object): def send(self,a1): raise NotImplementedError('子类中必须有send方法') class Msg(BaseMessage):('子类中必须有send方法') 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.8.1getattr(对象,"字符串")
根据字符串的形式去某个对象中 获取 对象的成员.
class Foo(object): def __init__(self,name): self.name = name def login(self): pass obj = Foo('alex') func_name = input('请输入方法名:') #login getattr(obj,func_name) #执行login方法 # 获取变量 v1 = obj.name v1 = getattr(obj,'name') obj.name = 'eric' setattr(obj,'name','eric') #重新赋值 # 获取方法 method_name = getattr(obj,'login') method_name()
根据字符串的形式去某个对象中判断是否有该成员。
#!/usr/bin/env python # -*- coding:utf-8 -*- from wsgiref.simple_server import make_server class View(object): def login(self): return '登陆' def logout(self): return '等处' def index(self): return '首页' def func(environ,start_response): start_response("200 OK", [('Content-Type', 'text/plain; charset=utf-8')]) # obj = View() # 获取用户输入的URL method_name = environ.get('PATH_INFO').strip('/') if not hasattr(obj,method_name): return ["sdf".encode("utf-8"),] response = getattr(obj,method_name)() return [response.encode("utf-8") ] # 作用:写一个网站,用户只要来方法,就自动找到第三个参数并执行。 server = make_server('192.168.12.87', 8000, func) server.serve_forever()
根据字符串的形式去某个对象中设置成员。
class Foo: pass obj = Foo() obj.k1 = 999 setattr(obj,'k1',123) # obj.k1 = 123 print(obj.k1) #123
7.8.4 delattr(对象,'变量')
class Foo: pass obj = Foo() obj.k1 = 999 delattr(obj,'k1') print(obj.k1)
# 反射 # hasattr(重要) # getattr(重要) # setattr # delattr # ab = 'test' # import demo # print(getattr(demo,'a')) # print(getattr(demo,'a')) import demo import sys # print(demo) # print(sys.modules) # print(sys.modules['demo']) # print(demo is sys.modules['demo']) #True # print(getattr(sys.modules['demo'],'a')) #取demo.py文件里a的值 # print(getattr(sys.modules[__name__],'ab'))#取demo.py文件里ab的值,__name__反射当前文件中的内容,不管是导入的还是就是当前的都用。( #print(geattr(sys.moudles['__main__'],'ab')) #当前文件取ab的值 __main__当前文件 # '__main__': <module '__main__' from 'D:/code/day24/1.内容回顾.py'> # setattr # delattr # 反射 # 通过 对象 来获取 实例变量、绑定方法 # 通过 类 来获取 类变量、类方法、静态方法 # 通过 模块名 来获取 模块中的任意变量(普通变量 函数 类) # 通过 本文件 来获取 本文件中的任意变量 # getattr(sys.modules[__name__],'变量名')
例题:
class Cloud(object): def upload(self): pass def download(self): pass def run(self): # up|C:/xxx/xxx.zip # down|xxxx.py value = input('请用户输入要干什么?') action = value.split('|')[0] # 最low的形式 if action == 'up': self.upload() elif action == 'down': self.download() else: print('输入错误') # 构造字典 (*) method_dict = {'up':self.upload, 'down':self.download} method = method_dict.get(action) method() # 反射(*) method = getattr(self,action) # action必须是upload 和download # self.upload (self,action)表示去找self.up或者self.download method() class Foo(object): def get(self): pass obj = Foo() # if hasattr(obj,'post'): # getattr(obj,'post') v1 = getattr(obj,'get',None) # 推荐 print(v1)
7.9 python一切皆对象
-
py文件
-
包
-
类
-
对象
模块 = importlib.import_module('utils.redis') 内部会执行 form utils import redis getattr(redis,'func') #用字符串的形式去对象(模块)中找她的成员
函数: import importlib path = 'utils.redis.func' module_path,func_name = path.rsplit('.',maxsplit =1) #从右边开始往左分割两个字符串,一个路径,一个函数名 module_object = importlib.import_module(module_path) getattr(module_object,func_name)() 类: import importlib middleware_classer = ['utils.redis.Redis','utils.mysql.Mysql'] for path in middleware_classer: module_path,class_name = path.rsplit('.',maxsplit =1) #从右边开始往左分割两个字符串,一个路径,一个类名 module_object = importlib.import_module(module_path) cls = getattr(module_object,class_name)#找到类 obj = cls() #实例化对象 obj.connect()
class Stack(object):#后进后出 pass class Queue(object): #队列 先进先出 pass # 补充 # 栈 Stack #后进先出是栈 lifo # 队列 Queue # 先进先出是队列 fifo
什么是单例模式 # 单例的应用场景 # __new__方法 :(指针)创建实例的 并且在init之前工作
class Foo: pass # 多例,每实例化一次就创建一个新的对象。 obj1 = Foo() # 实例,对象 obj2 = Foo() # 实例,对象 # 单例,无论实例化多少次,都用第一次创建的那个对象。 obj1 = Foo() obj2 = Foo()
无论实例化多少次对象用的都是第一次实例化创建的对象(第一次创建的内存地址)
应该场景:连接池,数据库的链接
class Singleton(object): instance = None def __new__(cls, *args, **kwargs): #cls = Singleton if not cls.instance:#判断是否存在 cls.instance = object.__new__(cls) return cls.instance obj1 = Singleton() obj2 = Singleton() #obj1和obj2的内存地址一样 # 不是最终,加锁。
文件的连接池
class FileHelper(object): instance = None def __init__(self, path): self.file_object = open(path,mode='r',encoding='utf-8') def __new__(cls, *args, **kwargs): if not cls.instance: cls.instance = object.__new__(cls) return cls.instance obj1 = FileHelper('x') #x是文件 obj2 = FileHelper('x') obj1.file_object.reda(1) obj2.file_object.read(2)