Python的面向对象编程方式学习笔记


Posted in Python onJuly 12, 2016

类与实例
类与实例相互关联着:类是对象的定义,而实例是“真正的实物”,它存放了类中所定义的对象的具体信息。

下面的示例展示了如何创建一个类:

class MyNewObjectType(bases):
   ''' 创建 MyNewObjectType 类'''
   class_suite

关键字是 class,紧接着一个类名。随后是定义类的类代码。这里通常由各种各样的定义和声明组成。新式类和经典类声明的最大不同在于,所有新式类必须继承至少一个父类,参数 bases 可以是一个(单继承)或多个(多重继承)用于继承的父类。

创建一个实例的过程称作实例化,过程如下(注意:没有使用 new 关键字):

myFirstObject = MyNewObjectType()

类名使用我们所熟悉的函数操作符(()),以“函数调用”的形式出现。然后你通常会把这个新建的实例赋给一个变量。赋值在语法上不是必须的,但如果你没有把这个实例保存到一个变量中,它就没用了,会被自动垃圾收集器回收,因为任何引用指向这个实例。这样,你刚刚所做的一切,就是为那个实例分配了一块内存,随即又释放了它。

类既可以很简单,也可以很复杂,这全凭你的需要。最简单的情况,类仅用作名称空间(namespace)。这意味着你把数据保存在变量中,对他们按名称空间进行分组,使得他们处于同样的关系空间中——所谓的关系是使用标准 Python 句点属性标识。例如,你有一个本身没有任何属性的类,使用它仅对数据提供一个名字空间,让你的类拥有像 C 语言中的结构体(structure)一样的特性,或者换句话说,这样的类仅作为容器对象来共享名字空间。

示例如下:

class MyData(object):
  pass

mathObj = MyData()
mathObj.x = 4
mathObj.y = 5
mathObj.x + mathObj.y
9
mathObj.x \\* mathObj.y
20

方法
在 Python 中,方法定义在类定义中,但只能被实例所调用。也就是说,调用一个方法的最终途径必须是这样的:(1)定义类(和方法);(2)创建一个实例;(3)最后一步,用这个实例调用方法。例如:

class MyDataWithMethod(object): # 定义类
  def printFoo(self): # 定义方法
    print 'You invoked printFoo()!'

这里的 self 参数,它在所有的方法声明中都存在。这个参数代表实例对象本身,当你用实例调用方法时,由解释器传递给方法的,所以,你不需要自己传递 self 进来,因为它是自动传入的。

举例说明一下,假如你有一个带两参数的方法,所有你的调用只需要传递第二个参数。

下面是实例化这个类,并调用那个方法:

> > > myObj = MyDataWithMethod()
> > > myObj.printFoo()
You invoked printFoo()!

\\_init\\(),是一个特殊的方法。在 Python 中, \\init\\() 实际上不是一个构造器。你没有调用“new”来创建一个新对象。(Python 根本就没有“new”这个关键字)。取而代之, Python 创建实例后,在实例化过程中,调用 \\init\\_()方法,当一个类被实例化时,就可以定义额外的行为,比如,设定初始值或者运行一些初步诊断代码——主要是在实例被创建后,实例化调用返回这个实例之前,去执行某些特定的任务或设置。

创建一个类(类定义)

class AddrBookEntry(object):
  '''address book entry class'''
  def __init__(self, nm, ph): # 定义构造器
    self.name = nm       # 设置 name
    self.phone = ph       # 设置 phone
    print 'Created instance for:', self.name

  def updatePhone(self, newph):  # 定义方法
    self.phone = newph
    print 'Updated phone# for: ', self.name

在 AddrBookEntry 类的定义中,定义了两个方法: \\_init\\()和updatePhone()。\\init\\()在实例化时被调用,即,在AddrBookEntry()被调用时。你可以认为实例化是对 \\init\\()的一种隐式的调用,因为传给AddrBookEntry()的参数完全与\\init\\_()接收到的参数是一样的(除了self,它是自动传递的)。

创建实例(实例化)

> > > john = AddrBookEntry('John Doe', '408-555-1212') # 为 John Doe 创建实例
> > > jane = AddrBookEntry('Jane Doe', '650-555-1212') # 为 Jane Doe 创建实例

这就是实例化调用,它会自动调用 \\_init\\()。 self 把实例对象自动传入\\init\\_()。

另外,如果不存在默认的参数,那么传给 \\_init\\_() 的两个参数在实例化时是必须的。

访问实例属性

> > > john
> > > john.name
> > > jane.name
> > > jane.phone

一旦实例被创建后,就可以证实一下,在实例化过程中,我们的实例属性是否确实被 \\_init\\_() 设置了。我们可以通过解释器“转储”实例来查看它是什么类型的对象。

方法调用(通过实例)

> > > john.updatePhone('415-555-1212')  # 更新 John Doe 的电话
> > > john.phone

updatePhone()方法需要一个参数(不计 self 在内):新的电话号码。在 updatePhone()之后,立即检查实例属性,可以证实已生效。

方法与属性的小结
直接上代码,已经在里面有注释了

#coding:utf8

name = 'yangyanxing'
class Test():
  class kevin():
    var1 = '我是内部类'

  name = 'kvein'
  gae = '26'

  def fun1(self):
    print self.name
    print '我是公共方法'
    self.__fun2() #可以通过公有就去来调用私有方法,在调用的过程中可以进行更改

  def __fun2(self):
    print '我是私有方法'

  @classmethod
  def fun3(self): #可以不通过实例来访问这个类方法
    print '#'*40
    print self.name
    print '我是类方法'

  @staticmethod #静态方法,也是可以不通过实例对象就可以访问的方法但是在定义的时候不用加self
  def fun4():
    print Test.name
    print name #这里的name是全局变量
    Test.fun3()
    print '我是静态方法'

print Test.name #公有属性可以直接方法,不用实例化对象
yang = Test() #实例化一个类
interyang = Test.kevin() #实例化一个内部类
yang.fun1() #方法类里面的公共属性
print interyang.var1 # 访问内部类里的属性
Test.fun3()#访问类方法
Test.fun4()
#coding:utf8

class Test():
  var1 = '类的公有属性'
  __var2 = '类的私有属性'

  def fun(self):
    self.var2 = '对象的公有属性' # 这里定义了一个对象的公有属性
    self.__var3 = '对象的私有属性'# 这里定义了一个对象的私有属性
    var4 = '函数的局部变量' #这里定义了一个函数的局部变量,这里面的var4只有在函数内部使用

kevin = Test() #实例了一个对象
yang = Test() #又实例了另外一个对象
print kevin.var1
##print kevin.__var2 #这里将无法访问
kevin.fun()
print kevin.var2 #在没有调用fun函数之前是没有var2的
##print kevin.__var3 对象的私有属性是无法调用的
##print yang.var2 #这里因为没有调用yang的fun方法,所以还是无法访问yang里的var2

创建子类
靠继承来进行子类化是创建和定制新类型的一种方式,新的类将保持已存在类所有的特性,而不会改动原来类的定义。对于新类类型而言,这个新的子类可以定制只属于它的特定功能。除了与父类或基类的关系外,子类与通常的类没有什么区别,也像一般类一样进行实例化。注意下面,子类声明中提到了父类:

class EmplAddrBookEntry(AddrBookEntry):
  '''Employee Address Book Entry class''' # 员工地址簿类
  def __init__(self, nm, ph, id, em):
    AddrBookEntry.__init__(self, nm, ph)
    self.empid = id
    self.email = em

  def updateEmail(self, newem):
    self.email = newem
    print 'Updated e-mail address for:', self.name

现在我们创建了第一个子类, EmplAddrBookEntry。 Python 中,当一个类被派生出来,子类就继承了基类的属性,所以,在上面的类中,我们不仅定义了 \\_init\\_(),UpdateEmail()方法,而且 EmplAddrBookEntry 还从 AddrBookEntry 中继承了 updatePhone()方法。

如果需要,每个子类最好定义它自己的构造器,不然,基类的构造器会被调用。然而,如果子类重写基类的构造器,基类的构造器就不会被自动调用了——这样,基类的构造器就必须显式写出才会被执行,就像我们上面那样,用AddrBookEntry.\\_init\\_()设置名字和电话号码。我们的子类在构造器后面几行还设置了另外两个实例属性:员工ID和电子邮件地址。

注意,这里我们要显式传递 self 实例对象给基类构造器,因为我们不是在该实例中而是在一个子类实例中调用那个方法。因为我们不是通过实例来调用它,这种未绑定的方法调用需要传递一个适当的实例(self)给方法。

使用子类

> > > john = EmplAddrBookEntry('John Doe', '408-555-1212', 42, 'john@spam.doe')
> > > john
> > > john.name
> > > john.phone
> > > john.email
> > > john.updatePhone('415-555-1212')
> > > john.phone
> > > john.updateEmail('john@doe.spam')
> > > john.email
Python 相关文章推荐
使用python实现递归版汉诺塔示例(汉诺塔递归算法)
Apr 08 Python
跟老齐学Python之不要红头文件(2)
Sep 28 Python
python 将列表中的字符串连接成一个长路径的方法
Oct 23 Python
Python爬取商家联系电话以及各种数据的方法
Nov 10 Python
Python实现中值滤波去噪方式
Dec 18 Python
python统计函数库scipy.stats的用法解析
Feb 25 Python
Python 实现网课实时监控自动签到、打卡功能
Mar 12 Python
python 安装库几种方法之cmd,anaconda,pycharm详解
Apr 08 Python
Python实现自动签到脚本功能
Aug 20 Python
Python爬虫过程解析之多线程获取小米应用商店数据
Nov 14 Python
python工具——Mimesis的简单使用教程
Jan 16 Python
Python入门基础之数字字符串与列表
Feb 01 Python
Python使用cookielib模块操作cookie的实例教程
Jul 12 #Python
Python网络编程中urllib2模块的用法总结
Jul 12 #Python
Python中内置的日志模块logging用法详解
Jul 12 #Python
Swift 3.0在集合类数据结构上的一些新变化总结
Jul 11 #Python
浅析Python的web.py框架中url的设定方法
Jul 11 #Python
深入解析Python的Tornado框架中内置的模板引擎
Jul 11 #Python
使用Python的Tornado框架实现一个Web端图书展示页面
Jul 11 #Python
You might like
如何使用PHP中的字符串函数
2006/11/24 PHP
php session_start()关于Cannot send session cache limiter - headers already sent错误解决方法
2009/11/27 PHP
PHP错误Warning: Cannot modify header information - headers already sent by解决方法
2014/09/27 PHP
Session 失效的原因汇总及解决丢失办法
2015/09/30 PHP
PHP上传文件参考配置大文件上传
2015/12/16 PHP
php下载文件超时时间的设置方法
2016/10/06 PHP
javascript右下角弹层及自动隐藏(自己编写)
2013/11/20 Javascript
javascript实现类似超链接的效果
2014/12/26 Javascript
jquery简单实现幻灯片的方法
2015/08/03 Javascript
详解微信小程序 相对定位和绝对定位
2017/05/11 Javascript
基于nodejs+express4.X实现文件下载的实例代码
2017/07/13 NodeJs
微信小程序实现蒙版弹窗效果
2018/11/01 Javascript
Angular PWA使用的Demo示例
2019/01/31 Javascript
跟老齐学Python之dict()的操作方法
2014/09/24 Python
python列表操作之extend和append的区别实例分析
2015/07/28 Python
更改Ubuntu默认python版本的两种方法python-> Anaconda
2016/12/18 Python
一张图带我们入门Python基础教程
2017/02/05 Python
python实现unicode转中文及转换默认编码的方法
2017/04/29 Python
Win10环境python3.7安装dlib模块趟过的坑
2019/08/01 Python
python连接PostgreSQL数据库的过程详解
2019/09/18 Python
python实现简易学生信息管理系统
2020/04/05 Python
django 文件上传功能的相关实例代码(简单易懂)
2020/01/22 Python
CSS3 重置iphone浏览器按钮input,select等表单元素的默认样式
2014/10/11 HTML / CSS
Canvas 文字碰撞检测并抽稀的方法
2019/05/27 HTML / CSS
Skyscanner澳大利亚:全球领先的旅游搜索网站
2018/03/24 全球购物
如何唤起类中的一个方法
2013/11/29 面试题
中专毕业自我鉴定
2013/10/16 职场文书
迟到检讨书900字
2014/01/14 职场文书
临床专业自荐信
2014/06/22 职场文书
银行柜员与客户起冲突检讨书
2014/09/27 职场文书
个人委托书范文
2015/01/28 职场文书
高考学习决心书
2015/02/04 职场文书
班主任自我评价范文
2015/03/11 职场文书
警示教育观后感
2015/06/17 职场文书
python3实现无权最短路径的方法
2021/05/12 Python
台积电称即便经济低迷也没有降价的计划
2022/04/21 数码科技