【python】基础知识巩固(五)

目录

继承和多态

定义:

eg: 

1)在()里面直接加父类名

2)实例化一下Dog和Cat 

3) 继承的第二个好处

4)多态

获取对象信息

使用type()

基本类型

一个变量指向函数或者类

判断是否相同类型 

使用isinstance()

使用dir() 

eg:

实例属性和类属性

练习


继承和多态

定义:

在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)

eg: 

  Animal的class,DogCat类时,就可以直接从Animal类继承:

1)在()里面直接加父类名

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

class Cat(Animal):
    pass

2)实例化一下Dog和Cat 

3) 继承的第二个好处

需要我们对代码做一点改进。你看到了,无论是Dog还是Cat,它们run()的时候,显示的都是Animal is running...,符合逻辑的做法是分别显示Dog is running...Cat is running...,因此,对DogCat类改进如下:(引出多态)

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

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

class Cat(Animal):

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

cat = Cat()
cat.run()

4)多态

我们就获得了继承的另一个好处:多态。 

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

获取对象信息

使用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'>

判断是否相同类型 

>>> type(123)==type(456)
True
>>> type(123)==int
True
>>> type('abc')==type('123')
True
>>> type('abc')==str
True
>>> type('abc')==type(123)
False


>>> import types
>>> def fn():
...     pass
...
>>> type(fn)==types.FunctionType
True
>>> type(abs)==types.BuiltinFunctionType
True
>>> type(lambda x: x)==types.LambdaType
True
>>> type((x for x in range(10)))==types.GeneratorType
True

使用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

 我们总是优先使用isinstance()判断类型,可以将指定类型及其子类都包含。

使用dir() 

如果要获得一个对象的所有属性和方法,可以使用dir()函数,

它返回一个包含字符串的list

eg:

比如,获得一个str对象的所有属性和方法:

>>> dir('ABC')
['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']

问题来了:这些__xxx__是什么来的? 

 类似__xxx__的属性和方法在Python中都是有特殊用途的,

比如__len__方法返回长度。在Python中,如果你调用len()函数试图获取一个对象的长度,实际上,在len()函数内部(__len__就是等价于len())

 剩下的都是普通属性或方法,比如lower()

>>> 'ABC'.lower()
'abc'

仅仅把属性和方法列出来是不够的,配合获取getattr()设置setattr()以及判断有无hasattr(),我们可以直接操作一个对象的状态:

>>> class MyObject(object):
...     def __init__(self):
...         self.x = 9
...     def power(self):
...         return self.x * self.x
...
>>> obj = MyObject()
>>> hasattr(obj, 'x') # 有属性'x'吗?
True
>>> obj.x
9
>>> hasattr(obj, 'y') # 有属性'y'吗?
False
>>> setattr(obj, 'y', 19) # 设置一个属性'y'
>>> hasattr(obj, 'y') # 有属性'y'吗?
True
>>> getattr(obj, 'y') # 获取属性'y'
19
>>> obj.y # 获取属性'y'
19

如果试图获取不存在的属性,会抛出AttributeError的错误:

>>> getattr(obj, 'z') # 获取属性'z'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'MyObject' object has no attribute 'z'

可以传入一个default参数,如果属性不存在,就返回默认值:

>>> getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404
404

实例属性和类属性

由于Python是动态语言,根据类创建的实例可以任意绑定属性。

给实例绑定属性的方法是通过实例变量,或者通过self变量:

class Student(object):
    def __init__(self, name):
        self.name = name

s = Student('Bob')
s.score = 90

 但是,如果Student类本身需要绑定一个属性呢?可以直接在class中定义属性,这种属性是类属性,归Student类所有:

class Student(object):
    name = 'Student'

完整代码:

相当于默认名为Student

>>> 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

练习

为了统计学生人数,可以给Student类增加一个类属性,每创建一个实例,该属性自动增加:

class Student(object):
    count = 0
    def __init__(self, name):
        self.name = name
        self.__set_count()
 
    def __set_count(self):
        Student.count += 1
 
if Student.count != 0:
    print('测试失败!')
else:
    bart = Student('Bart')
    if Student.count != 1:
        print('测试失败!')
    else:
        lisa = Student('Bart')
        if Student.count != 2:
            print('测试失败!')
        else:
            print('Students:', Student.count)
            print('测试通过!')

猜你喜欢

转载自blog.csdn.net/qq_62932195/article/details/122144731