阿齐兹的Python学习笔记——定制数据对象
2018-02-06 22:03
489 查看
定制数据对象
选择的数据结构要与数据匹配,Python中提供了列表、集合、字典和class语句字典可以将数据与名关联而不是与数字关联,从而实现快速查找
class语句允许你定义自己的数据结构
使用字典关联数据
字典:这是一个内置的数据结构(内置于Python中),允许将数据与键而不是数字关联。这样可以使内存中的数据与实际数据的结构保持一致使用一个Python字典,将数据值与键关联:
Name —— “Sarah Sweeney”
DOB —— “2002-6-17”
Times —— [‘2:58’, ‘2.58’, ‘2:39’, ‘2-25’, ‘2-55’, ‘2:54’, ‘2.18’, ‘2:55’, ‘2:55’, ‘2:22’, ‘2-21’, ‘2.22’]
Python字典在其他编程语言中还有不同的名字,例如“映射”、“散列”和“关联数组”,实际上指的就是字典
可以使用一个大括号创建字典,也可以使用一个工厂函数
dict()创建:
>>> cleese = {} >>> palin = dict() >>> type(cleese) <class 'dict'> >>> type(palin) <class 'dict'>
每个字典都有一个Name和Occupations列表。通过将键与值关联,可以向字典分别增加一些数据,也可以一次性创建
>>> cleese['Name'] = 'John Cleese' >>> cleese['Occupations'] = ['actor', 'comedian', 'writer', 'film producer'] >>> palin = {'Name': 'Michael Palin', 'Occupations': ['comedian', 'actor', 'write', 'tv']}
可以以键为索引访问指定字典中的数据项
使用数字来访问存储在一个特定字典键位置上的列表项,可以把它看作“索引串链”
>>> palin['Name'] 'Michael Palin' >>> cleese['Occupations'][-1] 'film producer'
Python字典可以动态扩展来存储额外的键/值对
与列表不同,Python不会维持插入的顺序,因为重点是关联关系
>>> palin['Birthplace'] = "Broomhill, Sheffield, England" >>> cleese['Birthplace'] = "Weston-super-Mare, North Somerset, England" >>> palin {'Name': 'Michael Palin', 'Occupations': ['comedian', 'actor', 'write', 'tv'], 'Birthplace': 'Broomhill, Sheffield, England'} >>> cleese {'Name': 'John Cleese', 'Occupations': ['actor', 'comedian', 'writer', 'film producer'], 'Birthplace': 'Weston-super-Mare, North Somerset, England'}
使用字典改进有关训练数据的程序:
import os os.chdir('C:/Users/0AQZ0/Documents/exercisecode/Python/HeadFirstPython/chapter6') def sanitize(time_string): """this funciton can formalize your data in the format: mins + '.' +secs""" if '-' in time_string: splitter = '-' elif ':' in time_string: splitter = ':' else: return time_string (mins, secs) = time_string.split(splitter) return (mins + '.' +secs) def get_coach_data(filename): try: with open(filename) as f: data = f.readline() return(data.strip().split(',')) except IOError as err: print('File error: ' + str(err)) return(None) sarah = get_coach_data('sarah2.txt') sarah_data = {} sarah_data['Name'] = sarah.pop(0) sarah_data['DOB'] = sarah.pop(0) sarah_data['Times'] = sarah print(sarah_data['Name'] + "'s fastest times are: " + str(sorted(set([sanitize(t) for t in sarah_data['Times']]))[0:3]))
改进
get_coach_data()函数一次性完成字典的创建:
import os os.chdir('C:/Users/0AQZ0/Documents/exercisecode/Python/HeadFirstPython/chapter6') def sanitize(time_string): """this funciton can formalize your data in the format: mins + '.' +secs""" if '-' in time_string: splitter = '-' elif ':' in time_string: splitter = ':' else: return time_string (mins, secs) = time_string.split(splitter) return (mins + '.' +secs) def get_coach_data(filename): try: with open(filename) as f: data = f.readline() templ = data.strip().split(',') return({'Name': templ.pop(0), 'DOB': templ.pop(0), 'Times': str(sorted(set([sanitize(t) for t in templ]))[0:3])}) except IOError as err: print('File error: ' + str(err)) return(None) sarah = get_coach_data('sarah2.txt') print(sarah['Name'] + "'s fastest times are: " + sarah['Times'])
将代码及其数据打包在类中
把代码和数据放在一起是对的函数只有在与数据关联时才有意义,函数通常特定于某些数据,而不是一般的通用函数
Python允许创建并定义面向对象的类,类可以用来将代码与代码处理的数据相关联
使用类的好处:
1. 使用类有助于降低复杂性
2. 降低复杂性意味着bug更少
3. bug更少意味着代码更可维护
定义一个类
Python提供了一种方法允许将代码及其处理的数据定义为一个类,一旦有了类定义,就可以用它来创建(实例化)数据对象,它会继承类的特性一些基本概念:
类的方法(method):你的代码
类的属性(attribute):数据
实例(instance):实例化的数据对象
每个对象都由类创建,并共享一组类似的特性。各个实例中的方法(代码)都相同,但是各个对象的属性(数据)不同,因为属性由原始数据创建
使用class定义类
Python使用class创建对象。每个定义的类都有一个特殊的方法,名为__init__(),可以通过这个方法控制如何初始化对象
class Athlete: def __init__(self): #The code to initialize a "Athlete" object. ......
“init”前面和后面分别有两个下划线
创建对象实例
创建对象实例,只需将对类名的调用赋至各个变量。通过这种方式,类(以及
__init__()方法)提供了一种机制,允许你创建一个定制的工厂函数,用来跟据需要创建多个对象实例
a = Athlete() b = Athlete() c = Athlete() d = Athlete()
小括号告诉Python要创建一个新的“Athlete”对象,并赋给一个变量
__init__()方法可以定制对象的初始状态
self的重要性
定义一个类时,实际上是在定义一个定制工厂函数,然后可以使用它来创建实例a = Athlete()
a:目标标识符,包含实例的一个引用
Athlete():调用类的定制工厂函数
Python处理这行代码时,目标标识符会赋至self参数
self是一个非常重要的参数,没有这个赋值,Python解释器无法得出方法调用要应用到哪个对象实例。要注意,类代码设计在所有对象实例间共享:方法是共享的,而属性不共享,self参数可以帮助标识处理哪个对象实例的数据
Athlete().__init__(a)
每个方法的第一个参数都是self
不仅__init__()方法需要self作为它的第一个参数,类中定义的所有其他方法都是如此
Python要求每个方法的第一个参数为调用对象实例
class Athlete: def __init__(self, value=0): self.thing = value def how_big(self): return(len(self.thing))
每个方法都使用self标识调用对象实例
初始化代码将所提供的一个值赋至一个名为self.thing的类属性
d = Athlete('Holy Grail') d.how_big()
等效于
Athlete.__init__(d, 'Holy Grail') Athlete.how_big(d)
其中Athlete是类,
__init__()、
how_big()是方法
示例:
定义一个类
>>> class Athlete: def __init__(self, a_name, a_dob=None, a_times=[]): self.name = a_name self.dob = a_dob self.times = a_times >>> sarah =Athlete('Sarah Sweeney', '2002-6-17', ['2:58', '2.58', '1.56']) >>> james = Athlete('James Jones') #james使用缺省值 >>> type(sarah) <class '__main__.Athlete'> >>> type(james) <class '__main__.Athlete'>
sarah和james的内存地址不同
>>> serah <__main__.Athlete object at 0x0000011C6A31A828> >>> james <__main__.Athlete object at 0x0000011C6A3ADE80>
可以使用点记法来访问各个与对象实例关联的属性
>>> serah.name 'Sarah Sweeney' >>> james.name 'James Jones' >>> serah.dob '2002-6-17' >>> james.dob #james对象实例没有dob值,所以屏幕上不显示任何内容 >>> serah.times ['2:58', '2.58', '1.56'] >>> james.times []
使用类定义改进有关训练数据的程序
import os os.chdir('C:/Users/0AQZ0/Documents/exercisecode/Python/HeadFirstPython/chapter6') def sanitize(time_string): """this funciton can formalize your data in the format: mins + '.' +secs""" if '-' in time_string: splitter = '-' elif ':' in time_string: splitter = ':' else: return time_string (mins, secs) = time_string.split(splitter) return (mins + '.' +secs) class Athlete: def __init__(self, a_name, a_dob=None, a_times=[]): self.name = a_name self.dob = a_dob self.times = a_times def top3(self): return(sorted(set([sanitize(t) for t in self.times]))[0:3]) def get_coach_data(filename): try: with open(filename) as f: data = f.readline() templ = data.strip().split(',') return(Athlete(templ.pop(0), templ.pop(0), templ)) except IOError as err: print('File error: ' + str(err)) return(None) sarah = get_coach_data('sarah2.txt') print(sarah.name + "'s fastest times are: " + str(sarah.top3()))
更多功能==更多方法
只需增加方法将你需要的新功能封装在类中,一个类可以有多少个方法根本没有限制
值得注意的问题
top3()方法返回一个列表,而不是一个字符串,这么做可以更加灵活,因为不是所以程序都希望处理字符串
不直接把最快的3个时间作为一个属性存储在类中,也是为了灵活性,因为假如增加更多的数据,top3()方法可以动态地计算最快的3个时间
在各个对象的属性中保留原始数据,可以支持类的扩展来满足将来的其他需求
为了向现有对象中增加更多的数据,可以定义一个方法来增加一个数据或者一个列表
如果改变类的实现,或者利用类实现的内部细节,将会破坏原先使用这个类的所有代码
使用面向对象的原因之一就是要对类的用户隐藏类实现的细节,定义你的API正是充分支持了这个设计理念。倘若暴露类实现的内部细节,或者希望程序员利用类的实现细节,会很大程度上破坏面向对象的基本理念
定义新的方法来向现有对象中增加更多的数据
class Athlete: def __init__(self, a_name, a_dob=None, a_times=[]): self.name = a_name self.dob = a_dob self.times = a_times def top3(self): return(sorted(set([sanitize(t) for t in self.times]))[0:3]) def add_time(self, time_value): self.times.append(time_value) def add_times(self, list_of_times): self.times.extend(list_of_times)
继承Python内置的list
class允许你从零开始创建一个定制类,还允许通过继承现有的其他类来创建一个类,这包括用list、set、dict提供的Python内置数据结构类通过继承创建的这些类称为子类
从一个现有的类(如list)继承时,它会为你提供所有现有的功能
定义一个子类
>>> class NamedList(list): def __init__(self, a_name): list.__init__([]) self.name = a_name
list提供一个类名,新类将派生这个类
__init__()中还要增加初始化所派生的类这一步
创建一个对象实例
>>> johnny = NamedList("John Paul Jones") >>> type(johnny) <class '__main__.NamedList'> >>> dir(johnny) ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__module__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'name', 'pop', 'remove', 'reverse', 'sort']
johnny可以做列表能做的所有事情,还可以在name属性中存储数据
可以对johnny使用list类提供的功能,也可以对johnny做列表处理
>>> johnny.append("Bass Player") >>> johnny.extend(["Composer", "Arranger", "Musician"]) >>> johnny ['Bass Player', 'Composer', 'Arranger', 'Musician'] >>> johnny.name 'John Paul Jones' >>> for attr in johnny: print(johnny.name + " is a " + attr + ".") John Paul Jones is a Bass Player. John Paul Jones is a Composer. John Paul Jones is a Arranger. John Paul Jones is a Musician.
用继承list的子类改进关于训练数据的程序
import os os.chdir('C:/Users/0AQZ0/Documents/exercisecode/Python/HeadFirstPython/chapter6') def sanitize(time_string): """this funciton can formalize your data in the format: mins + '.' +secs""" if '-' in time_string: splitter = '-' elif ':' in time_string: splitter = ':' else: return time_string (mins, secs) = time_string.split(splitter) return (mins + '.' +secs) class AthleteList(list): def __init__(self, a_name, a_dob=None, a_times=[]): list.__init__([]) self.name = a_name self.dob = a_dob self.extend(a_times) def top3(self): return(sorted(set([sanitize(t) for t in self]))[0:3]) def get_coach_data(filename): try: with open(filename) as f: data = f.readline() templ = data.strip().split(',') return(AthleteList(templ.pop(0), templ.pop(0), templ)) except IOError as err: print('File error: ' + str(err)) return(None) sarah = get_coach_data('sarah2.txt') print(sarah.name + "'s fastest times are: " + str(sarah.top3()))
值得注意的问题
可以从任何内置的类型继承Python支持多重继承
可以从自己定制的类继承。你可以创建一个一般化的类,然后派生子类来提高更特定、更有针对性的功能
可以把类放在模块中,在多个程序中共享这个类。如果把AthleteList类保存在athletelist.py中,可以使用
from athletelist import AthleteList这行代码导入这个类
小结
如何创建一个字典:dict()、{}如何访问一个字典:中括号记法
字典的动态扩大:键值对形式的扩大
如何填充一个字典:一个一个/一次性
用class关键字定义一个类,
__init__方法
self参数的作用
如何继承一个内置的类或者定制的类
相关文章推荐
- 【Head First Python-第六章-定制数据对象】学习笔记
- Python学习笔记_Chapter 6定制数据对象
- 阿齐兹的Python学习笔记——处理数据
- 《Head First Python》笔记 第六章 定制数据对象
- Head First Python 学习笔记-Chapter6:自定义数据对象:字典与类
- python系列学习四——定制数据对象
- Python学习笔记 03 Python对象
- Python学习笔记(1)--数据结构
- Python 学习笔记【文件对象】
- [Python学习第一天]内置数据类型介绍,万物皆对象!
- Python3.3 学习笔记3 - 数据类型和运算
- 面向对象的程序设计学习笔记-21-常量数据成员的定义和初始化
- Python学习笔记 03 Python对象
- Python学习笔记一:数据类型转换
- Python学习笔记-Python对象
- Python源码学习笔记(1 基本数据类型)
- python学习笔记(一) 基本数据类型及运算
- python 学习笔记 对象(4)
- Python学习笔记——文件对象和操作(1)
- Python对象学习笔记