Python21期 day6 之面向对象
面向对象VS面向过程
面向过程的程序设计的核心是过程(流水线思维),过程即解决问题的步骤,面向过程就好比一条流水线,考虑周全什么时候处理什么东西
优点:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可
缺点是:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身
面向对象的程序设计的核心是对象(上帝式思维)
优点:解决程序的扩展性,对某一个对象单独修改,会立刻反映到整个体系中
缺点:可控性差
面向对象编程可以使程序的维护和扩展变得简单,并且可以提高程序开发效率
名词:类、对象、实例、实例化
类:具有相同特征的一类事物
对象/实例:具体的某一个事物
实例化:类---->对象的过程
初始类和对象
Python中一切皆为对象,类型的本质就是类。用变量表示特征,函数表示技能,因而具有相同特征和技能的一类事物就是类,对象则是这一类事物中具体的一个
#声明函数 def functionName(args): 函数体 #声明类 ''' class 类名: 类体 ''' #创建一个类 class Data: pass
class Person: #定义一个人类 role = 'person' #人的角色属性都是人 def walk(self): #人都可以走路,也就是有一个走路方法,也叫动态属性 print("person is walking...")
类的两种作用:属性引用和实例化
属性引用(类名.属性)
class Person: #定义一个人的类 role = 'person' #人的角色属性是人 def walk(self): #人可以走路,也就是有一个走路方法 print('person is walking...') print(Person.role) #查看人的role属性 print(Person.walk) #引用人的走路方法,注意这里不是调用
实例化:类名加括号就是实例化,会自动触发__init__函数的运行
class Person: role = 'person' def __init__(self,name): self.name = name #每一个角色都有自己的昵称 def walk(self): #人可以走路,也就是有一个走路方法 print('person is walking...') print(Person.role) print(Person.walk)
实例化的过程就是类---->对象的过程
原本只有一个Person类,在这个过程中,产生了一个egg对象,有自己的名字、攻击值和生命值
语法:对象名=类名(参数)
egg = Person('egon') #类名()就等于在执行Person.__init__() #执行完__init__()就会返回一个对象。这个对象类似一个字典,存着属于这个人本身的一些属性和方法
查看属性和调用方法 print(egg.name) #查看属性,对象名.属性名 print(egg.walk()) #调用方法,对象名.方法名()
关于self
self:在实例化时自动将对象/实例本身传给__init__的第一个参数,默认是用self
类属性的补充
一、定义类的属性存在哪了?两种方法查看 dir(类名):查出的是一个名字列表 类名.__dict__:查出的是一个字典,key为属性名,value为属性值 二、特殊的类属性 类名.__name__ #类的名字(字符串) 类名.__doc__ #类的文档字符串 类名.__base__# 类的第一个父类(在讲继承时会讲) 类名.__bases__# 类所有父类构成的元组(在讲继承时会讲) 类名.__dict__# 类的字典属性 类名.__module__# 类定义所在的模块 类名.__class__# 实例对应的类(仅新式类中)
回到咱们的人狗大战:现在我们需要对我们的类做出一点点改变
人类除了可以走路之外,还应该具备一些攻击技能。
class Person: role = 'person' def __init__(self,name,hp,dps): self.name = name #角色的昵称 self.hp = hp #角色的攻击力 self.dps = dps #角色的生命值 def attack(self,dog): dog.dps -= self.hp #人可以攻击狗,这里狗也是一个对象 #人攻击狗,那么狗的生命值就是根据人的攻击力而下降
对象是关于类而实际存在的一个例子,即实例
对象/实例只有一个作用:属性引用
egg = Person('egon',10,1000) print(egg.name) print(egg.hp) print(egg.dps) 当然也可以引用一个方法,因为方法也是一个属性,只不过是一个类似函数的属性,也叫动态属性。引用动态属性不是执行这个方法,更想调用方法和调用函数是一样的,都需要在后面加上括号
#面向对象小结 ---- 定义及调用的固定模式 class 类名: def __init__(self,参数1,参数2): self.对象的属性1 = 参数1 self.对象的属性2 = 参数2 def 方法名(self):pass def 方法名2(self):pass 对象名 = 类名(1,2) #对象就是实例,代表一个具体的东西 #类名():类名+括号就是实例化一个类,相当于调用了__init__方法 #括号里传参数,参数不需要传self,其他与init中的形参一一对应 #结果返回一个对象 对象.对象的属性1 #查看对象的属性,直接用 对象名.属性名 对象名.方法名() #调用类中方法,直接用对象名.方法名()
练习:在终端输出如下信息 小明,10岁,男,上山去砍柴 小明,10岁,男,开车去东北 小明,10岁,男,最爱大保健 老李,90岁,男,上山去砍柴 老李,90岁,男,开车去东北 老李,90岁,男,最爱大保健 class Person: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def action(self,hoby): self.hoby = hoby print('%s,%d,%s,%s'%(self.name,self.age,self.sex,self.hoby)) egon = Person('小明',10,'man') li = Person('老李',90,'man') egon.action('上山去砍柴') egon.action('开车去东北') egon.action('最爱大保健') li.action('上山去砍柴') li.action('开车去东北') li.action('最爱大保健')
对象间的交互
现在我们已经有一个人类了,通过给人类一些具体的属性我们就可以拿到一个实实在在的人。
现在我们要再创建一个狗类,狗就不能打人了,只能咬人,所以我们给狗一个bite方法。
有了狗类,我们还要实例化一只实实在在的狗出来。
然后人和狗就可以打架了。现在我们就来让他们打一架吧!
创建一个狗的类
class Dog: role = 'dog' def __init__(self,name,bread,hp,dps): self.name = name # 每一只狗都有自己的昵称; self.breed = breed # 每一只狗都有自己的品种; self.hp = hp # 每一只狗都有自己的攻击力; self.dps = dps ## 每一只狗都有自己的生命值; def bite(self,people): people.dps -= self.hp
ha2 = Dog('二愣子','哈士奇',10,1000) #创造了一只实实在在的狗ha2
交互 egon打ha2 print(ha2.dps) egg.attack(ha2) #egg打了ha2
完整的代码
class Person: def __init__(self,name,hp,dps,sex): self.name = name self.hp = hp self.dps = dps self.sex = sex self.bag = [] def attack(self,dog): dog.hp -= self.dps print('%s打了%s,%s掉了%s点血,剩余%s点血' %(self.name,dog.name,dog.name,self.dps,dog.hp)) class Dog: def __init__(self,name,kind,hp,dps): self.name = name self.kind = kind self.hp = hp self.dps = dps def bite(self,person): person.hp -= self.dps print('%s咬了%s,%s掉了%s点血,剩余%s点血' %(self.name,person.name,person.name,self.dps,person.hp)) alex = Person('alex',250,500,'man') ha2 = Dog('小哈','藏獒',15000,200) #掉用方式 -- 对象名.方法名 alex.attack(ha2) #相当于Person.attack(alex) ha2.bite(alex)
计算圆的面积和周长: from match import pi class Circle: def __init__(self,r): self.r = r def area(self): print( pi * self.r ** 2) def perimeter(self): print( 2 * self.r * pi) circle = Circle(5) #实例化一个圆 circle.area() #计算圆的面积 circle.perimeter() #计算圆的周长
类命名空间与对象、实例的命名空间
创建一个类就会创建一个类的命名空间,用来存储类中定义的所有名字,这些名字称为类的属性
类有两种属性:静态属性和动态属性
静态属性就是直接在类中定义的变量
动态属性就是定义在类中的方法
其中类的数据属性是共享给所有对象的
>>>id(egg.role) 4341594072 >>>id(Person.role) 4341594072
类的动态属性是绑定到所有对象的
>>>egg.attack <bound method Person.attack of <__main__.Person object at 0x101285860>> >>>Person.attack <function Person.attack at 0x10127abf8>
创建一个对象/实例就会创建一个对象/实例的名称空间,存放对象/实例的名字,称为对象/实例的属性
在obj.name会从obj自己的命名空间找name,找不到则去类中找,类找不到就找父类,最后找不到抛出异常
面向对象的组合用法
组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合
class Weapon: def prick(self,obj): # 这是该装备的主动技能,扎死对方 obj.life_value -= 500 # 假设攻击力是500 class person: def __init__(self,name): self.name = name self.weapon = Weapon() #给角色绑定一个武器 egg = Person('egon') egg.weapon.price() #egg组合了一个武器的对象,可以直接egg.weapon来使用组合类中的所有方法
面向对象的三大特性
继承
继承是一种创建新类的方式,在Python中,新建的类可以继承一个或多个父类,父类又可以成为基类或超类,新建的类称为派生类或子类

浙公网安备 33010602011771号