Day.7类与对象
作业一:总结
1.什么是绑定到对象的方法,如何定义,如何调用,给谁用?有什么特性
定义:只要是在类内部定义的,并且没有被任何装饰器修饰过的方法,都是绑定到对象的方法
class Foo: def test(self): #绑定到对象的方法 pass def test1(): #也是绑定到对象的方法,只是对象.test1(),会把对象本身自动传给test1,因test1没有参数所以会抛出异常 pass
调用:对象.对象的绑定方法(),不用为self传值,就是给对象去用
特性:调用时会把对象本身当做第一个参数传给对象的绑定方法
2.什么是绑定到类的方法,如何定义,如何调用,给谁用?有什么特性
定义:在类内部定义的,并且被装饰器@classmethod修饰过的方法,都是绑定到类的方法
class Foo: @classmethod #把一个方法绑定给类:类.绑定到类的方法(),会把类本身当做第一个参数自动传给绑定到类的方法 def test(cls,x): print(cls,x) #拿掉一个类的内存地址后,就可以实例化或者引用类的属性了
调用:类.类的绑定方法(),不用为cls传值,就是给类去用
特性:调用时会把类本身当做第一个参数传给类的绑定方法
3.什么是解除绑定的函数,如何定义,如何调用,给谁用?有什么特性
定义:在类内部定义的,并且被装饰器@staticmethod修饰过的方法,就是解除绑定的方法,可以说staticmethod就是相当于一个普通的工具包
class Foo: def test1(self): pass def test2(): pass @classmethod def test3(cls): pass @classmethod def test4(): pass @staticmethod def test5(): pass f=Foo() print(Foo.test1)#<function Foo.test1 at 0x000000B1704AC8C8> print(Foo.test2)#<function Foo.test2 at 0x000000B1704AC950> print(Foo.test3)#<bound method Foo.test3 of <class '__main__.Foo'>> print(Foo.test4)#<bound method Foo.test4 of <class '__main__.Foo'>> print(Foo.test5)#<function Foo.test5 at 0x000000B1704ACAE8> print(f.test1)#<bound method Foo.test1 of <__main__.Foo object at 0x000000B1704AE1D0>> print(f.test2)#<bound method Foo.test2 of <__main__.Foo object at 0x000000B1704AE1D0>> print(f.test3)#<bound method Foo.test3 of <class '__main__.Foo'>> print(f.test4)#<bound method Foo.test4 of <class '__main__.Foo'>> print(f.test5)#<function Foo.test5 at 0x000000B1704ACAE8>
调用:test1与test2都是绑定到对象方法:调用时就是操作对象本身,test3与test4都是绑定到类的方法:调用时就是操作类本身,test5是不与任何事物绑定的:就是一个工具包,谁来都可以用,没有专门操作谁这么一说
特性:不管是类还是对象来调用,都没有自动传值这么一说了
4.什么是property,如何定义,如何使用,给谁用,什么情况下应该将一个属性定义成property,有什么好处?
定义:在类内部定义的,并且被装饰器@property修饰过的方法,就是类的特性,即property
import math class Circle: def __init__(self,radius): self.r=radius @property def area(self): return math.pi*self.r**2 @property def perimeter(self): return 2*math.pi*self.r c=Circle(7) print(c.r) print(c.area) print(c.perimeter)
调用:对象.对象的绑定方法,不用为self传值,也不用加()去运行,直接回返回函数的执行结果,就是给对象去用
意义:在保护隐私,或者隔离复杂度时使用property函数,也就是在封装的情况下。加了装饰器@property的属性还有其余两种方法:@特性名.setter和@特性名.deleter两个装饰器,property的好处就是让使用者以为是在调用类里面的变量,实则是函数,这种特性的使用方式遵循了统一访问的原则,而且被property装饰的属性会优先于对象的属性被使用,还可以设置接口供使用者调用来获取自己需要的数据。
作业二:
要求一:自定义用户信息数据结构,写入文件,然后读出内容,利用eval重新获取数据结构
对于文件的读写操作,可参考:Day5.对文件的增删改查-http://www.cnblogs.com/lxyoung/p/6678765.html
with open('user.db','w') as write_file: write_file.write(str({ "egon":{"password":"123",'status':False,'timeout':0}, "alex":{"password":"456",'status':False,'timeout':0}, })) with open('user.db','r') as read_file: data=read_file.read() d=eval(data) print(d['egon']['password'])# 123 print(d['egon']['status'])# False print(d['egon']['timeout'])# 0
要求二:定义用户类,定义属性db,执行obj.db可以拿到用户数据结构
class User: db_path='user.db' def __init__(self,username): self.username=username @property def db(self): data=open(self.db_path,'r').read() return eval(data) u1=User('egon') u2=User('alex') print(u1.db_path)# user.db print(u2.db)# {'egon': {'password': '123', 'status': False, 'timeout': 0}, 'alex': {'password': '456', 'status': False, 'timeout': 0}} print(u1.db[u1.username]["password"])# 123 print(u2.db[u2.username]["password"])# 456
要求三:分析下述代码的执行流程
import time#导入time模块 class User:#定义User这个类 db_path='user.db'#定义路径-User类下对象的共有的特性 def __init__(self,name):#定义User类下对象的独有的特性 self.name=name#对象独有的名字 @property#将下面的函数伪装成变量 def db(self):#定义db-User类下对象的共有的技能 with open(self.db_path,'r') as read_file:#打开路径文件获得文件句柄 info=read_file.read()#将读取的文件内容传给info这个变量 return eval(info)#将info这个字符串类型数据转换为字典类型数据并作为函数的返回值 @db.setter#实际意义就是修改db这个函数的返回值 def db(self,value):#因为是修改,所以定义是加一个新的参数 with open(self.db_path,'w') as write_file:#打开路径文件获得文件句柄,并且是覆盖的方式进行写操作 write_file.write(str(value))#将新的值赋值给文件的内容 write_file.flush()#将写入的新内容刷新至文件当中 def login(self):#定义一个与用户交互的登录函数,可参考:Day5.三次登陆后锁定-http://www.cnblogs.com/lxyoung/p/6678765.html data=self.db#实质是调用的@property下边这个函数,并把文件内容给了data这个变量 if data[self.name]['status']:#判断登陆状态 print('已经登录') return True if data[self.name]['timeout'] < time.time():#判断是否超时 count=0 while count < 3:#当次数小于3的时候执行下面代码 passwd=input('password>>: ') if not passwd:continue if passwd == data[self.name]['password']: data[self.name]['status']=True#若输入正确密码修改登录状态为Ture data[self.name]['timeout']=0#重置时间 self.db=data#实质是调用的@db.setter下边这个函数,修改过的data覆盖的写入文件中 break count+=1 else: data[self.name]['timeout']=time.time()+10#当前时间戳加10秒 self.db=data else: print('账号已经锁定10秒') u1=User('egon') u1.login() u1.login()#将密码正确输入,执行结果为已经登录。打开下面代码的注释并执行,将密码错误输入三次后,获得执行结果 # time.sleep(5) # u1.login() # time.sleep(6) # u1.login()
执行结果如下:
要求四:根据上述原理,编写退出登录方法(退出前要判断是否是登录状态),自定义property,供用户查看自己账号的锁定时间
import time class User: db_path='user.db' def __init__(self,name): self.name=name @property def db(self): with open(self.db_path,'r') as read_file: info=read_file.read() return eval(info) @db.setter def db(self,value): with open(self.db_path,'w') as write_file: write_file.write(str(value)) write_file.flush() @property def checktime(self): data = self.db print("您的用户还有%s秒解锁"%(data[self.name]['timeout']-time.time())) def login(self): data=self.db if data[self.name]['status']: print('已经登录') return True if data[self.name]['timeout'] < time.time(): count=0 while count < 3: passwd=input('password>>: ') if not passwd:continue if passwd == data[self.name]['password']: data[self.name]['status']=True data[self.name]['timeout']=0 self.db=data break count+=1 else: data[self.name]['timeout']=time.time()+10 self.db=data else: print('账号已经锁定10秒') def userexit(self): data = self.db if data[self.name]['status']: data[self.name]['status'] = False self.db = data print("成功退出登录") else: print("无法退出,您当前没有登录") u1=User('egon') # u1.login() # u1.login() # u1.userexit() # u1.userexit() # u1.login() u1.login() u1.login() u1.checktime time.sleep(3) u1.checktime