面向对象
面向对象三大特点
- 封装:既可对数据结构进行封装,又可对处理数据的方法进行封装
- 继承:强调的父子类的关系
- 多态:不同对象调用相同的方法,会有不同的响应
类的继承
-
相关概念
- 继承:父类的属性和方法,子类直接拥有,称为继承
- 派生:子类在父类的基础上衍生出新的特征(属性和行为)
- 总结:其实他们是一回事,只是描述问题的侧重点不同(继承强调相同点,派生强调不同点)
-
继承语法
# class Animal(object): # 当没有指定父类时,默认继承object class Animal: def __init__(self, name): self.name = name def eat(self): print('小动物喜欢一天到晚出个不停') # 继承自Animal class Dog(Animal): pass d = Dog('旺财') # 可以拥有父类的方法 d.eat() # 也可以拥有父类的属性 print(d.name)
-
派生示例
class Animal: def run(self): print('小动物喜欢成天跑个不停') class Cat(Animal): def eat(self): print('猫喜欢吃老鼠') tom = Cat() tom.run() # 多出来的行为 tom.eat() # 多出来的属性 tom.color = '蓝色' print(tom.color)
-
重写方法
- 若父类的方法完全不合适,可以进行覆盖重写
- 若父类的方法不够完善,可以添枝加叶进行完善
- 示例:
class Animal: def eat(self): print('小动物一天到晚的出个不停') def run(self): print('小动物一天到晚的四处连跑') class Cat(Animal): # 父类的方法完全不合适,覆盖重写 def run(self): print('俺走的是猫步') # 父类的方法部分合适,需要添加内容进行完善 def eat(self): # 保留父类的内容,不建议使用此方式 # Animal.eat(self) # super(Cat, self).eat() # 类名及self可以不传 super().eat() print('不过俺喜欢吃鱼') jiafei = Cat() jiafei.run() jiafei.eat()
-
多继承:一个子类可以拥有多个父类
class A: def eat(self): print('eat func in class A') class B: def eat(self): print('eat func in class B') class C(A, B): def eat(self): # 这种方案是默认的继承顺序进行选择的父类方法 # super().eat() # 人为指定调用某个父类的方法 B.eat(self) c = C() c.eat()
访问权限
-
权限
- 公有的:类中的普通的属性和方法,默认都是公有的;可以在类内、类外、子类中使用
- 私有的:定义时在前面添加两个'_',就变成了私有的;只能在类内使用,不能在类外及子类中使用
-
示例:
class Person: def __init__(self, name): self.name = name self.__age = 20 def eat(self): print('民以食为天') def __test(self): print('__test') xiaoming = Person('小明') print(xiaoming.name) xiaoming.eat() # 不能在类外使用 print(xiaoming.__age) xiaoming._Person__test() print(xiaoming.dict) # 尽管可以这样访问私有属性,但是强烈建议不要这样使用 print(xiaoming._Person__age) class Man(Person): def introduce(self): # 不能在子类中使用 # print(self.__age) print('我叫{}'.format(self.name)) self.eat() m = Man('诸葛') m.introduce()
类属性
-
说明:定义类时,写在方法外的属性,通常会写在类的开头,这样的属性称为类属性
-
示例:
class Person: # 类属性,通过类名访问,属于整个类,而不是某个对象 # nation = '中国' # 限制可以使用的属性,提高访问的效率 # 也可以提高访问速度,减少内存使用 __slots__ = ('name', 'age', 'nation') def __init__(self, name): self.name = name self.nation = 'china' p1 = Person('小明') p2 = Person('小红') print(p1.name, p2.name) print(Person.nation) # p1.nation = 'china' print(p1.nation) print(p2.nation) # print(Person.nation) p1.age = 20 # p1.height = 180 # 特殊的类属性 # 表示类名的字符串 print(Person.__name__) # 表示父类构成的元组 print(Person.__bases__) # 存储类的相关信息 print(Person.__dict__) # 限制可以使用的属性 print(Person.__slots__)
类方法
-
说明:
- 定义时使用
classmethod
装饰器装饰的方法 - 使用时通过类名调用
- 定义时使用
-
作用:
- 可以创建对象或者简洁的创建对象
- 对外提供简单易用的接口
-
示例1:创建对象
class Person: def eat(self): print('我喜欢吃麻辣烫,不要麻椒和辣椒') @classmethod def test(cls): print(cls) print('类方法') # 创建对象,或者简洁的创建对象 @classmethod def create(cls): p = cls() p.age = 1 return p p1 = Person() p1.eat() # 通过类名调用 Person.test() # 创建或简洁的创建对象 p2 = Person.create() print(type(p2))
-
示例2:提供接口
class Number: def __init__(self, num1, num2): self.num1 = num1 self.num2 = num2 def add(self): return self.num1 + self.num2 def sub(self): return self.num1 - self.num2 def mul(self): return self.num1 * self.num2 def div(self): if self.num2 == 0: return None return self.num1 / self.num2 # 对外提供简单易用的接口 @classmethod def pingfanghe(cls, num1, num2): n1 = cls(num1, num1) n12 = n1.mul() n2 = cls(num2, num2) n22 = n2.mul() n3 = cls(n12, n22) return n3.add() he = Number.pingfanghe(3, 4) print(he)
静态方法
-
说明:
- 使用
staticmethod
装饰器装饰的方法(方法没有cls参数) - 通过类名进行调用
- 使用
-
示例:
class Person: @staticmethod def test(): print('static method test') # 创建对象 @staticmethod def create(): p = Person() return p Person.test() p = Person.create() print(p)
-
总结:
- 凡是静态方法完成的功能都可以是类方法完成
- 若方法中没有使用到类名(cls),可以使用静态方法
多态特性
-
定义:不同的对象,调用相同的方法,有不同的响应,称为多态
-
示例:
class Animal: def run(self): pass class Dog(Animal): def run(self): print('狗通常走S型') class Cat(Animal): def run(self): print('猫平时走猫步,偶尔突然加速') def test(obj): obj.run() d = Dog() c = Cat() test(d) test(c)
属性函数
-
说明:将成员方法当做属性一样进行访问
-
作用:保护特定属性,或者对特定属性进行处理
-
示例:
class User: def __init__(self, username, password): self.username = username self.__password = password # 该方法可以像成员属性一样访问 @property def password(self): print('有人想查看密码') return '想偷看密码,没门' # return self.__password # 在设置密码时,会自动调用 @password.setter def password(self, password): print('@password.setter', password) self.__password = '加密' + password + '加密' u = User('xiaoming', '111111') # print(u.password()) print(u.password) # 设置密码,会自动调用setter方法 u.password = 'abcde'