Python之面向对象一
引子
小游戏:人狗大战
角色:人和狗
角色属性:姓名,血量,战斗力和性别(种类)
技能:打/咬
用函数实现人打狗和狗咬人的情形
def Dog(name,blood,aggr,kind):
dog = {
'name':name,
'blood':blood,
'aggr':aggr,
'kind':kind
}
def bite(person):
person['blood'] -= dog['aggr']
print('%s被咬了,掉了%s的血'%(person['name'],dog['aggr']))
dog['bite'] = bite
return dog
def Person(name,blood,aggr,sex):
person = {
'name':name,
'blood':blood,
'aggr':aggr,
'sex':sex
}
def attack(dog):
dog['blood'] -= person['aggr']
print('%s被打了,掉了%s的血'%(dog['name'],person['aggr']))
person['attack'] = attack
return person
person = Person('武大',100,5,'nan')
dog = Dog('大黄',100,2,'jin')
dog['bite'](person)
person['attack'](dog)
print(person)
print(dog)
>>>
武大被咬了,掉了2的血
大黄被打了,掉了5的血
{'name': '武大', 'blood': 98, 'aggr': 5, 'sex': 'nan', 'attack': <function Person.<locals>.attack at 0x000002729A1CFB70>}
{'name': '大黄', 'blood': 95, 'aggr': 2, 'kind': 'jin', 'bite': <function Dog.<locals>.bite at 0x000002729A1CFBF8>}
这个简单的例子使用的编程思想就是简单的面向对象编程,
面向过程 VS 面向对象
面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。
优点是:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。
缺点是:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。
应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。
面向对象的程序设计的核心是对象(上帝式思维),要理解对象为何物,必须把自己当成上帝,上帝眼里世间存在的万物皆为对象,不存在的也可以创造出来。面向对象的程序设计好比如来设计西游记,如来要解决的问题是把经书传给东土大唐,如来想了想解决这个问题需要四个人:唐僧,沙和尚,猪八戒,孙悟空,每个人都有各自的特征和技能(这就是对象的概念,特征和技能分别对应对象的属性和方法),然而这并不好玩,于是如来又安排了一群妖魔鬼怪,为了防止师徒四人在取经路上被搞死,又安排了一群神仙保驾护航,这些都是对象。然后取经开始,师徒四人与妖魔鬼怪神仙互相缠斗着直到最后取得真经。如来根本不会管师徒四人按照什么流程去取。
面向对象的程序设计的
优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现,一刀砍死3个人,这个游戏就失去平衡。
应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。
在python 中面向对象的程序设计并不是全部。
面向对象编程可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
相关名词:类、对象、实例、实例化
类:具有相同特征的一类事物(人、狗、老虎)
对象/实例:具体的某一个事物(隔壁阿花、楼下旺财)
实例化:类——>对象的过程
初识类和对象
python中一切皆为对象,类型的本质就是类。在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) #查看人的role属性
print(Person.walk) #引用人的走路方法,注意,这里不是在调用
实例化的过程就是类——>对象的过程
原本我们只有一个Person类,在这个过程中,产生了一个武大对象,有自己具体的名字、攻击力和生命值。
语法:对象名 = 类名(参数)
武大 = Person('武大') #类名()就等于在执行Person.__init__()
#执行完__init__()就会返回一个对象。这个对象类似一个字典,存着属于这个人本身的一些属性和方法。
#你可以偷偷的理解:武大 = {'name':'武大','walk':walk}
查看属性和调用方法:
print(武大.name) #查看属性直接 对象名.属性名
print(武大.walk()) #调用方法,对象名.方法名()
关于self:
self:在实例化时自动将对象/实例本身传给__init__的第一个参数,可以是其他名字,但默认都是这个,要不然其他人会不认识的。
类属性的补充:
一:我们定义的类的属性到底存到哪里了?有两种方式查看
dir(类名):查出的是一个名字列表
类名.__dict__:查出的是一个字典,key为属性名,value为属性值 二:特殊的类属性
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类(继承相关知识)
类名.__bases__# 类所有父类构成的元组(继承相关知识)
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中) 类属性的补充
对象
对象是关于类而实际存在的一个例子,即实例。
对象/实例只有一种作用:属性引用
理解面向对象:
def Person(*args,**kwargs):
self = {}
def attack(self,dog):
dog['life_value'] -= self['aggressivity'] def __init__(name,aggressivity,life_value):
self['name'] = name
self['aggressivity'] = aggressivity
self['life_value'] = life_value
self['attack'] = attack __init__(*args,**kwargs)
return self egg = Person('武大',78,10)
print(武大['name']) 帮你了解面向对象
面向对象小结——定义及调用的固定模式
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 shangshan(self):
print('%s,%s岁,%s,上山去砍柴'%(self.name,self.age,self.sex)) def drive(self):
print('%s,%s岁,%s,开车去东北' % (self.name,self.age,self.sex)) def favor(self):
print('%s,%s岁,%s,最爱大保健' % (self.name,self.age,self.sex)) 小明 = Person('小明',10,'男')
小明.shangshan()
小明.drive()
小明.favor()
老李 = Person('老李',90,'男')
老李.shangshan()
老李.drive()
老李.favor()
计算已知半径圆的周长和面积
from math import pi
class Circular:
def __init__(self,r):
self.r = r
def perimeter(self):
return self.r*2*pi
def acreage(self):
return self.r**2*pi
c1 = Circular(4)
print(c1.perimeter())
print(c1.acreage())
计算正方形的周长和面积
class Square:
def __init__(self,l):
self.l = l
def perimeter(self):
return 4*self.l
def acreage(self):
return self.l**2
square = Square(5)
print(square.perimeter())
print(square.acreage())
对象之间的交互
人狗大战:
import time
class Person:
def __init__(self,name,age,sex,country,hp,aggr):
self.name = name
self.age = age
self.sex = sex
self.country = country
self.hp = hp
self.aggr = aggr
def Hit(self,dog):
dog.hp -= self.aggr
if dog.hp <= 0 :
print('%s打了%s,造成%s点伤害,已扑街。。。'%(self.name,dog.name,self.aggr))
else:
print('%s打了%s,造成%s点伤害,剩余%s点生命值'%(self.name,dog.name,self.aggr,dog.hp))
class Dog:
def __init__(self,name,hp,aggr,kind):
self.name = name
self.hp = hp
self.aggr = aggr
self.kind = kind
def bite(self,person):
person.hp -= self.aggr
if person.hp <= 0:
print('%s咬了%s,造成%s点伤害,已扑街。。。'%(self.name,person.name,self.aggr))
else:
print('%s咬了%s,造成%s点伤害,剩余%s点生命值'%(self.name,person.name,self.aggr,person.hp))
小明 = Person('小明',18,'男','中国',1000,50)
啸天犬 = Dog('啸天',600,80,'teddy')
print('>>>>>欢迎来到人狗大战世界<<<<<')
while 1:
choice = input('》》》')
if choice.upper() == 'Q':
break
elif choice.upper() == 'W' :
小明.Hit(啸天犬)
elif choice.upper() == 'E':
啸天犬.bite(小明)
time.sleep(1)
人狗大战
类命名空间与对象、实例的命名空间
创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性。
而类有两种属性:静态属性和动态属性
- 静态属性就是直接在类中定义的变量
- 动态属性就是定义在类中的方法
其中类的数据属性是共享给所有对象的
而类的动态属性是绑定到所有对象的
创建一个对象/实例就会创建一个对象/实例的名称空间,存放对象/实例的名字,称为对象/实例的属性
只能在对象或实例中的名称空间里找动态属性,找不到就到类中的名称空间里找,找不到就报错,不会在类外面找。
面向对象的组合用法
组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合
例子:人狗大战
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
self.aggr += weapon.aggr
else:
print("余额不足,请先充值") class Weapon:
def __init__(self,name,aggr,njd,price):
self.name = name
self.aggr = aggr
self.njd = njd
self.price = price def hand18(self,person):
if self.njd > 0:
person.hp -= self.aggr * 2
self.njd -= 1 武大 = Person('武大',20,300,'不详')
哮天犬 = Dog('哮天犬',100,500,'teddy')
w = Weapon('打狗棒',100,3,998)
# alex装备打狗棒
武大.money += 1000
武大.get_weapon(w)
print(武大.weapon)
print(武大.aggr)
武大.attack(哮天犬)
print(哮天犬.hp)
武大.weapon.hand18(哮天犬)
print(哮天犬.hp)
组合的例子--人狗大战
圆环是由两个圆组成的,圆环的面积是外面圆的面积减去内部圆的面积。圆环的周长是内部圆的周长加上外部圆的周长。
这个时候,我们就首先实现一个圆形类,计算一个圆的周长和面积。然后在"环形类"中组合圆形的实例作为自己的属性来用
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()
r = Ring(5,2)
print(r.area()) class Teacher:
def __init__(self,name,birthday):
self.name = name
self.birth = birthday
class Birthday:
def __init__(self,day):
self.day = day
b = Birthday(123456789)
t = Teacher('',b)
print(t.birth.day)
计算圆环的周长和面积
用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python课程
class BirthDate:
def __init__(self,year,month,day):
self.year=year
self.month=month
self.day=day class Couse:
def __init__(self,name,price,period):
self.name=name
self.price=price
self.period=period class Teacher:
def __init__(self,name,gender,birth,course):
self.name=name
self.gender=gender
self.birth=birth
self.course=course
def teach(self):
print('teaching') p1=Teacher('egon','male',
BirthDate('','',''),
Couse('python','','4 months')
) print(p1.birth.year,p1.birth.month,p1.birth.day) print(p1.course.name,p1.course.price,p1.course.period)
'''
运行结果:
27
python 28000 4 months
'''
教授的生日和教授课程
当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好
Python之面向对象一的更多相关文章
- python基础——面向对象编程
python基础——面向对象编程 面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的 ...
- Python的面向对象3
接下来,我们接着讲Python的面向对象,在上一次的博客中,我们详细介绍了类与对象的属性,今天,我们来详细介绍一下面向对象中的方法! 1.定义实例方法 一个实例的私有属性就是以__开头的属性,无法被外 ...
- Python的面向对象2
我们接着讲解Python的面向对象 1.初始化实例属性 在现实生活中,一种类型的实例会具有相同的某些属性,把这些实例划分为一个类型,则这些实例必然有相似的部分.但是,在创建实例之后,我们一个一个的为实 ...
- Python的面向对象1
今天,我们来介绍Python的面向对象编程,其实面向对象并不陌生,在C++ ,Java ,PHP中也有大量使用! 好了,我们来步入正题! 那什么是面向对象编程呢? 1. 面向对象编程是一种程序设计 ...
- My way to Python - Day05 - 面向对象-思维导图
My way to Python - Day05 - 面向对象 思维导图
- Python进阶---面向对象的程序设计思想
Python的面向对象 一.面向过程与面向对象的对比 面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优 ...
- python基础——面向对象进阶下
python基础--面向对象进阶下 1 __setitem__,__getitem,__delitem__ 把对象操作属性模拟成字典的格式 想对比__getattr__(), __setattr__( ...
- python基础——面向对象进阶
python基础--面向对象进阶 1.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 ...
- python基础——面向对象的程序设计
python基础--面向对象的程序设计 1 什么是面向对象的程序设计 面向过程的程序设计的核心是过程,过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优 ...
随机推荐
- 设计模式——观察者模式(C++实现)
#include <iostream> #include <vector> #include <algorithm> #include <iterator&g ...
- opencv3.4+vs2015+win10安装过程问题解决
在使用cmake configure生成vs的工程文件时,有几个第三方的库和文件会频繁下载不成功,分别是: ffmpeg_version.cmake opencv_ffmpeg.dll opencv_ ...
- 基于Cesium三维地图项目记录_通视分析功能的实现
实现了剖面分析功能之后,下面来看看如何实现通视分析,还是基本按照之前的思路实现: 了解软件LocaScape是怎么实现的: 网址如下:http://www.locaspace.cn/V3.0/help ...
- mysql与emoji和特殊字符
从微信登陆已经是非常普遍的登陆方式了,在数据库设计时也应该考虑相关性.一般存储open_id.图标.昵称就够了.其中昵称要特殊注意,否则可能就像这样: mysql : 1366 Incorrect s ...
- AVL树(Java实现)
AVL树基本介绍 AVL树是一种自平衡的二叉查找树,在AVL树中任何节点的两个子树的高度差不能超过1.就是相当于在二叉搜索树的基础上,在插入和删除时进行了平衡处理. 不平衡的四种情况 LL:结构介绍 ...
- 在Node应用中避免“Dot Hell”
转载自:http://blog.leapoahead.com/2015/09/03/prevent-node-require-dot-hell/ 在Node应用中,我们使用require来加载模块.在 ...
- linux 的tee命令
tee 如果你在linux下希望将程序或命令运行的信息,在输入到文件的同时,也能够显示在屏幕上,你可以考虑使用tee这个命令.举个例子,直接上图 这里我调用函数aaa来完成将结果输入到aaa.log里 ...
- mysql多实例运行
1.主配置文件 [mysqld_multi] mysqld = /usr/local/mysql/bin/mysqld_safe mysqladmin = /usr/local/mysql/bin/m ...
- 用python程序来画花
from turtle import * import time setup(600,800,0,0) speed(0) penup() seth(90) fd(340) seth(0) pendow ...
- Beta冲刺NO.6
Beta冲刺 第六天 1. 昨天的困难 1.对于设计模式的应用不熟悉,所以在应用上出现了很大的困难. 2.SSH中数据库的管理是用HQL语句实现的,所以在多表查询时出现了很大的问题. 3.页面结构太凌 ...