chapter 13面向对象-再次阅读

核心编程

1.复习一下dir()和__dict__.

>>> class C(object):

pass


>>> c=C()

>>> dir(C)

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', 


'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

>>> dir(c)

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', 


'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

>>> c.__dict__

{}

>>> c.bar='rao'

>>> dir(c)

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', 


'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 


'bar']

>>> dir(C)

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', 


'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

>>> c.__dict__

{'bar': 'rao'}


可以看出实例的dir(c)包括类的dir(C)加上实例自己的数据属性。

而实例的__dict__则仅仅是他的数据属性,(实例也没有方法属性)

内建类型中可以用dir(),不可以用__dict__

2.

实例仅有两个特殊属性(见表13.2)。对于任意对象I:

表13.2 特殊实例属性

I.__class__ 实例化I 的类

I.__dict__ I 的属性





从标准类型派生(标准类型分两种:可变类型,不可变类型)

可变类型(list的值改变了但是id没有变化,id(list)一直不变化):list,dict

不可变类型:string,int,tuple


class RoundFloat(float):

def __new__(cls, val):


return float.__new__(cls, round(val, 2))

#return super(RoundFloat,cls).__new__(cls,round(val,2))


tips:所有的__new()__方法都是类方法,我们要显式传入类作为第一个参数(cls),这类似于常见的方法如__init__()中需要的self


类、实例和其他对象的内建函数:

issubclass(sub,sup)

isinstance(obj1,obj2)

hasattr(), getattr(),setattr(), delattr()有两个参数,第一个是正在处理的对象,第二个就是属性名,是属性的字符串名字


对于每个定义的类都有一个名为__mro__的属性,她是一个元组,按照他们被搜索时的顺序,列出了被搜索的类。super()是用来解决多重继承的问


题的,而且只能作用于新式类上。super()用来调用父类非绑定的方法


vars()

vars()内建函数与dir()相似,只是给定的对象参数都必须有一个__dict__属性。vars()返回一

个字典,它包含了对象存储于其__dict__中的属性(键)及值。如果提供的对象没有这样一个属性,

则会引发一个TypeError 异常。如果没有提供对象作为vars()的一个参数,它将显示一个包含本地

名字空间的属性(键)及其值的字典,也就是,locals()。我们来看一下例子,使用类实例调用vars():




用特殊方法定制类:


class Time60(object):

    def __init__(self,hr,min):

        self.hr=hr

        self.min=min


    def __str__(self):

        return '%d:%d'%(self.hr,self.min)


    __repr__=__str__


    def __add__(self,other):

        hour=self.hr+other.hr

        mins=self.min+other.min

        if mins>60:

            return self.__class__(hour+1,mins-60)

        else:

            return self.__class__(hour,mins)


    def __sub__(self,other):

        return self.__class__(abs(self.hr-other.hr),abs(self.min-other.min))


mon=Time60(10,30)

tue=Time60(11,55)

print mon-tue


随机序列迭代器:

要想自定义的类的实例可以迭代必须加载iter方法

    def __iter__(self):

        return self


from random import choice


class RandSeq(object):

    def __init__(self,seq):

        self.data=seq

    def __iter__(self):

        return self


    def next(self):

        return choice(self.data)


    def __str__(self):

        return  str(self.data)


rand=RandSeq([1,2,3,4,5])


for eachItem in rand:

    print eachItem




class AnyIter(object):

    def __init__(self,data,safe=False):

        self.safe=safe

        self.iter=iter(data)


    def __iter__(self):

        return self


    def next(self,howmany):

        retval=[]

        for eachItem in range(howmany):

            try:

                retval.append(self.iter.next())

            except StopIteration:

                if self.safe:

                    break

                else:

                    raise

        return retval

a=AnyIter(range(10))

i=iter(a)

for j in range(1,5):

    print j,':',a.next(j)


question:这个例子中我不明白为什么要设置i=iter(a),然后调用print j,':',i.next(j),我发现直接调用我写的 print j,':',a.next(j)

也是生成同样的结果哎。。。


*多类型定制(NumStr)


class NumStr(object):

    def __init__(self,num=0,str=''):

        self.num=num

        self.str=str

    def __str__(self):

        return "[%d::%r]"%(self.num,self.str)

    __repr__ = __str__


    def __add__(self,other):

        return self.__class__(self.num+other.num,self.str+other.str)

    def __mul__(self,num):

        if isinstance(num,int):

            return self.__class__(self.num*num,self.str*num)

        else:

            raise TypeError,'Illegal argument type for built-in operation'


    def __nonzero__(self):

       return self.num or len(self.str)

    def __norm_cval(self,cmpres):

        return cmp(cmpres,0)

    def __cmp__(self,other):

        return self.__norm_cval(cmp(self.num,other.num))+self.__norm_cval(cmp(self.str,other.str))


a=NumStr(2,'rao')

b=NumStr(3,'yuan')

print a>b



包装的定义:

授权是包装的一个特性,包装一个类型通常是对已经存在的类型的一些定制,实现授权的关键点就是覆盖__getattr__()方法,,在代码中包含一个

对getattr()内建函数的调用。特别地,调用getattr()以得到默认对象属性(数据属性或者方法)并返回它以便访问或调用。特殊方法__getattr__

()的工作方式是,当搜索一个属性时,任何局部对象首先被找到(定制的对象)。如果搜索失败了,则__getattr__()会被调用,然后调用getattr()

得到一个对象的默认行为。

下面是包装类的例子:
包装一般都是针对类型的,如果是自定义的类只需要派生就可以了。

_slots__类属性:
字典位于实例的“心脏”。__dict__属性跟踪所有实例属性。举例来说,你有一个实例inst.它有一个属性foo,那使用inst.foo 来访问它与使用

inst.__dict__['foo']来访问是一致的。
字典暂用内存空间比较大所以可以用_slots__属性来替代__dict__。__slots__是一个类变量,由一序列型对象组成,由所有合法标识构成的实例属

性的集合来表示。它可以是一个列表,元组或可迭代对象。也可以是标识实例能拥有的唯一的属性的简单字符串。任何试图创建一个其名不在

__slots__中的名字的实例属性,这种特性的主要目的是节约内存。其副作用是某种类型的"安全",它能防止用户随心所欲的动态增加实例属性。带

__slots__属性的类定义不会存在__dict__了(除非你在__slots__中增加'__dict__'元素)

特殊方法__getattribute__():
Python 类有一个名为__getattr__()的特殊方法,它仅当属性不能在实例的__dict__或它的类(类的__dict__),或者祖先类(其__dict__)中找到

时,才被调用。我们曾在实现授权中看到过使用__getattr__()。


描述符:
描述符是Python 新式类中的关键点之一
如你的对象有代理,并且这个代理有一个“get”属性(实际写法为__get__),当这个代理被调用时,你就可以访问这个对象了。

__get__(),__set__(),__delete__()特殊方法
class Person(object):

    def addProperty(self, attribute):
        # create local setter and getter with a particular attribute name
        getter = lambda self: self._getProperty(attribute)
        setter = lambda self, value: self._setProperty(attribute, value)

        # construct property attribute and add it to the class
        setattr(self.__class__, attribute, property(fget=getter, \
                                                    fset=setter, \
                                                    doc="Auto-generated method"))

    def _setProperty(self, attribute, value):
        print "Setting: %s = %s" %(attribute, value)
        setattr(self, '_' + attribute, value.title())   

    def _getProperty(self, attribute):
        print "Getting: %s" %attribute
        return getattr(self, '_' + attribute)

关于描述符http://www.ibm.com/developerworks/cn/opensource/os-pythondescriptors/讲的很通熟易懂,后续再看

你可能感兴趣的:(chapter 13面向对象-再次阅读)