DAY15 面向对象初始

初识面向对象

   在python之中,一切皆对象。面向对象编程(OOP)是一种编程思想,把对象作为编程的单元,使得程序更加容易拓展。

   面向对象编程的一些专业名词:

     类 :具有相同属性和功能的一类事物。

     对象/实例 :类的具体实现。

     实例化 :类--->对象的过程。

类是什么?

    类:具有相同属性或者功能的一类事物。

class A:
    name = 'he'   #属性(静态属性)/静态变量/静态字段

    def func1(self):  #动态属性/方法
        pass

     通过上面的代码,我们创建了一个类A,接下来我们来看看具体的定义:

   class :定义类的关键字,类似于def。

   name = ‘he’ :类的属性,又称为静态属性/静态字段/静态变量。

    def func1(self):pass  : 这个类似于函数的东西,在类中称为方法,也称为动态属性。

  总结:从上面我们可以得到,一个类主要有两部分组成,类的属性+类的方法

类名的使用:操作类的属性

    首先,我们必须明白一个概念。类,是一个公共模型,是一个公共的框架。

class Person:
    animal = '高级动物'             #类的属性
    walk_way = '直立行走'           
    language = '语言'
    
    def eat(self):                 #类的方法
        print('吃吃吃,喝喝喝')
    def work(self):
        print('人类都需要工作')
    

   如果知道一个类究竟有哪些属性以及方法?此时“__dict__”方法就能帮到我们。

      __dict__ :   查看类/对象中的所有属性以及方法,并返回一个字典。

class Person:
    animal = '高级动物'
    walk_way = '直立行走'
    language = '语言'
    
    def eat(self):
        print('吃吃吃,喝喝喝')
    def work(self):
        print('人类都需要工作')


#(1)通过__dict__方法查看类Person中的所有属性以及方法
print(Person.__dict__)
>>>
{'__module__': '__main__', 'animal': '高级动物', 'walk_way': '直立行走', 'language': '语言', '__init__': <function Person.__init__ at 0x0000020F50318A60>, 'eat': <function Person.eat at 0x0000020F50318AE8>, 'work': <function Person.work at 0x0000020F50318B70>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}


#(2) 返回的是一个字典,取个值看看。
print(Person.__dict__['animal'])
>>>
高级动物

#(3)既然能够取值,那么能否修改呢?
Person.__dict__['animale'] = '低级动物‘
>>>
TypeError: 'mappingproxy' object does not support item assignment       #报错了

    总结:通过以上的例子,__dict__方法的使用方法如下:

      (1)__dict__方法能够以字典的方式,把类中的所有属性和方法返回回来。对于单个的值,可以通过__dict__[key]来查询,但是只能查不能修改。。

      (2)一般在工作中,__dict__方法只用在查询类的属性以及方法上,不进行其他操作。对于增删查改类中的某个属性,某个方法,可以用到万能的点"."。

    

      类中属性的查有两种方式:1.__dict__[属性名]    2.‘类名.属性名’

class Person:
    animal = '高级动物'
    walk_way = '直立行走'
    language = '语言'

#(1)通过__dict__查询animal的值
print(Person.__dict__['animal'])
>>>
高级动物
#(2)通过万能的点 print(Person.animal) >>> 高级动物

       

#如果定义一个类中本没有的属性,那么就可以把新属性添加进去。
Person.thinking = '思考'
print(Person.__dict__)                        #thinking:思考 就会新添加进去。
>>>
{'__module__': '__main__', 'animal': '高级动物', 'walk_way': '直立行走', 'language': '语言', '__init__': <function Person.__init__ at 0x0000024D779689D8>, 'eat': <function Person.eat at 0x0000024D77968A60>, 'work': <function Person.work at 0x0000024D77968AE8>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None, 'thinking': '思考'}

        

# 通过del语句删除类中的属性
del Person.walk_way
print(Person.walk_way)
>>>
AttributeError: type object 'Person' has no attribute 'walk_way'    #类中没有该属性

       

#如果一个现有的属性,想更改他对应的值。
Person.animal = '低等动物'
print(Person.animal)
>>>
低等动物

类名的使用:操作类的方法

   类中的方法,一般不直接通过类名来操作,而是通过对象来操作类的方法。

#方法一:通过__dict__方法来执行类的方法(骚操作,不建议使用)
Person.__dict__['work']('alex')
>>>
人类都需要工作

#方法二:通过万能的点(不建议使用)
Person.work('alex')
>>>
人类都需要工作

 

对象是什么?

   对象:类的具体实现,类的实例化。

#类的实例化
he = Person()   #这样就实例化了一个对象,在内存空间中开辟了一个对象空间。

     看到这里,我们可能会比较懵圈,究竟怎么样产生的一个对象?接下来,__init__(self)特殊方法就该登场了。

__init__()特殊方法

   __init__()方法的第一个参数必须是self,在类的实例化过程中执行。

class Person:
    animal = '高级动物'
    walk_way = '直立行走'
    language = '语言'

    def __init__(self,name,age,eye):    #特殊方法,给对象封装属性。
        print(self)
        self.name = name                     #给对象增加一个属性
        self.age = age
        self.eye = eye


    def eat(self):
        print('吃吃吃,喝喝喝')
    def work(self):
        print('人类都需要工作')


#此时,你会好奇,self这个参数究竟是何方神圣??于是,立马实例化一个对象
he = Person('he',23,'small eye')      #实例化了一个对象he,手动把实参传入,self去哪了??
print(he)
>>>
<__main__.Person object at 0x000002CC8FE0E128>
<__main__.Person object at 0x000002CC8FE0E128>

#两个内存地址是一样的,证明self就是he这个对象。

   类的实例化过程中其实有三个步骤:

  (1)执行类的实例化过程,会在内存中创建一个对象空间,其中有一个类对象指针,能够指向类的内存空间。

  (2)自动执行__init__()特殊方法,把对象空间自动传给self参数,其他所需参数需要手工传递。

  (3)执行__init__()方法的具体逻辑,给对象空间封装属性。

对象操作对象空间

he = Person('he',23,'small eye')    #实例化一个对象,he这个对象自动传给参数self,其他参数需要填入。
print(he.__dict__)                       #查看对象空间的所有属性和方法
>>>
{'name': 'he', 'age': 23, 'eye': 'small eye'}

#属性的查
print(he.name)
>>>
he

#属性的增
he.sex = 'male'
print(he.__dict__)
>>>
{'name': 'he', 'age': 23, 'eye': 'small eye', 'sex': 'male'}

#属性的改
he.eye = 'big eye'
print(he.eye)
>>>
big eye

#属性的删除
del he.eye
print(he.__dict__)
>>>
{'name': 'he', 'age': 23}

对象操作类空间的属性以及方法

#对象操作类空间的属性, 只能查看类中的属性,不能修改。
print(he.animal)                  #类只能查看类中的属性
he.animal = '低等动物'          #看似改变类的属性,其实就是给对象新增一个对象
print(Person.animal)
print(he.__dict__)
>>>
高级动物
高级动物
{'name': 'he', 'age': 23, 'eye': 'small eye', 'animal': '低等动物'}


#对象操作类中的方法(推荐)
he = Person('he',23,'small eye')
he.eat()
>>>
吃吃吃。。

   问题一: 对象为什么能够调用类中的属性与方法?

   答:因为对象空间中存在着类对象指针,对象会先在对象空间中寻找,如果找不到,会到类空间中寻找。。

   问题二: 对象与对象之间能够互相调用吗?

   答:同一个类实例化出来的对象之间是不能互相调用的;但是不同类实例化出来的对象,可以互相调用。

   问题三: 如果给对象封装属性?

   答: 方式一:通过__init__()特殊方法,给对象封装属性。

      方式二:如果有特殊属性,在任何位置都可以增加。

 

组合

  组合:给一个类的对象封装一个属性,这个属性是另一个类的对象。

  哔哔哔,现在有了一个新的需求,要求盖伦用它的大宝剑对亚索发起一个攻击,亚索也可以通过他的日本武士刀给盖伦来一刀。有了上面的经验,一瞬间~

class GameRole:
    def __init__(self,name,ad,hp):
        self.name = name
        self.ad = ad
        self.hp = hp

    def attack(self,role):
        role.hp = role.hp - self.ad
        print('%s攻击了%s,%s掉了%s血,还剩%s血'%(self.name,role.name,role.name,self.ad,role.hp))

p1 = GameRole('盖伦',20,500)
p2 = GameRole('剑豪',100,200)

class Weapon:
    def __init__(self,name,ad):
        self.name = name
        self.ad = ad

    def fight(self,role1,role2):
        role2.hp = role2.hp - self.ad
        print('%s用%s攻击%s,%s掉了%s血,还剩%s血'%(
            role1.name,
            self.name,
            role2.name,
            role2.name,
            self.ad,
            role2.hp
        ))

w1 = Weapon('大宝剑',30)
w2 = Weapon('武士刀',50)


#一瞬间写完,然后执行:
w1.fight(p1,p2)
>>>
盖伦用大宝剑攻击剑豪,剑豪掉了30血,还剩170血

 

  啪啪啪,一顿敲完,也运行成功了,自豪感油然而生~但是真的正确吗,静静的看一下,应该就能看到了端倪。有点不合常理啊,应该攻击的发起者是人类,但是现在却变成了武器对象。

  但是,角色对象和武器对象分属于两个不同的类。。能够通过一个类的对象访问另外一个类的方法吗?组合变能够做到。

class GameRole:
    def __init__(self,name,ad,hp):
        self.name = name
        self.ad = ad
        self.hp = hp

    def attack(self,role):
        role.hp = role.hp - self.ad
        print('%s攻击了%s,%s掉了%s血,还剩%s血'%(self.name,role.name,role.name,self.ad,role.hp))

    def equipment(self,w):            
        self.weapon = w             #这就是组合,给一个类的对象封装一个属性,该属性的值是另一个类的 
                                               对象


p1 = GameRole('盖伦',20,500)
p2 = GameRole('剑豪',100,200)

class Weapon:
    def __init__(self,name,ad):
        self.name = name
        self.ad = ad

    def fight(self,role1,role2):
        role2.hp = role2.hp - self.ad
        print('%s用%s攻击%s,%s掉了%s血,还剩%s血'%(
            role1.name,
            self.name,
            role2.name,
            role2.name,
            self.ad,
            role2.hp
        ))

w1 = Weapon('大宝剑',30)
w2 = Weapon('武士刀',50)

 
p2.equipment(w2)                   #即p2.weapen = w2,就能欧访问到为w2的内存地址。
p2.weapon.fight(p2,p1)

  总结:

    组合的好处就是能够把一个类的对象与另一个类的对象产生关系,从而是一个类与另一个类产生关系。

  

      

 

 

 

 

posted @ 2018-08-23 21:04  hehehe1994  阅读(144)  评论(0编辑  收藏  举报