• 第六篇 面向对象


    面向对象典型的语言就是Java

    一.基本概念

    __init__(cls):是对将来具体实例的初始化方法,一般是不需要写的,Python会自动执行 
    __new__(self): 对__init__生成并返回的具体对象进行初始化  ---- 术语:构造函数
    __del__(self):Python解释器自动执行的,在程序执行完后,Python解释器会自动执行,回收,释放内存的时候才会调用;一般情况下也是不需要写的,Python会自动执行 ---术语:析构函数
    __super__:
    @classmethod  ---修饰器
    @staticmethod  --- 修饰器
    
    在类外面定义的变量就叫变量;在类里面定义的变量就叫属性
    在类外面定义的函数就叫函数;在类里面定义的函数就叫方法

    二.类的定义和调用

    1. 基础语法

    class LeiMing():
        
        def __init__(self, canshu):
            self.canshu = canshu
        
        def fangfa(self):
            pass
        
    
    # 对象的使用
    # 1. 初始化对象
    a = LeiMing(1)
    # 2. 调用类中的方法
    a.fangfa()

    示例1:人类

    # 定义了一个类,类型,不区分具体的对象个体
    class Person():
        # 在类里可以定义变量
        age = 10
        # 初始化对象(初始化函数)
        def __init__(self,age = None):
            if age is not None:
                self.age = age    # self代表的是将来具体的person1 、person2 这样一个个具体的个体对象
        # 在类里也可以定义函数
        def speak(self):
            print("Hello")
    
    
    # 类的使用,person1 和 person2 就是对象,是一个个具体的人,每个人(对象)都有自己特有的特征
    person1 = Person()
    print(person1.age)     # 10 
    person1.speak()        # Hello
    person1.age = 20   # 修改了person1的age
    print(person1.age)    # 20
    
    person2 = Person(30)
    print(person2.age)   # 30
    
    print(Person.age)    # 10 

    示例2:猫

    class Cat():
    
        def __init__(self,age = 0, sex = "male"):
            self.age = age
            self.sex = sex
    
        def sleep(self):
            pass
    
        def eat(self):
            pass
    
    
    big_cat = Cat(6, 'male')   
    er_cat = Cat(7, 'female')
    san_cat = Cat(7)
    
    print(big_cat.age, big_cat.sex)    # 6 male
    print(er_cat.age,er_cat.sex)       # 7 female
    print(san_cat.age,san_cat.sex)     # 7 male

    2.变量和类的属性

    在类外面定义的变量就叫变量;在类里面定义的变量就叫属性

    变量的查找顺序:变量-->类->基类

    class Cat():
    
        def __init__(self,age = 0, sex = "male"):
            self.age = age
            self.sex = sex
    
        def sleep(self):
            pass
    
        def eat(self):
            pass
    
    
    big_cat = Cat(6, 'male')
    er_cat = Cat(7, 'female')
    san_cat = Cat(7)
    
    big_cat.color = 'white'
    print(big_cat.color)  # white   # 是从big_cat的变量里取的值
    
    print(er_cat.color)
    # AttributeError: 'Cat' object has no attribute 'color'
    # 因为er_cat没有定义它自己的变量color,类里也没有定义color,基类里也没有color,所以会报属性错误
    # 变量的查找顺序:变量-->类->基类
    class Cat():
    
        color = 'BlACK'
    
        def __init__(self,age = 0, sex = "male"):
            self.age = age
            self.sex = sex
    
        def sleep(self):
            pass
    
        def eat(self):
            pass
    
    big_cat = Cat(6, 'male')
    er_cat = Cat(7, 'female')
    san_cat = Cat(7)
    
    big_cat.color = 'white'
    print(big_cat.color)  # white   # 是从big_cat的变量里取的值
    
    print(er_cat.color)   # BlACK
    # er_cat没有定义自己的color,就从类里找属性,找到了BLACK

    3. 类的方法

    在类外面定义的函数就叫函数;在类里面定义的函数就叫方法

    函数和方法的使用没有任何区别,只是方法的第一个参数是self

    class Cat():
        # 类的属性, color, self.age 都是类里的变量,但是术语叫做属性
        color = 'BlACK'
        def __init__(self,name,age = 0, sex = "male"):
            self.age = age
            self.sex = sex
            self.name = name
    
        # 类的方法
        def sleep(self):
            print("{} sleep".format(self.name))   # self.name:就是将来那个对象个体的名字,比如可以是damao,ermao,sanmao的名字
        def eat(self):
            print("{} eat".format(self.name))
    
    
    big_cat = Cat('damao',6, 'male')
    er_cat = Cat('ermao',7, 'female')
    san_cat = Cat('sanmao',7)
    
    
    # 类方法的调用
    big_cat.sleep()   # damao sleep
    er_cat.eat()      # ermao eat

    三.面向对象中的内置方法

    1. 构造方法 与 析构方法

    class Dog(object):
    
        # __init__的作用:是给具体对象dog进行初始化的
        def __init__(self):  # self代表的是将来的具体的对象个体
            print("__init__")
    
        # __new__方法的作用:就是用类型(Dog)生成具体对象(dog)的,通常是不需要写的
    # 构造方法
    def __new__(cls): # cls代表的是当前的这个类,这里就是Dog这个类 print("__new__") # 作用:回收 # 是Python解释器自己调用执行的
    # 析构方法
    def __del__(self): print("__del__") def speak(self): print("我啥都不想说") dog = Dog() dog.speak() # 报错 ''' AttributeError: 'NoneType' object has no attribute 'speak' 在上面的Person和Cat类里,没有__new__方法,就可以正常执行,而这里有 __new__ 方法,就报错了,为什么? '''
    class Dog(object):
    
        # __init__的作用:是给具体对象dog进行初始化的
        def __init__(self):  # self代表的是将来的具体的对象个体
            print("__init__")
    
        # __new__方法的作用:就是用类型(Dog)生成具体对象(dog)的,通常是不需要写的
        def __new__(cls):    # cls代表的是当前的这个类,这里就是Dog这个类
            print("__new__")
            return object.__new__(cls)   # 这里是通用写法,而且写了一定要返回
    
        # 作用:回收
        # 是Python解释器自己调用执行的,一般也是不需要写的
        def __del__(self):
            print("__del__")
    
        def speak(self):
            print("我啥都不想说")
    
    
    dog = Dog()
    dog.speak()
    
    # 输出
    __new__
    __init__
    我啥都不想说
    __del__
    
    '''
    看上面输出的代码的执行顺序
    1. 先执行__new__
    2. 再执行__init__
    3. 接着执行函数方法
    4. 等所有逻辑执行完成后,最后执行__del__,回收,释放内存
    
    '''

    四. 继承与super函数

    class Fish(object):  # Fish继承了Python的基类
    
        def __init__(self,name):
            self.name = name
    
        def bubble(self):
            print("我叫{}: 我吐一串泡泡".format(self.name))
    
        def swam(self):
            print("我是{}我游得很快".format(self.name))
    
    
    # 定义一个多宝鱼,继承鱼类
    class Turbot(Fish):
        def __init__(self,name):
            super(Turbot,self).__init__(name)
            # 固定写法:
            # 1. super()函数的第一个参数是类型(类名),第二个参数是对象
            # 2  super()函数写在哪个类里面,第一个参数就是哪个类的类名,第二个参数是对象,对象是self;
            # 3. super()后面调用的是父类的方法,此处是父类(Fish类)的初始化方法__init__(name)
            # super()函数的本质:是调用它继承的那个类(即父类)里的方法或者属性
            # super()函数的作用:可以一次性调用所有父类
    
        def run(self):
            # 多宝鱼没有跑方法,但是可以通过super调用父类的swam方法,那多宝鱼也有了游的方法
            super(Turbot,self).swam()
    
    
    
    fish = Turbot("多宝鱼")
    fish.swam()
    fish.bubble()
    fish.run()

    五. 类的修饰器 @classmethod 和 @staticmethod

    class Fish(object):  # Fish继承了Python的基类
    
        def __init__(self,name):
            self.name = name
    
        def bubble(self):
            print("我叫{}: 我吐一串泡泡".format(self.name))
    
        def swam(self):
            print("我是{}我游得很快".format(self.name))
    
    
    # 定义一个多宝鱼,继承鱼类
    class Turbot(Fish):
        def __init__(self,name):
            super(Turbot,self).__init__(name)
            # 固定写法:
            # 1. super()函数的第一个参数是类型(类名),第二个参数是对象
            # 2  super()函数写在哪个类里面,第一个参数就是哪个类的类名,第二个参数是对象,对象是self;
            # 3. super()后面调用的是父类的方法,此处是父类(Fish类)的初始化方法__init__(name)
            # super()函数的本质:是调用它继承的那个类(即父类)里的方法或者属性
            # super()函数的作用:可以一次性调用所有父类
    
        # 类方法里面的self参数代表具体对象本身
        def run(self):
            # 多宝鱼没有跑方法,但是可以通过super调用父类的swam方法,那多宝鱼也有了游的方法
            super(Turbot,self).swam()
    
        # 类方法里面的cls参数,代表的是类(这里是Trubot这个类)本身
        # 想代表类本身的时候,它就是个类方法,类方法可以用@classmethod去修饰,而用@classmethod修饰的类方法,可以直接用
        # 类名.方法名调用  或者 对象.方法名
        @classmethod
        def balabala(cls):
            print("balabala")
    
        # 静态方法:可以认为与外面的函数是等价的,是一个普通函数,因为完全不需要用self或者cls去修饰
        # 静态方法:可以在任何时候调用
        # 调用方法:类名.方法名()
        # 用静态方法修饰后,可以理解为既不属于这个类,也不属于self那个对象,只是把这个方法写在了类里面而已
        # 静态方法是独立于各种类以外的
        @staticmethod
        def kalakala():  # 静态方法,可以没有cls参数
            print("kalakala")
    
    fish = Turbot("多宝鱼")
    
    Turbot.balabala()   # 类可以直接调用被@classmethod修饰过的类方法
    Turbot.kalakala()   # 类可以直接调用被@staticmethod修改过的方法
    
    fish.balabala()    # 对象可以调用被@classmethod修饰过的类方法
    fish.kalakala()    # 对象可以调用被@staticmethod修改过的方法

    练习:实现水果类,并通过继承方法实现苹果,梨,香蕉和西瓜类

    class Fruit(object):
        def __init__(self,name,price):
            self.name = name
            self.price = price
    
    
    class Apple(Fruit):
    
        def __init__(self,name,price):
            super(Apple,self).__init__(name,price)
    
    class Peer(Fruit):
        def __init__(self,name,price):
            super(Peer,self).__init__(name,price)
    
    
    class Banana(Fruit):
        def __init__(self,name,price):
            super(Banana, self).__init__(name,price)
    
    class Watermelon(Fruit):
        def __init__(self,name,price):
            super(Watermelon, self).__init__(name,price)

     六. 总结

    一. 类中__new__() 和 __init__()的区别是什么?
    1.__new__()方法是把类型创建为具体的对象;__init__()是给具体的对象进行初始化的
    2. __init__()要想初始化具体的对象,必须通过__new__先创建一个对象,并且要在__new__返回这个对象后,__init__()才能知道该去初始化谁。

     

    通过new生成对象,然后要返回对象,这是通用写法;

    object也是类,object是Python的最根本的类型,生成一个新的对象都是根据object来生成 的;

    所以上面示例中dog这个具体的对象是__new__生成的,而不是__init__生成的;

    通常情况下,__new__是不需要写的,Python会自动给每个来加一个__new__方法;

    3. 执行顺序一定是先执行__new__,后执行__init__

  • 相关阅读:
    珍珠项链——容斥的应用
    协程库中 WaitGroup / CountDownLatch 实现
    简单C++线程池
    switch 比 if/else 效率更高?
    [LeetCode 264.] 丑数 II
    [LeetCode 229.] 求众数 II
    [NC41] 最长无重复子数组
    [NC105] 二分查找-II
    高楼扔鸡蛋
    C++ 编译期计算
  • 原文地址:https://www.cnblogs.com/victorm/p/11299298.html
Copyright © 2020-2023  润新知