OPP介绍

programming的核心原则需要铭记:

1. 写重复代码是非常不好的低级行为

2. 写的代码需要经常变更

初学者虽然理解面对对象编程(定义类,方法,三大特性等),但是一正真写程序,就喜欢用面对过程式编程来写代码(一个个函数)。 这主要是没有充分理解OPP所带来的好处。 开发正规的程序和写只运行一次的小脚本最大不同是,代码总需要不断的更改,不管是修改bug或者添加新功能等,所以为了日后方便程序的修改和扩张,写的代码一定要可读性好、易扩展。 OPP比函数编程更加易读,易改。 以下简单的仿cs游戏实例就可以看出这点。

为每个角色开发以下几个功能被打中后就会掉血的功能:
开枪功能
换子弹
买枪
跑、走、跳、下蹲等动作
保护人质(仅适用于警察)
不能杀同伴
。。。
仿cs游戏需要满足的条件
'''
创建4个角色
'''
roles = {
    1: {'name': 'Alex',
        'role': 'terrorist',
        'weapon': 'AK47',
        'life_value': 100,
        'money': 15000,
        },
    2: {'name': 'Jack',
        'role': 'police',
        'weapon': 'B22',
        'life_value': 100,
        'money': 15000,
        },
    3: {'name': 'Rain',
        'role': 'terrorist',
        'weapon': 'C33',
        'life_value': 100,
        'money': 15000,
        },
    4: {'name': 'Eirc',
        'role': 'police',
        'weapon': 'B51',
        'life_value': 100,
        'money': 15000,
        },
}

# 调用角色的方式
print(roles[1])  # Alex
print(roles[2])  # Jack

def shot(by_who):
    # 开枪功能,开了抢后减少子弹
    pass


def got_shot(who):
    # 中枪后要减血
    who['life_value'] -= 10
    pass


def buy_gun(who, gun_name):
    # 检查钱够否,买了抢扣钱
    pass
仿cs游戏 之 过程式编程

但是,从以上例子就可以看出,过程式编程的缺陷问题:

1. 每个角色下设的属性种类(包括name, role, weapon, life_value, money)都一样。创建新角色时,如果属性名字错误(weapon -> wepon),就无法读取。而且复制黏贴创建也不是很高级。同时,当要增加属性类别时,得一个个加,极其崩溃。

2. terrorist和policy 有相同的功能,也有不同的功能。 以上做法无法区分。 角色无法个性化

3. 减血应该只能通过got_shot()函数。但是以上程序,可以直接通过调用 roles[who]['life_value'] 绕过got_shot直接减血,等于是个作弊器。

用OPP的话,大量缩减代码量,同时更易读。 见下:

class Role(object):    # 定义一个类,class是定义类的语法, role是类名,(object)是新式类的写法,必须这样写
    def __init__(self,name,role, weapon, life_value=100, money=15000):   # 初始化函数,在生成一个角色时要初始化的一些属性
        self.name = name
        self.role = role
        self.weapon = weapon
        self.life_value = life_value
        self.money = money

    def shot(self):
        print("shooting")

    def got_shot(self):
        print("ah..., i got shot...")

    def buy_gun(self, gun_name):
        print("just bought %s" %gun_name)


r1 = Role("alex", "police", "ak47")  # 生成一个角色,会自动把参数传给role下面的__init__(...)方法
r2 = Role("Jack", 'terrorist', 'b22')   # 生成一个角色
仿cs游戏 之 面向对象编程

何时适用OPP 面向对象编程呢?

  1. 应用场景: SSH 链接操作
  2. 模版
  3. 很多函数都需要传公共的参数

基本定义及语法

OPP编程是利用“类”和“对象”来创建各种模型来实现对最后的需求。 其定义如下:

class 类

类似于模版。 一个类即是对一类拥有相同属性的对象的抽象、蓝图、及原型。在类中,定义了这些object都具有的属性(variables), 共同的方法或者功能。 

object 对象

对象即是一个类的实例化后的实例(通过模版刻画出来的实物)。 一个类必须经过实例化后方可在程序中调用, 一个类可以实例化多个对象。 每个对象亦可有不同的特性。

实例化其实就是以类为模版,在内存中开辟一块空间,存上数据,赋值成一个变量名。 其他关于类和对象,见以下示例:

class Dog(object):
 
    print("hello,I am a dog!")
 
 
d = Dog() #实例化这个类,
#此时的d就是类Dog的实例化对象
 
#实例化,其实就是以Dog类为模版,在内存里开辟一块空间,存上数据,赋值成一个变量名
类、实例化和实例化后的实例-对象
class Dog(object):
 
    def __init__(self,name,dog_type):   #成员属性/构造函数/构造方法 == 初始化方法
        self.name = name
        self.type = dog_type
 
    def sayhi(self):                              # 类的方法
 
        print("hello,I am a dog, my name is ",self.name)
 
 
d = Dog('LiChuang',"京巴")                # Dog(d, “litchang” ) # 实力化后产生的对象
d.sayhi()
成员属性,类的方法及对象

总结下,类、实例化对象 的内存储存方式见下图:

类的语法

过程: 定义类 -> 实例化 -> 实例对象

类的语法涉及:

1. 构造函数 或 初始化函数, 即指类实例化后的对象初始化的一些属性

 表达式: def __initial__(self) 

2. 成员变量 或 属性 或 字段,即在__initial__(self)函数下设置的内容

 表达式:   self.name = name 或 self.life_value = life_value 等 

   其中,self指的是实例化后的对象本身。 之后将这个对象作为参数传入类的功能。 见下图

3. 方法 或 动态属性

 表达式: def sayhi(self)

4. 私有属性,定义在构建函数之下,前缀 __ 。 一般,对外不可访问,但是可以通过内部方法调用访问。 

 表达式: self.__heart = "normal" 

 私用属性的访问方式有三种,案例见下代码:

  • 通过类内的方法下设访问
  • 通过类内的对外提供只读的访问借口 return self.__heart
  • 强行访问  r1._Role__heart()

5. 公有属性, 即所有属于类的对象都可以访问的属性。成员属性不是公有属性。 公有属性直接在class下面,不在任何built-in 函数里面。

6. 析构方法, 实例销毁的时候自动调用。 变量实例化后,在内存中就存了数据,不会自动清除。 del 用来销毁实例, 自动调用 __del__(self)。 销毁实例,只是撤销r2这个名字(类似门牌号)和内存地址之间的引用关系,并没有删除内存地址里的内容。 python有自动垃圾清除机制,如果发现门牌号摘掉了,就删除内存里的数据。 主要用于一些程序的收尾工作

一般搜索过程,是先搜索成员属性,在到父集找公有属性。同时,除了公有属性是共享的,下设函数也是公有,也是共享的。 所有在函数需要导入参数self

以下例子中展示了1-5的使用方法

class Role(object):    # 定义一个类,class是定义类的语法, role是类名,(object)是新式类的写法,必须这样写
    nationality = "JP"         # 5. 公有属性, 在类里直接定义的属性即是公有属性

    def __init__(self,name,role, weapon, life_value=100, money=15000):   # 1. 构造函数或初始化函数,在生成一个角色时要初始化的一些属性
        self.name = name       # 2. 成员变量,属性
        self.role = role
        self.weapon = weapon
        self.life_value = life_value
        self.money = money
        self.__heart = 'normal'   # 4. 私有属性,私有属性对外部不可访问;但内部客访问见下

    def shot(self):               # 3. 方法/功能,动态属性
        print("shooting")
        self.__heart = 'DIE'
        print(self.__heart)

    def got_shot(self):
        print("ah..., i got shot...")
        self.__heart = "die"
        print(self.__heart)      # 4. 私有属性的内部访问,比较推荐的方式,方法一

    def buy_gun(self, gun_name):
        print("just bought %s" %gun_name)

    def get_heart(self):
        return self.__heart      # 4. 私有属性, 对外提供只读访问借口  方法二

    def __del__(self):           # 6. 析构方法,实例销毁是自动调用
        print("del...run...")


r1 = Role("alex", "police", "ak47")  # 生成一个角色,会自动把参数传给role下面的__init__(...)方法
r2 = Role("Jack", 'police dog', 'b13')   # 生成一个角色

r1.got_shot()

print(r1.get_heart())

print(r1._Role__heart)          # 4. 私有属性的强制访问  方法三

Role.nationality = "usa"        # 5. 更改类的公有属性
print(r1.nationality)           # 5. 打印公有属性
r1.nationality = "tailand"      # 5. 从新在r1对象下新建了一个nationality 的成员变量,不是公有变量
print(r1.nationality)

del r2   # 6. 销毁实例, 自动调用 __del__(self)。 销毁实例,只是撤销r2这个名字(类似门牌号)和内存地址之间的引用关系,并没有删除内存地址里的内容。 python有自动垃圾清除机制,如果发现门牌号摘掉了,就删除内存里的数据

 

Reference: 

day 6 by Alex 老男孩课件

posted on 2017-11-27 21:41  lg100_lg100  阅读(208)  评论(0编辑  收藏  举报