Python入门教程[4]-面向对象编程

  • A+
所属分类:python快速入门
摘要这一篇文章会介绍面向对象的思想在python中的应用,面向对象在python的实际应用中还是用得很广泛的,如果之前没有接触过面向对象,可以先看一下,然后在以后的学习中在慢慢理解其中的思想。

了解面向对象的编程

讲之前推荐一篇文章,面向对象圣经,可以把这一篇学完之后再回过去看一下,讲得还是很好的。

下面简单讲一下面向对象编程的思想。

以面向过程思想设计程序时,程序是一条条指令的顺序执行,当指令变得多起来时,它们被分隔成我们先前实验中讲解过的函数。 而面向对象思想则是对象视为程序的组成单元,程序的执行通过调用对象提供的接口完成。

面向对象的四个核心概念:

  • 抽象
  • 封装
  • 继承
  • 多态

下面讲一下这四个概念在python中的应用。不完全按照这四个核心概念来讲。

抽象,封装

我们先看一个简单的类的例子

#创建类
class Foo(object):
    def __init__(self,name):
        self.name = name
    def Bar(self):
        print('Bar')
    def Hello(self):
        print('i am %s' %self.name)

# 根据类Foo创建对象obj
obj = Foo('Dog')
obj.Bar() #执行Bar方法
>> 'Bar'
obj.Hello() #执行Hello方法
>> 'i am Dog'
print(dir(obj))
>> #这个可以看这个对象的方法

上面这个类中,object是Python中所有对象的祖先,它是所有类的基类。 类需要一个初始化方法__init__是Python的初始化方法,注意前后各有两个下划线 _,self指代当前的对象。所以在类的实例化的时候,需要Foo('Dog'),之后在类中就是要self来间接调用被封装的内容。

为了看出类有什么用处,我们来看一个练习:游戏人生程序

1、创建三个游戏人物,分别是:

苍井井,女,18,初始战斗力1000
东尼木木,男,20,初始战斗力1800
波多多,女,19,初始战斗力2500

2、游戏场景,分别:

草丛战斗,消耗200战斗力
自我修炼,增长100战斗力
多人游戏,消耗500战斗力

可以看到这个例子中需要创建一个类,初始化的时候需要名字,性别,年龄和战斗力。然后这个类里面有三个方法,分别是草丛战斗,自我修炼和多人游戏,可以参考下面的代码。

class practice_02(object):
    def __init__(self,name,gender,age,combat_effectiveness):
        self.name = name
        self.gender = gender
        self.age = age
        self.combat_effectiveness = combat_effectiveness
    @property
    def print_message(self):
        print('%s,%s,%s,战斗力为%s' %(self.name,self.gender,self.age,self.combat_effectiveness))
    def grass_battle(self):
        self.combat_effectiveness = self.combat_effectiveness-200
    def self_practice(self):
        self.combat_effectiveness = self.combat_effectiveness+100
    def multiplayer_game(self):
        self.combat_effectiveness = self.combat_effectiveness-500

player = practice_02('仓井井','女','18',1000)
player.print_message
player.grass_battle()#参加一次草丛战斗
player.print_message
player.self_practice()#参加一次自我修炼
player.print_message
player.multiplayer_game()#参加一次多人游戏
player.print_message

继承

继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容。

例如:

  • 猫可以:喵喵叫、吃、喝、拉、撒

  • 狗可以:汪汪叫、吃、喝、拉、撒

如果我们要分别为猫和狗创建一个类,那么就需要为实现他们所有的功能,如下所示:

class 猫:
    def 喵喵叫(self):
        print '喵喵叫'
    def 吃(self):
        # do something
    def 喝(self):
        # do something
    def 拉(self):
        # do something
    def 撒(self):
        # do something

class 狗:
    def 汪汪叫(self):
        print '喵喵叫'
    def 吃(self):
        # do something
    def 喝(self):
        # do something
    def 拉(self):
        # do something
    def 撒(self):
        # do something

上述代码不难看出,吃、喝、拉、撒是猫和狗都具有的功能,而我们却分别的猫和狗的类中编写了两次。所以有了继承的概念,我们从猫和狗身上提取共同的特点,来进行编写,如下所示:

class Animal(object):
    def eat(self):
        print('%s 吃' %self.name)
    def drink(self):
        print('%s 喝' %self.name)
    def shit(self):
        print('%s 拉' %self.name)
    def pee(self):
        print('%s 撒' %self.name)

class Cat(Animal):
    def __init__(self,name):
        self.name = name
    def cry(self):
        print('喵喵叫')

cat = Cat('小猫猫')
cat.eat()
cat.cry()
cat.pee()

所以,对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。

静态变量

静态变量是可以直接从类访问的,不需要实例化对象就可以访问。还是以上面动物的例子为例,假如说那些动物都来自动物园('zoo'),我们可以在Animal中加一个静态变量,一般声明在__init__前面。

class Animal(object):
    owner = 'zoo'
    def eat(self):
        print('%s 吃' %self.name)
    def drink(self):
        print('%s 喝' %self.name)
    def shit(self):
        print('%s 拉' %self.name)
    def pee(self):
        print('%s 撒' %self.name)

class Cat(Animal):
    def __init__(self,name):
        self.name = name
    def cry(self):
        print('喵喵叫')

cat = Cat('小猫猫')
print(cat.owner)
>> 'zoo'
print(Animal.owner) #不需要实例化,可以直接访问
>> 'zoo'

类方法

类方法和静态变量类似,它也可以通过类名直接访问,类方法用@classmethd装饰,类方法中可以访问类的静态变量。

class Animal(object):
    owner = 'zoo'
    def owner_name(cls):
        return cls.owner
    def eat(self):
        print('%s 吃' %self.name)
    def drink(self):
        print('%s 喝' %self.name)
    def shit(self):
        print('%s 拉' %self.name)
    def pee(self):
        print('%s 撒' %self.name)

class Cat(Animal):
    def __init__(self,name):
        self.name = name
    def cry(self):
        print('喵喵叫')

cat = Cat('小猫猫')
print(cat.owner_name())
>> 'zoo'
print(Animal.owner_name(Animal))
>> 'zoo'

注意类方法的第一个参数传入的是类对象,而不是实例对象,所以是 cls

我们再来看一个例子

class Foo(object):
    def __init__(self,name):
        self.name = name
    def ord_func(self):
        #定义普通方法
        print('普通方法')
    @classmethod
    def class_func(cls):
        #定义类方法
        print('类方法')
    @staticmethod
    def static_func():
        #定义静态方法
        print('静态方法')

f = Foo('江苏')
f.ord_func()
>> '普通方法'
#调用类方法
Foo.class_func()
>> '类方法'
#调用静态方法
Foo.static_func()
>> '静态方法'

property

在Python中,property可以将方法变成一个属性来使用,借助property可以实行Python风格的getter/setter,即可以通过property获得和修改对象的某一个属性。

我们就看下面的例子里理解吧。

class goods(object):
    def __init__(self):
        #原价
        self.original_price = 100
        #折扣
        self.discount = 0.8

    @property
    def price(self):
        #实际价格=原价*折扣
        new_price = self.original_price*self.discount
        return new_price

    @price.setter
    def price(self,value):
        self.original_price = value
    @price.deleter
    def price(self,value):
        del self.original_price

obj = goods()
print(obj.price) #查看商品的价格
>> 80
obj.price = 200 #设置商品的价格
print(obj.price) #查看现在商品的价格
>> 160
#del obj.price 删除商品价格

类的特殊成员__doc__

这里我们讲一个类的特殊成员,__doc__,这个是输出类的描述信息,什么意思呢,可以看下面的例子。

class describe(object):
    """可以显示类的说明信息
    """
    def __init__(self,name):
        self.name = name
    def speak_name(self):
        return self.name

des = describe('dog')
des.__doc__
>> '可以显示类的说明信息\n'

所以说我们可以使用__doc__来看一下类的说明的文档。

类的特殊成员__repr__

repr是用来指定输出的格式的。

我们可以看一下下面的这个例子,如果直接打印类,打印出来的是地址,这个时候我们可以使用repr来定义输出的格式。

  1. In [1]: class Test(object):
  2.    ...:     def __init__(self, value='hello, world!'):
  3.    ...:         self.data = value
  4.    ...:
  5. In [2]: t = Test()
  6. In [3]: t
  7. Out[3]: <__main__.Test at 0x108844e48>
  8. In [4]: class TestNew(object):
  9.    ...:     def __init__(self, value='hello, world!'):
  10.    ...:         self.data = value
  11.    ...:     def __repr__(self):
  12.    ...:         return 'This is __repr__:{0}'.format(self.data)
  13.    ...:
  14. In [5]: tn = TestNew()
  15. In [6]: tn
  16. Out[6]: This is __repr__:hello, world!

 

类的特殊成员还有__init__,__dict__(返回类对象中的所有成员)等等,详细的可以去看说明文档。

  • 微信公众号
  • 关注微信公众号
  • weinxin
  • QQ群
  • 我们的QQ群号
  • weinxin
王 茂南

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: