Python基础语法(八)面向对象

类定义

类中包含属性和方法,类通过class来定义

class Cat:
    """定义了一个Cat类"""

    #初始化对象
    def __init__(self, new_name, new_age):
        self.name = new_name
        self.age = new_age

    #打印对象信息
    def __str__(self):
        return "%s的年龄是:%d"%(self.name, self.age)

    #方法
    def eat(self):
        print("猫在吃鱼....")

    def drink(self):
        print("猫正在喝kele.....")

    def introduce(self):
        print("%s的年龄是:%d"%(self.name, self.age))

#创建一个对象
tom = Cat("汤姆", 40)

lanmao = Cat("蓝猫", 10)

print(tom) #tom的年龄是:40
print(lanmao) #lanmao的年龄是:10

不用定义属性,属性在每个对象中是独立的

对象包含对象

class Home:
    def __init__(self, new_area, new_info, new_addr):
        self.area = new_area
        self.info = new_info
        self.addr = new_addr
        self.left_area = new_area
        self.contain_items = []

    def __str__(self):
        msg = "房子的总面积是:%d,可用面积是:%d,户型是:%s,地址是:%s"%(self.area, self.left_area, self.info, self.addr)
        msg += " 当前房子里的物品有%s"%(str(self.contain_items))
        return msg

    def add_item(self, item):
        #self.left_area -= item.area
        #self.contain_items.append(item.name)

        self.left_area -= item.get_area()
        self.contain_items.append(item.get_name())

class Bed:
    def __init__(self, new_name, new_area):
        self.name = new_name
        self.area = new_area

    def __str__(self):
        return "%s占用的面积是:%d"%(self.name, self.area)

    def get_area(self):
        return self.area

    def get_name(self):
        return self.name

fangzi = Home(129, "三室一厅", "北京市 朝阳区 长安街 666号")
print(fangzi) #房子的总面积是:129,可用面积是:129,户型是:三室一厅,地址是:北京市 朝阳区 长安街 666号 当前房子里的物品有

bed1 = Bed("席梦思", 4)
print(bed1) #席梦思占用的面积是:4

fangzi.add_item(bed1)
print(fangzi) #房子的总面积是:129,可用面积是:125,户型是:三室一厅,地址是:北京市 朝阳区 长安街 666号 当前房子里的物品有席梦思

bed2 = Bed("沙发",3)
fangzi.add_item(bed2)
print(fangzi) #房子的总面积是:129,可用面积是:122,户型是:三室一厅,地址是:北京市 朝阳区 长安街 666号 当前房子里的物品有席梦思,沙发

隐藏对象属性

class Dog:

    def __init__(self, new_name):
        self.name = new_name
        self.__age = 0#定义了一个私有的属性,属性的名字是__age

    def set_age(self,new_age):
        if new_age>0 and new_age<=100:
            self.__age = new_age
        else:
            self.__age = 0

    def get_age(self):
        return self.__age

dog = Dog("小白")
#dog.age = -10
#dog.name = "小白"

#print(dog.age)


dog.set_age(10)
age = dog.get_age()
print(age) #10

#dog.get_name()

#dog.__age = -10
print(dog.__age)#访问不了

私有方法

class Dog:

    #私有方法 方法前面加__
    def __send_msg(self):
        print("------正在发送短信------")

    #公有方法
    def send_msg(self, new_money):
        if new_money>10000:
            self.__send_msg()
        else:
            print("余额不足,请先充值 再发送短信")

dog = Dog()
dog.send_msg(100)

对象初始化

def __init__(self, new_name):
        self.name = new_name

对象销毁

def __del__(self):
        print("对象销毁")
class Dog:
    
    def __del__(self):
        print("-----英雄over------")

dog1 = Dog()
dog2 = dog1

del dog1#不会调用 __del__方法,因为这个对象 还有其他的变量指向它,即 引用计算不是0
del dog2#此时会调用__del__方法,因为没有变量指向它了
print("====================")

打印结果:
-----英雄over------
====================
#如果在程序结束时,有些对象还存在,那么python解释器会自动调用它们的__del__方法来完成清理工作

sys 库中,getrefcount()函数可以获取对象引用个数,默认初始化一个变量后得到的数值是2,因为这个方法也对该对象进行了引用

实例属性

class Tool(object):
    def __init__(self, new_name):
        self.name = new_name


num = 0
tool1 = Tool("铁锹")
num+=1
print(num)
tool2 = Tool("工兵铲")
num+=1
print(num)
tool3 = Tool("水桶")
num+=1
print(num)

name为实例属性,tool1、tool2为实例对象,里面的属性不共享

类属性

class Tool(object):
    #类属性
    num = 0

    #方法
    def __init__(self, new_name):
        #实例属性
        self.name = new_name
        #对类属性+=1,调用格式:类名.类属性
        Tool.num += 1 

tool1 = Tool("铁锹")
tool2 = Tool("工兵铲")
tool3 = Tool("水桶")

print(Tool.num)

num为类属性,所有实例对象共享

实例属性类属性区别:
实例属性属于实例对象,每个实例对象拥有自己独有的实例属性,实例属性在多个类对象中不共享
类对象属于类,多个实例对象共享该类属性

实例方法、类方法、静态方法

class Game(object):

    #类属性
    num = 0

    #实例方法 必需要有self参数,调用实例属性
    def __init__(self):
        #实例属性
        self.name = "laowang"

    #类方法 需要加上@classmethod
    @classmethod
    def add_num(cls):#默认参数cls,调用类属性
        cls.num = 100

    #静态方法 需要加上 @staticmethod,方法中的参数可以添加变量,也可以不添加,取决于静态方法内部所使用的是类属性还是实例属性。。。
    @staticmethod
    def print_menu():
        print("----------------------")
        print("    穿越火线V11.1")
        print(" 1. 开始游戏")
        print(" 2. 结束游戏")
        print("----------------------")

game = Game()
#Game.add_num()#可以通过类的名字调用类方法
game.add_num()#还可以通过这个类创建出来的对象 去调用这个类方法
print(Game.num)

#Game.print_menu()#通过类 去调用静态方法
game.print_menu()#通过实例对象 去调用静态方法

静态方法可以通过类对象或者实例对象来进行调用。。。

实例方法,类方法,静态方法之间的区别及调用关系

实例方法,类方法,静态方法之间的区别及调用关系

如果只看这个图,很多人可能会看的一头雾水,特别是学过完全面向对象语言的同学, Python 是双面向的,既可以面向函数编程,也可以面向对象编程,所谓面向函数就是单独一个. py 文件,里面没有类,全是一些函数,调用的时候导入模块,通过模块名.函数名()即可调用,完全不需要类,那么你可能会问,那要类还有什么毛用? 类就是用来面向对象编程啦,类可以有自己的属性,类可以创建很多实例,每个实例可以有不同的属性,这也就保存了很多私有的数据,总之都有存在的必要.
再来看上面这张图,在类里面定义的函数就是方法,类方法需要@ classmethod 修饰并且有个隐藏参数 cls,实例方法必须有个参数 self, 静态方法必须有 @staticmethod修饰,类和实例都可以访问静态方法,实例可以访问实例方法也可以访问类方法,类可以访问类方法也可以访问实例方法,访问实例方法必须要带参数 self, 可以理解为类其实也是一个实例,类访问实例方法不带参数会报错的.类本身可以访问函数,实例却不行.

__new__方法

class Dog(object):
    def __init__(self):
        print("----init方法-----")

    def __del__(self):
        print("----del方法-----")

    def __str__(self):
        print("----str方法-----")
        return "对象的描述信息"

    def __new__(cls):#cls此时是Dog指向的那个类对象

        #print(id(cls))

        print("----new方法-----")
        return object.__new__(cls)
#print(id(Dog))
xtq = Dog()

创建一个对象,必需返回,否则创建失败,创建成功后调用init方法,调用成功后返回一个对象的引用

通过__new__方法创建一个单例并且实例属性只初始化一次

class Dog(object):

    __instance = None
    __init_flag = False

    def __new__(cls, name):
        if cls.__instance == None:
            cls.__instance = object.__new__(cls)
            return cls.__instance
        else:
            #return 上一次创建的对象的引用
            return cls.__instance

    def __init__(self, name):
        if Dog.__init_flag == False:
            self.name = name
            Dog.__init_flag = True

a = Dog("旺财")
print(id(a))
print(a.name)

b = Dog("哮天犬")
print(id(b)) #与a的id相同
print(b.name) # 打印结果:旺财
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容

  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,846评论 6 13
  • 定义类并创建实例 在Python中,类通过 class 关键字定义。以 Person 为例,定义一个Person类...
    绩重KF阅读 3,919评论 0 13
  • Python 面向对象Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对...
    顺毛阅读 4,205评论 4 16
  • 要点: 函数式编程:注意不是“函数编程”,多了一个“式” 模块:如何使用模块 面向对象编程:面向对象的概念、属性、...
    victorsungo阅读 1,457评论 0 6
  • 每个人都有一个死角,自己走不出来,别人也闯不进去,人生,总有许多沟坎需要我们跨越。当有负面情绪的时候,不要说。管好...
    刘玉婷LYT阅读 249评论 1 0