Python笔记-类和实例、继承和多态

类和实例

1、通过class关键字创建一个类

class Student(object):
    pass

(object)表示该类是从哪个类继承下来的,通常,如果没有合适的继承类,就使用object类,这是所有类都会继承的类。

2、创建实例是通过类名+()实现的。如果类有必须绑定的属性,则在类内需要定义一个特殊的__init__方法(这个方法名不能改成其他的,前后各两条横线)。

比如学生类必须有姓名和分数属性:

class Student(object):

    def __init__(self, name, score):
    #self指向正在被创建的对象本身
        self.name = name
        self.score = score

有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去

>>> Bart = Student('Bart Simpson', 59)

要在类里面定义一个方法,除了第一个参数是self外,其他和普通函数一样。

要调用类里面一个方法,只需要在实例变量上直接调用,除了self不用传递,其他参数正常传入。

class Student(object):

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

    def print_score(self):
        print('%s: %s' % (self.name, self.score))

>>> Bart.print_score()
Bart Simpson: 59

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量。

class Student(object):

    def __init__(self, name, score):
        self.__name = name
        self.__score = score

    def print_score(self):
        print('%s: %s' % (self.__name, self.__score))

此时已经无法从外部访问实例变量.__name和实例变量.__score了。
如果外部代码要获取name和score怎么办?可以给Student类增加get_name和get_score这样的方法。

class Student(object):
    ...

    def get_name(self):
        return self.__name

    def get_score(self):
        return self.__score

如果又要允许外部代码修改score怎么办?可以再给Student类增加set_score方法:

class Student(object):
    ...

    def set_score(self, score):
        if 0 <= score <= 100:
            self.__score = score
        else:
            raise ValueError('bad score')

需要注意的是,在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用__name__、__score__这样的变量名。

3、如果我们想要限制实例的属性怎么办?比如,只允许对Student实例添加name和age属性。

为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性:

class Student(object):
    __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称

>>> s = Student() # 创建新的实例
>>> s.name = 'Michael' # 绑定属性'name'
>>> s.score = 99 # 绑定属性'score'
(出错了,没有score属性)

使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的。除非在子类中也定义__slots__,这样,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__。

继承和多态

1、一个名为Animal的class,有一个run()方法

class Animal(object):
    def run(self):
        print('Animal is running...')

编写Dog和Cat类时,就可以直接从Animal类继承:

class Dog(Animal):
    pass

class Cat(Animal):
    pass

可以对子类增加一些方法,比如Dog类:

class Dog(Animal):

    def run(self):
        print('Dog is running...')

    def eat(self):
        print('Eating meat...')

当子类和父类都存在相同的run()方法时,我们说,子类的run()覆盖了父类的run(),在代码运行的时候,总是会调用子类的run()。

2、在继承关系中,如果一个实例的数据类型是某个子类,那它的数据类型也可以被看做是父类。但是,反过来就不行。

3、多继承

class Parrot(Bird):
    pass

class Ostrich(Bird):
    pass

要给动物再加上Runnable和Flyable的功能,只需要先定义好Runnable和Flyable的类:

class Runnable(object):
    def run(self):
        print('Running...')

class Flyable(object):
    def fly(self):
        print('Flying...')

对于需要Runnable功能的动物,就多继承一个Runnable,例如Dog:

class Dog(Mammal, Runnable):
    pass

对于需要Flyable功能的动物,就多继承一个Flyable,例如Bat:

class Bat(Mammal, Flyable):
    pass

鸭子类型

1、对于静态语言来说,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类,否则将无法调用run()方法。

2、对于Python这样的动态语言来说,则不一定需要传入Animal类型。我们只需要保证传入的对象有一个run()方法就可以了。

3、这就是动态语的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。

class Quote():
    def __init__(self, person, words):
        self.person = person
        self.words = words
    def who(self):
        return self.person
    def says(self):
        return self.words + '.'

class QuestionQuote(Quote):
    def says(self):
        return self.words + '?'

class ExclamationQuote(Quote):
    def says(self):
        return self.words + '!'

hunter = Quote('Elmer Fudd', "I'm hunting wabbits")
hunted1 = QuestionQuote('Bugs Bunny', "What's up, doc")
hunted2 = ExclamationQuote('Daffy Duck', "It's rabbit season")

print(hunter.who(), 'says:', hunter.says())
print(hunter1.who(), 'says:', hunter1.says())
print(hunter2.who(), 'says:', hunter2.says())

结果:
Elmer Fudd says: I'm hunting wabbits.
Bugs Bunny says: What's up, doc?
Daffy Duck says: It's rabbit season!

三个不同版本的says()为上面三种类提供了不同的响应方式,这是面向对象的语言中多态的传统形式

Python中,无论对象的种类是什么,只要包含 who() 和says(),你便可以调用它。我们再来定义一个 BabblingBrook 类,它与我们之前的猎人猎物(Quote 类的后代)什么的没有任何关系:

class BabblingBrook():
    def who(self):
        return 'Brook'
    def says(self):
        return 'Babble'

def who_says(obj):
    print(obj.who(), 'says', obj.says())

brook = BabblingBrook()

print(who_says(hunter))
print(who_says(hunter1))
print(who_says(hunter2))
print(who_says(brook ))

结果:
Elmer Fudd says I'm hunting wabbits.
Bugs Bunny says What's up, doc?
Daffy Duck says It's rabbit season!
Brook says Babble
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值