美文网首页
Python ☞ day 8

Python ☞ day 8

作者: 浪子彦卿L | 来源:发表于2018-05-09 00:33 被阅读0次

Python学习笔记之 面向对象

第一个python类
  • 设计类
    类名:见名之意,首字母大写,其他遵循驼峰原则
    属性:见名之意,其他遵循驼峰原则
    行为(方法/功能):见名之意,其他遵循驼峰原则
  • 列如:
  1. 类名:Wife
    属性:sex age height weight faceValue
    行为:做饭 洗衣服 拖地 揉肩 捶腿
  2. 类名:Husband
    属性:sex age height weight faceValue
    行为:吃饭 看电视 打游戏 被揉肩 被捶腿
  3. 类名:Car
    属性: color type
    行为:跑
  • 创建类
    类:一种数据类型,本身并不占内存空间,根所学过的number,string,boolean等类似。用类创建实例化对象(变量),对象占内存空间
格式:
class  类名(父类列表):
    属性
    行为
#            object:基类,超类,所有类的父类,一般没有合适的父类就写object
class Person(object):
    #定义属性(定义变量)
    name = ""
    age = 0
    height = 0
    weight = 0

    #定义方法(定义函数)
    #注意:方法的参数必须以self当第一个参数
    #self代表类的实例(某个对象)
    def run(self):
        print("run")
    def eat(self, food):
        print("eat" + food)
使用类实例化对象
  • 实例化对象
    格式: 对象名 = 类名(参数列表)
    注意:没有参数,小括号也不能省略
class Person(object):
    name = ""
    age = 0
    height = 0
    weight = 0
    def run(self):
        print("run")
    def eat(self, food):
        print("eat" + food)
    def openDoor(self):
        print("我已经打开了冰箱门")
    def fillEle(self):
        print("我已经把大象装进冰箱了")
    def closeDoor(self):
        print("我已经关闭了冰箱门")


#实例化一个对象
per1 = Person()
print(per1)
print(type(per1))
print(id(per1))

per2 = Person()
print(per2)
print(type(per2))
print(id(per2))
访问对象的属性和方法
  • 访问属性
    格式:对象名.属性名
    赋值:对象名.属性名 = 新值
class Person(object):
    name = "stu"
    age = 10
    height = 160
    weight = 90
    def run(self):
        print("run")
    def eat(self, food):
        print("eat " + food)
    def openDoor(self):
        print("我已经打开了冰箱门")
    def fillEle(self):
        print("我已经把大象装进冰箱了")
    def closeDoor(self):
        print("我已经关闭了冰箱门")


per = Person()

per.name = "tom"
per.age = 18
per.height = 160
per.weight = 80
print(per.name, per.age, per.height, per.weight)
  • 访问方法
    格式:对象名.方法名(参数列表)
class Person(object):
   name = "stu"
   age = 10
   height = 160
   weight = 90
   def run(self):
       print("run")
   def eat(self, food):
       print("eat " + food)
   def openDoor(self):
       print("我已经打开了冰箱门")
   def fillEle(self):
       print("我已经把大象装进冰箱了")
   def closeDoor(self):
       print("我已经关闭了冰箱门")


per = Person()

per.openDoor()
per.fillEle()
per.closeDoor()

per.eat("apple")



#问题:目前来看Person创建的所有对象属性都是一样的
per2 = Person()
print(per2.age)
per3 = Person()
print(per3.age)
对象的初始状态(构造函数)
构造函数:__init__()   在使用类创建对象的时候自动调用
注意:如果不显示的写出构造函数,默认会自动添加一个空的构造函数
class Person(object):
    #name = "stu"
    #age = 10
    #height = 160
    #weight = 90
    def run(self):
        print("run")
    def eat(self, food):
        print("eat " + food)

    def __init__(self, name, age, height, weight):
        #print(name, age, height, weight)
        #定义属性
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight


per = Person("hanmeimei", 20, 170, 55)
print(per.name, per.age)

per2 = Person("lilei", 21, 175, 70)
print(per2.name, per2.age)

per.run()
self
  • self代表类的实例,而非类
    哪个对象调用方法,那么该方法中的self就代表那个对象
self.__class__  代表类名_
class Person(object):
    def run(self):
        print("run")
        print(self.__class__)
        p = self.__class__("tt", 30, 10, 30)
        print(p)
    def eat(self, food):
        print("eat " + food)
    def say(self):
        print("Hello! my name is %s, I am %d years old" % (self.name, self.age))
    #self不是关键字,换成其他的标识符也是可以的,但是帅的人都是用self
    def play(a):
        print("play " + a.name)
    def __init__(self, name, age, height, weight):
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight

per1 = Person("tom", 20, 160, 80)
per1.say()

per2 = Person("hanmeimei", 21, 160, 80)
per2.say()


per1.play()

per1.run()
析构函数
析构函数:__del__()    释放对象是自动调用
class Person(object):
    def run(self):
        print("run")
    def eat(self, food):
        print("eat " + food)
    def __init__(self, name, age, height, weight):
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight
    def __del__(self):
        print("这里是析构函数")

per = Person("hanmeimei", 20, 170, 55)
#释放对象
del per

#对象释放以后就不能再访问了
#print(per.age)


#在函数里定义的对象,会在函数结束时自动释放,这样可以用来减少内存空间的浪费
def func():
    per2 = Person("aa", 1, 1, 1)

func()

while 1:
    pass
重写:将函数重写定义写一遍
__str__():在调用print打印对象时自动调用,是给用户用的,是一个描述对象的方法。
__repr__():是给机器用的,在Python解释器里面直接敲对象名在回车后调用的方法
注意:在没有str时,且有repr,str = repr
class Person(object):
    def __init__(self, name, age, height, weight):
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight
    def __str__(self):
        return "%s-%d-%d-%d" % (self.name, self.age, self.height, self.weight)


per = Person("hanmeimei", 20, 170, 55)
#print(per.name, per.age, per.height, per.weight)
print(per)

优点:当一个对象的属性值很多,并且都需要打印,重写了__str__方法后,简化了代码
访问限制
class Person(object):
    def run(self):
        print(self.__money)
        print("run")
    def eat(self, food):
        print("eat " + food)
    def __init__(self, name, age, height, weight, money):
        self.name = name
        self.__age__ = age
        self._height = height
        self.weight = weight
        self.__money = money#_Person__money

    #通过内部的方法,取修改私有属性
    #通过自定义的方法实现对私有属性的赋值与取值
    def setMoney(self, money):
        #数据的过滤
        if money < 0:
            money = 0
        self.__money = money
    def getMoney(self):
        return self.__money


per = Person("hanmeimei", 20, 170, 55, 100000)
#per.age = 10
#print(per.age)

#如果要让的内部属性不被外部直接访问,在属性前加两个下划线(__),在Python中如果在属性前加两个下划线,那么这个属性就变成了私有属性
#print(per.__money)  #外部使用
#per.run()   #内部可以使用

per.setMoney(10)
print(per.getMoney())

#不能直接访问per.__money是因为Python解释器把__money变成了_Person__money,仍然可以用_Person__money去访问,但是强烈建议不要这么干(帅的人都不这么干),不同的解释器可能存在解释的变量名不一致
per._Person__money = 1
print(per.getMoney())



#在Python中  __XXX__   属于特殊变量,可以直接访问
print(per.__age__)


#在Python中  _XXX  变量,这样的实例变量外部是可以访问的,但是,按照约定的规则,当我们看到这样的变量时,意思是“虽然我可以被访问,但是请把我视为私有变量,不要直接访问我”
print(per._height)
单继承的实现
# 定义第一个类:
class Person(object):
    def __init__(self, name, age, money):
        self.name = name
        self.age = age
        self.__money = money

    def setMoney(self, money):
        self.__money = money
    def getMoney(self):
        return self.__money

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

    def eat(self, food):
        print("eat " + food)



# 定义第一个继承类
from person import Person  #引入Person类

class Student(Person):
    def __init__(self, name, age, money, stuId):
        #调用父类中的__init__
        super(Student, self).__init__(name, age, money)
        #子类可以有一些自己独有的属性
        self.stuId = stuId

    def stuFunc(self):
        print(self.__money)



# 定义第二个继承类
from person import Person

class Worker(Person):
    def __init__(self, name, age, money):
        #调用父类中的__init__
        super(Worker, self).__init__(name, age, money)



# 单继承的实现
from person import Person
from student import Student
from worker import Worker

per = Person("aa", 1, 2)


stu = Student("tom", 18, 12345, 110)
print(stu.name, stu.age)
stu.run()
print(stu.stuId)
#print(stu.__money)私有属性
print(stu.getMoney())  #通过继承过来的共有方法访问私有属性
#stu.stuFunc()


wor = Worker("lilei", 20, 111)
print(wor.name, wor.age)
wor.eat("apple")


print(per.getMoney())

多继承的实现
# 定义一个母亲类
class Mother(object):
    def __init__(self, faceValue):
        self.faceValue = faceValue
    def eat(self):
        print("eat")
    def func(self):
        print("func2")


# 定义一个父亲类
class Father(object):
    def __init__(self, money):
        self.money = money
    def play(self):
        print("play")
    def func(self):
        print("func1")



# 定义一个小孩类
from Father import Father
from Mother import Mother

class Child(Father, Mother):
    def __init__(self, money, faceValue):
        #写法
        Father.__init__(self, money)
        Mother.__init__(self, faceValue)



# 多继承的实现   调用
from Child import Child

def main():
    c = Child(300, 100)
    print(c.money, c.faceValue)
    c.play()
    c.eat()
    #注意:父类中方法名相同,默认调用的是在括号中排前面的父类中的方法
    c.func()
if __name__ == "__main__":
    main()

多态
# 定义一个动物类
class Animal(object):
    def __init__(self, name):
        self.name = name
    def eat(self):
        print(self.name + "吃")


# 定义一个猫类
from animal import Animal
class Cat(Animal):
    def __init__(self, name):
        #self.name = name
        super(Cat, self).__init__(name)
    # def eat(self):
    #     print(self.name + "吃")


# 定义一个老鼠类
from animal import Animal
class Mouse(Animal):
    def __init__(self, name):
        #self.name = name
        super(Mouse, self).__init__(name)
    # def eat(self):
    #     print(self.name + "吃")


# 定义一个人类
class Person(object):
    '''
    def feedCat(self, cat):
        print("给你食物")
        cat.eat()
    def feedMouse(self, mouse):
        print("给你食物")
        mouse.eat()
    '''
    def feedAnimal(self, ani):
        print("给你食物")
        ani.eat()


# 多态        -    及调用
from cat import Cat
from mouse import Mouse
from person import Person
'''
多态:一种事物的多种形态

最终目标:人可以喂任何一种动物
'''

tom = Cat("tom")
jerry = Mouse("jerry")

tom.eat()
jerry.eat()

#思考:在添加100种动物,也都有name属性和eat方法
#定义了一个有name属性和eat方法的Animal类,让所有的动物类都继承自Animal



#定义一个人类,可以喂猫和老鼠吃东西
per = Person()

#per.feedCat(tom)
#per.feedMouse(jerry)


#思考:人要喂100种动物,难道要写100个feed方法吗??
#tom和jerry都继承自动物
per.feedAnimal(tom)
per.feedAnimal(jerry)

对象属性与类属性

class Person(object):
    # 这里的属性实际上属于类属性(用类名来调用)
    name = "person"
    def __init__(self, name):
        pass
        #对象属性
        self.name = name


print(Person.name)
per = Person("tom")
#对象属性的优先级高于类属性
print(per.name)
#动态的给对象添加对象属性
per.age = 18#只针对于当前对象生效,对于类创建的其他对象没有作用
print(Person.name)
per2 = Person("lilei")
#print(per2.age)  #没有age属性


#删除对象中的name属性,在调用会使用到同名的类属性
del per.name
print(per.name)

#注意:以后千万不要讲对象属性与类属性重名,因为对象属性会屏蔽掉类属性。但是当删除对象属性后,在使用又能使用类属性了。


动态给实例添加属性和方法并使用__slots__
from types import MethodType

#创建一个空类
class Person(object):
    __slots__ = ("name", "age", "speak")


per = Person()
#动态添加属性,这体现了动态语言的特点(灵活)
per.name = "tom"
print(per.name)
#动态添加方法
'''
def say(self):
    print("my name is " + self.name)
per.speak = say
per.speak(per)
'''
def say(self):
    print("my name is " + self.name)
per.speak = MethodType(say, per)
per.speak()


#思考:如果我们想要限制实例的属性怎么办?
#比如,只允许给对象添加name,age,height,weight属性


#解决:定义类的时候,定义一个特殊的属性(__slots__),可以限制动态添加的属性

per.height = 170
print(per.height)


class Person(object):
    def __init__(self, name, age):
        #属性直接对外暴露
        #self.age = age
        #限制访问
        self.__age = age
        self.__name = name

    def getAge(self):
        return self.__age
    def setAge(self, age):
        if age < 0:
            age = 0
        self.__age = age

    #方法名为受限制的变量去掉双下划綫
    @property
    def age(self):
        return self.__age
    @age.setter  #去掉下划线.setter
    def age(self, age):
        if age < 0:
            age = 0
        self.__age = age

    @property
    def name(self):
        return self.__name
    @name.setter  # 去掉下划线.setter
    def name(self, name):
        self.__name = name


per = Person("sunck", 18)

#属性直接对外暴露
#不安全,没有数据的过滤
#per.age = -10
#print(per.age)


#使用限制访问,需要自己写set和get方法才能访问
#per.setAge(15)
#print(per.getAge())

per.age = -100 #相当于调用setAage
print(per.age) #相当于调用getAge

print(per.name)

#property:可以让你对受限制访问的属性使用点语法
  • 人开枪射击子弹练习
# 定义一个弹夹类
class BulletBox(object):
    def __init__(self, count):
        self.bulletCount = count



# 定义一个枪类
class Gun(object):
    def __init__(self, bulletBox):
        self.bulletBox = bulletBox
    def shoot(self):
        if self.bulletBox.bulletCount == 0:
            print("没有子弹了")
        else:
            self.bulletBox.bulletCount -= 1
            print("剩余子弹:%d发" % (self.bulletBox.bulletCount))



# 定义一个人类
class Person(object):
    def __init__(self, gun):
        self.gun = gun
    def fire(self):
        self.gun.shoot()
    def fillBullet(self, count):
        self.gun.bulletBox.bulletCount = count



# 调用
from person import Person
from gun import Gun
from bulletbox import BulletBox

'''
人
类名:Person
属性:gun
行为:fire


枪
类名:Gun
属性:bulletBox
行为:shoot

弹夹
类名:BulletBox
属性:bulletCount
行为:
'''


#弹夹
bulletBox = BulletBox(5)

#枪
gun = Gun(bulletBox)

#人
per = Person(gun)


per.fire()
per.fire()
per.fire()
per.fire()
per.fire()

per.fire()
per.fire()

per.fillBullet(2)
per.fire()
per.fire()
per.fire()


执行调用这个程序得到结果:
剩余子弹:4发
剩余子弹:3发
剩余子弹:2发
剩余子弹:1发
剩余子弹:0发
没有子弹了
没有子弹了
剩余子弹:1发
剩余子弹:0发
没有子弹了

相关文章

网友评论

      本文标题:Python ☞ day 8

      本文链接:https://www.haomeiwen.com/subject/xbmgrftx.html