- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Python面向对象程序设计类的多态用法详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
本文实例讲述了python面向对象程序设计类的多态用法。分享给大家供大家参考,具体如下:
多态 。
1、多态使用 。
一种事物的多种体现形式,举例:动物有很多种 。
注意: 继承是多态的前提 。
函数重写就是多态的体现形式 。
演示:重写animal类 。
第一步:先定义猫类和老鼠类,继承自object,在其中书写构造方法和eat方法 第二步: 抽取animal父类,定义属性和eat方法,猫类与老鼠类继承即可 第三步: 定义人类,在其中分别定义喂猫和喂老鼠的方法 第四步:使用多态,将多个喂的方法提取一个.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
# 测试类
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方法吗?
#前提:tom和jerry都继承自动物
per.feedanimal(tom)
per.feedanimal(jerry)
|
输出:
tom吃 jerry吃 给你食物 tom吃 给你食物 jerry吃 。
1
2
3
4
5
6
|
#animal.py文件中的动物类
class
animal(
object
):
def
__init__(
self
, name):
self
.name
=
name
def
eat(
self
):
print
(
self
.name
+
"吃"
)
|
1
2
3
4
5
|
#cat.py文件中的猫类
class
cat(animal):
def
__init__(
self
, name):
#self.name = name
super
(cat,
self
).__init__(name)
|
1
2
3
4
5
|
#mouse.py中的老鼠类
class
mouse(animal):
def
__init__(
self
, name):
#self.name = name
super
(mouse,
self
).__init__(name)
|
1
2
3
4
5
|
#person.py中的人类
class
person(
object
):
def
feedanimal(
self
, ani):
print
(
"给你食物"
)
ani.eat()
|
2、对象属性与类属性 。
对象属性和类属性的区别
a.定义的位置不同,类属性是直接在类中的属性,对象属性是在定义在构造方法中的属性; 。
b.对象属性使用对象访问,类属性使用类名访问; 。
c.在内存中出现的时机不同[类属性随着类的加载而出现,对象属性随着对象的创建而出现]; 。
d.优先级不同,对象属性的优先级高于类属性.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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 person 。
3、动态添加属性和方法 。
正常情况下,我们定义了一个class,创建一个class的实例后,我们可以给该实例绑定任何的的属性和方法,这就是动态语言的灵活性.
python语言的特点:灵活.
这里说的动态添加属性和方法主要指的是关于slots函数的使用 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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绑定方法 。
1
2
3
4
5
6
7
|
#动态添加方法
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添加功能,这在静态语言中很难实现.
如果我们想限制实例的属性怎么办?
比如,只允许给person实例添加name,age属性,为了达到限制的目的,python中允许在定义class的时候,定义一个特殊的变量【slots】变量,来限制该class添加的属性 。
1
2
3
4
5
6
7
8
|
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__
语法:
1
|
__slots__
=
(属性名
1
,属性名
2
,...)
|
作用:
限制类的属性名 。
注意:当子类没有添加slots时,子类继承父类的时候,它的属性名不受父类的影响 。
若子类中也添加slots,子类的限制应该是父类的slots与子类slots的并集 。
5、@property 。
绑定属性时,如果我们直接把属性暴露出去,虽然写起来简单,但是没有办法检查参数,导致可以随意的更改.
比如:
1
2
|
p
=
person()
p.age
=
-
1
|
这显然不合常理,为了限制age的范围,我们可以通过setage()的方法来设置age,再通过getage()的方法获取age,这样在setage()中就可以检查输入的参数的合理性了.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
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.setage(15)
# print(per.getage())
# property:可以让你对受限制访问的属性使用"."语法
per.age
=
80
# 相当于调用setage
print
(per.age)
# 相当于调用getage
print
(per.name)
|
输出:
80 lili 。
property 。
总结语法:
针对私有化的属性添加的.
1
2
3
|
@property
def
属性名(
self
):
return
self
.__属性名
|
1
2
3
4
|
@属性名.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之前创建对象 |
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
# 举例
# 数字和字符串都能相加
#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)
# 如果两个对象相加会怎样?
# 对象相加,编译器解释不了,所以就要用到运算符重载
per1
=
person(
1
)
per2
=
person(
2
)
print
(per1
+
per2)
# 结果为地址:per1+per2 === per1.__add__(per2),如果想得到num的和则重写str方法
# 上述打印就等价于:print(per1.__add__(per2)),只不过add方法会自动调用
print
(per1)
print
(per2)
|
输出:
num = 3 num = 1 num = 2 。
希望本文所述对大家python程序设计有所帮助.
原文链接:https://blog.csdn.net/lm_is_dc/article/details/80171357 。
最后此篇关于Python面向对象程序设计类的多态用法详解的文章就讲到这里了,如果你想了解更多关于Python面向对象程序设计类的多态用法详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在创建一个多区域 AlwaysOn Sql Availability 组。我在东部有 2 个虚拟机,在西部有 1 个虚拟机。我需要使用面向公众的负载平衡器对这些进行负载平衡。是否可以使用存在于不同
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我是 Smalltalk 技术的新手。我的编程经验是使用 C 和 C++。我想了解smalltalk的设计方法论。谁能推荐一些用smalltalk开发的简单的实时应用程序,可以帮助像我这样的初学者探索
现在我已经对 web2py 比较熟悉了,我想试试 Django。 主要区别是什么? 考虑到 web2py 知识,最有效的入门方法是什么? (一定有一些python应用框架的知识,不是吗?) 编辑 另外
我之前发过一个问题,Moving away from VSS ,其中我向使用 VSS 的 Delphi 开发人员询问了最佳的 VCS 控件。大多数开发人员似乎将 svn 与 TortoiseSVN 一
引用this question ,收集对 Delphi 初学者真正有帮助的网站链接可能会很好。 第一个答案指向Delphi Basics ,这是一个非常好的网站。 但一定还有更多。 所以:请为这个社区
我已经构建了一个 saas 产品,其中 Angular 4 与 golang Rest api 集成,并将构建上传到了 aws ec2 实例上。我的项目是一个基于 Multi-Tenancy 的应用程
我是 .NET 开发人员,在此之前使用过 VB6。我已经非常熟悉这些环境,并在垃圾收集语言的上下文中工作。但是,我现在希望通过 native C++ 增强我的技能,但发现自己有点不知所措。具有讽刺意味
就目前情况而言,这个问题不太适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、民意调查或扩展讨论。如果您觉得这个问题可以改进并可能重新开放,visit
由于我在数学方面没有任何出色的技能,所以我问您是否存在我应该在未来可能会改变的类(class)中使用的算法。 考虑以下场景: “角色”类具有以下字段: private boolean admin; p
我有许多面向“列”的 csv 文件,我需要对其进行预处理才能最终索引它们。 这是面向时间的数据,每个“设备”都有大量的列(最多 128 列),例如: LDEV_XXXXXX.csv
我想就重构技巧的最佳资源展开讨论,着眼于前端 JavaScript 重构。 一个我尊重其意见的 friend 建议这个 book ,尽管它使用 Java 中的示例。我明白 OO 重构的原则应该翻译成另
我不明白如何使用 Jquery/javascript 处理对象。 以及如何创建私有(private)方法/变量?我在论坛上看到关闭,但我尝试过但没有用。以及如何查看方法/变量是否是私有(private
我已经使用 MATLAB 多年并且非常熟练。我习惯了 MATLAB 调试,您可以在其中跳过行并查看变量及其变化方式,这就是我学习编码的方式。我现在正在研究使用 FORTRAN、C++ 和 Python
我正在学习如何实现“单一 Activity - 多个 fragment ”架构。据我所知,这是如今很普遍的方法,你可以找到很多关于这个主题的文章。例如这个 http://vinsol.com/blog
目前是否有任何简单的方法可以在 Apache Tomcat Servlet 容器前面设置 YAWS Web 服务器,类似于流行的 Apache httpd + Tomcat 设置? 最佳答案 我不相信
我是一个相当有能力的 Ruby 脚本编写者/程序员,但一直感到要扩展到 C++ 的压力。我没能找到任何与“C++ for Ruby Programmers”相关的网站。 This site Pytho
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 5 年前。
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我在表上有一个名为 cart_product_fti 的全文索引 每当我使用它时,我都必须准确列出索引中的所有字段: MATCH (foo,bar,etc) 我的想法是,如果稍后我决定向索引添加/删除
我是一名优秀的程序员,十分优秀!