python封装、继承、多态

封装

封装是将属性和方法封装到一个抽象的类中。对象方法的细节都被封装在类的内部。
在对象的方法内部,是可以直接访问对象的属性的;同一个类创建的多个对象之间,属性是互不干扰的。
以下是房子添加家具的封装实例(把对象传给成员函数参数):

# -*- coding: utf-8 -*-
class HouseItem:
    def __init__(self,name,area):
        self.name=name
        self.area=area
    def __str__(self):
        return "%s家具占地%d平"%(self.name,self.area)
task=HouseItem("桌子",3)
bed=HouseItem("床",6)
shafa=HouseItem("沙发",10)

class House:
    def __init__(self,house_type,area):
        self.house_type=house_type
        self.area=area
        self.free_area=area
        self.item_list=[]
    def __str__(self):
        return ("户型为%s,面积为%d的房子中放下了这些家具%s,还剩下面积%.2f"%(self.house_type,self.area,self.item_list,self.free_area))
    def add_item(self,item):
        if self.free_area<item.area:
            print("房子面积不够了,无法放下家具%s"%item.name)
            return
        print("把面积为%.2f的家具%s房子房子中"%(item.area,item.name))
        self.item_list.append(item.name)
        self.free_area-=item.area
hotel=House("旅馆",100)
hotel.add_item(task)
hotel.add_item(bed)
hotel.add_item(shafa)
print(hotel)

=========================================================================================
士兵实例(把类对象传给类属性):
 

# -*- coding: utf-8 -*-
class Gun:
    def __init__(self,model):
        self.model=model
        self.bullet_count=0
    def add_bullet(self,count):
        if self.bullet_count==0:
            self.bullet_count+=count
            print("%s枪没子弹了,增加%d颗子弹"%(self.model,count))
            return
        print("%s枪还有子弹%d发,不用添加子弹"%(self.model,self.bullet_count))

    def shoot(self):
        print("pengpeng...")
        self.bullet_count-=1
class Soldier:
    def __init__(self,name):
        self.name=name
        self.gun=None
    def fire(self):
        if self.gun.model is None:
            print("%s没有枪,请先配枪"%self.name)
            return
        self.gun.add_bullet(3)
        self.gun.shoot()
        print("开火了")
gun=Gun("ak47")
sold=Soldier("阿甘")
sold.gun=gun
sold.fire()
sold.fire()
sold.fire()
sold.fire()
sold.fire()
sold.fire()
sold.fire()
sold.fire()
sold.fire()
sold.fire()

身份运算符

身份运算符用于比较两个对象的内存地址shi'是否一致——是否是对同一个对象的引用
is判断两个对象是否是同一个;==判断引用变量的值是否相等
python中针对None比较时,建议使用is
 

身份运算符
运算符 描述 实例
is is 是判断两个标识符是不是引用同一个对象 x is y,类似 id(x) == id(y)
is not is not 是判断两个标识符是不是引用不同对象 x is not y,类似 id(a) != id(b)
     

以下是一些其他的理解
 

class Cat:
    def __init__(self):
        self.name="汤姆"
    def eat(self):
        print("%s爱吃鱼"%self.name)
    def drink(self):
        print("%s要喝水"%self.name)
tom=Cat()  # 默认把对象tom赋给self,self=tom
tom.eat()
tom.drink()

lazy_cat=Cat()
lazy_cat.eat()

=================================================================================

# -*- coding: utf-8 -*-
class Cat:
    # 1、self=tom
    # 2、self=lazy_cat

    def __init__(self,name_str):  # self=tom,name_str="tom"  ||| self=lazy_cat,name="大懒猫"
        # 1、tom.name="汤姆"  ---》 在tom的对象空间里,创建变量 存储“汤姆”
        # 2、lazy_cat.name="懒猫"----》在lazy_cat的对象空间里面
        print(self,id(self))    # 打开和关闭,试试看
        self.name=name_str
    def eat(self):
        print("%s爱吃鱼"%self.name)
    def drink(self):
        print("%s要喝水"%self.name)
print(Cat("汤姆"),id(Cat("汤姆")))  # tom=Cat()默认调用__init__(tom,"汤姆")  加上默认的参数和传入的数据
# print("***********************************")  # 前面创建了一次对象,立马删除;后面又创建了一次对象
                                                # 会使用之前的对象内存。如果在这之间有其他语句,那么之前创建的
                                                #内存对象会彻底销毁;之后的创建对象会创建新的内存对象空间
                                                # 对象空间是在内存中吗
# Cat("11")                                        # a=1,a和1分别存储在哪里,内存,磁盘
tom=Cat("汤姆")
print(tom)
print(id(tom))
# tom.eat()
# tom.drink()

# lazy_cat=Cat("懒猫")
# lazy_cat.eat()
a=1
print(id(a),id(1))
a=2
print(id(a),id(2))

"""
同时,如果没有任何变量指向内存空间的某个值,这个值称为垃圾数据,
系统会自动将其删除,回收它占用的内存空间。

也可以使用del 命令 删除变量,
但是删除之后就不能再使用了。否则会报错:变量没有定义。

0x000002B0F307C128才是地址
2959014871336是系统给的临时id地址,id是唯一的。
一块对象空间的地址赋值给a,a可能是2959014871448,a被回收了,再把对象空间地址赋值给b,2959014871448,a和b存储的地址可能
不同,但是都是指向0x000002B0F307C128地址。0x000002B0F307C128是绝对地址,2959014871448是临时定义的一串唯一地址,这一串
唯一地址没被回收的时候,0x000002B0F307C128赋值给c,id(c)也等于2959014871448。
a被回收后,0x000002B0F307C128赋值给d,id(d)变为了其他值。
"""

=====================================

# -*- coding: utf-8 -*-
class Cat:
    def __init__(self,new_name):
        self.name=new_name
        print("%s来了"%self.name)
    def __del__(self):          # 程序(代码)一走完就调用
        print("%s去了"%self.name)  # object中没有__del__()方法
tom=Cat("汤姆")
print(tom.name)

del tom    # del关键字可以删除一个对象
# a=object()
# a.
print("-------------")
# -*- coding: utf-8 -*-
class Cat:
    def __init__(self,new_name):
        self.name=new_name
        print("%s来了"%self.name)
    def __del__(self):          # 程序(代码)一走完就调用
        print("%s去了"%self.name)
    def __str__(self):          # self=tom
        return "我是小猫"       # 返回值必须存在
tom=Cat("汤姆")       # 创建了一个对象tom,对象传参self=tom
                      # 在类外部,tom.成员;在类中,self.成员
print(tom.name)
print(tom)  # print(tom.__str__()) print(地址值)
            # __str__(tom)必须要有返回值

# del tom    # del关键字可以删除一个对象

========================
***********************************************************************************************************************

私有属性和方法

应用场景

  • 在实际开发中,对象 的 某些属性或方法 可能只希望 在对象的内部被使用,而 不希望在外部被访问到
  • 私有属性 就是 对象 不希望公开的 属性
  • 私有方法 就是 对象 不希望公开的 方法

定义方式

  • 在 定义属性或方法时,在 属性名或者方法名前 增加 两个下划线,定义的就是 私有 属性或方法

伪私有属性和方法

Python 中,并没有 真正意义 的 私有

在给 属性、方法 命名时,实际是对 名称 做了一些特殊处理,使得外界无法访问到
处理方式:在 名称 前面加上 _类名 => _类名__名称
# 私有属性,外部不能直接访问到
print(xiaofang._Women__age)

# 私有方法,外部不能直接调用
xiaofang._Women__secret()

********************************************************************************************************************************

猜你喜欢

转载自blog.csdn.net/shuzhikang/article/details/81567084