python重写带参数的父类方法_学好python拿高薪系列一(8):面向对象进阶

小伙伴们大家好,上一期我们专门分享了python中一个比较难懂的部分,就是闭包与装饰器。有了这部分内容做基础,今天分享的面向对象进阶部分就比较容易懂了。

16af8e6716f4d36f2f59cd72b6d96a79.png

@property 装饰器

还记得在面向对象基础部分,我们讨论的关于python中属性和方法的访问权限问题,我们不建议在实际开发中将属性设置为私有的,但是如果直接将属性暴漏在外界也是有问题的。我们的建议是,像java一样,将属性设置为私有,然后通过装饰器封装getter和setter方法来完成对属性的访问。

class Person(object): def __init__(self, name, age): self._name = name self._age = age # 访问器 - getter方法 @property def name(self): return self._name # 访问器 - getter方法 @property def age(self): return self._age # 修改器 - setter方法 @age.setter def age(self, age): self._age = age def play(self): if self._age <= 16: print('%s正在玩飞行棋.' % self._name) else: print('%s正在玩斗地主.' % self._name)def main(): person = Person('王大锤', 12) person.play() person.age = 22 person.play() # person.name = '白元芳' # AttributeError: can't set attributeif __name__ == '__main__': main()

_slots_魔法

我们知道,python是一门动态语言,支持在程序执行的过程中给对象绑定新的属性和方法,同时又能够再执行过程中解除绑定。而我们是可以限定自定义类型的对象只能绑定某些属性,这就可以用_slots_魔法来实现。

 class Person(object): # 限定Person对象只能绑定_name, _age和_gender属性 __slots__ = ('_name', '_age', '_gender') def __init__(self, name, age): self._name = name self._age = age @property def name(self): return self._name @property def age(self): return self._age @age.setter def age(self, age): self._age = age def play(self): if self._age <= 16: print('%s正在玩飞行棋.' % self._name) else: print('%s正在玩斗地主.' % self._name)def main(): person = Person('王大锤', 22) person.play() person._gender = '男' # AttributeError: 'Person' object has no attribute '_is_gay' # person._is_gay = True

静态方法和类方法

1、和C++中的静态方法一样,静态方法由类名直接调用,多个对象共享访问,同时又不被某一对象所占有。

例如在判断能否组成三角形中,就可以把判断的方法作为静态方法,由类名直接调用。方式就是在判断方法上方用@staticmethod来装饰。

 from math import sqrtclass Triangle(object): def __init__(self, a, b, c): self._a = a self._b = b self._c = c @staticmethod def is_valid(a, b, c): return a + b > c and b + c > a and a + c > b def perimeter(self): return self._a + self._b + self._c def area(self): half = self.perimeter() / 2 return sqrt(half * (half - self._a) * (half - self._b) * (half - self._c))def main(): a, b, c = 3, 4, 5 # 静态方法和类方法都是通过给类发消息来调用的 if Triangle.is_valid(a, b, c): t = Triangle(a, b, c) print(t.perimeter()) # 也可以通过给类发消息来调用对象方法但是要传入接收消息的对象作为参数 # print(Triangle.perimeter(t)) print(t.area()) # print(Triangle.area(t)) else: print('无法构成三角形.')if __name__ == '__main__': main()

2、和静态方法相似,python中也可以定义类方法,在定义时类方法的第一个参数约定为cls,他代表当前类相关的信息的对象(因为类本身也是一个对象),通过这个参数我们可以获取和类相关的信息并且创建出类的对象,同时要在类方法上方用@classmethod来装饰。

例如,使用类方法获取当前系统时间完成数字时钟。

 from time import localtime,time,sleep#通过类方法实现基于当前时间的时钟class Clock(object): def __init__(self,hour=0,minute=0,second=0): self.hour=hour self.minute=minute self.second=second #定义获取当前时间的类方法 @classmethod def now(cls): ctime=localtime(time()) return cls(ctime.tm_hour,ctime.tm_min,ctime.tm_sec) #完成动态始终的过程 def run(self): self.second+=1 if self.second==60: self.second=0 self.minute+=1 if self.minute==60: self.minute=0 self.hour+=1 if self.hour==24: self.hour=0 #打印时间 def printTime(self): return ("%02d:%02d:%02d" %(self.hour,self.minute,self.second))#main1()def main1(): #类方法获取当前系统时间 nowTime=Clock.now() tt=Clock(nowTime.hour,nowTime.minute,nowTime.second) while True: print(tt.printTime()) tt.run() sleep(1)#main2()def main2(): tt = Clock.now() while True: print(tt.printTime()) tt.run() sleep(1)if __name__=="__main__": main2()
9d03b195ab2d4c1b8c5925b74a8c4147.png
98d1dd7dc2f6b8374d07f7ae9b6b2b24.png

类之间的关系

类之间的关系通常分为三种:is-a(继承或泛化)、has-a(关联关系)、use-a(依赖关系)

  • is-a:学生和人的关系、手机和电子产品的关系
  • has-a:部门和员工的关系
  • use-a:司机有一个驾驶行为,其中(参数)用到了汽车,司机和汽车为依赖关系

继承和多态

主类:提供继承信息的,也叫超类和基类。

子类:得到继承信息的,也就派生类或衍生类。

子类除了继承父类的属性和方法,也可以定义自己特有的属性和方法,所以子类比父类通常具有更多的能力,在实际开发中,我们经常会用子类对象去替换父类对象,称之为里氏替换原则。

1、父类

class Person(object):

"""人"""

def __init__(self, name, age):

self._name = name

self._age = age

@property

def name(self):

return self._name

@property

def age(self):

return self._age

@age.setter

def age(self, age):

self._age = age

2、子类,用class 类名(父类名): 完成对父类的继承

class Student(Person): """学生""" def __init__(self, name, age, grade): super().__init__(name, age)#super()完成对父类属性的继承 self._grade = grade @property def grade(self): return self._grade @grade.setter def grade(self, grade): self._grade = grade def study(self, course): print('%s的%s正在学习%s.' % (self._grade, self._name, course))

子类继承了父类的方法后,可以对父类的方法进行更新,我们称之为方法的重写(override)。通过方法的重写我们能让一个方法具有多个版本。当调用经过重写的方法时,不同的子类对象表现出不同的行为,我们即称之为多态(poly-morphism)。

所以就是:

继承->重写父类方法->子类对象调用行为不同->多态

3、案列

from abc import ABCMeta, abstractmethod#抽象类模块class Pet(object, metaclass=ABCMeta): """宠物""" def __init__(self, nickname): self._nickname = nickname @abstractmethod def make_voice(self): """发出声音""" passclass Dog(Pet): """狗""" def make_voice(self): print('%s: 汪汪汪...' % self._nickname)class Cat(Pet): """猫""" def make_voice(self): print('%s: 喵...喵...' % self._nickname)def main(): pets = [Dog('旺财'), Cat('凯蒂'), Dog('大黄')] for pet in pets: pet.make_voice()if __name__ == '__main__': main()

我将Pet类处理成了一个抽象类,所谓抽象类就是不能够创建对象的类,这种类的存在就是专门为了让其他类去继承它。Python从语法层面并没有像Java或C#那样提供对抽象类的支持,但是我们可以通过abc模块的ABCMeta元类和abstractmethod包装器来达到抽象类的效果如果一个类中存在抽象方法那么这个类就不能够实例化(创建对象)。上面的代码中,Dog和Cat两个子类分别对Pet类中的make_voice抽象方法进行了重写并给出了不同的实现版本,当我们在main函数中调用该方法时,这个方法就表现出了多态行为(同样的方法做了不同的事情)。

好了,今天的分享就到这儿了,欢迎持续关注小编相互交流!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值