python对象及面向对象技术详解


Posted in Python onJuly 19, 2016

本文实例讲述了python对象及面向对象技术。分享给大家供大家参考,具体如下:

1 先看一个例子. 本章将讲解这个例子程序:

文件: fileinfo.py:

"""Framework for getting filetype-specific metadata.
Instantiate appropriate class with filename. Returned object acts like a
dictionary, with key-value pairs for each piece of metadata.
  import fileinfo
  info = fileinfo.MP3FileInfo("/music/ap/mahadeva.mp3")
  print "\n".join(["%s=%s" % (k, v) for k, v in info.items()])
Or use listDirectory function to get info on all files in a directory.
  for info in fileinfo.listDirectory("/music/ap/", [".mp3"]):
    ...
Framework can be extended by adding classes for particular file types, e.g.
HTMLFileInfo, MPGFileInfo, DOCFileInfo. Each class is completely responsible for
parsing its files appropriately; see MP3FileInfo for example.
"""
import os
import sys
from UserDict import UserDict
def stripnulls(data):
  "strip whitespace and nulls"
  return data.replace("{post.content}", "").strip()
class FileInfo(UserDict):
  "store file metadata"
  def __init__(self, filename=None):
    UserDict.__init__(self)
    self["name"] = filename
class MP3FileInfo(FileInfo):
  "store ID3v1.0 MP3 tags"
  tagDataMap = {"title"  : ( 3, 33, stripnulls),
         "artist" : ( 33, 63, stripnulls),
         "album"  : ( 63, 93, stripnulls),
         "year"  : ( 93, 97, stripnulls),
         "comment" : ( 97, 126, stripnulls),
         "genre"  : (127, 128, ord)}
  def __parse(self, filename):
    "parse ID3v1.0 tags from MP3 file"
    self.clear()
    try:
      fsock = open(filename, "rb", 0)
      try:
        fsock.seek(-128, 2)
        tagdata = fsock.read(128)
      finally:
        fsock.close()
      if tagdata[:3] == "TAG":
        for tag, (start, end, parseFunc) in self.tagDataMap.items():
          self[tag] = parseFunc(tagdata[start:end])
    except IOError:
      pass
  def __setitem__(self, key, item):
    if key == "name" and item:
      self.__parse(item)
    FileInfo.__setitem__(self, key, item)
def listDirectory(directory, fileExtList):
  "get list of file info objects for files of particular extensions"
  fileList = [os.path.normcase(f)
        for f in os.listdir(directory)]
  fileList = [os.path.join(directory, f)
        for f in fileList
        if os.path.splitext(f)[1] in fileExtList]
  def getFileInfoClass(filename, module=sys.modules[FileInfo.__module__]):
    "get file info class from filename extension"
    subclass = "%sFileInfo" % os.path.splitext(filename)[1].upper()[1:]
    return hasattr(module, subclass) and getattr(module, subclass) or FileInfo
  return [getFileInfoClass(f)(f) for f in fileList]
if __name__ == "__main__":
  for info in listDirectory("/music/_singles/", [".mp3"]):
    print "\n".join(["%s=%s" % (k, v) for k, v in info.items()])
    print

2 使用 from module import 导入模块

我们以前学的导入模块是用下边的语法:

import 模块名

这样在需要使用该模块中的东西时. 要通过 模块名.XXX 的形式. 例如:

>>> import types
>>> types.FunctionType
<type 'function'>
>>> FunctionType

如果不用模块名而直接使用其中的名字则出错. 所以打印:

Traceback (most recent call last):
 File "<interactive input>", line 1, in <module>
NameError: name 'FunctionType' is not defined

现在看看另一种导入模块中名字的语法:

from 模块名 import 名字

或者用

from 模块名 import *

例如:

>>> from types import FunctionType

这样导入的名字就可以不通过模块名而直接使用. 如:

>>> FunctionType
<type 'function'>

3 类的定义

定义类的语法:

class 类名:
    pass

或者

class 类名(基类列表) :
    pass

其中的 pass 是Python的关键字. 表示什么也不做.

类也可以有类文档. 如果有的话. 他应该是类定义中的第一个东西. 如:

class A(B) :
  " this is class A. "

类的构造函数为:

__init__

不过. 准确的说. 这只能算是创建该类对象后. 自动执行的方法. 当执行这个函数时. 对象已初始化了.

例如:

class A(B) :
  "this is class A. "
  def __init__ (self):
    B.__init__(self)

这里为类A 定义了一个构造方法. 并且在其中调用了基类B的构造方法.

要注意的是. 在Python中. 构造派生类时. 并不会"自动"的调用基类的构造方法. 需要的话必须显式写出.

所有的类方法. 第一个参数都是用来接收this指针. 习惯上这个参数的名字是 self.

调用时不要传递这个参数. 它会自动被加上的.

但是在象上边的构造函数中. 调用基类的__init()时. 这个参数必须显式给出.

4 类的实例化

实例化一个类和其它语言相似. 只把它的类名当作一个函数调用就行了. 而没有其它语言的new之类.

类名(参数表)

其中参数表中不必给出__init__的第一个参数self.

例如:

a = A()

我们可以通过类或类的实例查看该类的文档. 这通过它们的__doc__属性. 如:

>>> A.__doc__
'this is class A. '
>>> a.__doc__
'this is class A. '

我们也可以通过类的实例来得到它的类. 这通过它的__class__属性. 如:

>>> a.__class__
<class __main__.A at 0x011394B0>

创建了类的实例后. 我们不用担心回收的问题. 垃圾回收会根据引用计数自动销毁不用的对象.

Python中. 类的数据成员也没有专门的声明语句. 而是在赋值的时候"突然产生"的. 例如:

class A :
  def __init__(self) :
    self.data = []

这时. 就自动让data作为类A的成员了.

之后在类的定义内. 要使用类中的成员变量或成员方法. 都要用 self.名字 来限定.

所以一般要产生数据成员. 在任何方法中对 self.成员名字 赋值即可.

不过. 在__init__方法中对所有数据属性都赋一个初始值. 是一个好习惯.

Python不支持函数重载.

这里再说说代码缩进. 实际上. 如果一个代码块只有一句. 可以直接放在 冒号 后边. 而不需要换行缩进格式.

6 专用类方法

和普通的方法不同. 在类中定义专用方法后. 并不要你显式的调用它们. 而是在某些时候有Python自动调用.

获得和设置数据项.

这需要在类中定义 __getitem__ 和 __setitem__ 方法.

例如:

>>> class A:
... def __init__(self):
...  self.li = range(5)
... def __getitem__(self, i):
...  return self.li[-i]
...
>>> a = A()
>>> print a[1]

这里的 a[1] 就调用了 __getitem__ 方法. 它等于 a.__getitem__(1)

与__getitem__方法类似的有 __setitem__

例如在上边的A类中定义:

def __setitem__(self, key, item):
  self.li[key] = item

然后调用这个方法如下:

a[1] = 0 它等于调用 a.__setitem__(1, 0)

7 高级专用类方法

和 __getitem__ __setitem__ 类似. 还有一些特殊的专用函数. 如下:

def __repr__(self): return repr(self.li)

这个专用方法用来本对象的字符串表示. 调用它是通过内置函数repr(). 如

repr(a)

这个repr()可以作用在任何对象上.

实际上. 在交互窗口中. 只要输入 变量名 回车. 就用repr显示变量的值.

def __cmp__(self, x):
  if isinstance(x, A): return cmp(self.li, x.li)

它用来比较两个实例 self 和 x 是否相等. 调用它时如下:

a = A()
b = A()
a == b

这里比较 a和b是否相等. 和调用 a.cmp(b) 一样

def __len__(self): return len(self.li)

它用来返回对象的长度. 在使用 len(对象) 的时候会调用它.
用它可以指定一个你希望的逻辑长度值.

def __delitem__(self, key): del self.li[key]

在调用 del 对象[key] 时会调用这个函数.

8 类属性

类属性指的是象c++中静态成员一类的东西.

Python中也可以有类属性. 例如:

class A :
  l = [1, 2, 3]

可以通过类来引用(修改). 或者通过实例来引用(修改). 如:

A.l

a.__class__.l

9 私有函数

Python中也有"私有"这个概念:

私有函数不可以从它们的模块外边被调用.
私有类方法不能从它们的类外边被调用.
私有属性不能从它们的类外边被访问.

Python中只有私有和公有两种. 没有保护的概念. 而区分公有还是私有是看函数. 类方法. 类属性的名字.

私有的东西的名字以 __ 开始. (但前边说的专用方法(如__getitem__)不是私有的).

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
python有证书的加密解密实现方法
Nov 19 Python
Windows下安装Scrapy
Oct 17 Python
一百行python代码将图片转成字符画
Feb 19 Python
使用Python制作表情包实现换脸功能
Jul 19 Python
Python MySQL 日期时间格式化作为参数的操作
Mar 02 Python
查看已安装tensorflow版本的方法示例
Apr 19 Python
Jupyter notebook如何实现指定浏览器打开
May 13 Python
python中tab键是什么意思
Jun 18 Python
python 模拟登录B站的示例代码
Dec 15 Python
Django前后端分离csrf token获取方式
Dec 25 Python
python中封包建立过程实例
Feb 18 Python
python中pandas.read_csv()函数的深入讲解
Mar 29 Python
python异常和文件处理机制详解
Jul 19 #Python
python线程、进程和协程详解
Jul 19 #Python
浅谈python字符串方法的简单使用
Jul 18 #Python
python读取oracle函数返回值
Jul 18 #Python
Python读取一个目录下所有目录和文件的方法
Jul 15 #Python
Python在线运行代码助手
Jul 15 #Python
python 实现网上商城,转账,存取款等功能的信用卡系统
Jul 15 #Python
You might like
全国FM电台频率大全 - 9 上海市
2020/03/11 无线电
file_get_contents获取不到网页内容的解决方法
2013/03/07 PHP
php递归方法实现无限分类实例代码
2014/02/28 PHP
ThinkPHP之getField详解
2014/06/20 PHP
PHP多维数组指定多字段排序的示例代码
2018/05/16 PHP
在chrome中window.onload事件的一些问题
2010/03/01 Javascript
Javascript 类、命名空间、代码组织代码
2011/07/31 Javascript
3种js实现string的substring方法
2015/11/09 Javascript
JS实现“隐藏与显示”功能(多种方法)
2016/11/24 Javascript
IE8兼容Jquery.validate.js的问题
2016/12/01 Javascript
从零开始学习Node.js系列教程之SQLite3和MongoDB用法分析
2017/04/13 Javascript
详解使用nvm管理多版本node的方法
2017/08/30 Javascript
在 Node.js 中使用原生 ES 模块方法解析
2017/09/19 Javascript
Vue v2.4中新增的$attrs及$listeners属性使用教程
2018/01/08 Javascript
关于node-bindings无法在Electron中使用的解决办法
2018/12/18 Javascript
jQuery实现合并表格单元格中相同行操作示例
2019/01/28 jQuery
8 个有用的JS技巧(推荐)
2019/07/03 Javascript
对Layer UI 模块化的用法详解
2019/09/26 Javascript
JS回调函数简单易懂的入门实例分析
2019/09/29 Javascript
javascript设计模式 ? 单例模式原理与应用实例分析
2020/04/09 Javascript
ES2020系列之空值合并运算符 '??'
2020/07/22 Javascript
快速解决pandas.read_csv()乱码的问题
2018/06/15 Python
Python 获取中文字拼音首个字母的方法
2018/11/28 Python
python 含子图的gif生成时内存溢出的方法
2019/07/07 Python
Python如何爬取qq音乐歌词到本地
2020/06/01 Python
一款CSS3实现多功能下拉菜单(带分享按)的教程
2014/11/05 HTML / CSS
canvas学习笔记之2d画布基础的实现
2019/02/21 HTML / CSS
迪卡侬荷兰官网:Decathlon荷兰
2017/10/29 全球购物
尤为Wconcept中国官网:韩国设计师品牌服饰
2019/01/10 全球购物
中兴通讯全球官方网站:ZTE
2020/12/26 全球购物
static函数与普通函数有什么区别
2015/12/25 面试题
2015年出纳个人工作总结
2015/04/02 职场文书
高三毕业感言
2015/07/30 职场文书
新党员入党决心书
2015/09/22 职场文书
导游词之晋城蟒河
2019/12/12 职场文书
Python还能这么玩之只用30行代码从excel提取个人值班表
2021/06/05 Python