• python_面向对象编程


    一、面向对象编程

    # 1.什么是面向对象
        面向过程与面向对象
            面向过程编程:解决问题从过程出发,解决问题步骤化
    
            面向对象编程:解决问题从对象出发,解决问题找对象
    
        对象与类
            类:对象的类型 => 数字
                具有相同特征与行为集合的抽象
    
            对象:类的具体表现 => 数字10
                类的实例化,就是具有特征与行为实际存在的个体(每一个对象都是唯一的)
    
    # 2.为什么要面向对象编程
            面向过程:开发成本高,解决问题局限性小
            面向对象:开发成本低,解决问题局限于对象
    
            问题:'abc' => {'a', 'b', 'c'}
                面向过程: 自己写
                面向对象:str => list => set  #(引用模块)
    
            开发:优选面向对象(找解决问题的对象),
            再考虑找多个对象(面向对象与面向过程的结合),
            最后自己去封装一个可以解决问题的对象(对外是面向对象的体现,内部解决问题的核心是面向过程)

    # 例如:
    s = 'abc'  # => ['a', 'b', 'c']
    # 解决方案
    # re.findall()  list初始化方法
    # for循环append
    
    # 面向过程:解决问题步骤化
    res = []
    for c in s:
        res.append(c)
    print(res)
    
    # 面向对象:解决问题找对象
    #       -- 对象如何解决问题:对象.解决问题的方法()
    
    # 找re对象
    import re
    res = re.findall(r'[a-z]', s)
    print(res)
    
    # 找list对象
    res = list(s)
    print(res)
    
    # 模块 md.py
    def print_num(a):
        print(a)
    
    from md import print_num as pn
    pn(100)
    pn(200)

    二、类的声明语法

    class 类名:
        # 在该缩进下(在类下)定义多个函数,类名就可以整体管理所有的函数,通过点语法来调用具体的函数
        def fn1():
            print('fn1 run')
        def fn2():
            print('fn2 run')
        def fn3():
            print('fn3 run')
            
    # 类名的命名规范:采用大驼峰

    三、点语法与名称空间

    def fn():
        pass
    
    class Fn():
        def a_fn():
            pass
        pass
    
    import md
    
    print(fn, fn.__dict__)
    # <function fn at 0x0000000001CF2EA0> {}
    
    print(Fn, Fn.__dict__)
    # <class '__main__.Fn'> {'__module__': '__main__', 'a_fn': <function Fn.a_fn at 0x0000000002947048>, '__dict__': <attribute '__dict__' of 'Fn' objects>, '__weakref__': <attribute '__weakref__' of 'Fn' objects>, '__doc__': None}
    
    print(md, md.__dict__)
    #<module 'md' from 'F:\安装包\JetBrains\JetBrains\Projects\09\代码\part2\md.py'> {'__name__': 'md', '__doc__': None, '__package__': '', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000001EA6E10>, '__spec__': ModuleSpec(name='md', loader=<_frozen_importlib_external.SourceFileLoader object at 0x0000000001EA6E10>, origin='F:\安装包\JetBrains\JetBrains\Projects\09\代码\part2\md.py'), '__file__': 'F:\安装包\JetBrains\JetBrains\Projects\09\代码\part2\md.py', '__cached__': 'F:\安装包\JetBrains\JetBrains\Projects\09\代码\part2\__pycache__\md.cpython-36.pyc', '__builtins__': {'__name__': 'builtins', '__doc__': "Built-in functions, exceptions, and other objects.
    
    Noteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", '__package__': '', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>), '__build_class__': <built-in function __build_class__>, '__import__': <built-in function __import__>, 'abs': <built-in function abs>, 'all': <built-in function all>, 'any': <built-in function any>, 'ascii': <built-in function ascii>, 'bin': <built-in function bin>, 'callable': <built-in function callable>, 'chr': <built-in function chr>, 'compile': <built-in function compile>, 'delattr': <built-in function delattr>, 'dir': <built-in function dir>, 'divmod': <built-in function divmod>, 'eval': <built-in function eval>, 'exec': <built-in function exec>, 'format': <built-in function format>, 'getattr': <built-in function getattr>, 'globals': <built-in function globals>, 'hasattr': <built-in function hasattr>, 'hash': <built-in function hash>, 'hex': <built-in function hex>, 'id': <built-in function id>, 'input': <built-in function input>, 'isinstance': <built-in function isinstance>, 'issubclass': <built-in function issubclass>, 'iter': <built-in function iter>, 'len': <built-in function len>, 'locals': <built-in function locals>, 'max': <built-in function max>, 'min': <built-in function min>, 'next': <built-in function next>, 'oct': <built-in function oct>, 'ord': <built-in function ord>, 'pow': <built-in function pow>, 'print': <built-in function print>, 'repr': <built-in function repr>, 'round': <built-in function round>, 'setattr': <built-in function setattr>, 'sorted': <built-in function sorted>, 'sum': <built-in function sum>, 'vars': <built-in function vars>, 'None': None, 'Ellipsis': Ellipsis, 'NotImplemented': NotImplemented, 'False': False, 'True': True, 'bool': <class 'bool'>, 'memoryview': <class 'memoryview'>, 'bytearray': <class 'bytearray'>, 'bytes': <class 'bytes'>, 'classmethod': <class 'classmethod'>, 'complex': <class 'complex'>, 'dict': <class 'dict'>, 'enumerate': <class 'enumerate'>, 'filter': <class 'filter'>, 'float': <class 'float'>, 'frozenset': <class 'frozenset'>, 'property': <class 'property'>, 'int': <class 'int'>, 'list': <class 'list'>, 'map': <class 'map'>, 'object': <class 'object'>, 'range': <class 'range'>, 'reversed': <class 'reversed'>, 'set': <class 'set'>, 'slice': <class 'slice'>, 'staticmethod': <class 'staticmethod'>, 'str': <class 'str'>, 'super': <class 'super'>, 'tuple': <class 'tuple'>, 'type': <class 'type'>, 'zip': <class 'zip'>, '__debug__': True, 'BaseException': <class 'BaseException'>, 'Exception': <class 'Exception'>, 'TypeError': <class 'TypeError'>, 'StopAsyncIteration': <class 'StopAsyncIteration'>, 'StopIteration': <class 'StopIteration'>, 'GeneratorExit': <class 'GeneratorExit'>, 'SystemExit': <class 'SystemExit'>, 'KeyboardInterrupt': <class 'KeyboardInterrupt'>, 'ImportError': <class 'ImportError'>, 'ModuleNotFoundError': <class 'ModuleNotFoundError'>, 'OSError': <class 'OSError'>, 'EnvironmentError': <class 'OSError'>, 'IOError': <class 'OSError'>, 'WindowsError': <class 'OSError'>, 'EOFError': <class 'EOFError'>, 'RuntimeError': <class 'RuntimeError'>, 'RecursionError': <class 'RecursionError'>, 'NotImplementedError': <class 'NotImplementedError'>, 'NameError': <class 'NameError'>, 'UnboundLocalError': <class 'UnboundLocalError'>, 'AttributeError': <class 'AttributeError'>, 'SyntaxError': <class 'SyntaxError'>, 'IndentationError': <class 'IndentationError'>, 'TabError': <class 'TabError'>, 'LookupError': <class 'LookupError'>, 'IndexError': <class 'IndexError'>, 'KeyError': <class 'KeyError'>, 'ValueError': <class 'ValueError'>, 'UnicodeError': <class 'UnicodeError'>, 'UnicodeEncodeError': <class 'UnicodeEncodeError'>, 'UnicodeDecodeError': <class 'UnicodeDecodeError'>, 'UnicodeTranslateError': <class 'UnicodeTranslateError'>, 'AssertionError': <class 'AssertionError'>, 'ArithmeticError': <class 'ArithmeticError'>, 'FloatingPointError': <class 'FloatingPointError'>, 'OverflowError': <class 'OverflowError'>, 'ZeroDivisionError': <class 'ZeroDivisionError'>, 'SystemError': <class 'SystemError'>, 'ReferenceError': <class 'ReferenceError'>, 'BufferError': <class 'BufferError'>, 'MemoryError': <class 'MemoryError'>, 'Warning': <class 'Warning'>, 'UserWarning': <class 'UserWarning'>, 'DeprecationWarning': <class 'DeprecationWarning'>, 'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>, 'SyntaxWarning': <class 'SyntaxWarning'>, 'RuntimeWarning': <class 'RuntimeWarning'>, 'FutureWarning': <class 'FutureWarning'>, 'ImportWarning': <class 'ImportWarning'>, 'UnicodeWarning': <class 'UnicodeWarning'>, 'BytesWarning': <class 'BytesWarning'>, 'ResourceWarning': <class 'ResourceWarning'>, 'ConnectionError': <class 'ConnectionError'>, 'BlockingIOError': <class 'BlockingIOError'>, 'BrokenPipeError': <class 'BrokenPipeError'>, 'ChildProcessError': <class 'ChildProcessError'>, 'ConnectionAbortedError': <class 'ConnectionAbortedError'>, 'ConnectionRefusedError': <class 'ConnectionRefusedError'>, 'ConnectionResetError': <class 'ConnectionResetError'>, 'FileExistsError': <class 'FileExistsError'>, 'FileNotFoundError': <class 'FileNotFoundError'>, 'IsADirectoryError': <class 'IsADirectoryError'>, 'NotADirectoryError': <class 'NotADirectoryError'>, 'InterruptedError': <class 'InterruptedError'>, 'PermissionError': <class 'PermissionError'>, 'ProcessLookupError': <class 'ProcessLookupError'>, 'TimeoutError': <class 'TimeoutError'>, 'open': <built-in function open>, 'quit': Use quit() or Ctrl-Z plus Return to exit, 'exit': Use exit() or Ctrl-Z plus Return to exit, 'copyright': Copyright (c) 2001-2017 Python Software Foundation.
    # All Rights Reserved. ...
    
    # 访问名字的底层
    print(Fn.__dict__['__module__'])  # __main__
    # 访问名字的语法优化
    print(Fn.__module__)  # __main__
    # 总结:对象.名字 本质 对象.__dict__['名字']
    
    
    # 赋值
    fn.name = '我写的函数'
    print(fn.__dict__)  # {'name': '我写的函数'}
    print(fn.__dict__['name']) # 我写的函数
    print(fn.name) # 我写的函数
    
    # 了解:对象的名称空间,与对象内部的名称空间不是同一个
    print('========================================')
    def func():
        a = 10
        b = 20
        print(locals()) # {'b': 20, 'a': 10}
    func()
    print(func.__dict__)  # {}
    
    # 记住:
    # 对象.名字 = 值 是为该对象添加一个名称空间的名字,
    # 也只能通过 对象.名字 来使用
    func.name = 'func function'
    print(func.name) # func function
    View Code
    # 可以产生名称空间的语法
    
    def fn():  # 具有名称空间:fn.__dict__
        pass
    
    class Fn():  # 具有名称空间:Fn.__dict__
        pass
    
    import md  # 具有名称空间:md.__dict__
    
    
    # 名称空间如何为一个名字设置值,或访问一个名字对应的值
    fn.__dict__[名字] = 值  # 设置值
    print(fn.__dict__[名字])  # 取值
    
    
    # 重点:名称空间取值赋值的语法优化:点语法
    fn.名字 = 值  # 设置值
    print(fn.名字)  # 取值

    四、类与对象的声明

    class People:
        name = ''
        
    p1 = People()
    p2 = People()
    
    # 结论1:类与每一个对象的名称空间都是独立的
    print(p1.__dict__)  # {}
    print(p2.__dict__)  # {}
    print(People.__dict__)  # {'name': '人', ...系统的}
    
    # 结论2:类与每一个对象都可以使用类中的名字
    print(People.name)  #
    print(p1.name)  #
    print(p2.name)  #
    
    # 结论3:对象访问名字,优先访问自己的,自己没有再访问类的
    p1.name = '张三'
    p2.user = '李四'
    print(People.name)  #
    print(p1.name)  # 张三
    print(p2.user)  # 李四
    print(p2.name)  #
    
    # 重点:
    # 对象操作名字,操作的是对象的,类操作名字操作的是类的,之间相互不干预
    # 类只能访问类的名字
    # 对象访问名字,优先访问自身的,自身没有再访问类的

    五、类的初始化方法

    # 可以快速为类实例化出的每一个对象,产生对象名称空间中的多个名字
    
    class NewTeacher:
        def __init__(self, name, sex, age):
            # print(id(self))  # self就是实例化产生的对象(nt1)
            # print('init 被调用了')
            self.name = name
            self.sex = sex
            self.age = age
        pass
    
    # 类()就是在调用类的__init__方法
    nt1 = NewTeacher('王大锤', '', 58)
    # print(id(nt1))
    print(nt1.name, nt1.sex, nt1.age)
    
    
    nt2 = NewTeacher('王小锤', '', 48)
    print(nt2.name, nt2.sex, nt2.age)

    演化:

    class Teacher:
        name = '教授'
    
    def set_obj(obj, name, sex, age):
        obj.name = name
        obj.sex = sex
        obj.age = age
    
    t1 = Teacher()
    # t1.name = 'C老师'
    # t1.sex = "女"
    # t1.age = 36
    set_obj(t1, 'C老师', "", 36)
    print(t1.name, t1.sex, t1.age)
    
    t2 = Teacher()  # 类()应该就是函数的调用,函数调用可以传参,能优化属性的赋值
    # t2.name = 'W老师'
    # t2.sex = "女"
    # t2.age = 28
    set_obj(t2, 'W老师', "", 28)
    print(t2.name, t2.sex, t2.age)
    
    # t3 = Teacher()
    # set_obj(t3, '王大锤', '男', 58)
    
    # 能不能再优化 => t3 = Teacher('王大锤', '男', 58)
    # print(t3.name, t3.sex, t3.age)
    例子

    六、类的方法分类

    # 对象方法:直接定义的方法,建议由对象调用,类中内部需要使用对象的数据时的方法要定义为对象方法
    # 1.对象方法对象调用,默认传入对象给第一个形参 
    class 类名:
        def fn(self, *args, **kwargs): pass
    
    # 类方法:被classmethod修饰的方法,建议由类调用,类中内部需要使用类的数据时的方法要定义为类方法
    # 2.类方法由类调用,默认传入类给第一个形参
    class 类名:
        @classmethod
        def fn(cls, *args, **kwargs): pass
    
    # 静态方法:被staticmethod修饰的方法,建议由类调用,类中内部不需要类相关数据时的方法要定义为静态方法
    # 3.静态方法建议由类调用,默认不传入调用者
        @staticmethod
        def fn(*args, **kwargs): pass

    案例1:

    class Student:
        name = '学生'
        def __init__(self, name, id_num):
            self.name = name
            self.id_num = id_num
    
        # 对象(成员)方法
        def study(self):  # 在类中产生的所有方法,都是属于类的,但是对象可以调用
            # print('self>>', id(self))
            print("%s在学习" % self.name)
    
        # 类方法: 第一个参数就是用来接收调用者,类方法的调用者一定是类,所以第一个参数命名约定为cls
        @classmethod
        def fn(cls):
            print(id(cls))
    
    
        # 静态方法
        @staticmethod
        def func():
            print('func run')
    
    stu1 = Student('Bob', 1)
    print(stu1.__dict__)  # {'name': 'Bob', 'id_num': 1}
    print(stu1.name) # Bob
    # stu1.__dict__.clear()  # 清空stu1
    # print(stu1.__dict__)  # {}
    # print(stu1.name) # 学生
    
    print("====================")
    stu2 = Student('Tom', 2)
    stu1.study() # Bob在学习
    print(id(stu1)) # 32140984
    stu2.study() # Tom在学习
    print(id(stu2)) #
    print("====================")
    # 结论1:对象调用类中的方法,默认隐式将对象自身传入,在方法中,第一个参数用self来接受传入的对象
    # Student.fn(Student) => Student.fn()
    # print(id(Student))
    
    Student.fn() # 41758904
    print(id(Student)) # 41758904
    
    # 结论2:类中用@classmethod装饰的方法,是类方法,用类来调用,默认会将类传入给方法的第一个参数
    
    print("====================")
    Student.func() # func run
    stu1.func() # func run
    # 结论3:类中用@staticmethod装饰的方法,是静态方法,可以被类和对象调用,默认不会将类或对象传入
    View Code

    案例二:类的不同方法应用

    # 案例
    class Book:
        name = ''
        def __init__(self, name, price):
            self.name = name
            self.price = price
    
        # 书的详情信息 => 一定需要知道哪本书
        # @classmethod  # 类调用cls就是类,对象调用处理成 对象.__class__
    
        def detail(self):
            # print(cls.name)
            print("%s的价格为:%s元" % (self.name, self.price))
    
    book1 = Book('西游记', 38.8)
    book2 = Book('三国', 88.8)
    book1.detail()
    book2.detail()
    # print(book1.__class__)
    
    
    # 静态方法:方法的内部不需要对象及类的参与,所以定义为静态方法,但是方法必须由调用者,建议用类就可以了
    class NumTool:  # 工具类 => 模块
        def max_two(self, n1, n2):
            max_num = n1 if n1 > n2 else n2
            print('大数是%s' % max_num)
    
        @staticmethod
        def new_max_two(n1, n2):
            max_num = n1 if n1 > n2 else n2
            print('大数是%s' % max_num)
    
    n1 = NumTool()
    n2 = NumTool()
    n1.max_two(10, 20)
    n2.max_two(10, 20)
    
    NumTool.new_max_two(10, 20)
    n1.new_max_two(10, 20)
    
    
    # 类方法:方法的内部需要类的参与,所以定义为类方法,第一个参数默认传类
    class NewNumTool:
        PI = 3.14
    
        @classmethod
        def new_max_two(cls, n1, n2):
            max_num = n1 if n1 > n2 else n2
            return max_num
    
        @classmethod
        def new_max_three(cls, n1, n2, n3):
            # max_num = "想去复用new_max_two"
            max_num = cls.new_max_two(n1, n2)
            max_num = cls.new_max_two(max_num, n3)
            return max_num
    
        @classmethod
        def is_PI(cls, num):
            if num == cls.PI:
                return True
            return False
    
    
    res = NewNumTool.new_max_three(1, 5, 3)
    print('大数是%s' % res)
    
    print(NewNumTool.is_PI(3.149))
    View Code

     七、封装

    # 什么是封装:将类的一下属性和方法对外隐藏,对内可见
    # 为什么要封装:为属性和方法的操作添加权限,具体权限都是通过自定义逻辑来处理
    
    # 封装的手段:在类属性方法,对象属性方法,静态方法名字前添加 __
    # 只要是通过 __名字 这种命名规范,就是对外隐藏
        # 本质:__名字 封装隐藏变量的本质是 将名字修饰成 _类名__名字
    
    # 对外解决封装的方式
    # 1.如果真的不想让外界访问,就不对外提供访问数据的方法
    # 2.如果想让外界访问,可以对外提供访问数据的方法,方法具有逻辑,使用可以添加操作权限
    class Test:
        def __init__(self, name):
            # __name只是对外隐藏,对内可见
            self.__name = name
    
        def get_name(self):
            return self.__name
    
        def set_name(self, name):
            if 'sb' not in name:  # 对数据的修改可能会产生数据的安全性问题,可以添加限制条件
                self.__name = name
    # 重点:封装的对外访问语法的优化
    class User:
        def __init__(self, name):
            self.__name = name
    
        @property  # 将方法伪装成属性
        def name(self):
            return self.__name
    
        @name.setter  # 能为有伪装get方法的(方法)属性,再伪装set方法
        def name(self, value):
            self.__name = value
    
        @name.deleter
        def name(self):
            del self.__name
            
        # 总结:
        # 1.对象没了,对象的属性也就没了,所以不需要属性 @名字.deleter
        # 2.对外提供get方法是基础,@property,如果没有,外界不可读不可写
        # 3.如果有@property,则可以 @名字.setter,有set,为可读可写,无set为只读
    
        @property  # 伪装的属性方法,不需要一定有 __开头 的名字与之对应
        def pwd(self):
            return '123456'
    
    u1 = User('Owen')
    print(u1.name)  # 如果一个方法伪装成属性,对象.方法名 就会自动调用该方法
    
    u1.name = 'Zero'
    print(u1.name)
    
    # del u1.name
    # print(u1.name)
    
    print(u1.pwd)

    #@property 将方法伪装成属性,从而可以像__init__里的属性一样调用u1.name

     八、类的继承

    什么是继承
        继承是一种新建类的方式,继承的类称之为子类或派生类
        被继承的类称之为父类或基类或超类
        子类继承父类,也就意味着子类继承了父类所有的属性和方法
        可以直接调用
    为什么要有继承
        减少代码冗余
    如何使用
    class Parent1:
        pass
    class Parent2:
        pass
    class Son1(Parent1):
        pass
    # python中支持多继承
    class Son2(Parent1,Parent2):
        pass
    # 如何查看类的父类
    print(Son1.__bases__) # (<class '__main__.Parent1'>,)
    print(Son2.__bases__) # (<class '__main__.Parent1'>, <class '__main__.Parent2'>)
    # 自定义的没有显示继承任何类的父类到底有没有偷偷继承某个类呢?
    print(Parent1.__bases__) # (<class 'object'>,)
    print(Parent2.__bases__) # (<class 'object'>,)
    # python2:类如果没有显示继承任何类的情况下,不继承任何类
    # python3:类如果没有显示继承任何类的情况下,默认都继承object类
    
    经典类与新式类
       经典类:
            不继承object或者其子类的类  叫经典类  
       新式类: 
            继承object或者其子类的类    叫新式类
    # ps:经典类与新式类只在python2有区分
    #python3中只有新式类

    派生:

    # 派生:在继承了父类的属性和方法的基础之上 自己定义了其他的属性和方法
    # 如果派生出的方法与父类的同名了 那么相当于覆盖了父类的方法
    
    # 类:一系列对象相似的特征与技能的结合体
    # 类与类之间相似的特征与技能的结合体  >>> 父类
    # 类:一系列对象相似的特征与技能的结合体
    # 类与类之间相似的特征与技能的结合体  >>> 父类
    import pickle
    class OldboyPeople:
        school = 'oldboy'
        def __init__(self,name,age,gender):
            self.name = name
            self.age = age
            self.gender = gender
    
        def save(self):
            with open(self.name,'wb') as f:
                pickle.dump(self,f)
    
    class OldboyStudent(OldboyPeople):
        def choose_course(self):
            print('%s is choosing course'%self.name)
    
    
    class OldboyTeacher(OldboyPeople):
        def __init__(self,name,age,gender,level):
            OldboyPeople.__init__(self,name,age,gender)
            self.level = level
    
        def score(self):
            print('%s is score'%self.name)
    
    stu = OldboyStudent('simon',18,'male')
    print(stu.name) # simon
    stu.save() # 创建文件存数据
    
    tea = OldboyTeacher('xc',18,'male',10)
    print(tea.name) # simon
    tea.save()

    子类方法中调用父类的方法:

     # 方法一:指名道姓
    # OldboyPeople.__init__(self,name,age,gender)   跟继承一点关系都没有
    
    # 方法二:和继承有关系
    # 单继承情况下的属性查找
    class B:
        def f1(self):
            print('from B f1')
    
        def f2(self):
            print('from B f2')
            self.f1()
    class A(B):
        def f1(self):
            print('from A f1')
    obj = A()
    obj.f2()
    """
    from B f2
    from A f1
    """
    # 上面的例子可以看出:类是查找顺序是先查找自己,再查找父类

    # 多继承
    # 无论是python2还是python3继承都遵循深度优先(菱型继承除外)
    # 深度优先:依次先从左边分支查找完后向右查找
    # # 多继承
    class D:
        # def test(self):
        #     print('D')
        pass
    class E:
        def test(self):
            print('E')
    class F:
        def test(self):
            print('F')
    class A(D):
        # def test(self):
        #     print('A')
        pass
    class B(E):
        # def test(self):
        #     print('B')
        pass
    class C(F):
        def test(self):
            print('C')
    class G(A,B,C):
        # def test(self):
        #     print('G')
        pass
    
    obj = G()
    obj.test() # E
    View Code
    # 调用方式
    import pickle
    class OldboyPeople:
        school = 'oldboy'
        def __init__(self,name,age,gender):
            self.name = name
            self.age = age
            self.gender = gender
        def save(self):
            with open(self.name,'wb') as f:
                pickle.dump(self,f)
    
    
    class OldboyTeacher(OldboyPeople):
        def __init__(self,name,age,gender,level):
            # OldboyPeople.__init__(self,name,age,gender)
            # super(OldboyTeacher,self).__init__(name,age,gender)
            super().__init__(name,age,gender) # 调用
            self.level = level
    tea = OldboyTeacher('ymc',18,'male',10)
    print(tea.name) # ymc
    tea.save()

    MRO列表,C3算法

    # mro列表   C3算法
    class D:
        pass
    class E:
        pass
    class F:
        pass
    class A(D):
        pass
    class B(E):
        pass
    class C(F):
        pass
    class G(A,B,C):
        pass

    print(G.mro()) """ G A D B E C F [<class '__main__.G'>, <class '__main__.A'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class 'object'>] """
    # super是严格按照mro列表的顺序调用父类的方法的!!!
    class A:
        def f1(self):
            print('from a f1')
        def f2(self):
            print('from a f2')
            super().f1()
    class B:
        def f1(self):
            print('from b f1')
        def f2(self):
            print('from b f2')
    class C(A,B):
        def f1(self):
            print('from c f1')
    print(C.mro())
    # [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
    obj = C()
    obj.f2()
    """
    from a f2
    from b f1
    """

    九、多态与多态性

    # 什么是多态
        一种事物的不同形态(动物:人,狗,猫),代码层面上来说其实就是继承      
    # 为什么要有多态
        多态仅仅是一个概念
    # 多态性:在不需要考虑对象具体类型的情况下 调用对象的方法    
    # 如何使用
    class Animal:
        def talk(self):
            pass
    class People(Animal):
        def talk(self):
            print('hello')
    class Dog(Animal):
        def talk(self):
            print('wangwang')
    class Cat(Animal):
        def talk(self):
            print('miaomiao')
    people = People()
    dog = Dog()
    cat = Cat()
    
    people.talk()
    dog.talk()
    cat.talk()

    # 例如:len获取长度

    十、反射

    # 通过字符串来操作对象的属性或方法
    # 通过字符串来操作对象的属性或方法
    class User:
        school = 'oldgirl'
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def func(self):
            print('func')
    
    # hasattr判断对象是否有某个属性或方法
    print(User.school) # oldgirl
    print('school' in User.__dict__) # True
    print('xxx' in User.__dict__) # False
    print(hasattr(User,'school')) # True
    print(hasattr(User,'xxx')) # False
    print(hasattr(User,'func')) # True
    print('func' in User.__dict__) # True
    d = {'name':"jason"}
    print(d.get('password','hahahahahaha'))  # hahahahahaha
    
    # getattr 取类中的属性或方法
    print(getattr(User,'school')) # oldgirl
    print(getattr(User,'func')) # <function User.func at 0x00000000021F7048>
    print(User.__dict__['school']) # oldgirl
    print(User.__dict__['func']) # <function User.func at 0x00000000027D7048>
    # print(getattr(User,'xxx')) # 获取没有的报错
    if hasattr(User,'xxx'):
        getattr(User,'xxx')
    
    # setattr
    obj = User('simon',18)
    setattr(obj,'gender','male')  # obj.gender = 'male'
    print(obj.__dict__)
    
    # delattr
    delattr(User,'school')
    print(User.__dict__)

    十一、内置方法

    class User:
        def __init__(self,name,password):
            self.name = name
            self.password = password
    
        def __str__(self):
            # return '%s:%s'%(self.name,self.password)
            return '我被打印了,自动触发'
    
        def __getattr__(self, item):
            print(item)
    
        def __setattr__(self, key, value):
            print(key,value)
    
    # __str__对象被执行了打印操作  自动触发
    obj = User('simon',123)
    print(User)
    print(obj)
    """
    name simon
    password 123
    <class '__main__.User'>
    我被打印了,自动触发
    """
    
    # __getattr__ 当对象获取一个不存在的属性时候才会触发
    obj = User('simon',18)
    print(obj.name)
    """
    name simon
    password 18
    name
    None
    """
    
    # __setattr__: obj.name = 'xxx'  固定句式
    obj = User('simon',18)
    obj.sex = 'sexy'
    """
    name simon
    password 18
    sex sexy
    """
    
    class Demo(dict):
        def __getattr__(self, item):
            return self.get(item)
    d = Demo(name='simon',password=123)
    print(d.name) # simon
    print(d.password) # 123

    作业一:

    1.自定义一个 Fruit 类:该类有一个 类属性: identify:值为"水果",有两个对象属性: name,price:值由实例化对象时赋值,
    一个类方法: get_identify:打印类属性identify的值,
    一个对象方法:get_total_price(num):打印『%s个%s值%s钱』,
    一个静态方法:packing(*fruits) 静态方法(装箱)的思路分析 red_apple = Fruit("红苹果", 10) green_apple = Fruit("青苹果", 10) yellow_banana = Fruit("黄香蕉", 8) 调用:Frulit.packing(red_apple, green_apple, yellow_banana) 打印:一箱装了2个苹果1个香蕉 2.自定义一个 Person 类,该类具有 name、weight、height、sex 四个对象属性, -- 对name属性进行封装,但是外界任然可以访问name以及设置name -- 有一个方法属性bmi(标准体重),可以获取一个人的bmi,bmi只读不可写,bmi计算规则 -- 男:(身高cm-80)× 70﹪ | 女:(身高cm-70)× 60﹪ 提示:类属性就是直接写在类中的变量,对象属性就是写在__init__方法中的用self.属性 = 值 赋值的属性,方法属性就是用 @property 修饰的方法伪装成的属性 4.用面向对象实现 植物大战僵尸游戏 1).定义一个僵尸Zombie类,该类可以实例化出多种僵尸对象,僵尸对象产生默认都有 名字name、血量HP、防具armor -- 名字:普通僵尸 | 路障僵尸 | 铁桶僵尸 -- 血量:默认就是100,不需要外界提供 -- 防具:不需要外界提供,从名字中分析确定,防具的值是一个列表,从名字分析得到 -- ['', 0] | ['路障', 5] | ['铁桶', 15] => [防具名, 防具的防御值] -- 通过@property的getter、setter方式,对外提供防具的两个访问接口armor_name与armor_count -- armor_name可以取值、赋值、删除值:通过一个 -- eg: 普通僵尸对象.armor_name = '铁桶',不仅改变了防具名 -- 普通僵尸对象的名字name也会变成 铁桶僵尸 -- armor_count只可以取值 2).定义一个角色User类,该类有名字name属性、以及打僵尸的beat方法 -- 名字:随意自定义 -- beat:该方法需要传入一个僵尸对象 -- 在方法内部可以实现:某某用户攻击了某某个僵尸,僵尸损失多少血,还剩多少血 -- 每一次攻击,都固定扣除25滴血,但是不同的僵尸会被防具相应抵消掉一定的伤害值 -- 循环攻击僵尸,3s攻击一次,僵尸被击杀后,打印 某某用户击杀了某某个僵尸 并结束方法 3).定义一个Game类,该类有一个name属性,属性值为 "植物大战僵尸" ,该类中有一个start方法,通过Game.start()来启动游戏 -- 游戏一开始先显示游戏的名字 植物大战僵尸游戏 -- 会随机产生三种僵尸,总共产生三个作为要被击杀的对象 -- 生成一个有角色名的角色,依次去击杀随机产生的每一只僵尸 -- 开始击杀第一只僵尸 => 某某用户攻击了某某个僵尸,僵尸损失多少血,还剩多少血 => 某某用户击杀了某某个僵尸 => 第一只僵尸已被击杀完毕 => 开始击杀第二只僵尸 ... => 第三只僵尸已被击杀完毕

    作业二:

    角色:学校、学员、课程、讲师
    要求:
    1. 创建北京、上海 2 所学校---学校
    2. 创建linux , python , go 3个课程 , linuxpy 在北京开, go 在上海开 ----课程、地点
    3. 课程包含,周期,价格,通过学校创建课程-----时间、价格、
    4. 通过学校创建班级, 班级关联课程、讲师---班级、课程、讲师
    5. 创建学员时,选择学校,关联班级 ---学员、学校、班级
    5. 创建讲师角色时要关联学校,---讲师、学校
    6. 提供两个角色接口
    6.1 学员视图, 可以注册, 交学费, 选择班级,---》注册、学费、班级
    6.2 讲师视图, 讲师可管理自己的班级, 上课时选择班级, 查看班级学员列表 , 修改所管理的学员的成绩
    6.3 管理视图,创建讲师, 创建班级,创建课程
    7. 上面的操作产生的数据都通过pickle序列化保存到文件里
  • 相关阅读:
    INT最值
    约瑟夫问题
    word里的图片怎么复制出来
    必须掌握的8个dos命令
    vld(Visual Leak Detector 内存泄露检测工具
    sscanf,sscanf_s及其相关用法
    游戏开发梦开始的地方笔记
    关于字符编码,你所需要知道的
    CreateMutex创建互斥体可以用于只运行进程的一个实例
    sprintf,你知道多少?
  • 原文地址:https://www.cnblogs.com/yangmeichong/p/10893732.html
Copyright © 2020-2023  润新知