核心編程
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/講的很通熟易懂,後續再看