Python学习之路—面向对象基础

面向对象

python中一切皆为对象,类型的本质就是类,所以,不管你信不信,你已经使用了很长时间的类了

>>> dict #类型dict就是类dict
<class 'dict'>
>>> d=dict(name='eva') #实例化
>>> d.pop('name') #向d发一条消息,执行d的方法pop
'eva'

从上面的例子来看,字典就是一类数据结构,我一说字典你就知道是那个用{}表示,里面由k-v键值对的东西,它还具有一些增删改查的方法。但是我一说字典你能知道字典里具体存了哪些内容么?不能,所以我们说对于一个类来说,它具有相同的特征属性和方法。

而具体的{'name':'eva'}这个字典,它是一个字典,可以使用字典的所有方法,并且里面有了具体的值,它就是字典的一个对象。对象就是已经实实在在存在的某一个具体的个体。

再举一个其他的例子,通俗一点,比如你现在有一个动物园,你想描述这个动物园,那么动物园里的每一种动物就是一个类,老虎、天鹅、鳄鱼、熊。他们都有相同的属性,比如身高体重出生时间和品种,还有各种动作,比如鳄鱼会游泳,天鹅会飞,老虎会跑,熊会吃。

但是这些老虎熊啥的都不是具体的某一只,而是一类动物。虽然他们都有身高体重,但是你却没有办法确定这个值是多少。如果这个时候给你一只具体的老虎,而你还没死,那你就能给他量量身高称称体重,这些数值是不是就变成具体的了?那么具体的这一只老虎就是一个具体的实例,也是一个对象。不止这一只,其实每一只具体的老虎都有自己的身高体重,那么每一只老虎都是老虎类的一个对象。

在python中,用变量表示特征,用函数表示技能,因而具有相同特征和技能的一类事物就是‘类’,对象是则是这一类事物中具体的一个。

 

类的相关知识

初识类

声明

class 类型:
    类中的代码
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类,在这个过程中,产生了一个egg对象,有自己具体的名字、攻击力和生命值。

语法:对象名 = 类名(参数)

egg = Person('egon')  #类名()就等于在执行Person.__init__()
#执行完__init__()就会返回一个对象。这个对象类似一个字典,存着属于这个人本身的一些属性和方法。
#你可以偷偷的理解:egg = {'name':'egon','walk':walk}

查看属性&调用方法

print(egg.name)     #查看属性直接 对象名.属性名
print(egg.walk())   #调用方法,对象名.方法名()

关于self

self:在实例化时自动将对象/实例本身传给__init__的第一个参数,你也可以给他起个别的名字,但是正常人都不会这么做。
因为你瞎改别人就不认识

 

对象的相关知识

给人类添加一个技能

复制代码
class Person:
role = 'person' # 类属性,静态属性
def __init__(self,name,sex,aggr=100): # 对象属性,属性
self.name = name
self.sex = sex
self.aggr = aggr
self.blood = 1000
def attack(self,dog): # 类的动态属性
print('%s打了%s一下' %(self.name,dog.name))
dog.blood -= self.aggr
复制代码

对象是关于类而实际存在的一个例子,即实例

对象/实例只有一种作用:属性引用

egon = Person('agon','male',200)
alex = Person('agon','male',300)

后期如何给对象添加属性:

egon.weapon='菜刀'
print(egon.weapon)

当然了,你也可以引用一个方法,因为方法也是一个属性,只不过是一个类似函数的属性,我们也管它叫动态属性。

引用动态属性并不是执行这个方法,要想调用方法和调用函数是一样的,都需要在后面加上括号

print(egon.attack)
egon.attack()

 

print(Tom.hobbies)
print(Tom.role)
Tom.attack()

# 对象名
对象.对象属性(属性)
对象.类属性    # 对象名最好不要调用类属性
对象.动态属性(方法)()

print(Person.role)
Person.attack    # 可以查看
Person.attack()  # 不能调用

# 类名
类名.类属性
类名.动态属性(方法)()  # 不能调用动态属性

小结:

# 类:具有相同属性和方法的一类事物
# 对象(示例): 具体的某一个事物
# 实例化:一个类实例出一个对象

 

对象之间的交互

现在我们已经有一个人类了,通过给人类一些具体的属性我们就可以拿到一个实实在在的人。
现在我们要再创建一个狗类,狗就不能打人了,只能咬人,所以我们给狗一个bite方法。
有了狗类,我们还要实例化一只实实在在的狗出来。
然后人和狗就可以打架了。现在我们就来让他们打一架吧!

创建一个狗类

复制代码
class Dog:
role = 'dog'
def __init__(self,name,breed,aggr,blood):
self.name = name
self.breed = 'zangao'
self.aggr = aggr
self.blood = blood
def bite(self,person):
print('%s咬了%s一口' %(self.name,person.name))
person.blood -= self.aggr 
复制代码

 

实例化一只狗出来

flash = Dog('flash','zangao',500,1000)

交互 egon打flash一下

egon.attack(flash)
print(flash.blood)

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

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

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

  • 静态属性就是直接在类中定义的变量
  • 动态属性就是定义在类中的方法

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

>>>id(egg.role)
4341594072
>>>id(Person.role)
4341594072 

而类的动态属性是绑定到所有对象的

>>>egg.attack
<bound method Person.attack of <__main__.Person object at 0x101285860>>
>>>Person.attack
<function Person.attack at 0x10127abf8> 

创建一个对象/实例就会创建一个对象/实例的名称空间,存放对象/实例的名字,称为对象/实例的属性

在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常

小结:

class A:
    age = 18
    sex = '未知'

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

    def show_name(self):
        print(self.name)


Tom = A('Tom', 22)
print(Tom.age)  # Tom对象自己有age属性所以用自己的age属性(对象属性)
print(Tom.sex)  # Tom没有自己的sex属性所以用类的age属性(类属性)
Tom.sex = '男'  # 给Tom对象添加一个sex属性
print(Tom.sex)  # 男
print(A.sex)    # 未知

# 对于类的静态属性(类属性):
    # 可以在后期添加  A.Hobby = '吃'
    # 类名.属性名  调用的就是类中的属性
    # 对象名.属性名  先从自己的命名空间中找属性名,找打就用自己的,找不到就用类中的属性,如果类中也没有就会报错

print(Tom.show_name)  # <bound method A.show_name of <__main__.A object at 0x000001929E507588>>
print(A.show_name)    # <function A.show_name at 0x000001929E508AE8>

# 关于类的动态属性(方法):
    # 不能在后期添加
    # 这个方法本身就存在类中,并不会存在对象的命名空间中。
    # 但是在对象调用类中的方法时,要依赖于自己命名空间中的一个地址簿去类中寻找对应的方法。

# 关于对象的属性:
    # 对象的属性就存放在对象的命名空间中
    # 可以在后期添加 a.hobby = '喝'
    # 只能被对象调用、修改
    # 不能被类调用

 

组合

软件重用的重要方式除了继承之外还有另外一种方式,即:组合,组合指的是,一个类的对象作为另一个类的属性,称为类的组合

圆环是由两个圆组成的,圆环的面积是外面圆的面积减去内部圆的面积。圆环的周长是内部圆的周长加上外部圆的周长。这个时候,我们就首先实现一个圆形类,计算一个圆的周长和面积。然后在"环形类"中组合圆形的实例作为自己的属性来用

from math import pi


class Circle(object):

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

    def area(self):
        """
        :return:计算圆的面积
        """
        return pi * pow(self.r, 2)

    def perimeter(self):
        """
        :return: 圆的周长
        """
        return 2 * pi * self.r


class Ring(object):

    def __init__(self, r_out, r_in):
        self.circle_out = Circle(r_out)  # c1 = Circle(12)
        self.circle_in = Circle(r_in)

    def area(self):
        """
        :return: 圆环的面积
        """
        return self.circle_out.area() - self.circle_in.area()

    def perimeter(self):
        """
        :return: 圆环的周长
        """
        return self.circle_out.perimeter() + self.circle_in.perimeter()


r1 = Ring(10, 5)
print(r1.area())
print(r1.perimeter())

 

学生有自己的生日,学生还有自己的课程。所以学生和生日、课程之间就是一种组合关系。

class Subject:
    def __init__(self, name, time, teacher, price):
        self.name = name
        self.time = time
        self.teacher = teacher
        self.price = price


class Birthday:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day


class Person:
    def __init__(self, name, birthday_obj, subject):
        self.name = name
        self.birth = birthday_obj
        self.subject = subject

my_birth = Birthday(1995,8,8)
Python = Subject('Python','6 month','alex','20000')
xiaoming = Person('xiaoming',my_birth,Python.name)

print(xiaoming.subject)
print(xiaoming.birth.year)

 

人狗大战

class Person:
    role = 'person'

    def __init__(self, name, sex, aggr, blood, money):
        self.name = name
        self.sex = sex
        self.aggr = aggr
        self.blood = blood
        self.money = money

    def attack(self, enemy):
        print("%s 打了一下 %s" % (self.name, enemy.name))
        enemy.blood -= self.aggr
        if enemy.blood == 0:
            print("%s is Game Over!" % (enemy.name))

    def equip(self, weapon):
        self.money -= weapon.price  # 人的钱-武器的价格
        self.weapon = weapon  #给人装备武器

    def user_equip(self, enemy):
        self.blood += self.weapon.back_blood  # 人的血量+武器的回血量
        self.weapon.aggr += self.aggr  # 武器的攻击力+人的攻击力
        self.weapon.hurt(enemy)  # 武器的伤害


class Dog:
    role = 'dog'

    def __init__(self, name, kind, aggr, blood):
        self.name = name
        self.kind = kind
        self.aggr = aggr
        self.blood = blood

    def bite(self, enemy):
        print("%s 咬了 %s 一口" % (self.name, enemy.name))
        enemy.blood -= self.aggr
        if enemy.blood == 0:
            print("%s is Game Over!" % (enemy.name))


class Weapon:

    def __init__(self, name, aggr, back_blood, price):
        self.name = name
        self.aggr = aggr
        self.back_blood = back_blood
        self.price = price

    def hurt(self, enemy):
        enemy.blood -= self.aggr


caidao = Weapon('菜刀', 500, 1000, 200)
Tom = Person('Tom', 'male', 200, 2000, 500)
flash = Dog('flash', '藏獒', 500, 3000)

if Tom.money >= caidao.price:
    Tom.equip(caidao)
    Tom.user_equip(flash)

print(Tom.blood)
print(flash.blood)

 

 

 

 

 

 

posted @ 2017-09-14 16:14  流星之泪  阅读(89)  评论(0)    收藏  举报