Python语法基础-函数和类 (2)

面向对象编程的一个重要特点就是数据封装,比如在上面例子中,Dog类的每个实例都有weight和color,我们可以直接在Dog类的内部定义访问数据的函数,这样,就把“数据”给封装起来了。这些封装数据的函数是和Dog类本身是关联起来的,我们称之为类的方法:

class Dog(object): def __init__(self, weight, color): self.weight = weight self.color = color def print_dog(self): print('%s: %s' % (self.weight, self.color))

我们从外部看Dog类,就只需要知道,创建实例需要给出weight和color,而如何打印,都是在Dog类的内部定义的,这些数据和逻辑被“封装”起来了,调用很容易,但却不用知道内部实现的细节。

(3). 访问限制

从前面Dog类的定义来看,外部代码还是可以自由地修改一个实例的weight、color属性,我们可以设置内部属性不被外部访问:

class Dog(object): # 加下划线 def __init__(self, weight, color): self.__weight = weight self.__color = color def print_dog(self): print('%s: %s' % (self.__weight, __self.color)) huskey = Dog(60, 'green') print(huskey.__name) # 无法再访问属性,会出错

但是如果外部代码需要获取weight、color属性呢?-> 添加get_weight、get_color方法

class Dog(object): ... def get_weight(self): return self.__weight def get_color(self): return self.__color

如果又要允许外部代码修改weight、color怎么办?->添加set_weight、set_color方法

class Dog(object): ... def set_weight(self,weight): self.__weight = weight def set_color(self): self.__color = color

为什么要费这么大周折呢?之前不是可以直接husky.weight=10直接改吗
因为在方法中,可以对参数做检查,避免传入无效的参数:

class Dog(object): ... def set_weight(self,weight): if 0<=weight<=100: self.__weight = weight else: raise ValueError('Bad weight') (4). 获取对象信息 # type():判断对象类型 type([1,2,3]) type('abc') == str type(huskey) # isinstance(): 一个对象是否属于某种类型 isinstance(h, husky) isinstance(h, cat) # dir() 获取一个对象的所有属性和方法 dir('ABC') dir('huskey') 1.2. 继承和多态

继承就是:父类和子类之间的交互关系

(1)为什么要用继承?

最大的好处是子类获得了父类的全部功能

class Animal(object): def run(self): print('Animal is running...') # Dog继承父类Animal,并且自动拥有run属性,可以在Dog对象中直接调用 class Dog(Animal): pass # 子类可以自己增加一些方法(eat),同时也可以重写父类的方法(run)---》这就是多态 class Cat(Animal): def run(self): print('Dog is running...') def eat(self): print('Eating meat...') (2)什么是多态?

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

C是dog,C也是animal
D是animal,但你不能说D也是Dog

# 首先创建对象并查看对象类型 a = list() # a是list类型 isinstance(a, list) # true b = Animal() # b是Animal类型 isinstance(b, Animal) # true c = Dog() # c是Dog类型 isinstance(c, Dog) # true # C既是Dog也是Animal isinstance(c, Animal) # true # 反过来就错了 isinstance(b, Dog) # false (3)那么为题来了。这样设置成多态有什么好处呢?

任何依赖父类作为参数的函数或者方法都可以不加修改地正常运行,原因就在于多态。

当我们需要传入Dog、Cat、Tortoise……时,我们只需要接收Animal类型就可以了,因为Dog、Cat、Tortoise……都是Animal类型,然后,按照Animal类型进行操作即可。由于Animal类型有run()方法,因此,传入的任意类型,只要是Animal类或者子类,就会自动调用实际类型的run()方法,这就是多态的意思

对于一个变量,我们只需要知道它是Animal类型,无需确切地知道它的子类型,就可以放心地调用run()方法,而具体调用的run()方法是作用在Animal、Dog、Cat还是Tortoise对象上,由运行时该对象的确切类型决定

def run_twice(animal): animal.run() run_twice(Animal()) # 调用animal的run run_twice(Dog()) # 调用dog的run run_twice(Cat()) # 调用cat的run 2. 面向对象高级编程 (1). __slots__的使用

动态绑定允许我们在程序运行的过程中动态给class加上功能, 但是,如果我们想要限制实例的属性怎么办?比如,只允许对Student实例添加name和age属性。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpsdgf.html