1.定制序列(容器)
(1) 如果希望定制的容器不可变,只需要定义魔法方法__len__()和__getitem__()
(2) 如果希望定制的容器可变,需要定义__len__()和__getitem__()和__setitem__()和__delitem__()
魔法方法详解:
http://bbs.fishc.com/forum.php?mod=viewthread&tid=48793&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403
练习:
编写一个不可改变的自定义列表,要求记录列表中每个元素被访问的次数。
class CountList:
def __init__(self, *args): #*args, 参数数量可变
self.values = [x for x in args]
self.count = {}.fromkeys(range(len(self.values)), 0)
def __len__(self):
return len(self.values)
def __getitem__(self, key):
self.count[key] += 1
return self.values[key]
运行:
>>> c1 = CountList(1, 3, 5, 7, 9)
>>> c2 = CountList(2, 4, 6, 7, 10)
>>> c1[1] #c1[1] == 3被访问1次
3
>>> c2[1]
4
>>> c1[1] + c2[1] #c1[1] == 3被访问2次
7
>>> c1.count
{0: 0, 1: 2, 2: 0, 3: 0, 4: 0}
>>> c1[1] #c1[1] == 3被访问3次
3
>>> c1.count
{0: 0, 1: 3, 2: 0, 3: 0, 4: 0}
2.迭代器 iter-next
iter
iter() 内置方法, 功能:返回一个迭代器对象
__iter__() 魔法方法
next
next() 内置方法
__next__() 魔法方法
for循环迭代器:
>>> links = {'百度':'http://www.baidu.com', \
'谷歌':'http://www.google.com', \
'搜狗':'http://www.sougou.com', \
'腾讯':'http://www.qq.com'}
>>> for each in links:
print("%s -> %s" % (each, links[each]))
谷歌 -> http://www.google.com
搜狗 -> http://www.sougou.com
腾讯 -> http://www.qq.com
百度 -> http://www.baidu.com
iter迭代器:
>>> string = 'yuan.jiang'
>>> it = iter(string)
>>> while True:
try:
each = next(it)
except StopIteration:
break;
print(each, end=' ')
运行:
y u a n . j i a n g
斐波那契数列迭代器
>>> class Fibs: #斐波那契数列
def __init__(self, n=10): #加一个参数n控制迭代范围
self.a = 0
self.b = 1
self.n = n
def __iter__(self):
return self #本身就是一个迭代器
def __next__(self):
self.a, self.b = self.b, self.a+self.b
if self.a > self.n:
raise StopIteration
return self.a
>>> fibs = Fibs()
>>> for each in fibs:
print(each, end=' ')
1 1 2 3 5 8
>>> fibs = Fibs(100)
>>> for each in fibs:
print(each, end=' ')
1 1 2 3 5 8 13 21 34 55 89
3. 生成器实际上是一个特殊的迭代器;
生成器 yield
(1) 生成器是一种特殊的迭代器,兼容next()内置方法
(2) 生成器模仿了协同程序
协同程序:可以运行的对立函数调用,函数可以暂停或挂起,并再需要的时候从程序离开的地方继续活着重新开始。
举例:
>>> def MyGen():
print('生成器被执行!')
yield 1
yield 2
>>> myg = MyGen()
>>> next(myg)
生成器被执行!
1
>>> next(myg)
2
>>> next(myg)
StopIteration
>>> for i in MyGen(): #for循环自动检测迭代器的StopIteration异常
print(i)
生成器被执行!
1
2
>>> def fibs():
a = 0
b = 1
while True:
a, b = b, a+b
yield a
>>> for each in fibs():
if each > 100:
break
print(each, end=' ')
1 1 2 3 5 8 13 21 34 55 89
列表推导式
>>> a = [i for i in range(100) if not (i % 2) and (i % 3)] #列表推导式
>>> a
[2, 4, 8, 10, 14, 16, 20, 22, 26, 28, 32, 34, 38, 40, 44, 46, 50, 52, 56, 58, 62, 64, 68, 70, 74, 76, 80, 82, 86, 88, 92, 94, 98]
>>> b = {i:i % 2 == 0 for i in range(10)} #字典推导式(例子:小于10以内的偶数)
>>> b
{0: True, 1: False, 2: True, 3: False, 4: True, 5: False, 6: True, 7: False, 8: True, 9: False}
>>> c = {i for i in [1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 3, 2, 1]} #集合推导式(元素不重复)
>>> c
{1, 2, 3, 4, 5, 6, 7, 8}
#没有字符串推导式,引号内的强制解释为字符串
>>> e = (i for i in range(10)) #没有元组推导式,()小括号生成的是生成器推导式
>>> e
>>> next(e)
0
>>> next(e)
1
>>> for each in e:
print(each, end=' ')
2 3 4 5 6 7 8 9
>>> sum(i for i in range(100) if i % 2)
2500
生成器扩展阅读:
http://bbs.fishc.com/forum.php?mod=viewthread&tid=56023&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403
4. 模块 module
容器 -> 数据的封装
函数 -> 语句的封装
类 -> 方法和属性的封装
模块 -> 程序的封装,其实就是.py的python程序
(1) import导入的.py模块文件必须放在与python.exe同一目录下,即可正确导入。
(2) 导入方法有三种:
① import 模块名
② from 模块名 import 函数名1, 函数名2, ... #不建议这样用,可能会覆盖系统函数
③ import 模块名 as 新名字
举例:
在python下新建test_module文件夹:C:\python\test_module
C:\python\test_module\TempeatureConversion.py
C:\python\test_module\calc.py
#TempeatureConversion.py
def c2f(cel):
fah = cel * 1.8 + 32
return fah
def f2c(fah):
cel = round((fah - 32) / 1.8, 1)
return cel
#calc.py
import TemperatureConversion as tc
print('32摄氏度 = %.1f华氏度' % tc.c2f(32))
print('99华氏度 = %.1f摄氏度' % tc.f2c(99))
运行calc.py:
=================== RESTART: C:\python\test_module\calc.py ===================
32摄氏度 = 89.6华氏度
99华氏度 = 37.2摄氏度