• 面向对象(视频)


    一、基本的例子

    '''
    概念:类、对象、
    封装(防止数据被随意修改,外部调用变得简单)、
    继承(共同点在父类,不同点在子类)、
    多态(子类重写父类方法,对不同类的对象发出相同的消息将会有不同的行为)
    '''
    class Dog:
        nation = "JAPAN"
        def __init__(self, name):  # 构造函数
            self.name = name
        def sayhi(self):   # 类的方法
            print(self.name + ": " + "hello,i'm a dog..")
        def __del__(self):
            print("析构方法,删除对象的引用后执行。例如:del(对象)或者程序执行结束",注意引用计数为0时才执行此方法)
    d1 = Dog("Dog1")
    d2 = Dog("Dog2")
    d1.sayhi()  # Dog1: hello,i'm a dog..
    d2.sayhi()  # Dog2: hello,i'm a dog..
    print(d1.nation, d2.nation)  # JAPAN JAPAN
    Dog.nation = "JP"  # 通过类修改共有属性
    print(d1.nation, d2.nation)  # JP JP
    d1.nation = "CN"  # 只修改某对象的共有属性
    print(d1.nation, d2.nation)  # CN JP
    Dog.nation = "MO"  # 再通过类修改共有属性
    print(d1.nation, d2.nation)  # CN MO
    面向对象代码的例子
    '''
    最基本的类就写完了,
    self是实例本身:
    d = Dog("Dog1") <==>  d = Dog(d, "Dog1")
    1、成员属性self.name=name
    2、方法def sayhi这个方法也是共有的类的所有成员都用这个方法,
        要用私有方法只能:
        def sayhi2(self):
            print("my sayhi")
        d1.sayhi = sayhi2
        d1.sayhi(d1)
    3、私有属性self.__name=name
        内部可以访问,外部不能访问,
        如果想外部只读取,可以定义def get__name(self):return self.__name
    4、共有属性,在类里定义的变量nation。对象d.nation先找成员属性nation再找
        共有属性nation。如果没有成员属性nation就取类的nation,
        如果d.nation = 1这样就创建了类本身的成员属性nation,
        跟共有属性nation没有关系。
    5、类里的方法和共有属性只有一份。类的所有对象共用类里的方法,这样是为什么
       类的方法必须要有self关键字,这样类的方法才知道是谁在调用
    6、__del__(self)是类的析构方法。作用是清除对象的引用(当引用被清除那内存空间很快
       也将被垃圾回收机制清除),引用为0时会运行,在程序结束后会运行,运行中可以手动del(对象)
    '''

    二、继承的例子

    '''
    继承可以通过“继承”或“组合”实现
    多重继承,多级继承
    '''
    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
        def talk(self):
            print("person is talking..")
    class BlackPerson(Person):
        def __init__(self, name, age, strength):
            super().__init__(name, age)  # <==> Person.__init__(name, age)
            self.strength = strength
        def talk(self):
            print("Black Person talking..")
    class WritePerson(Person):
        pass
    
    b = BlackPerson("Smith", 30, "Strong")
    b.talk()
    继承的例子(一)
    class SchoolMember:
        '''
        学校成员类
        '''
        member = 0
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
        def enroll(self):
            print("注册了一个新成员:", self.name)
            SchoolMember.member += 1
        def tell(self):
            print("打印个人信息:",self.name)
            for k in self.__dict__:
                print(k,self.__dict__[k])
            print("---------end------------")
        def __del__(self):
            print("开除了:",self.name)
            SchoolMember.member -= 1
    class Teacher(SchoolMember):
        def __init__(self, name, age, sex, salary, course):
            super().__init__(name, age, sex)
            self.salary = salary
            self.course = course
            self.enroll()
        def teaching(self):
            print("teaching 课程:", self.course)
    class Student(SchoolMember):
        def __init__(self, name, age, sex, course, tuition):
            super().__init__(name, age, sex)
            self.course = course
            self.tuition = tuition
            self.amount = 0
            self.enroll()
        def pay_tution(self, amount):
            print(self.name, amount)
            self.amount += amount
    t1 = Teacher("Wusir", 28, "M", 8000, "Python")
    s1 = Student("HaiTao", 20, "F", "python", 12000)
    s1 = Student("Jack", 20, "F", "python", 12000)
    # print(SchoolMember.member)
    # del(s1)
    s1.tell()
    继承的例子(二)

    三、新式类经典类一丝丝区别(不重要)

    ################################################################################
    了解,不重要:
    Python2中,继承的层级。经典类是深度查询,新式类是广度查询
    python3中,继承的层级。都是广度查询
    ###############################################################################

    四、Python模拟多态

    '''
    多态:接口重用
    Python模拟多态
    '''
    class Animal:
        def __init__(self, name):
            self.name = name
        def talk(self):
            raise NotImplementedError("子类必须重构talk方法")
        @staticmethod
        def all_talk(obj):
            obj.talk()
    class Cat(Animal):
        def talk(self):
            print("Miao..Miao..")
    class Dog(Animal):
        def talk(self):
            print("Wang..Wang..")
    d = Dog("dog1")
    c = Cat("cat1")
    
    Animal.all_talk(d)
    Animal.all_talk(c)
    模拟多态

    五、类的属性有哪些

    ##############################################################################
    '''
    属性:
        成员属性
        公有属性(类属性)
        私有属性
    方法:
        公有方法
        私有方法
        静态方法@staticmethod
        类方法@classmethod
    属性方法(特性)@property
    ''' ###############################################################################

    六、静态方法例子

    '''
    静态方法@staticmethod
    静态方法相当于单纯的函数,没有self关键字
    类方法@classmethod
    类方法只能访问公有属性。之前每个对象修改的公有属性是自己的,
    通过类修改公有属性才改的大家的。
    变为类方法后任何对象都可以修改公有属性。
    '''
    class Person:
        nation = "朝鲜"
        def __init__(self, name):
            self.name = name
        @classmethod
        def change_nation(self):
            self.nation = "中国"
    p = Person("金三胖")
    p1 = Person("朴xx")
    p.change_nation()
    print(p.nation, p1.nation)   #中国 中国
    print(Person.nation)  #中国
    静态方法例子

    七、属性方法(或者叫做特性)

    class Dog:
        def __init__(self):
            self.__food = None
        @property
        def eat(self):
            print("eat:", self.__food)
        @eat.setter
        def eat(self, food):
            self.__food = food
        @eat.deleter
        def eat(self):
            del self.__food
    
    d = Dog()
    d.eat
    d.eat = "骨头"
    d.eat
    del d.eat
    d.eat
    
    ############
    # eat: None
    # eat: 骨头
    # AttributeError: 'Dog' object has no attribute '_Dog__food'
    ############
    属性方法简单例子
    '''
    属性方法的应用实例:
    用户查航班状态,
    1、需要调航空公司接口
    2、解析数据
    3、返回给用户结果
    '''
    class Flight:
        def __init__(self, name):
            self.name = name
        @property
        def flight_status(self):
            api = 1
            if api == 0:
                print("航班延迟")
            elif api == 1:
                print("航班到达")
            elif api == 2:
                print("航班飞走")
            else:
                print("无法确认")
    f = Flight("CA980")
    f.flight_status
    属性方法例子

    八、理解概念“类也是一个对象”

    '''
    __doc__:打印类的注释信息
    __module__:返回对象的模块
    __class__:输出类名
    __init__:
    __del__:
    __call__:让对象可以加括号运行
    __dict__:查看类(打印类里的所有属性不包括实例属性)或对象(打印实例属性不包括类属性)中的所有成员
    __str__:打印对象的字符串形式
    __getitem__:用户自己封装一个字典,用字典的形式使用对象,obj["name"]
    __setitem__:用户自己封装一个字典,用字典的形式使用对象,obj["name"]="alex"
    __delitem__:用户自己封装一个字典,用字典的形式使用对象,del obj["name"]
    __metaclass__:定义自己的类被哪个原类创建
    '''
    '''
    类也是一个对象。类的类是type
    '''
    def func(self):
        print("hello world", self.name, self.age)
    def __init__(self, name, age):
        self.name = name
        self.age = age
    Foo = type("Foo", (), {"talk":func, "__init__":__init__}) # 类定义(用type实例化类)
    f = Foo("BB", 23)  # 实例化对象
    f.talk()   # 打印hello world

    九、对象怎么被创建的? 1.先由“元类” 创建“元类”的对象--“类”   2. 再由“类” 创建“类”的对象--“对象”

    class MyType(type):
        def __init__(self, what, bases=None, dict=None):
            print("---MyType init---")
            super(MyType, self).__init__(what, bases, dict)
        def __call__(self, *args, **kwargs):
            print("---MyType call---")
            obj = self.__new__(self, *args, **kwargs)
            self.__init__(obj, *args, **kwargs)
    
    class Foo:
        __metaclass__ = MyType    # Python2中:对象类Foo被MyType元类创建
        def __new__(cls, *args, **kwargs):
            print("Foo  __new__")
            return object.__new__(cls)  # cls是对象类本身__new__在__init__之前执行,创建实例要用
        def __init__(self, name):
            self.name = name
            print("Foo  __init__")
    
    f = Foo("Tommy")
    ####----Python2中的输出结果:
    # ---MyType init---
    # ---MyType call---
    # Foo  __new__
    # Foo  __init__
    #############################
    ####----Python3中的输出结果:
    # Foo  __new__
    # Foo  __init__
    #############################

    如果要在Python3中想要获得Python2中的输出结果:

    class MyType(type):
        def __init__(self, what, bases=None, dict=None):
            print("---MyType init---")
            super(MyType, self).__init__(what, bases, dict)
        def __call__(self, *args, **kwargs):
            print("---MyType call---")
            obj = self.__new__(self, *args, **kwargs)
            self.__init__(obj, *args, **kwargs)
    
    class Foo(metaclass=MyType):  # Python3中:对象类Foo被MyType元类创建
        def __new__(cls, *args, **kwargs):
            print("Foo  __new__")
            return object.__new__(cls)  # cls是对象类本身__new__在__init__之前执行,创建实例要用
        def __init__(self, name):
            self.name = name
            print("Foo  __init__")
    
    f = Foo("Tommy")
    
    ####----Python2中的输出结果:未使用
    # 
    #############################
    ####----Python3中的输出结果:
    # ---MyType init---
    # ---MyType call---
    # Foo  __new__
    # Foo  __init__
    #############################

     元类是如何创建的?

    class UpperAttrMetaClass(type):
        def __new__(mcs, class_name, class_parents, class_attr):
            print("---UpperAttrMetaClass new---")
            # attrs = ((name, value) for name, value in class_attr.items() if not name.startswith('__'))
            # class_attr = dict((name.upper(), value) for name, value in attrs)
            a = super(UpperAttrMetaClass, mcs).__new__(mcs, class_name, class_parents, class_attr)
            return a      # <class '__main__.UpperAttrMetaClass'>
    
        def __init__(cls, *args, **kwargs):
            print("---UpperAttrMetaClass init---")
            super(UpperAttrMetaClass, cls).__init__(*args, **kwargs)
    
        def __call__(cls, *args, **kwargs):
            print("---UpperAttrMetaClass call---")
            obj = cls.__new__(cls, *args, **kwargs)
            cls.__init__(obj, *args, **kwargs)
    
    
    class Foo(metaclass=UpperAttrMetaClass):
        bar = 12
        money = 'unlimited'
    
        def __new__(cls, *args, **kwargs):
            print("Foo  __new__")
            return object.__new__(cls)  # cls是对象类本身__new__在__init__之前执行,创建实例要用
    
        def __init__(self, name):
            self.name = name
            print("Foo  __init__")
    
    
    Foo('alex')
    print('Foo.bar:', Foo.bar)
    print('Foo.money:', Foo.money)
    
    ########################
    # ---UpperAttrMetaClass new---
    # ---UpperAttrMetaClass init---
    # ---UpperAttrMetaClass call---
    # Foo  __new__
    # Foo  __init__
    # Foo.bar: 12
    # Foo.money: unlimited
    ########################

     完整

    class MyMetaClass(type):
        def __new__(mcs, name, bases, attrs):
            '''
            作用是创建一个类Foo,
            :param name: 类名
            :param bases: 父类
            :param attrs: 类的属性、方法
            :return:
            '''
            print('---1.MyMetaClass.__new__: 参数为(类名,父类,类的属性或方法),创建一个Foo类,并给Foo类加一个属性"hh"---')
            attrs['hh'] = 'haha'
            # 用这里返回的Foo调用__call__方法来创建Foo对象,如果不返回,下面的__call__会调用失败
            return super(MyMetaClass, mcs).__new__(mcs, name, bases, attrs)
    
        def __init__(cls, name, bases=None, attrs=None):
            print(
                '---2.MyMetaClass.__init__: Foo类已经创建好了,走到__init__里面了,这里面只是用于创建完了做一点事情
    '
                '                           不调用父类__init__没关系,没有返回值也没关系,估计这个方法没什么用---')
    
        def __call__(cls, *args, **kwargs):
            '''
            这个方法是对子类的Foo.__new__()方法进行拦截。子类Foo创建的对象都是这个方法的返回值。
            如果不返回,子类Foo创建的对象都为None
            等价于:Foo(*args, **kwargs)
            '''
            print("---3.MyMetaClass.__call__: 用于创建Foo类的实例,如果Foo(12, k=1, p=2), 这里的args=(12,) kwargs={'k':1, 'p':2}
    "
                  "                           这个方法在Foo.__new__之前执行,Foo类的实例优先为这个方法的返回值,其次为Foo.__new__的返回值
    "
                  "                           必须调Foo的new和init方法。如果不调用Foo.__new__对象为None,不调用Foo.__init__对象没被初始化")
            print(cls)
            obj = cls.__new__(cls, *args, **kwargs)
            cls.__init__(obj, *args, **kwargs)
            return obj
    
    
    class Bar:
        def __new__(cls, *args, **kwargs):
            print('Bar  __new__')
            return object.__new__(cls)
    
    
    class Bar1:
        def __new__(cls, *args, **kwargs):
            print('Bar1 __new__')
            return object.__new__(cls)
    
    
    class Foo(metaclass=MyMetaClass):
        # metaclass只是用来创建Foo用,__new__方法是创建Foo的实例用,优先用自己的__new__,其次用第一个父类的__new__
        def __new__(cls, *args, **kwargs):
            # 如果Foo(12, k=1, p=2), 这里的args=(12,) kwargs={'k':1, 'p':2}
            print('---4.Foo.__new__:返回Foo的未初始化的实例---')
            return object.__new__(cls)  # cls是对象类本身,只接收一个参数
    
        def __init__(self, name):
            self.name = name
            print("---5.Foo.__init__---")
    
    
    f = Foo('alex')
    print(f.name)
    print(Foo.hh)
    
    '''
    ---1.MyMetaClass.__new__: 参数为(类名,父类,类的属性或方法),创建一个Foo类,并给Foo类加一个属性"hh"---
    ---2.MyMetaClass.__init__: Foo类已经创建好了,走到__init__里面了,这里面只是用于创建完了做一点事情
                               不调用父类__init__没关系,没有返回值也没关系,估计这个方法没什么用---
    ---3.MyMetaClass.__call__: 用于创建Foo类的实例,如果Foo(12, k=1, p=2), 这里的args=(12,) kwargs={'k':1, 'p':2}
                               这个方法在Foo.__new__之前执行,Foo类的实例优先为这个方法的返回值,其次为Foo.__new__的返回值
                               必须调Foo的new和init方法。如果不调用Foo.__new__对象为None,不调用Foo.__init__对象没被初始化
    <class '__main__.Foo'>
    ---4.Foo.__new__:返回Foo的未初始化的实例---
    ---5.Foo.__init__---
    alex
    haha
    '''

    重要:metaclass也从父类继承

    假设用户定义一个class User(Model)时,Python解释器首先在当前类User的定义中查找__metaclass__

    如果没有找到,就继续在父类Model中查找__metaclass__,找到了,就使用Model中定义的__metaclass__ModelMetaclass来创建User类,

    也就是说,metaclass可以隐式地继承到子类,但子类自己却感觉不到。

    用metaclass实现ORM框架:https://www.liaoxuefeng.com/wiki/897692888725344/923030550637312

    思考,如果有动态创建表的需求,如银行小微系统根据指标大类动态创建表,需要使用type()来动态创建类。这样动态创建的类才能使用ORM框架

    general_table = type(类名,父类, 属性)   //创建model类

    general_table.create()   //动态创建表

    创建过程图示:

     

  • 相关阅读:
    H5学习的第三周
    2017.3.12 H5学习的第一周
    js中比较实用的函数用法
    JS学习中遇到的一些题目
    H5学习第四周
    idea快捷键
    中国国内可用API合集
    ssm整合 idea+maven版
    Dubbo的使用及原理浅析
    $.extend 和$.fn.extend的区别
  • 原文地址:https://www.cnblogs.com/staff/p/9357110.html
Copyright © 2020-2023  润新知