本文实例讲述了Python面向对象程序设计类的多态用法。分享给大家供大家参考,具体如下:
多态
1、多态使用
一种事物的多种体现形式,举例:动物有很多种
注意: 继承是多态的前提
函数重写就是多态的体现形式
演示:重写Animal类
第一步:先定义猫类和老鼠类,继承自object,在其中书写构造方法和eat方法
第二步: 抽取Animal父类,定义属性和eat方法,猫类与老鼠类继承即可
第三步: 定义人类,在其中分别定义喂猫和喂老鼠的方法
第四步:使用多态,将多个喂的方法提取一个。
# 测试类 from cat import Cat from mouse import Mouse from person import Person ''' 多态: 一种事物的多种状态 需求:人可以喂任何一种动物 ''' #创建猫和老鼠的对象 tom = Cat("tom") jerry = Mouse("jerry") #调用各自的方法 tom.eat() jerry.eat() #定义了一个有name属性和eat方法的Animal类,让所有的动物类都继承自Animal. #定义一个人类,可以喂猫和老鼠吃东西 per = Person() #per.feedCat(tom) #per.feedMouse(jerry) #思考:人要喂100种动物,难道要写100个feed方法吗"htmlcode">#animal.py文件中的动物类 class Animal(object): def __init__(self, name): self.name = name def eat(self): print(self.name + "吃")#cat.py文件中的猫类 class Cat(Animal): def __init__(self, name): #self.name = name super(Cat,self).__init__(name)#mouse.py中的老鼠类 class Mouse(Animal): def __init__(self, name): #self.name = name super(Mouse,self).__init__(name)#person.py中的人类 class Person(object): def feedAnimal(self, ani): print("给你食物") ani.eat()2、对象属性与类属性
对象属性和类属性的区别:
a.定义的位置不同,类属性是直接在类中的属性,对象属性是在定义在构造方法中的属性;
b.对象属性使用对象访问,类属性使用类名访问;
c.在内存中出现的时机不同[类属性随着类的加载而出现,对象属性随着对象的创建而出现];
d.优先级不同,对象属性的优先级高于类属性。
class Person(object): #1.定义位置 #类属性:直接定义在类中的属性 name = "person" def __init__(self, name): #对象属性:定义在构造方法中的属性 self.name = name #2.访问方式 print(Person.name) per = Person("tom") #对象属性的优先级高于类属性 print(per.name) #动态的给对象添加对象属性 per.age = 18 #只针对当前对象生效,对于类创建的其他对象没有作用 print(Person.name) per2 = Person("lilei") #print(per2.age) #没有age属性 #删除对象中的name属性,再调用会使用到同名的类属性 del per.name print(per.name) #注意事项:不要将对象属性与类属性重名,因为对象属性会屏蔽掉类属性,但是当删除对象属性之后,再使用就能使用到类属性了.输出:
person
tom
person
person3、动态添加属性和方法
正常情况下,我们定义了一个class,创建一个class的实例后,我们可以给该实例绑定任何的的属性和方法,这就是动态语言的灵活性。
python语言的特点:灵活。
这里说的动态添加属性和方法主要指的是关于
slots
函数的使用from types import MethodType #定义一个空类 ''' class Person(): pass ''' class Person(object): __slots__ = ("name","age","speak","hobby") pass # 动态添加属性[体现了动态语言的特点:灵活性] per = Person() per.name = "tom" print(per.name) #动态添加方法 def say(self): print("my name is "+ self.name) per.speak = say per.speak(per) #这样实现不好,所以引入MethodType def hobby(self): print("my hobby is running") per.hobby = MethodType(hobby,per) per.hobby()输出:
tom
my name is tom
my hobby is running但是,给一个实例绑定的方法对另外一个实例是不起作用的。
为了给所有的实例都绑定方法,可以通过给class绑定方法
#动态添加方法 def say(self,name): self.name = name print("my name is "+ self.name) Person.speak = say per2 = Person() per2.speak('hh')输出:
my name is hh
给class绑定方法后,所有的实例均可调用。
4、slots
通常情况下,上面的say方法可以直接定义在class中,但动态绑定允许我们在程序在运行的过程中动态的给class添加功能,这在静态语言中很难实现。
如果我们想限制实例的属性怎么办"htmlcode">
class Person(object): __slots__=("name","age") #[不想无限制的任意添加属性] #比如,只允许给对象添加name, age属性 #解决:定义类的时候,定义一个特殊的属性(__slots__),可以限制动态添加的属性范围 per = Person() per.height = 170 print(per.height)这样做会报错
AttributeError: 'Person' object has no attribute 'height'
使用slots的时候需要注意,slots定义的属性仅仅对当前类的实例起作用,对继承的子类是不起作用的。
除非在子类中也定义slots,这样子类实例允许定义的属性就是自身的slots加上父类的slots。
总结:
__slots__
:语法:
__slots__ = (属性名1,属性名2,...)作用:
限制类的属性名
注意:当子类没有添加slots时,子类继承父类的时候,它的属性名不受父类的影响
若子类中也添加slots,子类的限制应该是父类的slots与子类slots的并集
5、@property
绑定属性时,如果我们直接把属性暴露出去,虽然写起来简单,但是没有办法检查参数,导致可以随意的更改。
比如:
p = Person() p.age = -1这显然不合常理,为了限制age的范围,我们可以通过
setAge()
的方法来设置age,再通过getAge()
的方法获取age,这样在setAge()
中就可以检查输入的参数的合理性了。class Person(object): def __init__(self, name, age): # 属性直接对外暴露 # self.age = age # 限制访问 self.__age = age self.__name = name # self.__name = name def getAge(self): return self.__age def setAge(self, age): if age < 0: age = 0 self.__age = age # 通过@property和@age.setter改变原来的get/set方法 # 方法名为受限制的变量去掉双下划线 # 相当于get方法 @property def age(self): return self.__age # 相当于set的方法 @age.setter # 去掉下划线.setter def age(self, age): if age < 0: age = 0 self.__age = age @property def name(self): return self.__name @name.setter def name(self, name): self.__name = name per = Person("lili", 18) # 属性直接对外暴露 # 不安全,没有数据的过滤 # per.age = -10 # print(per.age) # 使用限制访问,需要自己写set和get的方法才能访问 # 劣势:麻烦,代码不直观 # 思考问题:如果我就想使用对象"."的方式访问对象的私有属性,怎么办"."语法 per.age = 80 # 相当于调用setAge print(per.age) # 相当于调用getAge print(per.name)输出:
80
liliproperty
总结语法:
针对私有化的属性添加的。
@property def 属性名(self): return self.__属性名@属性名.setter def 属性名(self, 值): #业务逻辑处理 self.属性名 = 值总结:
a.装饰器(decorator)可以给函数动态加上功能,对于类的方法,装饰器一样起作用,python内置的@property装饰器就是负责把一个方法变成属性调用的。
b.@property的实现比较复杂,我们先考虑如何使用,把一个getter方法变成属性,只需要加上@property就可以了,此时@property本身又创建了另一个装饰器@属性setter,负责把一个setter方法变成属性赋值.
c.@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。6、运算符重载
类可以重载加减运算,打印,函数调用,索引等内置运算,运算符重载使我们的对象的行为与内置函数一样,在python调用时操作符会自动的作用于类的对象,python会自动的搜索并调用对象中指定的方法完成操作。
1、常见运算符重载方法
常见运算符重载方法
方法名 重载说明 运算符调用方式 init 构造函数 对象创建: X = Class(args) del 析构函数 X对象收回 add sub 加减运算 X+Y, X+=Y/X-Y, X-=Y or 运算符| X|Y, X|=Y str_ repr 打印/转换 print(X)、repr(X)/str(X) call 函数调用 X(*args, **kwargs) getattr 属性引用 X.undefined setattr 属性赋值 X.any=value delattr 属性删除 del X.any getattribute 属性获取 X.any getitem 索引运算 X[key],X[i:j] setitem 索引赋值 X[key],X[i:j]=sequence delitem 索引和分片删除 del X[key],del X[i:j] len 长度 len(X) bool 布尔测试 bool(X) lt gt le ge eq ne 特定的比较 依次为XY,X<=Y,X>=Y, X==Y,X!=Y 注释:(lt: less than, gt: greater than, le: less equal, ge: greater equal, eq: equal, ne: not equal ) radd 右侧加法 other+X iadd 实地(增强的)加法 X+=Y(or else add) iter next 迭代 I=iter(X), next() contains 成员关系测试 item in X(X为任何可迭代对象) index 整数值 hex(X), bin(X), oct(X) enter exit 环境管理器 with obj as var: get set delete 描述符属性 X.attr, X.attr=value, del X.attr new 创建 在init之前创建对象# 举例 # 数字和字符串都能相加 #print(1 + 2) #print("1" + "2") # 不同的类型用加法会有不同的解释 class Person(object): def __init__(self, num): self.num = num # 运算符重载 def __add__(self, other): return Person(self.num + other.num) # 方法重写 def __str__(self): return "num = " + str(self.num) # 如果两个对象相加会怎样"_blank" href="//www.jb51.net/Special/684.htm">Python面向对象程序设计入门与进阶教程》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python编码操作技巧总结》及《Python入门与进阶经典教程》希望本文所述对大家Python程序设计有所帮助。
Python,面向对象,类的多态
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
更新日志
- 雨林唱片《赏》新曲+精选集SACD版[ISO][2.3G]
- 罗大佑与OK男女合唱团.1995-再会吧!素兰【音乐工厂】【WAV+CUE】
- 草蜢.1993-宝贝对不起(国)【宝丽金】【WAV+CUE】
- 杨培安.2009-抒·情(EP)【擎天娱乐】【WAV+CUE】
- 周慧敏《EndlessDream》[WAV+CUE]
- 彭芳《纯色角3》2007[WAV+CUE]
- 江志丰2008-今生为你[豪记][WAV+CUE]
- 罗大佑1994《恋曲2000》音乐工厂[WAV+CUE][1G]
- 群星《一首歌一个故事》赵英俊某些作品重唱企划[FLAC分轨][1G]
- 群星《网易云英文歌曲播放量TOP100》[MP3][1G]
- 方大同.2024-梦想家TheDreamer【赋音乐】【FLAC分轨】
- 李慧珍.2007-爱死了【华谊兄弟】【WAV+CUE】
- 王大文.2019-国际太空站【环球】【FLAC分轨】
- 群星《2022超好听的十倍音质网络歌曲(163)》U盘音乐[WAV分轨][1.1G]
- 童丽《啼笑姻缘》头版限量编号24K金碟[低速原抓WAV+CUE][1.1G]