15. Python脚本学习笔记十五特殊方法、属性和迭代器
2017-11-10 22:12
871 查看
15. Python脚本学习笔记十五特殊方法、属性和迭代器
本篇名言:“得糊涂是一种境界,心平如境是一种修养,顺其自然是一种超脱,威武不屈是一种品格,富贵不淫是一种情操,常笑就是健康,快乐成就人生。愿你我共勉!”
在Python中,有些名称会在前后加上两个下划线,这种拼写表示名字有特殊含义。所以绝不要在自己的程序中使用这种名字。
classFooBar:
def
__init__(self):
self.somevar=42
f=FooBar()
printf.somevar
我们修改一下如下:
classFooBar:
def
__init__(self,value=42):
self.somevar=value
f=FooBar("what's this?")
print f.somevar
输出如下:
what'sthis?
如下所示:
classA:
def
hello(self):
print"hello ,I.m A"
classB(A):
pass
a=A()
b=B()
a.hello()
b.hello()
输出如下:
hello,I.m A
hello,I.m A
B类没有定义自己的方法hello调用的是父类的hello方法。
如果进行重写这个方法,如下:
classA:
def
hello(self):
print"hello ,I.m A"
classB(A):
pass
def
hello(self):
print"Hello,I'm B"
a=A()
b=B()
a.hello()
b.hello()
输出如下:
hello,I.m A
Hello,I'm B
classBird:
def
__init__(self):
self.hungry=True
def
eat(self):
if
self.hungry:
print'Aaah...'
self.hungry=False
else:
print"No,thansk"
classSongBird(Bird):
def
__init__(self):
self.sound='Squawk!'
def
sing(self):
print
self.sound
sb=SongBird()
sb.sing()
sb.eat()
运行如下:
Squawk!
Traceback(most recent call last):
AttributeError:SongBird instance has no attribute 'hungry'
没有hungry属性。
没有得到父类的属性,需要用到Super函数,处理后如下:
from_pyio
import__metaclass__
__metaclass__=type
classBird:
def
__init__(self):
self.hungry=True
def
eat(self):
if
self.hungry:
print'Aaah...'
self.hungry=False
else:
print"No,thansk"
classSongBird(Bird):
def
__init__(self):
# Bird.__init__(self)
super(SongBird,self).__init__()
self.sound='Squawk!'
def
sing(self):
print
self.sound
sb=SongBird()
sb.sing()
sb.eat()
运行如下:
Squawk!
Aaah...
序列和映射是对象的集合。为了实现他们基本的规则,对于可变的对象需要如下4个方法:
输入如下代码:
defcheckIndex(key):
ifnotisinstance(key,(int,long)):
raiseTypeError
if key<0:
raise IndexError
classArithmeticSequence:
def
__init__(self,start =0,step=1):
self.start=start
self.step=step
self.changed={}
def
__getitem__(self,key):
checkIndex(key)
try:return
self.changed[key]
except KeyError:
return
self.start+key*self.step
def
__setitem__(self,key,value):
checkIndex(key)
self.changed[key]=value
s=ArithmeticSequence(1,2)
s[4]
prints[4]
s[4]=2
prints[4]
print s[5]
输出如下:
9
2
11
最开始的s[4]=start+key*step =1+4*2=9
修改后就直接返回修改后的值。
s[5]=start+key*step=1+5*2=11
当操作del s[4],时候都会报错
AttributeError:ArithmeticSequence instance has no attribute '__delitem__'
应为没有实现__del__方法。
当执行s[“four”],
if not isinstance(key,(int,long)): raiseTypeError
TypeError
s[-42]
if key<0: raise IndexError
IndexError
标准库有3个关于序列和映射规则(UserList,UserString和UserDict),可以子类化内建类型。
看如下示例,CounterList 类严重依赖于它的子类化超类(list)的行为。没有重写任何的方法。在__init__中添加了所需的初始化counter特性的行为,并在__getitem__中更新了counter特性。
classCounterList(list):
def
__init__(self,*args):
super(CounterList,self).__init__(*args)
self.counter=0
def
__getitem__(self, index):
self.counter+=1
return super(CounterList,self).__getitem__(index)
c1=CounterList(range(10))
printc1
c1.reverse()
printc1
delc1[3:6]
printc1
printc1.counter
printc1[4]+c1[2]
c1.counter
执行如下:
[0, 1,2, 3, 4, 5, 6, 7, 8, 9]
[9, 8,7, 6, 5, 4, 3, 2, 1, 0]
[9, 8,7, 3, 2, 1, 0]
0
9
2
包含一个counter特性,每次列表元素被访问时,都会自增,在执行c1[4]+c1[2]后,自增两次,变为2.
classRectangle:
def
__init__(self):
self.width=0
self.height=0
def
setSize(self,size):
self.width,self.height=size
def
getSize(self):
return
self.width,self.height
r=Rectangle()
r.width=10
r.height=5
printr.getSize()
r.setSize((150,100))
print r.width
输出如下:
(10,5)
150
通过访问器定义的特性被称为属性。
在Pyhton中有两种创建属性的机制。当前常用的是property函数。
修改成如下:
from_pyio
import__metaclass__
__metaclass__=type
classRectangle:
def
__init__(self):
self.width=0
self.height=0
def
setSize(self,size):
self.width,self.height=size
def
getSize(self):
return
self.width,self.height
size=property(getSize,setSize)
r=Rectangle()
r.width=10
r.height=5
printr.size
r.size = 150,
100
print r.width
输出如下:
(10,5)
150
理论上应该使用property函数而不是访问器方法。
静态方法和类成员方法分别在创建的时装入Staticmethod类型和Classmethod。类型的对象中。静态方法的定义没有self参数,且能够被类本身直接调用。
如下示例:
classMyClass:
@staticmethod
def
smeth():
print'This is a static method'
@classmethod
def
cmeth(cls):
print'This is a class method of', cls
MyClass.smeth()
MyClass.cmeth()
输出如下:
Thisis a static method
Thisis a class method of __main__.MyClass
不过静态方法和类方法在Python中并不是很重要,因为大部分情况下可以使用函数或者绑定方法替换。
classRectangle:
def
__init__(self):
self.width=0
self.height=0
def
__setattr__(self,name,value):
if name=='size':
self.width,self.height= value
print'setattr'
else:
self.__dict__[name] = value
def
__getattr__(self,name):
if name=='size':
print'getattr'
return
self.width,self.height
else:
raise AttributeError
def
setSize(self,size):
self.width,self.height=size
def
getSize(self):
return
self.width,self.height
size=property(getSize,setSize)
r=Rectangle()
r.width=10
r.height=5
printr.size
r.size = 150,
100
print r.width
输出如下:
(10,5)
setattr
150
一个实现了__iter__方法的对象时可迭代的,一个实现了next方法的对象则是迭代器。
我们来实现一个迭代器:
classFibs:
def
__init__(self):
self.a=0
self.b=1
def
next(self):
self.a,self.b =
self.b,self.a+self.b
return
self.a
def
__iter__(self):
return
self
fibs=Fibs()
forf
in fibs:
if f>1000:
print f
break
输出如下:
1597
此外内建函数iter可以从可迭代的对象中获得迭代器,如下:
>>> it=iter([1,2,3])
>>> it.next()
1
>>> it.next()
2
除了在迭代器和可迭代对象上进行迭代外,还能把他们转换为序列。
使用迭代器获得序列,如下代码:
classTestIterator:
value=0
def
next(self):
self.value+=1
if
self.value>10:raiseStopIteration
return
self.value
def
__iter__(self):
return
self
ti=TestIterator()
print list(ti)
输出如下:
[1, 2,3, 4, 5, 6, 7, 8, 9, 10]
本篇名言:“得糊涂是一种境界,心平如境是一种修养,顺其自然是一种超脱,威武不屈是一种品格,富贵不淫是一种情操,常笑就是健康,快乐成就人生。愿你我共勉!”
在Python中,有些名称会在前后加上两个下划线,这种拼写表示名字有特殊含义。所以绝不要在自己的程序中使用这种名字。
1. __init__方法
Python 类中有默认的构造函数__init__我们可以覆盖它来试试。如下:classFooBar:
def
__init__(self):
self.somevar=42
f=FooBar()
printf.somevar
我们修改一下如下:
classFooBar:
def
__init__(self,value=42):
self.somevar=value
f=FooBar("what's this?")
print f.somevar
输出如下:
what'sthis?
2. 重写方法
如果一个方法在B类的一个实例中被调用,但在B类中没有找到方法,那么就会在超类A里面找。如下所示:
classA:
def
hello(self):
print"hello ,I.m A"
classB(A):
pass
a=A()
b=B()
a.hello()
b.hello()
输出如下:
hello,I.m A
hello,I.m A
B类没有定义自己的方法hello调用的是父类的hello方法。
如果进行重写这个方法,如下:
classA:
def
hello(self):
print"hello ,I.m A"
classB(A):
pass
def
hello(self):
print"Hello,I'm B"
a=A()
b=B()
a.hello()
b.hello()
输出如下:
hello,I.m A
Hello,I'm B
3. 使用Super函数
我看来看下个例子如下:classBird:
def
__init__(self):
self.hungry=True
def
eat(self):
if
self.hungry:
print'Aaah...'
self.hungry=False
else:
print"No,thansk"
classSongBird(Bird):
def
__init__(self):
self.sound='Squawk!'
def
sing(self):
self.sound
sb=SongBird()
sb.sing()
sb.eat()
运行如下:
Squawk!
Traceback(most recent call last):
AttributeError:SongBird instance has no attribute 'hungry'
没有hungry属性。
没有得到父类的属性,需要用到Super函数,处理后如下:
from_pyio
import__metaclass__
__metaclass__=type
classBird:
def
__init__(self):
self.hungry=True
def
eat(self):
if
self.hungry:
print'Aaah...'
self.hungry=False
else:
print"No,thansk"
classSongBird(Bird):
def
__init__(self):
# Bird.__init__(self)
super(SongBird,self).__init__()
self.sound='Squawk!'
def
sing(self):
self.sound
sb=SongBird()
sb.sing()
sb.eat()
运行如下:
Squawk!
Aaah...
4. 成员访问
在其他语言中对象可能被要求属于某一个类,或者被要求实现某个接口,但是Python中只是简单地要求它遵循几个给定的规则。序列和映射是对象的集合。为了实现他们基本的规则,对于可变的对象需要如下4个方法:
输入如下代码:
defcheckIndex(key):
ifnotisinstance(key,(int,long)):
raiseTypeError
if key<0:
raise IndexError
classArithmeticSequence:
def
__init__(self,start =0,step=1):
self.start=start
self.step=step
self.changed={}
def
__getitem__(self,key):
checkIndex(key)
try:return
self.changed[key]
except KeyError:
return
self.start+key*self.step
def
__setitem__(self,key,value):
checkIndex(key)
self.changed[key]=value
s=ArithmeticSequence(1,2)
s[4]
prints[4]
s[4]=2
prints[4]
print s[5]
输出如下:
9
2
11
最开始的s[4]=start+key*step =1+4*2=9
修改后就直接返回修改后的值。
s[5]=start+key*step=1+5*2=11
当操作del s[4],时候都会报错
AttributeError:ArithmeticSequence instance has no attribute '__delitem__'
应为没有实现__del__方法。
当执行s[“four”],
if not isinstance(key,(int,long)): raiseTypeError
TypeError
s[-42]
if key<0: raise IndexError
IndexError
标准库有3个关于序列和映射规则(UserList,UserString和UserDict),可以子类化内建类型。
看如下示例,CounterList 类严重依赖于它的子类化超类(list)的行为。没有重写任何的方法。在__init__中添加了所需的初始化counter特性的行为,并在__getitem__中更新了counter特性。
classCounterList(list):
def
__init__(self,*args):
super(CounterList,self).__init__(*args)
self.counter=0
def
__getitem__(self, index):
self.counter+=1
return super(CounterList,self).__getitem__(index)
c1=CounterList(range(10))
printc1
c1.reverse()
printc1
delc1[3:6]
printc1
printc1.counter
printc1[4]+c1[2]
c1.counter
执行如下:
[0, 1,2, 3, 4, 5, 6, 7, 8, 9]
[9, 8,7, 6, 5, 4, 3, 2, 1, 0]
[9, 8,7, 3, 2, 1, 0]
0
9
2
包含一个counter特性,每次列表元素被访问时,都会自增,在执行c1[4]+c1[2]后,自增两次,变为2.
5. 属性
来看个示例:classRectangle:
def
__init__(self):
self.width=0
self.height=0
def
setSize(self,size):
self.width,self.height=size
def
getSize(self):
return
self.width,self.height
r=Rectangle()
r.width=10
r.height=5
printr.getSize()
r.setSize((150,100))
print r.width
输出如下:
(10,5)
150
通过访问器定义的特性被称为属性。
在Pyhton中有两种创建属性的机制。当前常用的是property函数。
修改成如下:
from_pyio
import__metaclass__
__metaclass__=type
classRectangle:
def
__init__(self):
self.width=0
self.height=0
def
setSize(self,size):
self.width,self.height=size
def
getSize(self):
return
self.width,self.height
size=property(getSize,setSize)
r=Rectangle()
r.width=10
r.height=5
printr.size
r.size = 150,
100
print r.width
输出如下:
(10,5)
150
理论上应该使用property函数而不是访问器方法。
静态方法和类成员方法分别在创建的时装入Staticmethod类型和Classmethod。类型的对象中。静态方法的定义没有self参数,且能够被类本身直接调用。
如下示例:
classMyClass:
@staticmethod
def
smeth():
print'This is a static method'
@classmethod
def
cmeth(cls):
print'This is a class method of', cls
MyClass.smeth()
MyClass.cmeth()
输出如下:
Thisis a static method
Thisis a class method of __main__.MyClass
不过静态方法和类方法在Python中并不是很重要,因为大部分情况下可以使用函数或者绑定方法替换。
6. 拦截对象的特性访问
为了在访问特性的时候可以执行代码,需要使用如下4种方法。classRectangle:
def
__init__(self):
self.width=0
self.height=0
def
__setattr__(self,name,value):
if name=='size':
self.width,self.height= value
print'setattr'
else:
self.__dict__[name] = value
def
__getattr__(self,name):
if name=='size':
print'getattr'
return
self.width,self.height
else:
raise AttributeError
def
setSize(self,size):
self.width,self.height=size
def
getSize(self):
return
self.width,self.height
size=property(getSize,setSize)
r=Rectangle()
r.width=10
r.height=5
printr.size
r.size = 150,
100
print r.width
输出如下:
(10,5)
setattr
150
7. 迭代器
方法__iter__ 是迭代器规则的基础。__iter__方法返回一个迭代器,所谓迭代器就是具有next方法的对象,这个方法在调用时不需要任何参数。一个实现了__iter__方法的对象时可迭代的,一个实现了next方法的对象则是迭代器。
我们来实现一个迭代器:
classFibs:
def
__init__(self):
self.a=0
self.b=1
def
next(self):
self.a,self.b =
self.b,self.a+self.b
return
self.a
def
__iter__(self):
return
self
fibs=Fibs()
forf
in fibs:
if f>1000:
print f
break
输出如下:
1597
此外内建函数iter可以从可迭代的对象中获得迭代器,如下:
>>> it=iter([1,2,3])
>>> it.next()
1
>>> it.next()
2
除了在迭代器和可迭代对象上进行迭代外,还能把他们转换为序列。
使用迭代器获得序列,如下代码:
classTestIterator:
value=0
def
next(self):
self.value+=1
if
self.value>10:raiseStopIteration
return
self.value
def
__iter__(self):
return
self
ti=TestIterator()
print list(ti)
输出如下:
[1, 2,3, 4, 5, 6, 7, 8, 9, 10]
相关文章推荐
- Python基础教程 第9章: 魔法方法、属性和迭代器 学习笔记
- python基础教程_学习笔记11:魔法方法、属性和迭代器
- python基础教程_学习笔记11:魔法方法、属性和迭代器
- <<Python基础教程>>学习笔记 | 第09章 | 魔法方法、属性和迭代器
- Python学习笔记——动态添加属性与方法
- Python学习笔记——特殊方法
- Python深入学习笔记1-特殊方法与多范式
- python学习笔记(属性和方法)
- python基础教程总结8——特殊方法,属性,迭代器,生成器,八皇后问题
- Python学习笔记1:数据模型和特殊方法(魔术方法)
- python学习笔记之七:魔法方法,属性
- 我的Python学习笔记(四):动态添加属性和方法
- python学习笔记-实例方法、类方法、静态方法、属性方法
- python进阶学习笔记(四)——python中访问限制、创建类属性、定义实例方法、定义类方法、类的继承
- Python学习笔记(九)——Python _init_特殊方法和模块
- 第9章 Python笔记 魔法方法、属性和迭代器
- Python学习笔记(二)——特殊方法(续)
- python学习笔记13-python面向对象,属性,方法
- Python学习笔记1:数据模型和特殊方法(魔术方法)