Python面向对象2021-08-27

面向对象思想及简介

软件编程的实质:

软件编程就是将我们的思维转换成计算机能够识别语言的一个过程

什么是面向过程?

 1、自上而下顺序执行,逐步求精
 2、其程序结构是按功能划分为若干个基本模块,这些模块形成树状结构 
 3、各模块之间的关系尽可能简单,在功能上相对独立 
 4、每一模块内部均是由顺序、选择和循环三种基本结构组成 
 5、其模块化实现的具体方法是使用子程序 程序流程在写程序时就已决定

什么是面向对象?

 1、把数据及对数据的操作方法放在一起,作为一个相互依赖的整体—对象 
 2、对同类对象抽象出其共性,形成类 
 3、类中的大多数数据,只能用本类的方法进行处理 
 4、类是通过一个简单的外部接口与外界发生关系,对象与对象之间通过消息进行通信 
 5、程序流程由用户在使用中决定

理解面向对象

1、 面向对象是面向过程而言 
2、 面向对象和面向过程都是一只思想 面向过程
 	  强调的是功能行为 
 	  关注的是解决问题需要哪些步骤 
3、 面向对象
 	将功能封装进对象,强调具备了功能的对象 
 	关注的是解决问 题需要哪些对象 
4、 面向对象是基于面向过程的

面向对象和面向过程思想

在这里插入图片描述

面向对象的特点

是一种符合人们思考习惯的思想 
可以将复杂的事情简单化 将程序员从 
执行者转成了指挥者 
完成需求时: 
	先要去找具有所需的功能的对象来用 
	如果该对象不存在,那么创建一个具有所需功能的对象

类与对象的关系

使用计算机语言就是不断的在描述现实生活中的事 
Python中描述事物通过类的形式体现,类是具体事物概念上的定义 
对象既是该类事物实实在在存在的个体

1、类:

类的定义

生活中描述事物无非是描述事物的名称、属性和行为
	 如:人的身高,体重等属性,行为有说话打架等 
Python中用类来描述事物也是如此 
	属性:对应类中的成员变量 
	行为:对应类中成员的方法 
定义类其实在定义类中的成员(成员变量和成员方法) 
拥有相同(或者类似)属性和行为的对象都可以
一种数据类型,本身并不占内存空间跟所学过的number,string,boolean等类似

用类创建实例化对象(变量),对象占内存空间

设计类

只关心3样东西 
事物名称(类名):人(Person) 
属性{身高(height)、年龄(age) 
行为(功能):跑(run)、打架(fight)

类名:见明之意,首字母大写,其他遵循驼峰原则,
属性:见明之意,其他遵循驼峰原则,
行为(方法/功能):见明之意,其他遵循驼峰原则,

创建类

格式:
class 类名(父类列表):
    属性
    行为
class Person(object):
#object:基类,超类,所有类的父类。一般没有合适的父类就写object

    #定义属性(定义变量)
    name = ""
    age = 0
    height = 0
    weight = 0

    #定义方法(定义函数)
    #注意:方法的参数必须以self当做第一个参数
    #self代表类的实例(某个对象)
    def run(self):
        print("run")
    def eat(self, food):
        print("eat" + food)

2、使用类实例化对象

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))

3、访问对象的属性与方法

class Person(object):
    name = "stu"
    age = 10
    height = 160
    weight = 80
    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)

访问方法

格式: 对象名.方法名(参数列表)
per.openDoor()
per.fillEle()
per.closeDoor()

per.eat("apple")

#问题:目前来看Person创建的所有对象属性都是一样的
per2 = Person()
print(per2.age)
per3 = Person()
print(per3.age)

4、对象的初始状态(构造函数)

class Person(object):
    # name = "stu"
    # age = 10
    # height = 160
    # weight = 80
    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
'''
构造函数:__init__()
在使用类创建对象的时候自动调用
注意:如果不显示的写出构造函数,默认会自动添加一个空的构造函数
'''
per = Person("hanmeimei", 20, 170, 55)
print(per.name, per.age)
per2 = Person("lilei", 21, 175, 70)
print(per2.name, per2.age)

5、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")
    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()

6、析构函数

析构函数: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, 50)
#释放对象
del per
#对象释放以后就不能访问了
# print(per.age)

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

7、重写__repr__与__str__函数

重写:将函数重写定义写一遍,
__str__():在调用print打印对象时自动调用,时给用户用的,是一个描述对象的方法
__repr__():是给机器用的,在Python解释器里面直接敲对象名再回车后调用的方法
注意:在没有str时,且有repr,repr = str
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, 50)
# print(per.name, per.age, per.height, per.weight)
print(per)

#优点:当一个对象的属性值很多,并且都需要打印,重写了___str__方法后,简化了代码

8、访问限制

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

per = Person("hanmeimei", 20, 170, 50, 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__属于特殊变量,可以直接访问

#在Python中 _xxx 变量,这样的实例变量,外部也可以访问,但是按照约定的规则,
# 当我们看到这样的变量时,意思是,虽然我可以被访问,但是请把我视为私有变量,
# 不要直接访问我

9、继承

继承i

10、单继承的实现

person.py

class Person(object):
    def __init__(self, name, age, money):
        self.name = name
        self.age = age
        self.__money = money
    def run(self):
        print("run")
    def eat(self, food):
        print("eat " + food)
    def setMoney(self, money):
        self.__money = money
    def getMoney(self):
        return self.__money

student.py

from person import 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)

worker.py

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

单继承的实现.py

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())
wor = Worker("lilei", 20, 111)
print(wor.name, wor.age)
wor.eat("apple")
print(per.getMoney())

11、多继承的实现

多继承的实现.py

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

children.py

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)

father.py

class Father(object):
    def __init__(self, money):
        self.money = money
    def run(self):
        print("run")
    def func(self):
        print("func1")

mother.py

class Mother(object):
    def __init__(self, faceValue):
        self.faceValue = faceValue
    def eat(self):
        print("eat")
    def func(self):
        print("func2")

12、多态

多态:一种事物的多种形态

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个么?
#tom 和 Jerry都继承自动物
per = Person()
per.feedAnimal(tom)
per.feedAnimal(jerry)

animal.py

class Animal(object):
    def __init__(self, name):
        self.name = name
    def eat(self):
        print(self.name + "吃")

cat.py

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 + "吃")

mouse.py

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 + "吃")

person.py

class Person(object):
    '''
    def feedCat(self, cat):
        print("给你食物")
        cat.eat()
    def feedMouse(self, mouse):
        print("给你食物")
        mouse.eat()
    '''
    def feedAnimal(self, ani):
        print("给你食物")
        ani.eat()

13、对象属性与类属性

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)
#注意:以后千万不要将对象属性与类属性重名,因为对象属性会屏蔽掉类属性,
#但是当删除对象属性后,再使用又能使用类属性了

14、动态给实例添加属性和方法并使用

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()
'''
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)

15、@property

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 #相当于调用setAge
print(per.age)#相当于调用getAge

print(per.name)
# @property可以让你对受限制的访问的属性使用点语法

16、运算符重载

#不同的类型用加法会有不同的解释

print(1 + 2)
print("1" + "2")
#不同的类型用加法会有不同的解释
class Person(object):
    def __init__(self, num):
        self.num = num
    #运算符重载
    def __add__(self, other):
        return Person(self.num + other.num)
    def __str__(self):
        return "num =" + str(self.num)
per1 = Person(1)
per2 = Person(2)
print(per1 + per2)
#per1 + per2 === per1.__add__(per2)
print(per1)
print(per2)

算术运算符的重载:

  方法名                  运算符和表达式           说明
   __add__(self,rhs)        self + rhs            加法
   __sub__(self,rhs)        self - rhs            减法
   __mul__(self,rhs)        self * rhs            乘法
   __truediv__(self,rhs)    self / rhs            除法
   __floordiv__(self,rhs)   self //rhs            地板除
   __mod__(self,rhs)        self % rhs            取模(求余)
   __pow__(self,rhs)        self **rhs            幂运算

反向算术运算符的重载:

  方法名                       运算符和表达式       说明
    __radd__(self,lhs)       lhs + self           加法
    __rsub__(self,lhs)       lhs - self           减法
    __rmul__(self,lhs)       lhs * self           乘法
    __rtruediv__(self,lhs)    lhs / self          除法
    __rfloordiv__(self,lhs)   lhs // self         地板除
    __rmod__(self,lhs)       lhs % self           取模(求余)
    __rpow__(self,lhs)       lhs ** self          幂运算

复合赋值算术运算符的重载:

    方法名                    运算符和表达式      说明
    __iadd__(self,rhs)        self += rhs        加法
    __isub__(self,rhs)        self -= rhs        减法
    __imul__(self,rhs)        self *= rhs        乘法
    __itruediv__(self,rhs)    self /= rhs        除法
    __ifloordiv__(self,rhs)    self //=rhs       地板除
    __imod__(self,rhs)        self %= rhs        取模(求余)
    __ipow__(self,rhs)        self **=rhs        幂运算

比较算术运算符的重载

    比较算术运算符的重载:
        方法名                  运算符和表达式      说明
    __lt__(self,rhs)          self < rhs          小于
    __le__(self,rhs)          self <= rhs         小于等于
    __gt__(self,rhs)         self > rhs           大于
    __ge__(self,rhs)         self >= rhs          大于等于
    __eq__(self,rhs)         self == rhs          等于
    __ne__(self,rhs)         self != rhs          不等于

位运算符重载

        方法名              运算符和表达式        说明
    __and__(self,rhs)        self & rhs             位与
    __or__(self,rhs)         self | rhs              位或
    __xor__(self,rhs)        self ^ rhs             位异或
    __lshift__(self,rhs)      self <<rhs             左移
    __rshift__(self,rhs)      self >>rhs             右移

反向位运算符重载

         方法名            运算符和表达式       说明
   __and__(self,lhs)       lhs & rhs               位与
   __or__(self,lhs)         lhs | rhs                位或
   __xor__(self,lhs)       lhs ^ rhs                 位异或
   __lshift__(self,lhs)    lhs <<rhs                左移
   __rshift__(self,lhs)    lhs >>rhs                右移

复合赋值位相关运算符重载

       方法名              运算符和表达式        		说明
   __iand__(self,rhs)       self & rhs              位与
   __ior__(self,rhs)         self | rhs             位或
   __ixor__(self,rhs)        self ^ rhs             位异或
   __ilshift__(self,rhs)     self <<rhs             左移
   __irshift__(self,rhs)     self >>rhs             右移

一元运算符的重载

     方法名           运算符和表达式            说明
__neg__(self)          - self                  负号
__pos__(self)          + self                  正号
__invert__(self)       ~ self                  取反

索引和切片运算符重载方法:

   方法名                  运算符和表达式              说明
 __getitem__(self,i)      x = self(i)              索引/切片取值
 __setitem__(self,i,v)    self[i] = v              索引/切片赋值
 __delitem__(self,i)      del self[i]              del语句删除索引/切片
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值