Python程序设计6——面向对象
面向对象有三大特征:多态(对应方法覆写)、封装、继承(对应方法重载),这个在Java中已经说得很详细了,这里面只是介绍Python在这三个特性方面的实现。
1 创建自定义类
Python和Java一样使用class关键字来创建对象。语法格式如下:
class 类名:
def 方法名1(参数列表):
pass
从上述语法来看,类必须使用class关键字来定义,接着是类名,然后使用pass占位。
一个例子如下:
class Person:
def getName(self):
print 'My name is AIQI'
def getAge(self):
print 'My age is 27'
def getHoppy(self):
print 'My hobby is love you'
>>> import Person
>>> person = Person.Person()
>>> person.getName()
My name is AIQI
>>> person.getAge()
My age is 27
>>> person.getHoppy()
My hobby is love you
实例应用
myStr = raw_input('Please input one object:')
class MyWorld:
#define one person method
def printPerson(self):
self.myTalk = 'I can speak'
self.myLimbs = 'I can move'
print 'I am a person so,I can %s, %s' % (self.myTalk, self.myLimbs)
#define one pig method
def printPig(self):
self.myTalk = 'Hengheng...'
self.myWeight = 'I am fat'
print 'I am a pig so,%s, %s' % (self.myTalk, self.myWeight)
if __name__ == '__main__':
myWorld = MyWorld()
if myStr == 'Person':
myWorld.printPerson()
elif myStr == 'Pig':
myWorld.printPig()
else:
print 'No this object'
运行结果:
Please input one object:Person
I am a person so,I can I can speak, I can move
2 属性和方法
类是忧属性和方法组成的,属性是对数据的封装,方法是对行为的描述。在Java中,属性和方法都有访问权限控制符,在python中没有这样的封装级别控制符,在Python中,构造函数、析构函数、私有属性方法、公有属性方法都是通过名称的约定来辨别的。如果函数、方法或者属性的名称以两个下划线开始,则说明为私有类型。相反,如果没有以两个下划线开始,则表示为公有属性。在Java中还有一个受保护的类型修饰符protected 在python中不存在这种类型。
在python中也有静态属性和实例属性。实例属性即以self作为前缀的属性,如果在类的方法中定义的变量没有使用self作为前缀声明,那么该变量就是一个普通的局部变量。
2.1 类属性
class Fly:
#define one class attribute
price = 23
def __init__(self):
self.direction = 'To Paris'
speed = 32
if __name__ == '__main__':
print Fly.price
fly = Fly()
print fly.direction
Fly.price = fly.price + 10
print 'fly,fly away'
print 'the price increase:' + str(fly.price)
myFly = Fly()
print myFly.price
输出结果:
23
To Paris
fly,fly away
the price increase:33
33
另外方法中的局部变量speed是不能被实例及类来引用的
2.2 私有属性
将公有的实例属性direction修改成私有__direction
class Fly:
#define one class attribute
price = 23
def __init__(self):
self.__direction = 'To Paris'
self.speed = 32
if __name__ == '__main__':
print Fly.price
fly = Fly()
print fly.__direction
Fly.price = fly.price + 10
print 'fly,fly away'
print 'the price increase:' + str(fly.price)
myFly = Fly()
print myFly.price
输出结果:
23
Traceback (most recent call last):
File "Fly.py", line 10, in <module>
print fly.__direction
AttributeError: Fly instance has no attribute '__direction'
显然报错了,也就是私有的属性不能被实例化对象访问。Python提供了直接访问私有属性的方式
实例化对象名._类名__私有属性名
class Fly:
#define one class attribute
price = 23
def __init__(self):
self.__direction = 'To Paris'
self.speed = 32
if __name__ == '__main__':
print Fly.price
fly = Fly()
print fly._Fly__direction
Fly.price = fly.price + 10
print 'fly,fly away'
print 'the price increase:' + str(fly.price)
输出结果:
23
To Paris
fly,fly away
the price increase:33
2.3 数据属性
数据属性不需要预先定义,当数据属性初次被使用时,即被创建并赋值。
class DataAttribute:
pass
if __name__ == '__main__':
data = DataAttribute()
data.name = 'I am not defined'
print data.name
输出结果:I am not defined
2.4 内置属性
前面已经提到的__doc__就是内置属性。
class FatherClass:
def __init__(self):
self.built = 'I am the method __init__ \'s attribute'
class SonClass(FatherClass):
def accept(self):
self.acceptAttribute = "I am the attribute of SonClass's method accept"
if __name__ == '__main__':
f = FatherClass()
s = SonClass()
print "Inherite attribute from father class:", s.built
print "the tuple formed by base class:", SonClass.__bases__
print "the dict formed by neizhi:", s.__dict__
print s.__module__
print s.__doc__
print SonClass.__name__
输出结果:
Inherite attribute from father class: I am the method __init__ 's attribute
the tuple formed by base class: (<class __main__.FatherClass at 0x7f8d92e4ea10>,)
the dict formed by neizhi: {'built': "I am the method __init__ 's attribute"}
__main__
None
SonClass
说明:上面代码中,使用内置属性__bases__来输出其父类组成的元组。__dict__属性用例输出子类实例属性组成的字典,__module__属性用来输出当前运行的模块名称,__doc__属性用来输出doc文档,而__name__属性用例输出当前对象的类名。
2.5 类的方法
类似属性,方法也有类方法和实例方法,定义规则相同,在Java中用static来定义,而python中没有static关键字,而是使用函数staticmethod()或者@staticmethod指令的方式来定义静态方法。
2.5.1 类方法
class Methods:
@staticmethod
def myMethod():
print 'This is a static method'
def __myMethod():
print 'This is a private method'
def getMyMethod():
print 'I willbe converted to static method'
conversion = staticmethod(getMyMethod)
conPrivate = staticmethod(__myMethod)
if __name__ == '__main__':
methods = Methods()
methods.myMethod()
Methods.myMethod()
#访问转换为静态方法后的原有方法
methods.conversion()
Methods.conversion()
methods.conPrivate()
Methods.conPrivate()
输出结果:
This is a static method
This is a static method
I willbe converted to static method
I willbe converted to static method
This is a private method
This is a private method
上面代码中,在类Methods中分别声明了一个静态方法myMethod,一个私有方法__myMethod和一个普通方法getMyMethod,然后用函数staticmethod()将普通方法getMyMethod转换为静态方法conversion,将私有方法__myMethod转换为静态方法conPrivate
2.5.2 内置方法
有许多类内置的方法,这些方法可能会被封装起来被别的函数调用。
下面介绍几个重要的__init__方法
1.__init__方法
这个方法在Python中是构造函数,与Java不同的是,Java中的构造函数和类名是一样的,Python中不必如此,实际上构造函数更严谨的说法是初始化函数,所以__init__还是可以的。
class People:
def __init__(self, name):
self.name = name
def sayHi(self):
print 'Hello, My name is:', self.name
p = People('AiQi')
p.sayHi()
输出结果:Hello, My name is: AiQi
2.__del__方法
__del__方法的主要作用是释放被占用的资源,在Python中是析构函数。
所谓析构函数是:析构函数(destructor) 与构造函数相反,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,应在退出前在析构函数中用delete释放)。
class Room:
count = 0
def __init__(self, name):
self.name = name
print 'Initing, name is %s' % self.name
Room.count += 1
def __del__(self):
print '%s say byebye:' % self.name
Room.count -= 1
if Room.count == 0:
print 'I am the last one'
else:
print 'There is %d persons left' % Room.count
def sayHi(self):
print 'Hello,My name is %s ' % self.name
def howMany(self):
if Room.count == 1:
print 'I am the last one'
else:
print 'There is %d persons left' % Room.count
if __name__ == '__main__':
room = Room('AiQi')
room.sayHi()
运行结果:
Initing, name is AiQi
Hello,My name is AiQi
I am the last one
Initing, name is Ren
Hello,My name is Ren
There is 2 persons left
AiQi say byebye:
There is 1 persons left
Ren say byebye:
Exception AttributeError: "'NoneType' object has no attribute 'count'" in <bound method Room.__del__ of <__main__.Room instance at 0x7fc513263200>> ignored
AiQi say byebye:
Exception AttributeError: "'NoneType' object has no attribute 'count'" in <bound method Room.__del__ of <__main__.Room instance at 0x7fc5132631b8>> ignored
3. __new__方法
__new__方法在创建对象时被调用,返回当前对象的一个实例。看起来和__init__方法没有什么区别。实际上,__init__方法在创建完对象之后才被调用,对当前对象的实例进行初始化,而__new__方法则是在创建对象时被调用的。
class MyNew:
def __init__(self):
print ("__init__")
def __new__(self):
print ("__new__")
if __name__ == '__main__':
myNew = MyNew()
4.__setitem__方法
_setitem__专用方法的含义是进行赋值时,创建字典对象
class MySetitem:
def __setitem__(self, key, value):
print 'key=%s, value=%s' % (key, value)
mySetitem = MySetitem()
mySetitem['a'] = 'Alice'
mySetitem['b'] = 'Quinta'
mySetitem['c'] = 'Amy'
执行结果:
key=a, value=Alice
key=b, value=Quinta
key=c, value=Amy
5.__getitem__方法
__getitem__用于返回字典的值。这两个方法和java的setter和getter方法是类似的。
6.__delitem__方法
__delitem__方法是在调用"del 实例对象[key]"语句时调用。
class MyDelitem:
def __delitem__(self, key):
print 'delete item:%s' % key
myDelitem = MyDelitem()
del myDelitem['dcy']
输出结果:delete item:dcy
7.__cmp__方法
这个内置方法被封装用于给==比较累实例时候进行调用。
class MyCmp:
def __cmp__(self, other):
print '__cmp__ is called'
return 0
if __name__ == '__main__':
mycmp1 = MyCmp()
mycmp2 = MyCmp()
print mycmp1 == mycmp2
输出:
__cmp__ is called
True
2.6 方法的动态特性
python语言是一种完全面向对象的动态语言,主要体现在:可以动态添加类的方法,将某个已经定义的方法添加到类中。如果类本身已经有了同名的方法,那么将会替换掉类中的方法体。
class_name.method_name = exist_name
class Yesterday:
pass
def today(self):
print 'Today is a nice day'
if __name__ == '__main__':
Yesterday.yesterday = today
yes = Yesterday()
yes.yesterday()
输出结果:Today is a nice day
3 继承
继承是子类继承父类的属性和方法,python中没有extends关键字,用括号
class class_name(father_class_name)
一个例子:
3.1 super调用父类方法
python支持用super关键字来调用父类的方法
'''
Created on 2013-8-6 @author: Landau
'''
class Father:
def __init__(self):
print 'I am the __init__ of father'
print 'Use later'
class Son(Father):
def __init__(self):
print 'I am the __init__ of son'
Father.__init__(self)
b = Son()
我们也可以使用super关键字来实现上面的功能
3.2 多继承
python允许多重继承。语法格式如下:
class class_name(fatherclass1_name,fatherclass2_name)
多继承是这样的,比如一个人,眼睛像妈妈,肤色像爸爸。这就是多继承。
3.3 类的命名空间
类和类成员的名称是丰富的,为了描述一个具体的对象,需要对类和类成员进行设计,在设计类和类成员过程中,难免会出现类的名称或类成员中的方法相同的情况,这样就会造成代码混乱,从而使代码的可读性降低。使用命名空间可以解决此问题。
在java中,我们只要把类放到各自的包中,就可以避免类的名称或者类成员重复了,我们可以认为package是java的命名空间。
在python中,定义类时,所有位于class语句中的代码都在特殊的命名空间中执行,该命名空间被称为类命名空间(class namespace)。这个类命名空间不仅可以被类中所有成员访问,还可以被类的实例方法访问。
3.4 继承检查
python提供了内建的issubclass函数用于继承检查
issubclass函数的第一个参数是子类,第二个参数是可能的父类,类似还有一个函数isinstance,用于检查一个对象是不是一个类的实例,第一个参数是对象,第二个参数是可能的类。
3.5 新式类
新式类是指从python2.2开始引入的类。通常情况下,从object或者其他内置类型衍生的类,都被称为新式类。
__slots__类属性
这个类属性用于替代__dict__属性
__slots__是一个类变量,可以由一系列对象组成,使用所有合法标识构成的实例属性的集合来表示。它也可以是一个列表、元组或可迭代对象,总之,任何试图创建一个其名不在__slots__中的实例属性的操作都将引发AttributeError异常,而且实例属性必须初始化。
一般情况下,__slots__类属性在class语句顶层设置。下面通过一个例子说明:
class MyLimiter(object):
__slots__ = 'my_name', 'my_age', 'my_hobby'
if __name__ == '__main__':
x = MyLimiter()
x.my_name = 'AiQi'
print x.my_name
Python程序设计6——面向对象的更多相关文章
- Python进阶(十三)----面向对象
Python进阶(十三)----面向对象 一丶面向过程编程vs函数式编程vs面向对象编程 面向过程: 简而言之,step by step 一步一步完成功能,就是分析出解决问题所需要的步骤,然后用函 ...
- python基础_面向对象进阶
@property装饰器 之前我们讨论过Python中属性和方法访问权限的问题,虽然我们不建议将属性设置为私有的,但是如果直接将属性暴露给外界也是有问题的,比如我们没有办法检查赋给属性的值是否有效.我 ...
- python基础_面向对象
面向对象定义 把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封装(encapsulation)隐藏内部细节,通过继承(inheritance) ...
- (转)Python成长之路【第九篇】:Python基础之面向对象
一.三大编程范式 正本清源一:有人说,函数式编程就是用函数编程-->错误1 编程范式即编程的方法论,标识一种编程风格 大家学习了基本的Python语法后,大家就可以写Python代码了,然后每个 ...
- Python学习之面向对象基础
python的面向对象和以前学的c++,Java都是一般,大同小异,面向对象基础先谈谈类的构造,编写,属性和方法的可见性等等 1.定义类,创建和使用对象 #定义类 class Student(obje ...
- 20184302 2019-2020-2 《Python程序设计》实验一报告
20184302 2019-2020-2 <Python程序设计>实验一报告 课程:<Python程序设计> 班级: 1843 姓名: 李新锐 学号:20184302 实验教师 ...
- 20184302 2019-2020-2 《Python程序设计》实验四报告
20184302 2019-2020-2 <Python程序设计>实验四报告 课程:<Python程序设计> 班级: 1843 姓名: 李新锐 学号:184302 实验教师:王 ...
- Python程序设计(第3版)PDF高清完整版免费下载|百度网盘
百度网盘:Python程序设计(第3版)PDF高清完整版免费下载 提取码:48u4 内容简介 本书是面向大学计算机科学专业第一门程的教材.本书以Python语言为工具,采用相当传统的方法,强调解决问题 ...
- 实验一 Python程序设计入门
学号20184307 2019-2020-2 <Python程序设计>实验1报告 课程:<Python程序设计> 班级: 1843 姓名: 章森洋 学号:20184307 实验 ...
随机推荐
- RedHat 6.8 内核编译
/*************************************************************************** * RedHat 6.8 内核编译 * 说明: ...
- 【LeetCode】075. Sort Colors
Given an array with n objects colored red, white or blue, sort them so that objects of the same colo ...
- mapreduce-实现单表关联
//map类 package hadoop3; import java.io.IOException; import org.apache.hadoop.io.LongWritable;import ...
- 一次调用cloudera的的API和JSON想到的
JSON的null字段 在我的项目中修改了YARN的资源池,到cloudera中就报错,查询还不报错,但是修改的时候,就报错,大致意思就是信息有异常,“包含了尖括号. 因为通过API+json交互,我 ...
- python面向对象-我的理解
参考:博客 Vamei .廖雪峰 面向对象概念 面向对象完全可以按照自然界生物分类法来理解. 当然,它不会有自然界那么复杂. 因为我专业的关系,因此个人觉得微生物来举例很容易理解. 所有的微生物都具有 ...
- WPF案例:如何设计历史记录查看UI
(CSDN博客目前不支持外链, 只能纯文字) 设计WPF的UI,一般遵循下面的步骤: 1.首先分析数据结构 2.根据数据结构选择合理控件 3.定制外观 具体对于历史记录查看UI, 我们可以得知: 1. ...
- Laravel 传递数据到视图
// 使用传统的方法 $view = view('greeting')->with('name', 'Victoria'); // 使用魔术方法 $view = view('greeting') ...
- Gradle 配置
下载Gradle https://gradle.org/releases/ https://services.gradle.org/distributions/gradle-4.4.1-bin.zip ...
- hihoCoder#1079(线段树+坐标离散化)
时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho在回国之后,重新过起了朝7晚5的学生生活,当然了,他们还是在一直学习着各种算法~ 这天小Hi和小Ho所在的学 ...
- Spring Boot自定义配置与加载
Spring Boot自定义配置与加载 application.properties主要用来配置数据库连接.日志相关配置等.除了这些配置内容之外,还可以自定义一些配置项,如: my.config.ms ...