《Beginning Python From Novice to Professional》学习笔记十二:__Magic__

来源:互联网 发布:vs2010下qt界面编程 编辑:程序博客网 时间:2024/04/26 01:01
1.属性访问

这种技术语法上不错,但它将程序与一种accessor紧耦合了。
函数property能够解决这个问题:

原理:其实property是个满足descriptor协议的类(这样的类实现了__get__, __set__和__delete__方法)
下面测试accessor:
r = Rectangle()
r.width = 10
r.height = 5
r.size   ---> (10, 5)
r.size = 150, 100
r.width   ---> 150

实际上property函数也可以使用0个、1个、3个、4个参数。
0个 —— resulting property 既不可读也不可写
1个 —— resulting property 仅仅可读
3个 —— 第3个参数是用来删除某个属性的方法(此方法无参数)
4个 —— 第4个参数是documentation string
以上4个参数的名称为 fget, fset, fdel以及doc。
property(fget, fset, fdel, doc)

作者最后说,The moral is this: With new-style classes, you should use property rather than accessors.

2. 静态方法和类方法
静态方法是没有self参数的方法,而且可以由类直接调用。
类方法是使用了一个类似于self的参数cls。

以下是一个小例子:

在Python 2.4中, 引入了一个新的语法:decorators
   
以下为调用:
MyClass.smeth()
---> This is a static method
MyClass.cmeth()
---> This is a class method of <class '__main__.MyClass'>
静态方法和类方法之所以在Python中不太重要,是因为它未能在早期版本中实现。但在像factory函数中,它还是非常有用的。

3.__getattr__, __setattr__, and Friends
__getattribute__(self, name): 当属性name被访问时,被自动调用(Works correctly on new-style classes only.)   #Note:TODO
__getattr__(self, name):当属性name被访问时,被自动调用
__setattr__(self, name, value):当属性name要被赋值value时,被自动调用
__delattr__(self, name): 当属性name要被删除时,被自动调用
这些magic方法在处理多个属性的时候是很有用的,但是If you have a choice, though, stick with property.
一个使用例子:
   
4.迭代器Iterators
实现了__iter__方法的对象就可以和Sequences和Dictionaries一样在for循环中迭代。
__iter__方法返回一个迭代器,这是一个拥有next方法的任意对象,可调用但无参数。如果调用迭代器时已经没有了返回值,但会引发一个StopIteration异常。

!下面是一个可迭代的类示例:

下面在for循环中使用这个迭代:
#内置函数iter可以从一个可迭代对象中获得迭代器iter(obj)            Extracts an iterator from an iterable object.

除了使用迭代器遍历对象,还可以将其转换成Sequence:
...
ti = TestIterator()
list(ti)   ---> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

5.Generators(本质也是一种迭代)
#书中后面给出了定义:A generator is a function that contains the keyword yield. When called, the generator function returns a generator, which is a special type of iterator.

Making a Generator:

或者
list(flatten(nested))
---> [1, 2, 3, 4, 5]

递归Generator:(可以用来表示某种树结构)
   
更简洁的调用方式:
list(flatten([[[1],2],3,4,[5,[6,7]],8]))
---> [1, 2, 3, 4, 5, 6, 7, 8]

以上递归方式有一个隐患,当迭代string-like对象时,因为它是一个sequence,所以不会引起TypeError异常。(不过不应该迭代String-like对象),下面是一种更为安全的定义方式:
   
使用示例:
list(flatten(['foo', ['bar', ['baz']]]))
---> ['foo', 'bar', 'baz']
generators包含两总分:generator函数和generator迭代器。generator函数是包含yield的函数; generator迭代器是generator函数的返回值,和其它迭代器一样使用。

def simple_generator():
        yield 1
...
simple_generator
---> <function simple_generator at 153b44>   #这里被看成一个函数
simple_generator()
---> <generator object at 1510b0>   #加括号则看成一个generator
原创粉丝点击