Python 魔法方法、属性和迭代器(9) 持续更新

__metaclass__ = type

新类和旧类的区别

class NewStyle(object):
    pass

class OldStyle():
    pass

在类的作用域中 对 __metaclass__ 变量赋值,只会为这个类设定元类。关于元类可以搜索 python metaclasses

魔法方法之构造函数

class Class():
    def __init__(self):
        print 'Init Class'
    
_class = Class()

__del__ 是析构函数,垃圾回收钱调用的函数。

调用父类的构造方法

class Class1():
    def __init__(self):
        print 'Init Class1'

class Class2(Class1):
    def __init__(self):
        Class1.__init__(self)
        print 'Init Class2'

_class = Class2()

新式类 Super 调用方法

class Class1():
    def __init__(self):
        print 'Init Class1'

class Class2(Class1):
    def __init__(self):
        super(Class2, self).__init__()
        print 'Init Class2'

_class = Class2()

魔法方法之成员访问

序列的4个方法

__len__(self) 返回集合中所含项目的数量
__getitem__(self, item) 返回与所键对应的值
__setitem__(self, key, value) 存储键值
__delitem__(self, key) 删除键值

这些方法有以下几个要求

  1. 序列,如果键是负整数,要从末尾开始计数。 x[-n] 等价于 x[len(x) - n]
  2. 如果键是不适合的类型,引发TypeError异常
  3. 序列的索引是正取的类型,但超出范围,引发IndexError异常

示例

# coding=utf-8

# 确定使用新式类
__metaclass__ = type


def checkIndex(key):
    if not isinstance(key, (int, long)):raise TypeError

class ArithmeticSequence:
    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)
print s[4]
s[4] = 2
print s[4]
print s[5]

分片操作也可以的

http://stackoverflow.com/questions/27850161/what-should-i-use-instead-of-getslice

继承列表、字典和字符串

Python标准库有三个标准序列和映射规则 UserList、UserString 和 UserDict。

如果实现一个内建列表相似的序列,可以继承List实现。

当继承内建类型时,实际上间接继承了object。因此自动成为新式类,因此意味着可以直接使用像super函数的特性了。

# 带访问计数的列表

class CounterList(list):
    def __init__(self,*args):
        super(CounterList,self).__init__(*args)
        self.counter = 0
    def __getitem__(self, item):
        self.counter += 1
        return super(CounterList,self).__getitem__(item)

__list = CounterList(range(10))
print __list
__list.reverse()
del __list[3:6]
print __list
print __list[0]
print __list[1]
print __list.counter

当然这里counter不是完美的,比如访问列表元素还可以通过 pop 函数。

更多的魔法函数

http://pycoders-weekly-chinese.readthedocs.io/en/latest/issue6/a-guide-to-pythons-magic-methods.html

属性

class Rectangle:
    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
print r.getSize()
r.setSize((100, 200))
print r.getSize()
print r.width
print r.height

property函数

此函数须在新式类执行,否则会出现困惑的问题

__metaclass__ = type

class Rectangle:
    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
print r.getSize()
r.setSize((100, 200))
print r.getSize()
print r.width
print r.height
print r.size

静态方法(Staticmethod)和类成员方法(Classmethod)

__metaclass__ = type

class Class:

    @staticmethod
    def smeth():
        print 'this is a static method'

    @classmethod
    def cmeth(cls):
        print 'this is a class method',cls

    def cmeth2(self):
        print 'this is a class method2 ',self

# call static method
Class.smeth()

# call class method
___class = Class()
___class.cmeth()
___class.cmeth2()

静态函数和类成员函数区别是,静态函数没有self参数。

@staticmethod 这种语法叫装饰器。

当装饰器定义类成员方法时,cls参数会自动绑定到类。

__getattr__、__setattr__

# 特性name被访问时自动被调用(需在新式类使用)
def __getattribute__(self, item):
# 当特性name被访问且对象没有相应的特性时被自动调用
def __getattr__(self, item):
# 当给特性name赋值时,自动调用    
def __setattr__(self, key, value):
# 删除特性时,调用 
def __delattr__(self, item):
__metaclass__ = type

class Rectangle:
    def __init__(self):
        self.width = 0
        self.height = 0

    def __setattr__(self, key, value):
        if key == 'size':
            self.width,self.height = value
        else:
            self.__dict__[key] = value

    def __getattr__(self, item):
        if item == 'size':
            return self.width, self.height
        else:
            raise AttributeError

_class = Rectangle()
_class.size = 100,200
print _class.size

因为__getattribute__拦截所有特性的访问(在新式类),也拦截对__dict__的访问!访问__getattibute__中与Self相关的特性时,使用超类的 __getarrtibute__方法(使用super函数)是唯一安全的途径。

迭代器

迭代的意思是重复做一些事很多次,就像在循环中做的那样。

任何一个对象只要实现了__iter__方法,就可以进行迭代。__iter__方法返回一个迭代器。所谓迭代器就是具有next方法的对象。调用next方法,迭代器就会返回它下一个值。如果迭代器没有值返回,引发 StopInteration异常。

在Python3.0中,迭代器对象实现__next__方法,而不是next。next(it)等3.0之前it.next()。

迭代器的关键就是,使用时,一个一个返回值的,与列表一次性返回所有值,不一样的。

斐波那契数列

class Fibs():
    def __init__(self):
        self.a = 0
        self.b = 1

    def next(self):
        temp = self.a
        self.a, self.b = self.b, self.a + self.b
        return temp

    def __iter__(self):
        return self

fibs = Fibs()
for f in fibs:
    if f < 2000:
        print f
    else:
        break

iter函数 直接直接从可迭代的对象中获得迭代器

it = iter([1,2,3])
print it.next()
print it.next()

迭代器得到序列

class Fibs():
    def __init__(self):
        self.a = 0
        self.b = 1
        self.max_value = 2000

    def next(self):
        temp = self.a
        self.a, self.b = self.b, self.a + self.b
        if self.a > self.max_value:
            raise StopIteration
        return temp

    def __iter__(self):
        return self

fibs = Fibs()
print list(fibs)

生成器

def flatten(nested):
    for sublist in nested:
        for element in sublist:
            yield element

nested = [[1,2],[1,2],[1,2]]
for num in flatten(nested):
    print num

print list(flatten(nested))

输出

1
2
1
2
1
2
[1, 2, 1, 2, 1, 2]

生成器推导式

print ( (i+2)**2 for i in range(2,10) )
print [ (i+2)**2 for i in range(2,10) ]

输出

<generator object <genexpr> at 0x0000000002E6ACF0>
[16, 25, 36, 49, 64, 81, 100, 121]

生成器推导式可以在当前的圆括号内直接使用,如函数调用

print sum( i for i in range(1,101))

递归生成器

处理任意层的嵌套

def flatten(nested):
    try:
        for sublist in nested:
            for element in flatten(sublist):
                yield element
    except TypeError:
        yield nested

nested = [[1,2],12,2,2,2,2,[1,[33,44,[99,88]],2],[1,2]]
print list(flatten(nested))

输出

[1, 2, 12, 2, 2, 2, 2, 1, 33, 44, 99, 88, 2, 1, 2]

这里还有一个缺陷就是,字符串会进行迭代,解决如下

def flatten(nested):
    try:
        try:
            nested+''
        except Exception:
            pass
        else:
            raise TypeError

        for sublist in nested:
            for element in flatten(sublist):
                yield element
    except TypeError:
        yield nested

nested = [['AAAABBB',1,2],12,2,2,2,2,[1,[33,44,[99,88]],2],[1,2]]
print list(flatten(nested))

上述代码是通过字符串拼接来检查的,也可以用isinstance函数完成检查是不是字符串。

通用生成器

生成器函数时用def语句定义的,包含yield的部分,生成器的迭代器是函数返回的部分。合起来叫生成器。

生成器方法

http://wiki.jikexueyuan.com/project/start-learning-python/215.html

http://www.cnblogs.com/huxi/archive/2011/07/14/2106863.html

回溯策略-----八皇后经典算法

 

 

 

 

 

 

 

 



posted @ 2016-07-25 17:35  笨重的石头  阅读(252)  评论(0)    收藏  举报