• Python——创建类和对象


    ####创建类和对象###

    1.类的相关知识

       类有两种作用:属性应用和示例化

    1)属性的引用(类名.属性)

       定义一个类 --> 里面定义一个属性(但是这个属性是写死在程序里的) --> 每一个引用这个属性的都是一样的内容

    2)实例化:类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特有的属性

    关于类里的方法括号中的self:

       self 在实例化时自动将对象/实例本身传给__init__的第一个参数

       self 也可以说是:哪一个对象调用这个方法,self就是哪一个对象的引用

    在类封装的方法内部,self就表示当前调用方法的对象自己

    --调用方法时,程序员不需要传递self参数(但是定义的时候,第一个参数必须是self)

    --在方法内部:可以通过self.访问对象的属性

    --在方法内部:可以通过self.调用其他的对象方法

    示例:

    class Cat:

        """这是class Cat的信息"""

        def eat(self):

            print '%s爱吃鱼' %self.name

        def drink(self):

            print '%s要喝水'%self.name

    # 创建猫对象

    tom = Cat()

    # 可以使用 .属性名 利用赋值语句就可以了

    #tom.name = 'Tom'

    tom.eat()

    tom.name = 'Tom'

    tom.drink()

    print tom

    # lazy_cat = Cat()

    # lazy_cat.name = 'miaomiao'

    # lazy_cat.eat()

    # lazy_cat.drink()

    2.内置方法

    初始化方法:__init__是python对象的内置方法,在使用类名创建对象的时候自动被调用

    __init__方法是专门用来定义一个类具有那些属性和方法的

    ##如果不用初始化方法,像一些基本属性可能在创建对象以后,还需要对象.属性,这样填写属性,还需要print手动去输出它,添加这个初始化方法,在创建方法之后会主动调用这个方法,将填写的信息添加并且输出

     

    ##当初始化方法没有形参变量的时候,方法内部所定义的属性,在利用该类创建对象的时候,创建的所有对象都会拥有该属性

     

    ##当初始化方法含有形参变量的时候,在利用该类创建对象的时候,创建的所有对象都会自动调用初始化方法,并且会要求添加相应的对象的属性,如果不添加就执行的话,编译器会报错

     

    __del__方法:对象被从内存中销毁前,会自动调用

    __str__方法:返回对象的描述信息 print 对象

    __del__方法:在python中,当一个对象被从内存中销毁前(把这个对象从内存中删除掉),会自动调用__del__方法

    应用场景:

    __del__如果希望在对象被销毁前,再做一些事情,可以考虑一下__del__方法

    __str__方法:在python中,使用python输出对象变量,默认情况下,会输出这个变量引用的对象是由哪>一个类创建的对象,以及在内存中的地址(十六进制表示).如果在开发中,希望使用print输出对象变量时,能够打印自定义的内容,就可以利用__str__这个内置方法了

    示例:

    1)

    class Dog:

        def __init__(self,name,weight):

            self.name = 'rourou'

            self.weight = weight

            print '%s是一个%d斤的狗狗!'%(self.name,self.weight)

        def eat(self):

            print '%s爱吃肉'%self.name

        def drink(self):

            print '%s爱喝牛奶'%self.name

    rourou = Dog('rourou',10)

    rourou.eat()

    rourou.drink()

    print rourou

    2)

    class Dog:

        def __init__(self,name,weight):

            self.name = name

            self.weight = weight

            print '%s是一个%d斤重的狗狗!'%(self.name,self.weight)

        def __del__(self):

            print '内存信息被删除之前的调用!'

        def __str__(self):

            return '我是肉肉!'

    dog = Dog('rourou',10)

    print '========='

    print dog

    # tom是一个全局变量

    # 所以当我们的代码全部执行完之后,系统才会把tom这个对象进行回收

    tom = Cat('Tom')

    print tom

    # print tom.name

    # # del关键字,可以从内存中删除一个对象,del关键字自己调用了__del__方法

    # del tom

    # print '*' * 50

    生命周期

    一个对象从调用类名()创建,声明周期开始

    一个对象的__del__方法一旦被调用,生命周期就结束

    在对象的生命周期内,可以访问对象的属性,调用对象的方法

    3.私有属性和私有方法

    1)私有属性和私有方法:在属性或方法前加两个下划线 '__',声明该方法是私有方法或者属性,不能在类的外部调用。在类的内部可以调用

    私有属性 就是 对象 不希望公开的 属性

    私有方法 就是 方法 不希望公开的 方法

    2)应用场景及定义方式:

    应用场景:

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

    定义方法:

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

    示例:

    class Women:

        def __init__(self,name):

            self.name = name     ##这是一个公有属性

            self.__age = 18      ##这是一个私有属性

        def __secret(self):      ##这是一个私有方法

            print '%s 的年龄是 %d' %(self.name,self.__age)

    lily = Women('lily')

    print lily.name

    # 私有属性,外界不能直接访问

    print lily.age

    # 私有方法,外界不能直接调用

    lily.__secret()

    结果:

       会出现报错,显示没有这个属性,所以说,私有属性和方法,在类的外部不能被调用

    lily

    Traceback (most recent call last):

      File "/home/kiosk/PycharmProjects/王芳/day06/私有属性和私有方法.py", line 27, in <module>

        print lily.age

    AttributeError: Women instance has no attribute 'age'

    3)类的私有属性和私有方法

    --子类对象不能在自己的方法内部,直接访问父类的私有属性和私有方法

    --子类对象可以通过父类的公有方法间接访问到私有属性或私有方法

    私有属性,私有方法是对象的隐私,不对外公开,外界以及子类都不能直接访问

    私有属性,私有方法常用做一些内部的事情

    示例:

    class A:

        def __init__(self):

            # 在初始化方法中定义两个属性,一个公有属性一个私有属性

            self.num1 = 100     #公有属性

            self.__num2 = 200   #私有属性

        def __test(self):

            print '私有方法 %d %d' % (self.num1, self.__num2)

        ##如果要查看私有的属性和方法,可以在类A中定义一个公有方法,然后在公有方法中调用私有的方法和属性,再print就可以输出私有的属性和方法。再在子类直接调用这个公有方法就可以了

        def test(self):

            print '父类的共有方法 %d' % self.__num2

            self.__test()

    class B(A):

        def demo(self):

            # # 在子类的对象方法中,不能访问父类的私有属性

            # print '访问父亲的私有属性 %d' % self.__num2

            # # 在子类对象的方法中,不能调用父类的私有方法

            # self.__test()

            #调用父类的共有方法

            self.test()

    # 创建一个子类对象

    b = B()

    b.demo()

    # b.test()

    # 在外界不能直接访问对象有属性/调用私有方法

    # print b.__num2的私

    # b.__test()

    4.面向对象的三大特征

    (1)封装:根据职责将属性和方法封装到一个抽象的类中

    (2)继承:实现代码的重用,相同的代码不需要重复的写

    (3)多态

    5.单继承

    继承的概念:子类拥有父类的所有属性和方法

    继承的语法

    class 类名(父类):

        def 子类特有的方法

    """

    Cat类是Animal类的子类,Animal类是Cat类的父类,Cat从Animal类继承

    Cat类是Animal类的派生类,Animal类是Cat类的基类,Cat类从Animal类派生

    """

    class Animal(object):

        def eat(self):

            print '吃'

        def drink(self):

            print '喝'

        def run(self):

            print '跑'

        def sleep(self):

            print '睡'

    class Cat(Animal):

        # 子类拥有父类的所有属性和方法

        def call(self):

            print '喵喵'

    class Dog(Animal):

        def bark(self):

            print '旺旺'

    class Hellokitty(Cat):

        def speak(self):

            print '我可以说日语'

    # 创建一个猫对象

    fentiao = Cat()

    fentiao.eat()

    fentiao.drink()

    fentiao.run()

    fentiao.sleep()

    fentiao.call()

    # 创建一个hellokitty对象

    # kt = Hellokitty()

    # kt.speak()

    # kt.call()

    # 继承的传递性,子类拥有父类的父类的属性和方法

    """

    继承的传递性:(爷爷 父亲 儿子)

    1.C类从B类继承,B类又从A类继承

    2.那么C类就具有B类和A类的所有属性和方法

    子类拥有父类以及父类的父类中封装的所有属性和方法

    """

    kt.eat()

    kt.drink()

    kt.run()

    kt.sleep()

    # 子类继承自父类,可以直接享受父类中已经封装好的方法

    # 子类中应该根据自己的职责,封装子类特有的属性和方法

    6.多继承

    class A:

        def test(self):

            print 'A-----test 方法'

        def demo(self):

            print 'A-----demo 方法'

    class B:

        def test(self):

            print 'B------test 方法'

        def demo(self):

            print 'B-------demo方法'

    class C(B,A):

        """多继承可以让子类对象,同时具有多个父类的属性和方法"""

        """多继承(A,B)这个,如果两个父类的方法重名的话,哪个放在前面就继承哪个"""

        pass

    # 创建子类对象

    c = C()

    c.test()

    c.demo()

    7.封装

    (1)封装是面向对象编程的一大特点

    (2)面向对象编程的第一步 将属性和方法封装到一个抽象的类中(为什么说是抽象的,因为类不能直接使用)

    (3)外界使用类创建对象,然后让对象调用方法

    (4)对象方法的细节都被封装在类的内部

     

    示例:

    小明爱跑步

    1.小明体重75.0公斤

    2.每次跑步会减肥0.5公斤

    3每次吃东西体重会增加1公斤

    4.小美的体重是45.0公斤

    class Person:

        def __init__(self,name,weight):

            self.name = name

            self.weight = weight

        def __str__(self):

            return '我的名字叫 %s 体重是 %.2f' %(self.name,self.weight)

        def run(self):

            print '%s 爱跑步' %self.name

            # 在对象方法的内部,是可以直接访问对象的属性

            self.weight -= 0.5

        def eat(self):

            print '%s 吃东西' %self.name

            self.weight += 1

    xx = Person('小明',75.0)

    xx.run()

    xx.eat()

    print xx

    # 同一个类创建出来的多个对象之间,属性互不干扰

    xm = Person('小美',45.0)

    xm.run()

    xm.eat()

    print xm

    封装练习:

    (1)需求

    --房子有户型,总面积和家具名称列表

        新房子没有任何家具

    --家具有名字和占地面积,其中

        床:占4平米

        衣柜:占2平米

        餐桌:占1.5平米

    --将以上三件家具添加到房子中

    --打印房子时,要求输出:户型,总面积,剩余面积,家具名称列表

     

    被使用的类应该先开发

    就比如:先要将家具定义出来,然后才能往房子里面加

    # 创建家具类

    class HouseItem:

        def __init__(self, name, area):

            self.name = name

            self.area = area

        def __str__(self):

            return '[%s]占地为 %.2f' % (self.name, self.area)

    # 创建家具

    bed = HouseItem('bed', 4)

    print bed

    chest = HouseItem('chest', 2)

    print chest

    table = HouseItem('table', 1.5)

    print table

    # 创建房子类

    class House:

        def __init__(self, house_type, area):

            # 下面为从外界传递进来的参数

            self.house_type = house_type

            self.area = area

            # 剩余面积不需要从外面传递,内部计算

            # 剩余面积 = 总面积 - 家具面积

            # 新房子内没有任何家具,剩余面积=总面积

            self.free = area

            self.item_list = []

        def __str__(self):

            return '户型:%s 总面积:%.2f[剩余面积:%.2f] 家具:%s'

                   % (self.house_type, self.area, self.free, self.item_list)

        def add_item(self, item):

            if item.area >= self.area:

                print '请重新订购家具'

            else:

                print '添加成功'

                self.item_list.append(item.name)

                self.free -= item.area

    # 创建房子

    house = House('两室一厅', 100)

    house.add_item(bed)

    house.add_item(chest)

    house.add_item(table)

    print house

    (2)需求:

    --士兵瑞恩有一把AK47

    --士兵可以开火(士兵开火扣动的是扳机)

    --枪 能够 发射子弹(把子弹发射出去)

    --枪 能够 装填子弹  --增加子弹数量

     

    class Gun:

        def __init__(self, name):

            # 自己输入枪的型号

            self.name = name

            # 假设默认的子弹数是10个

            self.count = 10

            self.free = self.count

        def add_zidan(self, num):

            if num + self.free > 10:

                print '子弹数超过10颗!装子弹失败'

            else:

                self.free += num

                print '子弹添加成功!'

        def shoot(self):

            if self.free <= 0:

                print '没有子弹了!'

            else:

                self.free -= 1

                print '开火ing...'

    class Person:

        def __init__(self,name):

            self.name = name

            self.gun = None

        def fire(self):

            if self.gun == None:

                print '还没有枪'

                return

            print 'go!'

            self.gun.shoot()

            self.gun.add_zidan(1)

    ak47 = Gun('AK47')

    ren = Person('ryan')

    #人使用枪

    ren.gun = ak47

    ren.fire()

    print ren

    8.重写父类方法

    (1).覆盖父类的方法

    (2).扩展父类的方法

    class Animal:

        def eat(self):

            print '吃'

        def drink(self):

            print '喝'

        def run(self):

            print '跑'

        def sleep(self):

            print '睡'

    class Cat(Animal):

        # 子类拥有父类的所有属性和方法

        def call(self):

            print '喵喵'

    class Hellokitty(Cat):

        def speak(self):

            print '我可以说话'

        def call(self):

            # 重写父类的方法

            print '话~~'

            # 调用原本在父类中封装的代码

            Cat.call(self)

            # 增加其他的子类代码

            print '#!@$@!#!#'

    kt = Hellokitty()

    # 如果子类中,重写了父类的方法

    # 在运行中,只会调用在子类中重写的父类的方法而不会调用父类的方法

    kt.call()

    重写的练习:

    --在写好的代码Bird类的上面,加入一个唱歌的属性(要增加到默认属性当中)

    class Bird:

        def __init__(self):

            self.hungry = True

        def eat(self):

           # 如果吃过了就不饿了

            if self.hungry:

                print '吃东西ing。。。'

                self.hungry = False

            else:

                print 'No,thanks!'

    错误代码:

    class songBird(Bird):

        def __init__(self):

            self.sound = 'squawk!'

        def sing(self):

            print self.sound

    lb = songBird()

    lb.eat()

    lb.sing()

    print lb

    ##这就相当于是songBird的初始化方法将原本的代码的初始化方法覆盖了,因此就没有了 self.hungry = True 这行代码,因此下面的判断就不能够执行下去

    ##正确的代码应该是,继承了父类,重写并且调用父类的被重写的方法,这样就相当于是在不更改源代码的同时,增加了默认的属性

    正确代码:

    class songBird(Bird):

        def __init__(self):

            self.sound = 'squawk!'

            Bird.__init__(self)   ##这条语句就是调用父类的方法

        def sing(self):

            print self.sound

    lb = songBird()

    lb.eat()

    lb.sing()

    print lb

    9.新式类和旧式(经典)类

       object是Python为所有对象提供的基类,提供有一些内置的属性和方法,可以使用dir函数查看

       新式类:以object为基类的类,推荐使用

       经典类:不以object为基类的类,不推荐使用

       python3.X中定义的类时,如果没有指定父类,会默认使用object作为基类--python3.x中定义的类都是新式类

       python2.x中定义类时,如果没有指定父类,则不会以object作为基类

    ####推荐使用新式类#############

    新式类和旧式类在多继承时---会影响到方法的搜索顺序

    为保证编写的代码能够同时在python2.x和python3.x运行

    今后在定义类时,如果没有父类,建议统一继承自object

    10.综合练习

    图书管理系统

        图书管理系统

            1.查询

            2.增加

            3.借阅

            4.归还

            5.退出

  • 相关阅读:
    libevent-2.0.so.5 (安装MEMCACHED问题)
    MySQL的show语句大全
    远程客户端连接MysqL数据库太慢解决方案
    用SQL命令查看Mysql数据库大小
    elasticsearch-head安装及启动
    logstash收集IIS日志
    备份并删除7天以前数据
    shell脚本递归压缩实践
    二目运算符 “->”
    关于int main( int argc, char *argv[] )
  • 原文地址:https://www.cnblogs.com/wf-aiyouwei/p/9644022.html
Copyright © 2020-2023  润新知