chapter 13面向對象-再次閱讀

核心編程

1.複習一下dir()和__dict__.
python

>>> class C(object):編程

pass安全


>>> c=C()app

>>> dir(C)dom

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


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

>>> dir(c)ui

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


'__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/講的很通熟易懂,後續再看

相關文章
相關標籤/搜索