python----面向对象
一、面向过程和面向对象优缺点
面向过程:
优点:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。
缺点:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。
面向对象:
优点:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中。
缺点:可控性差,无法像面向过程的程序设计流水式的可以很精准的预测问题的处理流程与结果。
二、类的相关知识
在python中,用变量表示特征,用函数表示技能,因而具有相同特征和技能的一类事物就是‘类’,对象则是这一类事物中具体的一个。
类有两种作用:属性引用和实例化
属性引用(类名.属性)
class Person: #定义一个人类 role = 'person' #人的角色属性都是人 def walk(self): #人都可以走路,也就是有一个走路方法 print("person is walking...") print(Person.role) #查看人的role属性 print(Person.walk) #引用人的走路方法,注意,这里不是在调用
实例化:类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特征
class Person: #定义一个人类 eyes = 2 #人的眼睛属性都是2 def __init__(self, name): self.name = name # 每一个角色都有自己的昵称; def walk(self): #人都可以走路,也就是有一个走路方法 print("蹦蹦跳跳.") print(Person.eyes) #查看人的eyes属性 print(Person.walk) #引用人的走路方法,注意,这里不是在调用
实例化的过程就是: 类——> 对象的过程
p1 = Person('lucy') #类名()就等于在执行Person.__init__() #执行完__init__()就会返回一个对象。这个对象类似一个字典,存着属于这个人本身的一些属性和方法。 #你可以偷偷的理解:p1 = {'name':'lucy','walk':walk}
查看属性和调用方法
print(p1.name) #查看属性直接 对象名.属性名 print(p1.walk()) #调用方法,对象名.方法名()
self:在实例化时自动将对象/实例本身传给__init__的第一个参数,当然也可以给它起个别的名字。
类属性的补充
dir(类名):查出的是一个名字列表
类名.__dict__:查出的是一个字典,key为属性名,value为属性值
二:特殊的类属性
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类
类名.__bases__# 类所有父类构成的元组
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中)
对象是关于类而实际存在的一个例子,即实例
对象/实例只有一种作用:属性引用
面向对象——定义及调用的固定格式
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 #查看对象的属性,直接用 对象名.属性名 即可 对象名.方法名() #调用类中的方法,直接用 对象名.方法名() 即可
三、类命名空间与对象、实例的命名空间
创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性。
类有两种属性:静态属性和动态属性
静态属性就是直接在类中定义的变量
动态属性就是定义在类中的方法
类的数据属性是共享给所有对象的,而类的动态属性是绑定到所有对象的。
创建一个对象/实例就会创建一个对象/实例的名称空间,存放对象/实例的名字,称为对象/实例的属性
在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常
对象修改静态属性的值:
对于不可变数据类型来说,类变量最好用类名操作
对于可变数据类型来说,对象名的修改是共享的,重新赋值是独立的
四、面向对象的组合用法
组合:在一个类中以另一个类的对象作为数据属性,称为类的组合
class Dog: def __init__(self,*args): self.name = args[0] self.aggr = args[1] self.hp = args[2] self.kind = args[3] def bite(self,person): person.hp -= self.aggr class Person: def __init__(self,*args): self.name = args[0] self.aggr = args[1] self.hp = args[2] self.sex = args[3] self.money = 0 def attack(self,dog): dog.hp -= self.aggr def get_weapon(self,weapon): if self.money >= weapon.price: self.money -= weapon.price self.weapon = weapon self.aggr += weapon.aggr else: print('余额不足,请先充值') #武器类 class Weapon: def __init__(self,*args): self.name = args[0] self.aggr = args[1] self.njd = args[2] self.price = args[3] def hand18(self,person): if self.njd > 0: person.hp -= self.aggr * 2 self.njd -= 1 jim = Person('jim',0.5,100,'不详') bei = Dog('毒龙',100,500,'不详') w = Weapon('打狗棒',100,3,998) jim.money += 1000 jim.get_weapon(w) print(jim.aggr) jim.attack(bei) print(bei.hp) jim.weapon.hand18(bei) print(bei.hp)
首先实现一个圆形类,计算一个圆的周长和面积。然后在"环形类"中组合圆形的实例作为自己的属性来用
from math import pi class Circle: ''' 定义了一个圆形类; 提供计算面积(area)和周长(perimeter)的方法 ''' def __init__(self,r): self.r = r def area(self): return pi * self.r * self.r def perimeter(self): return 2 * pi *self.r # circle = Circle(10) #实例化一个圆 # area1 = circle.area() #计算圆面积 # per1 = circle.perimeter() #计算圆周长 # print(area1,per1) #打印圆面积和周长 class Ring: ''' 定义了一个圆环类 提供圆环的面积和周长的方法 ''' def __init__(self,r_outside,r_inside): self.outside_c = Circle(r_outside) self.inside_c = Circle(r_inside) def area(self): return self.outside_c.area() - self.inside_c.area() def perimeter(self): return self.outside_c.perimeter() + self.inside_c.perimeter() ring = Ring(10,5) #实例化一个环形 print(ring.perimeter()) #计算环形的周长 print(ring.area()) #计算环形的面积