面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。

是将数据和处理数据的函数绑定到一起封装到对象中

对象是特征与技能的结合体,基于面向对象设计程序

例子: 把大象装进冰箱 ?

面向过程:

1.打开冰箱

2.装入大象

3.关闭冰箱

面向对象:

找个具有装大象的技能的对象

在面向对象中程序员的角度发生改变,从具体的操作者变成了指挥者;

强调:对象不是凭空产生的,需要我们自己设计

优缺点

优点:

1.提高扩展性,当一个对象发生了修改时,对其他对象时没有任何影响的,对象之间相互独立,耦合度变得更低了

2.提高复用性

3.提高灵活性,如果某个对象发生变化,也不会影响其他的对象 , 扩展性

缺点:

1.可控性差,无法预知结果

2.程序的复杂度高

应用场景:

对扩展性要求较高的程序

面向过程编程思想

优点:逻辑清晰,将复杂问题简单化,流程化,

缺点:扩展性差,可维护性差,牵一发而动全身

使用场景:

对扩展性要求较低的程序例如:系统内核,git,计算器

类和对象

是OOP中的最核心的两个概念

是一系列具有相同特征和行为的集合体,是一种抽象概念

即类型,类别

对象

具备某种特征与行为的结合体,在程序中用变量来表示对象的特征,函数表示对象的技能,在生活中万物皆对象

对象:将变量与函数结合在一起,形成一个整体

也可以理解为:

变量的作用是存储数据,函数的作用在处理数据

对象是将数据与处理数据的函数绑定在一起

编程思想不是某一个具体语言或技术 ,
面向对象的语言:
python,Java,C++,C#
面向过程:
C,ruby

创建类与对象

在python中,定义类通过class关键字:

class Student:
    pass

class 后面紧跟是类名,遵循python 编码规范,类名通常是大写开头的单词,多个单词时使用驼峰命名法

大驼峰命名法
class Student:
    pass
小驼峰命名法
class student:
    pass
命名法

创建对象的语法

class Student:
    pass
#创建对象,通过类名加()实例化产生一个对象
p = Student()
print(p)
#实例化得到的内存地址  <__main__.Student object at 0x00000000022EC978>
print(Student)
#得到的类 <class '__main__.Student'>
语法

属性的写法

属性可以写在类中 
类中的属性,是所有对象公共的 

也可以写在对象中 
对象中的属性,是每个对象独特的(不一样的)


如果类中和对象中存在同样的属性,先访问对象 如果没有在访问类 


练习: 描述一个老师类 需要包含 一个公共属性和 一个独特的属性 

class Teacher:
    school = "oldboy"
    
t1 = Teacher()
t1.name = "jack"
t1.age = 28
写法

对象的属性操作

对象是特征(属性)与行为(方法)的结合体

其添加属性可以在创建对象后使用点语法(变量名加 . )比如为对象添加name属性

class Student:
    pass

#创建对象,通过类名加()实例化产生一个对象
p = Student()
print(p)
print(Student)
p.name = "Jerry"

同样通过点语法来获取对象的属性值

print(p.name)
#输出 Jerry

属性的增删改查

增加属性 
对象变量名称.属性名称 = 属性值

删除属性
del 对象的变量名称.属性名称 

修改 
对象.属性 = 新的值 

查看属性  访问的是对象的所有属性 
print(对象.__dict__)

访问对象的类信息
print(对象.__class__)

访问对象的类名
print(对象.__name__)

初始化方法

用于为对象的属性设置初始值的函数

class Student:
    def __init__ (self,name):
        print("init run")
        self.name = name
s1 = Student('李三')
s2 = Student('王五')
注意:该函数不能有任何返回值/.... 只能是None  规定如此..

执行过程:

在创建对象时Student("jack")会申请新的内存空间用于保存对象数据,接着自动调__init__函数

__init__函数要求第一个参数必须是self,该参数表示需要被初始化的对象本身,这样就可以将name属性绑定到对象上,有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去:

# p1 = Student()
# 以上代码将抛出异常:TypeError: __init__() missing 1 required positional argument: 'name'
p1 = Student("jack")
# 输出 init run
print(p1.name)
# 输出 jack
View Code
总结:

- init函数用于为对象属性设置初始值 
- 在创建对象时会自动调用
- 自动传入对象本身

属性查找顺序

可以将类中的内容都称之为属性,变量称为数据属性,函数就叫函数属性

类中可以声明变量来表示数据属性,为Student类添加数据属性和函数属性

class Student:
    school = "Tsinghua" #数据属性
    
    def say_hello(self):#函数属性
        print("hello i am a student")
    
    def __init__ (self,name): #初始化函数
        self.name = name
   
属性

也可以使用点语法在创建对象后为对象增加数据属性

stu = Student("Maria")
stu.age = 20

类中的数据属性是所有对象共享的

创建对象后为增加的数据属性,是这个对象特有的,去其他对象没有关联

查找顺序:

优先查找对象自己的名称空间,如果没有则在类中找,如果类中也没有则到父类中找,直到找到为止,如果父类中也没有则抛出异常

class Student:
    school = 'beidaokou'
    def __init__(self,name):
        self.name = name
        
stu1 = Student("Jack")
stu2 = Student("Rose")

#1.类中的数据属性是所有对象共享的
print(stu1.school)
print(stu2.school)
#输出均为 beidaokou

#2.类中的数据属性访问的是同一块内存
print(id(stu1.school))
print(id(stu2.school))
#输出 4470412656
#输出 4470412656

#3.类的函数属性是绑定给对象使用的,bound method称为绑定方法,每个对象的绑定方法内存地址不一样
print(stu1.say_hello)
print(stu2.say_hello)
#输出 <bound method Student.say_hello of <__main__.Student object at 0x10cc405f8>>
#输出 <bound method Student.say_hello of <__main__.Student object at 0x10cc40630>>


#4.优先访问对象自己的名称空间 
# 修改stu1的学习属性为北京大学 会在自stu1的名称空间增加school属性
stu1.school = "Beijing"
print(stu1.__dict__)
print(stu2.__dict__)
#输出 {'name': 'Jack', 'school': 'Beijing'}
#输出 {'name': 'Rose'}

#4.1再次查看学校属性
print(stu1.school)
print(stu2.school)
#输出 Beijing
#输出 Tsinghua

#__dict__用于访问对象的名称空间 本质是一个字典类型数据,存储名称与值的映射关系
查找

绑定方法

1.绑定到对象的方法:没有被任何装饰器装饰的方法。

在类中定义的函数默认都是绑定到对象的方法

特点:参数的第一个必须是self 表示当前对象本身,使用对象来调用,调用时会自动传入对象

class Student:
    
    def __init__(self,name):
        self.name = name
     
    def say_hi(self):
        print("hello my name is %s" % self.name)
绑定到对象

2.绑定到类的方法:用classmethod装饰器装饰的方法。

特点:参数的第一个必须是cls表示当前类本身,使用类名来调用,调用时会自动传入类

class OldBoyStudent:
    school = "oldboy"

    def __init__(self,name):
        self.name = name

    @classmethod
    def show_school(cls):
        # print(self.school)
        print(cls)
绑定到类
什么时候绑定给对象:当函数逻辑需要访问对象中的数据时

什么时候绑定给类:当函数逻辑需要访问类中的数据时

非绑定方法

用staticmethod装饰器装饰的方法

不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说。就是一个普通函数

不过由于作用域在类中所以需要使用类或对象类调用

class OldBoyStudent:
    school = "oldboy"

    def __init__(self,name):
        self.name = name
     @staticmethod
    def print_hello():
        print("hello world")
非绑定方法

练习:为学生类添加一个save方法 一个get方法

save是将对象存储到文件中

get是从文件中获取对象

import pickle


class Student:
    def __init__(self,name):
        self.name = name

    def say_hi(self):
        print("name:",self.name)

    def save(self):
        with open(self.name,"wb") as f:
            pickle.dump(self,f)

    @staticmethod
    def get(name):
        with open(name,"rb") as f:
            obj = pickle.load(f)
            return obj



# stu = Student("rose")
# stu.save()
#
#
# stu1 = Student("jack")
# stu1.save()

# obj = Student.get("rose")
# print(obj.name)
#
# obj = Student.get("jack")
# print(obj.name)

print(Student.__name__)
代码


需求设计王者荣耀中的英雄类,每个英雄对象可以对其他英雄对象使用技能

具备以下属性

英雄名称,等级,血量

和Q_hurt,W_hurt,E_hurt 三个属性,表示各技能的伤害量

具备以下技能

Q W E

三个技能都需要一个敌方英雄作为参数,当敌方血量小于等于0时角色死亡

import random
import time


class Hero:

    def __init__(self,name,level,blood,att,q_hurt,w_hurt,e_hurt):
        # 简便写法
        lcs = locals()
        lcs.pop("self")
        self.__dict__.update(lcs)

    def attack(self,enemy):
        enemy.blood -= self.att
        print("%s对%s释放了普通攻击 造成了%s的伤害 敌人剩余血量%s" % (self.name, enemy.name, self.att, enemy.blood))
        if enemy.blood <= 0:
            print("%s被%s使用普通攻击击杀了" % (enemy.name,self.name))


    def Q(self,enemy):
        enemy.blood -= self.q_hurt
        print("%s对%s释放了Q 造成了%s的伤害 敌人剩余血量%s" % (self.name, enemy.name, self.q_hurt, enemy.blood))
        if enemy.blood <= 0:
            print("%s被%s使用Q技能击杀了" % (enemy.name, self.name))

    def W(self,enemy):
        enemy.blood -= self.w_hurt
        print("%s对%s释放了W 造成了%s的伤害 敌人剩余血量%s" % (self.name, enemy.name, self.w_hurt, enemy.blood))
        if enemy.blood <= 0:
            print("%s被%s使用W技能击杀了" % (enemy.name, self.name))

    def E(self,enemy):
        enemy.blood -= self.e_hurt
        print("%s对%s释放了E 造成了%s的伤害 敌人剩余血量%s" % (self.name,enemy.name,self.e_hurt,enemy.blood))

        if enemy.blood <= 0:
            print("%s被%s使用E技能击杀了" % (enemy.name, self.name))


h1 = Hero("亚索",20,2000,100,600,0,1000)
h2 = Hero("妲己",20,2000,100,600,500,1000)
h3 = Hero("鲁班",20,1500,700,100,200,300)
h4 = Hero("蔡文姬",20,2000,10,0,0,10)


#
# h1.attack(h2)
# h2.Q(h1)
# h2.E(h1)
# h2.W(h1)

#从字典中随机拿出一个值

def  random_hero(heros):
    hero_index = random.randint(1, len(heros))
    return heros[hero_index]


while True:
    # # 把所有的攻击方法装到字典里  为了随机取出一个
    funcs = {1: Hero.Q, 2: Hero.W, 3: Hero.E, 4: Hero.attack}
    func_index = random.randint(1, 4)
    func = funcs[func_index]


    # 把所有的英雄方法装到字典里  为了随机取出一个
    heros = {1: h1, 2: h2, 3: h3, 4: h4}
    hero = random_hero(heros)

    # 剩余的英雄们
    other_heros = {}
    new_index = 1
    for k, v in heros.items():
        if v != hero:
            other_heros[new_index] = v
            new_index += 1

    # 从剩余的英雄中随机挑出一个英雄来挨打
    enemy = random_hero(other_heros)
    # 打他
    func(hero, enemy)
    if enemy.blood <= 0:
        break
    time.sleep(0.5)
代码

 

 

 

 

 

posted on 2019-07-24 20:37  我只想你  阅读(172)  评论(0编辑  收藏  举报