一、面向过程:面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。
优点:极大地降低了写成学的复杂度,只需要顺着执行的步骤,堆叠代码即可
缺点:一套流水线或者流程就是用来解决一个问题,如果修改代码就都得改变
二、面向对象:上帝的思想
优点:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现,一刀砍死3个人,这个游戏就失去平衡。
三、类:是具有相同特征的一类事物(人,狗,老虎)
对象/实例:具体的某一事物
实例化:类到对象的过程(实例=类名(参数1,参数2))
四、初始类和对象
类的定义:class Person: #class 类名:注意类名后面不要括号
类体
在python中,用变量表示特征,用函数表示技能,因而具有相同的特征和技能的一类事物就是‘类’,
对象则是这一类事物中具体的一个
类的两种作用:属性引用和实例化
1、属性引用
1 class Person: 2 role = '中国人' #类属性----静态属性 3 def walk(self): #这里的函数叫做方法-----动态属性 4 #注意:self必须写 5 print('person is walking ...') 6 print(Person.role) #查看类属性 7 print(Person.walk) #查看类方法 , 用类名去调用方法名,打印出来的是内存地址
2、实例化
类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特征
1 class Person: 2 role = '中国人' #这里人的角色属性都是中国人 3 def __init__(self,name,sex): 4 self.name=name #每个角色都有自己的昵称和性别 5 self.sex=sex 6 def walk(self): #人可以走路,也就是一个走路方法 7 print('person is walking') 8 9 hy = Person('haiyan',21) #实例化:类名(参数1,参数2) 10 print(hy.name) #直接查看对象属性 对象名.属性名 11 print(hy) #返回的是一个对象 12 hy.walk() #调用方法 ,对象名.方法()
对象的两种作用:查看属性和调用方法(上面的实例化中讲到)
补充:
# 包 —— __init__ # 为什么只要import time就能使用time下面的方法了? #我们在导入一个包(time)的时候就相当于实例化了一个对象,实例化对象这个名字的时候就要执行一个init文件做初始化 import time #类的实例化的过程,然后就能使用类下面的各种方法了 time.time()
五、关于self
self:在实例化时自动将对象/实例本身传给__init__的第一个参数,你也可以给它起个别的名字,但是一般正常人都不会这么做,因为你改了别人就不认识了。
注意:def __init__(self): 这句话可以写也可以不写,只要有参数参进来的时候就必须得写
def 方法名(self):这里的self必须得写
六、特殊的类属性
一:我们定义的类的属性到底存到哪里了?有两种方式查看 dir(类名):查出的是一个名字列表 类名.__dict__:查出的是一个字典,key为属性名,value为属性值 二:特殊的类属性 类名.__name__# 类的名字(字符串) 类名.__doc__# 类的文档字符串 类名.__base__# 类的第一个父类(在讲继承时会讲) 类名.__bases__# 类所有父类构成的元组(在讲继承时会讲) 类名.__dict__# 类的字典属性 类名.__module__# 类定义所在的模块 类名.__class__# 实例对应的类(仅新式类中)
七、对象的相关知识
1.对象是关于类而实际存在的一个例子,即实例
2.对象/实例只有一种作用:属性引用
egg = Person('egon',10,1000) print(egg.name) print(egg.aggressivity) print(egg.life_value)<br>当然,你也可以引用一个方法,因为方法也是一个属性。
八、面向对象小结
定义及调用的固定格式
1 class 类名: 2 def __init__(self,参数1,参数2): 3 self.对象的属性1 = 参数1 4 self.对象的属性2 = 参数2 5 6 def 方法名(self):pass 7 8 def 方法名2(self):pass 9 10 对象名 = 类名(1,2) #对象就是实例,代表一个具体的东西 11 #类名() : 类名+括号就是实例化一个类,相当于调用了__init__方法 12 #括号里传参数,参数不需要传self,其他与init中的形参一一对应 13 #结果返回一个对象 14 对象名.对象的属性1 #查看对象的属性,直接用 对象名.属性名 即可 15 对象名.方法名() #调用类中的方法,直接用 对象名.方法名() 即可
九、对象之间的交互
class Person: def __init__(self,name,aggr,life_value): self.name=name self.aggr=aggr self.life_value=life_value def attack(self,dog): #人可以攻击狗 dog.life_value=dog.life_value-self.aggr class Dog: def __init__(self,name,aggr,life_value): self.name = name self.aggr = aggr self.life_value = life_value def attack(self,egg): #狗也可以攻击人 egg.life_value = egg.life_value - self.aggr egg = Person('egon',250,1000) dog = Dog('乐乐',50,2000) print('狗没攻击前egon的生命值:',dog.life_value) #没攻击前egon的生命值 egg.attack(dog) #让egon去攻击狗乐乐 print('狗攻击后egon的生命值:',dog.life_value) #攻击后egon的生命值 print('egon没攻击前狗的生命值:',egg.life_value) #没攻击前egon的生命值 dog.attack(egg) #让狗去攻击egon print('egon攻击后狗的生命值:',egg.life_value) #攻击后egon的生命值
十、类命名空间与对象,实例的命名空间
创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字成为类的属性
而类有两种属性:静态属性和动态属性
- 静态属性就是直接在类中定义的变量
- 动态属性就是定义在类中的方法
# 对于不可变数据类型来说,类变量最好用类名操作 class Course: language = 'Chinese' #不可变数据类型 def __init__(self,teacher,course_name,period,price): self.teacher = teacher self.name = course_name self.period = period self.price = price def func(self): pass python = Course('egon','python','6 months',20000) linux = Course('oldboy','linux','6 months',20000) python.language='English' #并不能修改类中的属性,只是为Python对象添加新的属性,它存放在python自己的空间里 #以后python对象再调language属性时只能调自己内容空间里的,不能再调类中的language了 print(python.language) #English print(python.__dict__) #{'teacher': 'egon', 'name': 'python', 'period': '6 months', 'price': 20000, 'language': 'English'} print(linux.language) #Chinese print(linux.__dict__) #{'teacher': 'oldboy', 'name': 'linux', 'period': '6 months', 'price': 20000} print(Course.language) #Chinese
#类变量名用类操作
Course.language='English'
# 对于可变数据类型来说,对象名的修改是共享的,重新赋值是独立的 class Course: language = ['Chinese'] #可变数据类型 def __init__(self,teacher,course_name,period,price): self.teacher = teacher self.name = course_name self.period = period self.price = price def func(self): pass python = Course('egon','python','6 months',20000) linux = Course('oldboy','linux','6 months',20000) # 对象名的修改是共享的 python.language[0]='English' #['English']用下表的方式修改了类中的language:当加了一个[]后说明python空间里面首先得有一个language, # 但它自己里面没有一个language[],然后往类的内存空间里面找,找到后修改列表中的第一个元素 print(python.language) #['English'] print(python.__dict__) #{'teacher': 'egon', 'name': 'python', 'period': '6 months', 'price': 20000} print(linux.language) #['English'] print(linux.__dict__) #{'teacher': 'egon', 'name': 'python', 'period': '6 months', 'price': 20000} print(Course.language) #['English'] #重新赋值是独立的 # python.language=['language'] #这个表示在python内存空间里创建一个新属性,不影响类中的language
十一、绑定方法
当一个对象名去调用一个类中的方法时,这个方法就和这个对象绑定在一起了
class Foo: def func(self): print('func') def fun1(self): pass f1 = Foo() print(f1) #<__main__.Foo object at 0x0000021618958860> print(Foo.func) #<function Foo.func at 0x0000021618AF6620> print(f1.func) #<bound method Foo.func of <__main__.Foo object at 0x0000021618958860>> #把对象f1绑定给Foo类下面的方法func,绑定之后func方法能调用对象f1中的所有数据了 #就相当于把f1当做self传进fun方法中了 print(f1.fun1) #<bound method Foo.fun1 of <__main__.Foo object at 0x0000021618958860>>
十二、面向对象的组合用法(*****)
组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合
用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如人有生日
# 面向对象的三大特性 : 继承 多态 封装 # 组合 # 人狗大战 class Dog: def __init__(self,name,aggr,hp,kind): self.name = name self.aggr = aggr self.hp = hp self.kind = kind def bite(self,person): person.hp -= self.aggr class Person: def __init__(self,name,aggr,hp,sex): self.name = name self.aggr = aggr self.hp = hp self.sex = sex 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 #添加武器属性 #alex.weapon=w self.aggr += weapon.aggr #修改攻击力 else: print("余额不足,请先充值") class Weapon: def __init__(self,name,aggr,njd,price): self.name = name self.aggr = aggr self.njd = njd # njd:耐久度 self.price = price def hand18(self,person): #为武器设计招数 if self.njd > 0: person.hp -= self.aggr * 2 self.njd -= 1 #放一个大招耐久度减一 alex = Person('alex',0.5,100,'不详') jin = Dog('金老板',100,500,'teddy') w = Weapon('打狗棒',100,3,998) # alex装备打狗棒 alex.money += 1000 #先充钱 alex.get_weapon(w) print(alex.weapon) #<__main__.Weapon object at 0x0000022701B62B70> print(alex.aggr) #100.5 alex.attack(jin) print(jin.hp) #399.5 alex.weapon.hand18(jin) #alex使用武器放大招对付jin print(jin.hp) #199.5 # 组合 :一个对象(alex)的属性(weapon)值(w)是另外一个类(Weapon)的对象
class A: def __init__(self): self.name = 'egon' class B: def __init__(self,year,month,day): self.year = year self.month = month self.day = day b = B(18,1,17) a = A() a.birth = b #组合 print(b.year)
组合的应用1:计算圆环的面积和周长
from math import pi # 圆形类 class Circle: def __init__(self,r): self.r = r def area(self): return self.r**2 * pi def perimeter(self): return 2*pi*self.r # 圆形类 class Ring: def __init__(self,outside_r,inside_r): self.outside_c = Circle(outside_r) #组合:一个对象的属性值是另外一个类的对象 self.inside_c = Circle(inside_r) #组合 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(20,10) #实例化一个环形 print(ring.area())#计算环形的面积 print(ring.perimeter())#计算环形的周长
组合应用2:
from math import pi # 圆形类 class Circle: def __init__(self,r): self.r = r def area(self): return self.r**2 * pi def perimeter(self): return 2*pi*self.r # 圆形类 class Ring: def __init__(self,outside_r,inside_r): self.outside_c = Circle(outside_r) #组合:一个对象的属性值是另外一个类的对象 self.inside_c = Circle(inside_r) #组合 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(20,10) #实例化一个环形 # print(ring.area())#计算环形的面积 # print(ring.perimeter())#计算环形的周长 # 创建一个老师类 # 老师有生日 # 生日也可以是一个类 # 组合 class Birthday: def __init__(self,year,month,day): self.year = year self.month = month self.day = day class Course: def __init__(self,course_name,period,price): self.name = course_name self.period = period self.price = price class Teacher: def __init__(self,name,age,sex,birthday): self.name = name self.age = age self.sex = sex self.birthday =birthday self.course = Course('python','6 month',2000) #组合 b = Birthday(2018,1,16) egg = Teacher('egon',20,'女',b) #组合 print(egg.name) print(egg.birthday.year) print(egg.birthday.month) print(egg.course.price)
类操作示例:
class Person: # 类名 country = 'China' # 创造了一个只要是这个类就一定有的属性 静态属性 def __init__(self,name,blood,aggr,sex): # 初始化方法,self是对象,是一个必须传的参数 # self可以理解为一个可以存储很多属性的大字典,只是往字典里添加属性的方式发生了一些变化(用.的方式) self.name = name #等号左边的name是我们自定义的名字,相当于字典中的key,也可以用其它名字
#等号右边是传进来的参数值,相当于字典中的value
self.hp = blood self.aggr = aggr self.sex = sex def walk(self,n): # 类中的方法,一般情况下必须传self参数,且必须写在第一个 # 后面还可以传其他参数,是自由的 print('%s走走走,走了%s步'%(self.name,n)) # print(Person.country) # 类名可以查看类中的属性,不需要实例化就可以查看 China alex = Person('狗剩儿',100,1,'男') # 类名还可以实例化对象,alex对象 #实例化,此时alex就相当于Person中的self print(alex.__dict__) # 查看所有属性 {'name': '狗剩儿', 'hp': 100, 'aggr': 1, 'sex': '男'} print(alex.name) # 查看属性值 #狗剩儿 Person.walk(alex,5) #可简写成下面的方式,而且以后我们都用下面的简写方式调用类中的方法 alex.walk(5) # 调用方法 类名.方法名(对象名) #对于类的字典,只能看不能改 print(Person.__dict__) #{'__module__': '__main__', 'country': 'China', '__init__': <function Person.__init__ at 0x000001CB59AD6048>, # 'walk': <function Person.walk at 0x000001CB59AD6620>, '__dict__': <attribute '__dict__' of 'Person' objects>, # '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None} print(Person.__dict__['country']) #查看类的属性 #Chine # Person.__dict__['country'] = '中国' #这种写法是错误的,不能通过字典的方式修改类中属性值但可以通过以下方式修改
#Person.country='中国'
# 可以通过操作字典的方式查看或者修改对象的属性 print(alex.__dict__) #{'name': '狗剩儿', 'hp': 100, 'aggr': 1, 'sex': '男'} print(alex.name) #狗剩儿 # print(alex.__dict__['name']) #也通过字典的方式查看对象属性 #狗剩儿 alex.name = '二哥' #修改对象属性 # alex.__dict__['name'] = '二哥' #也可以通过字典的方式修改对象属性 print(alex.__dict__) #{'name': '二哥', 'hp': 100, 'aggr': 1, 'sex': '男'} print(alex.name) #二哥 alex.age = 18 #为对象添加新属性 print(alex.__dict__) #{'name': '二哥', 'hp': 100, 'aggr': 1, 'sex': '男', 'age': 18} #总结 # 对象 = 类名() # 过程: # 类名() 首先 会创造出一个对象,创建了一个self变量 # 调用init方法,类名括号里的参数会被这里接收 # 执行init方法 # 返回self,实例化对象就相当于这个返回的self # 对象能做的事: # 查看属性 # 调用方法 # __dict__ 对于对象的增删改查操作都可以通过字典的语法进行 # 类名能做的事: # 实例化 # 调用方法 : 只不过要自己传递self参数 # 调用类中的属性,也就是调用静态属性 # __dict__ 对于类中的名字只能看 不能操作