当前位置:首页>基础编程学习>Python>Python面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)
Python面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)
阅读 2
2024-10-03

面向对象编程(Object Oriented Programming-OOP)

面向对象编程(Object Oriented Programming-OOP) 是一种解决软件复用的设计和编程方法。 这种方法把软件 系统中相近相似的操作逻辑和操作 应用数据、状态,以类的型式描述出来,以对象实例的形式在软件系统中复用, 以达到提高软件开发效率的作用。

静态方法和类方法

1. 类方法

是类对象所拥有的方法,需要用修饰器 @classmethod 来标识其为类方法,对于类方法,第一个参数必须是类对象, 一般以 cls 作为第一个参数(当然可以用其他名称的变量作为其第一个参数,但是大部分人都习惯以'cls'作为第一 个参数的名字,就最好用'cls'了),能够通过实例对象和类对象去访问。
class People(object): 
    country = 'china'
#类方法,用classmethod来进行修饰 
    @classmethod
    def getCountry(cls):
        return cls.country
p =People()
#可以用过实例对象引用 print People.getCountry() #可以通过类对象引用
print(p.getCountry()) 
类方法还有一个用途就是可以对类属性进行修改:
class People(object): 
    country = 'china'
#类方法,用classmethod来进行修饰 
    @classmethod
    def getCountry(self):
        return self.country
    @classmethod
    def setCountry(self,country):
        self.country = country
p=People()

 #可以用过实例对象引用 print People.getCountry() #可以通过类对象引用
print(p.getCountry())
print(People.getCountry())
p.setCountry('USA')
print(p.getCountry()) 
china
china
USA
结果显示在用类方法对类属性修改之后,通过类对象和实例对象访问都发生了改变

2. 静态方法

需要通过修饰器 @staticmethod 来进行修饰,静态方法不需要多定义参数
class People(object):
country = 'china'
@staticmethod #静态方法
def getCountry():
return People.country
print(People.getCountry())
从类方法和实例方法以及静态方法的定义形式就可以看出来,类方法的第一个参数是类对象cls,那么通过cls引用 的必定是类对象的属性和方法;而实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有 可能是实例属性(这个需要具体分析),不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更 高。静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类对象来引用

应用英雄攻击故人

英雄类:

属性:

姓名
血量
持有的枪
方法:

安子弹
安弹夹
拿枪(持有抢)
开枪

子弹类

属性:
杀伤力

方法:

伤害敌人(让敌人掉血)

弹夹类

属性:
容量(子弹存储的最大值)
当前保存的子弹
方法:
保存子弹(安装子弹的时候)
弹出子弹(开枪的时候)

枪类

属性:
弹夹(默认没有弹夹,需要安装)
方法:
连接弹夹(保存弹夹)
射子弹

参考代码

#英雄类
#英雄
class Ren:
    def __init__(self,name): 
        self.name = name 
        self.xue = 100 
        self.qiang = None
    def __str__(self):
            return self.name   "剩余血量为:"   str(self.xue)
    
    def anzidan(self,danjia,zidan): 
         danjia.baocunzidan(zidan)
    def andanjia(self,qiang,danjia): 
         qiang.lianjiedanjia(danjia)
    def naqiang(self,qiang): 
         self.qiang = qiang
    def kaiqiang(self,diren): 
         self.qiang.she(diren)
    def diaoxue(self,shashangli): 
         self.xue -= shashangli
#弹夹类
class Danjia:
    def __init__(self, rongliang): 
        self.rongliang = rongliang 
        self.rongnaList = []
    def __str__(self):
        return "弹夹当前的子弹数量为:"   str(len(self.rongnaList))   "/"   str(self.rongliang)
    def baocunzidan(self,zidan):
        if len(self.rongnaList) < self.rongliang:
            self.rongnaList.append(zidan)
    def chuzidan(self): #判断当前弹夹中是否还有子弹
        if len(self.rongnaList) > 0:
        #获取最后压入到单间中的子弹 
            zidan = self.rongnaList[-1]
            self.rongnaList.pop() 
            return zidan
        else:
            return None
#子弹类 
class Zidan:
    def __init__(self,shashangli): 
         self.shashangli = shashangli
    def shanghai(self,diren): 
         diren.diaoxue(self.shashangli)
#枪类
class Qiang:
    def __init__(self): 
         self.danjia = None
    def __str__(self): 
         if self.danjia:
            return "枪当前有弹夹" 
         else:
            return "枪没有弹夹"
    def lianjiedanjia(self,danjia): 
        if not self.danjia:
            self.danjia = danjia
    def she(self,diren):
        zidan = self.danjia.chuzidan() 
        if zidan:
            zidan.shanghai(diren) 
        else:
            print("没有子弹了,放了空枪....")

#创建一个英雄对象
heroWang = Ren("王英雄")
#创建一个弹夹
danjia = Danjia(20) 
print(danjia)
#循环的方式创建一颗子弹,然后让老王把这颗子弹压入到弹夹中 
i=0
while i<5:
    zidan = Zidan(5) 
    heroWang.anzidan(danjia,zidan) 
    i =1
#测试一下,安装完子弹后,弹夹中的信息 
print(danjia)
#创建一个枪对象
qiang = Qiang()
print(qiang) #让老王,把弹夹连接到枪中 
heroWang.andanjia(qiang,danjia) 
print(qiang)
#创建一个敌人
diren = Ren("敌人") 
print(diren)
#让王拿起枪 
heroWang.naqiang(qiang)
#王开枪射敌人 
heroWang.kaiqiang(diren) 
print(diren) 
print(danjia)
结果:
弹夹当前的子弹数量为:0/20
弹夹当前的子弹数量为:5/20
枪没有弹夹
枪当前有弹夹
敌人剩余血量为:100
敌人剩余血量为:95
弹夹当前的子弹数量为:4/20

类和对象

面向对象编程的2个非常重要的概念:类和对象 对象是面向对象编程的核心,在使用对象的过程中,为了将具有共同特征和行为的一组对象抽象定义,提出了另外
一个新的概念——类 类就相当于制造飞机时的图纸,用它来进行创建的飞机就相当于对象

1.类

类是抽象的,在使用的时候通常会找到这个类的一个具体的存在,使用这个具体的存在。一个类可以找到多个对象

2. 对象

某一个具体事物的存在 ,在现实世界中可以是看得见摸得着的。 可以是直接使用的

3. 类和对象之间的关系

类就是创建对象的模板

4. 练习:区分类和对象

奔驰汽车 类
奔驰smart 类 张三的那辆奔驰smart 对象 狗类
大黄狗 类 李四家那只大黄狗 对象 水果 类
苹果 类
红苹果 类 红富士苹果 类 我嘴里吃了一半的苹果 对象

5. 类的构成

类(Class) 由3个部分构成
类的名称:类名
类的属性:一组数据
类的方法:允许对进行操作的方法 (行为)
1)人类设计,只关心3样东西:
事物名称(类名):
人(Person) 属性:身高(height)、年龄(age) 方法(行为/功能):跑(run)、打架(fight)
2)狗类的设计
类名:狗(Dog)
属性:品种 、毛色、性别、名字、 腿儿的数量 方法(行为/功能):叫 、跑、咬人、吃、摇尾巴

6. 类的抽象

如何把日常生活中的事物抽象成程序中的类? 拥有相同(或者类似)属性和行为的对象都可以抽像出一个类 方法:一般名词都是类(名词提炼法)

定义类

定义一个类,格式如下:
 class 类名: 
 方法列表
 
定义一个Car
# 定义类 
class Car:
# 方法
    def getCarInfo(self):
        print('车轮子个数:%d, 颜色%s'%(self.wheelNum, self.color))
    def move(self): 
        print("车正在移动...")
定义类时有2种:新式类和经典类,上面的Car为经典类,如果是Car(object)则为新式类
类名 的命名规则按照"大驼峰"

self

1. 理解self

 # 定义一个类 
class Animal:
# 方法
    def __init__(self, name):
        self.name = name 
    def printName(self):
        print('名字为:%s'%self.name)
# 定义一个函数
def myPrint(animal):
    animal.printName()
dog1 = Animal('西西') 
myPrint(dog1)
dog2 = Animal('北北') 
myPrint(dog2)
所谓的self,可以理解为自己
可以把self当做C 中类里面的this指针一样理解,就是对象自身的意思 某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面 的参数即可
保护对象的属性
如果有一个对象,当需要对其进行修改属性时,有2种方法
对象名.属性名 = 数据 ---->直接修改 对象名.方法名() ---->间接修改
为了更好的保存属性安全,即不能随意修改,一般的处理方式为
将属性定义为私有属性
添加一个可以调用的方法,供调用
class People(object):
    def __init__(self, name): 
        self.__name = name
    def getName(self): 
        return self.__name
    def setName(self, newName): 
        if len(newName) >= 5:
            self.__name = newName 
        else:
            print("error:名字长度需要大于或者等于5")
xiaoming = People("Bj") 
print(xiaoming.__name)
  print(xiaoming.__name)
AttributeError: 'People' object has no attribute '__name'
class People(object):
    def __init__(self, name): 
        self.__name = name
    def getName(self): 
        return self.__name
    def setName(self, newName): 
        if len(newName) >= 5:
                self.__name = newName 
        else:
            print("error:名字长度需要大于或者等于5") 
xiaoming = People("Solar")
xiaoming.setName("wanger") 
print(xiaoming.getName())
xiaoming.setName("lisi") 
print(xiaoming.getName())
Python中没有像Cpublicprivate这些关键字来区别公有属性和私有属性
它是以属性命名方式来区分,如果在属性名前面加了2个下划线'__',则表明该属性是私有属性,否则为公有属 性(方法也是一样,方法名前面加了2个下划线的话表示该方法是私有的,否则为公有的)。

"魔法"方法

1. 打印id()

2. 定义 __str__() 方法

class Car:
def __init__(self, newWheelNum, newColor):
self.wheelNum = newWheelNum
self.color = newColor
def __str__(self):
sg = "嘿。。。我的颜色是" self.color "我有" int(self.wheelNum) "个轮胎..."
return msg
def move(self):
print('车在跑,目标:夏威夷')
BMW = Car(4, "白色")
print(BMW)
python中方法名如果是 __xxxx__() 的,那么就有特殊的功能,因此叫做“魔法”方法
当使用print输出对象的时候,只要自己定义了 __str__(self) 方法,那么就会打印从在这个方法中return的数据

创建对象

定义了一个Car类;就好比有车一个张图纸,那么接下来就应该把图纸交给生成工人们去生成了 python中,可以根据已经定义的类去创建出一个个对象
创建对象的格式为:
 对象名 = 类名()
创建对象
# 定义类 
class Car:
# 移动
    def move(self):
        print('车在奔跑...')
# 鸣笛
    def toot(self):
        print("车在鸣笛...嘟嘟..")
# 创建一个对象,并用变量BMW来保存它的引用 
BMW = Car()
BMW.color = '黑色'
BMW.wheelNum = 4 #轮子数量
BMW.move() 
BMW.toot() 
print(BMW.color) 
print(BMW.wheelNum)
BMW = Car(),这样就产生了一个Car的实例对象,此时也可以通过实例对象BMW来访问属性或者方法
第一次使用BMW.color = '黑色'表示给BMW这个对象添加属性,如果后面再次出现BMW.color = xxx表示对属 性进行修改
BMW是一个对象,它拥有属性(数据)和方法(函数)
当创建一个对象时,就是用一个模子,来制造一个实物

__init__() 方法

 def 类名: 
#初始化函数,用来完成一些默认的设定 
     def __init__():
         pass
   

__init__() 方法的调用

 # 定义汽车类 
class Car:
    def __init__(self): 
        self.wheelNum = 4 
        self.color = '蓝色'
    def move(self): 
        print('车在跑,目标:夏威夷')
# 创建对象 
BMW = Car()
print('车的颜色为:%s'%BMW.color) 
print('车轮胎数量为:%d'%BMW.wheelNum)
self作为第一个形参外还需要2个形参,例如 __init__(self,x,y)
方法,在创建一个对象时默认被调用,不需要手动调用 中,默认有1个参数名字为self,如果在创建对象时传递了2个实参,那么 __init__(self) 中出了
__init__()
__init__(self)
__init__(self) 中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递进去

__del__() 方法

创建对象后,python解释器默认调用 __init__() 方法;
当删除一个对象时,python解释器也会默认调用一个方法,这个方法为 __del__() 方法
import time
class Animal(object):
# 初始化方法
# 创建完对象后会自动被调用 
    def __init__(self, name):
        print('__init__方法被调用') 
        self.__name = name
# 析构方法
# 当对象被删除时,会自动被调用 
    def __del__(self):
        print("__del__方法被调用") 
        print("%s对象马上被干掉了..."%self.__name)
# 创建对象
dog = Animal("哈皮狗")
# 删除对象 del dog
cat = Animal("波斯猫") 
cat2 = cat
cat3 = cat
print("---马上 删除cat对象") 
del cat
print("---马上 删除cat2对象") 
del cat2
print("---马上 删除cat3对象") 
del cat3
print("程序2秒钟后结束") 
time.sleep(2)
当有1个变量保存了对象的引用时,此对象的引用计数就会加1
当使用del删除变量指向的对象时,
如果对象的引用计数不会1,比如3,那么此时只会让这个引用计数减1,即 变为2,当再次调用del时,变为1,如果再调用1del,此时会真的把对象进行删除

继承介绍以及单继承

1. 继承的概念

在程序中,继承描述的是事物之间的所属关系,例如猫和狗都属于动物,程序中便可以描述为猫和狗继承自动物;
同理,波斯猫和巴厘猫都继承自猫,而沙皮狗和斑点狗都继承足够

2. 继承示例

 # 定义一个父类,如下: 
class Cat(object):
    def __init__(self, name, color="白色"): 
        self.name = name
        self.color = color
    def run(self): 
        print("%s--在跑"%self.name)
# 定义一个子类,继承Cat类如下: 
class Bosi(Cat):
    def setNewName(self, newName): 
        self.name = newName
    def eat(self): 
        print("%s--在吃"%self.name)
bs = Bosi("印度猫") 
print('bs的名字为:%s'%bs.name) 
print('bs的颜色为:%s'%bs.color) 
bs.eat()
bs.setNewName('波斯') 
bs.run()
虽然子类没有定义 __init__ 方法,但是父类有,所以在子类继承父类的时候这个方法就被继承了,所以只要创建Bosi的对象,就默认执行了那个继承过来的 __init__ 方法
子类在继承的时候,在定义类时,小括号()中为父类的名字
父类的属性、方法,会被继承给子类

3. 注意点

class Animal(object):
    def __init__(self, name='动物', color='白色'): 
        self.__name = name
        self.color = color
    def __test(self): 
        print(self.__name) 
        print(self.color)
    def test(self):
         print(self.__name) 
         print(self.color)
class Dog(Animal):
    def dogTest1(self):
        #print(self.__name) #不能访问到父类的私有属性 
        print(self.color)
    def dogTest2(self):
        #self.__test() #不能访问父类中的私有方法 
        self.test()
A = Animal()
#print(A.__name) #程序出现异常,不能访问私有属性 
print(A.color)
#A.__test() #程序出现异常,不能访问私有方法 
A.test()
print("------分割线-----")
D = Dog(name = "小花狗", color = "黄色") 
D.dogTest1()
D.dogTest2()
私有的属性,不能通过对象直接访问,但是可以通过方法访问
私有的方法,不能通过对象直接访问
私有的属性、方法,不会被子类继承,也不能被访问
一般情况下,私有的属性、方法都是不对外公布的,往往用来做内部的事情,起到安全的作用
上一篇: Python 模块module
评论 (0)