首先,通过之前学习的函数编写一个 人狗大战 的例子。

分析下这个需求,人 狗 大战  三个事情。
角色:人、狗
动作:狗咬人,人打狗

先创建人和狗两个角色:

def person(name, hp, aggr, sex):
data = {
'name': name,
'hp': hp,
'aggr': aggr,
'sex': sex
} return data def dog(name, hp, aggr, dog_type):
data = {
'name': name,
'hp': hp,
'aggr': aggr,
'dog_type': dog_type
} return data kk = person('kk', 100, 5, 'male') # 人的角色
gg = dog('gg', 100, 10, 'teddy') # 狗的角色

人和狗两个角色

人创建完成,但是我们还有两个动作才能开始游戏,于是使用函数在写两个动作:

def person(name, hp, aggr, sex):
data = {
'name': name,
'hp': hp,
'aggr': aggr,
'sex': sex
} return data def dog(name, hp, aggr, dog_type):
data = {
'name': name,
'hp': hp,
'aggr': aggr,
'dog_type': dog_type
} return data kk = person('人', 100, 5, 'male')
gg = dog('狗狗', 100, 10, 'teddy') def bite(g, p):
p['hp'] -= g['aggr']
print('%s 被咬,掉了%s 的血。' %(p['name'], g['aggr'])) bite(gg, kk) def hit(p, g):
g['hp'] -= p['aggr']
print('%s 被打,掉了%s 的血。' %(g['name'], p['aggr'])) hit(kk, gg)

两个动作

上面的代码已经实现了我们最初设计的人狗大战,但是每个函数都是相互独立的,没有任何限制。也就是说,可以出现以下这种情况:

hit(gg, kk)
bite(kk, gg) 执行结果: 人 被打,掉了10 的血。
狗狗 被咬,掉了5 的血。

这样,人和狗正好相反了,应该是人打狗,狗咬人才对。因此必须要加上限制:

def person(name, hp, aggr, sex):
data = {
'name': name,
'hp': hp,
'aggr': aggr,
'sex': sex
} def hit(g):
g['hp'] -= data['aggr']
print('%s 被打,掉了%s 的血。' % (g['name'], data['aggr'])) data['hit'] = hit
return data def dog(name, hp, aggr, dog_type):
data = {
'name': name,
'hp': hp,
'aggr': aggr,
'dog_type': dog_type
} def bite(p):
p['hp'] -= data['aggr']
print('%s 被咬,掉了%s 的血。' % (p['name'], data['aggr'])) data['bite'] = bite
return data kk = person('人', 100, 5, 'male')
gg = dog('狗狗', 100, 10, 'teddy') kk['hit'](gg)
gg['bite'](kk)

为角色的动作加上限制

这样,我们在代码层面就实现了限制,代码基本完美了。

回看我们上面的代码,创建的是角色函数,也就是通过角色函数,我们可以创建无数的人和狗大战。

人是人类、狗是狗类 通过这样的思想来进行编程就是面向对象的编程思想。从角色和大类入手,上帝视角

比如:
人类,是一个大类,这个大类里面有各种各样的属性,比如吃饭,睡觉,打豆豆这都是共性。
类中还有方法,方法就是一个过程,一个动作,做某件事。
比如:爬山、打篮球。这些都是动作,都应该是一个方法出现;

面向过程与面向对象

面向过程的程序设计核心是过程。过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线。

优点:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可;
缺点:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。

应用场景:一般 bash 脚本都是面向过程思想写出来的,处理流程化事件。

面向对象的程序设计

面向对象的程序设计的核心是对象。

优点:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
缺点:可控性差,无法像面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间交互解决问题。

应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的地方;

在python中面向对象的程序设计并不是全部。

面向对象编程可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率,基于面向对象的程序可以使它人更加容易理解你的代码逻辑。
虽然 面向对象很好用,但是它并没有比面向过程高级,对于不同的应用需求场景采用合适的编程思想才是最重要的。

def functionName(args):
函数体

申明函数

class Data:
pass

申明类

类有两种作用:属性引用和实例化

属性引用(类名.属性)

class Person:
role = 'person' def walk(self):
print('person is walking...')

上面代码中 role 是 Person的一个属性,walk 是 Person的方法。

print(Person.role)  # 查看人的role属性
print(Person.walk) # 引用人的走路方法,注意,这里不是在调用

实例化:类名加括号就是实例化,会自动触发 __init__ 函数的运行,可以用它来为每个实例定制自己的特征

class Person:
def __init__(self, name):
self.name = name p = Person('hkey') # 实例化 Person
print(p.name) # 执行结果:
# hkey p = Person('hkey') 就是一个实例化的过程,实例化会自动执行 __init__()方法。

关于 self

self: 在实例化时自动将对象/实例本身传给__init__的第一个参数
class Person:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
print(id(self)) p = Person('hkey', 20, 'male') # 实例化 Person
print(id(p)) # 执行结果:
#
#

通过上面的代码,我们可以查看到 self 和 对象 p 内存空间地址是一致的,印证了上面这句话。

如何查看一个类有哪些属性和方法,可以使用__dict__方法

class Person:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex print(Person.__dict__)
p = Person('hkey', 20, 'male') # 实例化 Person
print(p.__dict__)

对象的相关知识

对象是关于类而实际存在的一个例子,即实例
对象/实例只有一种作用:属性引用

class Person:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex p = Person('hkey', 20, 'male') # 这一步就是实例化一个对象p class Person:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex p = Person('hkey', 20, 'male') # 实例化 Person print('name:', p.name)
print('age:', p.age)
print('sex:', p.sex)
print('walk:', p.walk) # 在类中,方法也是对象。 # 执行结果: # name: hkey
# age: 20
# sex: male
# walk: <bound method Person.walk of <__main__.Person object at 0x0000024A4E819400>>

对象的使用

这里,我们把之前人狗大战的例子通过面向对象来重写下:

class Person(object):
def __init__(self, name, hp, aggr, job):
self.name = name
self.hp = hp
self.aggr = aggr
self.job = job def hit(self, gg):
gg.hp -= self.aggr
print('\033[31;1m%s被打,掉了%s的血。\033[0m' % (gg.name, self.aggr)) class Dog(object):
def __init__(self, name, hp, aggr, kind):
self.name = name
self.hp = hp
self.aggr = aggr
self.kind = kind def bite(self, p):
p.hp -= self.aggr
print('\033[31;1m%s被咬,掉了%s的血。\033[0m' % (p.name, self.aggr)) p = Person('kk', 100, 2, 'it')
teddy = Dog('teddy', 100, 3, 'teddy') p.hit(teddy)
print(teddy.hp) teddy.bite(p)
print(p.hp)

人狗大战

可以分析下上面的代码。
1. 我们创建两个类,一个人类,一个狗类
2. 通过实例化,我们创建了两个对象, p 和 teddy
3. 通过p.hit 调用人类的方法时,参数为狗类的对象,这里就是用到了对象的交互。
4. 通过teddy.bite 调用狗类的方法时,参数为人类的对象, 这里就是用到了对象的交互。

所以说,面向对象程序一旦开始就由对象之间的交互解决问题。

实例化:
    对象 = 类名(参数是__init__方法的参数)

实例 = 对象 完全没区别

对象查看属性:
    对象.属性名
    
对象调用方法:
    对象.方法名(参数)

练习:正方形的周长和面积

class Squ:
def __init__(self, length):
self.length = length def per(self):
return self.length * 4 def area(self):
return self.length ** 2 cfx = Squ(20)
print(cfx.per())
print(cfx.area())

正方形的周长和面积

类命名空间与对象、实例的命名空间

创建一个类就会创建一个类的名称空间用来存储类中定义的所有名字,这些名字称为类的属性

而类有两种属性:静态属性和动态属性

  • 静态属性就是直接在类中定义的变量
  • 动态属性就是定义在类中的方法
class Person:
language = 'Chinese' def __init__(self, name, age, job):
self.name = name
self.age = age
self.job = job hkey = Person('hkey', 20, 'it')
jay = Person('jay', 20, 'singer')

上面的代码中有一个类,实例化出两个对象 hkey 和 jay, 如下图:

1. 对象是通过类实例化出来的;
2. 对象和类是单向联系,也就是说,通过对象能够找到类,但是通过类是无法寻找到对象的;
3. 对象共享类中的属性和方法,但是二者之间是相互独立的内存空间

class Person:
language = 'Chinese' def __init__(self, name, age, job):
self.name = name
self.age = age
self.job = job hkey = Person('hkey', 20, 'it')
jay = Person('jay', 20, 'singer') print(Person.language) # 通过类调用静态属性
print(hkey.language) # 通过对象 hkey 调用静态属性
print(jay.language) # 通过对象 jay 调用静态属性 # 执行结果:
# Chinese
# Chinese
# Chinese

1. 通过类名调用静态属性,因为静态属性就在类的命名空间中,直接就可以取出使用;
2. 通过对象调用静态属性,首先对象会先在自己的命名空间中寻找 language 属性,如果没有会在类中去寻找 language 类中有则返回
3. 当对象自定义和类中静态属性一样的名称时,对象再次调用时,因为自己命名空间中已经存在,则直接返回。

class Person:
language = 'Chinese' def __init__(self, name, age, job):
self.name = name
self.age = age
self.job = job hkey = Person('hkey', 20, 'it')
jay = Person('jay', 20, 'singer') print(Person.language)
hkey.language = 'English'
print(hkey.language)
print(jay.language) # 执行结果:
# Chinese
# English
# Chinese

所以,在使用类中静态属性的时候,最好使用 类名.静态属性 调用

类中静态属性使用的经典例子:

要求:创建一个类,每次实例化一个对象就记录下来。

class Count:
count = 0
def __init__(self):
Count.count += 1
a = Count()
b = Count()
print(a.count)

记录每次实例化

[ python ] 初始面向对象的更多相关文章

  1. python初始面向对象

    阅读目录 楔子 面向过程vs面向对象 初识面向对象 类的相关知识 对象的相关知识 对象之间的交互 类命名空间与对象.实例的命名空间 类的组合用法 初识面向对象小结 面向对象的三大特性 继承 多态 封装 ...

  2. python之--初始面向对象

    阅读目录 楔子 面向过程vs面向对象 初识面向对象 类的相关知识 对象的相关知识 对象之间的交互 类命名空间与对象.实例的命名空间 类的组合用法 初识面向对象小结 面向对象的三大特性 继承 多态 封装 ...

  3. python基础——面向对象进阶下

    python基础--面向对象进阶下 1 __setitem__,__getitem,__delitem__ 把对象操作属性模拟成字典的格式 想对比__getattr__(), __setattr__( ...

  4. python基础——面向对象的程序设计

    python基础--面向对象的程序设计 1 什么是面向对象的程序设计 面向过程的程序设计的核心是过程,过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优 ...

  5. python学习------面向对象的程序设计

    一 面向对象的程序设计的由来 1940年以前:面向机器 最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行的指令和数 据.简单来说,就是直接编写 和 的序列来代表程序语言 ...

  6. Python之面向对象之初识面向对象

    初始面向对象 一.面向过程:面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优点:极大地降低了写成学的复 ...

  7. python基础——面向对象编程

    python基础——面向对象编程 面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的 ...

  8. Python的面向对象3

    接下来,我们接着讲Python的面向对象,在上一次的博客中,我们详细介绍了类与对象的属性,今天,我们来详细介绍一下面向对象中的方法! 1.定义实例方法 一个实例的私有属性就是以__开头的属性,无法被外 ...

  9. Python的面向对象2

    我们接着讲解Python的面向对象 1.初始化实例属性 在现实生活中,一种类型的实例会具有相同的某些属性,把这些实例划分为一个类型,则这些实例必然有相似的部分.但是,在创建实例之后,我们一个一个的为实 ...

随机推荐

  1. 【刷题】BZOJ 1453 [Wc]Dface双面棋盘

    Description Input Output Sample Input Sample Output HINT Solution 不强制在线的动态图问题,那就LCT了 类似二分图那道题目 对于四个方 ...

  2. HDU 4383 To The Moon 解题报告

    HDU 4383 To The Moon 题意翻译 已知一个长为\(n\)的序列\(a\),你需要进行下面的四种操作. C l r d 将区间\([l,r]\)中的数加上\(d\),同时时间加\(1\ ...

  3. Redis Scan迭代器遍历操作原理(一)

    Redis在2.8.0版本新增了众望所归的scan操作,从此再也不用担心敲入了keys*, 然后举起双手看着键盘等待漫长的系统卡死了··· 命令的官方介绍在这里, 中文版由huangz同学细心翻译了, ...

  4. AtCoder Regular Contest 088 E - Papple Sort(树状数组+结论)

    结论:每次把字符丢到最外面最优,用树状数组统计答案,把字符放到最外边后可以当成消失了,直接在树状数组上删掉就好. 感性理解是把字符丢到中间会增加其他字符的移动次数,但是丢到外面不会,所以是正确的. # ...

  5. 相机标定 和 单应性矩阵H

    求解相机参数的过程就称之为相机标定. 1.相机模型中的四个平面坐标系: 1.1图像像素坐标系(u,v) 以像素为单位,是以图像的左上方为原点的图像坐标系: 1.2图像物理坐标系(也叫像平面坐标系)(x ...

  6. [DeeplearningAI笔记]卷积神经网络1.9-1.11池化层/卷积神经网络示例/优点

    4.1卷积神经网络 觉得有用的话,欢迎一起讨论相互学习~Follow Me 1.9池化层 优点 池化层可以缩减模型的大小,提高计算速度,同时提高所提取特征的鲁棒性. 池化层操作 池化操作与卷积操作类似 ...

  7. jquery validate 二选一,错误提示在一处

    转载自:http://blog.51yip.com/jsjquery/1483.html 有一同事对jquery validate这个插件不熟,实现多处报错信息在一处,并且还有二选一的情况,二个输入框 ...

  8. Packet Tracer 5.0 构建CCNA实验(3)—— 路由器实现vlan间通信

    --交换机配置 --交换机和路由器连接的接口 switchport mode trunk --路由器配置 enable conf t int fa0/0.1 --路由器接口的子接口 encapsula ...

  9. C11工具类:字符转换

    1.数值类型和字符串转换 1.1 数值转换为字符 std::string to_string(int value); std::string to_string(long value); std::s ...

  10. 【BZOJ】3771: Triple FTT+生成函数

    [题意]给定n个物品,价值为$a_i$,物品价格互不相同,求选一个或两个或三个的价值为x的方案数,输出所有存在的x和对应方案数.$ai<=40000$. [算法]生成函数+FFT [题解]要求价 ...