Python【day 17-2】面向对象-成员

''''''
'''
1、简述面向对象三大特性并用示例解释说明?【背写】
    1、封装
        狭义的封装:把一组属性封装到一个对象,创建对象的时候
        广义的封装:代码块,函数、对象、类、模块-py文件都是封装
                   把封装后的对象看成一个黑盒子,只需要关注输入和输出,不必关注黑盒子内部的实现
    2、继承
        1、避免代码的重复
        2、可扩展
            共有的写在父类,扩展的时候用子类
    3、多态

2. 面向中的变量分为哪几种?并用示例说明区别?【背写】
    1、成员变量
        写在构造方法中的,前面是self.  局部的意思
    2、类变量(静态变量)
        写在类中方法(成员方法)之外的变量,全局的意思
        多个对象共享的

3. 面向对象中方法有哪几种?并用示例说明区别?【背写】
    1、成员方法
        1、包括构造方法和普通方法
        2、第一个参数是self
        3、通过对象来直接调用
    2、静态方法
        1、参数不需要self
        2、写法是方法名字上面加上一行@staticmethod
        3、通过类名来调用
        4、把它理解成类中的函数即可
    3、类方法
        1、参数只有一个cls,表示可以说传入类名
        2、写法是方法名字上面加上一行@classmethos
        3、通过类名来调用
        4、可以在类方法中创建对象,设计模式

4. 面向对象中的属性有什么?并用示例说明?
   定义:用方法来表示一个属性(成员变量)
   写法:方法名字上面加一行@property
        只有一个参数self
        必须有返回值(属性取的就是返回值)
   调用:对象名.方法名
         注意方法名字后面不加小括号
   例子:人的年龄
        1、成员变量中,一般不存储人的年龄,因为年龄每年都会变
        2、成员变量中,存储的是人的生日
        3、可以用成员方法,根据生日计算年龄,但是年龄是一个属性-名称
           用方法-动词计算不是特别合适
        4、就引入了用方法的变种--属性来表示年龄

5. 简述静态方法和类方法的区别?
    1、写法不同
        前者方法名字前面加上@staticmethod
        后者方法名字前面加上@classmethod
    2、参数不同
        前者的参数没有self
        后者的参数是cls
    3、含义不同
        前者可以理解成类中的函数,不需要传self,对象
        后者的参数传入的是类名,主要用于对象的创建,设计模式

'''
6. 面向对象的方法中那个无需传参数?
    静态方法无需传参数
    成员方法self
    类方法cls

7. 面向对象中公有和私有成员,在编写和调用时有哪些不同?
    1、编写上
        后者名字前面需要加上__,前者不需要
    2、调用上
        后者不能通过对象直接访问
        后者可以通过对象调用公有成员方法的形式,访问私有变量或者私有方法
        (把私有变量或者私有方法写在公有成员方法中)

        前者可以通过对象直接访问
# 18.现有50条数据.请使用面向对象的思维来完成这50条数据的分页工作(升级题)
class Page:
    def __init__(self,lst,pagesize):
        self.lst = lst
        self.pagesize = pagesize
    def start(self):
        '''
        返回第一页的内容
        '''
    def end(self):
        '''
        返回最后一页的内容
        '''
    def index(self):
        '''
        返回指定页的内容
        '''
        page = input('请输入你要查询的数据的页数:')

'''
伪代码思路:
第一步
1、一共是6条数据,每页2条,分成3页
2、输入页数1,打印1-2(索引号和值都是1,2)
3、输入页数3,打印5-6

第二步
1、一共是5条数据,每页2条,分成3页
2、输入页数1,打印1-2(索引号和值都是1,2)
3、输入页数3,打印5

'''

class Page:
    def __init__(self,lst,pagesize):
        self.lst = lst
        self.pagesize = pagesize
    def start(self):
        '''
        返回第一页的内容
        '''
        # total_page = len(self.lst)/self.pagesize
        print(self.lst[:self.pagesize])
        return self.lst[:self.pagesize]

    def end(self):
        '''
        返回最后一页的内容
        '''
        total_page = len(self.lst) / self.pagesize
        # print(total_page)
        if type(total_page) == int:
            print(self.lst[-self.pagesize:])
            return self.lst[-self.pagesize:]
        else:
            result, remainder = divmod(len(self.lst),self.pagesize)
            # print(result)  2 商是2
            # print(remainder) 1 余数是1
            print(self.lst[-remainder:])  #[5]
            return self.lst[-remainder:]

    def specified_page(self,n):
        print(self.lst[self.pagesize*(n-1):self.pagesize*n])
        return self.lst[self.pagesize*(n-1):self.pagesize*n]

    def index(self):
        '''
        返回指定页的内容
        '''
        while 1:
            page = input('请输入你要查询的数据的页数,输入q退出:')
            if page.upper() == 'Q':
                print('退出了')
                break
            elif page == '1':
                self.start()
            elif page == '-1':
                self.end()
            elif page.isdigit() == False:
                print('只能输入数字,请输入数字')
            elif int(page) <= (len(self.lst)/self.pagesize)+1 :
                self.specified_page(int(page))
            # elif int(page) > (len(self.lst) / self.pagesize) + 1 :
            #     print('页码超出范围了')
            else:
                print('页码超出范围了')

# li1 = [1,2,3,4,5,6]
li1 = [1,2,3,4,5]
p1 = Page(li1,2)  #一共是5条记录,每页2条记录
p1.index()
print('------------------------18 ')
''''''
'''
19.在昨天最后一题的基础上.把数据写入到文件中.并且注册的时候需要到文件中判断是否重
复.如果重复提示不能注册.(升级题
'''

# 16.    补充代码:实现用户注册和登录
# class User:
#     def __init__(self,user,pwd):
#         self.user = user
#         self.pwd = pwd

class Account:
    def __init__(self):
        # user_list = []  #存放user对象  这个必须加上self变成成员变量才行
        # self.user_list = []  #存放user对象   #注意点2:这里必须加self,表示成员变量(可以在方法间使用)

        #新建文件
        # self.f1 = open('acount.txt',mode='w+',encoding='utf-8')  #先w+  后a+  可写可读 每次都清空,覆盖
        self.f1 = open('acount.txt',mode='a+',encoding='utf-8')  #先w+  后a+   可追加可读
        #1 新建文件,文件对象存储成成员变量,方便方法间使用

    def register(self): #1 注册功能
        print('欢迎来到注册页面')
        username = input('请输入你要注册的登录用户名:')
        password = input('请输入你要注册的登录密码:')
        # u1 = User(username,password)  #新建对象,对象中封装正确的用户名和密码
        # self.user_list.append(u1)  #self.user_list 表示成员变量(可以在方法间使用)
        # print(self.user_list) #[<__main__.User object at 0x00000098C5EDF0C8>]

        #一、先判断用户名是否在文件中已经存在
        self.f1.seek(0, 0)  # 1光标到文件开头   关键点1
        #是在第二次运行程序的时候,判断用户名是否存在的时候,从历史注册用户名中进行查找、判断、去重
        for i in self.f1:  # 2 遍历文件对象,读取文件中每一行
            if username == i.split('|')[0]:#3 判断用户输入的用户名和文件中已经存在的用户名进行比对
                print('用户名已经存在')
                break  #4,如果已经存在,就跳出整个for循环
        else: #5 如果没有任何break 正常结束,执行else,如果有break,else下面就不会执行
        # 如果不写else,即使有break,下面的内容也会执行; 有没有else,在break的情况下,执行是完全不同的
            #6 往空白文件中写入用户名和密码
            self.f1.write(username+'|'+password+'
')
            self.f1.flush()  #7 将写入的及时刷新到文件
            # self.f1.seek(0,0)  #光标到文件开头
            # self.f1.close()  #8 先不关闭,如果在这里关闭,就会报错
            #ValueError: I/O operation on closed file.

    def login(self): #2 登录接口
        print('欢迎来到登录页面')
        n = 0
        for i in range(3):  #3次重试机会
            username2 = input('请输入你要登录的登录用户名:')
            password2 = input('请输入你要登录的登录密码:')
            # for i in self.user_list:   #循环遍历用户对象  self.user_list表示成员变量(可以在方法间使用)
            self.f1.seek(0, 0)  # 1、光标到文件开头  关键点2
            #2 在用户输入用户名和密码登录的时候,需要从文件开头遍历已经注册的用户名和密码
            for i in self.f1:   #3 循环遍历文件对象  self.f1表示成员变量(可以在方法间使用)
                # if i.user == username2 and i.pwd == password2:  #关键点1 i.user取的是对象的属性
                if i.split('|')[0].strip() == username2 and i.split('|')[1].strip() == password2:  #
                    #4 strip()是为了去掉换行符
                    #5 把用户输入的用户名密码和文件中的用户名密码进行匹配
                    print('登录成功')
                    # self.f1.close()  #关闭文件  检查点
                    #ValueError: I/O operation on closed file.
                    # break  #注意点3  只能退出当层内循环
                    return  #注意点4  可以退出内层循环和外层循环(一次退出2层循环)
            else:  #6 这个else必须是和for同级,而不能是和if同级  关键点2
                #因为期望结果的每行判断完,才能说明登录失败
                n+=1
                print('登录失败,请重新输入,你还有 %s 次重试机会' % (3-n) )
        self.f1.close()  # 7关闭文件 注意这行代码的位置  关键点3

    def run(self):#3 选择注册还是登录,先注册,后登录
        while 1:
            choice = input('请选择,1表示注册,2表示登录,Q表示退出:')
            if choice == '1':
                self.register()  #注意点1  方法前面必须加上self
            elif choice == '2':
                self.login()  #注意点1  方法前面必须加上self
            elif choice.upper() == 'Q':
                print('已经退出了')
                break
            else:
                print('你输入的不对,请重新输入')

a1 = Account()
a1.run()
'''
注册和登录的逻辑:
1、注册的时候,把正确的用户名和密码,比如:jack/123 存入数据库(或者对象中,列表中)
   保存之前,先判断用户名在文件中是否已经存在,如果重复提示不能注册
2、登录的时候,输入登录用户名和密码,拿用户输入的用户名和密码 和之前注册的用户名和密码进行比对
   如果相等匹配,就是登录成功
   如果不相等不匹配,就是登录失败
3、之前是将注册后的用户名和密码存在列表中--内存中
   现在需要存在文件中(类似于-持久化到数据库)

注意点:
1、光标的位置回到文件的开头
2、关闭文件对象的代码所在的位置

扩展:
1、能否把对象写入文件中--不能
   --文件中只能写入字符串,不能写入对象
2、先实现用户名|密码+换行符 写入文件
3、注册用户名去重--ok

接口的概念:
1、接口可以对外提供服务,对外提供功能,接口是服务端
2、客户端-发起端发起请求,调用登录接口
    只需要传入正确的参数(用户名和密码),就可以登录成功
'''
原文地址:https://www.cnblogs.com/wangtp/p/12020172.html