Python基础知识:面向对象(封装、继承、多态)1

    技术2022-07-10  128

    面向对象(封装、继承、多态)

    领取Python学习资料可以加小编的微信:tz2020jd

    类中: ①特征被称为属性;②行为被称为方法;③三要素:类名、属性、方法;

    dir函数可以查看对象的所有方法;

    dir显示的方法中,__方法名__格式的方法是Python提供的内置方法/属性;

    类中的方法第一个参数必须是self(类似Java中的this?); 创建第一个类:

    class Cat:     def eat(self):         print("小猫爱吃鱼!")     def drink(self):         print("小猫爱喝水!")

    tom = Cat()  # 和Java不同,不需要使用 new tom.eat() tom.drink()

    print(tom)  # 输出对象变量 print("%x" % id(tom))  # 输出16进制的地址 print("%d" % id(tom))  # 输出10进制的地址 输出:

    引用的强调

    Python如果不想修改类,可以直接给对象增加属性(不同于其他语言!)(这种方式不推荐); self关键字(Java中的this关键字): 哪一个对象调用的这个方法,self就是哪个对象的引用,可以通过self.访问对象的属性和方法; 初始化方法__init__: 当使用类名()创建对象时,会自动执行以下操作:

    ①. 为对象在内存中分配空间 – 创建对象; ②. 为对象的属性 设置初始值 – 初始化方法(init);

    这个初始化方法就是__init__方法,__init__是对象的内置方法。 __init__方法是专门用来定义一个类具有哪些属性的方法!

    在初始化方法__init__内部定义属性: 在init方法内部使用self.属性名 = 属性的初始值就可以定义属性; 定义属性之后,再使用该类创建的对象,都拥有该属性; 使用:

    class Cat:     def __init__(self):         print("这是一个初始化方法")         self.name = "Tom"

        def eat(self):         print("%s 爱吃鱼" % self.name)

    tom = Cat() print(tom.name) tom.eat() 输出:

     

    这是一个初始化方法 Tom Tom 爱吃鱼

    初始化方法__init__中带参数,构造对象; class Cat:     def __init__(self, new_name):         print("这是一个初始化方法")         self.name = new_name

        def eat(self):         print("%s 爱吃鱼" % self.name)

    tom = Cat("Tom") print(tom.name) tom.eat()

    lazy_cat = Cat("大懒猫") print(lazy_cat.name) lazy_cat.eat()

    __del__方法的调用

    class Cat:     def __init__(self, new_name):         print("初始化方法被调用")

        def __del__(self):         print("del方法被调用")

    # tom是一个全局变量 等到程序全部执行完成之后才会销毁 tom = Cat("Tom")

    # 可以手动调用 del tom 提前销毁 tom对象 # del tom print("*" * 50)

    输出: (注意: 如果不注释 # del tom,__del__方法的调用就在输出横线的上方)

     

    初始化方法被调用 ************************************************** del方法被调用 __str__方法(类似Java中的toString()) 在python中,使用print输出对象变量,默认情况下输出这个变量 引用的对象是由哪一个类创建的对象,以及在内存中的地址(16进制表示) ; 如果在开发中,希望使用print输出对象变量时,能够打印自定义内容,就可以利用__str__方法; 注意:__str__方法必须返回一个字符串; class Cat:     def __init__(self, new_name):         self.name = new_name

        def __str__(self):  # 返回的是一个字符串         return "我是小猫【%s】" % self.name

    tom = Cat("Tom") print(tom) 输出:

    我是小猫【Tom】 1 面向对象案例一 : 房子和家具 class HouseItem:     def __init__(self, name, area):         self.name = name         self.area = area

        def __str__(self):         return "家具名称: %s, 家具面积: %s " % (self.name, self.area)

    class House:     def __init__(self, house_type, area):  # 房子类型, 总面积         self.house_type = house_type         self.area = area         self.free_area = area  # 一开始剩余面积等于总面积         self.item_list = []  # 家具列表一开始是空的         pass

        def __str__(self):         # python 能够自动的将一对括号内内部的代码 连接在一起         return ("户型: %s\n总面积: %.2f【剩余: %.2f】\n家具: %s"  # 如果没有使用括号,这里就要有一个 \ 换行标符                 % (self.house_type, self.area,                    self.free_area, self.item_list))  # 注意这里使用了一个括号

        def add_item(self, item):  # 在列表中添加家具         if self.free_area < item.area:             print("房子已满,不能再放家具了!")             return         self.item_list.append(item.name)         self.free_area -= item.area

    # 创建家具 bed = HouseItem("席梦思", 40) chest = HouseItem("衣柜", 2) table = HouseItem("餐桌", 20)

    # 创建房子 my_home = House("两室一厅", 60) print(my_home)

    # 添加家具 my_home.add_item(bed) print(my_home) my_home.add_item(chest) print(my_home) my_home.add_item(table) print(my_home)

    输出:

    户型: 两室一厅 总面积: 60.00【剩余: 60.00】 家具: [] 户型: 两室一厅 总面积: 60.00【剩余: 20.00】 家具: ['席梦思'] 户型: 两室一厅 总面积: 60.00【剩余: 18.00】 家具: ['席梦思', '衣柜'] 房子已满,不能再放家具了! 户型: 两室一厅 总面积: 60.00【剩余: 18.00】 家具: ['席梦思', '衣柜']

    面向对象案例二 : 枪和士兵 class Gun:  # 枪类     def __init__(self, model):          self.model = model         self.bullet_mount = 0

        def add_bullet(self, count):         self.bullet_mount += count

        def shoot(self):         if self.bullet_mount <= 0:             print("【%s】没有子弹了..." % self.model)

            self.bullet_mount -= 1         print("%s 突突突...【剩余子弹: %d】" % (self.model, self.bullet_mount))

    class Soldier:     def __init__(self, name):         self.name = name         # 这个使用None关键字 假定新兵没有枪         self.gun = None  # Node类似Java中的null

        def fire(self):         # 1.判断士兵是否有枪         # if self.gun == None:  # 不推荐         if self.gun is None:             print("【%s】 还没有枪..." % self.name)             return         # 2. 高喊口号         print("冲鸭...【%s】" % self.name)         # 3. 让枪装填子弹         self.gun.add_bullet(50)         # 4.让枪发射子弹         self.gun.shoot()

    # 创建枪的对象 ak47 = Gun("AK47") ak47.add_bullet(50) ak47.shoot()

    # 创建士兵对象 xusanduo = Soldier("许三多") xusanduo.fire()  # 没有枪,打不了 xusanduo.gun = ak47  # 给士兵一把ak47的枪 xusanduo.fire()

    身份运算符( == 类似Java中的equals,而 is(身份运算符) 却类似 java中的 ==);  

    a = [1, 2, 3] b = [1, 2, 3]

    print(a == b)  # True print(a is b)  # False

    私有属性和私有方法: 只需要在属性名或者方法名前面加上两个下划线(真的6…),私有属性只能在类的内部使用; 但是Python中没有真正意义的私有,这个私有只是伪私有。可以使用_类名__属性或者_类名__方法强制访问私有属性或方法; class Woman:     def __init__(self, name):         self.name = name         self.__age = 18  # 加上两个_表示私有属性

        def secret(self):         # 注意对象内部可以访问私有属性         print("%s 的年龄是 %d" % (self.name, self.__age))

    xiaomei = Woman("小美")

    # print(xiaomei.__age)  # 报错,不能直接访问私有方法 xiaomei.secret()  # 这个可以

    # 但是也可以通过 " _类名__属性/方法"  来强制访问私有属性或方法 print(xiaomei._Woman__age)  # 强制访问

    输出:

    小美 的年龄是 18 18 关于继承中的重写,和Java中差不多,直接覆盖即可; class Animal:

        def eat(self):         print("吃!")

        def drink(self):         print("喝!")

        def run(self):         print("跑!")

        def sleep(self):         print("睡")

    class Dog(Animal):  # 继承直接加上括号,不需要extends 关键字

        def bark(self):         print("汪汪汪!")

    class XiaoTianQuan(Dog):  # 继承可以传递,既继承了Animal也继承了Dog

        def fly(self):         print("飞!")

        def bark(self):  # 重写方法         print("嗷嗷嗷!")

    xiao_tian = XiaoTianQuan() xiao_tian.eat() xiao_tian.drink() xiao_tian.bark() xiao_tian.fly() 扩展相关方法中使用super()关键字,和Java也差不多; class XiaoTianQuan(Dog):  # 继承可以传递,既继承了Animal也继承了Dog

        def fly(self):         print("飞!")

        def bark(self):  # 重写方法         super().bark()  # 先调用父类的方法  #注意这个super()关键字在python2.x中没有         print("嗷嗷嗷!")

    注意子类不能访问父类的私有属性 class A:     def __init__(self):         self.num1 = 3           self.__num2 = 33

        def __test(self):         print("num1 = %d, num2 = %d" % (self.num1, self.__num2))

    class B(A):     def demo(self):  # 测试能不能访问父类的私有方法         # 访问父类的私有属性         print("访问父类的私有属性 %d" % self.__num2)

            # 访问父类的私有方法         self.test()

    a = A() b = B() b.demo()  # 报错

    但是子类可以通过公有方法间接的来访问父类的私有属性; class A:     def __init__(self):         self.__num2 = 33

        def __test(self):         print("__num2 = %d" % self.__num2)

        def test(self):         # 访问自己类的 私有属性         print("私有属性__num2 = %d" % self.__num2)         # 访问自己类的 私有方法         self.__test()

    class B(A):     def demo(self):         self.test()  # 通过访问公共方法 test来间接访问 私有属性

    b = B() b.demo()  # 报错

    注意,使用多继承的时候,如果两个父类中有相同的方法,尽量避免使用多继承, 避免产生混淆。可以使用__mro__(方法搜索顺序)用于在多继承时,判断方法、属性的调用路径; class A:     def test1(self):         print("A类中的test_1方法!")

        def test2(self):         print("A类中的test_2方法!")

    class B:     def test1(self):         print("B类中的test_1方法!")

        def test2(self):         print("B类中的test_2方法!")

    class C(A, B):     pass

    c = C() c.test1() c.test2() print(C.__mro__)  # 输出C的继承路径

    输出:

     

    领取Python学习资料可以加小编的微信:tz2020jd

    Processed: 0.028, SQL: 9