Python中的类与实例对象

类和对象实例

类是图纸,实例是成品,实例是照着图纸生产的,图纸设计的特征,成品都有。写代码本质上是画图纸,实例就是一个个按图纸生产好的零部件为我们所用。

基础

定义类的方式

class Student(object):
    pass

创建实例的方式

>>> bart = Student()
>>> bart
<__main__.Student object at 0x10a67a590>
>>> Student
<class '__main__.Student'>

__init__方法
在创建类的时候绑定属性,self表示创建的实例本身

class Student(object):

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

和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量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))

访问限制
类的某些属性不想被外部访问,声明时在变量前加__表示私有变量

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 = Student('Bart Simpson', 59)
>>> bart.__name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute '__name'

当然如果你还是想访问,可以按照我的规则来,我给你提供set和get函数给你存取实例,防止你乱改乱访问。

*不要给一个私有属性赋值,python会给你创建一个相应的不一样的属性

>>> bart = Student('Bart Simpson', 59)
>>> bart.get_name()
'Bart Simpson'
>>> bart.__name = 'New Name' # 设置__name变量!
>>> bart.__name
'New Name'

继承和多态

面向对象编程,都要讨论继承与多态的属性。

继承

类分父类和子类,子类继承父类,子类拥有父类的所有属性,并且在此之上添加自己独有的属性,就比如汽车的图纸,父类的图纸只有汽车的框架和用到的基础零件,至于子类就可以在此之上发扬自己的特色。越野,面包,超跑,你自己二次设计。

简单的继承写法

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

class Cat(Animal):
    pass


dog = Dog()
dog.run()

cat = Cat()
cat.run()

#result
Animal is running...
Animal is running...

覆盖父类的方法

class Dog(Animal):

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

class Cat(Animal):

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

#result
Dog is running...
Cat is running...

多态

多态是个字面意思上不太好理解的词。
多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。
定义一个class实际上就是定义了类似于 list,str一样的数据类型,用isinstance()可以判断某一个变量是否属于某一数据类型:

a = list() # a是list类型
b = Animal() # b是Animal类型
c = Dog() # c是Dog类型


>>> isinstance(a, list)
True
>>> isinstance(b, Animal)
True
>>> isinstance(c, Dog)
True

实际上c也是Animal类型的

>>> isinstance(c, Animal)
True

用法

def run_twice(animal):
    animal.run()
    animal.run()

>>> run_twice(Animal())
Animal is running...
Animal is running...

>>> run_twice(Dog())
Dog is running...
Dog is running...

新增一个Animal的子类,不必对run_twice()做任何修改,实际上,任何依赖Animal作为参数的函数或者方法都可以不加修改地正常运行,原因就在于多态。

“开闭”原则
对扩展开放:允许新增Animal子类;
对修改封闭:不需要修改依赖Animal类型的run_twice()等函数。

鸭子类型
python不严格遵守继承,传入的对象有相应的方法就可以运行。

获取对象数据

type()

可以用type()来判断基本类型,函数和类:

>>> type(123)
<class 'int'>

>>> type('str')
<class 'str'>

>>> type(None)
<type(None) 'NoneType'>

>>> type(abs)
<class 'builtin_function_or_method'>

>>> type(a)
<class '__main__.Animal'>

isinstance()

对于class的继承关系来说,使用type()就很不方便。我们要判断class的类型,可以使用isinstance()函数。

object -> Animal -> Dog -> Husky
>>> a = Animal()
>>> d = Dog()
>>> h = Husky()

>>> isinstance(h, Husky)
True
>>> isinstance(h, Dog)
True
>>> isinstance(h, Animal)
True
>>> isinstance(d, Dog) and isinstance(d, Animal)
True
>>> isinstance(d, Husky)
False

# 能用type()判断的基本类型也可以用isinstance()判断
>>> isinstance('a', str)
True
>>> isinstance(123, int)
True
>>> isinstance(b'a', bytes)
True
>>> isinstance([1, 2, 3], (list, tuple))
True
>>> isinstance((1, 2, 3), (list, tuple))
True

类属性与实例属性

>>> class Student(object):
...     name = 'Student'
...
>>> s = Student() # 创建实例s
>>> print(s.name) # 打印name属性,因为实例并没有name属性,所以会继续查找class的name属性
Student
>>> print(Student.name) # 打印类的name属性
Student
>>> s.name = 'Michael' # 给实例绑定name属性
>>> print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
Michael
>>> print(Student.name) # 但是类属性并未消失,用Student.name仍然可以访问
Student
>>> del s.name # 如果删除实例的name属性
>>> print(s.name) # 再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了
Student

猜你喜欢

转载自blog.csdn.net/YPJMFC/article/details/79008234