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.退出

原文地址:https://www.cnblogs.com/wf-aiyouwei/p/9644022.html